背景

博客之前不支持数学公式渲染,对于技术文章中涉及数学表达式的内容(如算法分析、机器学习公式等)无法正确显示。本次更新通过集成 KaTeX 引擎,为博客添加了数学公式渲染能力。

技术方案

选择 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" 即可。

注意事项

  • 数学公式使用 KaTeX CDN 加载,需要网络连接
  • KaTeX 支持大部分 LaTeX 数学语法,但不支持所有 LaTeX 宏包
  • 如果某篇文章不需要数学公式,可以在 front matter 中设置 math: false 来禁用,减少不必要的资源加载
  • 行内公式中避免使用 $ 符号作为货币单位,如需使用可用 \$ 转义

参考资料