@fumadocs/mdx-remote
Version:
The remote MDX files adapter for Fumadocs
140 lines (136 loc) • 4.51 kB
JavaScript
import { t as executeMdx$1 } from "./render-DHnSPAbU.js";
import * as Plugins from "fumadocs-core/mdx-plugins";
import { createProcessor } from "@mdx-js/mdx";
import matter from "gray-matter";
import { pathToFileURL } from "node:url";
//#region src/utils.ts
function pluginOption(def, options = []) {
const list = def(Array.isArray(options) ? options : []).filter(Boolean);
if (typeof options === "function") return options(list);
return list;
}
/**
* Parse frontmatter, currently powered by `gray-matter`
*/
function parseFrontmatter(content) {
const out = matter(content);
return {
frontmatter: out.data,
content: out.content
};
}
//#endregion
//#region src/compile.ts
function createCompiler(mdxOptions) {
let instance;
function getProcessor() {
if (instance) return instance;
let format = mdxOptions?.format;
if (!format || format === "detect") format = "mdx";
return instance = createProcessor({
...mdxOptions?.preset === "minimal" ? mdxOptions : getCompileOptions(mdxOptions),
format
});
}
return {
async render(compiled, scope, filePath) {
return executeMdx$1(compiled, {
scope,
baseUrl: filePath ? pathToFileURL(filePath) : void 0,
jsxRuntime: mdxOptions?.development ? await import("react/jsx-dev-runtime") : void 0
});
},
async compileFile(from) {
return getProcessor().process(from);
},
async compile(options) {
const { scope = {}, skipRender } = options;
const { frontmatter, content } = parseFrontmatter(options.source);
const file = await this.compileFile({
value: content,
path: options.filePath,
data: { frontmatter }
});
const compiled = String(file);
const exports = !skipRender ? await this.render(compiled, scope, options.filePath) : null;
return {
vfile: file,
compiled,
frontmatter,
async body(props) {
if (!exports) throw new Error("Body cannot be rendered when `skipRender` is set to true");
return exports.default({ components: {
...options.components,
...props.components
} });
},
toc: exports?.toc ?? file.data.toc,
exports
};
}
};
}
/**
* @deprecated Use `createCompiler()` API instead, this function will always create a new compiler instance.
*/
async function compileMDX(options) {
return createCompiler(options.mdxOptions).compile(options);
}
function getCompileOptions({ preset: _, rehypeCodeOptions, remarkImageOptions, rehypeTocOptions, remarkHeadingOptions, remarkCodeTabOptions, remarkNpmOptions, imageDir = "./public", ...options } = {}) {
function getPlugin(name) {
return name in Plugins ? Plugins[name] : null;
}
const remarkGfm = getPlugin("remarkGfm");
const remarkHeading = getPlugin("remarkHeading");
const remarkCodeTab = getPlugin("remarkCodeTab");
const remarkNpm = getPlugin("remarkNpm");
const remarkImage = getPlugin("remarkImage");
const rehypeCode = getPlugin("rehypeCode");
const rehypeToc = getPlugin("rehypeToc");
return {
...options,
outputFormat: "function-body",
remarkPlugins: pluginOption((v) => [
remarkGfm,
remarkHeading && remarkHeadingOptions !== false ? [remarkHeading, remarkHeadingOptions] : null,
remarkImage && remarkImageOptions !== false ? [remarkImage, {
useImport: false,
publicDir: imageDir,
...remarkImageOptions
}] : null,
remarkCodeTab && remarkCodeTabOptions !== false ? [remarkCodeTab, remarkCodeTabOptions] : null,
remarkNpm && remarkNpmOptions !== false ? [remarkNpm, remarkNpmOptions] : null,
...v
], options.remarkPlugins),
rehypePlugins: pluginOption((v) => [
rehypeCode && rehypeCodeOptions !== false ? [rehypeCode, rehypeCodeOptions] : null,
rehypeToc && rehypeTocOptions !== false ? [rehypeToc, rehypeTocOptions] : null,
...v
], options.rehypePlugins)
};
}
//#endregion
//#region src/index.ts
/**
* @deprecated Use `compiler.render` instead
*/
async function executeMdx(compiled, scope, baseUrl) {
let jsxRuntime;
if (process.env.NODE_ENV === "production") jsxRuntime = await import("react/jsx-runtime");
else jsxRuntime = await import("react/jsx-dev-runtime");
const fullScope = {
opts: {
...jsxRuntime,
baseUrl
},
...scope
};
const values = Object.values(fullScope);
const params = Object.keys(fullScope);
params.push(`return (async () => { ${compiled} })()`);
const hydrateFn = new Function(...params);
return await hydrateFn.apply(hydrateFn, values);
}
//#endregion
export { compileMDX, createCompiler, executeMdx, parseFrontmatter };
//# sourceMappingURL=index.js.map