From 5a3e489aac6a32849d7cbc39dbba6d46f304b1fb Mon Sep 17 00:00:00 2001 From: Daniel van Dijk Date: Sun, 13 Oct 2024 22:53:12 +0200 Subject: [PATCH] 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 --- .changeset/lazy-worms-attack.md | 5 + .changeset/real-garlics-argue.md | 5 + .../qwik-city/src/buildtime/markdown/mdx.ts | 13 +- .../src/buildtime/markdown/mdx.unit.ts | 111 +++++++++++++++--- 4 files changed, 109 insertions(+), 25 deletions(-) create mode 100644 .changeset/lazy-worms-attack.md create mode 100644 .changeset/real-garlics-argue.md diff --git a/.changeset/lazy-worms-attack.md b/.changeset/lazy-worms-attack.md new file mode 100644 index 00000000000..de866e201c0 --- /dev/null +++ b/.changeset/lazy-worms-attack.md @@ -0,0 +1,5 @@ +--- +'@builder.io/qwik-city': patch +--- + +MDX content no longer ignores Layout components. See [the MDX docs](https://mdxjs.com/docs/using-mdx/#layout) for more information. diff --git a/.changeset/real-garlics-argue.md b/.changeset/real-garlics-argue.md new file mode 100644 index 00000000000..45032734e77 --- /dev/null +++ b/.changeset/real-garlics-argue.md @@ -0,0 +1,5 @@ +--- +'@builder.io/qwik-city': patch +--- + +Fixed MDX layout default export being ignored by transformer. diff --git a/packages/qwik-city/src/buildtime/markdown/mdx.ts b/packages/qwik-city/src/buildtime/markdown/mdx.ts index 55dbf5f5e89..00bd6f15cfa 100644 --- a/packages/qwik-city/src/buildtime/markdown/mdx.ts +++ b/packages/qwik-city/src/buildtime/markdown/mdx.ts @@ -4,7 +4,6 @@ import { rehypeSyntaxHighlight } from './syntax-highlight'; import type { BuildContext } from '../types'; import { parseFrontmatter } from './frontmatter'; import { getExtension } from '../../utils/fs'; -import { createHash } from 'node:crypto'; import type { CompileOptions } from '@mdx-js/mdx'; export async function createMdxTransformer(ctx: BuildContext): Promise { @@ -70,17 +69,11 @@ export async function createMdxTransformer(ctx: BuildContext): Promise { - return _jsxC(RenderOnce, {children: _jsxC(_createMdxContent, {}, 3, null)}, 3, ${JSON.stringify(key)}); + const content = _createMdxContent({}); + return typeof MDXLayout === 'function' ? jsx(MDXLayout, {children: content}) : content; }; export default WrappedMdxContent; `; diff --git a/packages/qwik-city/src/buildtime/markdown/mdx.unit.ts b/packages/qwik-city/src/buildtime/markdown/mdx.unit.ts index 814776b3d7b..79222658876 100644 --- a/packages/qwik-city/src/buildtime/markdown/mdx.unit.ts +++ b/packages/qwik-city/src/buildtime/markdown/mdx.unit.ts @@ -1,29 +1,32 @@ import { describe, expect, test } from 'vitest'; import { createMdxTransformer } from './mdx'; -describe('mdx', () => { - test('convert mdx', async () => { - const ctx = { - frontmatter: new Map(), - opts: { - mdx: { - remarkPlugins: [], - rehypePlugins: [], - }, - mdxPlugins: {}, +// It could be that new MDX versions change the output used for snapshot matching. Change as needed. +describe('mdx', async () => { + const ctx = { + frontmatter: new Map(), + opts: { + mdx: { + remarkPlugins: [], + rehypePlugins: [], }, - }; - const transformer = await createMdxTransformer(ctx as any); + mdxPlugins: {}, + }, + }; + + const transformer = await createMdxTransformer(ctx as any); + + test('convert flat mdx', async () => { const mdx = ` # Hello Hello
World
`; const result = await transformer(mdx, 'file.mdx'); - // It could be that new mdx versions change this output, make sure it still makes sense + expect(result).toMatchInlineSnapshot(` { - "code": "import { _jsxC, RenderOnce } from '@builder.io/qwik'; + "code": "import { jsx } from '@builder.io/qwik'; import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "@builder.io/qwik/jsx-runtime"; export const headings = [{ "text": "Hello", @@ -59,7 +62,8 @@ describe('mdx', () => { } const WrappedMdxContent = () => { - return _jsxC(RenderOnce, {children: _jsxC(_createMdxContent, {}, 3, null)}, 3, "eB2HIyA1"); + const content = _createMdxContent({}); + return typeof MDXLayout === 'function' ? jsx(MDXLayout, {children: content}) : content; }; export default WrappedMdxContent; ", @@ -75,4 +79,81 @@ describe('mdx', () => { } `); }); + + test('convert layout mdx', async () => { + const mdx = ` +# Hello + +export default function Layout({ children: content }) { + return
{content}
; +} + +Hello +
World
+`; + const result = await transformer(mdx, 'file.mdx'); + + expect(result).toMatchInlineSnapshot(` + { + "code": "import { jsx } from '@builder.io/qwik'; + import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "@builder.io/qwik/jsx-runtime"; + export const headings = [{ + "text": "Hello", + "id": "hello", + "level": 1 + }]; + export const frontmatter = undefined; + const MDXLayout = function Layout({children: content}) { + return _jsx("main", { + children: content + }); + }; + function _createMdxContent(props) { + const _components = { + a: "a", + h1: "h1", + span: "span", + ...props.components + }; + return _jsxs(_Fragment, { + children: [_jsxs(_components.h1, { + id: "hello", + children: [_jsx(_components.a, { + "aria-hidden": "true", + tabindex: "-1", + href: "#hello", + children: _jsx(_components.span, { + class: "icon icon-link" + }) + }), "Hello"] + }), "\\n", "\\n", _jsx("a", { + href: "http://example.com", + children: "Hello" + }), "\\n", _jsx("div", { + children: "World" + })] + }); + } + + const WrappedMdxContent = () => { + const content = _createMdxContent({}); + return typeof MDXLayout === 'function' ? jsx(MDXLayout, {children: content}) : content; + }; + export default WrappedMdxContent; + ", + "map": { + "file": "file.mdx", + "mappings": ";;;;;;;kBAGe,iBAAkBA,UAAUC;cACjC;cAAMA;;;;;;;;;;;;;;;;;;;;UAHd;;;gBAM2B;;gBACxB", + "names": [ + "children", + "content", + ], + "sources": [ + "file.mdx", + ], + "version": 3, + }, + } + `); + }); });