diff --git a/.changeset/warm-terms-admire.md b/.changeset/warm-terms-admire.md new file mode 100644 index 000000000..6a7575706 --- /dev/null +++ b/.changeset/warm-terms-admire.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix issue where Markdown could close it's parent element early (#494) diff --git a/examples/with-markdown/src/layouts/main.astro b/examples/with-markdown/src/layouts/main.astro index 26993bcaf..c3ef56d60 100644 --- a/examples/with-markdown/src/layouts/main.astro +++ b/examples/with-markdown/src/layouts/main.astro @@ -1,4 +1,5 @@ --- +const { content } = Astro.props; --- diff --git a/examples/with-markdown/src/pages/external.astro b/examples/with-markdown/src/pages/external.astro new file mode 100644 index 000000000..1149666b2 --- /dev/null +++ b/examples/with-markdown/src/pages/external.astro @@ -0,0 +1,17 @@ +--- +import { Markdown } from 'astro/components'; +import Layout from '../layouts/main.astro'; + +const title = `External Markdown`; +const content = `Markdown *content* to render`; +--- + + +
+
+ +

Some other stuff

+
+

Lastly...

+
+
diff --git a/packages/astro/src/compiler/codegen/index.ts b/packages/astro/src/compiler/codegen/index.ts index 843ecc428..ea094a32c 100644 --- a/packages/astro/src/compiler/codegen/index.ts +++ b/packages/astro/src/compiler/codegen/index.ts @@ -509,6 +509,12 @@ async function compileHtml(enterNode: TemplateNode, state: CodegenState, compile async function pushMarkdownToBuffer() { const md = buffers.markdown; const { markdownOptions = {} } = astroConfig; + if (!md.trim()) { + buffers.out += ',' + md; + buffers.markdown = ''; + curr = 'out'; + return; + } const { $scope: scopedClassName } = state.markers.insideMarkdown as Record<'$scope', any>; let { content: rendered } = await renderMarkdown(dedent(md), { ...(markdownOptions as AstroMarkdownOptions), @@ -627,7 +633,8 @@ async function compileHtml(enterNode: TemplateNode, state: CodegenState, compile if (componentName === 'Markdown') { const { $scope } = attributes ?? {}; state.markers.insideMarkdown = typeof state.markers.insideMarkdown === 'object' ? { $scope, count: state.markers.insideMarkdown.count + 1 } : { $scope, count: 1 }; - if (attributes.content) { + const keys = Object.keys(attributes).filter(attr => attr !== '$scope'); + if (keys.length > 0) { if (curr === 'markdown') { await pushMarkdownToBuffer(); } @@ -717,7 +724,7 @@ async function compileHtml(enterNode: TemplateNode, state: CodegenState, compile case 'Body': case 'Title': case 'Element': { - if (state.markers.insideMarkdown) { + if (curr === 'markdown') { await pushMarkdownToBuffer(); } if (paren !== -1) { @@ -732,6 +739,10 @@ async function compileHtml(enterNode: TemplateNode, state: CodegenState, compile if ((state.markers.insideMarkdown as Record).count <= 0) { state.markers.insideMarkdown = false; } + const hasAttrs = (node.attributes.filter(({ name }: Attribute) => name !== '$scope')).length > 0; + if (hasAttrs) { + return; + } } if (curr === 'markdown' && buffers.markdown !== '') { await pushMarkdownToBuffer(); diff --git a/packages/astro/test/astro-markdown.test.js b/packages/astro/test/astro-markdown.test.js index cadb255bd..73e17a5f8 100644 --- a/packages/astro/test/astro-markdown.test.js +++ b/packages/astro/test/astro-markdown.test.js @@ -82,4 +82,12 @@ Markdown('Renders dynamic content though the content attribute', async ({ runtim assert.ok($('#inner').is('[class]'), 'Scoped class passed down'); }); +Markdown('Does not close parent early when using content attribute (#494)', async ({ runtime }) => { + const result = await runtime.load('/close'); + if (result.error) throw new Error(result.error); + + const $ = doc(result.contents); + assert.equal($('#target').children().length, 2, ' closed div#target early'); +}); + Markdown.run(); diff --git a/packages/astro/test/fixtures/astro-markdown/src/pages/close.astro b/packages/astro/test/fixtures/astro-markdown/src/pages/close.astro new file mode 100644 index 000000000..1da319c03 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown/src/pages/close.astro @@ -0,0 +1,12 @@ +--- +import { Markdown } from 'astro/components'; +const content = `Markdown *content* to render`; +--- + +
+
+ +

Some other stuff

+
+

Lastly...

+