在 Slidev 中使用 PlantUML 绘制 UML 图:语法、渲染原理与自定义服务器配置
本篇技术指南围绕 Slidev 内置的 PlantUML 支持展开,讲解如何直接在幻灯片中以 plantuml 代码块编写文本描述并自动渲染为 UML 图,涵盖基础语法、代码块参数、plantUmlServer 配置项,以及从 Markdown 解析到浏览器渲染的完整实现链路。读完本文,你将能够写出可复现的 PlantUML 幻灯片,并根据内网、离线等场景自定义渲染服务器,深入理解底层每个环节的作用。
一句话认识这个能力
Slidev 把 PlantUML 作为「开箱即用」的代码块能力内置:不需要安装任何插件,只要在一个以 plantuml 作为语言标识的围栏代码块(fenced code block)中书写 @startuml ... @enduml 描述,幻灯片解析器就会在构建阶段将其转换为 <PlantUml> 组件,最终由浏览器向 PlantUML 服务端请求渲染好的 SVG 图片并展示在页面上。对应功能文档见 docs/features/plantuml.md。
PlantUML 代码块的基础用法
在 slides.md 的任意一张幻灯片中写入如下围栏代码块,即可生成一张时序图:
```plantuml
@startuml
Alice -> Bob : Hello!
@enduml
```
图内文本(即 @startuml 与 @enduml 之间的全部内容)是标准的 PlantUML 描述语言。例如把 Alice 与 Bob 之间的消息改为中文或补充多条消息、添加激活条(activate / deactivate)、分组(group)等,都会被 PlantUML 服务端原样解释:
```plantuml
@startuml
Alice -> Bob : 请求数据
activate Bob
Bob --> Alice : 返回结果
deactivate Bob
@enduml
```
该用法与 Mermaid 一致——docs/features/mermaid.md 中同样是靠围栏语言标识触发渲染。二者的取舍通常看团队习惯与图种偏好:PlantUML 的语法更为「文本化、结构贴近代码」,适合从代码注释与设计文档中直接迁移图描述。
支持的主要图表类型
plantuml 代码块没有限定图种,凡是 PlantUML 语言本身支持的图,理论上都能渲染,常见的包括:
- 时序图(Sequence diagrams):
Alice -> Bob : Hello!即属此类; - 类图(Class diagrams):用
class、继承与关联关系描述领域模型; - 活动图(Activity diagrams):用
start、if、repeat描述业务流程分支; - 组件图(Component diagrams):描述软件模块之间的依赖与接口;
- 状态图(State diagrams):用
[*]与state描述对象状态机; - 对象图(Object diagrams):描述某一时刻的对象实例关系;
- 用例图(Use case diagrams):用
actor与usecase表达系统需求场景。
在真实使用中,若同一页出现 ```plantuml 以外的图种(如 mermaid、ts、md 等),各个渲染器会按注册顺序逐个尝试处理,并不会互相干扰(详见下文「渲染原理」的代码块流水线)。
自定义 PlantUML 服务器(plantUmlServer)
默认行为
默认情况下,Slidev 会把图描述发送给公共服务器 https://www.plantuml.com/plantuml 进行渲染。这个默认值来自 packages/parser/src/config.ts 的 getDefaultConfig():
plantUmlServer: 'https://www.plantuml.com/plantuml',
类型定义同步声明于 packages/types/src/frontmatter.ts,注释明确标注其默认值为 https://www.plantuml.com/plantuml,含义为「渲染图表所用的 PlantUML 服务器 URL」。
在 headmatter 中覆盖
如果幻灯片运行环境无法访问公网,或企业出于安全考虑不允许把图源文本发送到第三方服务器,可以在 slides.md 顶部的 headmatter 中覆盖它:
---
plantUmlServer: https://your-server.com/plantuml
---
这里的 plantUmlServer 是顶层配置键(不是嵌套在 config: 下的子项),文档示例同时出现在 docs/custom/index.md,并附注释 Learn more: https://sli.dev/features/plantuml.html,指向本功能对应文档页。VS Code 扩展还为其提供了 schema 补全与校验支持,见 packages/vscode/schema/headmatter.json。
一个典型的自定义地址形态如 http://localhost:8080/plantuml(本地 docker 镜像 plantuml/plantuml-server 默认路径为 /plantuml)。需要注意:该 URL 只需指向「PlantUML Server 根路径」,Slidev 会在其后自动拼接 /svg/<编码串>(见下节),因此请勿把 /svg 或编码路径一并写进配置。
代码块级参数:缩放等渲染选项
和 Mermaid、Monaco 等代码块一样,plantuml 围栏代码块支持在语言标识后跟一个花括号对象来注入渲染参数。以缩放为例:
```plantuml {scale:0.5}
@startuml
Alice -> Bob : Hello!
@enduml
```
{scale:0.5} 会把图片缩放为原始尺寸的一半。解析规则在 packages/slidev/node/syntax/codeblock/plant-uml.ts 的正则中定义:
const RE_PLANT_UML = /^plantuml\s*(\{[^\n]*\})?/
即在 plantuml 语言标识后允许可选地跟一个单行对象字面量。该对象会被整体透传给渲染组件:
const optionsProp = options ? `v-bind="${options}"` : ''
因而除 scale 外,任何组件支持的 prop(如自定义 alt)都可以这样传入,例如 plantuml {alt:"系统时序图"}。这一行为有端到端测试佐证:packages/slidev/node/syntax/integration.test.ts 中 plantuml {scale:0.5} 被转换为:
<PlantUml v-bind="{scale:0.5}" code="SoWkIImgAStDuNBCoKnELT2rKt3AJx9Iy4ZDoSddSaZDIodDpG40" />
渲染原理:从 Markdown 代码块到 <img>
理解这个功能的底层链路,有助于排查「图不显示」「请求了错误地址」等问题。整体分三步:
-
Markdown 围栏被拦截:解析期,Slidev 覆写 MarkdownIt 的 fence 渲染规则,并按顺序执行一组代码块转换器,见 packages/slidev/node/syntax/codeblock/index.ts。
plantUmlTransformer与mermaidTransformer、magicMoveTransformer、monacoTransformer等并列注册,任一转换器返回非空结果即结束处理。 -
转换为组件:在 packages/slidev/node/syntax/codeblock/plant-uml.ts 中,转换器读取已解析的
plantUmlServer配置,并用plantuml-encoder(一种 deflate + base64 编码,也是 PlantUML 官方服务器识别的 URL 编码)压缩图源文本:const encoded = encodePlantUml(code.trim()) const serverProp = plantUmlServer === undefined ? '' : ` server=${JSON.stringify(plantUmlServer)}` return `<PlantUml ${optionsProp} code="${encoded}"${serverProp} />`也就是说,
plantUmlServer未显式配置时,最终<PlantUml>组件会退回到运行期的默认服务器地址;若在 headmatter 中显式配置,则会被序列化进组件属性。 -
浏览器端请求 SVG:运行时渲染组件 packages/client/builtin/PlantUml.vue 仅是一个轻量封装——按 props 组合出图片地址并输出
<img>:const uri = computed(() => `${props.server}/svg/${props.code}`)<img :src="uri" :style="{ scale }" :alt="alt">即最终图片 URL 形如
https://www.plantuml.com/plantuml/svg/<编码串>,alt默认值为'PlantUML diagram',可通过代码块参数覆盖。注释中也明确提示:这是一个「自动转换」得到的组件,无需手动直接使用<PlantUml>。
由此引出的三条实践结论
- 渲染发生在浏览器端:幻灯片页面加载时才会按需向
plantUmlServer发起图片请求,因此离线浏览、导出 PDF 与在线演示一样需要保证到该服务器网络可达; - 编码并非「明文传参」:图源经压缩编码后才出现在 URL 中,但 PlantUML 服务器本质上仍能解码还原出全部描述内容——涉及保密架构图时,请务必使用自建服务器而不是默认的公网实例;
- 构建阶段只做转写:真正的图形渲染完全委托给 PlantUML 服务端,本地机器无需安装任何 Java/Graphviz 等 PlantUML 依赖。
常见问题与排查要点
- 图片区域空白 / 裂图:先检查当前环境能否访问
plantUmlServer(默认https://www.plantuml.com/plantuml)。网络受限时,在 headmatter 中改指内网服务器即可,无需改动任何代码块内容。 - 请求落到了错误的地址:确认 headmatter 中的键拼写为
plantUmlServer(首字母大写 U、S 均大写),且是顶层键。 - 缩进中的代码块不生效:
plantuml围栏可以出现在列表等嵌套结构中(integration.test.ts 中即有嵌套在有序列表中的用例),只要保持 Markdown 围栏语法正确即可被识别。 - 缩放不生效:确认花括号紧跟语言标识且无多余换行,例如
plantuml {scale:0.5},因为正则要求选项位于同一行内。
小结
PlantUML 是 Slidev 中与 Mermaid 并列的内置文本化图表方案,入口极简:写好 plantuml 代码块即渲染。它的深度可控性体现在两端——作者侧可通过 headmatter 的 plantUmlServer 切换到私有服务器、通过代码块参数控制缩放等表现;实现侧则是一条清晰的分层链路:fence 转换器负责把文本压缩编码成组件参数(codeblock/plant-uml.ts),轻量组件负责把地址拼装为远程 SVG 图片(client/builtin/PlantUml.vue)。需要图源保密或离线演示时,配置一个私有 plantUmlServer 即可继续沿用同一套书写语法,这也是本能力在生产环境中落地最常用的一步。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00