diff --git a/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/__fixtures__/non-text-content.md b/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/__fixtures__/non-text-content.md
index 2ea62a2bbaf6..94814d8d9be8 100644
--- a/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/__fixtures__/non-text-content.md
+++ b/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/__fixtures__/non-text-content.md
@@ -7,3 +7,5 @@
## HTML
## `inline.code()`
+
+## some styled heading test
diff --git a/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/__snapshots__/index.test.ts.snap
index 8af155e2c96d..5cad7ef21337 100644
--- a/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/__snapshots__/index.test.ts.snap
+++ b/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/__snapshots__/index.test.ts.snap
@@ -171,6 +171,11 @@ exports[`toc remark plugin works on non text phrasing content 1`] = `
value: 'inline.code()
',
id: 'inlinecode',
level: 2
+ },
+ {
+ value: 'some styled heading test',
+ id: 'some-styled-heading--test',
+ level: 2
}
]
@@ -183,6 +188,8 @@ exports[`toc remark plugin works on non text phrasing content 1`] = `
## HTML
## \`inline.code()\`
+
+## some styled heading test
"
`;
diff --git a/packages/docusaurus-mdx-loader/src/remark/utils/index.ts b/packages/docusaurus-mdx-loader/src/remark/utils/index.ts
index da3c40209997..46e959176239 100644
--- a/packages/docusaurus-mdx-loader/src/remark/utils/index.ts
+++ b/packages/docusaurus-mdx-loader/src/remark/utils/index.ts
@@ -8,26 +8,57 @@
import escapeHtml from 'escape-html';
import type {Parent} from 'unist';
import type {PhrasingContent, Heading} from 'mdast';
-// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
-import type {MdxJsxAttributeValueExpression} from 'mdast-util-mdx';
+import type {
+ MdxJsxAttribute,
+ MdxJsxAttributeValueExpression,
+ MdxJsxTextElement,
+ // @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
+} from 'mdast-util-mdx';
export function stringifyContent(
node: Parent,
- toString: (param: unknown) => string, // TODO weird but works): string {
+ toString: (param: unknown) => string, // TODO weird but works
): string {
return (node.children as PhrasingContent[])
.map((item) => toValue(item, toString))
.join('');
}
+// TODO This is really a workaround, and not super reliable
+// For now we only support serializing tagName, className and content
+// Can we implement the TOC with real JSX nodes instead of html strings later?
+function mdxJsxTextElementToHtml(
+ element: MdxJsxTextElement,
+ toString: (param: unknown) => string, // TODO weird but works
+): string {
+ const tag = element.name;
+
+ const attributes = element.attributes.filter(
+ (child): child is MdxJsxAttribute => child.type === 'mdxJsxAttribute',
+ );
+
+ const classAttribute =
+ attributes.find((attr) => attr.name === 'className') ??
+ attributes.find((attr) => attr.name === 'class');
+
+ const classAttributeString = classAttribute
+ ? `class="${escapeHtml(String(classAttribute.value))}"`
+ : ``;
+
+ const allAttributes = classAttributeString ? ` ${classAttributeString}` : '';
+
+ const content = stringifyContent(element, toString);
+
+ return `<${tag}${allAttributes}>${content}${tag}>`;
+}
+
export function toValue(
node: PhrasingContent | Heading,
toString: (param: unknown) => string, // TODO weird but works
): string {
switch (node.type) {
case 'mdxJsxTextElement': {
- const tag = node.name;
- return `<${tag}>${stringifyContent(node, toString)}${tag}>`;
+ return mdxJsxTextElementToHtml(node as MdxJsxTextElement, toString);
}
case 'text':
return escapeHtml(node.value);