Hexo 中 Latex 公式渲染问题


问题分析

不难发现,上边既然有成功的渲染,就说明 MathJax 本身没有罢工。而且,仔细观察还会发现,第一个公式中最开始两个*中间的字体变成了斜体;第二个公式中最开始两个_也是同样的情况。审查元素发现,第一个公式中的斜体部分被渲染成了``标签:

1
<em>})=\frac{x-x^</em>

这样来看答案就很清楚了:这个错误是由 Markdown 渲染器(默认的是 hexo-renderer-marked )引起的。Markdown 本身并不支持 Latex在渲染时正则匹配到两个_*就会把下划线替换成了``,于是到了 MathJax 渲染公式时就彻底懵了。

解决办法也很简单:使用 hexo-renderer-kramed 替换 Hexo 默认的渲染器 hexo-renderer-marked

替换默认渲染引擎

hexo-renderer-kramedhexo-renderer-markedFork 修改版,仅针对 MathJax 渲染的语义冲突问题进行了修改,因此可以放心使用。在 Hexo 根目录下执行以下命令替换默认渲染引擎:

1
2
npm uninstall hexo-renderer-marked --save
npm install hexo-renderer-kramed --save

更换渲染引擎后,整行公式就可以正常显示了,然而行内公式还是会遇到标签语义冲突的问题。在 Markdown 语法中,用$$包括起来的内容表示整行公式,用$包括起来的内容表示行内公式。之所以行内公式的渲染依然存在问题,是因为 hexo-renderer-kramed 引擎同样存在语义冲突的问题。

解决语义冲突

在博客根目录下,找到node_modules/kramed/lib/rules/inline.js文件,在inline变量中做出如下修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var inline = {
// escape: /^\\([\\`*{}\[\]()#$+\-.!_>])/, 第 11 行, 将其修改为
escape: /^\\([`*\[\]()#$+\-.!_>])/,
autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
url: noop,
html: /^<!--[\s\S]*?-->|^<(\w+(?!:\/|[^\w\s@]*@)\b)*?(?:"[^"]*"|'[^']*'|[^'">])*?>([\s\S]*?)?<\/\1>|^<(\w+(?!:\/|[^\w\s@]*@)\b)(?:"[^"]*"|'[^']*'|[^'">])*?>/,
link: /^!?\[(inside)\]\(href\)/,
reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
reffn: /^!?\[\^(inside)\]/,
strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
// em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, 第 20 行,将其修改为
em: /^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
br: /^ {2,}\n(?!\s*$)/,
del: noop,
text: /^[\s\S]+?(?=[\\<!\[_*`$]| {2,}\n|$)/,
math: /^\$\$\s*([\s\S]*?[^\$])\s*\$\$(?!\$)/,
};

第 11 行的修改去掉了\\{},目的是在原基础上去掉对\{}的转义 (escape)。

第 20 行的修改去掉了\b_((?:__|[\s\S])+?)_\b,目的是去掉对两个_之间内容的``标签转义。

也就是说,依然可以在 Hexo 中使用*表示斜体,但_表示斜体就不会生效了

另外在行内公式中,针对两个*的语义冲突依旧存在,目前来看没什么比较好的解决办法(摊手)。

hexo-renderer-marked

同样的,在查看 hexo-renderer-marked 中使用的 marked 程序后,可以定位到535行,进行如下修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var inline = {
escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
url: noop,
tag: '^comment'
+ '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
+ '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
+ '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
+ '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
+ '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>', // CDATA section
link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
strong: /^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,
// em: /^_([^\s_])_(?!_)|^\*([^\s*<\[])\*(?!\*)|^_([^\s<][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_<][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s<"][\s\S]*?[^\s\*])\*(?!\*|[^\spunctuation])|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,
em: /^\*([^\s*<\[])\*(?!\*)|^\*([^\s<"][\s\S]*?[^\s\*])\*(?!\*|[^\spunctuation])|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,
code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
br: /^( {2,}|\\)\n(?!\s*$)/,
del: noop,
text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n))|(?= {2,}\n))/
};

Hexo 中 Latex 公式渲染问题

http://blog.czccc.cc/p/fcc15206/

作者

Cheng

发布于

2020-01-03

更新于

2022-08-06

许可协议

评论