参考文章:

  1. hexo 更换 markdown渲染器 @upupming/hexo-renderer-markdown-it-plus
  2. Butterfly 安裝文檔(四) 主題配置-2
  3. Pandoc User’s Guide
  4. MathJax Documentation

1 我的需求

最近写的文章包括很多数学公式,但是当在typora中写好后,放到页面上却出现了各种显示上的问题,比如公式不全,公式超出文章边界等等一系列问题。这让我不得不寻找另外的文章渲染器。

2 hexo博客的渲染插件

首先上网查了一下hexo博客目前可用的渲染器,主要有以下几个。

2.1 hexo-renderer-marked

hexo-renderer-marked是hexo默认的渲染器,不支持复杂的数学公式,正是我需要换掉的。

2.2 hexo-renderer-kramed

hexo-renderer-kramed在默认渲染器的基础上添加了mathjax的支持,支持更多的数学公式,与原渲染器有冲突,需要先卸载默认的渲染器再使用它。

1
2
npm uninstall hexo-renderer-marked --save # 先卸载原渲染器
npm install hexo-renderer-kramed --save # 安装hexo-renderer-kramed

配置hexo根目录的配置文件_config.yml

1
2
3
4
5
6
7
8
kramed:
gfm: true
pedantic: false
sanitize: false
tables: true
breaks: true
smartLists: true
smartypants: true

具体字段的说明见github。

采用这种渲染器对于大多数公式都没有问题,但是复杂的公式,比如矩阵、特殊符号等仍然显示不全,无法满足我的需求。

2.3 hexo-renderer-markdown-it

hexo-renderer-markdown-it增加了对CommonMark的支持,渲染速度更快,并且支持一些脚注。不过默认不支持数学公式,需要额外安装KaTeX插件,具体操作方法见:How can I add math support?,总之我尝试了之后,不能解决我的问题。

2.4 hexo-renderer-markdown-it-katex

hexo-renderer-markdown-it-katex默认支持KaTeX插件,但是KaTeX插件本身对公式支持的不完善,所以仍不能满足我的需求。

2.5 hexo-renderer-markdown-it-plus

hexo-renderer-markdown-it-plus能渲染的东西更多了、支持的功能也更多,对于普通用户来说已经足够了,但是公式渲染还是不够好。

3 数学显示插件

前面介绍的都是hexo的渲染器,它们本身并不具备渲染数学公式的能力(或只有简单的公式可以渲染)。真正让数学公式可以显示的是两大插件,分别是mathjax和katex,hexo的渲染器基本上是通过它们之一来获得对数学公式的支持。

相比于mathjax来说,katex速度更快,更轻量,但没有前者的功能多。如果你的需求仅仅是简单公式的话,katex就足够了。由于我需要编写更复杂的公式,因此我选择使用功能更多的mathjax。具体选择什么还是取决于使用需求。

4 使用pandoc获得更好的mathjax支持

pandoc是一个强大的渲染工具,它支持从多种标记格式转换为另一种标记格式,这里就包括markdown和mathjax格式,以及其它许许多多的格式,就像瑞士军刀一样,它可以完美处理markdown文档中的数学公式。可以查看pandoc官网了解更多pandoc支持的格式。插件hexo-renderer-pandoc可以使用pandoc作为hexo的渲染器。

下面介绍如何使用pandoc和mathjax作为我的博客渲染器。

4.1 安装pandoc和hexo-renderer-pandoc插件

首先,卸载默认的hexo渲染器,安装hexo-renderer-pandoc插件:

1
2
npm uninstall hexo-renderer-marked --save # 先卸载原渲染器
npm install hexo-renderer-pandoc --save

然后,为你的电脑安装2.0版本以上的pandoc。进入pandoc下载页面,点击Download the latest installer,然后下载安装即可(pandoc支持Windows、mac、linux系统),对于windows系统,可能需要重启一次电脑使配置生效。

配置hexo根目录的配置文件_config.yml

1
2
3
4
5
6
7
8
9
pandoc:
args:
- '-f'
- 'commonmark_x'
- '-t'
- 'html'
- '--mathjax'
extensions:
- '-implicit_figures'

-f表示输入格式,-t表示输出格式,这里的commonmark_x,是带有扩展的CommonMark风格,还可以替换为以下的markwodn书写风格:

--mathjax用于添加mathjax数学公式的支持。

对于更多插件的配置,具体参考Pandoc User’s Guidehexo-renderer-pandoc

