SSmd

在 Markdown 里用 Mermaid 画图:流程图和时序图实例

在 Markdown 文件里用几行文字画出流程图和时序图:能直接照抄的例子、常用语法,以及 Mermaid 图画不出来的几种常见原因,包括中文标点引起的问题。

Mermaid 能把几行文字变成一张图。把它写在标着 mermaid 的代码块里,支持 Mermaid 的应用就会把图画出来,GitHub、GitLab、Obsidian、Typora 和 SSmd 都支持。在不支持的地方,读者看到的是代码,也照样看得懂。这正是用它的理由:图和周围的文字待在同一个文本文件里,在哪都能改,改了什么,在版本对比里和改一行字一样清楚。

下面每个例子都用 SSmd 内置的 Mermaid 12.2.0 画过,配图就是它画出来的样子。

第一张流程图

flowchart TD
    A[草稿] --> B{可以发了吗?}
    B -->|可以| C[导出 PDF]
    B -->|还不行| D[再改改]
    D --> B
一张流程图:草稿指向判断“可以发了吗?”,“可以”通向导出 PDF,“还不行”通向再改改,再改改又回到判断。

第一行写图的类型和方向。TD 是从上到下,LR 是从左到右,BT 和 RL 反过来。之后每一行连接两个节点。A[草稿] 创建一个 id 为 A、显示为“草稿”的节点;之后单写 A 就是指这个节点,D --> B 就是这样连回去的。

在旧一点的例子里,你可能会看到 graph TD,那是同一种图以前的写法,现在照样能用。

节点形状

文字外面的括号决定形状:

写法 形状
A[文字] 矩形
A(文字) 圆角矩形
A([文字]) 胶囊形
A{文字} 菱形,用来表示判断
A[(文字)] 圆柱,用来表示数据库
A((文字)) 圆形
写法 连线
A --> B 箭头
A --- B 无箭头的线
A -.-> B 虚线箭头
A ==> B 粗箭头
A -->|文字| B 带文字的箭头
A <--> B 双向箭头

分组

subgraph 会给相关的节点画一个框,结尾要有对应的 end:

flowchart LR
    subgraph 我的 Mac
        E[编辑器] --> F[(笔记.md)]
    end
    subgraph 备份
        S[iCloud 云盘]
        G[Git 仓库]
    end
    F <--> S
    F --> G
一张从左到右的流程图,有两个框:“我的 Mac”里编辑器指向“笔记.md”圆柱;“备份”里 iCloud 云盘与笔记.md 双向同步,笔记.md 还指向 Git 仓库。

时序图

时序图按从上到下的顺序,画出谁给谁发了什么。每个参与者占一条竖线:

sequenceDiagram
    actor U as 你
    participant A as 应用
    participant S as 服务器
    U->>A: 点击登录
    A->>S: 校验密码
    alt 密码正确
        S-->>A: 返回令牌
        A-->>U: 打开收件箱
    else 密码错误
        S-->>A: 返回错误
        A-->>U: 请重新输入
    end
    Note over A,S: 全程 HTTPS
一张时序图,参与者是你、应用和服务器:你点击登录,应用向服务器校验密码,接着分两种情况:返回令牌并打开收件箱,或者返回错误并请你重新输入。

->> 是带箭头的实线,表示请求;-->> 是虚线,表示回应。participant S as 服务器 给短 id 配一个显示名,actor 会画成小人而不是方框。

alt 和 else 表示几种情况二选一,opt 表示可能发生也可能不发生的一步,loop 表示重复,它们都以 end 结束。Note over A,S: 在两个参与者上方横跨一条备注,只放在一侧用 Note right of A:。

其他图

Mermaid 能画的不止这两种:甘特图(gantt)、饼图(pie)、类图(classDiagram)、状态图(stateDiagram-v2)、实体关系图(erDiagram)、思维导图(mindmap)、时间线(timeline)等等。甘特图值得学一下,计划写在文本文件里,改起来最方便:

