Hexo + 安知鱼主题下 MathJax 与 KaTeX 混合渲染异常排查与解决方案

🤖 提示:此文章由运维AI自动生成,用于记录本次 Hexo 博客数学公式渲染问题的排查与修复全过程。

在运行 Hexo 博客(使用安知鱼主题)时,文章中的数学公式出现了视觉上渲染了 2 遍(如 Fe₃CFe3C)或公式显示未渲染的现象。本文记录这次问题的现象分析、排查步骤及最终排坑方案。


一、 问题现象与初查

在阅读文章《古代铁器修护保护资料整理》时,发现正文中的数学公式在网页上呈现出非常奇怪的重复状态,例如:

碳化铁(Fe3CFe3C)\text{碳化铁}(Fe_3CFe3C)

前面一部分是格式化渲染好的数学符号 Fe3CFe_3C,后面紧接着粘连着纯文本 Fe3C


二、 原因排查与定位

经过逐层抓包与源码分析,确定了导致该异常的两大根本原因:

1. KaTeX 样式缺失导致 DOM 结构泄露(“假双重渲染”)

在使用 markdown-it-katex 等构建时渲染插件时,KaTeX 会在 HTML 中生成如下结构的 DOM:

1
2
3
4
5
6
7
8
9
10
<span class="katex">
<!-- MathML / 源码存储层(默认需通过 CSS 隐藏) -->
<span class="katex-mathml">
<annotation encoding="application/x-tex">Fe_{3}C</annotation>
</span>
<!-- 视觉渲染层 -->
<span class="katex-html">
<span class="base">Fe₃C</span>
</span>
</span>

如果页面没有引入 katex.min.css,原本应该被 CSS display: none 隐藏的 .katex-mathml 层就会直接暴露在网页中,导致用户肉眼看到“渲染后的公式 + 原始文本公式”重叠/粘连在一起。

2. Markdown 行内公式语法与中文字符边界判定

行内公式使用 $...$ 语法时,在某些解析器中,如果公式结束符 $ 紧贴着中文字符(如 $Fe_{2}O_{3}\cdot H_{2}O$为主,中间无空格),解析器无法准确判断公式边界,导致公式未能正确识别或渲染被破坏。在公式 $ 后加一个半角空格可解决此解析歧义。

3. 主题配置文件覆盖与模板无条件加载

  • 多重配置覆盖:Hexo 项目根目录下的 _config.anzhiyu.yml 会覆盖主题目录下的 _config.yml。此前主题目录中设置了 mathjax: false,但根目录覆盖文件中仍开着 mathjax: true
  • 主题模板逻辑缺陷:安知鱼主题模板 additional-js.pug 中引入 math/index.pug 时未判断全局开关,导致即使关闭了 MathJax,相关脚本仍可能被无条件加载。

三、 解决方案与最佳实践

针对上述排查结果,采取以下步骤完成修复:

1. 语法规范化(修复解析歧义)

检查 Markdown 文章源文件,确保行内公式 $ 结束符与紧跟的中文字符之间留有空格:

1
2
- 中心层以$Fe_{2}O_{3}\cdot H_{2}O$为主
+ 中心层以$Fe_{2}O_{3}\cdot H_{2}O$ 为主

2. 补全 KaTeX 静态样式文件(隐藏 MathML 源码层)

在主题头部模板 layout/includes/head.pug 的 CSS 引入区域中,添加 KaTeX 样式表:

1
2
3
4
//- KaTeX CSS (用于 markdown-it-katex 构建时生成的公式样式)
link(rel='stylesheet', href=url_for(theme.asset.katex) media="print" onload="this.media='all'")
noscript
link(rel='stylesheet', href=url_for(theme.asset.katex))

3. 规范主题模板判断逻辑

修改 themes/anzhiyu/layout/includes/third-party/math/index.pug,添加开关守卫,防止关闭渲染器时主题继续无条件注入脚本:

1
2
3
4
5
6
7
8
if theme.mathjax.enable
include ./mathjax.pug

if theme.katex.enable
include ./katex.pug

if theme.mermaid.enable
include ./mermaid.pug

四、 总结

表现症状 归因分析 解决办法
Fe₃CFe3C 重复显示 缺失 KaTeX CSS,导致隐藏层暴露 <head> 中引入 katex.min.css
部分公式直接显示原码 公式结尾 $ 紧贴中文导致无法闭合 $ 与中文字符间加入空格
JS 脚本重复/冲突 主题覆盖配置 _config.anzhiyu.yml 开启了默认 MathJax 统一 Hexo 渲染器与主题渲染配置