Relevant source files
The following files were used as context for generating this wiki page:
- packages/mdx-remote/src/render.ts
- packages/mdx-remote/src/index.ts
- packages/local-md/src/eval-estree-expression/index.ts
- packages/mdx-remote/src/client/index.ts
- packages/mdx-remote/src/compile.ts
- packages/mdx/src/runtime/dynamic.ts
- packages/mdx/src/runtime/browser.tsx
- packages/core/src/content/md.ts
- packages/mdx/src/loaders/mdx/remark-include.ts
- packages/local-md/src/md/compiler.ts
- packages/local-md/src/md/renderer.ts
- packages/mdx/src/webpack/mdx.ts
- packages/mdx/src/plugins/index-file.ts
- packages/mdx/src/loaders/mdx/index.ts
- packages/core/src/mdx-plugins/remark-llms.ts
- packages/local-md/src/js/executor-native.ts
- packages/preview/src/lib/md.ts
- packages/preview/src/pages/...slugs.tsx
- packages/radix-ui/src/mdx.tsx
- packages/mdx/src/loaders/mdx/build-mdx.ts
- packages/local-md/src/client.ts
- packages/mdx/src/next/index.ts
- packages/core/src/content/mdx/preset-runtime.ts
- packages/mdx/src/runtime/server.ts
- packages/preview/src/components/markdown.tsx
- packages/base-ui/src/mdx.tsx
- packages/core/src/mdx-plugins/remark-mdx-files.ts
- packages/base-ui/src/mdx.server.tsx
- packages/core/src/mdx-plugins/remark-llms.runtime.ts
- packages/radix-ui/src/mdx.server.tsx
Overview
MDX Runtime Compilation facilitates the parsing, frontmatter extraction, compilation, and evaluation of MDX documents on demand across server and browser runtimes. It leverages the MDX processor, Unified transformation pipelines, and custom runtime execution functions to convert raw string inputs into executable React components, structured table-of-contents data, and metadata exports. By coordinating dynamic doc collections, standard schema validation, and custom component binding, the system enables flexible documentation rendering across diverse UI frameworks and bundlers.
Sources: packages/mdx-remote/src/compile.ts:60-121, packages/mdx-remote/src/render.ts:17-33, packages/mdx/src/runtime/dynamic.ts:47-122, packages/mdx/src/runtime/browser.tsx:58-76, packages/mdx/src/runtime/server.ts:72-241
Remote Compilation Architecture
Compiler Factory and Processor Initialization
The createCompiler function initializes and caches a unified MDX processor instance configured via createProcessor. It accepts either a minimal configuration or a full preset configuration through CompilerOptions. If format options are omitted or set to 'detect', the processor defaults to MDX format.
export function createCompiler(mdxOptions?: CompilerOptions) {
let instance: ReturnType<typeof createProcessor> | undefined;
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,
}));
}Sources: packages/mdx-remote/src/compile.ts:60-73
The compilation pipeline processes raw source strings by first extracting frontmatter via parseFrontmatter. It then feeds the content body into the cached processor along with the file path and extracted frontmatter data.
async compile<Frontmatter extends object = Record<string, unknown>>(
options: CompileMDXOptions,
): Promise<CompileMDXResult<Frontmatter>> {
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);Sources: packages/mdx-remote/src/compile.ts:89-102
Warning
Setting skipRender to true on CompileMDXOptions will bypass the execution phase, leaving exports as null and throwing an error if the resulting body function is invoked.
Sources: packages/mdx-remote/src/compile.ts:44-48, packages/mdx-remote/src/compile.ts:109-115
Execution Scope and Function Hydration
Once the MDX text is compiled into function body string output, executeMdx constructs a dynamic asynchronous function via AsyncFunction. It merges scope options, JSX runtimes, and base URLs into an opts object, exposing remaining scope properties as arguments to the generated function.
export async function executeMdx(compiled: string, options: Options = {}) {
const { opts: scopeOpts, ...scope } = options.scope ?? {};
const fullScope = {
opts: {
...(scopeOpts as object),
...(options.jsxRuntime ?? jsxRuntimeDefault),
baseUrl: options.baseUrl,
},
...scope,
};
const hydrateFn = new AsyncFunction(...Object.keys(fullScope), compiled);
return (await hydrateFn.apply(hydrateFn, Object.values(fullScope))) as {
default: MdxContent;
toc?: TOCItemType[];
};
}Sources: packages/mdx-remote/src/render.ts:17-33
| Option Key | Default / Source | Purpose |
|---|---|---|
scope | {} | Custom variables and context injected into the MDX execution scope. |
baseUrl | pathToFileURL(filePath) | Resolves relative file paths for remote compilation contexts. |
jsxRuntime | react/jsx-runtime (or dev runtime) | Supplies JSX element creation functions during component hydration. |
Sources: packages/mdx-remote/src/render.ts:8-12, packages/mdx-remote/src/compile.ts:76-81
Note
The synchronous counterpart executeMdxSync uses a standard synchronous Function constructor instead of AsyncFunction, evaluating compiled outputs immediately when asynchronous evaluation is not required.
Sources: packages/mdx-remote/src/render.ts:35-52
Client-Side Evaluation and Component Injection
Asynchronous and Synchronous Hydration Functions
Client runtimes execute compiled MDX bundle strings by constructing dynamic functions via executeMdx and executeMdxSync. The executeMdx function uses an asynchronous function constructor derived from executeMdx0 or executeMdx, while executeMdxSync utilizes a standard Function constructor to evaluate bundles synchronously.
const AsyncFunction: new (...args: string[]) => (...args: unknown[]) => Promise<unknown> =
Object.getPrototypeOf(executeMdx).constructor;
export async function executeMdx(compiled: string, options: Options = {}) {
const { opts: scopeOpts, ...scope } = options.scope ?? {};
const fullScope = {
opts: {
...(scopeOpts as object),
...(options.jsxRuntime ?? jsxRuntimeDefault),
baseUrl: options.baseUrl,
},
...scope,
};
const hydrateFn = new AsyncFunction(...Object.keys(fullScope), compiled);
return (await hydrateFn.apply(hydrateFn, Object.values(fullScope))) as {
default: MdxContent;
toc?: TOCItemType[];
};
}Sources: packages/mdx-remote/src/render.ts:14-33
| Hydration Function | Constructor Type | Return Signature |
|---|---|---|
executeMdx | AsyncFunction | Promise<{ default: MdxContent; toc?: TOCItemType[] }> |
executeMdxSync | Function | { default: MdxContent; toc?: TOCItemType[] } |
Sources: packages/mdx-remote/src/render.ts:14-15, packages/mdx-remote/src/render.ts:28-32, packages/mdx-remote/src/render.ts:46-51
Note
The legacy executeMdx implementation in packages/mdx-remote/src/index.ts automatically selects between react/jsx-runtime and react/jsx-dev-runtime based on process.env.NODE_ENV === 'production'.
Sources: packages/mdx-remote/src/index.ts:10-17
Scope Merging and Component Bindings
Both executeMdx and executeMdxSync accept an Options object containing scope variables, base URLs, and custom JSX runtimes. The options merge property values into an opts object, exposing remaining scope properties as arguments to the generated hydration function.
export async function executeMdx(compiled: string, options: Options = {}) {
const { opts: scopeOpts, ...scope } = options.scope ?? {};
const fullScope = {
opts: {
...(scopeOpts as object),
...(options.jsxRuntime ?? jsxRuntimeDefault),
baseUrl: options.baseUrl,
},
...scope,
};Sources: packages/mdx-remote/src/render.ts:17-26
Warning
Failing to supply a valid jsxRuntime option defaults execution to jsxRuntimeDefault (react/jsx-runtime), which may cause runtime errors if development-only JSX annotations are required by the compiled bundle.
Sources: packages/mdx-remote/src/render.ts:4-4, packages/mdx-remote/src/render.ts:22-22, packages/mdx-remote/src/render.ts:40-40
The resulting MdxContent component accepts optional components bindings matching MDXComponents alongside table-of-contents data structured as TOCItemType[].
import type { MDXComponents } from 'mdx/types';
import type { TOCItemType } from 'fumadocs-core/toc';
import type { FC } from 'react';
import jsxRuntimeDefault from 'react/jsx-runtime';
export type MdxContent = FC<{ components?: MDXComponents }>;Sources: packages/mdx-remote/src/render.ts:1-6, packages/mdx-remote/src/render.ts:29-32
Dynamic Doc Collection Runtime
On-Demand Collection Initialization and Execution
The runtime compilation engine initializes dynamic documentation collections using dynamic and server modules. The dynamic function initializes core configurations via createCore and builds configuration exports from the working directory using buildConfig.
export async function dynamic<Config, TC extends InternalTypeConfig>(
configExports: Config,
coreOptions: CoreOptions,
serverOptions?: ServerOptions,
) {
const core = createCore(coreOptions);
await core.init({
config: buildConfig(configExports as Record<string, unknown>, process.cwd()),
});Sources: packages/mdx/src/runtime/dynamic.ts:47-55
Note
The getDocCollection utility validates collection existence, retrieving either standard documentation arrays or single documentation entries based on the collection type definition.
Sources: packages/mdx/src/runtime/dynamic.ts:59-65
Lazy entry compilation reads raw file content via node:fs/promises, strips frontmatter metadata using the frontmatter utility, and compiles MDX through buildMDX in runtime environment mode. The compiled output string is then evaluated using an asynchronous function constructor initialized by executeMdx.
async function compile({ info, data }: LazyEntry<unknown>) {
let content = await fs.readFile(info.fullPath, 'utf-8');
content = frontmatter(content).content;
const compiled = await buildMDX(core, collection, {
filePath: info.fullPath,
source: content,
frontmatter: data as Record<string, unknown>,
isDevelopment: false,
environment: 'runtime',
});
return (await executeMdx(String(compiled.value), {
baseUrl: pathToFileURL(info.fullPath),
})) as CompiledMDXProperties;
}Sources: packages/mdx/src/runtime/dynamic.ts:71-86
| Execute Option | Type | Purpose |
|---|---|---|
scope | Record<string, unknown> | Injected variables and options scope for MDX execution |
baseUrl | string | URL | File URL reference for relative asset resolution |
jsxRuntime | unknown | Custom JSX runtime fallback overriding default imports |
Sources: packages/mdx/src/runtime/dynamic.ts:22-26, packages/mdx/src/runtime/dynamic.ts:33-39
Server Document Mapping and Lazy Collections
The server module provides utility factories including fileInfo, mapDocData, and createDocMethods to construct document metadata and method bindings for file entries. Passthrough properties defined in server options are explicitly mapped into document data records alongside body contents, table-of-contents trees, and structured data extracts.
export function server<Config, TC extends InternalTypeConfig>(options: ServerOptions = {}) {
const { doc: { passthroughs: docPassthroughs = [] } = {} } = options;
function fileInfo(file: string, base: string): FileInfo {
if (file.startsWith('./')) {
file = file.slice(2);
}
return {
path: file,
fullPath: path.join(base, file),
};
}
function mapDocData(entry: CompiledMDXProperties): DocData {
const data: DocData = {
body: entry.default,
toc: entry.toc,
structuredData: entry.structuredData,
_exports: entry as unknown as Record<string, unknown>,
};
for (const key of docPassthroughs) {
// @ts-expect-error -- handle passthrough properties
data[key] = entry[key];
}
return data;
}Sources: packages/mdx/src/runtime/server.ts:72-100
Warning
Calling getText('processed') or getMDAST() on document methods throws an error unless includeProcessedMarkdown or includeMDAST are enabled in the collection configuration.
Sources: packages/mdx/src/runtime/server.ts:296-310
Collections support both eager and lazy loading variants through doc, docLazy, docs, docsLazy, and meta methods. Lazy execution caches compilation promises per entry, preventing redundant file reads and MDX build steps during subsequent document retrievals.
for (const entry of entries) {
head[entry.info.path] = () => entry.data;
let cachedResult: Promise<CompiledMDXProperties> | undefined;
body[entry.info.path] = () => (cachedResult ??= compile(entry));
}
return { head, body };
}Sources: packages/mdx/src/runtime/dynamic.ts:88-95, packages/mdx/src/runtime/server.ts:126-155
The toFumadocsSource function aggregates page and metadata items into a unified virtual file structure for downstream source consumers, applying optional base directory paths to all registered virtual file entries.
export function toFumadocsSource<
Page extends DocMethods & PageData,
Meta extends MetaMethods & MetaData,
>(
pages: Page[],
metas: Meta[],
options?: ToFumadocsSourceOptions,
): Source<{
pageData: Page;
metaData: Meta;
}> {
const baseDir = options?.baseDir;
const files: VirtualFile<{
pageData: Page;
metaData: Meta;
}>[] = [];
for (const entry of pages) {
files.push({
type: 'page',
path: baseDir ? path.join(baseDir, entry.info.path) : entry.info.path,
absolutePath: entry.info.fullPath,
data: entry,
});
}
for (const entry of metas) {
files.push({
type: 'meta',
path: baseDir ? path.join(baseDir, entry.info.path) : entry.info.path,
absolutePath: entry.info.fullPath,
data: entry,
});
}
return {
files,
};
}Sources: packages/mdx/src/runtime/server.ts:243-281
Browser Execution and Client Loaders
Client Loader Creation and Cache Sharing
The browser runtime exports the browser factory and createClientLoader utility to manage compiled MDX file entries and render components within React client environments. To prevent duplicate chunks generated by code-splitting frameworks such as Tanstack Start from fracturing state, createClientLoader accepts an optional id configuration option to share document preloads across multiple instances through a global loaderStore map.
const loaderStore = new Map<
string,
{
preloaded: Map<string, CompiledMDXProperties>;
}
>();
export function createClientLoader<
Doc = CompiledMDXProperties,
Props extends object | undefined = undefined,
>(
globEntries: Record<string, () => Promise<Doc>>,
options: ClientLoaderOptions<Doc, Props>,
): ClientLoader<Doc, Props> {
const { id = '', component: useRenderer } = options;
const renderers: Record<string, FC<Props>> = {};
const loaders = new Map<string, () => Promise<Doc>>();
const store = loaderStore.get(id) ?? {
preloaded: new Map(),
};
loaderStore.set(id, store);
Sources: packages/mdx/src/runtime/browser.tsx:78-99
Note
File path keys registered in glob entries are normalized by stripping leading ./ prefixes to ensure consistent cache lookups regardless of glob path syntax.
Sources: packages/mdx/src/runtime/browser.tsx:100-102
Standard Schema Integration and Renderer Methods
The doc method on the browser collection entry infers frontmatter output types via @standard-schema/spec while wrapping raw glob entries and forwarding options to createClientLoader.
export function browser<Config, TC extends InternalTypeConfig>() {
return {
doc<Name extends keyof Config & string>(
_name: Name,
glob: Record<string, () => Promise<unknown>>,
) {
const out: DocCollectionEntry = {
raw: glob as DocCollectionEntry['raw'],
createClientLoader({ id = _name as string, ...options }) {
return createClientLoader(this.raw, { id, ...options });
},
};
return out as Config[Name] extends DocCollection<infer Schema> | DocsCollection<infer Schema>
? DocCollectionEntry<Name, StandardSchemaV1.InferOutput<Schema>, TC>
: never;
},Sources: packages/mdx/src/runtime/browser.tsx:58-74
Client loaders return an interface containing three core methods for retrieving and rendering documentation entries: preload, getComponent, and useContent.
| Method | Parameters | Return Type | Description |
|---|---|---|---|
preload | path: string | Promise<Doc> | Asynchronously fetches and caches raw document content into the store |
getComponent | path: string | FC<Props> | Returns a React functional component that renders the document using React's use() hook |
useContent | path: string, props?: Props | ReactNode | Directly renders the document component populated with the provided properties |
Sources: packages/mdx/src/runtime/browser.tsx:28-40, packages/mdx/src/runtime/browser.tsx:125-138
Warning
Requesting a path that does not exist in the available glob entries throws an error directly from getLoader during resolution.
Sources: packages/mdx/src/runtime/browser.tsx:104-109
Runtime Plugin Presets and Execution
MDX Preset Configuration and Default Plugins
The mdxPreset function asynchronous helper builds and configures ProcessorOptions for unified and MDX pipelines by resolving default remark and rehype plugins alongside custom overrides. By default, the output format is set to function-body, and standard plugins can be disabled by passing false to their respective option flags in MDXRuntimePresetOptions.
| Preset Option | Default State | Associated Module / Plugin | Configuration Object |
|---|---|---|---|
remarkHeadingOptions | Enabled (unless false) | @/mdx-plugins/remark-heading | { generateToc: false, ...remarkHeadingOptions } |
remarkImageOptions | Enabled (unless false) | @/mdx-plugins/remark-image | remarkImageOptions |
remarkCodeTabOptions | Enabled (unless false) | @/mdx-plugins/remark-code-tab | remarkCodeTabOptions |
remarkNpmOptions | Enabled (unless false) | @/mdx-plugins/remark-npm | remarkNpmOptions |
remarkStructureOptions | Enabled (unless false) | @/mdx-plugins/remark-structure | { exportAs: 'structuredData', ...remarkStructureOptions } |
rehypeCodeOptions | Enabled (unless false) | @/mdx-plugins/rehype-code | rehypeCodeOptions |
remarkPlugins / rehypePlugins | Resolves v | remark-gfm (remark), @/mdx-plugins/rehype-toc (rehype) | User-defined or resolved via resolvePlugins |
export async function mdxPreset(options: MDXRuntimePresetOptions = {}): Promise<ProcessorOptions> {
const {
rehypeCodeOptions,
remarkImageOptions,
remarkHeadingOptions,
remarkStructureOptions,
remarkCodeTabOptions,
remarkNpmOptions,
outputFormat = 'function-body',
...mdxOptions
} = options;
const remarkPlugins = await resolvePlugins(
(v) => [
import('remark-gfm').then((mod) => mod.default),
remarkHeadingOptions !== false &&
import('@/mdx-plugins/remark-heading').then((mod) => [
mod.remarkHeading,
{
generateToc: false,
...remarkHeadingOptions,
},
]),
remarkImageOptions !== false &&
import('@/mdx-plugins/remark-image').then((mod) => [mod.remarkImage, remarkImageOptions]),
remarkCodeTabOptions !== false &&
import('@/mdx-plugins/remark-code-tab').then((mod) => [
mod.remarkCodeTab,
remarkCodeTabOptions,
]),
remarkNpmOptions !== false &&
import('@/mdx-plugins/remark-npm').then((mod) => [mod.remarkNpm, remarkNpmOptions]),
...v,
remarkStructureOptions !== false &&
import('@/mdx-plugins/remark-structure').then((mod) => [
mod.remarkStructure,
{
exportAs: 'structuredData',
...remarkStructureOptions,
} satisfies Plugins.StructureOptions,
]),
],
mdxOptions.remarkPlugins,
);
const rehypePlugins = await resolvePlugins(
(v) => [
rehypeCodeOptions !== false &&
import('@/mdx-plugins/rehype-code').then((mod) => [mod.rehypeCode, rehypeCodeOptions]),
...v,
import('@/mdx-plugins/rehype-toc').then((mod) => mod.rehypeToc),
],
mdxOptions.rehypePlugins,
);
return {
...mdxOptions,
outputFormat,
remarkPlugins,
rehypePlugins,
};
}Sources: packages/core/src/content/mdx/preset-runtime.ts:23-84
Note
The remark heading plugin explicitly forces generateToc: false by default within the preset runtime, separating table-of-contents generation into the rehype TOC pipeline.
Sources: packages/core/src/content/mdx/preset-runtime.ts:38-45
File Tree Transformation and Auto-Files Parsing
The remarkMdxFiles transformer parses code blocks with the files language identifier or auto-files JSX flow elements into MDX component structures (<Files />, <Folder />, and <File />). The parseFileTree helper splits code lines, tracks indentation depth using standard Unix or Windows line endings, and builds hierarchical folder-file relationships. When encountering <auto-files> elements, the transformer extracts dir, pattern, and defaultOpenAll attributes, utilizing tinyglobby to scan directories relative to the virtual file's parent directory or CWD.
function parseFileTree(code: string) {
const lines = code.split(/\r?\n/);
const stack = new Map<number, Node>();
for (const line of lines) {
let depth = 0;
let name = line;
let match: RegExpMatchArray | null;
while ((match = /(?:├──|│|└──)\s*/.exec(name))) {
name = name.slice(match[0].length);
depth++;
}
if (!name) continue;
const node: Node = name.endsWith('/')
? { type: 'folder', name, children: [], depth }
: { type: 'file', name, depth };
let parent: Node | undefined;
for (let i = depth - 1; i >= 0 && !parent; i--) {
parent = stack.get(i);
}
stack.set(depth, node);
if (!parent) continue;
if (parent.type === 'file') {
Object.assign(parent, {
type: 'folder',
children: [],
});
}
(parent as FolderNode).children.push(node);
}
return stack.get(0);
}
function defaultToMDX(node: Node, options: ToMdxOptions, depth = 0): MdxJsxFlowElement {
if (depth === 0) {
return {
type: 'mdxJsxFlowElement',
name: 'Files',
attributes: [],
children: [defaultToMDX(node, options, depth + 1)],
};
}
const attributes: MdxJsxAttribute[] = [
{ type: 'mdxJsxAttribute', name: 'name', value: node.name },
];
if (node.type === 'file') {
return {
type: 'mdxJsxFlowElement',
attributes,
children: [],
name: 'File',
};
}
if (options.defaultOpenAll) {
attributes.push({
type: 'mdxJsxAttribute',
name: 'defaultOpen',
value: null,
});
}
return {
type: 'mdxJsxFlowElement',
attributes,
name: 'Folder',
children: node.children.map((item) => defaultToMDX(item, options, depth + 1)),
};
}
/**
*Sources: packages/core/src/mdx-plugins/remark-mdx-files.ts:40-162
Warning
Omitting the pattern attribute on an <auto-files> element triggers an immediate failure on the virtual file (file.fail) at the node's exact AST position.
Sources: packages/core/src/mdx-plugins/remark-mdx-files.ts:146-156
Placeholder Rendering and Serialization
The renderPlaceholder runtime function evaluates delimited control strings matching the control regex /\0(.+?)\0/gs, parsing inner JSON payloads into PlaceholderData objects containing name, attributes, and children. If nested child blocks contain text, renderPlaceholder executes recursively. If a matching renderer exists in the renderers dictionary, the placeholder output is replaced with the renderer's return value; otherwise, it falls back to the raw child text or the original match block upon a JSON parsing error.
const regex = /\0(.+?)\0/gs;
export async function renderPlaceholder(
text: string,
renderers: Record<string, (data: PlaceholderData) => Awaitable<string>>,
): Promise<string> {
let out = '';
let idx = 0;
for (const match of text.matchAll(regex)) {
out += text.slice(idx, match.index);
const inner = match[1];
try {
const data = JSON.parse(inner) as PlaceholderData;
const renderer = data.name && renderers[data.name];
if (data.children.trim()) {
data.children = await renderPlaceholder(data.children, renderers);
}
if (renderer) {
out += await renderer(data);
} else {
out += data.children;
}
} catch {
out += match[0];
}
idx = match.index + match[0].length;
}
out += text.slice(idx);
return out;Sources: packages/core/src/mdx-plugins/remark-llms.runtime.ts:10-42
Preview and Dynamic Rendering Integration
Markdown Compiler Setup and Plugin Pipelines
The markdown compiler pipeline is configured via createMarkdownCompiler, which accepts remarkPlugins, rehypePlugins, and remarkRehypeOptions. In preview environments, the processor integrates remarkGfm, remarkMath, remarkMdxMermaid, remarkHeading, remarkNpm, and remarkCodeTab, alongside rehypeKatex, rehypeCode, and rehypeToc with { exportToc: { as: 'data' } }.
const compiler = createMarkdownCompiler({
remarkPlugins: [
remarkGfm,
remarkMath,
remarkMdxMermaid,
plugin(remarkHeading, { generateToc: false }),
plugin(remarkNpm, { persist: { id: 'package-manager' } }),
remarkCodeTab,
],
remarkRehypeOptions: {
passThrough: ['mdxJsxFlowElement', 'mdxJsxTextElement'],
},
rehypePlugins: [
rehypeKatex,
plugin(rehypeCode, { lazy: true, fallbackLanguage: 'text' }),
plugin(rehypeToc, { exportToc: { as: 'data' } }),
],
});Sources: packages/preview/src/pages/...slugs.tsx:29-46
| Compiler Option | Configured Plugins / Options | Purpose |
|---|---|---|
remarkPlugins | remarkGfm, remarkMath, remarkMdxMermaid, remarkHeading, remarkNpm, remarkCodeTab | Extends markdown parsing with tables, math, mermaid diagrams, headings, package managers, and code tabs. |
remarkRehypeOptions | passThrough: ['mdxJsxFlowElement', 'mdxJsxTextElement'] | Preserves JSX flow and text elements during AST conversion. |
rehypePlugins | rehypeKatex, rehypeCode, rehypeToc | Applies KaTeX math formatting, code syntax highlighting, and table of contents extraction. |
Sources: packages/preview/src/pages/...slugs.tsx:29-46
Caution
The markdown compilation renderer throws an explicit error when encountering disallowed evaluation nodes, disallowing program evaluation and limiting identifier lookup strictly to override component bindings.
Sources: packages/preview/src/lib/md.ts:45-55
Component Injection and Rendering Handlers
The DocPage routing component loads layout and page structures based on configuration presets (docs or flux), resolving page slugs through source loaders. When rendering content inside MdContent, ServerImage intercepts non-absolute image sources and rewrites them into query parameters containing page, project, and src.
function useMdxComponents(page: SourcePage) {
function ServerImage({ src, ...rest }: ComponentProps<'img'>) {
// resolve non-absolute src
if (src && !URL.canParse(src)) {
const params = new URLSearchParams();
params.set('page', page.absolutePath!);
params.set('project', page.data.project.dir);
params.set('src', src);
src = `/img?${params}`;
}
return <Image src={src} {...rest} />;
}
return {
...defaultMdxComponents,
Mermaid,
img: ServerImage,
};
}Sources: packages/preview/src/pages/...slugs.tsx:48-67
Note
When page compilation fails, the preview layout catches the error and formats the stack trace inside a code block component rather than crashing the request.
Sources: packages/preview/src/pages/...slugs.tsx:170-194
Related
On This Page
OverviewRemote Compilation ArchitectureCompiler Factory and Processor InitializationExecution Scope and Function HydrationClient-Side Evaluation and Component InjectionAsynchronous and Synchronous Hydration FunctionsScope Merging and Component BindingsDynamic Doc Collection RuntimeOn-Demand Collection Initialization and ExecutionServer Document Mapping and Lazy CollectionsBrowser Execution and Client LoadersClient Loader Creation and Cache SharingStandard Schema Integration and Renderer MethodsRuntime Plugin Presets and ExecutionMDX Preset Configuration and Default PluginsFile Tree Transformation and Auto-Files ParsingPlaceholder Rendering and SerializationPreview and Dynamic Rendering IntegrationMarkdown Compiler Setup and Plugin PipelinesComponent Injection and Rendering HandlersRelated