gantt
    title 写报告
    dateFormat YYYY-MM-DD
    axisFormat %m-%d
    section 初稿
    查资料   :a1, 2026-11-02, 4d
    写初稿   :a2, after a1, 5d
    section 审阅
    收集意见 :b1, after a2, 3d
    定稿     :b2, after b1, 2d
一张标题为“写报告”的甘特图:初稿部分是查资料和写初稿,审阅部分是收集意见和定稿,每项任务在上一项结束后开始。

dateFormat 说明日期怎么写,axisFormat 决定坐标轴怎么显示。每一行任务依次是名称、可选的 id、开始时间和时长。开始时间可以写日期,也可以写 after 加另一个任务的 id,这样查资料多花一天,只要改一个数字,后面的任务会跟着顺延。

Mermaid 每次发版都会加新语法,而各个应用更新内置 Mermaid 的时间不一样。如果一张图在官方的 Mermaid Live Editor 里能画,在你的应用里画不出来,多半是应用里的版本旧了。

图为什么画不出来

冒号、括号打成了全角

用中文输入法写时序图,很容易把消息前的冒号打成全角的 :,这时整张图都画不出来:

sequenceDiagram
    你->>应用:点击登录

参与者和消息之间必须是半角冒号 :。消息文字里面用全角标点没关系,A->>B: 好的,收到。 能正常显示。

节点文字里的全角括号也没关系,A[保存(⌘S)] 能画出来;出问题的是半角括号,下面会说到。

节点叫 end

在流程图里,end 用来结束一个分组,所以名叫 end 的节点会让整张图失败:

flowchart LR
    start --> end

改成大写(End 或 END),或者换个 id 再加显示名:done[end]。

文字里有半角括号

节点文字里的半角方括号、圆括号会被当成形状语法,所以这样写会报错:

flowchart LR
    A[保存 (⌘S)] --> B[完成]

给文字加上双引号,里面写什么都行:A["保存 (⌘S)"]。

节点以 o 或 x 开头

A---oB 连到的并不是叫 oB 的节点,而是画一条末端带圆圈的线连到 B;---x 末端是叉。中间加个空格写成 A--- oB,或者把字母改成大写。

少了第一行

第一行必须写明是哪种图:flowchart、sequenceDiagram、pie 等等。少了这一行,后面写得再对也画不出来。

Typora 的 flow 和 sequence 代码块

Typora 还支持两种更老的格式:给 flowchart.js 写的 flow 代码块,和给 js-sequence-diagrams 写的 sequence 代码块。SSmd 两种都能画,从 Typora 带过来的文档不会丢图:

st=>start: 开始
op=>operation: 写初稿
cond=>condition: 满意吗?
e=>end: 发布
st->op->cond
cond(yes)->e
cond(no)->op
一张 flowchart.js 流程图:开始,写初稿,然后判断“满意吗?”,yes 通向发布,no 回到写初稿。

新写的文档建议用 Mermaid,它一直有人维护,支持的地方也多得多。js-sequence-diagrams 已经很多年没有更新了,所以 SSmd 会先把 sequence 代码块翻译成 Mermaid 再画。

在 SSmd 里用 Mermaid

输入三个反引号和 mermaid,写好图,再把光标移出代码块,代码就会换成图。点一下图,代码又回来了。

SSmd 打开一篇名为“一篇文章的诞生”的文档,页面中间是一张流程图:收集灵感、写下初稿,判断“读起来顺吗?”,还不顺就再改一遍,顺了就分享出去。
光标离开 Mermaid 代码块后,SSmd 里显示的样子。

图的颜色跟着你选的纸张走,白色、米黄、石墨、黑色上都很协调。导出 PDF 时图保持矢量,放多大都清楚。图是在你的 Mac 上用应用内置的 Mermaid 画的,不会往外发送任何内容。代码有错时,SSmd 会在图的位置显示错误,点进去改就行。

刚接触 Markdown 的话,在 Mac 上写 Markdown讲了基础写法。