4.2 安装hexo-filter-mathjax插件

然后安装hexo-filter-mathjax插件,该插件用于后端渲染mathjax:

1
npm install hexo-filter-mathjax

配置hexo根目录的配置文件_config.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mathjax:
tags: none # or 'ams' or 'all'
single_dollars: true # enable single dollar signs as in-line math delimiters
cjk_width: 0.9 # relative CJK char width
normal_width: 0.6 # relative normal (monospace) width
append_css: true # add CSS to pages rendered by MathJax
every_page: true # if true, every page will be rendered by MathJax regardless the `mathjax` setting in Front-matter
packages:
- physics
- mathtools
- color
- noerrors
- amsmath
extension_options: {}
# you can put your extension options here
# see http://docs.mathjax.org/en/latest/options/input/tex.html#tex-extension-options for more detail

这里主要关注以下mathjax的扩展包配置,也就是packages。可以查看The TeX/LaTeX Extension List,里面包含了目前支持的所有扩展包,我这里添加了一些需要用到的包。注意,扩展包并不是越多越好,满足够用原则即可,否则可能会拖慢渲染速度!

every_page设置为true,每个页面都会由mathjax呈现,如果你只需要某些页面使用mathjax,则需要这里设置为false,并对于某篇特定的文章中,添加:

1
2
3
4
5
6
---
title: xxxx
categories: xxx
date: xxxx-xx-xx xx:xx:xx
mathjax: true
---

就可以在单独的这篇文章中使用latex语法。

4.3 后端渲染与前端渲染

上一节介绍的方法是通过hexo-filter-mathjax插件进行后端渲染mathjax的。什么是后端渲染与前端渲染呢?众所周知,hexo是静态博客,需要经过渲染器编译之后才能修改页面上的内容,这个经过渲染器编译修改的过程就包括了mathjax的后端渲染,经过后端渲染后,此时页面上已经是html格式的文件了。

而前端渲染,就是直接引入mathjax.js(一般是通过CDN引入到页面),此时并不需要hexo-filter-mathjax插件对文章中的公式内容进行编译,而是将其交给前端的mathjax.js进行处理,这就是前端渲染。

理解前端渲染和后端渲染之后,我们来分析一下它们各自的优点和缺点:

前端渲染后端渲染
优点1.无需hexo-filter-mathjax插件;
2.拥有支持mathjax.js支持的全部功能,比如右键菜单;
1.在后端完成公式渲染,不需要引入CDN,减少流量消耗,提升页面加载速度;
缺点1.依赖CDN引入,增加网页流量消耗;
2.可能会拖慢网页html加载速度;
1.需要hexo-filter-mathjax插件支持;
2.无法支持前端mathjax.js提供的全部功能,比如不支持右键菜单;

我个人使用过前端渲染后,发现CDN引入的方式不稳定性很多(CDN一般都是外网,访问速度堪忧,国内镜像源容易挂掉,不稳定),因此我倾向于后端渲染,但是为了文章的完整性,这里介绍前端渲染的使用方式。

首先还是需要安装pandoc和hexo-renderer-pandoc插件,然后不需要安装hexo-filter-mathjax插件,而是直接为页面引入CDN:

有许多免费的 CDN 服务提供 MathJax 的副本。其中大多数要求你指定要加载的 MathJax 的特定版本,但有些提供“滚动版本”,即在发布时更新到最新可用版本的链接。

比如要使用 jsdelivr ,可以这样写:

1
2
3
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">
</script>

更多的细节可以参考Using MathJax from a Content Delivery Network (CDN)

对于butterfly来说,你可以直接在butterfly的项目配置文件_config.butterfly.yml中的inject下添加:

1
2
3
4
inject:
head:
- <script defer src="mathjax_config.js"></script>
- <script type="text/javascript" id="MathJax-script" defer src="https://unpkg.com/mathjax@3/es5/tex-chtml.js"></script>

这里引入CDN文件后,可以进行自定义配置,因此这里我额外引入了mathjax_config.js这个文件,文件中的内容参考官方文档的配置方法,你可以这样写:

1
2
3
4
5
MathJax = {
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']]
}
};

对于更多的配置,非常复杂,每个人的需求不同,因此强烈建议去看官方文档!

以上,通过使用pandoc+mathjax渲染博客,完美解决了所有的公式渲染问题,目前使用非常丝滑,满足我的使用需求。

下面展示效果: