Mermaid 和 PlantUML 实操指南:如何导出 PNG、SVG 图片并发布到 CSDN

很多同学第一次接触 Mermaid 和 PlantUML 时,都会有一个很实际的问题:

我会写语法了,也能在 Markdown 里预览图表,但如果我要发到 CSDN,怎么把它们导出成 pngsvg 这种真正的图片?

这篇文章就不再停留在"会写语法"的层面,而是直接做一遍实操,带你把 Mermaid 和 PlantUML 图表导出成图片,并整理成适合发布到 CSDN 的使用方式。

文章主要解决这几个问题:

  • Mermaid 怎么导出 pngsvg
  • PlantUML 怎么导出 pngsvg
  • 命令行方式怎么用
  • 有哪些适合新手的简单办法
  • 导出后怎么更适合发到 CSDN

如果你只是想先看结论,可以记住这一句,命令行方式更专业,在线方式更方便,可以根据实际情况选择。

命令行方式导出图片:

  • Mermaid 常用 mmdc 导出图片
  • PlantUML 常用 plantuml.jar 导出图片

在线方式导出图片:

下面开始实操。

1. 为什么发布到 CSDN 更建议导出成图片

虽然 Mermaid 在很多 Markdown 环境里都能自动渲染,但 CSDN 并不是所有场景都能稳定原生渲染 Mermaid 代码块。

所以如果你准备把文章长期发布到 CSDN,通常更推荐这两种写法:

  • 方案一:正文里放导出的图片,保证读者打开就能看到图
  • 方案二:图片 + 源码一起放,既能看效果,也能学语法

这样做的好处很明显:

  • 兼容性更好
  • 读者不依赖特定编辑器
  • 手机端阅读更稳定
  • 不容易出现"代码显示了但图没渲染"的问题

2. Mermaid 导出 PNG 和 SVG 的实操

Mermaid 最常用的导出方式,是使用官方 CLI 工具:@mermaid-js/mermaid-cli

2.1 准备环境

你需要先安装 Node.js。安装完成后,打开终端,执行下面这条命令安装 Mermaid CLI:

bash 复制代码
npm install -g @mermaid-js/mermaid-cli

安装完成后,可以执行下面的命令检查是否成功:

bash 复制代码
mmdc -h

如果能看到帮助信息,说明安装成功。

2.2 先准备一个 Mermaid 源文件

新建一个文件,比如:login-flow.mmd

