diff --git a/.changeset/strong-hotels-cross.md b/.changeset/strong-hotels-cross.md new file mode 100644 index 000000000000..56f5789c67a6 --- /dev/null +++ b/.changeset/strong-hotels-cross.md @@ -0,0 +1,5 @@ +--- +'@astrojs/markdown-remark': patch +--- + +Fix double-escaping of non-highlighted code blocks in Astro-flavored markdown diff --git a/packages/markdown/remark/src/rehype-escape.ts b/packages/markdown/remark/src/rehype-escape.ts index e99e37e4168b..b0a4cb923f5c 100644 --- a/packages/markdown/remark/src/rehype-escape.ts +++ b/packages/markdown/remark/src/rehype-escape.ts @@ -1,4 +1,4 @@ -import { visit } from 'unist-util-visit'; +import { visit, SKIP } from 'unist-util-visit'; export function escapeEntities(value: string): string { return value.replace(/&/g, '&').replace(//g, '>'); @@ -14,8 +14,9 @@ export default function rehypeEscape(): any { visit(el, 'raw', (raw) => { raw.value = escapeEntities(raw.value); }); + // Do not visit children to prevent double escaping + return SKIP; } - return el; }); }; } diff --git a/packages/markdown/remark/test/entities.test.js b/packages/markdown/remark/test/entities.test.js index a6b5918a5a52..dff8443291b0 100644 --- a/packages/markdown/remark/test/entities.test.js +++ b/packages/markdown/remark/test/entities.test.js @@ -2,11 +2,25 @@ import { renderMarkdown } from '../dist/index.js'; import { expect } from 'chai'; describe('entities', () => { - const renderAstroMd = (text) => renderMarkdown(text, { isAstroFlavoredMd: false }); - - it('should not unescape entities', async () => { - const { code } = await renderAstroMd(`<i>This should NOT be italic</i>`); + it('should not unescape entities in regular Markdown', async () => { + const { code } = await renderMarkdown(`<i>This should NOT be italic</i>`, { + isAstroFlavoredMd: false, + }); expect(code).to.equal(`

<i>This should NOT be italic</i>

`); }); + + it('should not escape entities in code blocks twice in Astro-flavored markdown', async () => { + const { code } = await renderMarkdown( + `\`\`\`astro\n

{x && x.name || ''}!

\n\`\`\``, + { + isAstroFlavoredMd: true, + syntaxHighlight: false, + } + ); + + expect(code).to.equal( + `
<h1>{x && x.name || ''}!</h1>\n
` + ); + }); });