Skip to content

Official plugins

A Markdown plugin is a build-time transform added to the content compiler. It receives one Markdown or MDX syntax tree and returns transformed syntax or HTML. A plugin can also declare the CSS and browser scripts required by that page. The deployed result remains static HTML; the plugin itself does not run in production.

For example, math() turns $E = mc^2$ into KaTeX HTML during the build. mermaid() loads its diagram client only on pages that contain executable Mermaid fences. A search provider has a different lifecycle: it receives the completed site and writes a site-wide index instead of transforming one document.

Official plugins are published in @docfuse/plugins:

pnpm
pnpm add -D @docfuse/plugins

Available capabilities

table
externalLinks()markdown.pluginsAdd safe attributes to external linksNone
linkCard()markdown.pluginsRender a standalone link as a cardNone
readingTime()markdown.pluginsShow reading time below the titleNone
math()markdown.pluginsRender mathematical notationImport @docfuse/plugins/math.css when using the Markdown package directly
mermaid()markdown.pluginsRender Mermaid diagramsInstall mermaid
plantUml()markdown.pluginsRender PlantUML diagramsConfigure a trusted server
kroki()markdown.pluginsRender Graphviz and D2 through KrokiUses https://kroki.io by default; self-hosting is supported
pagefind()search.providerBuild a Pagefind search indexInstall pagefind

Configure and use plugins

These packages run during local development and site builds, so install them as development dependencies. Add only the capabilities the site needs; when enabling Mermaid or Pagefind, install the corresponding dependency as well:

bash
pnpm add -D mermaid pagefind
docfuse.config.ts
import { externalLinks, math, mermaid, pagefind } from '@docfuse/plugins'import { defineConfig } from 'docfuse'export default defineConfig({  search: {    provider: pagefind()  },  markdown: {    plugins: [      math(),      mermaid(),      externalLinks({ internalHosts: ['docs.example.com'] })    ]  }})

readingTime() includes English and Chinese labels. Pass labels only when adding another locale or changing the wording.

After configuration, write the syntax owned by the plugins:

markdown
Inline math $E = mc^2$.```mermaidflowchart LR  Markdown --> HTML```

docfuse check loads the config and uses plugin declarations to validate directives and code fences; it does not render complete pages. docfuse build and docfuse dev execute plugin transforms. Removing a plugin stops its syntax from being transformed, and fences not claimed by another plugin remain subject to the unknown-language policy.

Run and verify

bash
pnpm docs:checkpnpm docs:dev

Open the page containing the sample syntax. The formula should be typeset, and Mermaid should display a diagram instead of source. External links should have the configured target and rel attributes.

Check production output before publishing:

bash
pnpm docs:buildpnpm docs:preview

Search for the page in the preview and confirm that Pagefind returns it. Ordinary pages should not load the Mermaid client; the client is added only to pages with executable Mermaid fences. If a plugin has no effect, see Troubleshooting.

Option reference

Every option is optional. The table lists the behavior used when an option is omitted:

table
externalLinksnewTabtrueOpen external links in a new window
rel['noopener', 'noreferrer']Values written to external-link rel
internalHosts[]Hosts and subdomains treated as internal
linkCardinternalHosts[]Hosts that are not converted to external cards
includeRelativefalseAlso convert site links beginning with /
readingTimewordsPerMinute220Latin words per minute; must be positive and finite
cjkWordsPerMinute300CJK characters per minute; must be positive and finite
includeCodefalseInclude code in the estimate
label'{minutes} min read'Fallback template when no locale label matches
labelsBuilt-in ChineseOverride templates by locale while retaining {minutes}
maththrowOnErrorfalseThrow when KaTeX encounters invalid input
errorColor'#b42318'Error color when errors are rendered
trustfalseAllow trusted KaTeX commands that emit URLs or HTML
strict'warn'KaTeX strictness policy
macros{}Custom KaTeX macros
mermaidmoduleUrlBundled resourceOverride the browser Mermaid ESM URL
plantUmlserverfalsePlantUML server; source-only output when omitted
krokiserverhttps://kroki.ioKroki service URL
languagesGraphviz, Dot, GV, D2Markdown language to Kroki type mapping
format'svg'Emit svg or png
pagefindincludeCharacters'._-'Characters retained during Pagefind tokenization
keepIndexUrlfalsePreserve index-page URLs
writePlaygroundfalseGenerate Pagefind's debugging playground

Plugins, providers, and extensions

table
Markdown pluginSyntax or HTML transformation within one documentmarkdown.plugins
Search providerAn index generated from the complete sitesearch.provider
ExtensionRepository source transforms, page metadata, or extra filesextensions

The package manager installs the complete @docfuse/plugins package. Only plugins passed to the config process content and affect build output. Capabilities with browser runtimes also load assets per page. Only an executable Mermaid fence activates Mermaid; a Mermaid example shown inside a tutorial code block does not load the runtime.

Use the package root in normal site config. Capability subpaths remain public APIs for libraries and tools that resolve one focused entry.

Build a minimal plugin

A custom plugin can live in the project and be imported by docfuse.config.ts. This complete example adds a project-owned data-section attribute to every level-two heading without relying on internal Docfuse classes:

markdown/section-labels.mjs
import { defineMarkdownPlugin } from '@docfuse/markdown'function markSections() {  return (tree) => {    const walk = (node) => {      if (node.type === 'element' && node.tagName === 'h2') {        node.properties ??= {}        node.properties.dataSection = ''      }      node.children?.forEach(walk)    }    walk(tree)  }}export function sectionLabels() {  return defineMarkdownPlugin({    name: 'section-labels',    version: '1',    rehypePlugins: [markSections]  })}
docfuse.config.ts
import { defineConfig } from 'docfuse'import { sectionLabels } from './markdown/section-labels.mjs'export default defineConfig({  markdown: { plugins: [sectionLabels()] },  styles: ['./docs/section-labels.css']})
docs/section-labels.css
h2[data-section] {  border-inline-start: 0.2rem solid currentColor;  padding-inline-start: 0.75rem;}

Run pnpm docs:dev and verify that level-two headings have a leading rule. Then run pnpm docs:build and confirm that generated level-two headings have a data-section attribute. The first result verifies the project CSS; the second verifies the plugin transform.

name is unique within one compiler. Bump version when transform behavior changes and put resolved options in cacheKey. A plugin that owns custom directives or code fences must also declare directiveNames or fenceLanguages, so typo and unknown-language checks can distinguish valid plugin syntax.