内容如下:
#mermaid-svg-O3nXw2H3ET7QLKTz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-O3nXw2H3ET7QLKTz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-O3nXw2H3ET7QLKTz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-O3nXw2H3ET7QLKTz .error-icon{fill:#552222;}#mermaid-svg-O3nXw2H3ET7QLKTz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-O3nXw2H3ET7QLKTz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-O3nXw2H3ET7QLKTz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-O3nXw2H3ET7QLKTz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-O3nXw2H3ET7QLKTz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-O3nXw2H3ET7QLKTz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-O3nXw2H3ET7QLKTz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-O3nXw2H3ET7QLKTz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-O3nXw2H3ET7QLKTz .marker.cross{stroke:#333333;}#mermaid-svg-O3nXw2H3ET7QLKTz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-O3nXw2H3ET7QLKTz p{margin:0;}#mermaid-svg-O3nXw2H3ET7QLKTz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-O3nXw2H3ET7QLKTz .cluster-label text{fill:#333;}#mermaid-svg-O3nXw2H3ET7QLKTz .cluster-label span{color:#333;}#mermaid-svg-O3nXw2H3ET7QLKTz .cluster-label span p{background-color:transparent;}#mermaid-svg-O3nXw2H3ET7QLKTz .label text,#mermaid-svg-O3nXw2H3ET7QLKTz span{fill:#333;color:#333;}#mermaid-svg-O3nXw2H3ET7QLKTz .node rect,#mermaid-svg-O3nXw2H3ET7QLKTz .node circle,#mermaid-svg-O3nXw2H3ET7QLKTz .node ellipse,#mermaid-svg-O3nXw2H3ET7QLKTz .node polygon,#mermaid-svg-O3nXw2H3ET7QLKTz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-O3nXw2H3ET7QLKTz .rough-node .label text,#mermaid-svg-O3nXw2H3ET7QLKTz .node .label text,#mermaid-svg-O3nXw2H3ET7QLKTz .image-shape .label,#mermaid-svg-O3nXw2H3ET7QLKTz .icon-shape .label{text-anchor:middle;}#mermaid-svg-O3nXw2H3ET7QLKTz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-O3nXw2H3ET7QLKTz .rough-node .label,#mermaid-svg-O3nXw2H3ET7QLKTz .node .label,#mermaid-svg-O3nXw2H3ET7QLKTz .image-shape .label,#mermaid-svg-O3nXw2H3ET7QLKTz .icon-shape .label{text-align:center;}#mermaid-svg-O3nXw2H3ET7QLKTz .node.clickable{cursor:pointer;}#mermaid-svg-O3nXw2H3ET7QLKTz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-O3nXw2H3ET7QLKTz .arrowheadPath{fill:#333333;}#mermaid-svg-O3nXw2H3ET7QLKTz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-O3nXw2H3ET7QLKTz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-O3nXw2H3ET7QLKTz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-O3nXw2H3ET7QLKTz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-O3nXw2H3ET7QLKTz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-O3nXw2H3ET7QLKTz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-O3nXw2H3ET7QLKTz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-O3nXw2H3ET7QLKTz .cluster text{fill:#333;}#mermaid-svg-O3nXw2H3ET7QLKTz .cluster span{color:#333;}#mermaid-svg-O3nXw2H3ET7QLKTz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-O3nXw2H3ET7QLKTz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-O3nXw2H3ET7QLKTz rect.text{fill:none;stroke-width:0;}#mermaid-svg-O3nXw2H3ET7QLKTz .icon-shape,#mermaid-svg-O3nXw2H3ET7QLKTz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-O3nXw2H3ET7QLKTz .icon-shape p,#mermaid-svg-O3nXw2H3ET7QLKTz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-O3nXw2H3ET7QLKTz .icon-shape .label rect,#mermaid-svg-O3nXw2H3ET7QLKTz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-O3nXw2H3ET7QLKTz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-O3nXw2H3ET7QLKTz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-O3nXw2H3ET7QLKTz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

用户打开登录页
输入账号密码
校验成功?
进入系统首页
提示账号或密码错误

注意:这里文件扩展名常见可以用 .mmd,也可以用 .mermaid,本质上都是 Mermaid 源文件。

2.3 导出 PNG

执行下面命令:

bash 复制代码
mmdc -i login-flow.mmd -o login-flow.png

参数说明:

  • -i 表示输入文件
  • -o 表示输出文件

执行完成后,当前目录下就会生成一张 login-flow.png 图片。

2.4 导出 SVG

如果你想导出矢量图,执行:

bash 复制代码
mmdc -i login-flow.mmd -o login-flow.svg

SVG 的优点是:

  • 放大不失真
  • 更适合文档、博客、技术资料
  • 后续做排版时更灵活

如果你的文章图表比较偏流程说明、架构图、时序图,我个人更推荐优先导出 svg

2.5 导出时指定主题和背景

你还可以在导出时顺手指定主题和背景色,例如:

bash 复制代码
mmdc -i login-flow.mmd -o login-flow.png -t neutral -b white

常见参数:

  • -t neutral:使用较中性的主题
  • -b white:设置白色背景

如果你准备发到 CSDN,白底通常更稳,不容易因为页面背景色影响图表观感。

2.6 Mermaid 导出完整示例

下面是一组最常用命令,基本够日常使用:

bash 复制代码
mmdc -i login-flow.mmd -o login-flow.png
mmdc -i login-flow.mmd -o login-flow.svg
mmdc -i login-flow.mmd -o login-flow.png -t neutral -b white

3. PlantUML 导出 PNG 和 SVG 的实操

如果你平时写的是类图、用例图、组件图、部署图,那么 PlantUML 会更常用。

PlantUML 最常见的导出方式,是通过 plantuml.jar 来生成图片。

3.1 准备环境

