diff --git a/.changeset/wicked-adults-pull.md b/.changeset/wicked-adults-pull.md new file mode 100644 index 000000000..f36d0a054 --- /dev/null +++ b/.changeset/wicked-adults-pull.md @@ -0,0 +1,6 @@ +--- +'astro': patch +'@astrojs/markdown-remark': minor +--- + +Significantally more stable behavior for "Markdown + Components" usage, which now handles component serialization much more similarly to MDX. Also supports switching between Components and Markdown without extra newlines, removes wrapping `

` tags from standalone components, and improves JSX expression handling. diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 642fe9ffb..ada2427ad 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -513,16 +513,6 @@ export interface AstroUserConfig { */ drafts?: boolean; - /** - * @docs - * @name markdown.mode - * @type {'md' | 'mdx'} - * @default `mdx` - * @description - * Control wheater to allow components inside markdown files ('mdx') or not ('md'). - */ - mode?: 'md' | 'mdx'; - /** * @docs * @name markdown.shikiConfig diff --git a/packages/astro/src/vite-plugin-markdown/index.ts b/packages/astro/src/vite-plugin-markdown/index.ts index d75351ca3..d7c02192c 100644 --- a/packages/astro/src/vite-plugin-markdown/index.ts +++ b/packages/astro/src/vite-plugin-markdown/index.ts @@ -84,7 +84,7 @@ export default function markdown({ config }: AstroPluginOptions): Plugin { const source = await fs.promises.readFile(fileId, 'utf8'); const { data: frontmatter } = matter(source); return { - code: ` + code: ` // Static export const frontmatter = ${JSON.stringify(frontmatter)}; export const file = ${JSON.stringify(fileId)}; @@ -122,12 +122,17 @@ export default function markdown({ config }: AstroPluginOptions): Plugin { const hasInjectedScript = isPage && config._ctx.scripts.some((s) => s.stage === 'page-ssr'); // Extract special frontmatter keys - const { data: frontmatter, content: markdownContent } = matter(source); - let renderResult = await renderMarkdown(markdownContent, renderOpts); + let { data: frontmatter, content: markdownContent } = matter(source); + + // Turn HTML comments into JS comments + markdownContent = markdownContent.replace(/<\s*!--([^-->]*)(.*?)-->/gs, (whole) => `{/*${whole}*/}`) + + let renderResult = await renderMarkdown(markdownContent, { ...renderOpts, fileURL: fileUrl } as any); let { code: astroResult, metadata } = renderResult; const { layout = '', components = '', setup = '', ...content } = frontmatter; content.astro = metadata; const prelude = `--- +import { slug as $$slug } from '@astrojs/markdown-remark'; ${layout ? `import Layout from '${layout}';` : ''} ${components ? `import * from '${components}';` : ''} ${hasInjectedScript ? `import '${PAGE_SSR_SCRIPT_ID}';` : ''} @@ -151,6 +156,8 @@ ${setup}`.trim(); site: config.site ? new URL(config.base, config.site).toString() : undefined, sourcefile: id, sourcemap: 'inline', + // TODO: baseline flag + experimentalStaticExtraction: true, internalURL: `/@fs${prependForwardSlash( viteID(new URL('../runtime/server/index.js', import.meta.url)) )}`, diff --git a/packages/astro/test/astro-markdown.test.js b/packages/astro/test/astro-markdown.test.js index cfbf33b0a..0f9d28c86 100644 --- a/packages/astro/test/astro-markdown.test.js +++ b/packages/astro/test/astro-markdown.test.js @@ -28,12 +28,57 @@ describe('Astro Markdown', () => { const $ = cheerio.load(html); expect($('h2').html()).to.equal('Blog Post with JSX expressions'); - expect($('p').first().html()).to.equal('JSX at the start of the line!'); + + expect(html).to.contain('JSX at the start of the line!'); for (let listItem of ['test-1', 'test-2', 'test-3']) { - expect($(`#${listItem}`).html()).to.equal(`\n${listItem}\n`); + expect($(`#${listItem}`).html()).to.equal(`${listItem}`); } }); + it('Can handle slugs with JSX expressions in markdown pages', async () => { + const html = await fixture.readFile('/slug/index.html'); + const $ = cheerio.load(html); + + expect($('h1').attr("id")).to.equal('my-blog-post'); + }); + + it('Can handle code elements without extra spacing', async () => { + const html = await fixture.readFile('/code-element/index.html'); + const $ = cheerio.load(html); + + $('code').each((_, el) => { + expect($(el).html()).to.equal($(el).html().trim()) + }); + }); + + it('Can handle namespaced components in markdown', async () => { + const html = await fixture.readFile('/namespace/index.html'); + const $ = cheerio.load(html); + + expect($('h1').text()).to.equal('Hello Namespace!'); + expect($('button').length).to.equal(1); + }); + + it('Correctly handles component children in markdown pages (#3319)', async () => { + const html = await fixture.readFile('/children/index.html'); + + expect(html).not.to.contain('

