UNPKG

fumadocs-mdx

Version:

The built-in source for Fumadocs

353 lines (343 loc) 10.7 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/config/index.ts var config_exports = {}; __export(config_exports, { defineCollections: () => defineCollections, defineConfig: () => defineConfig, defineDocs: () => defineDocs, frontmatterSchema: () => frontmatterSchema, getDefaultMDXOptions: () => getDefaultMDXOptions, metaSchema: () => metaSchema, remarkInclude: () => remarkInclude }); module.exports = __toCommonJS(config_exports); // src/config/zod-4.ts var import_zod = require("zod"); var metaSchema = import_zod.z.object({ title: import_zod.z.string().optional(), pages: import_zod.z.array(import_zod.z.string()).optional(), description: import_zod.z.string().optional(), root: import_zod.z.boolean().optional(), defaultOpen: import_zod.z.boolean().optional(), icon: import_zod.z.string().optional() }); var frontmatterSchema = import_zod.z.object({ title: import_zod.z.string(), description: import_zod.z.string().optional(), icon: import_zod.z.string().optional(), full: import_zod.z.boolean().optional(), // Fumadocs OpenAPI generated _openapi: import_zod.z.looseObject({}).optional() }); // src/config/define.ts function defineCollections(options) { return options; } function defineDocs(options) { if (!options) console.warn( "[`source.config.ts`] Deprecated: please pass options to `defineDocs()` and specify a `dir`." ); const dir = options?.dir ?? "content/docs"; return { type: "docs", dir, docs: defineCollections({ type: "doc", dir, schema: frontmatterSchema, ...options?.docs }), meta: defineCollections({ type: "meta", dir, schema: metaSchema, ...options?.meta }) }; } function defineConfig(config = {}) { return config; } // src/utils/mdx-options.ts var plugins = __toESM(require("fumadocs-core/mdx-plugins"), 1); // src/mdx-plugins/remark-exports.ts var import_estree_util_value_to_estree = require("estree-util-value-to-estree"); function remarkMdxExport({ values }) { return (tree, vfile) => { for (const name of values) { if (!(name in vfile.data)) return; tree.children.unshift(getMdastExport(name, vfile.data[name])); } }; } function getMdastExport(name, value) { return { type: "mdxjsEsm", value: "", data: { estree: { type: "Program", sourceType: "module", body: [ { type: "ExportNamedDeclaration", specifiers: [], source: null, declaration: { type: "VariableDeclaration", kind: "let", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name }, init: (0, import_estree_util_value_to_estree.valueToEstree)(value) } ] } } ] } } }; } // src/utils/mdx-options.ts function pluginOption(def, options = []) { const list = def(Array.isArray(options) ? options : []).filter( Boolean ); if (typeof options === "function") { return options(list); } return list; } function getDefaultMDXOptions({ valueToExport = [], rehypeCodeOptions, remarkImageOptions, remarkHeadingOptions, remarkStructureOptions, remarkCodeTabOptions, remarkNpmOptions, _withoutBundler = false, ...mdxOptions }) { const mdxExports = [ "structuredData", "frontmatter", "lastModified", ...valueToExport ]; const remarkPlugins = pluginOption( (v) => [ plugins.remarkGfm, [ plugins.remarkHeading, { generateToc: false, ...remarkHeadingOptions } ], remarkImageOptions !== false && [ plugins.remarkImage, { ...remarkImageOptions, useImport: _withoutBundler ? false : remarkImageOptions?.useImport } ], "remarkCodeTab" in plugins && remarkCodeTabOptions !== false && [ plugins.remarkCodeTab, remarkCodeTabOptions ], "remarkNpm" in plugins && remarkNpmOptions !== false && [plugins.remarkNpm, remarkNpmOptions], ...v, remarkStructureOptions !== false && [ plugins.remarkStructure, remarkStructureOptions ], [remarkMdxExport, { values: mdxExports }] ], mdxOptions.remarkPlugins ); const rehypePlugins = pluginOption( (v) => [ rehypeCodeOptions !== false && [plugins.rehypeCode, rehypeCodeOptions], ...v, plugins.rehypeToc ], mdxOptions.rehypePlugins ); return { ...mdxOptions, outputFormat: _withoutBundler ? "function-body" : mdxOptions.outputFormat, remarkPlugins, rehypePlugins }; } // src/mdx-plugins/remark-include.ts var import_unist_util_visit = require("unist-util-visit"); var path = __toESM(require("path"), 1); var fs = __toESM(require("fs/promises"), 1); // src/utils/fuma-matter.ts var import_js_yaml = require("js-yaml"); var regex = /^---\r?\n(.+?)\r?\n---\r?\n/s; function fumaMatter(input) { const output = { matter: "", data: {}, content: input }; const match = regex.exec(input); if (!match) { return output; } output.matter = match[1]; output.content = input.slice(match[0].length); const loaded = (0, import_js_yaml.load)(output.matter); output.data = loaded ?? {}; return output; } // src/mdx-plugins/remark-include.ts function flattenNode(node) { if ("children" in node) return node.children.map((child) => flattenNode(child)).join(""); if ("value" in node) return node.value; return ""; } function parseSpecifier(specifier) { const idx = specifier.lastIndexOf("#"); if (idx === -1) return { file: specifier }; return { file: specifier.slice(0, idx), section: specifier.slice(idx + 1) }; } function extractSection(root, section) { for (const node of root.children) { if (node.type === "mdxJsxFlowElement" && node.name === "section" && node.attributes.some( (attr) => attr.type === "mdxJsxAttribute" && attr.name === "id" && attr.value === section )) { return { type: "root", children: node.children }; } } } function remarkInclude() { const TagName = "include"; async function update(tree, directory, data) { const queue = []; (0, import_unist_util_visit.visit)( tree, ["mdxJsxFlowElement", "mdxJsxTextElement"], (node, _, parent) => { let specifier; const params = {}; if ((node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement") && node.name === TagName) { const value = flattenNode(node); if (value.length > 0) { for (const attr of node.attributes) { if (attr.type === "mdxJsxAttribute" && (typeof attr.value === "string" || attr.value === null)) { params[attr.name] = attr.value; } } specifier = value; } } if (!specifier) return; const { file, section } = parseSpecifier(specifier); const targetPath = path.resolve( "cwd" in params ? process.cwd() : directory, file ); const asCode = params.lang || !file.endsWith(".md") && !file.endsWith(".mdx"); queue.push( fs.readFile(targetPath).then((buffer) => buffer.toString()).then(async (content) => { data._compiler?.addDependency(targetPath); if (asCode) { const lang = params.lang ?? path.extname(file).slice(1); Object.assign(node, { type: "code", lang, meta: params.meta, value: content, data: {} }); return; } const processor = data._processor ? data._processor.getProcessor( targetPath.endsWith(".md") ? "md" : "mdx" ) : this; let parsed = processor.parse(fumaMatter(content).content); if (section) { const extracted = extractSection(parsed, section); if (!extracted) throw new Error( `Cannot find section ${section} in ${file}, make sure you have encapsulated the section in a <section id="${section}"> tag` ); parsed = extracted; } await update.call( processor, parsed, path.dirname(targetPath), data ); Object.assign( parent && parent.type === "paragraph" ? parent : node, parsed ); }).catch((e) => { throw new Error( `failed to read file ${targetPath} ${e instanceof Error ? e.message : String(e)}`, { cause: e } ); }) ); return "skip"; } ); await Promise.all(queue); } return async (tree, file) => { await update.call(this, tree, path.dirname(file.path), file.data); }; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { defineCollections, defineConfig, defineDocs, frontmatterSchema, getDefaultMDXOptions, metaSchema, remarkInclude });