PlantUML 运行依赖 Java,所以你需要先安装 JDK 或 JRE。

安装完成后,先检查 Java 是否可用:

bash 复制代码
java -version

如果命令能正常输出 Java 版本,就说明环境没问题。

接着准备 plantuml.jar 文件。你可以从 PlantUML 官方渠道下载这个 jar 包,然后把它放到一个你方便操作的目录里。

例如:

text 复制代码
D:\tools\plantuml\plantuml.jar

3.2 先准备一个 PlantUML 源文件

新建文件:login-sequence.puml

内容如下:

plantuml 复制代码
@startuml
actor User
participant Frontend
participant Backend
participant Database

User -> Frontend: 提交登录表单
Frontend -> Backend: 发送登录请求
Backend -> Database: 查询用户信息
Database --> Backend: 返回用户记录
Backend --> Frontend: 返回 Token
Frontend --> User: 登录成功
@enduml

3.3 导出 PNG

执行下面命令:

bash 复制代码
java -jar plantuml.jar login-sequence.puml

注意:PlantUML 默认导出的就是 png

也就是说,这条命令执行后,会直接生成:

text 复制代码
login-sequence.png

3.4 导出 SVG

如果你想导出 SVG,可以加上 -tsvg 参数:

bash 复制代码
java -jar plantuml.jar -tsvg login-sequence.puml

执行后会生成:

text 复制代码
login-sequence.svg

3.5 PlantUML 导出完整示例

最常用的命令一般就是这两条:

bash 复制代码
java -jar plantuml.jar login-sequence.puml
java -jar plantuml.jar -tsvg login-sequence.puml

如果你的 plantuml.jar 不在当前目录,需要写完整路径,例如:

bash 复制代码
java -jar D:\tools\plantuml\plantuml.jar login-sequence.puml
java -jar D:\tools\plantuml\plantuml.jar -tsvg login-sequence.puml

4. 批量导出图片怎么做

如果你有很多图,一个一个导出会比较麻烦,这时候就可以考虑批量处理。

4.1 PlantUML 批量导出

假设你有一个 diagrams 目录,里面放了多个 .puml 文件:

bash 复制代码
java -jar plantuml.jar diagrams

这样 PlantUML 会自动处理目录中的图文件,并生成对应图片。

如果要批量导出为 SVG:

bash 复制代码
java -jar plantuml.jar -tsvg diagrams

4.2 Mermaid 批量导出思路

Mermaid CLI 更常见的是单文件导出。如果你有多个 .mmd 文件,可以写脚本循环调用 mmdc

例如思路上可以这样理解:

  • 遍历目录里的每个 .mmd 文件
  • 对每个文件执行一次 mmdc -i xxx.mmd -o xxx.png

如果后面你需要,我还可以单独帮你写一份 Windows 批处理版或者 PowerShell 批量导出脚本。

5. 导出图片后,怎么更适合发到 CSDN

这部分非常实用,因为很多人明明会导出图片了,但发到 CSDN 后排版仍然不理想。

我比较推荐下面这种方式。

5.1 正文先放效果图

比如你在文章里先写:

markdown 复制代码
### 登录流程图

![登录流程图](图片地址)

这样读者一打开文章就能直接看到结果,不用先理解语法。

5.2 图后面再放源码

在展示完图片后,再补一段源码:

markdown 复制代码
```mermaid
flowchart TD
    A[用户打开登录页] --> B[输入账号密码]
    B --> C{校验成功?}
    C -->|是| D[进入系统首页]
    C -->|否| E[提示账号或密码错误]
    E --> B
```

这样的阅读体验会更好:

  • 先看结果
  • 再学写法
  • 读者更容易接受

5.3 优先使用白底图片

技术博客大多是浅色背景,白底图片最稳妥。

尤其是 Mermaid,如果直接导出透明背景图,在某些页面主题下可能会显得发灰,或者边界不明显。

所以更建议:

  • PNG 导出时设置白底
  • SVG 导出后也检查一下背景和线条对比度

5.4 图片命名尽量语义化

不建议用 1.png2.png 这种名字。

