mathjax渲染异常与hexo prism高亮无效bug

Prism高亮

在安装设置完hexo之后,写代码的时候发现hexo默认自带的代码高亮工具highlight.js不太好用。便安装了Prism代码高亮插件。

Prism高亮插件GitHub仓库地址

安装方式:

npm i -S hexo-prism-plugin

安装完成之后需要关掉hexo自带的高亮,并配置prism。

mathjax显示

使用markdown编辑mathjax公式,markdown显示正常,部署到hexo中显示异常。

这个数学公式问题,主要是Hexo的Markdown解析器与MathJax有冲突引起的。

Markdwon本身的特殊符号与Latex中的符号出现冲突的时候,比如:

  • _的转义,在markdown中,_是斜体,但是在latex中,却有下标的意思,这样你在公式里面写下标会被解析为斜体。
  • \\的换行,在markdown中,\\会被转义为\这样也会影响影响mathjax对公式中的\\进行渲染。

hexo默认使用marked.js去解析我们写的markdown,比如一些符号,_代表斜体,会被处理为<em>标签,比如x_i在开始被渲染的时候,处理为x<em>i</em>,这个时候mathjax就无法渲染成下标了。很多符号都有这个问题,比如粗体*,也是无法在mathjax渲染出来的,好在有替代的乘法等,包括\\同理。 所以说到底,是hexo使用的markdown引擎的锅,因为很多其它引擎在这方面处理的很好。

不仅仅是公式的问题,代码也会出现这个问题,比如说<code><代码>在尖括号里面的字母或者数字会被隐藏。如下图:

尖括号字母被隐藏

上图是我在markdown中打出来的内容,而页面显示的部分却少了一块。

原因在于尖括号之间的内容会被解析为HTML元素,并且后面的内容样式会改变。我就遇到过c++代码中的部分内容消失了,就是因为这部分代码被包在了尖括号中,最简单的方法是输入尖括号之后加一个空格,如:< code>

那么如何避免mathjax公式的显示异常问题呢?

1. 手动转义(最简单)

这个方法最直接,多写一个转义。比如需要在公式中写下标符号,那就修改写法写为: x\_i,需要换行就使用\\\\,即可,需要写<的地方多加一个空格。

如果你不需要迁移到其他平台的话可以这样做,最简单。而且用\\\\换行到其他平台也影响不大,只是由一个换行变成了两个换行。

2.代码块保护

markdown解析的时候是不会解析两个 ` 之间内容的,某些情况下可以使用这种方法,但是需要注意的是mathjax仍然会解析里面的公式。

3.手动修改渲染引擎源码(失败)

hexo默认的渲染引擎为 hexo-renderer-marked,源码文件地址: nodes_modules/marked/lib/marked.js:

修改渲染引擎源码主要有两个目的:

  • 去掉\\的额外转义,这样\\就可以实现换行,就不会影响mathjax公式的换行显示了;
  • 将em标签对应的符号中,去掉_,因为markdown中有*可以表示斜体,去掉了就不会影响mathjax的下标显示了。

根据网上的教程,打开nodes_modules/marked/lib/marked.js

找到escape那一行

escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
    替换成
escape: /^\\([`*{}\[\]()# +\-.!_>])/,

找到em的那一行:

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

PS:

可能由于marked插件的版本不同,我的escape那一行和网上的不太一样

并且更改之后也没有效果,\\仍然不能实现换行。

4.更换模板引擎(可用)

以下是替代原始解析器的两个模板引擎:

  • hexo-renderer-pandoc,很强大的解析器,Pandoc的语法完全没有上述问题, 但是安装比较麻烦。
  • hexo-renderer-kramed,安装方便,修改了marked中一部分bug,但还是有部分问题。

以安装kramed为例:

安装kramed

npm uninstall hexo-renderer-marked --save // 卸载marked
npm install hexo-renderer-kramed --save // 安装kramed

kramed对于block形式的公式可以正确渲染,但是对于内联公式inline仍然有问题。所以我们仍然需要修改其转义部分的源码。

修改源码

打开/node_modules\kramed\lib\rules\inline.js
更改后为:

escape: /^\\([`*\[\]()#$+\-.!_>])/,
em: /^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,

我们输入以下图片中的公式,发现可以正常显示:

公式代码

显示效果:

$a_0\\b_{12}$

总结:

1.如果想正确显示公式,又不想太折腾,那么在输入公式的时候,用\_代替_,用\\\\代替\\,缺点是markdown文件放到其他平台时,渲染方式不兼容。

2.愿意折腾以下又追求完美的,可以更换渲染引擎,如pandoc和kramed。pandoc安装比较麻烦,但是听说很好用。kramed安装简单,但是内联公式显示仍然有问题,需要修改源码中的转义方式。并且kramed可能和hexo的其他插件发生冲突,比如上面安装的代码高亮插件Prism。

prism与kramed冲突

安装配置完kramed之后,mathjax公式显示正常了,但是这时候又发现了一个新的问题:

prism代码高亮失效了:

并且我们看到右上角的语言名前面多了一个Lang-

直觉告诉我,无法高亮与右上角的变化有关。

首先,markdown中代码块是以

格式写出来的。

通过查看网页元素,发现这些被固定格式包起来的代码,被渲染完成之后是以 < pre >< code >your code< /code > < /pre >的元素形式存在的

代码在页面中的元素

hexo中的主题中存在对应的CSS文件,用来渲染这些元素。

由于kramed渲染引擎会自动修改代码元素的class name,所以导致prism插件找不到对应元素,也就无法自动高亮代码块中的代码。

解决方法:

打开\node_modules\kramed\lib\renderer.js

langPrefix: 'lang-',
改为
langPrefix: '',

即可防止kramed自动修改元素的class name

最终prism又恢复了正常,效果如下:


  上一篇
搜索算法综述 搜索算法综述
本文为搜索求解算法学习笔记。主要内容为启发式搜索、对抗式搜索和蒙特卡洛树搜索。启发式搜索中包含了贪婪最佳优先和A*算法,对抗式搜索包括了最大最小搜索和以此为基础的Alpha-Bata剪枝搜索。
2020-10-02
下一篇 
MobileNet--准确与速度的均衡 MobileNet--准确与速度的均衡
卷积神经网络(CNN)在计算机视觉领域产生了许多新进展也衍生出了许多新型的网络,其中MobileNet就是CNN在轻量级网络的一个非常优秀的网络架构探索。
2020-07-27
   目录