Color mode

Markmap

Renders ```markmap code blocks as Markdown-heading mindmaps. The mindmap is drawn in the browser by markmap-lib + markmap-view, which are imported from the CDN only when a figure is present.

Japanese

Configure

ts
import { defineConfig } from "@riebeckite/core";
import { markmap } from "@riebeckite/plugin-markmap";
 
export default defineConfig({
  // ...
  plugins: [
    markmap({
      caption: true,
      height: 320,
      fallback: true,
    }),
  ],
});

The plugin runs with order: -10.

Syntax

The block body is ordinary Markdown: headings become nodes and their nesting becomes the tree. Content other than headings is ignored.

markdown
```markmap
# Project
 
## Design
 
### Notation
### Rendering
 
## Delivery
```

The caption comes from the code-block title.

How it renders

A ```markmap block becomes a figure.rb-markmap:

  • figure.rb-markmap: carries data-markmap="pending", data-markmap-source (the raw Markdown) and data-markmap-height
  • div.rb-markmap__canvas: the element the SVG is rendered into (role="img")
  • figcaption.rb-markmap__caption: the caption (enabled by default)
  • details.rb-markmap__fallback: the raw Markdown, folded away

initMarkmap finds every [data-markmap="pending"], loads the runtime, runs markmap-lib's Transformer over data-markmap-source, and renders the resulting tree with markmap-view's Markmap.create. On success the figure becomes data-markmap="rendered".

If loading the runtime, transforming the source, or rendering fails, the initializer does not throw: it opens that figure's details and marks it data-markmap="error".

A block whose body has no Markdown heading is left as a normal code block, and a diagnostic with source: "@riebeckite/plugin-markmap" is emitted.

Options

Option Default Description
caption true Show the code-block title as a caption
height 320 Canvas height in pixels
className "rb-markmap" Base class applied to the figure
language "markmap" Fenced-code language to recognize
fallback true Render the <details> block with the raw Markdown
colorFreezeLevel — Depth at which node colours are frozen

Client rendering

The client initializer is static and receives no plugin options. height and colorFreezeLevel are embedded into the figure's data-markmap-* attributes, and initMarkmap reads them from there.

markmap-lib and markmap-view are fetched from jsDelivr with a computed import specifier, so they are never bundled into the host's client bundle. markmap-view pulls d3 in as its own dependency. Because the libraries are loaded lazily, the page still renders (with the fallback details) when JavaScript is disabled.

The input-notation seam

The code-block body is turned into a mindmap tree by a single, pure function in src/parse.ts:

ts
parseMarkmapSource(source: string): MarkmapNode | null

MarkmapNode is the notation-neutral tree ({ content, children, payload? }). Only the standard Markdown-heading notation is implemented today. A future alternative notation (for example an "ExcaliMindMap"-style outline) is added by implementing another parser that produces the same MarkmapNode shape; the figure emission and the render path do not parse the notation themselves, so they stay unchanged. parseMarkmapSource is exported from the package entry point for that purpose.

Output hooks

  • figure[data-markmap]: state (pending / rendered / error)
  • figure[data-markmap-source]: the raw Markdown
  • figure[data-markmap-height], figure[data-markmap-color-freeze-level]
  • [data-markmap-canvas]: the render target
  • details.rb-markmap__fallback: the raw Markdown

Main exports

  • markmap(options?): create the plugin (markmapPlugin is an alias)
  • initMarkmap: initialize client-side rendering
  • parseMarkmapSource: parse the standard notation into a tree
  • describeMarkmapTree: derive an accessible label from a tree
  • Types: MarkmapOptions, MarkmapNode, MarkmapClientOptions

