在Hexo顯示數學公式

由於Hexo本身沒有支援數學公式的顯示,因此即便在Markdown文件輸入數學公式,他也僅會顯示成$\cos\theta = \frac{p\cdot q}{\|p\|\|q\|}$這樣的形式,為了讓Hexo能正確顯示我們想呈現的數學字串cosθ=pqpq\cos\theta = \frac{p\cdot q}{\|p\|\|q\|},我們需加入mathJax的插件。

安裝mathJax

安裝mathJax的方式相當簡單,只需在terminal中輸入下面指令:

1
$ npm install hexo-math --save

接下來在Hexo中的_config.yml裡新增以下指令:

1
2
3
4
5
6
math:
engine: 'mathjax' # or 'katex'
mathjax:
# src: custom_mathjax_source
config:
# MathJax config

並在主題的_config.yml下開啟mathJax的功能:

1
2
3
4
5
6
# MathJax Support
mathjax:
enable: true
per_page: true
# cdn: //cdn.bootcss.com/mathjax/2.7.1/latest.js?config=TeX-AMS-MML_HTMLorMML
cdn: //cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML

由於每次讀取文章時皆會載入這個套件,過多數學公式有可能造成文章讀取速度變慢。因此若想要在特定文章開啟這個功能,可以做一些調配。由於我使用的是Next的主題,這裡以Next的方式做說明。首先先確認themes/next/layout/_layout.swig有沒有將mathjsx.swig引入:

1
{% include '_third-party/mathjax.swig' %}

若沒有請自行將上述指令放入文件中。之後找到themes/next/layout/_third-party/mathjax.swig,裡面的原本內容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{% if theme.mathjax.enable %}
{% if not theme.mathjax.per_page or (page.total or page.mathjax) %}
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
processEscapes: true,
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
}
});
</script>

<script type="text/x-mathjax-config">
MathJax.Hub.Queue(function() {
var all = MathJax.Hub.getAllJax(), i;
for (i=0; i < all.length; i += 1) {
all[i].SourceElement().parentNode.className += ' has-jax';
}
});
</script>
<script type="text/javascript" src="{{ theme.mathjax.cdn }}"></script>
{% endif %}
{% endif %}

將之改為:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{% if page.mathjax %}
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
processEscapes: true,
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
}
});
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Queue(function() {
var all = MathJax.Hub.getAllJax(), i;
for (i=0; i < all.length; i += 1) {
all[i].SourceElement().parentNode.className += ' has-jax';
}
});
</script>
<script type="text/javascript" src="{{ theme.mathjax.cdn }}"></script>
{% endif %}

基本上這樣就大功告成了,之後在寫文章時,只要在front-matter中掛載插件mathjax: true即可:

1
2
3
4
5
6
7
8
---
title: 在Hexo顯示數學公式
tags:
- Hexo
categories:
- 程式那點事
mathjax: true
---

然而,只是安裝插件有些數學符號可能無法正確顯示,主要原因是跟Hexo的渲染引擎有關係。拿下標舉例,在Latex用下標是使用下底線_,但Markdown的斜體或粗體也是用下底線_斜體_,當數學式出現很多下標時,Hexo渲染就會把它優先轉成html形式。為了解決這個問題,我們須對Hexo的渲染做一些處理。

更改Hexo渲染設定

網路上有許多資料及做法,因原Hexo渲染插件為hexo-renderer-marked,有些方式會將此插件改為其他支援mathJax的插件,但許多做法我使用後沒有效果,不然就是要改變書寫markdown的方式,所以最後還是決定修改渲染引擎的js腳本。不過此方法也有它的缺點,其一是換一次電腦就必須變更一次設定,其二是原來使用底線做斜體的配置會失效,不過對於第二點可以使用*取代,倒也不是太大的問題。

更改方式不是太困難,找到node_modules\marked\lib\marked.js,將裡面的第451行:

1
escape: /^\\([\\`*{}\[\]()# +\-.!_>])/,

更改為:

1
escape: /^\\([`*\[\]()# +\-.!_>])/,

此步驟將原本\\轉換為\的轉譯取消。再找到459行:

1
em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,

更改為:

1
em:/^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,

這樣就把底線斜體取消了。到此應該就能完整呈現數學公式囉!好好享受吧!

參考資料

  1. hexo中插入数学公式
  2. Hexo博客(13)添加MathJax数学公式渲染
  3. Hexo 使用 Mathjax