Fix: use set:html when markdown mode is md (#4008)

* refactor: add legacy.jsxInMarkdown flag to config

* fix: use `set:html` when `markdown.mode` is 'md'

* Revert "refactor: add legacy.jsxInMarkdown flag to config"

This reverts commit 5572e8d9b3.

* fix: move `remarkUnwrap, remarkEscape` to MDX only

* fix: only apply scary HTML passthroughs on MDX

* fix: move all JSX-specific rehype plugins under `isMDX`

* fix: "allowDangerousHtml" for md (required for Shiki)

* fix: apply `set:html` for non-layouts too

* test: JSX expressions, components, syntax highlighting

* chore: changeset

* fix: ignore "setup" and "components" in plain MD mode

* refactor: create new fixture to avoid weird caching error

* fix: dup package name

* chore: update lock

* fix: apply rehypeCollectHeaders to md
This commit is contained in:
Ben Holmes 2022-07-21 18:01:26 -04:00 committed by GitHub
parent c2968b0542
commit 399d7e2698
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 143 additions and 13 deletions

View file

@ -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.

View file

@ -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>`;

View file

@ -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);
});
});
});

View file

@ -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/',
});

View file

@ -0,0 +1,9 @@
{
"name": "@test/astro-markdown-md-mode",
"version": "0.0.0",
"private": true,
"dependencies": {
"@astrojs/svelte": "workspace:*",
"astro": "workspace:*"
}
}

View file

@ -0,0 +1,5 @@
<script>
export let count = 0;
</script>
<button onClick={() => count += 1}>{count}</button>

View file

@ -0,0 +1,7 @@
# Fenced code blocks
```html
<body>
<div>This should also work without any problems.</div>
</body>
```

View file

@ -0,0 +1,5 @@
---
setup: import Counter from '../components/Counter.svelte'
---
<Counter client:load count={0}></Counter>

View file

@ -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>

View file

@ -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;

View file

@ -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:*