'); + }); + + it('Can handle HTML comments in markdown pages', async () => { + const html = await fixture.readFile('/comment/index.html'); + const $ = cheerio.load(html); + + expect($('h1').text()).to.equal('It works!'); + }); + + // https://github.com/withastro/astro/issues/3254 + it('Can handle scripts in markdown pages', async () => { + const html = await fixture.readFile('/script/index.html'); + console.log(html); + expect(html).not.to.match(new RegExp("\/src\/scripts\/test\.js")); + }); + it('Can load more complex jsxy stuff', async () => { const html = await fixture.readFile('/complex/index.html'); const $ = cheerio.load(html); diff --git a/packages/astro/test/fixtures/astro-markdown/src/components/TextBlock.jsx b/packages/astro/test/fixtures/astro-markdown/src/components/TextBlock.jsx new file mode 100644 index 000000000..d9ea2534f --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown/src/components/TextBlock.jsx @@ -0,0 +1,20 @@ +import { h } from 'preact'; + +const TextBlock = ({ + title, + children, + noPadding = false, +}) => { + return ( +
+

{title}

+

{children}

+
+ ); +}; + +export default TextBlock; diff --git a/packages/astro/test/fixtures/astro-markdown/src/components/index.js b/packages/astro/test/fixtures/astro-markdown/src/components/index.js new file mode 100644 index 000000000..e7cc94c58 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown/src/components/index.js @@ -0,0 +1,5 @@ +import Counter from './Counter'; + +export default { + Counter +} diff --git a/packages/astro/test/fixtures/astro-markdown/src/content/code-element.md b/packages/astro/test/fixtures/astro-markdown/src/content/code-element.md new file mode 100644 index 000000000..b091decc0 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown/src/content/code-element.md @@ -0,0 +1,3 @@ +This should have `nospace` around it. + +This should have nospace around it. diff --git a/packages/astro/test/fixtures/astro-markdown/src/pages/children.md b/packages/astro/test/fixtures/astro-markdown/src/pages/children.md new file mode 100644 index 000000000..a22ee5f96 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown/src/pages/children.md @@ -0,0 +1,12 @@ +--- +setup: import TextBlock from '../components/TextBlock' +--- +{/* https://github.com/withastro/astro/issues/3319 */} + + + + diff --git a/packages/astro/test/fixtures/astro-markdown/src/pages/code-element.astro b/packages/astro/test/fixtures/astro-markdown/src/pages/code-element.astro new file mode 100644 index 000000000..43ca0bfc5 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown/src/pages/code-element.astro @@ -0,0 +1,7 @@ +--- +const content = await Astro.glob('../content/*.md'); +--- + +
+ {content.map(({ Content }) => )} +
diff --git a/packages/astro/test/fixtures/astro-markdown/src/pages/comment.md b/packages/astro/test/fixtures/astro-markdown/src/pages/comment.md new file mode 100644 index 000000000..39a916351 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown/src/pages/comment.md @@ -0,0 +1,2 @@ + +# It works! diff --git a/packages/astro/test/fixtures/astro-markdown/src/pages/jsx-expressions.md b/packages/astro/test/fixtures/astro-markdown/src/pages/jsx-expressions.md index 2f038fdad..b87efbb2d 100644 --- a/packages/astro/test/fixtures/astro-markdown/src/pages/jsx-expressions.md +++ b/packages/astro/test/fixtures/astro-markdown/src/pages/jsx-expressions.md @@ -8,4 +8,6 @@ list: ['test-1', 'test-2', 'test-3'] {frontmatter.paragraph} -{frontmatter.list.map(item =>

{item}

)} + diff --git a/packages/astro/test/fixtures/astro-markdown/src/pages/namespace.md b/packages/astro/test/fixtures/astro-markdown/src/pages/namespace.md new file mode 100644 index 000000000..abbe26a3b --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown/src/pages/namespace.md @@ -0,0 +1,7 @@ +--- +setup: import ns from '../components/index.js'; +--- + +# Hello Namespace! + +Click me! diff --git a/packages/astro/test/fixtures/astro-markdown/src/pages/script.md b/packages/astro/test/fixtures/astro-markdown/src/pages/script.md new file mode 100644 index 000000000..f2b8bca88 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown/src/pages/script.md @@ -0,0 +1,7 @@ +# Test + +## Let's try a script... + +This should work! + +