# 当 Markdown 遇上 UML

# 引言

程序员喜欢简洁,所以 Markdown 作为轻量级、纯文本的格式化标记语言深受喜爱。在书写技术文档时,让程序员感受到「世界的美好」,将其从 Office 各种格式化问题的泥潭中解放出来,专注生产。

写技术文档不免需要要结合 UML 配图,以让读者更方便直观的理解。那么,同理,有没有什么工具/语言能让程序员免于下盗版 Visio 的痛苦?或者 ProcessOn 对 UML 支持有限的痛苦?再或者 Draw.io 连接慢的痛苦?

当然,我们能想到的大多场景,早已有人也在深受折磨后,造好了轮子。

# PlantUML 是什么

PlantUML 是一个开源项目,支持以特定简单直观的语法,来描述多种图表,并转化成图片,或者整合在 Markdown 中。支持 UML 中的类图、时序图、用例图等,非 UML 支持 LaxTex、思维导图、甘特图、架构图等,具体支持情况请参见官网。

# PlantUML 语法

PlantUML 提供的语法极其简单,几分钟就能上手,下面是声明语法:

开头 @startuml 和结尾 @enduml 是声明,若要放在 Markdown 里面的话,需要放在代码块中,声明为 plantuml,如下:

​```plantuml
@startuml
...do your own stuff
@enduml
​```
1
2
3
4
5

下面是我写的一些简单的例子,你可以去官网在线渲染服务 get your hands dirty。

# 类图

  • PlantUML 代码
​```plantuml
@startuml
Thanos -up-> InfinityGauntlet : use

SoulStone -up-|> InfinityStone
TimeStone -up-|> InfinityStone
SpaceStone -up-|> InfinityStone
MindStone -up-|> InfinityStone
RealityStone -up-|> InfinityStone
PowerStone -up-|> InfinityStone

SoulStone --o InfinityGauntlet
TimeStone --o InfinityGauntlet
SpaceStone --o InfinityGauntlet
MindStone --o InfinityGauntlet
RealityStone --o InfinityGauntlet
PowerStone --o InfinityGauntlet

interface InfinityStone {}

class InfinityGauntlet {
  snap()
}

note left:  需集齐6颗无限宝石

note "灭霸使用无限手套打响指" as N

N .. Thanos
InfinityGauntlet .. N
@enduml
​```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  • 生成后效果
uml diagram

可以看出,类之间关系的箭头,通过如 --|>--o 之类的符号,很直观的映射成了图中的关系,短横线 - 的长短决定了图中关系线的长短,还可以在短横线中加方向关键字 -up-> 来改变布局。下面是一些图例,一图胜千言:

plantuml-example

关系的声明和元素(类、接口)的声明是分开的,若仅有关系的声明,那么元素默认为类。你可以通过声明语法来改变元素的类型,并添加元素的成员变量和方法(其可访问性修饰符号也和 UML 一致),语法和 Java 很像:

​```plantuml
@startuml
skinparam classAttributeIconSize 0
// 声明类
class Dummy {
 -{static} field1
 #field2
 ~method1()
 +{abstract} method2()
}
// 声明枚举
enum TimeUnit {
  DAYS
  HOURS
  MINUTES
}
// 声明抽象类
abstract class AbstractList
// 声明接口
interface List
@enduml
​```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 时序图

  • PlantUML 代码
​```plantuml
@startuml
actor 需求 #yellow
actor 开发 #green
actor 测试 #red

需求 -> 开发: 要加个小需求
开发 -> 需求: 这个实现不了
需求 -> 开发: 这个很重要,客户都快投诉了
activate 开发
开发 ->>x 测试: 终于写完了
return 需求验证
开发 -> 开发: 还是先自测下
开发 -> 测试: 提测,你点几下
测试 ->> 开发: 有个 bug
开发 -> 测试: 这个需求不明确
测试 -> 需求: 这个需求需要明确下
[->> 需求: 客户确认
需求 ->> 开发: 那个这么改
开发 -> 需求: 这么改会影响以前的功能
需求 -> 开发: 那把以前的功能也改了啊
开发 -> 开发  ++ : 我...
return 增量需求开发完成
开发 -> 需求: 改完了,验证下,这回不会变了吧
[->> 需求: 客户又确认
需求 -> 开发: 放一百个心,客户说了...
开发 ->> 测试: 终于改完了,快测下发版
[->> 需求: 客户再...
需求 ->> 开发: 等下,客户又说了...
测试 ->> 开发: 之前的功能改出 bug 了
开发 --> 开发 !! : 猝
@enduml
​```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  • 生成后效果
uml diagram

# PlantUML 集成

PlantUML 的本质就是一个解析文本并转图片的渲染服务,所以你可以使用其官方的渲染服务,也可以自己本地搭设,主要有两种方式

  • JAR (with Maven)