更推荐:

  • login-flow.png
  • order-sequence.svg
  • system-architecture.png

后续维护和替换时会方便很多。

6. 一个完整的 Mermaid 导出示例

下面直接走一遍最小可用流程。

第一步:新建源文件

文件名:order-flow.mmd
#mermaid-svg-LhXmhPXamtxBZZ4k{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LhXmhPXamtxBZZ4k .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LhXmhPXamtxBZZ4k .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LhXmhPXamtxBZZ4k .error-icon{fill:#552222;}#mermaid-svg-LhXmhPXamtxBZZ4k .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LhXmhPXamtxBZZ4k .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LhXmhPXamtxBZZ4k .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LhXmhPXamtxBZZ4k .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LhXmhPXamtxBZZ4k .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LhXmhPXamtxBZZ4k .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LhXmhPXamtxBZZ4k .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LhXmhPXamtxBZZ4k .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LhXmhPXamtxBZZ4k .marker.cross{stroke:#333333;}#mermaid-svg-LhXmhPXamtxBZZ4k svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LhXmhPXamtxBZZ4k p{margin:0;}#mermaid-svg-LhXmhPXamtxBZZ4k .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LhXmhPXamtxBZZ4k .cluster-label text{fill:#333;}#mermaid-svg-LhXmhPXamtxBZZ4k .cluster-label span{color:#333;}#mermaid-svg-LhXmhPXamtxBZZ4k .cluster-label span p{background-color:transparent;}#mermaid-svg-LhXmhPXamtxBZZ4k .label text,#mermaid-svg-LhXmhPXamtxBZZ4k span{fill:#333;color:#333;}#mermaid-svg-LhXmhPXamtxBZZ4k .node rect,#mermaid-svg-LhXmhPXamtxBZZ4k .node circle,#mermaid-svg-LhXmhPXamtxBZZ4k .node ellipse,#mermaid-svg-LhXmhPXamtxBZZ4k .node polygon,#mermaid-svg-LhXmhPXamtxBZZ4k .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LhXmhPXamtxBZZ4k .rough-node .label text,#mermaid-svg-LhXmhPXamtxBZZ4k .node .label text,#mermaid-svg-LhXmhPXamtxBZZ4k .image-shape .label,#mermaid-svg-LhXmhPXamtxBZZ4k .icon-shape .label{text-anchor:middle;}#mermaid-svg-LhXmhPXamtxBZZ4k .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LhXmhPXamtxBZZ4k .rough-node .label,#mermaid-svg-LhXmhPXamtxBZZ4k .node .label,#mermaid-svg-LhXmhPXamtxBZZ4k .image-shape .label,#mermaid-svg-LhXmhPXamtxBZZ4k .icon-shape .label{text-align:center;}#mermaid-svg-LhXmhPXamtxBZZ4k .node.clickable{cursor:pointer;}#mermaid-svg-LhXmhPXamtxBZZ4k .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LhXmhPXamtxBZZ4k .arrowheadPath{fill:#333333;}#mermaid-svg-LhXmhPXamtxBZZ4k .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LhXmhPXamtxBZZ4k .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LhXmhPXamtxBZZ4k .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LhXmhPXamtxBZZ4k .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LhXmhPXamtxBZZ4k .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LhXmhPXamtxBZZ4k .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LhXmhPXamtxBZZ4k .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LhXmhPXamtxBZZ4k .cluster text{fill:#333;}#mermaid-svg-LhXmhPXamtxBZZ4k .cluster span{color:#333;}#mermaid-svg-LhXmhPXamtxBZZ4k div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LhXmhPXamtxBZZ4k .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LhXmhPXamtxBZZ4k rect.text{fill:none;stroke-width:0;}#mermaid-svg-LhXmhPXamtxBZZ4k .icon-shape,#mermaid-svg-LhXmhPXamtxBZZ4k .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LhXmhPXamtxBZZ4k .icon-shape p,#mermaid-svg-LhXmhPXamtxBZZ4k .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LhXmhPXamtxBZZ4k .icon-shape .label rect,#mermaid-svg-LhXmhPXamtxBZZ4k .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LhXmhPXamtxBZZ4k .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LhXmhPXamtxBZZ4k .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LhXmhPXamtxBZZ4k :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

