Katex
概述
KaTeX 是一个快速、轻量的 LaTeX 数学公式渲染库,相比 MathJax 加载更快,适合博客场景。
在 Hugo 中接入 KaTeX 的核心思路是:
- 创建一个
KaTeX.htmlpartial,按需加载 CDN 资源(页面中出现公式才加载)。 - 创建一个
katex_help.js,配置分隔符并调用renderMathInElement自动渲染。 - 在主题的
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选择器微调。