Skip to content

Commit 5a3e489

Browse files
fix: correctly handle MDX layouts (#6845)
* fix: correctly handle MDX layouts (#6844) * fix: adjust JSXNode return value (#6844) * refactor(mdx): use jsx instead of internals --------- Co-authored-by: Wout Mertens <[email protected]>
1 parent fa172c5 commit 5a3e489

File tree

4 files changed

+109
-25
lines changed

4 files changed

+109
-25
lines changed

.changeset/lazy-worms-attack.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@builder.io/qwik-city': patch
3+
---
4+
5+
MDX content no longer ignores Layout components. See [the MDX docs](https://mdxjs.com/docs/using-mdx/#layout) for more information.

.changeset/real-garlics-argue.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@builder.io/qwik-city': patch
3+
---
4+
5+
Fixed MDX layout default export being ignored by transformer.

packages/qwik-city/src/buildtime/markdown/mdx.ts

+3-10
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { rehypeSyntaxHighlight } from './syntax-highlight';
44
import type { BuildContext } from '../types';
55
import { parseFrontmatter } from './frontmatter';
66
import { getExtension } from '../../utils/fs';
7-
import { createHash } from 'node:crypto';
87
import type { CompileOptions } from '@mdx-js/mdx';
98

109
export async function createMdxTransformer(ctx: BuildContext): Promise<MdxTransform> {
@@ -70,17 +69,11 @@ export async function createMdxTransformer(ctx: BuildContext): Promise<MdxTransf
7069
const file = new VFile({ value: code, path: id });
7170
const compiled = await compile(file, options);
7271
const output = String(compiled.value);
73-
const hasher = createHash('sha256');
74-
const key = hasher
75-
.update(output)
76-
.digest('base64')
77-
.slice(0, 8)
78-
.replace('+', '-')
79-
.replace('/', '_');
80-
const addImport = `import { _jsxC, RenderOnce } from '@builder.io/qwik';\n`;
72+
const addImport = `import { jsx } from '@builder.io/qwik';\n`;
8173
const newDefault = `
8274
const WrappedMdxContent = () => {
83-
return _jsxC(RenderOnce, {children: _jsxC(_createMdxContent, {}, 3, null)}, 3, ${JSON.stringify(key)});
75+
const content = _createMdxContent({});
76+
return typeof MDXLayout === 'function' ? jsx(MDXLayout, {children: content}) : content;
8477
};
8578
export default WrappedMdxContent;
8679
`;

packages/qwik-city/src/buildtime/markdown/mdx.unit.ts

+96-15
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
import { describe, expect, test } from 'vitest';
22
import { createMdxTransformer } from './mdx';
33

4-
describe('mdx', () => {
5-
test('convert mdx', async () => {
6-
const ctx = {
7-
frontmatter: new Map(),
8-
opts: {
9-
mdx: {
10-
remarkPlugins: [],
11-
rehypePlugins: [],
12-
},
13-
mdxPlugins: {},
4+
// It could be that new MDX versions change the output used for snapshot matching. Change as needed.
5+
describe('mdx', async () => {
6+
const ctx = {
7+
frontmatter: new Map(),
8+
opts: {
9+
mdx: {
10+
remarkPlugins: [],
11+
rehypePlugins: [],
1412
},
15-
};
16-
const transformer = await createMdxTransformer(ctx as any);
13+
mdxPlugins: {},
14+
},
15+
};
16+
17+
const transformer = await createMdxTransformer(ctx as any);
18+
19+
test('convert flat mdx', async () => {
1720
const mdx = `
1821
# Hello
1922
<a href="http://example.com">Hello</a>
2023
<div>World</div>
2124
`;
2225
const result = await transformer(mdx, 'file.mdx');
23-
// It could be that new mdx versions change this output, make sure it still makes sense
26+
2427
expect(result).toMatchInlineSnapshot(`
2528
{
26-
"code": "import { _jsxC, RenderOnce } from '@builder.io/qwik';
29+
"code": "import { jsx } from '@builder.io/qwik';
2730
import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "@builder.io/qwik/jsx-runtime";
2831
export const headings = [{
2932
"text": "Hello",
@@ -59,7 +62,8 @@ describe('mdx', () => {
5962
}
6063
6164
const WrappedMdxContent = () => {
62-
return _jsxC(RenderOnce, {children: _jsxC(_createMdxContent, {}, 3, null)}, 3, "eB2HIyA1");
65+
const content = _createMdxContent({});
66+
return typeof MDXLayout === 'function' ? jsx(MDXLayout, {children: content}) : content;
6367
};
6468
export default WrappedMdxContent;
6569
",
@@ -75,4 +79,81 @@ describe('mdx', () => {
7579
}
7680
`);
7781
});
82+
83+
test('convert layout mdx', async () => {
84+
const mdx = `
85+
# Hello
86+
87+
export default function Layout({ children: content }) {
88+
return <main>{content}</main>;
89+
}
90+
91+
<a href="http://example.com">Hello</a>
92+
<div>World</div>
93+
`;
94+
const result = await transformer(mdx, 'file.mdx');
95+
96+
expect(result).toMatchInlineSnapshot(`
97+
{
98+
"code": "import { jsx } from '@builder.io/qwik';
99+
import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "@builder.io/qwik/jsx-runtime";
100+
export const headings = [{
101+
"text": "Hello",
102+
"id": "hello",
103+
"level": 1
104+
}];
105+
export const frontmatter = undefined;
106+
const MDXLayout = function Layout({children: content}) {
107+
return _jsx("main", {
108+
children: content
109+
});
110+
};
111+
function _createMdxContent(props) {
112+
const _components = {
113+
a: "a",
114+
h1: "h1",
115+
span: "span",
116+
...props.components
117+
};
118+
return _jsxs(_Fragment, {
119+
children: [_jsxs(_components.h1, {
120+
id: "hello",
121+
children: [_jsx(_components.a, {
122+
"aria-hidden": "true",
123+
tabindex: "-1",
124+
href: "#hello",
125+
children: _jsx(_components.span, {
126+
class: "icon icon-link"
127+
})
128+
}), "Hello"]
129+
}), "\\n", "\\n", _jsx("a", {
130+
href: "http://example.com",
131+
children: "Hello"
132+
}), "\\n", _jsx("div", {
133+
children: "World"
134+
})]
135+
});
136+
}
137+
138+
const WrappedMdxContent = () => {
139+
const content = _createMdxContent({});
140+
return typeof MDXLayout === 'function' ? jsx(MDXLayout, {children: content}) : content;
141+
};
142+
export default WrappedMdxContent;
143+
",
144+
"map": {
145+
"file": "file.mdx",
146+
"mappings": ";;;;;;;kBAGe,iBAAkBA,UAAUC;cACjC;cAAMA;;;;;;;;;;;;;;;;;;;;UAHd;;;gBAM2B;;gBACxB",
147+
"names": [
148+
"children",
149+
"content",
150+
],
151+
"sources": [
152+
"file.mdx",
153+
],
154+
"version": 3,
155+
},
156+
}
157+
`);
158+
});
78159
});

0 commit comments

Comments
 (0)