Limitations

  • Rendering is client-only. Nothing is rendered at build time, so mindmaps are not visible without JavaScript (the source remains in the fallback details)
  • The client fetches markmap-lib, markmap-view, and their CDN sub-modules on first use, so the first render waits on the network
  • Not every Markdown extension is supported by the standard notation; the parser recognises ATX (#) headings and ignores fenced code blocks
  • markmap-lib and markmap-view are MIT licensed

See also

History

1 changesCollapseExpand
1 + <!-- Generated from packages/plugins/markmap/README.md. Do not edit this page directly; edit the package README and run `pnpm docs:sync`. -->
2 +
3 + # Markmap
4 +
5 + Renders ` ```markmap ` code blocks as Markdown-heading mindmaps. The mindmap is
6 + drawn in the browser by `markmap-lib` + `markmap-view`, which are imported from
7 + the CDN only when a figure is present.
8 +
9 + [Japanese](./markmap.md)
10 +
11 + ## Configure
12 +
13 + ```ts
14 + import { defineConfig } from "@riebeckite/core";
15 + import { markmap } from "@riebeckite/plugin-markmap";
16 +
17 + export default defineConfig({
18 + // ...
19 + plugins: [
20 + markmap({
21 + caption: true,
22 + height: 320,
23 + fallback: true,
24 + }),
25 + ],
26 + });
27 + ```
28 +
29 + The plugin runs with `order: -10`.
30 +
31 + ## Syntax
32 +
33 + The block body is ordinary Markdown: headings become nodes and their nesting
34 + becomes the tree. Content other than headings is ignored.
35 +
36 + ````markdown
37 + ```markmap
38 + # Project
39 +
40 + ## Design
41 +
42 + ### Notation
43 + ### Rendering
44 +
45 + ## Delivery
46 + ```
47 + ````
48 +
49 + The caption comes from the code-block `title`.
50 +
51 + ## How it renders
52 +
53 + A ` ```markmap ` block becomes a `figure.rb-markmap`:
54 +
55 + - `figure.rb-markmap`: carries `data-markmap="pending"`,
56 + `data-markmap-source` (the raw Markdown) and `data-markmap-height`
57 + - `div.rb-markmap__canvas`: the element the SVG is rendered into
58 + (`role="img"`)
59 + - `figcaption.rb-markmap__caption`: the caption (enabled by default)
60 + - `details.rb-markmap__fallback`: the raw Markdown, folded away
61 +
62 + `initMarkmap` finds every `[data-markmap="pending"]`, loads the runtime, runs
63 + `markmap-lib`'s `Transformer` over `data-markmap-source`, and renders the
64 + resulting tree with `markmap-view`'s `Markmap.create`. On success the figure
65 + becomes `data-markmap="rendered"`.
66 +
67 + If loading the runtime, transforming the source, or rendering fails, the
68 + initializer does not throw: it opens that figure's `details` and marks it
69 + `data-markmap="error"`.
70 +
71 + A block whose body has no Markdown heading is left as a normal code block, and a
72 + diagnostic with `source: "@riebeckite/plugin-markmap"` is emitted.
73 +
74 + ## Options
75 +
76 + | Option | Default | Description |
77 + | --- | --- | --- |
78 + | `caption` | `true` | Show the code-block `title` as a caption |
79 + | `height` | `320` | Canvas height in pixels |
80 + | `className` | `"rb-markmap"` | Base class applied to the figure |
81 + | `language` | `"markmap"` | Fenced-code language to recognize |
82 + | `fallback` | `true` | Render the `<details>` block with the raw Markdown |
83 + | `colorFreezeLevel` | — | Depth at which node colours are frozen |
84 +
85 + ## Client rendering
86 +
87 + The client initializer is static and receives no plugin options. `height` and
88 + `colorFreezeLevel` are embedded into the figure's `data-markmap-*` attributes,
89 + and `initMarkmap` reads them from there.
90 +
91 + `markmap-lib` and `markmap-view` are fetched from jsDelivr with a computed
92 + import specifier, so they are never bundled into the host's client bundle.
93 + `markmap-view` pulls `d3` in as its own dependency. Because the libraries are
94 + loaded lazily, the page still renders (with the fallback `details`) when
95 + JavaScript is disabled.
96 +
97 + ## The input-notation seam
98 +
99 + The code-block body is turned into a mindmap tree by a single, pure function in
100 + `src/parse.ts`:
101 +
102 + ```ts
103 + parseMarkmapSource(source: string): MarkmapNode | null
104 + ```
105 +
106 + `MarkmapNode` is the notation-neutral tree (`{ content, children, payload? }`).
107 + Only the standard Markdown-heading notation is implemented today. A future
108 + alternative notation (for example an "ExcaliMindMap"-style outline) is added by
109 + implementing another parser that produces the same `MarkmapNode` shape; the
110 + figure emission and the render path do not parse the notation themselves, so
111 + they stay unchanged. `parseMarkmapSource` is exported from the package entry
112 + point for that purpose.
113 +
114 + ## Output hooks
115 +
116 + - `figure[data-markmap]`: state (`pending` / `rendered` / `error`)
117 + - `figure[data-markmap-source]`: the raw Markdown
118 + - `figure[data-markmap-height]`, `figure[data-markmap-color-freeze-level]`
119 + - `[data-markmap-canvas]`: the render target
120 + - `details.rb-markmap__fallback`: the raw Markdown
121 +
122 + ## Main exports
123 +
124 + - `markmap(options?)`: create the plugin (`markmapPlugin` is an alias)
125 + - `initMarkmap`: initialize client-side rendering
126 + - `parseMarkmapSource`: parse the standard notation into a tree
127 + - `describeMarkmapTree`: derive an accessible label from a tree
128 + - Types: `MarkmapOptions`, `MarkmapNode`, `MarkmapClientOptions`
129 +
130 + ## Limitations
131 +
132 + - Rendering is client-only. Nothing is rendered at build time, so mindmaps are
133 + not visible without JavaScript (the source remains in the fallback `details`)
134 + - The client fetches `markmap-lib`, `markmap-view`, and their CDN sub-modules on
135 + first use, so the first render waits on the network
136 + - Not every Markdown extension is supported by the standard notation; the
137 + parser recognises ATX (`#`) headings and ignores fenced code blocks
138 + - `markmap-lib` and `markmap-view` are MIT licensed
139 +
140 + ## See also
141 +
142 + - [Plugin system](../reference/plugin-api.en.md)
143 +