Skip to content

Commit

Permalink
fix: avoid evaluating JSX-like expressions inside inline code in heading
Browse files Browse the repository at this point in the history
  • Loading branch information
nokazn committed Jun 2, 2022
1 parent 33d987b commit 45dbd17
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/lazy-humans-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/markdown-remark': minor
---

Fix cases for JSX-like expressions in code blocks of headings
1 change: 1 addition & 0 deletions packages/markdown/remark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@astrojs/prism": "^0.4.1",
"assert": "^2.0.0",
"github-slugger": "^1.4.0",
"hast-util-to-html": "^8.0.3",
"mdast-util-mdx-expression": "^1.2.0",
"mdast-util-mdx-jsx": "^1.2.0",
"mdast-util-to-string": "^3.1.0",
Expand Down
13 changes: 7 additions & 6 deletions packages/markdown/remark/src/rehype-collect-headers.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -17,22 +18,18 @@ 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' || ['code', 'pre'].some((tag) => parent?.tagName === tag)) {
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('{');
}
Expand All @@ -41,6 +38,10 @@ export default function createCollectHeaders() {
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 as any).type = 'raw';
Expand Down

0 comments on commit 45dbd17

Please sign in to comment.