项目文件夹
Note
本文档由 WeHub 基于上游 README 翻译整理,属于社区翻译,非官方中文文档。
English · 原始项目 · 上游 README
原作者、版权与许可证归属以原始项目及本仓库 LICENSE 文件为准。
beautiful-mermaid
将 Mermaid 图表渲染为精美的 SVG 或 ASCII 艺术
超快、完全可主题化、零 DOM 依赖。为 AI 时代而生。
我们为何构建它
图表对于 AI 辅助编程至关重要。当你与 AI 编程助手协作时,能够在终端或聊天界面中直接可视化数据流、状态机和系统架构,能让复杂概念一目了然。
Mermaid 是基于文本的图表事实标准(de facto standard)。它非常出色。但默认渲染器存在一些问题:
- 美观度 — 或许只是个人偏好,但希望它们看起来更专业
- 复杂的主题定制 — 自定义颜色需要与 CSS 类较劲
- 无终端输出 — 无法为 CLI 工具渲染为 ASCII
- 沉重依赖 — 为简单图表引入大量代码
我们在 Craft 构建了 beautiful-mermaid,为 Craft Agents. 中的图表提供动力。它快速、美观,随处可用——从富 UI 到纯终端。
ASCII 渲染引擎基于 Alexander Grooff 的 mermaid-ascii。我们从 Go 移植到 TypeScript 并进行了扩展。感谢 Alexander 提供的优秀基础!(以及证明了这是可行的灵感。)
功能特性
- 6 种图表类型 — 流程图、状态图、时序图、类图、ER 图和 XY 图(柱状、折线、组合)
- 双输出 — SVG 用于富 UI,ASCII/Unicode 用于终端
- 同步渲染 — 无异步、无闪烁。可与 React
useMemo()配合使用 - 15 个内置主题 — 添加自定义主题也极其简单
- 完整 Shiki 兼容 — 直接使用任意 VS Code 主题
- 实时主题切换 — CSS 自定义属性,无需重新渲染
- 单色模式(Mono mode) — 仅用 2 种颜色也能生成精美图表
- 零 DOM 依赖 — 纯 TypeScript,随处可用
- 超快速度 — 500ms 内渲染 100+ 张图表
安装
npm install beautiful-mermaid
# or
bun add beautiful-mermaid
# or
pnpm add beautiful-mermaid
快速开始
SVG 输出
import { renderMermaidSVG } from 'beautiful-mermaid'
const svg = renderMermaidSVG(`
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Action]
B -->|No| D[End]
`)
渲染完全同步——没有 await,没有 promise。ELK.js 布局引擎通过 FakeWorker 绕过机制同步运行,因此你能立即获得 SVG 字符串。
需要异步?使用 renderMermaidSVGAsync() —— 输出相同,返回 Promise<string>。
ASCII 输出
import { renderMermaidASCII } from 'beautiful-mermaid'
const ascii = renderMermaidASCII(`graph LR; A --> B --> C`)
┌───┐ ┌───┐ ┌───┐
│ │ │ │ │ │
│ A │────►│ B │────►│ C │
│ │ │ │ │ │
└───┘ └───┘ └───┘
React 集成
由于渲染是同步的,你可以使用 useMemo() 实现零闪烁的图表渲染:
import { renderMermaidSVG } from 'beautiful-mermaid'
function MermaidDiagram({ code }: { code: string }) {
const { svg, error } = React.useMemo(() => {
try {
return {
svg: renderMermaidSVG(code, {
bg: 'var(--background)',
fg: 'var(--foreground)',
transparent: true,
}),
error: null,
}
} catch (err) {
return { svg: null, error: err instanceof Error ? err : new Error(String(err)) }
}
}, [code])
if (error) return <pre>{error.message}</pre>
return <div dangerouslySetInnerHTML={{ __html: svg! }} />
}
为何效果好:
- 无闪烁 — SVG 在渲染期间同步计算,而非在 useEffect 中
- CSS 变量 — 传递
var(--background)等,而非十六进制颜色。SVG 继承自应用的 CSS,因此主题切换可即时生效而无需重新渲染 - 记忆化(Memoized) — 仅在
code变化时重新渲染
主题
主题系统是 beautiful-mermaid 的核心。它既强大又极其简单。
双色基础
每张图表只需两种颜色:背景(bg)和前景(fg)。仅此而已。从这两种颜色出发,整个图表通过 color-mix() 推导得出:
const svg = renderMermaidSVG(diagram, {
bg: '#1a1b26', // Background
fg: '#a9b1d6', // Foreground
})
这就是单色模式(Mono Mode)——仅用两种颜色就能生成连贯、精美的图表。系统会自动推导:
| 元素 | 推导方式 |
|---|---|
| 文本 | --fg at 100% |
| 次要文本 | --fg at 60% into --bg |
| 边标签 | --fg at 40% into --bg |
| 淡色文本 | --fg at 25% into --bg |
| 连接线 | --fg at 50% into --bg |
| 箭头 | --fg at 85% into --bg |
| 节点填充 | --fg at 3% into --bg |
| 组标题 | --fg at 5% into --bg |
| 内部描边 | --fg at 12% into --bg |
| 节点描边 | --fg at 20% into --bg |
增强模式(Enriched Mode)
对于更丰富的主题,你可以提供可选的「增强」颜色来覆盖特定推导结果:
const svg = renderMermaidSVG(diagram, {
bg: '#1a1b26',
fg: '#a9b1d6',
// Optional enrichment:
line: '#3d59a1', // Edge/connector color
accent: '#7aa2f7', // Arrow heads, highlights
muted: '#565f89', // Secondary text, labels
surface: '#292e42', // Node fill tint
border: '#3d59a1', // Node stroke
})
若未提供增强颜色,则回退到 color-mix() 推导。这意味着你只需提供你关心的颜色。
CSS 自定义属性 = 实时切换
所有颜色都是 <svg> 元素上的 CSS 自定义属性。这意味着你可以即时切换主题而无需重新渲染:
// Switch theme by updating CSS variables
svg.style.setProperty('--bg', '#282a36')
svg.style.setProperty('--fg', '#f8f8f2')
// The entire diagram updates immediately
对于 React 应用,传递 CSS 变量引用而非十六进制值:
const svg = renderMermaidSVG(diagram, {
bg: 'var(--background)',
fg: 'var(--foreground)',
accent: 'var(--accent)',
transparent: true,
})
// Theme switches apply automatically via CSS cascade — no re-render needed
内置主题
开箱即用提供 15 个精心策划的主题:
| 主题 | 类型 | 背景 | 强调色 |
|---|---|---|---|
zinc-light |
Light | #FFFFFF |
Derived |
zinc-dark |
Dark | #18181B |
Derived |
tokyo-night |
Dark | #1a1b26 |
#7aa2f7 |
tokyo-night-storm |
Dark | #24283b |
#7aa2f7 |
tokyo-night-light |
Light | #d5d6db |
#34548a |
catppuccin-mocha |
Dark | #1e1e2e |
#cba6f7 |
catppuccin-latte |
Light | #eff1f5 |
#8839ef |
nord |
Dark | #2e3440 |
#88c0d0 |
nord-light |
Light | #eceff4 |
#5e81ac |
dracula |
Dark | #282a36 |
#bd93f9 |
github-light |
Light | #ffffff |
#0969da |
github-dark |
Dark | #0d1117 |
#4493f8 |
solarized-light |
Light | #fdf6e3 |
#268bd2 |
solarized-dark |
Dark | #002b36 |
#268bd2 |
one-dark |
Dark | #282c34 |
#c678dd |
import { renderMermaidSVG, THEMES } from 'beautiful-mermaid'
const svg = renderMermaidSVG(diagram, THEMES['tokyo-night'])
添加自定义主题
创建主题轻而易举。至少需要提供 bg 和 fg:
const myTheme = {
bg: '#0f0f0f',
fg: '#e0e0e0',
}
const svg = renderMermaidSVG(diagram, myTheme)
想要更丰富的颜色?添加任意可选增强色:
const myRichTheme = {
bg: '#0f0f0f',
fg: '#e0e0e0',
accent: '#ff6b6b', // Pop of color for arrows
muted: '#666666', // Subdued labels
}
完整 Shiki 兼容性
通过 Shiki 集成,可直接使用任意 VS Code 主题。这样你就能访问数百个社区主题:
import { getSingletonHighlighter } from 'shiki'
import { renderMermaidSVG, fromShikiTheme } from 'beautiful-mermaid'
// Load any theme from Shiki's registry
const highlighter = await getSingletonHighlighter({
themes: ['vitesse-dark', 'rose-pine', 'material-theme-darker']
})
// Extract diagram colors from the theme
const colors = fromShikiTheme(highlighter.getTheme('vitesse-dark'))
const svg = renderMermaidSVG(diagram, colors)
fromShikiTheme() 函数会智能地将 VS Code 编辑器颜色映射到图表角色:
| 编辑器颜色 | 图表角色 |
|---|---|
editor.background |
bg |
editor.foreground |
fg |
editorLineNumber.foreground |
line |
focusBorder / keyword token |
accent |
| comment token | muted |
editor.selectionBackground |
surface |
editorWidget.border |
border |
支持的图表
流程图
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Process]
B -->|No| D[End]
C --> D
支持所有方向:TD(自上而下)、LR(从左到右)、BT(自下而上)、RL(从右到左)。
状态图
stateDiagram-v2
[*] --> Idle
Idle --> Processing: start
Processing --> Complete: done
Complete --> [*]
时序图
sequenceDiagram
Alice->>Bob: Hello Bob!
Bob-->>Alice: Hi Alice!
Alice->>Bob: How are you?
Bob-->>Alice: Great, thanks!
类图
classDiagram
Animal <|-- Duck
Animal <|-- Fish
Animal: +int age
Animal: +String gender
Animal: +isMammal() bool
Duck: +String beakColor
Duck: +swim()
Duck: +quack()
ER 图
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE_ITEM : contains
PRODUCT ||--o{ LINE_ITEM : "is in"
内联边样式
使用 linkStyle 覆盖边的颜色和描边宽度——就像 Mermaid 的 linkStyle:
graph TD
A --> B --> C
linkStyle 0 stroke:#ff0000,stroke-width:2px
linkStyle default stroke:#888888
| 语法 | 效果 |
|---|---|
linkStyle 0 stroke:#f00 |
按索引(从 0 开始)为单条边设置样式 |
linkStyle 0,2 stroke:#f00 |
一次为多条边设置样式 |
linkStyle default stroke:#888 |
应用于所有边的默认样式 |
按索引设置的样式会覆盖默认样式。支持的属性:stroke、stroke-width。
适用于流程图和状态图。
XY 图表
柱状图、折线图及其组合——使用 Mermaid 的 xychart-beta 语法。
柱状图:
xychart-beta
title "Monthly Revenue"
x-axis [Jan, Feb, Mar, Apr, May, Jun]
y-axis "Revenue ($K)" 0 --> 500
bar [180, 250, 310, 280, 350, 420]
折线图:
xychart-beta
title "User Growth"
x-axis [Jan, Feb, Mar, Apr, May, Jun]
line [1200, 1800, 2500, 3100, 3800, 4500]
柱状图 + 折线图组合:
xychart-beta
title "Sales with Trend"
x-axis [Jan, Feb, Mar, Apr, May, Jun]
bar [300, 380, 280, 450, 350, 520]
line [300, 330, 320, 353, 352, 395]
水平方向:
xychart-beta horizontal
title "Language Popularity"
x-axis [Python, JavaScript, Java, Go, Rust]
bar [30, 25, 20, 12, 8]
坐标轴配置:
- 分类 x 轴:
x-axis [A, B, C] - 数值 x 轴范围:
x-axis 0 --> 100 - 坐标轴标题:
x-axis "Category" [A, B, C] - Y 轴范围:
y-axis "Score" 0 --> 100
多系列: 添加多个 bar 和/或 line 声明。每个系列会从基于主题强调色的单色调色板中获得一种独立颜色。
XY 图表样式
图表渲染器遵循受 Apple 和 Craft 启发的简洁、极简设计理念:
- 点状网格 — 绘图区域以微妙的点状图案填充,而非传统的实线网格
- 圆角柱条 — 所有柱条边角均做圆角处理,呈现现代、精致的外观
- 平滑曲线 — 折线系列采用自然三次样条插值,在所有数据点之间生成数学上平滑的曲线(而非直线段或阶梯状折线)
- 浮动标签 — 无可见坐标轴线或刻度线;标签自由浮动,营造简洁清爽的视觉效果
- 投影线条 — 每条折线系列下方都有微妙阴影,以增强层次感
- 单色调色板 — 系列 0 使用主题的强调色;其余系列在同一色相下获得更深/更浅的色调,并带有微妙的色相偏移,可自动适配浅色或深色背景
- 交互式工具提示 — 使用
interactive: true渲染时,悬停在柱条或数据点上会显示数值工具提示。当多个系列共享同一 x 位置时,会显示多行工具提示 - 稀疏折线点 — 数据点不超过 12 个的折线默认显示数据点标记,以提升可读性
- 完整主题支持 — 全部 15 个内置主题(以及自定义主题)均适用于图表。强调色驱动整个系列调色板
- 实时主题切换 — 图表系列颜色为 CSS 自定义属性(
--xychart-color-N),因此主题变更可即时生效,无需重新渲染
ASCII 输出
适用于终端环境、CLI 工具,或任何需要纯文本的场景,可渲染为 ASCII 或 Unicode 制表符:
import { renderMermaidASCII } from 'beautiful-mermaid'
// Unicode mode (default) — prettier box drawing
const unicode = renderMermaidASCII(`graph LR; A --> B`)
// Pure ASCII mode — maximum compatibility
const ascii = renderMermaidASCII(`graph LR; A --> B`, { useAscii: true })
Unicode 输出:
┌───┐ ┌───┐
│ │ │ │
│ A │────►│ B │
│ │ │ │
└───┘ └───┘
ASCII 输出:
+---+ +---+
| | | |
| A |---->| B |
| | | |
+---+ +---+
ASCII 选项
renderMermaidASCII(diagram, {
useAscii: false, // true = ASCII, false = Unicode (default)
paddingX: 5, // Horizontal spacing between nodes
paddingY: 5, // Vertical spacing between nodes
boxBorderPadding: 1, // Padding inside node boxes
colorMode: 'auto', // 'none' | 'auto' | 'ansi16' | 'ansi256' | 'truecolor' | 'html'
theme: { ... }, // Partial<AsciiTheme> — override default colors
})
ASCII XY 图表
XY 图表可使用专用图表绘制字符渲染为 ASCII:
- 柱状图 —
█块(Unicode)或#(ASCII 模式) - 折线图 — 带圆角的阶梯式路由:
╭╮╰╯│─(Unicode)或+|-(ASCII) - 多系列 — 每个系列从主题的强调色调色板中获得一种独立的 ANSI 颜色
- 图例 — 存在多个系列时自动显示
- 水平图表 — 完全支持,分类位于 y 轴
API 参考
renderMermaidSVG(text, options?): string
将 Mermaid 图表渲染为 SVG。同步执行。自动检测图表类型。
参数:
text— Mermaid 源代码options— 可选的RenderOptions对象
RenderOptions:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
bg |
string |
#FFFFFF |
背景色(或 CSS 变量) |
fg |
string |
#27272A |
前景色(或 CSS 变量) |
line |
string? |
— | 边/连接线颜色 |
accent |
string? |
— | 箭头、高亮 |
muted |
string? |
— | 次要文本、标签 |
surface |
string? |
— | 节点填充色调 |
border |
string? |
— | 节点描边颜色 |
font |
string |
Inter |
字体族 |
transparent |
boolean |
false |
以透明背景渲染 |
padding |
number |
40 |
画布内边距(px) |
nodeSpacing |
number |
24 |
同级节点之间的水平间距 |
layerSpacing |
number |
40 |
层与层之间的垂直间距 |
componentSpacing |
number |
24 |
不连通组件之间的间距 |
thoroughness |
number |
3 |
交叉最小化尝试次数(1-7,数值越高效果越好但速度越慢) |
interactive |
boolean |
false |
在 XY 图表的柱条和数据点上启用悬停工具提示 |
XY 图表: 以 xychart-beta 开头的图表会自动识别——无需单独函数。accent 颜色选项决定图表系列的颜色调色板。
renderMermaidSVGAsync(text, options?): Promise<string>
renderMermaidSVG() 的异步版本。输出相同,返回 Promise<string>。适用于异步服务器处理器或数据加载器。
renderMermaidASCII(text, options?): string
将 Mermaid 图表渲染为 ASCII/Unicode 文本。同步方法。
AsciiRenderOptions:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
useAscii |
boolean |
false |
使用 ASCII 而非 Unicode |
paddingX |
number |
5 |
水平节点间距 |
paddingY |
number |
5 |
垂直节点间距 |
boxBorderPadding |
number |
1 |
内部框内边距 |
colorMode |
string |
'auto' |
'none'、'auto'、'ansi16'、'ansi256'、'truecolor' 或 'html' |
theme |
Partial<AsciiTheme> |
— | 覆盖 ASCII 输出的默认颜色 |
parseMermaid(text): MermaidGraph
将 Mermaid 源码解析为结构化图对象(用于自定义处理)。
fromShikiTheme(theme): DiagramColors
从 Shiki 主题对象中提取图表颜色。
THEMES: Record<string, DiagramColors>
包含全部 15 个内置主题的对象。
DEFAULTS: { bg: string, fg: string }
默认颜色(#FFFFFF / #27272A)。
致谢
ASCII 渲染引擎基于 mermaid-ascii by Alexander Grooff。我们将其从 Go 移植到 TypeScript,并扩展了以下功能:
- 时序图(Sequence diagram)支持
- 类图(Class diagram)支持
- ER 图(ER diagram)支持
- Unicode 框线绘制字符
- 可配置的间距与内边距
感谢 Alexander 提供的优秀基础!
许可证
MIT — 详见 LICENSE。
由 Craft 团队用心打造
