Skip to content

Commit

Permalink
fix(mdx-loader): improve mdxJsxTextElementToHtml (#9262)
Browse files Browse the repository at this point in the history
  • Loading branch information
slorber authored Aug 25, 2023
1 parent b3c8f5c commit 9868bab
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 5 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,11 @@ exports[`toc remark plugin works on non text phrasing content 1`] = `
value: '<code>inline.code()</code>',
id: 'inlinecode',
level: 2
},
{
value: 'some <span class="some-class">styled</span> <strong>heading</strong> <span class="myClassName &lt;&gt; weird char"></span> test',
id: 'some-styled-heading--test',
level: 2
}
]
Expand All @@ -183,6 +188,8 @@ exports[`toc remark plugin works on non text phrasing content 1`] = `
## <i>HTML</i>
## \`inline.code()\`
## some <span className="some-class" style={{border: "solid"}}>styled</span> <strong>heading</strong> <span class="myClass" className="myClassName <> weird char" data-random-attr="456" /> test
"
`;

Expand Down
41 changes: 36 additions & 5 deletions packages/docusaurus-mdx-loader/src/remark/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 9868bab

Please sign in to comment.