summaryrefslogtreecommitdiff
path: root/packages/markdown/remark/src
diff options
context:
space:
mode:
authorGravatar nokazn <41154684+nokazn@users.noreply.github.com> 2022-06-03 21:26:39 +0900
committerGravatar GitHub <noreply@github.com> 2022-06-03 08:26:39 -0400
commit939fe159255cecf1cab5c1b3da2670d30ac8e4a7 (patch)
tree87de62f9bafed40ccb82a3263557b6fca363968e /packages/markdown/remark/src
parentd2bfb754c0b8fe9e46ca28d3152ef5f5500331fd (diff)
downloadastro-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.ts23
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