Hexo UML

1 PlantUML 简介

PlantUML是一个画图脚本语言,官方介绍如下:

Generate UML diagram from textual description

用它可以快速地画出:

  1. 顺序图
  2. 用例图
  3. 类图
  4. 活动图
  5. 组件图
  6. 状态图
  7. 对象图
  8. 部署图
  9. 时序图

对于工程师们来说,用代码的方式来画图,简直是为其量身定做的。PlantUML语法也非常简单,参见PlantUML Language Reference Guide,它支持很多工具,可以生成PNG、SVG、LaTeX和二进制图片。

2 插件安装

1
npm install hexo-tag-plantuml --save

3 语法

3.1 顺序图

3.1.1 声明参与者

  • 关键字 participant 用于改变参与者的先后顺序。

    你也可以使用其它关键字来声明参与者:

    • actor
    • boundary
    • control
    • entity
    • database
  • 关键字 as 用于重命名参与者

  • 您可以使用关键字 order自定义顺序来打印参与者。

  • 如果需要使用非字母符号,则需要使用引号

  • 你可以使用RGB值或者颜色名修改 actor 或参与者的背景颜色。

  • --> 绘制一个虚线箭头 ->绘制实线箭头

1
2
3
4
5
6
7
8
9
10
11
12
13
{% plantuml %}
actor Foo1 #red
boundary Foo2 #green
control Foo3 #blue
entity Foo4
database Foo5
collections Foo6
Foo1 -> Foo2 : To boundary
Foo1 -> Foo3 : To control
Foo1 -> Foo4 : To entity
Foo1 -> Foo5 : To database
Foo1 -> Foo6 : To collections
{% endplantuml %}

3.1.2 修改箭头样式

修改箭头样式的方式有以下几种:

  • 表示一条丢失的消息:末尾加 x
  • 让箭头只有上半部分或者下半部分:将<>替换成\或者 /
  • 细箭头:将箭头标记写两次 (如 >>//)
  • 虚线箭头:用 -- 替代 -
  • 箭头末尾加圈:->o
  • 双向箭头:<->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% plantuml %}
Bob ->x Alice
Bob -> Alice
Bob ->> Alice
Bob -\ Alice
Bob \\- Alice
Bob //-- Alice

Bob ->o Alice
Bob o\\-- Alice

Bob <-> Alice
Bob <->o Alice
{% endplantuml %}

3.1.3 修改箭头颜色

1
2
3
4
{% plantuml %}
Bob -[#red]> Alice : hello
Alice -[#0000FF]->Bob : ok
{% endplantuml %}

3.1.4 对消息序列编号

  • 关键字 autonumber 用于自动对消息编号。

  • 语句 autonumber *start* 用于指定编号的初始值,而 autonumber *start**increment* 可以同时指定编号的初始值和每次增加的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
{% plantuml %}
autonumber
Bob -> Alice : Authentication Request
Bob <- Alice : Authentication Response

autonumber 15
Bob -> Alice : Another authentication Request
Bob <- Alice : Another authentication Response

autonumber 40 10
Bob -> Alice : Yet another authentication Request
Bob <- Alice : Yet another authentication Response
{% endplantuml %}

3.1.5 分割示意图

关键字 newpage 用于把一张图分割成多张。

newpage 之后添加文字,作为新的示意图的标题。

这样就能很方便地在 Word 中将长图分几页打印。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% plantuml %}
Alice -> Bob : message 1
Alice -> Bob : message 2

newpage

Alice -> Bob : message 3
Alice -> Bob : message 4

newpage A title for the\nlast page

Alice -> Bob : message 5
Alice -> Bob : message 6
{% endplantuml %}

3.1.6 组合消息

我们可以通过以下关键词将组合消息:

  • alt/else

  • opt

  • loop

  • par

  • break

  • critical

  • group, 后面紧跟着消息内容

    可以在标头(header)添加需要显示的文字(group除外)。

    关键词 end 用来结束分组。

    注意,分组可以嵌套使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% plantuml %}
alt successful case
Bob -> Alice: Authentication Accepted
else some kind of failure
Bob -> Alice: Authentication Failure
group My own label
Alice -> Log : Log attack start
loop 1000 times
Alice -> Bob: DNS Attack
end
Alice -> Log : Log attack end
end
else Another type of failure
Bob -> Alice: Please repeat
end
{% endplantuml %}

