@docubook/core 2.0.0-alpha.2 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compile.d.ts +9 -0
- package/dist/extract.d.ts +22 -0
- package/dist/index.d.ts +10 -122
- package/dist/index.js +267 -444
- package/dist/index.js.map +1 -1
- package/dist/mdx-compiler/format-mdx-error.d.ts +4 -0
- package/dist/mdx-compiler/index.d.ts +15 -0
- package/dist/mdx-compiler/plugins/remove-dangerous-javascript-expressions.d.ts +2 -0
- package/dist/mdx-compiler/plugins/remove-imports-exports.d.ts +3 -0
- package/dist/mdx-compiler/plugins/remove-javascript-expressions.d.ts +6 -0
- package/dist/mdx-compiler/serialize.d.ts +5 -11
- package/dist/mdx-compiler/serialize.js +2 -7
- package/dist/mdx-compiler/types.d.ts +3 -0
- package/dist/plugins/handleCodeExpandable.d.ts +3 -0
- package/dist/plugins/handleCodeTitles.d.ts +2 -0
- package/dist/plugins/rehypeMermaid.d.ts +10 -0
- package/dist/plugins/remarkDirectiveToMdx.d.ts +23 -0
- package/dist/serialize-DEuXE4Xm.js +98 -0
- package/dist/serialize-DEuXE4Xm.js.map +1 -0
- package/dist/types.d.ts +5 -0
- package/dist/utils.d.ts +9 -12
- package/dist/utils.js +35 -16
- package/dist/utils.js.map +1 -1
- package/package.json +4 -4
- package/dist/chunk-HZJLRYAI.js +0 -45
- package/dist/chunk-HZJLRYAI.js.map +0 -1
- package/dist/chunk-J7CN2VUH.js +0 -188
- package/dist/chunk-J7CN2VUH.js.map +0 -1
- package/dist/mdx-compiler/serialize.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/compile.ts","../src/plugins/handleCodeTitles.ts","../src/plugins/handleCodeExpandable.ts","../src/plugins/rehypeMermaid.ts","../src/plugins/remarkDirectiveToMdx.ts","../src/mdx-compiler/index.ts","../src/extract.ts"],"sourcesContent":["import { serialize } from \"./mdx-compiler/serialize.js\";\nimport type { Node } from \"unist\";\nimport { visit } from \"unist-util-visit\";\nimport remarkGfm from \"remark-gfm\";\nimport rehypePrism from \"rehype-prism-plus\";\nimport rehypeAutolinkHeadings from \"rehype-autolink-headings\";\nimport rehypeSlug from \"rehype-slug\";\nimport rehypeCodeTitles from \"rehype-code-titles\";\nimport { handleCodeTitles } from \"./plugins/handleCodeTitles\";\nimport { handleCodeExpandableRemark, handleCodeExpandable } from \"./plugins/handleCodeExpandable\";\nimport { rehypeMermaid } from \"./plugins/rehypeMermaid\";\nimport { remarkDirectiveToMdx } from \"./plugins/remarkDirectiveToMdx\";\nimport remarkDirective from \"remark-directive\";\nimport type { ElementNode } from \"./utils\";\nimport type { Pluggable } from \"unified\";\n\n// Re-export serialize for non-RSC usage\nexport { serialize };\n\n// Re-export MDXRemote for client-side hydration\nexport { MDXRemote } from \"./mdx-compiler/index.js\";\n\ninterface TextNode extends Node {\n type: \"text\";\n value: string;\n}\n\nexport const preProcess = () => (tree: Node) => {\n visit(tree, (node: Node) => {\n const element = node as ElementNode;\n if (element?.type === \"element\" && element?.tagName === \"pre\" && element.children) {\n const [codeEl] = element.children as ElementNode[];\n if (codeEl.tagName !== \"code\" || !codeEl.children?.[0]) return;\n\n const className = codeEl.properties?.className;\n const classList = Array.isArray(className)\n ? className\n : typeof className === \"string\"\n ? className.split(\" \").filter(Boolean)\n : [];\n const languageClass = classList.find((item: string) => item.startsWith(\"language-\"));\n if (languageClass) {\n element.language = languageClass.replace(\"language-\", \"\").split(\":\")[0];\n }\n\n const textNode = codeEl.children[0] as TextNode;\n if (textNode.type === \"text\" && textNode.value) {\n element.raw = textNode.value;\n }\n }\n });\n\n return tree;\n};\n\nexport const postProcess = () => (tree: Node) => {\n visit(tree, \"element\", (node: Node) => {\n const element = node as ElementNode;\n if (element?.type === \"element\" && element?.tagName === \"pre\") {\n if (element.properties && element.raw) {\n element.properties.raw = element.raw;\n }\n if (element.properties && element.language && !element.properties[\"data-language\"]) {\n element.properties[\"data-language\"] = element.language;\n }\n if (element.properties && element.codeTitle && !element.properties[\"data-title\"]) {\n element.properties[\"data-title\"] = element.codeTitle;\n }\n }\n });\n\n return tree;\n};\n\nexport function createDefaultRehypePlugins(): Pluggable[] {\n return [\n preProcess,\n rehypeMermaid, // Transform ```mermaid before code transforms\n rehypeCodeTitles,\n handleCodeTitles,\n handleCodeExpandable, // Copy expandable metadata from <code> to <pre> before prism transforms nodes.\n rehypePrism,\n handleCodeExpandable, // Re-apply expandable attrs after prism tokenization.\n rehypeSlug,\n rehypeAutolinkHeadings,\n postProcess,\n ];\n}\n\nexport function createDefaultRemarkPlugins(): Pluggable[] {\n return [remarkGfm, handleCodeExpandableRemark, remarkDirective, remarkDirectiveToMdx];\n}\n","import type { Node, Parent } from \"unist\";\nimport { visit } from \"unist-util-visit\";\nimport type { ElementNode } from \"../utils\";\n\ninterface TextNode extends Node {\n type: \"text\";\n value: string;\n}\n\nexport const handleCodeTitles = () => (tree: Node) => {\n const toRemove: { parent: Parent; index: number }[] = [];\n\n visit(tree, \"element\", (node: ElementNode, index: number | null, parent: Parent | null) => {\n if (!parent || index === null || node.tagName !== \"div\") {\n return;\n }\n\n const isTitleDiv = node.properties?.className?.includes(\"rehype-code-title\");\n if (!isTitleDiv) {\n return;\n }\n\n let nextElement: ElementNode | null = null;\n for (let i = index + 1; i < parent.children.length; i++) {\n const sibling = parent.children[i];\n if (sibling.type === \"element\") {\n nextElement = sibling as ElementNode;\n break;\n }\n }\n\n if (nextElement?.tagName === \"pre\") {\n const titleNode = node.children?.[0] as TextNode;\n if (titleNode?.type === \"text\") {\n if (!nextElement.properties) {\n nextElement.properties = {};\n }\n nextElement.properties[\"data-title\"] = titleNode.value;\n nextElement.codeTitle = titleNode.value;\n toRemove.push({ parent, index });\n }\n }\n });\n\n // Remove title divs in reverse order to preserve indices\n for (let i = toRemove.length - 1; i >= 0; i--) {\n const { parent, index } = toRemove[i];\n parent.children.splice(index, 1);\n }\n};\n","import type { Node } from \"unist\";\nimport { visit } from \"unist-util-visit\";\nimport type { ElementNode } from \"../utils\";\n\n/**\n * Escape metadata values that are interpolated into MDX-compiled JavaScript.\n *\n * References:\n * - HTML spec (script data state): escape `</` as `\\u003C/` to prevent premature\n * `</script>` closing when the compiled JS is embedded as JSON in a <script> tag.\n * - Bun.escapeHTML(): escapes `< > \" ' &` for HTML context; for JS/JSON context\n * we use `\\uXXXX` JSON Unicode escapes instead so the value survives round-trip\n * through JSON.parse on the client side.\n * - React: JSX auto-escapes attribute values via `{expression}`, so values set\n * as HAST properties (data-language, data-title) are HTML-safe at render time.\n */\nfunction escapeMeta(s: string): string {\n let out = \"\";\n for (let i = 0; i < s.length; i++) {\n const ch = s[i];\n\n // HTML spec: prevent </script> in script/JSON context\n if (ch === \"<\" && s[i + 1] === \"/\") {\n out += \"\\\\u003C/\";\n i++;\n continue;\n }\n\n // JS string: escape template literal & string special chars\n if (ch === \"`\" || ch === \"$\" || ch === \"{\" || ch === \"}\" || ch === '\"' || ch === \"\\\\\") {\n out += `\\\\${ch}`;\n continue;\n }\n\n out += ch;\n }\n return out;\n}\n\ninterface CodeNode extends Node {\n type: \"code\";\n lang?: string;\n meta?: string;\n value: string;\n data?: {\n meta?: string;\n hProperties?: Record<string, unknown>;\n };\n}\n\nfunction countCodeLines(raw: string): number {\n let normalized = raw.replace(/\\r\\n/g, \"\\n\");\n if (normalized.startsWith(\"\\n\")) normalized = normalized.slice(1);\n if (normalized.endsWith(\"\\n\")) normalized = normalized.slice(0, -1);\n\n if (normalized.length === 0) return 0;\n return normalized.split(\"\\n\").length;\n}\n\nexport const handleCodeExpandableRemark = () => (tree: Node) => {\n visit(tree, \"code\", (node: CodeNode) => {\n if (!node.meta) return;\n\n const isExpandable = node.meta.includes(\"Expandable\");\n const [languagePart, titlePart] = (node.lang ?? \"\").split(\":\");\n const normalizedLanguage = languagePart?.trim();\n const normalizedTitle = titlePart?.trim();\n\n if (!isExpandable) return;\n\n const lineCount = countCodeLines(node.value);\n\n if (!node.data) {\n node.data = {};\n }\n if (!node.data.hProperties) {\n node.data.hProperties = {};\n }\n\n node.data.hProperties[\"data-expandable\"] = \"true\";\n node.data.hProperties[\"data-expandable-lines\"] = lineCount.toString();\n\n if (normalizedLanguage) {\n node.data.hProperties[\"data-language\"] = normalizedLanguage;\n }\n if (normalizedTitle) {\n node.data.hProperties[\"data-title\"] = normalizedTitle;\n }\n\n const currentClassName = node.data.hProperties.className;\n const classList = Array.isArray(currentClassName)\n ? currentClassName\n : typeof currentClassName === \"string\"\n ? currentClassName.split(\" \").filter(Boolean)\n : [];\n\n if (!classList.includes(\"mdx-expandable-meta\")) {\n classList.push(\"mdx-expandable-meta\");\n }\n\n node.data.hProperties.className = classList;\n\n if (normalizedLanguage && !node.meta.includes(\"dbLang(\")) {\n node.meta = `${node.meta} dbLang(${escapeMeta(normalizedLanguage)})`.trim();\n }\n if (normalizedTitle && !node.meta.includes(\"dbTitle(\")) {\n node.meta = `${node.meta} dbTitle(${escapeMeta(normalizedTitle)})`.trim();\n }\n });\n};\n\nexport const handleCodeExpandable = () => (tree: Node) => {\n visit(tree, \"element\", (node: ElementNode) => {\n if (node.tagName !== \"pre\") return;\n\n const codeElement = node.children?.find((child) => {\n const element = child as ElementNode;\n return element.type === \"element\" && element.tagName === \"code\";\n }) as ElementNode | undefined;\n\n const codeClassName = codeElement?.properties?.className;\n const codeClassList = Array.isArray(codeClassName)\n ? codeClassName\n : typeof codeClassName === \"string\"\n ? codeClassName.split(\" \").filter(Boolean)\n : [];\n\n const codeMeta =\n codeElement?.data &&\n typeof codeElement.data === \"object\" &&\n typeof codeElement.data[\"meta\"] === \"string\"\n ? (codeElement.data[\"meta\"] as string)\n : undefined;\n\n const languageFromMeta = codeMeta?.match(/dbLang\\(([^)]+)\\)/)?.[1];\n const titleFromMeta = codeMeta?.match(/dbTitle\\(([^)]+)\\)/)?.[1];\n\n const languageFromProps =\n typeof codeElement?.properties?.[\"data-language\"] === \"string\"\n ? (codeElement.properties[\"data-language\"] as string)\n : undefined;\n const titleFromProps =\n typeof codeElement?.properties?.[\"data-title\"] === \"string\"\n ? (codeElement.properties[\"data-title\"] as string)\n : undefined;\n\n const languageFromCodeClass = codeClassList\n .find((item) => item.startsWith(\"language-\"))\n ?.replace(\"language-\", \"\");\n\n const existingPreLanguage =\n typeof node.properties?.[\"data-language\"] === \"string\"\n ? (node.properties[\"data-language\"] as string)\n : undefined;\n const existingPreTitle =\n typeof node.properties?.[\"data-title\"] === \"string\"\n ? (node.properties[\"data-title\"] as string)\n : undefined;\n\n const isExpandable =\n codeElement?.properties?.[\"data-expandable\"] === \"true\" ||\n codeClassList.includes(\"mdx-expandable-meta\") ||\n codeMeta?.includes(\"Expandable\") === true;\n\n const expandableLines = codeElement?.properties?.[\"data-expandable-lines\"];\n if (!isExpandable) return;\n\n if (!node.properties) {\n node.properties = {};\n }\n\n node.properties[\"data-expandable\"] = \"true\";\n if (typeof expandableLines === \"string\" || typeof expandableLines === \"number\") {\n node.properties[\"data-expandable-lines\"] = expandableLines.toString();\n } else if (node.raw) {\n node.properties[\"data-expandable-lines\"] = countCodeLines(node.raw).toString();\n }\n\n const resolvedLanguage =\n languageFromProps ||\n languageFromMeta ||\n languageFromCodeClass ||\n existingPreLanguage ||\n node.language;\n const resolvedTitle = titleFromProps || titleFromMeta || existingPreTitle || node.codeTitle;\n\n if (resolvedLanguage) {\n node.properties[\"data-language\"] = resolvedLanguage;\n }\n if (resolvedTitle) {\n node.properties[\"data-title\"] = resolvedTitle;\n }\n\n const className = node.properties.className;\n if (!className) {\n node.properties.className = [];\n }\n\n if (Array.isArray(node.properties.className)) {\n if (!node.properties.className.includes(\"mdx-expandable-code\")) {\n node.properties.className.push(\"mdx-expandable-code\");\n }\n } else if (typeof className === \"string\") {\n const hasMarker = className.split(\" \").includes(\"mdx-expandable-code\");\n if (!hasMarker) {\n node.properties.className = `${className} mdx-expandable-code`.trim().split(\" \");\n }\n } else {\n node.properties.className = [\"mdx-expandable-code\"];\n }\n\n if (codeElement?.properties) {\n const cleanedCodeClassList = codeClassList.filter((item) => item !== \"mdx-expandable-meta\");\n codeElement.properties.className = cleanedCodeClassList;\n }\n });\n};\n","import type { Node, Parent } from \"unist\";\nimport { visit } from \"unist-util-visit\";\nimport type { ElementNode } from \"../utils\";\n\ninterface TextNode extends Node {\n type: \"text\";\n value: string;\n}\n\n/**\n * Rehype plugin that transforms `<pre><code class=\"language-mermaid\">` fenced\n * blocks into `<Mermaid chart=\"...\">` elements.\n *\n * This allows Mermaid diagram definitions to be authored via standard fenced\n * code blocks (````mermaid) which avoids JSX parsing collisions with\n * Mermaid's `{...}` (decision nodes) and `[...]` (label nodes) syntax.\n */\nexport const rehypeMermaid = () => (tree: Node) => {\n visit(tree, \"element\", (node: ElementNode, index: number | null, parent: Parent | null) => {\n if (!parent || index === null || node.tagName !== \"pre\") return;\n\n const codeEl = node.children?.find(\n (child) =>\n (child as ElementNode).type === \"element\" && (child as ElementNode).tagName === \"code\"\n ) as ElementNode | undefined;\n\n if (!codeEl) return;\n\n const classList = Array.isArray(codeEl.properties?.className)\n ? (codeEl.properties.className as string[])\n : typeof codeEl.properties?.className === \"string\"\n ? (codeEl.properties.className as string).split(\" \").filter(Boolean)\n : [];\n\n if (!classList.includes(\"language-mermaid\")) return;\n\n const textNode = codeEl.children?.find((child) => (child as TextNode).type === \"text\") as\n TextNode | undefined;\n\n const chart = textNode?.value ?? \"\";\n\n parent.children[index] = {\n type: \"element\",\n tagName: \"Mermaid\",\n properties: { chart },\n children: [],\n } as unknown as ElementNode;\n });\n};\n","import type { Node } from \"unist\";\n\n/**\n * Remark plugin: convert markdown directives into MDX component elements.\n *\n * Contract (docubook):\n * - `:::name{attrs} … :::` — container: EVERY component that holds content\n * (tabs, tab, accordions, accordion, steps, step, cards, card, files,\n * folder, note + variants). Children are the block between the opening\n * `:::` and closing `:::` — bounded by micromark's container grammar, so\n * a component can never trap siblings that follow it.\n * - `::name{attrs}` — self-closing leaf (no children): file, youtube,\n * mermaid.\n * - `:tooltip[label]{tip=\"…\"}` — the ONE inline (single-colon) directive.\n * Every other text directive is rebuilt as literal text\n * (`localhost:3000` stays intact). `::tooltip` (block leaf) is removed\n * in v2 — tooltips are inline only.\n *\n * Names are PascalCased to match the components map (`file-tree` → `FileTree`).\n * Bare attributes (`{horizontal}`) become boolean props (JSX bare attribute).\n * Callout variants (`:::tip`, `:::info`, …) map to their own registry entries\n * (`Tip`/`Info`/…) which wrap the `Callout` component with the type set.\n */\nexport function remarkDirectiveToMdx() {\n return (tree: Node) => {\n const root = tree as unknown as { children: Node[] };\n root.children = root.children.map(transform);\n return tree;\n };\n}\n\n/** Leaves that never hold children (self-closing). */\nconst PURE_LEAVES = new Set([\"youtube\"]);\n\ntype DirectiveNode = Node & {\n type: \"containerDirective\" | \"leafDirective\" | \"textDirective\";\n name: string;\n label?: string;\n attributes?: Record<string, string>;\n children?: Node[];\n};\n\nfunction isDirective(node: Node): node is DirectiveNode {\n return (\n node.type === \"containerDirective\" ||\n node.type === \"leafDirective\" ||\n node.type === \"textDirective\"\n );\n}\n\nfunction transform(node: Node): Node {\n if (!isDirective(node)) {\n const children = (node as unknown as { children?: Node[] }).children;\n if (Array.isArray(children)) {\n (node as unknown as { children: Node[] }).children = children.map(transform);\n }\n return node;\n }\n if (node.type === \"textDirective\") {\n // `:tooltip[label]{tip=\"…\"}` is the one inline component — it stays\n // inside the paragraph. Every other single-colon text directive is\n // rebuilt as literal text (`localhost:3000` stays intact).\n if (node.name === \"tooltip\") {\n return inlineTooltip(node);\n }\n return literalDirective(node);\n }\n // Block-form tooltips are gone in v2 — degrade to literal text so the\n // author sees the directive instead of a broken component.\n if (node.type === \"leafDirective\" && node.name === \"tooltip\") {\n return literalDirective(node);\n }\n // containerDirective → component with children; leafDirective → self-closing.\n const children =\n node.type === \"containerDirective\" && !PURE_LEAVES.has(node.name)\n ? (node.children ?? []).map(transform)\n : [];\n return directiveToElement(node, children);\n}\n\nfunction directiveToElement(directive: DirectiveNode, children: Node[]): Node {\n const name = pascalCase(directive.name);\n const attributes = Object.entries(directive.attributes ?? {}).map(([attrName, value]) => ({\n type: \"mdxJsxAttribute\",\n name: attrName,\n value: value === \"\" ? null : value,\n }));\n return {\n type: \"mdxJsxFlowElement\",\n name,\n attributes,\n children,\n } as Node;\n}\n\n/** Rebuild a text directive as literal text (single-colon is not a contract). */\nfunction literalDirective(directive: DirectiveNode): Node {\n const literal = \":\" + directive.name + (directive.label ? `[${directive.label}]` : \"\");\n const attrStr = Object.entries(directive.attributes ?? {})\n .map(([k, v]) => (v === \"\" ? k : `${k}=\"${v}\"`))\n .join(\" \");\n return { type: \"text\", value: literal + (attrStr ? `{${attrStr}}` : \"\") } as Node;\n}\n\n/**\n * Inline tooltip from a text directive: `:tooltip[label]{tip=\"…\"}`.\n * The label is the visible trigger (dotted underline); `tip` is the hover\n * bubble and defaults to the label, so `:tooltip[text]` alone already shows\n * a bubble. Emits an inline element so it stays inside the paragraph. The\n * bubble auto-positions (no `side` prop).\n */\nfunction inlineTooltip(directive: DirectiveNode): Node {\n const label = (directive.children ?? [])\n .map((child) => (child as { value?: string }).value ?? \"\")\n .join(\"\");\n const attrs = directive.attributes ?? {};\n const attributes = [\n { type: \"mdxJsxAttribute\", name: \"text\", value: attrs.text || label || \"?\" },\n { type: \"mdxJsxAttribute\", name: \"tip\", value: attrs.tip || label || \"\" },\n ];\n return { type: \"mdxJsxTextElement\", name: \"Tooltip\", attributes, children: [] } as Node;\n}\n\nfunction pascalCase(name: string): string {\n return name\n .split(\"-\")\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n}\n","// MPL-2.0 — derived from next-mdx-remote (IBM). See LICENSE-MPL-2.0.\nimport React, { useEffect, useState, useMemo } from \"react\";\nimport * as jsxRuntime from \"react/jsx-runtime\";\nimport * as jsxDevRuntime from \"react/jsx-dev-runtime\";\nimport * as mdx from \"@mdx-js/react\";\nimport type { MDXRemoteSerializeResult } from \"./types.js\";\n\n/** Props for the client-side `<MDXRemote>` (accepts pre-serialized result). */\nexport type MDXRemoteProps = MDXRemoteSerializeResult & {\n components?: Record<string, React.ComponentType<any>>;\n /** Defer hydration to an idle callback */\n lazy?: boolean;\n};\n\n/**\n * Client-side MDX renderer.\n *\n * Accepts a pre-compiled result from `serialize()` and renders it via\n * `MDXProvider` for custom component injection.\n */\nexport function MDXRemote({\n compiledSource,\n frontmatter,\n scope = {},\n components = {},\n lazy,\n}: MDXRemoteProps) {\n const [ready, setReady] = useState(!lazy || typeof window === \"undefined\");\n\n useEffect(() => {\n if (!lazy) return;\n const id = window.requestIdleCallback\n ? window.requestIdleCallback(() => setReady(true), { timeout: 500 })\n : setTimeout(() => setReady(true), 1);\n return () => {\n if (window.cancelIdleCallback) window.cancelIdleCallback(id as number);\n else clearTimeout(id as number);\n };\n }, [lazy]);\n\n const Content = useMemo(() => {\n // Non-RSC mode: compiled MDX expects `useMDXComponents` (\n // from @mdx-js/react) AND the JSX runtime.\n // In React 19, jsx/jsxs and jsxDEV live in separate modules,\n // so merge both to handle compiled output from any mode.\n const fullScope = {\n opts: { ...mdx, ...jsxRuntime, ...jsxDevRuntime },\n frontmatter,\n ...scope,\n };\n const keys = Object.keys(fullScope);\n const values = Object.values(fullScope);\n const fn = Reflect.construct(Function, keys.concat(`${compiledSource}`));\n return fn.apply(fn, values).default;\n }, [compiledSource, scope, frontmatter]);\n\n if (!ready) {\n return React.createElement(\"div\", {\n dangerouslySetInnerHTML: { __html: \"\" },\n suppressHydrationWarning: true,\n });\n }\n\n const content = React.createElement(\n mdx.MDXProvider,\n { components },\n React.createElement(Content, null)\n );\n\n return lazy ? React.createElement(\"div\", null, content) : content;\n}\n","import matter from \"@11ty/gray-matter\";\nimport type { ZodType } from \"zod\";\nimport type { TocItem } from \"./types\";\n\nconst FENCE_MARKER_REGEX = /^(````|```)(?!`)/;\nconst HEADING_REGEX = /^(#{2,4})\\s+(.+)$/;\n\nexport function sluggify(text: string): string {\n const normalized = text.normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\"); // Remove accents\n const slug = normalized.toLowerCase().replace(/\\s+/g, \"-\");\n return slug.replace(/[^a-z0-9-]/g, \"\");\n}\n\nexport function extractTocsFromRawMdx(rawMdx: string): TocItem[] {\n const extractedHeadings: TocItem[] = [];\n\n const lines = rawMdx.split(/\\r?\\n/);\n let inFence = false;\n let fenceLength = 0;\n\n for (const line of lines) {\n const trimmed = line.trimStart();\n\n const fenceMatch = FENCE_MARKER_REGEX.exec(trimmed);\n if (fenceMatch) {\n const marker = fenceMatch[1];\n\n if (!inFence) {\n inFence = true;\n fenceLength = marker.length;\n } else if (marker.length === fenceLength) {\n inFence = false;\n }\n\n continue;\n }\n\n if (inFence) {\n continue;\n }\n\n const headingMatch = HEADING_REGEX.exec(trimmed);\n if (headingMatch) {\n const headingLevel = headingMatch[1].length;\n const headingText = headingMatch[2].trim().replace(/\\s+#+\\s*$/, \"\");\n extractedHeadings.push({\n level: headingLevel,\n text: headingText,\n href: `#${sluggify(headingText)}`,\n });\n continue;\n }\n }\n\n return extractedHeadings;\n}\n\nexport function extractFrontmatter<Frontmatter>(content: string): Frontmatter {\n try {\n return matter(content).data as Frontmatter;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to extract frontmatter: ${reason}`, { cause: error });\n }\n}\n\n/**\n * Extract frontmatter and return both the parsed data and the content\n * with the frontmatter block stripped. Avoids a second parse during\n * compilation.\n *\n * Optionally validates the parsed frontmatter with a Zod schema.\n * YAML coerces unquoted values (e.g. `date: 2026-06-10` → Date, `3.5` → number),\n * so use `z.coerce.*` for fields that must remain strings.\n */\nexport function extractFrontmatterWithContent<Frontmatter>(content: string): {\n frontmatter: Frontmatter;\n strippedContent: string;\n};\nexport function extractFrontmatterWithContent<Frontmatter>(\n content: string,\n schema: ZodType<Frontmatter>\n): { frontmatter: Frontmatter; strippedContent: string };\nexport function extractFrontmatterWithContent<Frontmatter>(\n content: string,\n schema?: ZodType<Frontmatter>\n): { frontmatter: Frontmatter; strippedContent: string } {\n try {\n const { data, content: strippedContent } = matter(content);\n return {\n frontmatter: schema ? schema.parse(data) : (data as Frontmatter),\n strippedContent,\n };\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to extract frontmatter: ${reason}`, { cause: error });\n }\n}\n"],"mappings":"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","names":["visit","visit","visit","children","visit"]}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/plugins/handleCodeTitles.ts","../src/plugins/handleCodeExpandable.ts","../src/plugins/rehypeMermaid.ts","../src/plugins/remarkDirectiveToMdx.ts","../src/mdx-compiler/index.ts","../src/compile.ts","../src/extract.ts"],"sourcesContent":["import type { Node, Parent } from \"unist\";\nimport { visit } from \"unist-util-visit\";\nimport type { ElementNode } from \"../utils\";\n\ninterface TextNode extends Node {\n type: \"text\";\n value: string;\n}\n\nexport const handleCodeTitles = () => (tree: Node) => {\n const toRemove: { parent: Parent; index: number }[] = [];\n\n visit(tree, \"element\", (node: ElementNode, index: number | null, parent: Parent | null) => {\n if (!parent || index === null || node.tagName !== \"div\") {\n return;\n }\n\n const isTitleDiv = node.properties?.className?.includes(\"rehype-code-title\");\n if (!isTitleDiv) {\n return;\n }\n\n let nextElement: ElementNode | null = null;\n for (let i = index + 1; i < parent.children.length; i++) {\n const sibling = parent.children[i];\n if (sibling.type === \"element\") {\n nextElement = sibling as ElementNode;\n break;\n }\n }\n\n if (nextElement?.tagName === \"pre\") {\n const titleNode = node.children?.[0] as TextNode;\n if (titleNode?.type === \"text\") {\n if (!nextElement.properties) {\n nextElement.properties = {};\n }\n nextElement.properties[\"data-title\"] = titleNode.value;\n nextElement.codeTitle = titleNode.value;\n toRemove.push({ parent, index });\n }\n }\n });\n\n // Remove title divs in reverse order to preserve indices\n for (let i = toRemove.length - 1; i >= 0; i--) {\n const { parent, index } = toRemove[i];\n parent.children.splice(index, 1);\n }\n};\n","import type { Node } from \"unist\";\nimport { visit } from \"unist-util-visit\";\nimport type { ElementNode } from \"../utils\";\n\n/**\n * Escape metadata values that are interpolated into MDX-compiled JavaScript.\n *\n * References:\n * - HTML spec (script data state): escape `</` as `\\u003C/` to prevent premature\n * `</script>` closing when the compiled JS is embedded as JSON in a <script> tag.\n * - Bun.escapeHTML(): escapes `< > \" ' &` for HTML context; for JS/JSON context\n * we use `\\uXXXX` JSON Unicode escapes instead so the value survives round-trip\n * through JSON.parse on the client side.\n * - React: JSX auto-escapes attribute values via `{expression}`, so values set\n * as HAST properties (data-language, data-title) are HTML-safe at render time.\n */\nfunction escapeMeta(s: string): string {\n let out = \"\";\n for (let i = 0; i < s.length; i++) {\n const ch = s[i];\n\n // HTML spec: prevent </script> in script/JSON context\n if (ch === \"<\" && s[i + 1] === \"/\") {\n out += \"\\\\u003C/\";\n i++;\n continue;\n }\n\n // JS string: escape template literal & string special chars\n if (ch === \"`\" || ch === \"$\" || ch === \"{\" || ch === \"}\" || ch === '\"' || ch === \"\\\\\") {\n out += `\\\\${ch}`;\n continue;\n }\n\n out += ch;\n }\n return out;\n}\n\ninterface CodeNode extends Node {\n type: \"code\";\n lang?: string;\n meta?: string;\n value: string;\n data?: {\n meta?: string;\n hProperties?: Record<string, unknown>;\n };\n}\n\nfunction countCodeLines(raw: string): number {\n let normalized = raw.replace(/\\r\\n/g, \"\\n\");\n if (normalized.startsWith(\"\\n\")) normalized = normalized.slice(1);\n if (normalized.endsWith(\"\\n\")) normalized = normalized.slice(0, -1);\n\n if (normalized.length === 0) return 0;\n return normalized.split(\"\\n\").length;\n}\n\nexport const handleCodeExpandableRemark = () => (tree: Node) => {\n visit(tree, \"code\", (node: CodeNode) => {\n if (!node.meta) return;\n\n const isExpandable = node.meta.includes(\"Expandable\");\n const [languagePart, titlePart] = (node.lang ?? \"\").split(\":\");\n const normalizedLanguage = languagePart?.trim();\n const normalizedTitle = titlePart?.trim();\n\n if (!isExpandable) return;\n\n const lineCount = countCodeLines(node.value);\n\n if (!node.data) {\n node.data = {};\n }\n if (!node.data.hProperties) {\n node.data.hProperties = {};\n }\n\n node.data.hProperties[\"data-expandable\"] = \"true\";\n node.data.hProperties[\"data-expandable-lines\"] = lineCount.toString();\n\n if (normalizedLanguage) {\n node.data.hProperties[\"data-language\"] = normalizedLanguage;\n }\n if (normalizedTitle) {\n node.data.hProperties[\"data-title\"] = normalizedTitle;\n }\n\n const currentClassName = node.data.hProperties.className;\n const classList = Array.isArray(currentClassName)\n ? currentClassName\n : typeof currentClassName === \"string\"\n ? currentClassName.split(\" \").filter(Boolean)\n : [];\n\n if (!classList.includes(\"mdx-expandable-meta\")) {\n classList.push(\"mdx-expandable-meta\");\n }\n\n node.data.hProperties.className = classList;\n\n if (normalizedLanguage && !node.meta.includes(\"dbLang(\")) {\n node.meta = `${node.meta} dbLang(${escapeMeta(normalizedLanguage)})`.trim();\n }\n if (normalizedTitle && !node.meta.includes(\"dbTitle(\")) {\n node.meta = `${node.meta} dbTitle(${escapeMeta(normalizedTitle)})`.trim();\n }\n });\n};\n\nexport const handleCodeExpandable = () => (tree: Node) => {\n visit(tree, \"element\", (node: ElementNode) => {\n if (node.tagName !== \"pre\") return;\n\n const codeElement = node.children?.find((child) => {\n const element = child as ElementNode;\n return element.type === \"element\" && element.tagName === \"code\";\n }) as ElementNode | undefined;\n\n const codeClassName = codeElement?.properties?.className;\n const codeClassList = Array.isArray(codeClassName)\n ? codeClassName\n : typeof codeClassName === \"string\"\n ? codeClassName.split(\" \").filter(Boolean)\n : [];\n\n const codeMeta =\n codeElement?.data &&\n typeof codeElement.data === \"object\" &&\n typeof codeElement.data[\"meta\"] === \"string\"\n ? (codeElement.data[\"meta\"] as string)\n : undefined;\n\n const languageFromMeta = codeMeta?.match(/dbLang\\(([^)]+)\\)/)?.[1];\n const titleFromMeta = codeMeta?.match(/dbTitle\\(([^)]+)\\)/)?.[1];\n\n const languageFromProps =\n typeof codeElement?.properties?.[\"data-language\"] === \"string\"\n ? (codeElement.properties[\"data-language\"] as string)\n : undefined;\n const titleFromProps =\n typeof codeElement?.properties?.[\"data-title\"] === \"string\"\n ? (codeElement.properties[\"data-title\"] as string)\n : undefined;\n\n const languageFromCodeClass = codeClassList\n .find((item) => item.startsWith(\"language-\"))\n ?.replace(\"language-\", \"\");\n\n const existingPreLanguage =\n typeof node.properties?.[\"data-language\"] === \"string\"\n ? (node.properties[\"data-language\"] as string)\n : undefined;\n const existingPreTitle =\n typeof node.properties?.[\"data-title\"] === \"string\"\n ? (node.properties[\"data-title\"] as string)\n : undefined;\n\n const isExpandable =\n codeElement?.properties?.[\"data-expandable\"] === \"true\" ||\n codeClassList.includes(\"mdx-expandable-meta\") ||\n codeMeta?.includes(\"Expandable\") === true;\n\n const expandableLines = codeElement?.properties?.[\"data-expandable-lines\"];\n if (!isExpandable) return;\n\n if (!node.properties) {\n node.properties = {};\n }\n\n node.properties[\"data-expandable\"] = \"true\";\n if (typeof expandableLines === \"string\" || typeof expandableLines === \"number\") {\n node.properties[\"data-expandable-lines\"] = expandableLines.toString();\n } else if (node.raw) {\n node.properties[\"data-expandable-lines\"] = countCodeLines(node.raw).toString();\n }\n\n const resolvedLanguage =\n languageFromProps ||\n languageFromMeta ||\n languageFromCodeClass ||\n existingPreLanguage ||\n node.language;\n const resolvedTitle = titleFromProps || titleFromMeta || existingPreTitle || node.codeTitle;\n\n if (resolvedLanguage) {\n node.properties[\"data-language\"] = resolvedLanguage;\n }\n if (resolvedTitle) {\n node.properties[\"data-title\"] = resolvedTitle;\n }\n\n const className = node.properties.className;\n if (!className) {\n node.properties.className = [];\n }\n\n if (Array.isArray(node.properties.className)) {\n if (!node.properties.className.includes(\"mdx-expandable-code\")) {\n node.properties.className.push(\"mdx-expandable-code\");\n }\n } else if (typeof className === \"string\") {\n const hasMarker = className.split(\" \").includes(\"mdx-expandable-code\");\n if (!hasMarker) {\n node.properties.className = `${className} mdx-expandable-code`.trim().split(\" \");\n }\n } else {\n node.properties.className = [\"mdx-expandable-code\"];\n }\n\n if (codeElement?.properties) {\n const cleanedCodeClassList = codeClassList.filter((item) => item !== \"mdx-expandable-meta\");\n codeElement.properties.className = cleanedCodeClassList;\n }\n });\n};\n","import type { Node, Parent } from \"unist\";\nimport { visit } from \"unist-util-visit\";\nimport type { ElementNode } from \"../utils\";\n\ninterface TextNode extends Node {\n type: \"text\";\n value: string;\n}\n\n/**\n * Rehype plugin that transforms `<pre><code class=\"language-mermaid\">` fenced\n * blocks into `<Mermaid chart=\"...\">` elements.\n *\n * This allows Mermaid diagram definitions to be authored via standard fenced\n * code blocks (````mermaid) which avoids JSX parsing collisions with\n * Mermaid's `{...}` (decision nodes) and `[...]` (label nodes) syntax.\n */\nexport const rehypeMermaid = () => (tree: Node) => {\n visit(tree, \"element\", (node: ElementNode, index: number | null, parent: Parent | null) => {\n if (!parent || index === null || node.tagName !== \"pre\") return;\n\n const codeEl = node.children?.find(\n (child) =>\n (child as ElementNode).type === \"element\" && (child as ElementNode).tagName === \"code\"\n ) as ElementNode | undefined;\n\n if (!codeEl) return;\n\n const classList = Array.isArray(codeEl.properties?.className)\n ? (codeEl.properties.className as string[])\n : typeof codeEl.properties?.className === \"string\"\n ? (codeEl.properties.className as string).split(\" \").filter(Boolean)\n : [];\n\n if (!classList.includes(\"language-mermaid\")) return;\n\n const textNode = codeEl.children?.find((child) => (child as TextNode).type === \"text\") as\n TextNode | undefined;\n\n const chart = textNode?.value ?? \"\";\n\n parent.children[index] = {\n type: \"element\",\n tagName: \"Mermaid\",\n properties: { chart },\n children: [],\n } as unknown as ElementNode;\n });\n};\n","import type { Node } from \"unist\";\n\n/**\n * Remark plugin: convert markdown directives into MDX component elements.\n *\n * Contract (docubook):\n * - `:::name{attrs} … :::` — container: EVERY component that holds content\n * (tabs, tab, accordions, accordion, steps, step, cards, card, files,\n * folder, note + variants). Children are the block between the opening\n * `:::` and closing `:::` — bounded by micromark's container grammar, so\n * a component can never trap siblings that follow it.\n * - `::name{attrs}` — self-closing leaf (no children): file, youtube,\n * mermaid.\n * - `:tooltip[label]{tip=\"…\"}` — the ONE inline (single-colon) directive.\n * Every other text directive is rebuilt as literal text\n * (`localhost:3000` stays intact). `::tooltip` (block leaf) is removed\n * in v2 — tooltips are inline only.\n *\n * Names are PascalCased to match the components map (`file-tree` → `FileTree`).\n * Bare attributes (`{horizontal}`) become boolean props (JSX bare attribute).\n * Callout variants (`:::tip`, `:::info`, …) map to their own registry entries\n * (`Tip`/`Info`/…) which wrap the `Callout` component with the type set.\n */\nexport function remarkDirectiveToMdx() {\n return (tree: Node) => {\n const root = tree as unknown as { children: Node[] };\n root.children = root.children.map(transform);\n return tree;\n };\n}\n\n/** Leaves that never hold children (self-closing). */\nconst PURE_LEAVES = new Set([\"youtube\"]);\n\ntype DirectiveNode = Node & {\n type: \"containerDirective\" | \"leafDirective\" | \"textDirective\";\n name: string;\n label?: string;\n attributes?: Record<string, string>;\n children?: Node[];\n};\n\nfunction isDirective(node: Node): node is DirectiveNode {\n return (\n node.type === \"containerDirective\" ||\n node.type === \"leafDirective\" ||\n node.type === \"textDirective\"\n );\n}\n\nfunction transform(node: Node): Node {\n if (!isDirective(node)) {\n const children = (node as unknown as { children?: Node[] }).children;\n if (Array.isArray(children)) {\n (node as unknown as { children: Node[] }).children = children.map(transform);\n }\n return node;\n }\n if (node.type === \"textDirective\") {\n // `:tooltip[label]{tip=\"…\"}` is the one inline component — it stays\n // inside the paragraph. Every other single-colon text directive is\n // rebuilt as literal text (`localhost:3000` stays intact).\n if (node.name === \"tooltip\") {\n return inlineTooltip(node);\n }\n return literalDirective(node);\n }\n // Block-form tooltips are gone in v2 — degrade to literal text so the\n // author sees the directive instead of a broken component.\n if (node.type === \"leafDirective\" && node.name === \"tooltip\") {\n return literalDirective(node);\n }\n // containerDirective → component with children; leafDirective → self-closing.\n const children =\n node.type === \"containerDirective\" && !PURE_LEAVES.has(node.name)\n ? (node.children ?? []).map(transform)\n : [];\n return directiveToElement(node, children);\n}\n\nfunction directiveToElement(directive: DirectiveNode, children: Node[]): Node {\n const name = pascalCase(directive.name);\n const attributes = Object.entries(directive.attributes ?? {}).map(([attrName, value]) => ({\n type: \"mdxJsxAttribute\",\n name: attrName,\n value: value === \"\" ? null : value,\n }));\n return {\n type: \"mdxJsxFlowElement\",\n name,\n attributes,\n children,\n } as Node;\n}\n\n/** Rebuild a text directive as literal text (single-colon is not a contract). */\nfunction literalDirective(directive: DirectiveNode): Node {\n const literal = \":\" + directive.name + (directive.label ? `[${directive.label}]` : \"\");\n const attrStr = Object.entries(directive.attributes ?? {})\n .map(([k, v]) => (v === \"\" ? k : `${k}=\"${v}\"`))\n .join(\" \");\n return { type: \"text\", value: literal + (attrStr ? `{${attrStr}}` : \"\") } as Node;\n}\n\n/**\n * Inline tooltip from a text directive: `:tooltip[label]{tip=\"…\"}`.\n * The label is the visible trigger (dotted underline); `tip` is the hover\n * bubble and defaults to the label, so `:tooltip[text]` alone already shows\n * a bubble. Emits an inline element so it stays inside the paragraph. The\n * bubble auto-positions (no `side` prop).\n */\nfunction inlineTooltip(directive: DirectiveNode): Node {\n const label = (directive.children ?? [])\n .map((child) => (child as { value?: string }).value ?? \"\")\n .join(\"\");\n const attrs = directive.attributes ?? {};\n const attributes = [\n { type: \"mdxJsxAttribute\", name: \"text\", value: attrs.text || label || \"?\" },\n { type: \"mdxJsxAttribute\", name: \"tip\", value: attrs.tip || label || \"\" },\n ];\n return { type: \"mdxJsxTextElement\", name: \"Tooltip\", attributes, children: [] } as Node;\n}\n\nfunction pascalCase(name: string): string {\n return name\n .split(\"-\")\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n}\n","// MPL-2.0 — derived from next-mdx-remote (IBM). See LICENSE-MPL-2.0.\nimport React, { useEffect, useState, useMemo } from \"react\";\nimport * as jsxRuntime from \"react/jsx-runtime\";\nimport * as jsxDevRuntime from \"react/jsx-dev-runtime\";\nimport * as mdx from \"@mdx-js/react\";\nimport type { MDXRemoteSerializeResult } from \"./types.js\";\n\n/** Props for the client-side `<MDXRemote>` (accepts pre-serialized result). */\nexport type MDXRemoteProps = MDXRemoteSerializeResult & {\n components?: Record<string, React.ComponentType<any>>;\n /** Defer hydration to an idle callback */\n lazy?: boolean;\n};\n\n/**\n * Client-side MDX renderer.\n *\n * Accepts a pre-compiled result from `serialize()` and renders it via\n * `MDXProvider` for custom component injection.\n */\nexport function MDXRemote({\n compiledSource,\n frontmatter,\n scope = {},\n components = {},\n lazy,\n}: MDXRemoteProps): React.ReactElement {\n const [ready, setReady] = useState(!lazy || typeof window === \"undefined\");\n\n useEffect(() => {\n if (!lazy) return;\n const id = window.requestIdleCallback\n ? window.requestIdleCallback(() => setReady(true), { timeout: 500 })\n : setTimeout(() => setReady(true), 1);\n return () => {\n if (window.cancelIdleCallback) window.cancelIdleCallback(id as number);\n else clearTimeout(id as number);\n };\n }, [lazy]);\n\n const Content = useMemo(() => {\n // Non-RSC mode: compiled MDX expects `useMDXComponents` (\n // from @mdx-js/react) AND the JSX runtime.\n // In React 19, jsx/jsxs and jsxDEV live in separate modules,\n // so merge both to handle compiled output from any mode.\n const fullScope = {\n opts: { ...mdx, ...jsxRuntime, ...jsxDevRuntime },\n frontmatter,\n ...scope,\n };\n const keys = Object.keys(fullScope);\n const values = Object.values(fullScope);\n const fn = Reflect.construct(Function, keys.concat(`${compiledSource}`));\n return fn.apply(fn, values).default;\n }, [compiledSource, scope, frontmatter]);\n\n if (!ready) {\n return React.createElement(\"div\", {\n dangerouslySetInnerHTML: { __html: \"\" },\n suppressHydrationWarning: true,\n });\n }\n\n const content = React.createElement(\n mdx.MDXProvider,\n { components },\n React.createElement(Content, null)\n );\n\n return lazy ? React.createElement(\"div\", null, content) : content;\n}\n","import { serialize } from \"./mdx-compiler/serialize.js\";\nimport type { Node } from \"unist\";\nimport { visit } from \"unist-util-visit\";\nimport remarkGfm from \"remark-gfm\";\nimport rehypePrism from \"rehype-prism-plus\";\nimport rehypeAutolinkHeadings from \"rehype-autolink-headings\";\nimport rehypeSlug from \"rehype-slug\";\nimport rehypeCodeTitles from \"rehype-code-titles\";\nimport { handleCodeTitles } from \"./plugins/handleCodeTitles\";\nimport { handleCodeExpandableRemark, handleCodeExpandable } from \"./plugins/handleCodeExpandable\";\nimport { rehypeMermaid } from \"./plugins/rehypeMermaid\";\nimport { remarkDirectiveToMdx } from \"./plugins/remarkDirectiveToMdx\";\nimport remarkDirective from \"remark-directive\";\nimport type { ElementNode } from \"./utils\";\nimport type { Pluggable } from \"unified\";\n\n// Re-export serialize for non-RSC usage\nexport { serialize };\n\n// Re-export MDXRemote for client-side hydration\nexport { MDXRemote } from \"./mdx-compiler/index.js\";\n\ninterface TextNode extends Node {\n type: \"text\";\n value: string;\n}\n\nexport const preProcess = () => (tree: Node) => {\n visit(tree, (node: Node) => {\n const element = node as ElementNode;\n if (element?.type === \"element\" && element?.tagName === \"pre\" && element.children) {\n const [codeEl] = element.children as ElementNode[];\n if (codeEl.tagName !== \"code\" || !codeEl.children?.[0]) return;\n\n const className = codeEl.properties?.className;\n const classList = Array.isArray(className)\n ? className\n : typeof className === \"string\"\n ? className.split(\" \").filter(Boolean)\n : [];\n const languageClass = classList.find((item: string) => item.startsWith(\"language-\"));\n if (languageClass) {\n element.language = languageClass.replace(\"language-\", \"\").split(\":\")[0];\n }\n\n const textNode = codeEl.children[0] as TextNode;\n if (textNode.type === \"text\" && textNode.value) {\n element.raw = textNode.value;\n }\n }\n });\n\n return tree;\n};\n\nexport const postProcess = () => (tree: Node) => {\n visit(tree, \"element\", (node: Node) => {\n const element = node as ElementNode;\n if (element?.type === \"element\" && element?.tagName === \"pre\") {\n if (element.properties && element.raw) {\n element.properties.raw = element.raw;\n }\n if (element.properties && element.language && !element.properties[\"data-language\"]) {\n element.properties[\"data-language\"] = element.language;\n }\n if (element.properties && element.codeTitle && !element.properties[\"data-title\"]) {\n element.properties[\"data-title\"] = element.codeTitle;\n }\n }\n });\n\n return tree;\n};\n\nexport function createDefaultRehypePlugins(): Pluggable[] {\n return [\n preProcess,\n rehypeMermaid, // Transform ```mermaid before code transforms\n rehypeCodeTitles,\n handleCodeTitles,\n handleCodeExpandable, // Copy expandable metadata from <code> to <pre> before prism transforms nodes.\n rehypePrism,\n handleCodeExpandable, // Re-apply expandable attrs after prism tokenization.\n rehypeSlug,\n rehypeAutolinkHeadings,\n postProcess,\n ];\n}\n\nexport function createDefaultRemarkPlugins(): Pluggable[] {\n return [remarkGfm, handleCodeExpandableRemark, remarkDirective, remarkDirectiveToMdx];\n}\n","import matter from \"@11ty/gray-matter\";\nimport type { ZodType } from \"zod\";\nimport type { TocItem } from \"./types\";\n\nconst FENCE_MARKER_REGEX = /^(````|```)(?!`)/;\nconst HEADING_REGEX = /^(#{2,4})\\s+(.+)$/;\n\nexport function sluggify(text: string): string {\n const normalized = text.normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\"); // Remove accents\n const slug = normalized.toLowerCase().replace(/\\s+/g, \"-\");\n return slug.replace(/[^a-z0-9-]/g, \"\");\n}\n\nexport function extractTocsFromRawMdx(rawMdx: string): TocItem[] {\n const extractedHeadings: TocItem[] = [];\n\n const lines = rawMdx.split(/\\r?\\n/);\n let inFence = false;\n let fenceLength = 0;\n\n for (const line of lines) {\n const trimmed = line.trimStart();\n\n const fenceMatch = FENCE_MARKER_REGEX.exec(trimmed);\n if (fenceMatch) {\n const marker = fenceMatch[1];\n\n if (!inFence) {\n inFence = true;\n fenceLength = marker.length;\n } else if (marker.length === fenceLength) {\n inFence = false;\n }\n\n continue;\n }\n\n if (inFence) {\n continue;\n }\n\n const headingMatch = HEADING_REGEX.exec(trimmed);\n if (headingMatch) {\n const headingLevel = headingMatch[1].length;\n const headingText = headingMatch[2].trim().replace(/\\s+#+\\s*$/, \"\");\n extractedHeadings.push({\n level: headingLevel,\n text: headingText,\n href: `#${sluggify(headingText)}`,\n });\n continue;\n }\n }\n\n return extractedHeadings;\n}\n\nexport function extractFrontmatter<Frontmatter>(content: string): Frontmatter {\n try {\n return matter(content).data as Frontmatter;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to extract frontmatter: ${reason}`, { cause: error });\n }\n}\n\n/**\n * Extract frontmatter and return both the parsed data and the content\n * with the frontmatter block stripped. Avoids a second parse during\n * compilation.\n *\n * Optionally validates the parsed frontmatter with a Zod schema.\n * YAML coerces unquoted values (e.g. `date: 2026-06-10` → Date, `3.5` → number),\n * so use `z.coerce.*` for fields that must remain strings.\n */\nexport function extractFrontmatterWithContent<Frontmatter>(content: string): {\n frontmatter: Frontmatter;\n strippedContent: string;\n};\nexport function extractFrontmatterWithContent<Frontmatter>(\n content: string,\n schema: ZodType<Frontmatter>\n): { frontmatter: Frontmatter; strippedContent: string };\nexport function extractFrontmatterWithContent<Frontmatter>(\n content: string,\n schema?: ZodType<Frontmatter>\n): { frontmatter: Frontmatter; strippedContent: string } {\n try {\n const { data, content: strippedContent } = matter(content);\n return {\n frontmatter: schema ? schema.parse(data) : (data as Frontmatter),\n strippedContent,\n };\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to extract frontmatter: ${reason}`, { cause: error });\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { MDXRemoteSerializeResult } from "./types.js";
|
|
3
|
+
/** Props for the client-side `<MDXRemote>` (accepts pre-serialized result). */
|
|
4
|
+
export type MDXRemoteProps = MDXRemoteSerializeResult & {
|
|
5
|
+
components?: Record<string, React.ComponentType<any>>;
|
|
6
|
+
/** Defer hydration to an idle callback */
|
|
7
|
+
lazy?: boolean;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Client-side MDX renderer.
|
|
11
|
+
*
|
|
12
|
+
* Accepts a pre-compiled result from `serialize()` and renders it via
|
|
13
|
+
* `MDXProvider` for custom component injection.
|
|
14
|
+
*/
|
|
15
|
+
export declare function MDXRemote({ compiledSource, frontmatter, scope, components, lazy, }: MDXRemoteProps): React.ReactElement;
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import { Pluggable } from
|
|
2
|
-
|
|
3
|
-
/** Shape returned by `serialize()` — ready to pass to `<MDXRemote>`. */
|
|
4
|
-
type MDXRemoteSerializeResult = SerializeResult;
|
|
5
|
-
|
|
1
|
+
import type { Pluggable } from "unified";
|
|
6
2
|
/** @internal — re-exported from unified. */
|
|
7
3
|
type RemarkPlugins = Pluggable[];
|
|
8
4
|
type RehypePlugins = Pluggable[];
|
|
9
|
-
|
|
10
|
-
type SerializeOptions = {
|
|
5
|
+
export type { MDXRemoteSerializeResult } from "./types";
|
|
6
|
+
export type SerializeOptions = {
|
|
11
7
|
scope?: Record<string, unknown>;
|
|
12
8
|
mdxOptions?: {
|
|
13
9
|
remarkPlugins?: RemarkPlugins;
|
|
@@ -40,7 +36,7 @@ type SerializeOptions = {
|
|
|
40
36
|
*/
|
|
41
37
|
blockJS?: boolean;
|
|
42
38
|
};
|
|
43
|
-
type SerializeResult = {
|
|
39
|
+
export type SerializeResult = {
|
|
44
40
|
compiledSource: string;
|
|
45
41
|
frontmatter: Record<string, unknown>;
|
|
46
42
|
scope: Record<string, unknown>;
|
|
@@ -48,6 +44,4 @@ type SerializeResult = {
|
|
|
48
44
|
/**
|
|
49
45
|
* Compile raw MDX string into a serialized result that can be rendered.
|
|
50
46
|
*/
|
|
51
|
-
declare function serialize(source: string, { scope, mdxOptions, parseFrontmatter, blockJS, outputFormat, format, }?: SerializeOptions, rsc?: boolean): Promise<SerializeResult>;
|
|
52
|
-
|
|
53
|
-
export { type MDXRemoteSerializeResult, type SerializeOptions, type SerializeResult, serialize };
|
|
47
|
+
export declare function serialize(source: string, { scope, mdxOptions, parseFrontmatter, blockJS, outputFormat, format, }?: SerializeOptions, rsc?: boolean): Promise<SerializeResult>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Node } from "unist";
|
|
2
|
+
/**
|
|
3
|
+
* Rehype plugin that transforms `<pre><code class="language-mermaid">` fenced
|
|
4
|
+
* blocks into `<Mermaid chart="...">` elements.
|
|
5
|
+
*
|
|
6
|
+
* This allows Mermaid diagram definitions to be authored via standard fenced
|
|
7
|
+
* code blocks (````mermaid) which avoids JSX parsing collisions with
|
|
8
|
+
* Mermaid's `{...}` (decision nodes) and `[...]` (label nodes) syntax.
|
|
9
|
+
*/
|
|
10
|
+
export declare const rehypeMermaid: () => (tree: Node) => void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Node } from "unist";
|
|
2
|
+
/**
|
|
3
|
+
* Remark plugin: convert markdown directives into MDX component elements.
|
|
4
|
+
*
|
|
5
|
+
* Contract (docubook):
|
|
6
|
+
* - `:::name{attrs} … :::` — container: EVERY component that holds content
|
|
7
|
+
* (tabs, tab, accordions, accordion, steps, step, cards, card, files,
|
|
8
|
+
* folder, note + variants). Children are the block between the opening
|
|
9
|
+
* `:::` and closing `:::` — bounded by micromark's container grammar, so
|
|
10
|
+
* a component can never trap siblings that follow it.
|
|
11
|
+
* - `::name{attrs}` — self-closing leaf (no children): file, youtube,
|
|
12
|
+
* mermaid.
|
|
13
|
+
* - `:tooltip[label]{tip="…"}` — the ONE inline (single-colon) directive.
|
|
14
|
+
* Every other text directive is rebuilt as literal text
|
|
15
|
+
* (`localhost:3000` stays intact). `::tooltip` (block leaf) is removed
|
|
16
|
+
* in v2 — tooltips are inline only.
|
|
17
|
+
*
|
|
18
|
+
* Names are PascalCased to match the components map (`file-tree` → `FileTree`).
|
|
19
|
+
* Bare attributes (`{horizontal}`) become boolean props (JSX bare attribute).
|
|
20
|
+
* Callout variants (`:::tip`, `:::info`, …) map to their own registry entries
|
|
21
|
+
* (`Tip`/`Info`/…) which wrap the `Callout` component with the type set.
|
|
22
|
+
*/
|
|
23
|
+
export declare function remarkDirectiveToMdx(): (tree: Node) => Node;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { compile as e } from "@mdx-js/mdx";
|
|
2
|
+
import { VFile as t } from "vfile";
|
|
3
|
+
import { matter as n } from "vfile-matter";
|
|
4
|
+
import { remove as r } from "unist-util-remove";
|
|
5
|
+
import { SKIP as i, visit as a } from "unist-util-visit";
|
|
6
|
+
//#region src/mdx-compiler/format-mdx-error.ts
|
|
7
|
+
function o(e, t) {
|
|
8
|
+
return /* @__PURE__ */ Error(`[mdx] error compiling MDX:\n${e?.message ?? e}`);
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/mdx-compiler/plugins/remove-imports-exports.ts
|
|
12
|
+
function s() {
|
|
13
|
+
return (e) => r(e, "mdxjsEsm");
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/mdx-compiler/plugins/remove-javascript-expressions.ts
|
|
17
|
+
var c = () => (e) => {
|
|
18
|
+
a(e, (e, t, n) => {
|
|
19
|
+
if ((e.type === "mdxFlowExpression" || e.type === "mdxTextExpression") && n && typeof t == "number") return n.children.splice(t, 1), [i, t];
|
|
20
|
+
if (e.type === "mdxJsxFlowElement" || e.type === "mdxJsxTextElement") {
|
|
21
|
+
let t = e;
|
|
22
|
+
t.attributes &&= t.attributes.filter((e) => e.type === "mdxJsxAttribute" ? e.value === null || typeof e.value == "string" || e.value && e.value.type !== "mdxJsxAttributeValueExpression" : e.type !== "mdxJsxExpressionAttribute");
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}, l = /* @__PURE__ */ "eval.Function.AsyncFunction.GeneratorFunction.require.module.exports.__dirname.__filename.process.global.globalThis.Reflect.child_process.fs.net.http.https.vm.worker_threads.fetch.setTimeout.setInterval.setImmediate.queueMicrotask.XMLHttpRequest".split("."), u = [
|
|
26
|
+
"constructor",
|
|
27
|
+
"prototype",
|
|
28
|
+
"__proto__",
|
|
29
|
+
"eval",
|
|
30
|
+
"Reflect",
|
|
31
|
+
"Function",
|
|
32
|
+
"AsyncFunction",
|
|
33
|
+
"GeneratorFunction",
|
|
34
|
+
"require"
|
|
35
|
+
];
|
|
36
|
+
function d(e, t, n) {
|
|
37
|
+
if (!(!e || typeof e != "object")) {
|
|
38
|
+
if (e.type === "Identifier" && t.includes(e.name)) {
|
|
39
|
+
let t = e.parent, n = t?.type === "MemberExpression" && t.property === e && !t.computed, r = t?.type === "FunctionDeclaration" || t?.type === "FunctionExpression";
|
|
40
|
+
if (!n && !r) throw Error(`Security: Access to '${e.name}' is not allowed`);
|
|
41
|
+
}
|
|
42
|
+
if (e.type === "CallExpression" && e.callee?.type === "Identifier" && t.includes(e.callee.name)) throw Error(`Security: ${e.callee.name}() calls are not allowed`);
|
|
43
|
+
if (e.type === "ImportExpression") throw Error("Security: Dynamic import() is not allowed");
|
|
44
|
+
if (e.type === "TaggedTemplateExpression" && e.tag?.type === "Identifier" && t.includes(e.tag.name)) throw Error(`Security: ${e.tag.name}\`...\` tagged template is not allowed`);
|
|
45
|
+
if (e.type === "CallExpression" && e.callee?.type === "MemberExpression" && e.callee.computed) throw Error("Security: Function calls via computed property access are not allowed");
|
|
46
|
+
if (e.type === "MemberExpression" && !e.computed) {
|
|
47
|
+
let t = e.property;
|
|
48
|
+
if (t?.type === "Identifier" && n.includes(t.name)) throw Error(`Security: .${t.name} access is not allowed`);
|
|
49
|
+
}
|
|
50
|
+
if (e.type === "NewExpression" && e.callee?.type === "Identifier" && t.includes(e.callee.name)) throw Error(`Security: new ${e.callee.name}() is not allowed`);
|
|
51
|
+
for (let r in e) {
|
|
52
|
+
if (r === "parent" || r === "position") continue;
|
|
53
|
+
let i = e[r];
|
|
54
|
+
Array.isArray(i) ? i.forEach((e) => {
|
|
55
|
+
e && typeof e == "object" && d(e, t, n);
|
|
56
|
+
}) : i && typeof i == "object" && d(i, t, n);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
var f = (e, t) => () => (n) => (d(n, e ?? l, t ?? u), n);
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/mdx-compiler/serialize.ts
|
|
63
|
+
function p(e = {}, t = !1, n = !0, r = "function-body", i = "mdx") {
|
|
64
|
+
let a = [
|
|
65
|
+
...e?.remarkPlugins ?? [],
|
|
66
|
+
s,
|
|
67
|
+
...n ? [c] : [],
|
|
68
|
+
f()
|
|
69
|
+
];
|
|
70
|
+
return {
|
|
71
|
+
...e,
|
|
72
|
+
remarkPlugins: a,
|
|
73
|
+
rehypePlugins: e?.rehypePlugins ?? [],
|
|
74
|
+
format: i,
|
|
75
|
+
outputFormat: r,
|
|
76
|
+
providerImportSource: t ? void 0 : "@mdx-js/react",
|
|
77
|
+
development: process.env.NODE_ENV !== "production"
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async function m(r, { scope: i = {}, mdxOptions: a = {}, parseFrontmatter: s = !1, blockJS: c = !0, outputFormat: l = "function-body", format: u = "mdx" } = {}, d = !1) {
|
|
81
|
+
let f = new t(r);
|
|
82
|
+
s && n(f, { strip: !0 });
|
|
83
|
+
let m;
|
|
84
|
+
try {
|
|
85
|
+
m = String(await e(f, p(a, d, c, l, u)));
|
|
86
|
+
} catch (e) {
|
|
87
|
+
throw o(e, String(f));
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
compiledSource: m,
|
|
91
|
+
frontmatter: f.data.matter ?? {},
|
|
92
|
+
scope: i
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { m as t };
|
|
97
|
+
|
|
98
|
+
//# sourceMappingURL=serialize-DEuXE4Xm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize-DEuXE4Xm.js","names":[],"sources":["../src/mdx-compiler/format-mdx-error.ts","../src/mdx-compiler/plugins/remove-imports-exports.ts","../src/mdx-compiler/plugins/remove-javascript-expressions.ts","../src/mdx-compiler/plugins/remove-dangerous-javascript-expressions.ts","../src/mdx-compiler/serialize.ts"],"sourcesContent":["// MPL-2.0 — derived from next-mdx-remote (IBM). See LICENSE-MPL-2.0.\n/**\n * Wraps raw MDX compilation errors with a clear message prefix.\n */\nexport function createFormattedMDXError(error: any, _source: string): Error {\n return new Error(`[mdx] error compiling MDX:\\n${error?.message ?? error}`);\n}\n","// MPL-2.0 — derived from next-mdx-remote (IBM). See LICENSE-MPL-2.0.\nimport { remove } from \"unist-util-remove\";\nimport type { Node } from \"unist\";\n\n/** remark plugin: strips all `mdxjsEsm` nodes (import/export statements). */\nexport function removeImportsExportsPlugin() {\n return (tree: Node) => remove(tree, \"mdxjsEsm\");\n}\n","// MPL-2.0 — derived from next-mdx-remote (IBM). See LICENSE-MPL-2.0.\nimport { visit, SKIP } from \"unist-util-visit\";\nimport type { Node } from \"unist\";\n\n/**\n * remark plugin: removes JS expression nodes ({variable}, {func()}) from MDX.\n * Preserves JSX (<Component />) and plain markdown.\n */\nexport const removeJavaScriptExpressions = () => {\n return (tree: Node) => {\n visit(tree, (node: Node, index: number | undefined, parent: Node | undefined) => {\n if (node.type === \"mdxFlowExpression\" || node.type === \"mdxTextExpression\") {\n if (parent && typeof index === \"number\") {\n (parent as any).children.splice(index, 1);\n return [SKIP, index] as const;\n }\n }\n\n if (node.type === \"mdxJsxFlowElement\" || node.type === \"mdxJsxTextElement\") {\n const el = node as any;\n if (el.attributes) {\n el.attributes = el.attributes.filter((attr: any) => {\n if (attr.type === \"mdxJsxAttribute\") {\n return (\n attr.value === null ||\n typeof attr.value === \"string\" ||\n (attr.value && attr.value.type !== \"mdxJsxAttributeValueExpression\")\n );\n }\n return attr.type !== \"mdxJsxExpressionAttribute\";\n });\n }\n }\n });\n };\n};\n","// MPL-2.0 — derived from next-mdx-remote (IBM). See LICENSE-MPL-2.0.\nimport type { Node } from \"unist\";\n\nconst BLOCKED_GLOBALS = [\n // Code execution\n \"eval\",\n \"Function\",\n \"AsyncFunction\",\n \"GeneratorFunction\",\n // Module system\n \"require\",\n \"module\",\n \"exports\",\n \"__dirname\",\n \"__filename\",\n // Runtime\n \"process\",\n \"global\",\n \"globalThis\",\n \"Reflect\",\n // File system / network\n \"child_process\",\n \"fs\",\n \"net\",\n \"http\",\n \"https\",\n \"vm\",\n \"worker_threads\",\n // Browser-like (available in Node/Deno)\n \"fetch\",\n \"setTimeout\",\n \"setInterval\",\n \"setImmediate\",\n \"queueMicrotask\",\n \"XMLHttpRequest\",\n];\n\nconst BLOCKED_PROPERTIES = [\n \"constructor\",\n \"prototype\",\n \"__proto__\",\n \"eval\",\n \"Reflect\",\n \"Function\",\n \"AsyncFunction\",\n \"GeneratorFunction\",\n \"require\",\n];\n\nfunction walk(node: any, blockedGlobals: string[], blockedProperties: string[]) {\n if (!node || typeof node !== \"object\") return;\n\n if (node.type === \"Identifier\" && blockedGlobals.includes(node.name)) {\n const parent = node.parent;\n const isProperty =\n parent?.type === \"MemberExpression\" && parent.property === node && !parent.computed;\n const isParam = parent?.type === \"FunctionDeclaration\" || parent?.type === \"FunctionExpression\";\n if (!isProperty && !isParam) {\n throw new Error(`Security: Access to '${node.name}' is not allowed`);\n }\n }\n\n // Block direct calls to blocked globals: eval(), Function(), fetch(), etc.\n if (\n node.type === \"CallExpression\" &&\n node.callee?.type === \"Identifier\" &&\n blockedGlobals.includes(node.callee.name)\n ) {\n throw new Error(`Security: ${node.callee.name}() calls are not allowed`);\n }\n\n // Block dynamic import(): import(\"node:fs\")\n if (node.type === \"ImportExpression\") {\n throw new Error(\"Security: Dynamic import() is not allowed\");\n }\n\n // Block tagged template literals on blocked globals: eval`...`\n if (\n node.type === \"TaggedTemplateExpression\" &&\n node.tag?.type === \"Identifier\" &&\n blockedGlobals.includes(node.tag.name)\n ) {\n throw new Error(`Security: ${node.tag.name}\\`...\\` tagged template is not allowed`);\n }\n\n // Block computed MemberExpression calls on any object identifier\n // Catches: Object[\"constructor\"](...), Object[\"con\"+\"structor\"](...), etc.\n if (\n node.type === \"CallExpression\" &&\n node.callee?.type === \"MemberExpression\" &&\n node.callee.computed\n ) {\n throw new Error(\"Security: Function calls via computed property access are not allowed\");\n }\n\n // Block non-computed property access to dangerous properties:\n // obj.constructor, obj.prototype, obj.__proto__\n if (node.type === \"MemberExpression\" && !node.computed) {\n const prop = node.property;\n if (prop?.type === \"Identifier\" && blockedProperties.includes(prop.name)) {\n throw new Error(`Security: .${prop.name} access is not allowed`);\n }\n }\n\n // Block new expressions: new Function(...)\n if (\n node.type === \"NewExpression\" &&\n node.callee?.type === \"Identifier\" &&\n blockedGlobals.includes(node.callee.name)\n ) {\n throw new Error(`Security: new ${node.callee.name}() is not allowed`);\n }\n\n for (const key in node) {\n if (key === \"parent\" || key === \"position\") continue;\n const value = node[key];\n if (Array.isArray(value)) {\n value.forEach((child: any) => {\n if (child && typeof child === \"object\") walk(child, blockedGlobals, blockedProperties);\n });\n } else if (value && typeof value === \"object\") {\n walk(value, blockedGlobals, blockedProperties);\n }\n }\n}\n\nexport const CreateRemoveDangerousCallsPlugin = (\n blockedGlobals?: string[],\n blockedProperties?: string[]\n) => {\n return () => (tree: Node) => {\n walk(tree, blockedGlobals ?? BLOCKED_GLOBALS, blockedProperties ?? BLOCKED_PROPERTIES);\n return tree;\n };\n};\n","// MPL-2.0 — derived from next-mdx-remote (IBM). See LICENSE-MPL-2.0.\nimport { compile } from \"@mdx-js/mdx\";\nimport { VFile } from \"vfile\";\nimport { matter } from \"vfile-matter\";\nimport { createFormattedMDXError } from \"./format-mdx-error.js\";\nimport { removeImportsExportsPlugin } from \"./plugins/remove-imports-exports.js\";\nimport { removeJavaScriptExpressions } from \"./plugins/remove-javascript-expressions.js\";\nimport { CreateRemoveDangerousCallsPlugin } from \"./plugins/remove-dangerous-javascript-expressions.js\";\nimport type { Pluggable } from \"unified\";\n\n/** @internal — re-exported from unified. */\ntype RemarkPlugins = Pluggable[];\ntype RehypePlugins = Pluggable[];\n\nexport type { MDXRemoteSerializeResult } from \"./types\";\n\nexport type SerializeOptions = {\n scope?: Record<string, unknown>;\n mdxOptions?: {\n remarkPlugins?: RemarkPlugins;\n rehypePlugins?: RehypePlugins;\n };\n parseFrontmatter?: boolean;\n /**\n * MDX compile output shape.\n * - `\"function-body\"` (default): JS function body string for `<MDXRemote>`.\n * - `\"program\"`: full ESM module source (imports + `export default MDXContent`)\n * for static bundling / hydration without `new Function`.\n * @default \"function-body\"\n */\n outputFormat?: \"function-body\" | \"program\";\n /**\n * MDX input format.\n * - `\"mdx\"` (default): JSX tags are parsed and resolve via the components map.\n * - `\"md\"`: plain markdown — authored JSX tags are NOT parsed (dropped,\n * content kept as text). Markdown directives (`:::`/`::`/`::::`) still\n * work; this is the v2 authoring contract (no JSX tags).\n * @default \"mdx\"\n */\n format?: \"mdx\" | \"md\";\n /**\n * Strip JavaScript expressions from MDX (default: true).\n * When true, removes all `{expression}` and JSX attribute expression nodes\n * before compilation. When false, expressions are preserved but a\n * security sanitizer audits the AST for dangerous patterns.\n * @default true\n */\n blockJS?: boolean;\n};\n\nexport type SerializeResult = {\n compiledSource: string;\n frontmatter: Record<string, unknown>;\n scope: Record<string, unknown>;\n};\n\nfunction getCompileOptions(\n mdxOptions: SerializeOptions[\"mdxOptions\"] = {},\n rsc = false,\n blockJS = true,\n outputFormat: NonNullable<SerializeOptions[\"outputFormat\"]> = \"function-body\",\n format: NonNullable<SerializeOptions[\"format\"]> = \"mdx\"\n) {\n const remarkPlugins = [\n ...(mdxOptions?.remarkPlugins ?? []),\n removeImportsExportsPlugin,\n ...(blockJS ? [removeJavaScriptExpressions] : []),\n // Defense-in-depth: audit remaining AST for dangerous patterns.\n CreateRemoveDangerousCallsPlugin(),\n ];\n\n return {\n ...mdxOptions,\n remarkPlugins,\n rehypePlugins: mdxOptions?.rehypePlugins ?? [],\n format,\n outputFormat,\n providerImportSource: rsc ? undefined : \"@mdx-js/react\",\n development: process.env.NODE_ENV !== \"production\",\n };\n}\n\n/**\n * Compile raw MDX string into a serialized result that can be rendered.\n */\nexport async function serialize(\n source: string,\n {\n scope = {},\n mdxOptions = {},\n parseFrontmatter = false,\n blockJS = true,\n outputFormat = \"function-body\",\n format = \"mdx\",\n }: SerializeOptions = {},\n rsc = false\n): Promise<SerializeResult> {\n const vfile = new VFile(source);\n\n if (parseFrontmatter) {\n matter(vfile, { strip: true });\n }\n\n let compiledSource: string;\n try {\n compiledSource = String(\n await compile(vfile, getCompileOptions(mdxOptions, rsc, blockJS, outputFormat, format))\n );\n } catch (error: any) {\n throw createFormattedMDXError(error, String(vfile));\n }\n\n return {\n compiledSource,\n frontmatter: (vfile.data.matter ?? {}) as Record<string, unknown>,\n scope,\n };\n}\n"],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
package/dist/utils.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { ClassValue } from
|
|
2
|
-
import { Node } from
|
|
3
|
-
|
|
4
|
-
interface ElementNode extends Node {
|
|
1
|
+
import { type ClassValue } from "clsx";
|
|
2
|
+
import type { Node } from "unist";
|
|
3
|
+
export interface ElementNode extends Node {
|
|
5
4
|
type: string;
|
|
6
5
|
tagName?: string;
|
|
7
6
|
properties?: Record<string, unknown> & {
|
|
@@ -14,14 +13,12 @@ interface ElementNode extends Node {
|
|
|
14
13
|
language?: string;
|
|
15
14
|
codeTitle?: string;
|
|
16
15
|
}
|
|
17
|
-
declare function cn(...inputs: ClassValue[]): string;
|
|
16
|
+
export declare function cn(...inputs: ClassValue[]): string;
|
|
18
17
|
/** Parse both `dd-MM-yyyy` and ISO 8601 date strings into a Date object. */
|
|
19
|
-
declare function parseDate(dateStr: string): Date;
|
|
20
|
-
declare function stringToDate(date: string | Date): Date;
|
|
18
|
+
export declare function parseDate(dateStr: string): Date;
|
|
19
|
+
export declare function stringToDate(date: string | Date): Date;
|
|
21
20
|
/** Format date to long format (e.g. "Thursday, April 5, 2026") */
|
|
22
|
-
declare function formatDate(dateStrOrDate: string | Date): string;
|
|
21
|
+
export declare function formatDate(dateStrOrDate: string | Date): string;
|
|
23
22
|
/** Format date to short format (e.g. "Apr 5, 2026") */
|
|
24
|
-
declare function formatDate2(dateStrOrDate: string | Date): string;
|
|
25
|
-
declare function toIsoDateOnly(dateStrOrDate: string | Date): string;
|
|
26
|
-
|
|
27
|
-
export { type ElementNode, cn, formatDate, formatDate2, parseDate, stringToDate, toIsoDateOnly };
|
|
23
|
+
export declare function formatDate2(dateStrOrDate: string | Date): string;
|
|
24
|
+
export declare function toIsoDateOnly(dateStrOrDate: string | Date): string;
|
package/dist/utils.js
CHANGED
|
@@ -1,17 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
import { clsx as e } from "clsx";
|
|
2
|
+
import { twMerge as t } from "tailwind-merge";
|
|
3
|
+
//#region src/utils.ts
|
|
4
|
+
function n(...n) {
|
|
5
|
+
return t(e(n));
|
|
6
|
+
}
|
|
7
|
+
function r(e) {
|
|
8
|
+
if (/^\d{4}-/.test(e)) return new Date(e);
|
|
9
|
+
let [t, n, r] = e.split("-").map(Number);
|
|
10
|
+
return new Date(r, n - 1, t);
|
|
11
|
+
}
|
|
12
|
+
function i(e) {
|
|
13
|
+
return e instanceof Date ? e : r(e);
|
|
14
|
+
}
|
|
15
|
+
function a(e) {
|
|
16
|
+
return i(e).toLocaleDateString("en-US", {
|
|
17
|
+
weekday: "long",
|
|
18
|
+
year: "numeric",
|
|
19
|
+
month: "long",
|
|
20
|
+
day: "numeric"
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function o(e) {
|
|
24
|
+
return i(e).toLocaleDateString("en-US", {
|
|
25
|
+
month: "short",
|
|
26
|
+
day: "numeric",
|
|
27
|
+
year: "numeric"
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function s(e) {
|
|
31
|
+
return i(e).toISOString().slice(0, 10);
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { n as cn, a as formatDate, o as formatDate2, r as parseDate, i as stringToDate, s as toIsoDateOnly };
|
|
35
|
+
|
|
17
36
|
//# sourceMappingURL=utils.js.map
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\nimport type { Node } from \"unist\";\n\nexport interface ElementNode extends Node {\n type: string;\n tagName?: string;\n properties?: Record<string, unknown> & {\n className?: string[] | string;\n raw?: string;\n };\n data?: Record<string, unknown>;\n children?: Node[];\n raw?: string;\n language?: string;\n codeTitle?: string;\n}\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/** Parse both `dd-MM-yyyy` and ISO 8601 date strings into a Date object. */\nexport function parseDate(dateStr: string): Date {\n if (/^\\d{4}-/.test(dateStr)) return new Date(dateStr);\n const [day, month, year] = dateStr.split(\"-\").map(Number);\n return new Date(year, month - 1, day);\n}\n\nexport function stringToDate(date: string | Date) {\n return date instanceof Date ? date : parseDate(date);\n}\n\n/** Format date to long format (e.g. \"Thursday, April 5, 2026\") */\nexport function formatDate(dateStrOrDate: string | Date): string {\n const date = stringToDate(dateStrOrDate);\n return date.toLocaleDateString(\"en-US\", {\n weekday: \"long\",\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n}\n\n/** Format date to short format (e.g. \"Apr 5, 2026\") */\nexport function formatDate2(dateStrOrDate: string | Date): string {\n const date = stringToDate(dateStrOrDate);\n return date.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n });\n}\n\nexport function toIsoDateOnly(dateStrOrDate: string | Date): string {\n const date = stringToDate(dateStrOrDate);\n return date.toISOString().slice(0, 10);\n}\n"],"mappings":";;;AAkBA,SAAgB,EAAG,GAAG,GAAsB;CAC1C,OAAO,EAAQ,EAAK,CAAM,CAAC;AAC7B;AAGA,SAAgB,EAAU,GAAuB;CAC/C,IAAI,UAAU,KAAK,CAAO,GAAG,OAAO,IAAI,KAAK,CAAO;CACpD,IAAM,CAAC,GAAK,GAAO,KAAQ,EAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;CACxD,OAAO,IAAI,KAAK,GAAM,IAAQ,GAAG,CAAG;AACtC;AAEA,SAAgB,EAAa,GAAqB;CAChD,OAAO,aAAgB,OAAO,IAAO,EAAU,CAAI;AACrD;AAGA,SAAgB,EAAW,GAAsC;CAE/D,OADa,EAAa,CACnB,CAAA,CAAK,mBAAmB,SAAS;EACtC,SAAS;EACT,MAAM;EACN,OAAO;EACP,KAAK;CACP,CAAC;AACH;AAGA,SAAgB,EAAY,GAAsC;CAEhE,OADa,EAAa,CACnB,CAAA,CAAK,mBAAmB,SAAS;EACtC,OAAO;EACP,KAAK;EACL,MAAM;CACR,CAAC;AACH;AAEA,SAAgB,EAAc,GAAsC;CAElE,OADa,EAAa,CACnB,CAAA,CAAK,YAAY,CAAC,CAAC,MAAM,GAAG,EAAE;AACvC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docubook/core",
|
|
3
|
-
"version": "2.0.0-
|
|
3
|
+
"version": "2.0.0-beta.2",
|
|
4
4
|
"description": "Shared MDX compile pipeline and markdown utilities for DocuBook",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -71,14 +71,14 @@
|
|
|
71
71
|
"@types/unist": "^3.0.3",
|
|
72
72
|
"mdast-util-directive": "^3.1.0",
|
|
73
73
|
"react": "^19.0.0",
|
|
74
|
-
"
|
|
74
|
+
"vite": "^8.2.1",
|
|
75
75
|
"typescript": "^5.9.3",
|
|
76
76
|
"unified": "^11.0.0"
|
|
77
77
|
},
|
|
78
78
|
"scripts": {
|
|
79
|
-
"build": "
|
|
79
|
+
"build": "pnpm run clean && vite build && tsc -p tsconfig.build.json",
|
|
80
80
|
"test": "vitest run",
|
|
81
81
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
82
|
-
"clean": "rm -rf dist"
|
|
82
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo"
|
|
83
83
|
}
|
|
84
84
|
}
|
package/dist/chunk-HZJLRYAI.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
// src/utils.ts
|
|
2
|
-
import { clsx } from "clsx";
|
|
3
|
-
import { twMerge } from "tailwind-merge";
|
|
4
|
-
function cn(...inputs) {
|
|
5
|
-
return twMerge(clsx(inputs));
|
|
6
|
-
}
|
|
7
|
-
function parseDate(dateStr) {
|
|
8
|
-
if (/^\d{4}-/.test(dateStr)) return new Date(dateStr);
|
|
9
|
-
const [day, month, year] = dateStr.split("-").map(Number);
|
|
10
|
-
return new Date(year, month - 1, day);
|
|
11
|
-
}
|
|
12
|
-
function stringToDate(date) {
|
|
13
|
-
return date instanceof Date ? date : parseDate(date);
|
|
14
|
-
}
|
|
15
|
-
function formatDate(dateStrOrDate) {
|
|
16
|
-
const date = stringToDate(dateStrOrDate);
|
|
17
|
-
return date.toLocaleDateString("en-US", {
|
|
18
|
-
weekday: "long",
|
|
19
|
-
year: "numeric",
|
|
20
|
-
month: "long",
|
|
21
|
-
day: "numeric"
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
function formatDate2(dateStrOrDate) {
|
|
25
|
-
const date = stringToDate(dateStrOrDate);
|
|
26
|
-
return date.toLocaleDateString("en-US", {
|
|
27
|
-
month: "short",
|
|
28
|
-
day: "numeric",
|
|
29
|
-
year: "numeric"
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
function toIsoDateOnly(dateStrOrDate) {
|
|
33
|
-
const date = stringToDate(dateStrOrDate);
|
|
34
|
-
return date.toISOString().slice(0, 10);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export {
|
|
38
|
-
cn,
|
|
39
|
-
parseDate,
|
|
40
|
-
stringToDate,
|
|
41
|
-
formatDate,
|
|
42
|
-
formatDate2,
|
|
43
|
-
toIsoDateOnly
|
|
44
|
-
};
|
|
45
|
-
//# sourceMappingURL=chunk-HZJLRYAI.js.map
|