前言
最近发现利用hexo
搭建的博客无法渲染数学公式,hexo
默认使用的渲染引擎hexo-renderer-marked
不支持 LATEX 。而网上采用的各种方式要么不方便要么效果不理想。最后自己阅读文档构建出了了一个自认为不错的方案。主要采用了 KATEX 库,以及hexo
的插件功能,具有很好的可迁移性。
update: 结果后来发现Icarcus这个模板本来就支持 MathJax 和 Katax -_-|||,只不过需要手动转义。详见: Icarus User Guide - Other Plugins。
安装 KaTeX 库
nodejs中比较主流的数学公式渲染库有MathJax和 KATEX 。查看MathJax以及Katex文档后,感觉后者使用更加方便,于是选用了后者。
虽然nodejs还有一些功能更加强大的数学公式渲染工具,如vditor,但是没直接提供api,我也懒得去读代码。
回到正题,在hexo博客项目下,安装 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} $$
|
期望显示的效果如下:
acif bif d}行内数学公式
用$
表示行间数学公式
期望显示的效果为: E=mc2
编写插件
查看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');
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的默认渲染引擎,迁移也十分方便。