diff options
author | 2022-06-03 21:26:39 +0900 | |
---|---|---|
committer | 2022-06-03 08:26:39 -0400 | |
commit | 939fe159255cecf1cab5c1b3da2670d30ac8e4a7 (patch) | |
tree | 87de62f9bafed40ccb82a3263557b6fca363968e /packages/markdown/remark/src | |
parent | d2bfb754c0b8fe9e46ca28d3152ef5f5500331fd (diff) | |
download | astro-939fe159255cecf1cab5c1b3da2670d30ac8e4a7.tar.gz astro-939fe159255cecf1cab5c1b3da2670d30ac8e4a7.tar.zst astro-939fe159255cecf1cab5c1b3da2670d30ac8e4a7.zip |
Fix cases for JSX-like expressions in code blocks of headings (#3502)
* chore: fix typo in remark tests
* test: add test cases for markdown expressions in header
* fix: avoid evaluating JSX-like expressions inside inline code in heading
* fix: generate slug for id including values in backtick blocks
Diffstat (limited to 'packages/markdown/remark/src')
-rw-r--r-- | packages/markdown/remark/src/rehype-collect-headers.ts | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/packages/markdown/remark/src/rehype-collect-headers.ts b/packages/markdown/remark/src/rehype-collect-headers.ts index 426b782a3..44881864b 100644 --- a/packages/markdown/remark/src/rehype-collect-headers.ts +++ b/packages/markdown/remark/src/rehype-collect-headers.ts @@ -1,4 +1,5 @@ import { visit } from 'unist-util-visit'; +import { toHtml } from 'hast-util-to-html'; import Slugger from 'github-slugger'; import type { MarkdownHeader, RehypePlugin } from './types.js'; @@ -17,32 +18,36 @@ export default function createCollectHeaders() { if (!level) return; const depth = Number.parseInt(level); - let raw = ''; let text = ''; let isJSX = false; - visit(node, (child) => { - if (child.type === 'element') { + visit(node, (child, _, parent) => { + if (child.type === 'element' || parent == null) { return; } if (child.type === 'raw') { - // HACK: serialized JSX from internal plugins, ignore these for slug if (child.value.startsWith('\n<') || child.value.endsWith('>\n')) { - raw += child.value.replace(/^\n|\n$/g, ''); return; } } if (child.type === 'text' || child.type === 'raw') { - raw += child.value; - text += child.value; - isJSX = isJSX || child.value.includes('{'); + if (new Set(['code', 'pre']).has(parent.tagName)) { + text += child.value; + } else { + text += child.value.replace(/\{/g, '${'); + isJSX = isJSX || child.value.includes('{'); + } } }); node.properties = node.properties || {}; if (typeof node.properties.id !== 'string') { if (isJSX) { + // HACK: serialized JSX from internal plugins, ignore these for slug + const raw = toHtml(node.children, { allowDangerousHtml: true }) + .replace(/\n(<)/g, '<') + .replace(/(>)\n/g, '>'); // HACK: for ids that have JSX content, use $$slug helper to generate slug at runtime - node.properties.id = `$$slug(\`${text.replace(/\{/g, '${')}\`)`; + node.properties.id = `$$slug(\`${text}\`)`; (node as any).type = 'raw'; ( node as any |