内容管理

图表

介绍 Hugo 中绘制图表的几种方案及其渲染时机与取舍。

图表方案概览

在内容中插入图表大致有两条路线:一是构建期渲染(render at build time),由 Hugo 把图表描述直接转换成静态标记;二是浏览器端渲染(render in browser),页面先输出图表源码,再由加载的 JavaScript 库把它画出来。Hugo 对前者中的 GoAT 提供了内置支持,对 Mermaid 之类则要由站点自己编写渲染钩子(render hook)来接管。两条路线的依赖、产物与适用场景都不相同。

GoAT 图(ASCII)

Hugo 借助内置的代码块渲染钩子原生支持 GoAT 图。只要把围栏代码块的语言标识写为 goat,块内的 ASCII 内容就会在构建时被渲染成图形,无需任何 JavaScript,也不依赖本机安装额外程序:

```goat
      .               .                .               .--- 1          .-- 1     / 1
     / \              |                |           .---+            .-+         +
    /   \         .---+---.         .--+--.        |   '--- 2      |   '-- 2   / \ 2
   +     +        |       |        |       |    ---+            ---+          +
  / \   / \     .-+-.   .-+-.     .+.     .+.      |   .--- 3      |   .-- 3   \ / 3
 /   \ /   \    |   |   |   |    |   |   |   |     '---+            '-+         +
 1   2 3   4    1   2   3   4    1   2   3   4         '--- 4          '-- 4     \ 4
```

借助 GoAT 可以画出流程图、结构图、文件树、时序图、表格等多类图形,示例可参考 GoAT 项目本身的展示。这种方案只用文本字符构图,适合表达简单的流程与层级关系;线条密集的复杂图仍以专用绘图语言更省力。

Mermaid 图

Hugo 没有为 Mermaid 提供内置模板,需要自己按语言编写代码块渲染钩子。把下面这个模板保存为 layouts/_markup/render-codeblock-mermaid.html:

<pre class="mermaid">
  {{ .Inner | htmlEscape | safeHTML }}
</pre>
{{ .Page.Store.Set "hasMermaid" true }}

模板在渲染图表容器时顺手在页面存储(page store)里打了一个标记,之后在基础模板(base template)的 body 结束标签之前按需加载脚本:

{{ if .Store.Get "hasMermaid" }}
  <script type="module">
    import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs';
    mermaid.initialize({ startOnLoad: true });
  </script>
{{ end }}

做好这些准备后,内容里就可以直接用 mermaid 语言标识的围栏代码块:

```mermaid
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>John: Hello John, how are you?
    loop Healthcheck
        John->>John: Fight against hypochondria
    end
    Note right of John: Rational thoughts <br/>prevail!
    John-->>Alice: Great!
    John->>Bob: How about you?
    Bob-->>John: Jolly good!
```

渲染钩子内部的 .Inner 是代码块的原始内容,因此要用 htmlEscape 处理后再交给 safeHTML 输出,避免图表源码里的尖括号被当作标签解析。同理,图表定义必须留在围栏代码块中,否则 Markdown 解析器会先改写它的内容。

样式与尺寸

GoAT 图的围栏代码块同样接受 Markdown 属性,可以按需指定宽度、配色或类名:

```goat {width=300 color="orange"}
───Linux─┬─Android
         ├─Debian─┬─Ubuntu─┬─Lubuntu
         │        └─Mint
         └─Fedora
```

Mermaid 图的尺寸与配色则在站点自己的样式表里定义,常用的做法是给 .mermaid 类设置 max-width 或主题变量。

方案取舍

方案 渲染时机 依赖 适用场景
GoAT 构建期 无 简单的 ASCII 风格图、结构图与流程图
Mermaid 浏览器端 站点引入 JavaScript 流程图、时序图、状态图等

构建期渲染的产物是静态文件,页面无需执行脚本,对搜索引擎与纯文本阅读器更友好,代价是图形表达能力受描述语言限制;浏览器端渲染更灵活,但依赖访问者的浏览器,脚本加载失败时页面上只会剩下图表源码。选择方案时,先确定图表复杂度与部署环境可以接受的依赖,再决定渲染时机。

相关主题