A Rehype plugin to convert D2 diagrams to SVG or PNG.
bun install @vahor/rehype-d2
import { rehype } from 'rehype'
import rehypeD2 from '@vahor/rehype-d2'
const processor = await rehype()
.use(rehypeD2, { strategy: 'inline-svg', cwd: "d2", defaultMetadata: { default: { layout: "elk", sketch: true, pad: 0 } } })
.process(...)
-
strategy
: The strategy to use for rendering the diagrams.'inline-svg'
: Replace the diagram with an inline SVG. This is the default. Recommended.'inline-png'
: Replace the diagram with an inline PNG, the image source will be a data URI of the svg.
-
cwd
: The working directory to use for to resolve imports.- If not provided, imports won't be available.
-
defaultThemes
: The themes to use if no themes are specified in the metadata. Default is["default"]
. -
defaultMetadata
: The options to pass to the D2 renderer. See D2 Render Options- Dictionary of themes, each theme is a key.
-
globalImports
: A list of imports to add to the D2 renderer. Requirescwd
to be set.- Dictionary of themes, each theme is a key.
- Example:
{ light: ["light.d2"], dark: ["dark.d2"] }
, will prepend the content diagram with[email protected]
and[email protected]
respective to the theme. - Sometimes using the import syntax can be limiting, for example if you want a
*
selector to also effect other files. In this case you can use the include syntax:{ light: [{ filename: "light.d2", mode: "prepend" }], dark: [{ filename: "dark.d2", mode: "prepend" }] }
. When usingprepend
the whole file will be prepended as if it was always a single file. (default value is equivalent tomode: "impot"
You can pass any props to the code block, this will override the defaultMetadata
option.
<code class="language-d2" title="This is a diagram" alt="This is a description" width="200" height="100">
...@vars
a: From
b: To
a -> b: Message
</code>
When using remark to process markdown and transform it into HTML, metadata fields can also be used:
```d2 width=200 height=100 title="This is a diagram" alt="This is a description"
...@vars
a: From
b: To
a -> b: Message
```
This will generate the following HTML:
When using inline-svg
:
<svg aria-label="This is a description" width="200" height="100">
...
</svg>
When using inline-png
:
<img src="data:image/svg+xml,..." alt="This is a description" title="This is a diagram" width="200" height="100">
See other examples in the fixtures directory tests/fixtures
and tests/output
to see the generated HTML.
The default theme is default
.
When using multiple themes, this plugin will generate a svg or png for each theme. It's up to you to define the css to hide or show the diagrams.
For example, if you have a light and dark theme, you can use the following css to hide the light theme:
.dark [data-d2-theme]:not([data-d2-theme="dark"]) {
display: none;
}
.light [data-d2-theme]:not([data-d2-theme="light"]) {
display: none;
}
Example with markdown:
```d2 themes=dark,light
a: From
b: To
a -> b: Message
```
This will generate the following HTML:
<svg data-d2-theme="dark">
...
</svg>
<svg data-d2-theme="light">
...
</svg>
- Reduce the size of the generated SVGs. Currently each diagram contains the fonts, and colors even if they are already defined in another diagram or globally in the html page.
- If you already have a rehype plugin that process code blocks, I suggest placing
rehype-d2
first, so that the code block is unchanged. - When using with contentlayer. You might have to patch the
contentlayer
library to avoid bundling thed2
library. See issue
- Rehype Mermaid For the inspiration.