在Hexo中渲染latex数学公式

前言

最近发现利用hexo搭建的博客无法渲染数学公式,hexo默认使用的渲染引擎hexo-renderer-marked不支持 LaTeX\LaTeX 。而网上采用的各种方式要么不方便要么效果不理想。最后自己阅读文档构建出了了一个自认为不错的方案。主要采用了 KaTeX\KaTeX 库,以及hexo的插件功能,具有很好的可迁移性。

update: 结果后来发现Icarcus这个模板本来就支持 MathJax 和 Katax -_-|||,只不过需要手动转义。详见: Icarus User Guide - Other Plugins


安装 KaTeX 库

nodejs中比较主流的数学公式渲染库有MathJax和 KaTeX\KaTeX 。查看MathJax以及Katex文档后,感觉后者使用更加方便,于是选用了后者。

虽然nodejs还有一些功能更加强大的数学公式渲染工具,如vditor,但是没直接提供api,我也懒得去读代码。

回到正题,在hexo博客项目下,安装 KaTeX\KaTeX 库:

1
npm install katex

在hexo插件目录添加脚本

查看hexo官方文档,发现可以直接添加脚本使其在启动时自动加载,只需要将javascript文件放到scripts文件夹。

编写的插件需要使得渲染引擎hexo-renderer-marked能够识别并渲染我们编写在markdown文件中的数学公式。

行间数学公式

$$表示行间数学公式

1
2
3
4
5
6
$$
\begin{drcases}
a &\text{if } b \\
c &\text{if } d
\end{drcases}
$$

期望显示的效果如下:

aif bcif d}\begin{drcases} a &\text{if } b \\ c &\text{if } d \end{drcases}

行内数学公式

$表示行间数学公式

1
$ E=mc^2 $

期望显示的效果为: E=mc2E=mc^2

编写插件

查看marked的文档,编写代码并放入scripts文件夹:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
const { marked } = require('marked');
const katex = require('katex');
require('katex/contrib/mhchem'); // modify katex module

const equationBlock = {
name: 'equationBlock',
level: 'block',
start(src) {
let m = src.match(/\n\s*\$\$\s*\n/)
if(m) return m.index;
return null;
},
tokenizer(src, tokens) {
const rule = /^\s*\$\$\s*\n[^\$]*\$\$\s*\n/;
const match = rule.exec(src);
if(match){
const token = {
type: equationBlock.name,
raw: match[0],
text: match[0].trim().slice(2,-2).trim(),
tokens: []
};
return token;
};
},
renderer(token) {
let html;
try{
html = katex.renderToString(token.text,{displayMode: true, strict: false})
}catch(e){
console.log(e)
html = `<a style=" color: red; font-weight: bolder; ">KaTeX parse error</a>`
}
return html;
}
}

const equationInline = {
name: 'equationInline',
level: 'inline',
start(src) {
let m = src.match(/\s\$ /)
if(m) return m.index;
return null;
},
tokenizer(src, tokens) {
const rule = /^\s*\$ [^\n\$]+ \$(?:\s|$)/;
const match = rule.exec(src);
if(match){
const token = {
type: equationInline.name,
raw: match[0],
text: match[0].trim().slice(1,-1).trim(),
tokens: []
};
return token;
};
},
renderer(token) {
let html;
try{
html = ` ${katex.renderToString(token.text,{displayMode: false})} `
}catch(e){
html = `<a style=" color: red; font-weight: bolder; ">KaTeX parse error</a>`
}
return html;
}
}

marked.use({
extensions: [equationBlock, equationInline]
});


在博客页面插入样式表

在模板文件中加入以下script标签,检测到html中有.katex的元素时,插入样式表:

1
2
3
4
5
6
7
8
9
10
11
if(document.querySelector('.katex')) {
let l = document.createElement('link');
l = Object.assign(l, {
rel:"stylesheet",
href:"https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.css",
integrity:"sha384-K1E1xaIzoWihlXfiT5fcmLNabsnrl+dqc0errnRwtMX14tKRA9cCYNDGnXiHEZMs",
});
l.setAttribute("crossorigin" ,"anonymous");
document.head.appendChild(l)
}


这个方法不用修改node_module下的依赖库,也不用手动给markdown文件添加html标签,不用更换hexo的默认渲染引擎,迁移也十分方便。

在Hexo中渲染latex数学公式

https://psu.monster/post/2024/64096642afe4

作者

psu

发布于

2024-06-15

更新于

2024-06-19

许可协议

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×