🚀 先看结论
- 🌍 跨平台:支持 Android、iOS、Desktop 和 Web(Kotlin/Wasm)。
- 📊 完整范围:Mermaid.js
12.0.0的 33 个官方图表家族已全部实现,33/33 达到 Stable。 - ✅ 质量证据:完成 8,448 组 Native/Official 同源码视觉对拍、16,896 张矩阵截图、528 页 contact sheet;另有 441 组独立生产场景和 787 个 JVM 测试。
- 📦 已经发布:KMP/CMP 与 Kotlin
1.7.21Android 制品已进入 Maven Central,iOS 制品已发布到 CocoaPods。 - 🧪 立即体验:打开 Web Playground
Mermaid 很适合把流程图、时序图、状态图直接写进 Markdown。
但在 Android、iOS 或 Compose Multiplatform 应用里展示 Mermaid,常见做法通常是启动 WebView、加载 Mermaid.js,再显示 JavaScript 生成的 SVG。只展示一张图时很直接;一个页面同时出现十几张甚至几十张图时,WebView 的内存、启动开销、生命周期、滚动体验和多实例管理就会成为实际成本。
所以我做了开源项目 CMP Mermaid:
把 Mermaid.js
12.0.0的解析、状态、布局和渲染语义忠实翻译到 Kotlin Multiplatform,最终交给 Compose Canvas 绘制。生产链路不使用 WebView,也不加载 Mermaid.js。
- GitHub:github.com/swithun-liu…
- 在线 Demo:swithun-liu.github.io/cmp-mermaid…
- Stable 报告:github.com/swithun-liu…
- 8,448 案例视觉报告:github.com/swithun-liu…
这不是把 Mermaid 放进 WebView
CMP Mermaid 的正式渲染流程是:
Mermaid source
-> Kotlin preprocessor and translated parser
-> translated diagram database and layout preparation
-> platform-independent MermaidScene
-> Compose Canvas
其中:
mermaid-core负责解析、Diagram DB、布局准备、主题和平台无关 SceneGraph;mermaid-compose负责 Compose Canvas 绘制、文本测量、交互与缩放;- Official 渲染与 Playground 位于隔离的调试工具中,不进入生产依赖。
业务模块只需依赖原生渲染制品。Mermaid.js 只用于生成官方参考图和视觉对拍证据,不会进入正式渲染链路。
下面是两组同源码结果。
Flowchart:CMP Native / Compose Canvas
Flowchart:Official / Mermaid.js 12.0.0
XY Chart:CMP Native / Compose Canvas
XY Chart:Official / Mermaid.js 12.0.0
Mermaid 12.0.0 的 33 个图表家族
当前版本已经完成 Mermaid.js 12.0.0 全部 33 个用户可见图表家族:
| 类别 | 图表家族 |
|---|---|
| 流程与结构 | Flowchart、Sequence、Class、State、Entity Relationship、Requirement、Use Case、C4、Architecture、Block、TreeView、Railroad、Packet |
| 数据与规划 | Gantt、Timeline、Kanban、User Journey、Git Graph、XY Chart、Pie、Radar、Sankey、Treemap、Quadrant、Venn |
| 思维与专业建模 | Mindmap、Ishikawa、Cynefin、Event Modeling、Agentflow、Swimlanes、Wardley Map、ZenUML |
33 个家族都经过各自的解析、状态、布局、图形、主题、文本和视觉门禁。项目不再是“只支持几个热门图表”的早期版本。
同时内置 Mermaid 12.0.0 的 11 个主题:
default, dark, forest, neutral, base,
neo, neo-dark, redux, redux-color,
redux-dark, redux-dark-color
业务侧也可以从预设主题通过 Kotlin copy 派生品牌主题,或者传入 Mermaid 兼容的 themeVariables。
为什么选择“翻译源码”,而不是重新发明一套
如果目标只是画几个 Demo,自己写一个简化 parser 和自动布局并不难。真正困难的是长期维护:
- Mermaid 新版本增加语法后如何跟进;
- shape、marker 或 edge routing 改动后如何定位差异;
- parser 能识别,但 Diagram DB 状态语义不一致时如何修复;
- 浏览器 SVG 与 Compose Canvas 文本度量不同时如何保持行为一致。
如果实现与上游没有映射关系,每次升级都只能靠截图找差异,再一点点猜问题在哪里。短期看起来快,长期维护成本很高。
CMP Mermaid 采用源码映射的忠实翻译路线:
- 锁定 Mermaid、Jison、D3、Marked、Dagre、ELK 等版本;
- Kotlin parser、DB、layout、shape、theme、renderer 标注对应的上游文件和函数;
- 可生成的 parser table、rule、entity、fixture 和 worker 从锁定输入生成;
- Mermaid 升级时对照上游 diff,只翻译发生变化的部分;
- 每次变更重新运行 Native/Official 对拍与跨平台门禁。
这不是逐字符照搬 JavaScript,而是要求每段核心行为都能回答:
它对应 Mermaid 的哪段源码?
为什么 Compose 端需要这个适配?
这种映射让项目可以持续跟进 Mermaid 上游,而不是维护一套只能靠视觉猜测差异的自研实现。
“Stable”不是标签,而是公开证据
“能解析”“能画出来”和“可以用于生产”之间还有很长距离。当前 Stable 结论由几层独立证据共同支撑:
1. 441 组独立生产场景
这些是手写的复杂结构,不来自 Demo Gallery,用于能力覆盖、确定性 SceneGraph 重放、人工视觉审查、性能压力和常规 Quality Gate。
- 独立生产场景:441 组 Native/Official 对拍;
- 已声明能力覆盖:738/738;
- 独立语料截图:882 张;
- 确定性 SceneGraph 重放:441 个通过,0 个不一致。
2. 8,448 组 Native/Official 视觉矩阵
33 类图每类 256 个唯一 Mermaid source,总计:
- 8,448 个 CMP Native 截图;
- 8,448 个 Mermaid.js
12.0.0Official 截图; - 16,896 张矩阵截图;
- 528 页 contact sheet,每页展示 16 组同源码结果;
- 8,448/8,448 通过几何门禁和细节审查;
- 其中 7,458 组自动通过,990 组经人工复核通过;
- 0 个未解决案例。
自动门禁检查空白图、严重裁切、内容边界、前景密度和几何异常;它不会被包装成“像素级完全一致”,因此全部 528 页 contact sheet 仍然经过人工审阅。
3. 单元、主题、压力和跨平台门禁
JVM tests: 787 passed, 0 failed
Theme matrix: 363 / 363
Native stress inputs: 7,936 passed
Platform builds: Android / iOS / Desktop / Web passed
完整报告和所有对比图都公开在仓库中:
- Stable 报告:github.com/swithun-liu…
- 8,448 案例视觉报告:github.com/swithun-liu…
- 33 类能力矩阵:github.com/swithun-liu…
0.1.6 已发布:可以直接接入
目前生产制品已经发布到 Maven Central 和 CocoaPods。
| 使用场景 | 制品 |
|---|---|
| Kotlin Multiplatform 核心能力 | io.github.swithun-liu:mermaid-core:0.1.6 |
| Compose Multiplatform 渲染 | io.github.swithun-liu:mermaid-compose:0.1.6 |
Kotlin 1.7.21 Android 核心能力 | io.github.swithun-liu:mermaid-core-android-kotlin17:0.1.6 |
Kotlin 1.7.21 Android Compose 渲染 | io.github.swithun-liu:mermaid-compose-android-kotlin17:0.1.6 |
| iOS 二进制 | CocoaPod CMPMermaid 0.1.6 |
KMP / CMP
dependencies {
implementation("io.github.swithun-liu:mermaid-compose:0.1.6")
}
Kotlin 1.7.21 Android
dependencies {
implementation(
"io.github.swithun-liu:mermaid-compose-android-kotlin17:0.1.6",
)
}
iOS / CocoaPods
pod 'CMPMermaid', '0.1.6'
制品页面:
Compose 基本用法:
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.swithun.cmpmermaid.compose.MermaidDiagram
import com.swithun.cmpmermaid.core.MermaidTheme
import com.swithun.cmpmermaid.core.MermaidThemePreset
@Composable
fun Diagram(source: String) {
MermaidDiagram(
source = source,
modifier = Modifier.fillMaxWidth(),
theme = MermaidTheme.preset(MermaidThemePreset.Default),
contentDescription = "Mermaid diagram",
)
}
跨平台情况
Parser、Diagram DB、布局准备、主题和 SceneGraph 主要位于 commonMain,构建和运行验证覆盖:
- Android;
- iOS;
- Desktop;
- Web(Kotlin/Wasm)。
在线 Demo 本身也是 Compose Multiplatform Web 版本,可以直接体验 33 类图表、11 个主题、源码实时编辑和 Native/Official 对比:
swithun-liu.github.io/cmp-mermaid…
仍然有哪些边界
Stable 的准确含义是:
在 Mermaid.js
12.0.0基线和项目公开声明的 738 个能力点范围内,33 个图表家族已经通过生产场景、视觉矩阵、单元测试、压力和跨平台门禁。
仍需明确的边界:
- 任意浏览器
themeCSS依赖 DOM/CSS 语义,Native 端不做静默近似; - Compose 与浏览器的字体度量不同,不追求逐像素完全一致;
- 输入内容异常与运行时异常会返回结构化错误,由宿主决定回退 UI;
- Mermaid.js 只存在于隔离的 Official/Debug 工具中,不进入生产模块。
这些边界全部公开记录。项目不会把未支持能力静默降级成一张“看起来差不多”的图。
最后
这个项目最初只想解决一个具体问题:
一个页面需要展示很多 Mermaid 图时,能不能不要创建很多 WebView?
现在,CMP Mermaid 已经完成 Mermaid 12.0.0 的 33/33 图表家族,生产制品也已进入 Maven Central 与 CocoaPods,并建立了完整、公开、可复现的视觉和跨平台证据。
如果你正在做 Kotlin Multiplatform、Compose Multiplatform、Markdown/文档工具,或者也遇到 Native Mermaid 渲染问题,可以直接体验或查看实现:
- GitHub:github.com/swithun-liu…
- Web Playground:swithun-liu.github.io/cmp-mermaid…
觉得项目有价值,欢迎 Star、提交 Issue,或者带真实 Mermaid case 来验证。