3.1.7 添加注释

  • 给消息添加注释

    我们可以通过在消息后面添加 note left 或者 note right 关键词来给消息添加注释。

    你也可以通过使用 end note 来添加多行注释。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    {% plantuml %}
    Alice->Bob : hello
    note left: this is a first note

    Bob->Alice : ok
    note right: this is another note

    Bob->Bob : I am thinking
    note left
    a note
    can also be defined
    on several lines
    end note
    {% endplantuml %}
  • 其他注释

    可以使用note left ofnote right ofnote over在节点(participant)的相对位置放置注释。

    还可以通过修改背景色来高亮显示注释。

    以及使用关键字end note来添加多行注释。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    {% plantuml %}
    participant Alice
    participant Bob
    note left of Alice #aqua
    This is displayed
    left of Alice.
    end note

    note right of Alice: This is displayed right of Alice.

    note over Alice: This is displayed over Alice.

    note over Alice, Bob #FFAAAA: This is displayed\n over Bob and Alice.

    note over Bob, Alice
    This is yet another
    example of
    a long note.
    end note
    {% endplantuml %}
  • 改变备注框的形状

    你可以使用 hnoternote 这两个关键字来修改备注框的形状。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    {% plantuml %}
    caller -> server : conReq
    hnote over caller : idle
    caller <- server : conConf
    rnote over server
    "r" as rectangle
    "h" as hexagon
    endrnote
    {% endplantuml %}

3.1.8 分隔符

你可以通过使用 == 关键词来将你的图表分割多个步骤。

1
2
3
4
5
6
7
8
9
10
11
{% plantuml %}
== Initialization ==

Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response

== Repetition ==

Alice -> Bob: Another authentication Request
Alice <-- Bob: another authentication Response
{% endplantuml %}

3.1.9 引用

你可以在图中通过使用ref over关键词来实现引用

1
2
3
4
5
6
7
8
9
10
11
12
13
{% plantuml %}
participant Alice
actor Bob

ref over Alice, Bob : init

Alice -> Bob : hello

ref over Bob
This can be on
several lines
end ref
{% endplantuml %}

3.1.10 延迟

你可以使用...来表示延迟,并且还可以给延迟添加注释。

1
2
3
4
5
6
7
{% plantuml %}
Alice -> Bob: Authentication Request
...
Bob --> Alice: Authentication Response
...5 minutes latter...
Bob --> Alice: Bye !
{% endplantuml %}

3.1.11 增加空间

你可以使用|||来增加空间。

还可以使用数字指定增加的像素的数量。

1
2
3
4
5
6
7
8
9
10
{% plantuml %}
Alice -> Bob: message 1
Bob --> Alice: ok
|||
Alice -> Bob: message 2
Bob --> Alice: ok
||45||
Alice -> Bob: message 3
Bob --> Alice: ok
{% endplantuml %}

3.1.12 生命线的激活与撤销

关键字activatedeactivate用来表示参与者的生命活动。

一旦参与者被激活,它的生命线就会显示出来。

activatedeactivate适用于以上情形。

destroy表示一个参与者的生命线的终结。

还可以使用嵌套的生命线,并且运行给生命线添加颜色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{% plantuml %}
participant User

User -> A: DoWork
activate A #FFBBBB

A -> A: Internal call
activate A #DarkSalmon

A -> B: << createRequest >>
activate B

B --> A: RequestCreated
deactivate B
deactivate A
A -> User: Done
deactivate A
{% endplantuml %}

3.1.13 创建参与者

你可以把关键字create放在第一次接收到消息之前,以强调本次消息实际上是在创建新的对象。

1
2
3
4
5
6
7
8
9
10
11
12
{% plantuml %}
Bob -> Alice : hello

create Other
Alice -> Other : new

create control String
Alice -> String
note right : You can also put notes!

Alice --> Bob : ok
{% endplantuml %}

3.1.14 激活,停用,创建的快捷语法

在指定目标参与者之后,可以立即使用以下语法:

  • ++ Activate the target (optionally a #color may follow this)
  • -- Deactivate the source
  • ** Create an instance of the target
  • !! Destroy an instance of the target
1
2
3
4
5
6
7
8
9
10
{% plantuml %}
alice -> bob ++ : hello
bob -> bob ++ : self call
bob -> bib ++ #005500 : hello
bob -> george ** : create
return done
return rc
bob -> george !! : delete
return success
{% endplantuml %}

进入和发出消息

如果只想关注部分图示,你可以使用进入和发出箭头。

使用方括号[]表示图示的左、右两侧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% plantuml %}
[-> A: DoWork

activate A

A -> A: Internal call
activate A

A ->] : << createRequest >>

