Skip to content

Commit 39aef99

Browse files
committed
refactor with iso behavior
1 parent 1d4d17d commit 39aef99

File tree

2 files changed

+75
-76
lines changed

2 files changed

+75
-76
lines changed

packages/docusaurus-mdx-loader/src/remark/toc/utils.ts

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,21 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import {toValue} from '../utils';
9-
import type {Node} from 'unist';
10-
import type {MdxjsEsm} from 'mdast-util-mdx';
8+
import escapeHtml from 'escape-html';
9+
import type {Node, Parent} from 'unist';
10+
import type {
11+
MdxjsEsm,
12+
MdxJsxAttribute,
13+
MdxJsxTextElement,
14+
} from 'mdast-util-mdx';
1115
import type {TOCHeading, TOCItem, TOCItems, TOCSlice} from './types';
1216
import type {
1317
Program,
1418
SpreadElement,
1519
ImportDeclaration,
1620
ImportSpecifier,
1721
} from 'estree';
22+
import type {Heading, PhrasingContent} from 'mdast';
1823

1924
export function getImportDeclarations(program: Program): ImportDeclaration[] {
2025
return program.body.filter(
@@ -118,7 +123,7 @@ export async function createTOCExportNodeAST({
118123
const {toString} = await import('mdast-util-to-string');
119124
const {valueToEstree} = await import('estree-util-value-to-estree');
120125
const value: TOCItem = {
121-
value: toValue(heading, toString),
126+
value: toHeadingHTMLValue(heading, toString),
122127
id: heading.data!.id!,
123128
level: heading.depth,
124129
};
@@ -172,3 +177,67 @@ export async function createTOCExportNodeAST({
172177
},
173178
};
174179
}
180+
181+
function stringifyChildren(
182+
node: Parent,
183+
toString: (param: unknown) => string, // TODO weird but works
184+
): string {
185+
return (node.children as PhrasingContent[])
186+
.map((item) => toHeadingHTMLValue(item, toString))
187+
.join('');
188+
}
189+
190+
// TODO This is really a workaround, and not super reliable
191+
// For now we only support serializing tagName, className and content
192+
// Can we implement the TOC with real JSX nodes instead of html strings later?
193+
function mdxJsxTextElementToHtml(
194+
element: MdxJsxTextElement,
195+
toString: (param: unknown) => string, // TODO weird but works
196+
): string {
197+
const tag = element.name;
198+
199+
const attributes = element.attributes.filter(
200+
(child): child is MdxJsxAttribute => child.type === 'mdxJsxAttribute',
201+
);
202+
203+
const classAttribute =
204+
attributes.find((attr) => attr.name === 'className') ??
205+
attributes.find((attr) => attr.name === 'class');
206+
207+
const classAttributeString = classAttribute
208+
? `class="${escapeHtml(String(classAttribute.value))}"`
209+
: ``;
210+
211+
const allAttributes = classAttributeString ? ` ${classAttributeString}` : '';
212+
213+
const content = stringifyChildren(element, toString);
214+
215+
return `<${tag}${allAttributes}>${content}</${tag}>`;
216+
}
217+
218+
export function toHeadingHTMLValue(
219+
node: PhrasingContent | Heading | MdxJsxTextElement,
220+
toString: (param: unknown) => string, // TODO weird but works
221+
): string {
222+
switch (node.type) {
223+
case 'mdxJsxTextElement': {
224+
return mdxJsxTextElementToHtml(node as MdxJsxTextElement, toString);
225+
}
226+
case 'text':
227+
return escapeHtml(node.value);
228+
case 'heading':
229+
return stringifyChildren(node, toString);
230+
case 'inlineCode':
231+
return `<code>${escapeHtml(node.value)}</code>`;
232+
case 'emphasis':
233+
return `<em>${stringifyChildren(node, toString)}</em>`;
234+
case 'strong':
235+
return `<strong>${stringifyChildren(node, toString)}</strong>`;
236+
case 'delete':
237+
return `<del>${stringifyChildren(node, toString)}</del>`;
238+
case 'link':
239+
return stringifyChildren(node, toString);
240+
default:
241+
return toString(node);
242+
}
243+
}

packages/docusaurus-mdx-loader/src/remark/utils/index.ts

Lines changed: 2 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,8 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import escapeHtml from 'escape-html';
9-
import type {Parent, Node} from 'unist';
10-
import type {PhrasingContent, Heading} from 'mdast';
11-
import type {
12-
MdxJsxAttribute,
13-
MdxJsxAttributeValueExpression,
14-
MdxJsxTextElement,
15-
} from 'mdast-util-mdx';
8+
import type {Node} from 'unist';
9+
import type {MdxJsxAttributeValueExpression} from 'mdast-util-mdx';
1610

1711
/**
1812
* Util to transform one node type to another node type
@@ -35,70 +29,6 @@ export function transformNode<NewNode extends Node>(
3529
return node as NewNode;
3630
}
3731

38-
export function stringifyContent(
39-
node: Parent,
40-
toString: (param: unknown) => string, // TODO weird but works
41-
): string {
42-
return (node.children as PhrasingContent[])
43-
.map((item) => toValue(item, toString))
44-
.join('');
45-
}
46-
47-
// TODO This is really a workaround, and not super reliable
48-
// For now we only support serializing tagName, className and content
49-
// Can we implement the TOC with real JSX nodes instead of html strings later?
50-
function mdxJsxTextElementToHtml(
51-
element: MdxJsxTextElement,
52-
toString: (param: unknown) => string, // TODO weird but works
53-
): string {
54-
const tag = element.name;
55-
56-
const attributes = element.attributes.filter(
57-
(child): child is MdxJsxAttribute => child.type === 'mdxJsxAttribute',
58-
);
59-
60-
const classAttribute =
61-
attributes.find((attr) => attr.name === 'className') ??
62-
attributes.find((attr) => attr.name === 'class');
63-
64-
const classAttributeString = classAttribute
65-
? `class="${escapeHtml(String(classAttribute.value))}"`
66-
: ``;
67-
68-
const allAttributes = classAttributeString ? ` ${classAttributeString}` : '';
69-
70-
const content = stringifyContent(element, toString);
71-
72-
return `<${tag}${allAttributes}>${content}</${tag}>`;
73-
}
74-
75-
export function toValue(
76-
node: PhrasingContent | Heading | MdxJsxTextElement,
77-
toString: (param: unknown) => string, // TODO weird but works
78-
): string {
79-
switch (node.type) {
80-
case 'mdxJsxTextElement': {
81-
return mdxJsxTextElementToHtml(node as MdxJsxTextElement, toString);
82-
}
83-
case 'text':
84-
return escapeHtml(node.value);
85-
case 'heading':
86-
return stringifyContent(node, toString);
87-
case 'inlineCode':
88-
return `<code>${escapeHtml(node.value)}</code>`;
89-
case 'emphasis':
90-
return `<em>${stringifyContent(node, toString)}</em>`;
91-
case 'strong':
92-
return `<strong>${stringifyContent(node, toString)}</strong>`;
93-
case 'delete':
94-
return `<del>${stringifyContent(node, toString)}</del>`;
95-
case 'link':
96-
return stringifyContent(node, toString);
97-
default:
98-
return toString(node);
99-
}
100-
}
101-
10232
export function assetRequireAttributeValue(
10333
requireString: string,
10434
hash: string,

0 commit comments

Comments
 (0)