summaryrefslogtreecommitdiff
path: root/packages/markdown/remark/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/markdown/remark/src')
-rw-r--r--packages/markdown/remark/src/index.ts9
-rw-r--r--packages/markdown/remark/src/rehype-jsx.ts46
2 files changed, 36 insertions, 19 deletions
diff --git a/packages/markdown/remark/src/index.ts b/packages/markdown/remark/src/index.ts
index 917976d5e..a11419474 100644
--- a/packages/markdown/remark/src/index.ts
+++ b/packages/markdown/remark/src/index.ts
@@ -99,14 +99,13 @@ export async function renderMarkdown(
parser
.use(isMDX ? [rehypeJsx, rehypeExpressions] : [rehypeRaw])
.use(rehypeEscape)
- .use(rehypeIslands);
+ .use(rehypeIslands)
+ .use([rehypeCollectHeaders])
+ .use(rehypeStringify, { allowDangerousHtml: true })
let result: string;
try {
- const vfile = await parser
- .use([rehypeCollectHeaders])
- .use(rehypeStringify, { allowDangerousHtml: true })
- .process(input);
+ const vfile = await parser.process(input);
result = vfile.toString();
} catch (err) {
// Ensure that the error message contains the input filename
diff --git a/packages/markdown/remark/src/rehype-jsx.ts b/packages/markdown/remark/src/rehype-jsx.ts
index daeb4d56a..06783ba85 100644
--- a/packages/markdown/remark/src/rehype-jsx.ts
+++ b/packages/markdown/remark/src/rehype-jsx.ts
@@ -1,15 +1,14 @@
+import type { RehypePlugin } from './types.js';
import { visit } from 'unist-util-visit';
const MDX_ELEMENTS = ['mdxJsxFlowElement', 'mdxJsxTextElement'];
-export default function rehypeJsx(): any {
- return function (node: any): any {
- visit(node, 'element', (child: any) => {
- child.tagName = `${child.tagName}`;
- });
- visit(node, MDX_ELEMENTS, (child: any, index: number | null, parent: any) => {
+
+export default function rehypeJsx(): ReturnType<RehypePlugin> {
+ return function (tree) {
+ visit(tree, MDX_ELEMENTS, (node: any, index: number | null, parent: any) => {
if (index === null || !Boolean(parent)) return;
- const attrs = child.attributes.reduce((acc: any[], entry: any) => {
+ const attrs = node.attributes.reduce((acc: any[], entry: any) => {
let attr = entry.value;
if (attr && typeof attr === 'object') {
attr = `{${attr.value}}`;
@@ -26,23 +25,42 @@ export default function rehypeJsx(): any {
return acc + ` ${entry.name}${attr ? '=' : ''}${attr}`;
}, '');
- if (child.children.length === 0) {
- child.type = 'raw';
- child.value = `<${child.name}${attrs} />`;
+ if (node.children.length === 0) {
+ node.type = 'raw';
+ node.value = `<${node.name}${attrs} />`;
return;
}
- // Replace the current child node with its children
+ // If the current node is a JSX <a> element, remove autolinks from its children
+ // to prevent Markdown code like `<a href="/">**Go to www.example.com now!**</a>`
+ // from creating a nested link to `www.example.com`
+ if (node.name === 'a') {
+ visit(node, 'element', (el, elIndex, elParent) => {
+ const isAutolink = (
+ el.tagName === 'a' &&
+ el.children.length === 1 &&
+ el.children[0].type === 'text' &&
+ el.children[0].value.match(/^(https?:\/\/|www\.)/i)
+ );
+
+ // If we found an autolink, remove it by replacing it with its text-only child
+ if (isAutolink) {
+ elParent.children.splice(elIndex, 1, el.children[0]);
+ }
+ });
+ }
+
+ // Replace the current node with its children
// wrapped by raw opening and closing tags
const openingTag = {
type: 'raw',
- value: `\n<${child.name}${attrs}>`,
+ value: `\n<${node.name}${attrs}>`,
};
const closingTag = {
type: 'raw',
- value: `</${child.name}>\n`,
+ value: `</${node.name}>\n`,
};
- parent.children.splice(index, 1, openingTag, ...child.children, closingTag);
+ parent.children.splice(index, 1, openingTag, ...node.children, closingTag);
});
};
}