Hexo 博客支持 KaTeX(回炉版)

去年的这个时候,我写过一篇同样目的的文章 《Hexo 博客支持 KaTeX》。当时虽然搞成了,但基本属于误打误撞的状态,对于为什么要这些步骤并不知晓,仅仅像是一个操作工,这种感觉很不好,所以才有了这一篇回炉版的Hexo 博客支持 KaTeX 教程。

1. 什么是 KaTeX

KaTeX 是一个支持在网页上显示 TeX 公式的 JavaScript 库,相较于其更加有名的前辈 MathJax,KaTeX 最大的特点是渲染速度更快。读者可以在 KaTeX and MathJax Comparison Demo 上感受下两者速度的差别,在我电脑上,KaTeX 渲染完所有公式仅用了 118 毫秒,而 MathJax 用了 15708 毫秒,后者是前者的一百多倍。

当然,这种快速、轻量级的权衡,肯定会有一定的牺牲,相较于 MathJax,KaTeX 支持的符号相对较少一些。Function Support in KaTeX 列出了 KaTeX 支持的符号和环境,可以看到,对于绝大部分需求,KaTeX 已经能够满足需求了。去年12月我写第一版的时候,KaTeX 还是不支持 $\nabla$ 的,现在可以了。不过对于 \hat{x}\ \vec{x}\ \ddot{x}\ \overrightarrow{AB} 还是不可以。

2. 如何让 Hexo 博客支持 KaTeX?

默认已经完成 Hexo 博客搭建了,如果还没有,可以看我的上一篇文章 《知行合一的 Hexo 博客搭建教程》。 过程主要分为两大块:添加 katex.min.js 和 安装 katex.min.css、hexo-katex 插件。

2.1 添加 katex.min.js 和 katex.min.css

根据 KaTeX 的官方文档 https://github.com/Khan/KaTeX#usage,我们需要在生成网页的 HTML 里添加如下两行代码:

1
2
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.js"></script>

但在 Hexo 中,如果我们改动了原来的 markdown 文件,经常会使用 hexo clean 命令来清空以前生成的 HTML 文件,然后再用 hexo generate 来生成新的,每一次都要直接在 HTML 里面加入这两行代码会累死人的。好在 Hexo 是根据模板来生成 HTML 的,所以我们只要将这两行代码放到模板文件去。不同的模板不一样,这里分别以默认主题 Landscape 和本站采用的 Noise 为例,其他情形如法炮制。

2.1.1 Landscape 主题

在 Hexo 站点的本地文件夹下的 \themes\landscape\layout\_partial 文件夹下可以看到有很多 ejs 文件。EJS 是一个 JavaScript 模板库,用来从 JSON 数据中生成 HTML 字符串。我们要挑一个会在网站首页和每篇文章的网页上都存在的部件来添加这两行代码,参考 MathJax 的做法,我们也选择 _partial 文件夹下的 after-footer.ejs 文件。虽然不懂 ejs,但从 after-footer.ejs 的如下代码可以知道

1
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>

ejs 中的 JavaScript 和 CSS 的写法还是和 HTML 一样的,所以我们直接把上面的那两行代码复制到 after-footer.ejs 最后即可。

2.1.2 Noise 主题

假设已经安装好了Noise 主题,在 \themes\noise\layout\_partial 文件夹下找不到熟悉的 after-footer.ejs 文件了,而且\themes\noise\layout 下一个 ejs 文件都没有,都是 jade 文件。jade 用途同 ejs 一样,是另一种模板引擎。打开 base.jade 看一下,囧了,JavaScript 和 CSS 的写法和 HTML 不一样。不过只要细心一点肯定能发现,base.jade 里面有如下的代码:

1
2
link(rel='stylesheet', type='text/css', 	 href="//cdn.bootcss.com/fancybox/2.1.5/jquery.fancybox.css")
script(src="//cdn.bootcss.com/jquery/2.0.3/jquery.min.js")

这不就是 CSS 和 JavaScript 的用法么?所以我们只要照葫芦画瓢就行了,把要添加的那两行 KaTeX 改写一下,在上面两行代码的下面添加如下两行代码即可

1
2
3
4
// For KaTeX Begin
link(rel='stylesheet', type='text/css', href="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.css")
script(src="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.js")
// For KaTeX End

其中,// 开头的是注释。

