首页 / HUGO / Katex

Katex

概述

KaTeX 是一个快速、轻量的 LaTeX 数学公式渲染库,相比 MathJax 加载更快,适合博客场景。
在 Hugo 中接入 KaTeX 的核心思路是:

  1. 创建一个 KaTeX.html partial,按需加载 CDN 资源(页面中出现公式才加载)。
  2. 创建一个 katex_help.js,配置分隔符并调用 renderMathInElement 自动渲染。
  3. 在主题的 head.html 中引入该 partial。

本项目实际落地的三个文件:

№ 文件 作用
0 themes/overlookart/layouts/partials/KaTeX.html 检测公式并按需加载 KaTeX CSS/JS
1 themes/overlookart/assets/js/katex_help.js 配置分隔符,执行自动渲染
2 themes/overlookart/layouts/partials/head.html 引入 partial

第一步:创建 KaTeX.html partial

路径:themes/overlookart/layouts/partials/KaTeX.html

 1{{- /* KaTeX 数学公式:仅当页面正文中出现可渲染的 $...$(同行成对)或 $$...$$ 时才按需加载。
 2       检测基于渲染后的 HTML,先剔除代码与图表区域,与 auto-render 实际处理范围保持一致:
 3       命令行示例(每行单个 $)、代码块、mermaid/markmap 内容都不会触发加载。 */ -}}
 4{{- $html := .Content -}}
 5{{- $html = replaceRE "(?is)<pre.*?</pre>" "" $html -}}
 6{{- $html = replaceRE "(?is)<code.*?</code>" "" $html -}}
 7{{- $html = replaceRE "(?is)<div class=\"mermaid\">.*?</div>" "" $html -}}
 8{{- $html = replaceRE "(?is)<div class=\"infographic-container\".*?</div>" "" $html -}}
 9{{- $html = replaceRE "(?is)<div id=\"wordcloud\".*?</div>" "" $html -}}
10{{- $html = replaceRE "(?is)<script type=\"template\">.*?</script>" "" $html -}}
11{{ if findRE "\\$\\$|\\$[^$\\n]+\\$" $html }}
12<!-- KaTeX 数学公式渲染 -->
13<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.19.1/dist/katex.min.css">
14<script defer src="https://cdn.jsdelivr.net/npm/katex@0.19.1/dist/katex.min.js"></script>
15<script defer src="https://cdn.jsdelivr.net/npm/katex@0.19.1/dist/contrib/auto-render.min.js"></script>
16{{ $katexjs := resources.Get "js/katex_help.js" | js.Build }}
17<script defer src="{{ $katexjs.RelPermalink }}"></script>
18{{ end }}

要点说明:

  • 按需加载:先剔除 pre、code、mermaid、词云、信息图等区域,再用正则检测是否剩余成对的 $...$ 或 $$...$$,没有公式就不加载任何 KaTeX 资源,零开销。
  • 剔除逻辑要与渲染范围一致:命令行示例中每行单独出现的 $(如 echo $PATH)不是成对的,不会触发加载,避免误判。
  • defer 加载:三个 CDN 资源与自定义脚本均使用 defer,不阻塞页面渲染,且按文档顺序执行。

第二步:创建 katex_help.js

路径:themes/overlookart/assets/js/katex_help.js

 1// KaTeX 自动渲染:把正文中的 $...$(行内公式)和 $$...$$(独立公式)转换为数学公式
 2// 依赖脚本(katex.min.js、auto-render.min.js)以 defer 方式在本文件之前加载
 3function renderKaTeX() {
 4  if (typeof renderMathInElement !== 'function') return;
 5  var el =
 6    document.getElementById('nice') ||
 7    document.querySelector('#content article') ||
 8    document.body;
 9  renderMathInElement(el, {
10    delimiters: [
11      { left: '$$', right: '$$', display: true },
12      { left: '$', right: '$', display: false },
13      { left: '\\(', right: '\\)', display: false },
14      { left: '\\[', right: '\\]', display: true },
15    ],
16    // 图表容器内的 $ 是图表语法的一部分,不参与公式渲染
17    ignoredClasses: ['mermaid', 'markmap', 'wordcloud', 'infographic-container'],
18    throwOnError: false,
19  });
20}
21
22renderKaTeX();

要点说明:

  • 分隔符:支持 $...$(行内)、$$...$$(独立)、\(...\)、\[...\] 四种写法。
  • ignoredClasses:mermaid、markmap、词云、信息图等图表容器内的 $ 是图表自身语法(如 mermaid 的 style A fill:#f9f),必须排除。
  • throwOnError: false:公式写错时显示红色错误文本而不是让整页脚本报错。
  • 容器选择:优先渲染 #nice(主题正文容器),回退到 article,最后回退到 body。

第三步:在 head.html 中引入

路径:themes/overlookart/layouts/partials/head.html,在文件末尾追加:

1<!-- KaTeX 数学公式 -->
2{{ partial "KaTeX.html" . }}

Markdown 中的公式写法约定

1行内公式:质量 $m$ 的动能为 $E_k = \frac{1}{2}mv^2$。
2
3独立公式(独占一行,前后各留一个空行):
4
5$$
6\bar{r} = \frac{1}{n}\sum_{i=1}^{n} r_i
7$$

需要注意的约定:

  • 独立公式必须单行书写:$$ 公式不要在 Markdown 中折行,避免 findRE 的 \n 检测不到成对符号。
  • 百分号转义:正文中的字面 % 写成 \%(LaTeX 中 % 是注释符)。
  • 中文用 \text{} 包裹:如 \text{收益率} = \frac{a}{b},直接写中文会报错。
  • 转义反斜杠:$a \times b$、$x \in \mathbb{R}$ 等命令直接书写即可。

验证

1hugo server -D

在含有 $...$ 的文章页面按 F12 打开控制台,确认加载了 katex.min.css、katex.min.js、auto-render.min.js 与打包后的 katex_help.js,且公式被渲染为 <span class="katex"> 结构。在无公式的文章中确认这些资源没有被加载。

常见问题

  • $ 出现在代码块中被误渲染:partial 的剔除逻辑只负责「决定是否加载」,实际渲染范围由 ignoredClasses 与 auto-render 自身规则决定;代码块内的内容不在 renderMathInElement 处理范围内(<code>/<pre> 默认被忽略),无需额外配置。
  • mermaid 图报错或 $ 消失:确认 ignoredClasses 包含 mermaid、markmap、wordcloud、infographic-container。
  • 公式与主题 CSS 冲突:KaTeX 的 CSS 在 head.html 末尾加载,通常可覆盖主题样式;如有冲突可用 .katex 选择器微调。