用户下单
校验库存
库存充足?
生成订单
提示库存不足

第二步:导出 PNG

bash 复制代码
mmdc -i order-flow.mmd -o order-flow.png -t neutral -b white

第三步:导出 SVG

bash 复制代码
mmdc -i order-flow.mmd -o order-flow.svg

第四步:插入到 CSDN 文章

markdown 复制代码
### 订单流程图

![订单流程图](order-flow.png)

对应 Mermaid 语法:

```mermaid
flowchart LR
    A[用户下单] --> B[校验库存]
    B --> C{库存充足?}
    C -->|是| D[生成订单]
    C -->|否| E[提示库存不足]
复制代码
这样一来,文章既有图,也有源码,教程属性会很强。

## 7. 一个完整的 PlantUML 导出示例

### 第一步:新建源文件

文件名:`payment-sequence.puml`

```plantuml
@startuml
actor User
participant Frontend
participant PaymentService
participant Bank

User -> Frontend: 提交支付请求
Frontend -> PaymentService: 创建支付单
PaymentService -> Bank: 发起扣款
Bank --> PaymentService: 返回支付结果
PaymentService --> Frontend: 返回支付状态
Frontend --> User: 展示支付结果
@enduml

第二步:导出 PNG

bash 复制代码
java -jar plantuml.jar payment-sequence.puml

第三步:导出 SVG

bash 复制代码
java -jar plantuml.jar -tsvg payment-sequence.puml

第四步:插入到 CSDN 文章

markdown 复制代码
### 支付时序图

![支付时序图](payment-sequence.png)

对应 PlantUML 语法:

```plantuml
@startuml
actor User
participant Frontend
participant PaymentService
participant Bank

User -> Frontend: 提交支付请求
Frontend -> PaymentService: 创建支付单
PaymentService -> Bank: 发起扣款
Bank --> PaymentService: 返回支付结果
PaymentService --> Frontend: 返回支付状态
Frontend --> User: 展示支付结果
@enduml
复制代码
## 8. 常见问题和避坑

### 8.1 Mermaid 代码写对了,但导不出来

优先检查下面几项:

- Node.js 是否安装成功
- `@mermaid-js/mermaid-cli` 是否安装成功
- 输入文件路径是否写对
- 输出文件名后缀是否正确

### 8.2 PlantUML 执行失败

最常见的原因是:

- Java 没装好
- `plantuml.jar` 路径写错
- 当前命令所在目录不对

建议先分别确认:

```bash
java -version

以及:

bash 复制代码
java -jar plantuml.jar -help

8.3 PNG 和 SVG 该选哪个

如果你只是想快速发博客,png 更直接。

如果你更看重清晰度、缩放效果和后续复用,svg 更值得优先考虑。

我的建议是:

  • 博客封面式流程图、示意图:png
  • 架构图、类图、时序图:优先 svg

8.4 为什么我更推荐"图片 + 源码"一起发

因为单纯发图片,读者只能看结果;单纯发源码,读者又可能看不明白。

而"图片 + 源码"的写法兼顾了两件事:

  • 读者能快速看懂图
  • 想学习的人也能直接复制源码

这也是教程型文章最稳定的写法。

9. 总结

如果你准备把 Mermaid 和 PlantUML 真正用到博客、文档和项目里,那么"会写语法"只是第一步,"会导出图片并发布"才是真正落地。

最后再帮你归纳一遍:

  • Mermaid 导出 PNG:mmdc -i input.mmd -o output.png
  • Mermaid 导出 SVG:mmdc -i input.mmd -o output.svg
  • PlantUML 导出 PNG:java -jar plantuml.jar demo.puml
  • PlantUML 导出 SVG:java -jar plantuml.jar -tsvg demo.puml
  • 发到 CSDN 时,优先使用"效果图 + 源码说明"的结构

如果你是第一次写这类文章,我建议你直接按这套模板来:

  1. 先放效果图
  2. 再放源码
  3. 最后补命令行导出步骤
  4. 结尾补一个避坑总结