A<--] : RequestCreated
deactivate A
[<- A: Done
deactivate A
{% endplantuml %}

3.1.15 包裹参与者

可以使用boxend box画一个盒子将参与者包裹起来。

还可以在box关键字之后添加标题或者背景颜色。

1
2
3
4
5
6
7
8
9
10
{% plantuml %}
box "Internal Service" #LightBlue
participant Bob
participant Alice
end box
participant Other

Bob -> Alice : hello
Alice -> Other : hello
{% endplantuml %}

3.1.16 移除脚注

使用hide footbox关键字移除脚注。

1
2
3
4
5
6
7
{% plantuml %}
hide footbox
title Footer removed

Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response
{% endplantuml %}

3.1.17 外观参数(skinparam)

可以在如下场景中使用:

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
{% plantuml %}
skinparam sequenceArrowThickness 2
skinparam roundcorner 20
skinparam maxmessagesize 60
skinparam sequenceParticipant underline

actor User
participant "First Class" as A
participant "Second Class" as B
participant "Last Class" as C

User -> A: DoWork
activate A

A -> B: Create Request
activate B

B -> C: DoWork
activate C
C --> B: WorkDone
destroy C

B --> A: Request Created
deactivate B

A --> User: Done
deactivate A
{% endplantuml %}
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
34
35
36
37
38
39
40
41
42
43
44
{% plantuml %}
skinparam backgroundColor #EEEBDC
skinparam handwritten true

skinparam sequence {
ArrowColor DeepSkyBlue
ActorBorderColor DeepSkyBlue
LifeLineBorderColor blue
LifeLineBackgroundColor #A9DCDF

ParticipantBorderColor DeepSkyBlue
ParticipantBackgroundColor DodgerBlue
ParticipantFontName Impact
ParticipantFontSize 17
ParticipantFontColor #A9DCDF

ActorBackgroundColor aqua
ActorFontColor DeepSkyBlue
ActorFontSize 17
ActorFontName Aapex
}

actor User
participant "First Class" as A
participant "Second Class" as B
participant "Last Class" as C

User -> A: DoWork
activate A

A -> B: Create Request
activate B

B -> C: DoWork
activate C
C --> B: WorkDone
destroy C

B --> A: Request Created
deactivate B

A --> User: Done
deactivate A
{% endplantuml %}

3.2 用例图

3.2.1 用例

用例用圆括号括起来。

也可以用关键字usecase来定义用例。 还可以用关键字as定义一个别名,这个别名可以在以后定义关系的时候使用。

1
2
3
4
5
6
{% plantuml %}
(First usecase)
(Another usecase) as (UC2)
usecase UC3
usecase (Last\nusecase) as UC4
{% endplantuml %}

3.2.2 角色

角色用两个冒号包裹起来。

也可以用actor关键字来定义角色。 还可以用关键字as来定义一个别名,这个别名可以在以后定义关系的时候使用。

后面我们会看到角色的定义是可选的。

1
2
3
4
5
6
{% plantuml %}
:First Actor:
:Another\nactor: as Men2
actor Men3
actor :Last actor: as Men4
{% endplantuml %}

3.2.3 用例描述

如果想定义跨越多行的用例描述,可以用双引号将其裹起来。

还可以使用这些分隔符:--``..``==``__。 并且还可以在分隔符中间放置标题。

1
2
3
4
5
6
7
8
9
10
11
{% plantuml %}
usecase UC1 as "You can use
several lines to define your usecase.
You can also use separators.
--
Several separators are possible.
==
And you can add titles:
..Conclusion..
This allows large description."
{% endplantuml %}

3.2.4 基础示例

用箭头-->连接角色和用例。

横杠-越多,箭头越长。 通过在箭头定义的后面加一个冒号及文字的方式来添加标签。

在这个例子中,User并没有定义,而是直接拿来当做一个角色使用。

1
2
3
4
5
6
{% plantuml %}
User -> (Start)
User --> (Use the application) : A small label

:Main Admin: ---> (Use the application) : This is\nyet another\nlabel
{% endplantuml %}

3.2.5 继承

如果一个角色或者用例继承于另一个,那么可以用<|--符号表示。

1
2
3
4
5
6
7
{% plantuml %}
:Main Admin: as Admin
(Use the application) as (Use)

User <|-- Admin
(Start) <|-- (Use)
{% endplantuml %}

3.2.6 注释

可以用note left of , note right of , note top of , note bottom of等关键字给一个对象添加注释。

注释还可以通过note关键字来定义,然后用..连接其他对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{% plantuml %}
:Main Admin: as Admin
(Use the application) as (Use)

User -> (Start)
User --> (Use)

Admin ---> (Use)

note right of Admin : This is an example.

note right of (Use)
A note can also
be on several lines
end note

note "This note is connected\nto several objects." as N2
(Start) .. N2
N2 .. (Use)
{% endplantuml %}

3.2.7 构造类型

<<>> 来定义角色或者用例的构造类型。

1
2
3
4
5
6
7
8
9
10
11
{% plantuml %}
User << Human >>
:Main Database: as MySql << Application >>
(Start) << One Shot >>
(Use the application) as (Use) << Main >>

User -> (Start)
User --> (Use)

MySql --> (Use)
{% endplantuml %}

3.2.8 箭头方向

  • 默认连接是竖直方向的,用--表示,可以用一个横杠或点来表示水平连接。
  • 也可以通过翻转箭头来改变方向。
  • 还可以通过给箭头添加left, right, updown等关键字来改变方向。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% plantuml %}
