Skip to main content

Mermaid diagrams

A ```mermaid fence becomes a diagram, rendered in the browser by the kit's <dfk-mermaid> element:

Wiring​

One entry in the docs preset's remarkPlugins, and nothing else:

import {remarkMermaid} from 'duckfn-docs-kit/mermaid/remark';

export default {
presets: [
[
'classic',
{
docs: {
remarkPlugins: [remarkMermaid],
},
},
],
],
};

Do not install @docusaurus/theme-mermaid, do not list it in themes, and do not set markdown.mermaid. The kit's element replaces all three; leaving the theme in place would put two renderers on the same fence.

Why the kit renders it instead​

Two upstream defects are structural in the theme's React component, and neither can be fixed from docusaurus.config.ts or from the diagram source:

  • A dark-mode first load flashed. The theme colours by useColorMode(), whose value deliberately lags on the first client render, so a dark page painted a light diagram first and a dark one immediately after. The two also overlapped inside mermaid's mutable singleton, which occasionally resolved to an empty diagram with no error.
  • Two diagrams could not render at once — mermaid is one mutable singleton.

The element reads the colour mode from <html data-theme> (written before the first paint) and renders every diagram through one page-wide queue, so each diagram is rendered exactly once per mode, in the mode the page is really in.

The palette​

The default is the neo look with the redux palette — redux-color in light mode, redux-dark-color in dark. A site overrides it in its own config:

remarkMermaid({
config: {theme: {light: 'neutral', dark: 'dark'}, options: {look: 'classic'}},
});

theme is per colour mode; look has no light/dark counterpart and goes through options. Mermaid silently ignores a value it does not recognise and falls back — so check a diagram in a browser, not by the build. (node elements carry data-look, which is the quick way to confirm the look took.)

What the reader gets​

Hovering a diagram reveals four buttons in its top-right corner:

ButtonWhat it does
Reset zoomBack to fit. Only does something in fullscreen, where the wheel zooms and dragging pans.
FullscreenFills the viewport and turns zooming on; Esc exits.
Edit sourceOpens the mermaid source in a CodeMirror dialog. Apply re-renders; the change is local to the page.
Download SVGSaves the diagram as an .svg file, named after the section it sits in.

A diagram on the page is a picture, not a viewport. The wheel scrolls the page over it, the cursor is the ordinary one — an I-beam over a label — and dragging selects text, so a label can be copied like any other text on the page. Both are what fullscreen is for: expanding a diagram is what turns the wheel into a zoom and a drag into a pan, where the pointer becomes a grab hand. Reset zoom returns the diagram to fit without leaving fullscreen; zooming is off again as soon as the diagram comes back inline. There is no select/drag mode to switch.

The downloaded file is named from the page, not mermaid-diagram.svg — the section it sits in (2. Registration.svg). The name comes from the first of these that says anything: the diagram's own title (mermaid frontmatter, ---\ntitle: …\n---) → the nearest heading above it → the page title → mermaid-diagram.svg. Give a fence a frontmatter title: when the heading is not the name you want:

```mermaid
---
title: Where duckfn sits
---
flowchart LR
A["write Rust"] --> B["a DuckDB extension"]
```

Notes​

  • Diagrams render on the client, so a syntax error appears in the page (with mermaid's own message) rather than failing the build.
  • Keep labels quoted (A["text"]), use <br/> for a line break, and avoid a bare # or an unescaped &.
  • A ```mermaid fence inside a longer fence — documenting it, as this page does — stays text; it is not turned into a diagram.
  • A runnable SQL block can emit a diagram too: "show": "mermaid" hands the result's column to this same element — embedded in the result panel, so the frame and the floating cluster go away and Reset zoom / Edit source join the tab strip instead — see Runnable SQL blocks.