问题分析
不难发现,上边既然有成功的渲染,就说明 MathJax 本身没有罢工。而且,仔细观察还会发现,第一个公式中最开始两个*
中间的字体变成了斜体;第二个公式中最开始两个_
也是同样的情况。审查元素发现,第一个公式中的斜体部分被渲染成了``标签:
这样来看答案就很清楚了:这个错误是由 Markdown 渲染器(默认的是 hexo-renderer-marked )引起的。Markdown 本身并不支持 Latex,在渲染时正则匹配到两个_
或*
就会把下划线替换成了``,于是到了 MathJax 渲染公式时就彻底懵了。
解决办法也很简单:使用 hexo-renderer-kramed 替换 Hexo 默认的渲染器 hexo-renderer-marked。
替换默认渲染引擎
hexo-renderer-kramed 是 hexo-renderer-marked 的 Fork 修改版,仅针对 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: /^\\([`*\[\]()#$+\-.!_>])/, 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: /^\*((?:\*\*|[\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*>' + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' + '|^<\\?[\\s\\S]*?\\?>' + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>', 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\*])\*(?!\*|[^\spunctuation])|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/, code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/, br: /^( {2,}|\\)\n(?!\s*$)/, del: noop, text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n))|(?= {2,}\n))/ };
|