UNPKG

fumadocs-core

Version:

The React.js library for building a documentation website

184 lines (182 loc) 4.84 kB
import { generateCodeBlockTabs, parseCodeBlockAttributes } from "./codeblock-utils.js"; import { visit } from "unist-util-visit"; //#region src/mdx-plugins/remark-code-tab.ts const Types = { CodeBlockTabs: { convert(processor, nodes, withMdx = false, withParent = true) { const tabs = Array.from(processTabValue(nodes).entries()); const node = generateCodeBlockTabs({ defaultValue: tabs[0][0], triggers: tabs.map(([name]) => ({ value: name, children: [withMdx ? mdxToAst(processor, name) : { type: "text", value: name }] })), tabs: tabs.map(([name, codes]) => ({ value: name, children: codes })) }); if (!withParent) return createFragment(node.children); return node; } }, Tabs: { convert(processor, nodes, withMdx = false, withParent = true) { const tabs = Array.from(processTabValue(nodes).entries()); if (!withMdx) { const children$1 = tabs.map(([name, codes]) => { return { type: "mdxJsxFlowElement", name: "Tab", attributes: [{ type: "mdxJsxAttribute", name: "value", value: name }], children: codes }; }); if (!withParent) return createFragment(children$1); return { type: "mdxJsxFlowElement", name: "Tabs", attributes: [{ type: "mdxJsxAttribute", name: "items", value: { type: "mdxJsxAttributeValueExpression", value: tabs.map(([name]) => name).join(", "), data: { estree: { type: "Program", sourceType: "module", comments: [], body: [{ type: "ExpressionStatement", expression: { type: "ArrayExpression", elements: tabs.map(([name]) => ({ type: "Literal", value: name })) } }] } } } }], children: children$1 }; } const children = [{ type: "mdxJsxFlowElement", name: "TabsList", attributes: [], children: tabs.map(([name]) => ({ type: "mdxJsxFlowElement", name: "TabsTrigger", attributes: [{ type: "mdxJsxAttribute", name: "value", value: name }], children: [mdxToAst(processor, name)] })) }, ...tabs.map(([name, codes]) => ({ type: "mdxJsxFlowElement", name: "TabsContent", attributes: [{ type: "mdxJsxAttribute", name: "value", value: name }], children: codes }))]; if (!withParent) return createFragment(children); return { type: "mdxJsxFlowElement", name: "Tabs", attributes: [{ type: "mdxJsxAttribute", name: "defaultValue", value: tabs[0][0] }], children }; } } }; function remarkCodeTab(options = {}) { const { parseMdx = false, Tabs = "CodeBlockTabs" } = options; return (tree) => { const ignored = /* @__PURE__ */ new WeakSet(); visit(tree, (node) => { if (!("children" in node) || ignored.has(node)) return "skip"; let localTabs = Tabs; let localParseMdx = parseMdx; let withParent = true; if (node.type === "mdxJsxFlowElement" && node.name && node.name in Types) { withParent = false; localTabs = node.name; if (node.name === "Tabs" && localParseMdx) localParseMdx = node.attributes.every((attribute) => attribute.type !== "mdxJsxAttribute" || attribute.name !== "items"); } let start = -1; let end = 0; const close = () => { if (start === -1 || start === end) return; const replacement = Types[localTabs].convert(this, node.children.slice(start, end), localParseMdx, withParent); ignored.add(replacement); node.children.splice(start, end - start, replacement); end = start; start = -1; }; for (; end < node.children.length; end++) { const child = node.children[end]; if (child.type !== "code" || !child.meta) { close(); continue; } const meta = parseCodeBlockAttributes(child.meta, ["tab"]); if (!meta.attributes.tab) { close(); continue; } if (start === -1) start = end; child.meta = meta.rest; child.data ??= {}; child.data.tab = meta.attributes.tab; } close(); }); }; } function processTabValue(nodes) { const out = /* @__PURE__ */ new Map(); for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; const name = node.data?.tab ?? `Tab ${i + 1}`; const li = out.get(name) ?? []; li.push(node); out.set(name, li); } return out; } /** * MDX tab name to tab trigger node children */ function mdxToAst(processor, name) { const node = processor.parse(name); if (node.type === "root") node.children = node.children.flatMap((child) => { if (child.type === "paragraph") return child.children; return child; }); return node; } function createFragment(children) { return { type: "mdxJsxFlowElement", name: null, attributes: [], children }; } //#endregion export { remarkCodeTab }; //# sourceMappingURL=remark-code-tab.js.map