简介
mdbook-modern-dot 是一个 mdBook 预处理器,可将 Markdown 中的围栏代码块渲染为 Graphviz 图表。
功能特性
- 构建时通过
dot命令处理modern-dot代码块 - 内联 SVG(默认)或 输出到文件 并以图片引用
- 可选 明暗双主题渲染,与 mdBook HTML 主题(Light/Rust 与 Coal/Navy/Ayu)联动
- 支持 TOML 主题文件、
{{ token }}占位符与自动 preamble 注入
工作原理
-
在 Markdown 中编写 Graphviz dot 代码:
```modern-dot digraph { a -> b; } ``` -
执行
mdbook build时,预处理器调用dot,按需应用主题 token,并将代码块替换为 HTML(内联 SVG)或生成的图片文件。 -
启用
themed-output = true时,会同时生成明、暗两套 SVG,由 CSS 根据当前 mdBook 主题切换显示。
本书本身即由 mdbook-modern-dot 构建——切换 mdBook 主题即可看到图表配色随之变化。
安装
安装预处理器
从 crates.io 安装:
cargo install mdbook-modern-dot
从源码安装:
cargo install --path .
安装 Graphviz
预处理器在构建时会调用 dot 命令,需单独安装 Graphviz:
# macOS
brew install graphviz
# Debian/Ubuntu
sudo apt install graphviz
验证安装:
dot -V
若未找到 dot,mdbook build 会失败并提示安装方法。
安装 mdBook
构建书籍还需要 mdBook:
cargo install mdbook
快速开始
在 book.toml 中添加预处理器:
[preprocessor.modern-dot]
command = "mdbook-modern-dot"
在 Markdown 中编写图表:
```modern-dot
digraph {
"processed" -> "graph"
}
```
可在 info string 后添加可选标题:
```modern-dot 数据流
digraph { input -> output; }
```
构建:
mdbook build
启用明暗主题
[preprocessor.modern-dot]
command = "mdbook-modern-dot"
themed-output = true
theme-file = "themes/default.toml"
启用 themed-output 后,预处理器会在每个含主题图的章节首张图前自动注入内置 CSS,无需复制 modern-dot-theme.css 或配置 additional-css。
若需自定义样式,可设置 inject-theme-css = false 并自行引入 CSS 文件。
本仓库开发
开发本项目时,可指向本地 crate:
[preprocessor.modern-dot]
command = "cargo run -q -p mdbook-modern-dot"
themed-output = true
theme-file = "../themes/default.toml"
配置项
所有选项均写在 book.toml 的 [preprocessor.modern-dot] 下。
| 选项 | 默认值 | 说明 |
|---|---|---|
command | (必填) | mdbook-modern-dot 可执行文件路径 |
themed-output | false | 渲染明、暗两套 SVG |
inject-theme-css | true | 在每个含主题图的章节首张图前自动注入内置主题切换 CSS(themed-output = true 时生效) |
theme-file | themes/default.toml | 主题 TOML 路径(相对书籍根目录) |
dark-suffix | -dark | 文件模式下暗色 SVG 文件名后缀 |
theme-wrapper-class | theme-diagram | 主题输出外层 CSS 类名 |
info-string | modern-dot | 要处理的围栏代码块标记 |
output-to-file | false | 输出 SVG 文件而非内联 HTML |
link-to-file | false | 文件模式下用链接包裹图片(仅单主题) |
arguments | ["-Tsvg"] | 传给 dot 的额外参数 |
after | — | 在其他预处理器之后运行(如 ["links"]) |
环境变量
mdBook 支持用环境变量覆盖配置:
MDBOOK_preprocessor__modern_dot__themed_output="true" mdbook build
MDBOOK_preprocessor__modern_dot__output_to_file="true" mdbook build
选项名中的连字符 - 变为下划线 _;嵌套键使用双下划线 __。
自定义 info string
仅处理与 info-string 匹配的代码块,其他标记(如普通 ```dot)保持不变。
[preprocessor.modern-dot]
info-string = "graphviz"
嵌入外部 dot 文件
配合 mdBook 的 links 预处理器引入 dot 源码:
```dot
{{#include path/to/diagram.dot}}
```
确保 modern-dot 在 links 之后运行:
[preprocessor.modern-dot]
after = ["links"]
文件模式的 .gitignore
使用 output-to-file = true 时,建议添加:
*.modern-dot.svg
*.modern-dot-dark.svg
主题系统
启用 themed-output = true 后,每张图会渲染两次:分别使用主题文件中的 [light] 与 [dark] token。
主题文件格式
示例(themes/default.toml):
[light]
text = "#24292f"
node_fill = "#f6f7f9"
edge = "#5c6b7a"
[dark]
text = "#adbac7"
node_fill = "#2d333b"
edge = "#768390"
[preamble]
graph = 'graph [ bgcolor="transparent", fontcolor="{{ text }}" ];'
node = 'node [ style="filled", fillcolor="{{ node_fill }}", color="{{ node_stroke }}", fontcolor="{{ text }}" ];'
edge = 'edge [ color="{{ edge }}", fontcolor="{{ text }}" ];'
dot 代码中的占位符
在图表中使用 {{ token }}:
缺少 token 会导致构建失败,并列出未找到的键名。
自动 preamble 注入
若代码块中 没有 {{ ... }} 占位符,会在图定义开括号 { 之后自动注入主题文件 [preamble] 中的属性。
已使用占位符的代码块不会注入 preamble,样式由你完全控制。
CSS 切换
默认 inject-theme-css = true 时,预处理器在每个含主题图的章节首张图前注入内置 <style>,无需额外文件。
若需自定义,可关闭自动注入并手动引入 assets/modern-dot-theme.css:
[preprocessor.modern-dot]
inject-theme-css = false
[output.html]
additional-css = ["modern-dot-theme.css"]
生成的 HTML 结构:
<div class="mdbook-modern-dot-output theme-diagram">
<div class="diagram-light"><svg>...</svg></div>
<div class="diagram-dark"><svg>...</svg></div>
</div>
输出模式
内联模式(默认)
output-to-file = false — SVG 直接嵌入章节 HTML。
适合大多数书籍:无额外文件,图表随页面一起发布。
文件模式
[preprocessor.modern-dot]
output-to-file = true
每张图在源章节旁生成 SVG 文件:
chapter_name_0.modern-dot.svg(浅色)chapter_name_0.modern-dot-dark.svg(深色,需themed-output = true)
Markdown 中的代码块会被替换为 <img> 标签(主题模式下为双图 HTML)。
链接到文件
单主题文件模式下,可将图片包裹在指向 SVG 的链接中:
[preprocessor.modern-dot]
output-to-file = true
link-to-file = true
启用 themed-output = true 时不使用此选项(主题文件输出使用固定 HTML 结构)。
文件命名规则
生成文件名由以下部分组成:
- 规范化后的章节名
- info string 中的可选图标题
- 章节内代码块序号
示例:章节「Getting Started」、标题「Data Flow」、第一个块 → getting_started_data_flow_0.modern-dot.svg。
章节名与图标题中的非字母数字字符会规范化为下划线(仅保留 ASCII 字母数字)。
示例
以下图表由 mdbook-modern-dot 在 themed-output = true 下实时渲染。
切换 mdBook 主题(Light ↔ Coal/Navy/Ayu)即可看到配色变化。
Graphviz
示例书籍启用了 themed-output,图表会生成明、暗两套 SVG,随 mdBook 主题切换。只需写一个围栏代码块,无需手写 HTML。
显式 token 的主题图
自动 preamble 注入的简单图
不含 {{ token }} 占位符的图表,会从 themes/default.toml 自动注入默认 graph/node/edge 属性。
硬编码颜色(不随主题变化)
以下颜色固定不变,除非改为主题 token。
开发指南
环境要求
- Rust 1.92+(见
rust-toolchain.toml) - Graphviz(
dot在 PATH 中) - mdBook
构建本文档
在仓库根目录执行:
mdbook build book
mdbook serve book
book/ 目录既是项目手册,也是启用 themed-output 的集成示例。
常用命令
cargo test
cargo lint # clippy + fmt 检查
cargo fmt-check
发布
使用 cargo-release:
cargo release patch -x --no-confirm
许可证
AGPL-3.0-or-later — 见 LICENSE。