Remark LLMs: export a component with output: "function"
With output: "function", _markdown becomes a component instead of a string: Markdown content is still stringified at compile time, while JSX elements stay as JSX, receiving their original props.
// fumadocs-mdx collection config
postprocess: {
includeProcessedMarkdown: { output: 'function' },
},Render it with renderToMarkdown from fumadocs-core/server. Elements resolve from props.components: a component can call asMarkdown() to output its own Markdown form, other components (including missing ones) are serialized as JSX syntax.
import { renderToMarkdown } from 'fumadocs-core/server';
const { _markdown: Content } = await page.data.load();
const text = await renderToMarkdown(<Content components={getMDXComponents()} />);getText('processed') keeps working: it renders the component for you, with an optional components map:
const text = await page.data.getText('processed', { components: getMDXComponents() });Supported in bundler collections with both compilers, and in dynamic: true collections & @fumadocs/satteri/local-md with the Sätteri compiler.
Slice Markdown output from the authored source
remarkLlms and the stringify mode of remarkStructure no longer re-stringify the document with mdast-util-to-markdown, they share a stringifier that slices the original source instead. On a 40 kB document with the default preset, remarkLlms went from 45 ms to 11 ms per compile, and structured data with stringify from 34 ms to 8 ms.
For remarkLlms, the output now matches the authored document: heading IDs are appended, frontmatter and ESM nodes are dropped, remarkInclude splices in the included content, and package-manager tabs, images and admonitions appear as written instead of their expanded <Tabs> / <img> / <Callout> forms. Heading levels also no longer lose their # markers. Where generated content replaces the authored form, the output shows the generated content: remarkAutoTypeTable renders its type tables as Markdown tables, instead of the meaningless <auto-type-table> tag.
For remarkStructure, content records keep the authored inline syntax, while links and JSX elements are flattened into their plain text. stringify now takes true or a filterElement callback for the elements whose syntax should be kept:
remarkStructureOptions: {
stringify: {
filterElement: (node) => node.name === 'TypeTable',
},
},Elements inserted by plugins (e.g. remarkAutoTypeTable) have no source to slice, kept ones are reconstructed from their attributes so they stay searchable.
The mdast-util-to-markdown based options of both plugins (filterElement variants returning children-only, stringify functions, handlers) are removed, along with the mdast-util-gfm and mdast-util-mdx dependencies. Use the plugins of fumadocs-core if you need custom stringification.