至此,在模板文件中添加 katex.min.js 和 katex.min.css 的任务算是完成了。那是否可以直接用了呢?我们可以测试一下。在现有的 markdown 文件中添加一行 $E = m * c^2$,依次运行 hexo cleanhexo generate`hexo server, 到 http://localhost:4000/ 里去看一下,会发现 $E = m * c^2$ 是纯文本,并没有显示出数学公式。嗯?回想一下,诚然,我们知道这是一行数学公式,但 Hexo 不知道啊,怎么才能让 Hexo 在从 Markdown 转成 HTML 的时候,知道这是数学公式,调用 KaTeX 来渲染呢?这就还需要下一步。

2.2 安装 hexo-katex 插件

Github 上有一个 hexo-katex 插件,可以帮助我们在 Hexo 站点中使用 KaTeX,根据其项目主页以及 hexo-katex 依赖的 hexo-render-pandoc 安装过程有如下几步

  • Step 1: 安装神器 Pandoc,下载地址为https://github.com/wzpan/hexo-renderer-pandoc

  • Step 2: cd 到 Hexo 博客所在的文件夹,敲入如下命令,等待安装完成

    1
    npm install hexo-renderer-pandoc --save
  • Step 3: 修改 /node_modules/hexo-render-pandoc/index.js,将 var args = [ '-f', 'markdown', '-t', 'html', '--mathjax', '--smart'] 中的 mathjax 替换为 katex,即

    1
    2
    //var args = [ '-f', 'markdown', '-t', 'html', '--mathjax', '--smart']
    var args = [ '-f', 'markdown', '-t', 'html', '--katex', '--smart']
  • Step 4: 仍然在 Hexo 博客所在的文件夹,在终端 或者 cmd 中敲入如下命令,等待安装完成。

    1
    npm install hexo-katex --save

​至此,Hexo 博客支持 KaTeX 的所有步骤都已经结束。可以依次运行 hexo cleanhexo generate`hexo server, 到 http://localhost:4000/ 里去看一下,应该能够将 $E = m * c^2$ 正确显示成 $E = m c^2$。如果运行 hexo generate 的时候报错,不要紧,把 cmd 关掉重新打开就好,应该是 Pandoc 或者这两个插件 是在 cmd 打开之后安装的缘故。不添加 katex.min.jskatex.min.css,单独安装 hexo-katex 插件,会显示成 `E = m c^2E=m∗c2 ,也不行,所以添加katex.min.jskatex.min.css和安装hexo-katex` 插件这两步一步都不能少。

3. 存在的问题

hexo-katex 主页 上提供的信息很少,Inline math 用$ 括起来,Display math 用 $$ 括起来,具体形式如下:

Inline math $E = m * c^2$

Display math

1
2
3
$$
E = m * c^2
$$

对于简单的式子没问题,但我随便挑了三个例子,问题就来了。

Case definitions
1
2
3
$$
f(n) = \begin{cases} \frac{n}{2}, &amp; \text{if } n\text{ is even} \\ 3n+1, & \text{if } n\text{ is odd} \end{cases}
$$

$$f(n) = \begin{cases} \frac{n}{2}, & \text{if } n\text{ is even} \ 3n+1, & \text{if } n\text{ is odd} \end{cases}$$

Matrices
1
2
3
$$
\begin{pmatrix}a_{11} & a_{12} & a_{13}\\ a_{21} & a_{22} & a_{23}\\ a_{31} & a_{32} & a_{33}\end{pmatrix}
$$

$$
\begin{pmatrix}a{11} & a{12} & a{13}\ a{21} & a{22} & a{23}\ a{31} & a{32} & a_{33}\end{pmatrix}
$$

Multi-line function
1
2
3
$$
\begin{array}{lcl}z & = & a \\f(x,y,z) & = & x + y + z\end{array}
$$

$$
\begin{array}{lcl}z & = & a \f(x,y,z) & = & x + y + z\end{array}
$$

啊啊啊!用来对齐的 & 符号会被显示成 amp;,但其对排版的作用又是起到的。这些例子,在用 KaTeX 渲染的其他网页上都是正常的,所以应该是 hexo-renderer-pandochexo-katex 中间有某一个出问题了。独自解决这个问题,超过我目前的能力范围。我在 hexo-katex 的 Github 主页上提了一个 issue &-alignment markers get displayed as “amp;”,希望 hexo-katex 作者能够给出解答,不过希望不是很大。最近,还没有写要用到 LaTeX 的文章的打算,即使写了也不会大量用到 & 符号,所以就暂且凑合着。万一要用到了怎么办,目前想得就只有两条路了:

  • 还是切回 MathJax,看看能不能自己搭 CDN,加载快一点。
  • 用 KLatexFormula 生成图片,上传图床凑合下。

感谢您一直阅读到这里,如果我的文章有错误或不足之处,请务必在评论中留言指出,千万不用客气,万分感谢~


如果您觉得我的文章对您有所帮助,不妨小额捐助一下,您的鼓励是我长期坚持的动力。

Alipay_Middle Wechat_Middle