fumadocs-core
Version:
The React.js library for building a documentation website
143 lines (140 loc) • 3.32 kB
JavaScript
import { toEstree } from "hast-util-to-estree";
//#region src/mdx-plugins/hast-utils.ts
/**
* Visit a node with filtered tag names
*/
function visit(node, tagNames, handler) {
if (node.type === "element" && tagNames.includes(node.tagName)) {
if (handler(node) === "skip") return;
}
if ("children" in node) node.children.forEach((n) => {
visit(n, tagNames, handler);
});
}
//#endregion
//#region src/mdx-plugins/rehype-toc.ts
const TocOnlyTag = "[toc]";
const NoTocTag = "[!toc]";
function rehypeToc({ exportToc = true } = {}) {
return (tree) => {
const output = [];
visit(tree, [
"h1",
"h2",
"h3",
"h4",
"h5",
"h6"
], (element) => {
const id = element.properties.id;
if (typeof id !== "string") return "skip";
let isTocOnly = false;
const last = element.children.at(-1);
if (last?.type === "text" && last.value.endsWith(TocOnlyTag)) {
isTocOnly = true;
last.value = last.value.substring(0, last.value.length - 5).trimEnd();
} else if (last?.type === "text" && last.value.endsWith(NoTocTag)) {
last.value = last.value.substring(0, last.value.length - 6).trimEnd();
return "skip";
}
const estree = toEstree(element, {
elementAttributeNameCase: "react",
stylePropertyNameCase: "dom"
});
if (estree.body[0].type === "ExpressionStatement") output.push({
title: estree.body[0].expression,
depth: Number(element.tagName.slice(1)),
url: `#${id}`
});
if (isTocOnly) Object.assign(element, {
type: "comment",
value: ""
});
return "skip";
});
const declaration = {
type: "VariableDeclaration",
kind: "const",
declarations: [{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: "toc"
},
init: {
type: "ArrayExpression",
elements: output.map((item) => ({
type: "ObjectExpression",
properties: [
{
type: "Property",
method: false,
shorthand: false,
computed: false,
key: {
type: "Identifier",
name: "depth"
},
value: {
type: "Literal",
value: item.depth
},
kind: "init"
},
{
type: "Property",
method: false,
shorthand: false,
computed: false,
key: {
type: "Identifier",
name: "url"
},
value: {
type: "Literal",
value: item.url
},
kind: "init"
},
{
type: "Property",
method: false,
shorthand: false,
computed: false,
key: {
type: "Identifier",
name: "title"
},
value: {
type: "JSXFragment",
openingFragment: { type: "JSXOpeningFragment" },
closingFragment: { type: "JSXClosingFragment" },
children: item.title.children
},
kind: "init"
}
]
}))
}
}]
};
tree.children.push({
type: "mdxjsEsm",
value: "",
data: { estree: {
type: "Program",
body: [exportToc ? {
type: "ExportNamedDeclaration",
declaration,
attributes: [],
specifiers: []
} : declaration],
sourceType: "module",
comments: []
} }
});
};
}
//#endregion
export { rehypeToc as t };
//# sourceMappingURL=rehype-toc-DVwJcwvA.js.map