让博客园设置支持PlantUml画图

  1. [1. 引入](#1. 引入)
  2. [2. 博客园不支持plantuml渲染](#2. 博客园不支持plantuml渲染)
  3. [3. 编写js脚本支持plantuml](#3. 编写js脚本支持plantuml)
  4. [4. 缺点](#4. 缺点)

1. 引入

众所周知,我们在写博客的时候,常使用PlantUML 和 Mermaid绘制图表、流程图、架构图。这是因为用代码去画图,不怎么需要手动控制格式、对齐、间距等细节,只需要专注于逻辑结构和内容本身,工具会自动完成布局和渲染。就像我们写博客的时候,更加偏向于markdown而不是富文本,这样可以让我们专注于博客内容,而不是总在调整格式。

博客园对与Mermaid支持原生渲染,例如:

plaintext 复制代码
‍```mermaid
sequenceDiagram
    participant User as 用户
    participant Frontend as 博客园前端
    participant Backend as 博客园后端
    participant DB as 数据库

    User->>Frontend: 登录并进入写博客页面
    Frontend->>User: 渲染编辑器界面
    User->>Frontend: 编写文章并点击"发布"
    Frontend->>Backend: 发送 POST /api/posts (含标题、内容)
    Backend->>DB: 保存文章数据
    DB-->>Backend: 保存成功
    Backend-->>Frontend: 返回成功响应
    Frontend-->>User: 显示"发布成功"提示
‍```

渲染结果如下:
sequenceDiagram participant User as 用户 participant Frontend as 博客园前端 participant Backend as 博客园后端 participant DB as 数据库 User->>Frontend: 登录并进入写博客页面 Frontend->>User: 渲染编辑器界面 User->>Frontend: 编写文章并点击"发布" Frontend->>Backend: 发送 POST /api/posts (含标题、内容) Backend->>DB: 保存文章数据 DB-->>Backend: 保存成功 Backend-->>Frontend: 返回成功响应 Frontend-->>User: 显示"发布成功"提示

上述语法可以在博客园中进行原生渲染,very good。

2. 博客园不支持plantuml渲染

但是如果使用如下的plantuml语法,博客园就会渲染失败

plaintext 复制代码
‍```plantuml
@startuml
actor 用户 as User
participant "博客园前端" as Frontend
participant "博客园后端" as Backend
database "数据库" as DB

User -> Frontend : 登录并进入写博客页面
Frontend --> User : 渲染编辑器
User -> Frontend : 编写文章,点击"发布"
Frontend -> Backend : POST /api/posts\n{title, content}
Backend -> DB : INSERT INTO posts(...)
DB --> Backend : OK
Backend --> Frontend : {success: true, id: 123}
Frontend --> User : 显示"发布成功"
@enduml
‍```

3. 编写js脚本支持plantuml

plantuml进行渲染,有很多种方法,其中一种方法如下:

  • 官方提供 PlantUML Server

    • 用户发送 PlantUML 文本(Base64 编码)
    • 服务端解析 → 调用 Graphviz → 返回 PNG/SVG
    • 例如:https://www.plantuml.com/plantuml/png/SoWkIImgAStDuNBAJrBGjLDmpCbCJbMmKiX8pSd9vt98pKi1IW80

在博客园页脚html代码输入如下js脚本:

html 复制代码
<script src="https://files.cnblogs.com/files/xiaohuiduan/plantuml-encoder.min.js"></script>
<script>
(function() {
  const format = 'svg'; // 可改为 'svg' 获得矢量图,png获得png图
  const server = 'https://www.plantuml.com/plantuml/' + format + '/';

  // 查找所有 ‍```plantuml 生成的代码块
  document.querySelectorAll('code.language-plantuml').forEach(codeEl => {
    const code = codeEl.textContent.trim();
    if (!code) return;

    try {
      const encoded = plantumlEncoder.encode(code);
      const img = document.createElement('img');
      img.src = server + encoded;
      img.alt = 'PlantUML Diagram';
      img.style.maxWidth = '100%';
      img.style.height = 'auto';
      img.style.display = 'block';
      img.style.margin = '1em auto';

      // 替换整个 <pre> 容器(因为 code 在 pre 里面)
      const preEl = codeEl.parentElement;
      if (preEl && preEl.tagName === 'PRE') {
        preEl.parentNode.replaceChild(img, preEl);
      } else {
        codeEl.parentNode.replaceChild(img, codeEl);
      }
    } catch (e) {
      console.error('PlantUML render error:', e, code);
      codeEl.style.color = 'red';
      codeEl.textContent = 'PlantUML 渲染失败: ' + (e.message || e);
    }
  });
})();
</script>

最终便能够进行渲染了:

plantuml 复制代码
@startuml
actor 用户 as User
participant "博客园前端" as Frontend
participant "博客园后端" as Backend
database "数据库" as DB

User -> Frontend : 登录并进入写博客页面
Frontend --> User : 渲染编辑器
User -> Frontend : 编写文章,点击"发布"
Frontend -> Backend : POST /api/posts\n{title, content}
Backend -> DB : INSERT INTO posts(...)
DB --> Backend : OK
Backend --> Frontend : {success: true, id: 123}
Frontend --> User : 显示"发布成功"
@enduml

4. 缺点

尽管上述方案可以让博客园支持插入plantuml语法,但是还是存在以下缺点:

  1. 如果plantuml程序字符过长,可能会渲染失败。
  2. plantuml server在国外,可能会因为网络等因素导致渲染失败。

其实最好的方法就是博客园原生支持plantuml。

Make cnblogs great again!