改进 Hexo 中 MathJax 数学公式的渲染

之前,更新了一篇《Markdown 写作指南》的博文,这次更新重点梳理了一下 MathJax 数学公式的书写。在之后 Blog 书写过程中,也就越来越多的开始依赖 MathJax 数学公式。但是,有时候,我发现我的公式书写完全正确,并且在本地 vscode 的预览也能渲染出正确结果。可是,当我部署到我的 blog 里时,公式总是出现大大小小的问题。不知道,你是否也有过这样的疑惑?

首先,得先说一下,这里说的 MathJax 渲染出错,是你已经在主题配置文件下设置了 mathJax 为 true,依旧出现公式渲染出错;

原因

经过网上一番了解。其实,造成这种现象主要原因是 Hexo 默认的渲染引擎 hexo-renderer-marked 对公式渲染时与 Mathjax 发生了一些冲突,导致了 bug;

实际渲染中,Hexo 默认的 MarkDown 渲染引擎 hexo-renderer-marked 会调用 marked 模块的 node_modules\marked\lib\marked.js 脚本进行最终的解释,该引擎会把一些特殊的 markdown 符号转换为相应的 html 标签:

  • 在 markdown 语法中,下划线 _ 代表斜体,会被渲染引擎处理为 <em> 标签;
  • \\ 也会被转义成一个 \
    • 而 Latex 格式书写的数学公式下划线 _ 表示角标,\\ 表示公式换行,有特殊的含义,所以 MathJax 引擎在渲染数学公式的时候就会出错;
    • 类似的语义冲突的符号还包括 *, {, } 等。

解决思路:

  • 针对下划线的问题,markdown 的 marked.js 中有两种斜体的表示方式,因此取消 _ 作为斜体转义,以后用 * 作为斜体表示即可;
  • 针对 marked.js 与 Mathjax 对于个别字符二次转义的问题,我们只要不让 marked.js 去转义 \\,\{,\} 在 MathJax 中有特殊用途的字符就行了。

解决

首先,可以更换 Hexo 的 markdown 渲染引擎:

1
2
$ npm uninstall hexo-renderer-marked --save
$ npm install hexo-renderer-kramed --save

  • 说明:hexo-renderer-kramed 引擎是在默认的渲染引擎 hexo-renderer-marked 的基础上修改了一些 bug ,两者比较接近,也比较轻量级;
  • 但是也需要注意,更换完后,可能对原先的 markdown 书写有一些影响,但是我个人觉得影响不大,如果你对此十分介意,想了解受影响的地方,可以参考该引擎官方文档;
  • 其实你也可以直接跳过此步,按照下面的内容,直接修改上面提到过的 node_modules\marked\lib\marked.js 脚本;

此时,hexo-renderer-kramed 只是修改了部分 bug,还不足以解决所有冲突,为了避免以后再出现其他问题,这里再手动进一步修改一下:

  • 到博客的根目录下,找到 node_modules\kramed\lib\rules\inline.js;
  • 修改第 11 行的 escape 变量的值:
    1
    2
    // escape: /^\\([\\`*{}\[\]()#$+\-.!_>])/,
    escape: /^\\([`*\[\]()#$+\-.!_>])/,
    • 这一步是在原基础上取消了对 \ , { , } 的转义(escape);
  • 现在在第 21 行的 em 变量也要做相应的修改:
    1
    2
    // em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
    em: /^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
    • 这一步取消了对斜体标记_的转义

清除原先 hexo 缓存,重新生成部署就可以看到问题已经解决了。

补充

因为我们在主题配置文件中开启了 mathJax,因此,对所有的文章都会使用 mathJax 进行渲染,即使有些文章里,你根本没用上 mathJax,这样会影响你页面的访问速度。

因此,可以考虑在文章的 Front-matter 里针对性的打开 mathjax 开关:

1
2
3
4
5
6
7
8
9
10
11
---
title: 改进 Hexo 中 MathJax 数学公式的渲染
data: 2020-05-20 17:05:14
categories:
- Blog 相关

tags:
- Blog

mathjax: false
---

参考文章