summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/moody-crabs-occur.md6
-rw-r--r--packages/astro/src/vite-plugin-markdown/index.ts22
-rw-r--r--packages/astro/test/astro-markdown-md-mode.test.js52
-rw-r--r--packages/astro/test/fixtures/astro-markdown-md-mode/astro.config.mjs11
-rw-r--r--packages/astro/test/fixtures/astro-markdown-md-mode/package.json9
-rw-r--r--packages/astro/test/fixtures/astro-markdown-md-mode/src/components/Counter.svelte5
-rw-r--r--packages/astro/test/fixtures/astro-markdown-md-mode/src/pages/code-in-md.md7
-rw-r--r--packages/astro/test/fixtures/astro-markdown-md-mode/src/pages/components.md5
-rw-r--r--packages/astro/test/fixtures/astro-markdown-md-mode/src/pages/jsx-expressions.md13
-rw-r--r--packages/markdown/remark/src/index.ts18
-rw-r--r--pnpm-lock.yaml8
11 files changed, 143 insertions, 13 deletions
diff --git a/.changeset/moody-crabs-occur.md b/.changeset/moody-crabs-occur.md
new file mode 100644
index 000000000..050e9ec0d
--- /dev/null
+++ b/.changeset/moody-crabs-occur.md
@@ -0,0 +1,6 @@
+---
+'astro': patch
+'@astrojs/markdown-remark': patch
+---
+
+Avoid parsing JSX, components, and Astro islands when using "plain" md mode. This brings `markdown.mode: 'md'` in-line with our docs description.
diff --git a/packages/astro/src/vite-plugin-markdown/index.ts b/packages/astro/src/vite-plugin-markdown/index.ts
index 2c218610b..3d70aba72 100644
--- a/packages/astro/src/vite-plugin-markdown/index.ts
+++ b/packages/astro/src/vite-plugin-markdown/index.ts
@@ -137,6 +137,7 @@ export default function markdown({ config }: AstroPluginOptions): Plugin {
const filename = normalizeFilename(id);
const source = await fs.promises.readFile(filename, 'utf8');
const renderOpts = config.markdown;
+ const isMDX = renderOpts.mode === 'mdx';
const fileUrl = new URL(`file://${filename}`);
const isPage = fileUrl.pathname.startsWith(resolvePages(config).pathname);
@@ -148,7 +149,7 @@ export default function markdown({ config }: AstroPluginOptions): Plugin {
// Turn HTML comments into JS comments while preventing nested `*/` sequences
// from ending the JS comment by injecting a zero-width space
// Inside code blocks, this is removed during renderMarkdown by the remark-escape plugin.
- if (renderOpts.mode === 'mdx') {
+ if (isMDX) {
markdownContent = markdownContent.replace(
/<\s*!--([^-->]*)(.*?)-->/gs,
(whole) => `{/*${whole.replace(/\*\//g, '*\u200b/')}*/}`
@@ -167,19 +168,30 @@ export default function markdown({ config }: AstroPluginOptions): Plugin {
const prelude = `---
import Slugger from 'github-slugger';
${layout ? `import Layout from '${layout}';` : ''}
-${components ? `import * from '${components}';` : ''}
+${isMDX && components ? `import * from '${components}';` : ''}
${hasInjectedScript ? `import '${PAGE_SSR_SCRIPT_ID}';` : ''}
-${setup}
+${isMDX ? setup : ''}
const slugger = new Slugger();
function $$slug(value) {
return slugger.slug(value);
}
-const $$content = ${JSON.stringify(content)}
+const $$content = ${JSON.stringify(isMDX
+ ? content
+ // Avoid stripping "setup" and "components"
+ // in plain MD mode
+ : { ...content, setup, components })}
---`;
const imports = `${layout ? `import Layout from '${layout}';` : ''}
-${setup}`.trim();
+${isMDX ? setup : ''}`.trim();
+
+ // Wrap with set:html fragment to skip
+ // JSX expressions and components in "plain" md mode
+ if (!isMDX) {
+ astroResult = `<Fragment set:html={${JSON.stringify(astroResult)}} />`
+ }
+
// If the user imported "Layout", wrap the content in a Layout
if (/\bLayout\b/.test(imports)) {
astroResult = `${prelude}\n<Layout content={$$content}>\n\n${astroResult}\n\n</Layout>`;
diff --git a/packages/astro/test/astro-markdown-md-mode.test.js b/packages/astro/test/astro-markdown-md-mode.test.js
new file mode 100644
index 000000000..46056605f
--- /dev/null
+++ b/packages/astro/test/astro-markdown-md-mode.test.js
@@ -0,0 +1,52 @@
+import { expect } from 'chai';
+import * as cheerio from 'cheerio';
+import { loadFixture } from './test-utils.js';
+
+describe('Astro Markdown - plain MD mode', () => {
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: './fixtures/astro-markdown-md-mode/',
+ });
+ await fixture.build();
+ });
+
+ it('Leaves JSX expressions unprocessed', async () => {
+ const html = await fixture.readFile('/jsx-expressions/index.html');
+ const $ = cheerio.load(html);
+
+ expect($('h2').html()).to.equal('{frontmatter.title}');
+ });
+
+ it('Leaves JSX components un-transformed', async () => {
+ const html = await fixture.readFile('/components/index.html');
+
+ expect(html).to.include('<counter client:load="" count="{0}">');
+ });
+
+ describe('syntax highlighting', async () => {
+ it('handles Shiki', async () => {
+ const html = await fixture.readFile('/code-in-md/index.html');
+ const $ = cheerio.load(html);
+
+ expect($('pre.astro-code').length).to.not.equal(0);
+ });
+
+ it('handles Prism', async () => {
+ fixture = await loadFixture({
+ root: './fixtures/astro-markdown-md-mode/',
+ markdown: {
+ syntaxHighlight: 'prism',
+ mode: 'md',
+ },
+ });
+ await fixture.build();
+
+ const html = await fixture.readFile('/code-in-md/index.html');
+ const $ = cheerio.load(html);
+
+ expect($('pre.language-html').length).to.not.equal(0);
+ });
+ });
+});
diff --git a/packages/astro/test/fixtures/astro-markdown-md-mode/astro.config.mjs b/packages/astro/test/fixtures/astro-markdown-md-mode/astro.config.mjs
new file mode 100644
index 000000000..3fab631f3
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-markdown-md-mode/astro.config.mjs
@@ -0,0 +1,11 @@
+import { defineConfig } from 'astro/config';
+import svelte from "@astrojs/svelte";
+
+// https://astro.build/config
+export default defineConfig({
+ markdown: {
+ mode: 'md',
+ },
+ integrations: [svelte()],
+ site: 'https://astro.build/',
+});
diff --git a/packages/astro/test/fixtures/astro-markdown-md-mode/package.json b/packages/astro/test/fixtures/astro-markdown-md-mode/package.json
new file mode 100644
index 000000000..48a6c6816
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-markdown-md-mode/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "@test/astro-markdown-md-mode",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "@astrojs/svelte": "workspace:*",
+ "astro": "workspace:*"
+ }
+}
diff --git a/packages/astro/test/fixtures/astro-markdown-md-mode/src/components/Counter.svelte b/packages/astro/test/fixtures/astro-markdown-md-mode/src/components/Counter.svelte
new file mode 100644
index 000000000..4e91b2659
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-markdown-md-mode/src/components/Counter.svelte
@@ -0,0 +1,5 @@
+<script>
+ export let count = 0;
+</script>
+
+<button onClick={() => count += 1}>{count}</button>
diff --git a/packages/astro/test/fixtures/astro-markdown-md-mode/src/pages/code-in-md.md b/packages/astro/test/fixtures/astro-markdown-md-mode/src/pages/code-in-md.md
new file mode 100644
index 000000000..72206a868
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-markdown-md-mode/src/pages/code-in-md.md
@@ -0,0 +1,7 @@
+# Fenced code blocks
+
+```html
+<body>
+ <div>This should also work without any problems.</div>
+</body>
+```
diff --git a/packages/astro/test/fixtures/astro-markdown-md-mode/src/pages/components.md b/packages/astro/test/fixtures/astro-markdown-md-mode/src/pages/components.md
new file mode 100644
index 000000000..cd27bc09f
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-markdown-md-mode/src/pages/components.md
@@ -0,0 +1,5 @@
+---
+setup: import Counter from '../components/Counter.svelte'
+---
+
+<Counter client:load count={0}></Counter>
diff --git a/packages/astro/test/fixtures/astro-markdown-md-mode/src/pages/jsx-expressions.md b/packages/astro/test/fixtures/astro-markdown-md-mode/src/pages/jsx-expressions.md
new file mode 100644
index 000000000..b87efbb2d
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-markdown-md-mode/src/pages/jsx-expressions.md
@@ -0,0 +1,13 @@
+---
+title: Blog Post with JSX expressions
+paragraph: JSX at the start of the line!
+list: ['test-1', 'test-2', 'test-3']
+---
+
+## {frontmatter.title}
+
+{frontmatter.paragraph}
+
+<ul>
+ {frontmatter.list.map(item => <li id={item}>{item}</li>)}
+</ul>
diff --git a/packages/markdown/remark/src/index.ts b/packages/markdown/remark/src/index.ts
index 567a4414d..6c72ba981 100644
--- a/packages/markdown/remark/src/index.ts
+++ b/packages/markdown/remark/src/index.ts
@@ -46,8 +46,7 @@ export async function renderMarkdown(
let parser = unified()
.use(markdown)
- .use(isMDX ? [remarkMdxish, remarkMarkAndUnravel] : [])
- .use([remarkUnwrap, remarkEscape]);
+ .use(isMDX ? [remarkMdxish, remarkMarkAndUnravel, remarkUnwrap, remarkEscape] : [])
if (remarkPlugins.length === 0 && rehypePlugins.length === 0) {
remarkPlugins = [...DEFAULT_REMARK_PLUGINS];
@@ -76,13 +75,13 @@ export async function renderMarkdown(
markdownToHtml as any,
{
allowDangerousHtml: true,
- passThrough: [
+ passThrough: isMDX ? [
'raw',
'mdxFlowExpression',
'mdxJsxFlowElement',
'mdxJsxTextElement',
'mdxTextExpression',
- ],
+ ] : [],
},
],
]);
@@ -92,10 +91,13 @@ export async function renderMarkdown(
});
parser
- .use(isMDX ? [rehypeJsx, rehypeExpressions] : [rehypeRaw])
- .use(rehypeEscape)
- .use(rehypeIslands)
- .use([rehypeCollectHeaders])
+ .use(isMDX ? [
+ rehypeJsx,
+ rehypeExpressions,
+ rehypeEscape,
+ rehypeIslands,
+ rehypeCollectHeaders,
+ ] : [rehypeCollectHeaders, rehypeRaw])
.use(rehypeStringify, { allowDangerousHtml: true });
let result: string;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0f48f3ed9..633ee1b9d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1280,6 +1280,14 @@ importers:
dependencies:
astro: link:../../..
+ packages/astro/test/fixtures/astro-markdown-md-mode:
+ specifiers:
+ '@astrojs/svelte': workspace:*
+ astro: workspace:*
+ dependencies:
+ '@astrojs/svelte': link:../../../../integrations/svelte
+ astro: link:../../..
+
packages/astro/test/fixtures/astro-markdown-plugins:
specifiers:
'@astrojs/preact': workspace:*