mvn jetty:run -Djetty.port=9999
1
  • Docker
# 直接运行
docker run -d -p 8080:8080 plantuml/plantuml-server:jetty
docker run -d -p 8080:8080 plantuml/plantuml-server:tomcat
# 拉镜像
docker pull plantuml/plantuml-server
1
2
3
4
5

将 PlantUML 和你现有的工具流集成也不是件麻烦事,下面简单介绍下我常用工具的集成,其它未提及的,可以探索下官网教程

# 编辑器

# Typora( Winows / Mac OS / Linux )

作为 Markdown 编辑器中的明星产品,Typora 对图表绘制仅做了有限的支持,不过支持无需第三方服务完成本地渲染。缺乏对 UML 更全面的支持(一般的需求也已覆盖)实在让人叹息,值得让人期待的是,官方有个 issue 列举了对一些图表库/语法,其中 PlantUML 呼声最高,后续可能会考虑支持。

若现在你的写作流 Typora 是无可替代的,那么只能采取先将 PlantUML 转成图片,上传图床,再把图片贴回来。

# MWeb( Mac OS )

国产独立开发者做的 Markdown 编辑器精品还真不少,MWeb 对 PlantUML 原生支持,无需第三方服务可完成实时渲染,也支持导出图片、PDF 等,很是省心。这家伙甚至丧心病狂的支持了 echarts。

# VSCode( Winows / Mac OS / Linux )

大厂的编辑器品质有保证,在 M$ 收购 Github 前,同样使用 Electron 开发的 VSCode 比 Atom 性能高出不是一星半点(而且 Electron 还是 Github 开发的)。使用 VSCode 最大的幸福感之一坐拥无比繁荣的插件生态,要什么样的自行车,丰俭由君。支持 Markdown 中使用 PlantUML 主要涉及两个插件:PlantUMLMarkdown Extended,前者主要集成 PlantUML 渲染服务以及语法高亮,后者主要提供转化文件。

Tips:

  • PlantUML 插件需要配置渲染服务的地址,你可以使用官网提供的,也可以本地搭一个,在 settings.json 里添加:
"plantuml.server": "https://www.plantuml.com/plantuml",
"plantuml.render": "PlantUMLServer",
1
2
  • PlantUML 插件仅能将某一块 PlantUML 代码转换成图片,Markdown Extended 插件可以将整个 Markdown 文件(含 UML 转化)转化为 PDF 等格式。Ctrl/Cmd + Shift + P 唤出 VSCode 的命令面板,输入 export 搜索就会出现 Markdown: Export Markdown To File 条目,选择后会提示下载 chromium(因为是基于 puppeteer 的),下载后就能转化了。

# IntelliJ IDEA( Winows / Mac OS / Linux )

IDEA 的支持也是靠插件:PlantUML integration,安装完成后,Ctrl + Shift + A 唤出 IDEA 的 Action 搜索 PlantUML,选择 PlantUML File New,可根据不同的类别直接生成模板。此插件同样支持在无需配置渲染服务的情况下,实时浏览。唯一的不足是,不支持整个 Markdown 文件支持导出,PlantUML 代码只能挨个导出图片。

# 服务

# Gitlab

Gitlab 从 8.16 开始就支持了 PlantUML 集成,未自己试过,可以参考下官方文档

# VuePress

VuePress 是 Vue 官方出品的一款静态网站生成器,可以实现用 Markdown 写博客/文档,同时还支持 Vue 的一些特性。由于 VuePress 使用 markdown-it 作为其 Markdown 渲染器,所以就可以使用 markdown-it 的插件来支持。

npm 安装:

npm i -D markdown-it-plantuml
1

编辑 .vuepress/config.js 文件:

module.exports = {
	markdown: {
		extendMarkdown: (md) => {
			md.use(require('markdown-it-plantuml'))
		},
	},
}
1
2
3
4
5
6
7

# 结语

“Sometimes the truth of a thing is not so much in the think of it, but in the feel of it.”

​ —STANLEY KUBRICK

最后,引述 John Gruber 在其 Dive Into Markdown 一文中对创造 Markdown 的想法,来总结下我折腾 PlantUML 的初衷。

我在文章开始引用库布里克的话是我非常喜欢的之一。当你在用 HTML 标签写作时,它迫使你将注意力耗散在思考(样式)上,而不是在感受上。但正是后者,才是我想 Markdown 作为格式化语言所去传达的。

PlantUML 正是作为一种简单直观的语言来描述图表,正像 Markdown 当时将人们从 HTML 中解放出来一样,将人们的注意力聚焦在内容本身的思考(类的设计,交互的时序等),而不是在一个 GUI 工具里面拖拽方框,然后将其摆得好看。