背景
博客之前不支持数学公式渲染,对于技术文章中涉及数学表达式的内容(如算法分析、机器学习公式等)无法正确显示。此外,mermaid 图表引擎版本过旧(v8.8.0),无法支持较新的图表语法。本次更新通过集成 KaTeX 引擎和改进 Mermaid 渲染方式(按 Hugo 官方文档采用 CDN ESM 模块),解决了这两个问题。
技术方案
选择 KaTeX 而非 MathJax,主要考虑以下因素:
- 渲染速度:KaTeX 的渲染速度比 MathJax 快得多
- 体积轻量:CDN 加载,不增加项目体积
- Hugo 原生支持:Hugo 的 Goldmark 扩展支持 passthrough 模式,与 KaTeX 配合良好
改动内容
1. 修改 config.yml
Hugo Goldmark passthrough 扩展配置
在 markup 部分添加了 passthrough 扩展,让 Hugo 在处理 Markdown 时保留数学公式的原始内容,而不是转义其中的特殊字符:
markup:
goldmark:
extensions:
passthrough:
delimiters:
block:
- - \[
- \]
- - $$
- $$
inline:
- - \(
- \)
- - $
- $
enable: true
全局启用数学公式
在 params 中添加 math: true,使所有页面默认支持数学公式:
params:
math: true
2. 修改 layouts/partials/extend_head.html
引入 KaTeX 的 CSS 样式表和 JavaScript 库:
{{ if .Params.math | default .Site.Params.math }}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js" crossorigin="anonymous"></script>
{{ end }}
3. 修改 layouts/partials/extend_footer.html
添加 KaTeX auto-render 初始化脚本,在页面 DOM 加载完成后自动渲染数学公式:
{{ if .Params.math | default .Site.Params.math }}
<script>
document.addEventListener("DOMContentLoaded", function () {
renderMathInElement(document.body, {
delimiters: [
{ left: "$$", right: "$$", display: true },
{ left: "$", right: "$", display: false },
{ left: "\\[", right: "\\]", display: true },
{ left: "\\(", right: "\\)", display: false }
],
throwOnError: false
});
});
</script>
{{ end }}
使用方式
行内公式
使用单个 $ 或 \(...\) 包裹:
质能方程 $E = mc^2$ 是物理学中著名的公式。
渲染效果:质能方程 $E = mc^2$ 是物理学中著名的公式。
块级公式
使用双 $$ 或 \[...\] 包裹:
$$
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
$$
渲染效果:
$$ \int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi} $$更多示例
矩阵:
$$ \begin{bmatrix} a & b \\ c & d \end{bmatrix} $$求和公式:
$$ \sum_{i=1}^{n} i = \frac{n(n+1)}{2} $$欧拉公式:
$$ e^{i\pi} + 1 = 0 $$薛定谔方程:
$$ i\hbar\frac{\partial}{\partial t}\Psi(\mathbf{r},t) = \hat{H}\Psi(\mathbf{r},t) $$踩坑记录
在初次部署后发现数学公式无法渲染,排查发现是 KaTeX CDN 资源的 integrity(SRI hash)值写错了,导致浏览器在加载 CSS 和 JS 文件时校验失败,资源被拒绝加载。移除错误的 integrity 属性后问题解决。
教训:使用 CDN 资源时,SRI hash 必须与实际文件内容完全匹配。如果不确定正确的 hash 值,建议不添加
integrity属性,仅使用crossorigin="anonymous"即可。
Mermaid 图表渲染
问题描述
博客中已有的 mermaid.js 版本为 8.8.0,该版本不支持较新的 mermaid 语法(如 flowchart TD、新版 sequenceDiagram 等),导致图表渲染报错 Syntax error in graph mermaid version 8.8.0。
改动内容
1. 删除本地 mermaid.min.js,改用 CDN ESM 模块
移除 static/js/mermaid.min.js(原 v8.8.0,约 3MB),改为从 CDN 按需加载 ESM 模块,始终获取最新版本。
2. 创建 layouts/_markup/render-codeblock-mermaid.html
按照 Hugo 官方文档 创建代码块渲染钩子(注意路径是 layouts/_markup/,不是 layouts/_default/_markup/):
<pre class="mermaid">
{{ .Inner | htmlEscape | safeHTML }}
</pre>
{{ .Page.Store.Set "hasMermaid" true }}
Page.Store.Set "hasMermaid" true 标记页面使用了 mermaid 图表。
3. 修改 layouts/_default/baseof.html
在 </body> 标签前添加 mermaid ESM 脚本,按需加载(只有使用 mermaid 的页面才会加载):
{{ 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 }}
4. 清理 extend_head.html
移除 layouts/partials/extend_head.html 中之前添加的 mermaid 加载脚本(不再需要)。
使用方式
直接在文章中使用 mermaid 代码块即可,不需要在 front matter 中设置 mermaid: true:
```mermaid
flowchart TD
A[开始] --> B{条件判断}
B -->|是| C[操作1]
B -->|否| D[操作2]
```
Hugo 的 render hook 会自动将代码块转为 <pre class="mermaid"> 元素,baseof.html 中的 ESM 脚本会自动检测并渲染。
更多示例
流程图:
graph TD
A[输入数据] --> B[预处理]
B --> C{数据质量?}
C -->|合格| D[模型训练]
C -->|不合格| E[数据清洗]
E --> B
D --> F[评估]
F --> G[部署]
序列图:
sequenceDiagram
participant U as 用户
participant S as 服务器
participant D as 数据库
U->>S: 发送请求
S->>D: 查询数据
D-->>S: 返回结果
S-->>U: 响应
注意事项
数学公式
- 数学公式使用 KaTeX CDN 加载,需要网络连接
- KaTeX 支持大部分 LaTeX 数学语法,但不支持所有 LaTeX 宏包
- 如果某篇文章不需要数学公式,可以在 front matter 中设置
math: false来禁用,减少不必要的资源加载 - 行内公式中避免使用
$符号作为货币单位,如需使用可用\$转义
Mermaid 图表
- 在文章 front matter 中设置
mermaid: true才能加载 mermaid.js - 推荐使用 mermaid 代码块语法,也支持 shortcode 方式插入
- mermaid.js v10.9.3 支持所有主流图表类型:flowchart、sequenceDiagram、classDiagram、stateDiagram、gantt、pie 等
- mermaid.js 文件较大(约 3MB),仅在需要的文章中加载
...