:user: --> (Use case 1)
:user: -> (Use case 2)
{% endplantuml %}

{% plantuml %}
(Use case 1) <.. :user:
(Use case 2) <- :user:
{% endplantuml %}

{% plantuml %}
:user: -left-> (dummyLeft)
:user: -right-> (dummyRight)
:user: -up-> (dummyUp)
:user: -down-> (dummyDown)
{% endplantuml %}

3.2.9 分割图示

newpage关键字将图示分解为多个页面。

1
2
3
4
5
{% plantuml %}
:actor1: --> (Usecase1)
newpage
:actor2: --> (Usecase2)
{% endplantuml %}

3.2.10 构图方向

  • 默认从上往下构建图示。
  • 你可以用left to right direction命令改变图示方向。
1
2
3
4
5
6
7
8
9
10
11
12
{% plantuml %}
'default
top to bottom direction
user1 --> (Usecase 1)
user2 --> (Usecase 2)
{% endplantuml %}

{% plantuml %}
left to right direction
user1 --> (Usecase 1)
user2 --> (Usecase 2)
{% endplantuml %}

3.2.11 显示参数

skinparam改变字体和颜色。

可以在如下场景中使用:

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
{% plantuml %}
skinparam handwritten true

skinparam usecase {
BackgroundColor DarkSeaGreen
BorderColor DarkSlateGray

BackgroundColor<< Main >> YellowGreen
BorderColor<< Main >> YellowGreen

ArrowColor Olive
ActorBorderColor black
ActorFontName Courier

ActorBackgroundColor<< Human >> Gold
}

User << Human >>
:Main Database: as MySql << Application >>
(Start) << One Shot >>
(Use the application) as (Use) << Main >>

User -> (Start)
User --> (Use)

MySql --> (Use)
{% endplantuml %}

3.3 活动图

3.3.1 开始/结束

你可以使用关键字startstop表示图示的开始和结束。

1
2
3
4
5
6
7
{% plantuml %}
start
:Hello world;
:This is on defined on
several **lines**;
stop
{% endplantuml %}

3.3.2 条件语句

  • 可以使用关键字ifthenelse设置分支测试。标注文字则放在括号中。
  • 也可以使用关键字elseif设置多个分支测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% plantuml %}
start
if (condition A) then (yes)
:Text 1;
elseif (condition B) then (yes)
:Text 2;
stop
elseif (condition C) then (yes)
:Text 3;
elseif (condition D) then (yes)
:Text 4;
else (nothing)
:Text else;
endif
stop
{% endplantuml %}

3.3.3 循环

使用关键字repeatrepeatwhile进行重复循环。

1
2
3
4
5
6
7
8
9
10
{% plantuml %}
start

repeat
:read data;
:generate diagrams;
repeat while (more data?)

stop
{% endplantuml %}

使用关键字whileend while进行while循环。

1
2
3
4
5
6
7
8
9
10
{% plantuml %}
start

