Mathjax部署

Mathjax部署

研究了很多方法,比如用hexo install hexo-math --save来安装,但是这种安装需要换markdown渲染引擎,然而我的代码高亮插件和kmarked冲突,然后这种方法就咕咕咕了。
但是,突然在星空str的博客中看到了直接把mathjax内置到主题内部的方法,和我的password的实现方式有几分相似,于是便尝试了一下,果然很不错!
$$
F_a = F_b + F_c + F_{\mu}\\
\begin{cases}
\frac{x^2}{a^2}+\frac{y^2}{b^2}=1\\
Ax+By+C=0
\end{cases}
$$

配置过程

下面我就直接复制粘贴博客(上面有超链接)上的原话了,并且修改了一些细节。
首先在themes/mic/layout/_partial目录中新建mathjax.ejs,填入如下js代码:

<!-- MathJax配置,可通过单美元符号书写行内公式等 -->
<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
    "HTML-CSS": { 
        preferredFont: "TeX", 
        availableFonts: ["STIX","TeX"], 
        linebreaks: { automatic:true }, 
        EqnChunk: (MathJax.Hub.Browser.isMobile ? 10 : 50) 
    },
    tex2jax: { 
        inlineMath: [ ["$", "$"], ["\\(","\\)"] ], 
        processEscapes: true, 
        ignoreClass: "tex2jax_ignore|dno",
        skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
    },
    TeX: {  
        equationNumbers: { autoNumber: "AMS" },
        noUndefined: { attributes: { mathcolor: "red", mathbackground: "#FFEEEE", mathsize: "90%" } }, 
        Macros: { href: "{}" } 
    },
    messageStyle: "none"
    }); 
</script>
<!-- 给MathJax元素添加has-jax class -->
<script type="text/x-mathjax-config">
    MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for(i=0; i < all.length; i += 1) {
            all[i].SourceElement().parentNode.className += ' has-jax';
        }
    });
</script>
<!-- 通过连接CDN加载MathJax的js代码 -->
<script type="text/javascript" async
  src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML">
</script>

之后,考虑到在每个页面都加载mathjax会比较慢,所以我们就只在含有mathjax公式的页面里才渲染,判断方式和password的判断方式一样,就是通过判断页面文件的front-matter中的mathjax是否为true即可。
因此,我们在所有有公式的文章的front-matter中增加一项配置 mathjax: true,例如:

---
title: 结构化机器学习项目
tags:
  - 机器学习
categories:
  - 机器学习
date: 2017-10-9 22:22:00
toc: false
mathjax: true
---

然后在themes/mic/layout/post.ejs中通过此配置变量决定是否加载mathjax.ejs :

<!-- 根据页面mathjax变量决定是否加载MathJax数学公式js -->
<% if (page.mathjax){ %>
<%- partial('_partial/mathjax') %>
<% } %>

这时候写几个公式后,我们会发现markdown的渲染会与mathjax冲突,于是解决如下:(以下引用原文)
添加MathJax后写几个公式发现渲染出了很多问题,原因是Hexo默认先使用hexo-renderer-marked引擎渲染MarkDown,然后再交给MathJax渲染。hexo-renderer-marked会把一些特殊的markdown符号转换为相应的html标签,比如在markdown语法中,下划线_代表斜体,会被转化为< em>标签,\\也会被转义成一个\。而类Latex格式书写的数学公式下划线_表示角标,\\表示公式换行,有特殊的含义,所以MathJax引擎在渲染数学公式的时候就会出错。

解决方法有人提出更换Hexo的MarkDown渲染引擎,用hexo-renderer-kramed 替换默认的hexo-renderer-marked引擎,但我看了下hexo-renderer-kramed的文档说明,如果用这个引擎的话,要改变我的MarkDown书写习惯,还是不用了,并且换了这个引擎还是没有完全解决问题。

最终解决方法是参考一篇博文中修改hexo-renderer-marked渲染引擎的js脚本,去掉对_\\的转义。
Hexo默认的MarkDown渲染引擎hexo-renderer-marked会调用marked模块的marked.js脚本进行最终的解释,这个脚本在Hexo安装后的node_modules\marked\lib\目录中。
有两点修改:

针对下划线的问题,取消_作为斜体转义,因为marked.js中*也是斜体的意思,所以取消掉_的转义并不影响使用markdown,我平时一般不用斜体,就是用也更习惯用*作为斜体标记。
针对marked.js与Mathjax对于个别字符二次转义的问题,我们只要不让marked.js去转义\\,\{,\}在MathJax中有特殊用途的字符就行了。
编辑node_modules\marked\lib\marked.js脚本,
【第一步】
将451行的

escape: /^\\([\\`*{}\[\]()# +\-.!_>])/,

替换为

escape: /^\\([`*\[\]()# +\-.!_>])/,

这一步取消了对\\,\{,\}的转义(escape)
【第二步】
将459行的

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

替换为

em:/^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,

这一步取消了对斜体标记_的转义。
弊端嘛…就是每次换电脑都要重新改一次。