while (data available?)
:read data;
:generate diagrams;
endwhile

stop
{% endplantuml %}

3.3.4 并行处理

你可以使用关键字forkfork againend fork表示并行处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% plantuml %}
start

if (multiprocessor?) then (yes)
fork
:Treatment 1;
fork again
:Treatment 2;
end fork
else (monoproc)
:Treatment 1;
:Treatment 2;
endif

stop
{% endplantuml %}

3.3.5 注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% plantuml %}
start
:foo1;
floating note left: This is a note
:foo2;
note right
This note is on several
//lines// and can
contain <b>HTML</b>
====
* Calling the method ""foo()"" is prohibited
end note
stop
{% endplantuml %}

3.3.6 颜色

你可以为活动(activity)指定一种颜色

1
2
3
4
5
6
7
8
{% plantuml %}
start
:starting progress;
#HotPink:reading configuration files
These files should edited at this point!;
#AAAAAA:ending of the process;
stop
{% endplantuml %}

3.3.7 箭头

使用->标记,你可以给箭头添加文字或者修改箭头颜色

同时,你也可以选择点状 (dotted),条状(dashed),加粗或者是隐式箭头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{% plantuml %}
:foo1;
-> You can put text on arrows;
if (test) then
-[#blue]->
:foo2;
-[#green,dashed]-> The text can
also be on several lines
and **very** long...;
:foo3;
else
-[#black,dotted]->
:foo4;
endif
-[#gray,bold]->
:foo5;
{% endplantuml %}

3.3.8 连接器

你可以使用括号定义连接器

1
2
3
4
5
6
7
8
9
{% plantuml %}
start
:Some activity;
(A)
detach
(A)
:Other activity;
stop
{% endplantuml %}

3.3.9 组合

通过定义分区(partition),你可以把多个活动组合(group)在一起。

1
2
3
4
5
6
7
8
9
10
11
12
13
{% plantuml %}
start
partition Initialization {
:read config file;
:init internal variable;
}
partition Running {
:wait for user interaction;
:print information;
}

stop
{% endplantuml %}

3.3.10 泳道

你可以使用管道符|来定义泳道。

还可以改变泳道的颜色

1
2
3
4
5
6
7
8
9
10
11
12
13
{% plantuml %}
|Swimlane1|
start
:foo1;
|#AntiqueWhite|Swimlane2|
:foo2;
:foo3;
|Swimlane1|
:foo4;
|Swimlane2|
:foo5;
stop
{% endplantuml %}

3.3.11 分离

可以使用关键字detach移除箭头。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{% plantuml %}
:start;
fork
:foo1;
:foo2;
fork again
:foo3;
detach
endfork
if (foo4) then
:foo5;
detach
endif
:foo6;
detach
:foo7;
stop
{% endplantuml %}

3.3.12 特殊领域语言(SDL)

通过修改活动标签最后的分号分隔符(;),可以为活动设置不同的形状。

  • |
  • <
  • >
  • /
  • ]
  • }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{% plantuml %}
:Ready;
:next(o)|
:Receiving;
split
:nak(i)<
:ack(o)>
split again
:ack(i)<
:next(o)
on several line|
:i := i + 1]
:ack(o)>
split again
:err(i)<
:nak(o)>
split again
:foo/
split again
:i > 5}
stop
end split
:finish;
{% endplantuml %}

3.3.13 完整实例

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
34
35
{% plantuml %}
start
:ClickServlet.handleRequest();
:new page;
if (Page.onSecurityCheck) then (true)
:Page.onInit();
if (isForward?) then (no)
:Process controls;
if (continue processing?) then (no)
stop
endif

if (isPost?) then (yes)
:Page.onPost();
else (no)
:Page.onGet();
endif
:Page.onRender();
endif
else (false)
endif

if (do redirect?) then (yes)
:redirect process;
else
if (do forward?) then (yes)
:Forward request;
else (no)
:Render page template;
endif
endif

stop

{% endplantuml %}

3.4 类图

4 思维导图

4.1 安装插件

1
npm install hexo-simple-mindmap

4.2 使用

1
2
3
4
5
6
7
8
{% pullquote mindmap mindmap-md %}
- [在 Hexo 中使用思维导图](https://hunterx.xyz/use-mindmap-in-hexo.html)
- 前言
- 操作指南
- 准备需要的文件
- 为主题添加 CSS/JS 文件
- 使用方法
{% endpullquote %}