很高兴和你相遇
这里正在记录我的所思所学
订阅免费邮件通讯接收最新内容
首页 归档 想法 工具 通讯 播客 简历 主页

在博客中展示数学公式

最近写的一系列文章中需要时不时插入一些数学公式,也就不得不接触一些 LaTeX 相关内容,另外由于要发到博客上,还需要让博客能够正确解析 LaTeX 语法。

Hexo 插入数学公式起步

Hexo 博客框架默然使用的 Markdown 解析插件是 hexo-renderer-marked, 我同时使用了 Next 主题。

首先要说明的是,Hexo 默认 Markdown 是不支持 LaTeX 语法的,但是,Next 的主题默认已经支持 MathJax,也就是说不需要再在网页的 header 中引入如下代码:

<script type="text/javascript"
  src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>

只需要在主题下的配置文件_config.yml中启用相关设置即可

# MathJax Support
mathjax:
  enable: true
  per_page: true
  cdn: //cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML

在需要启用 MathJax 的 post 中进行设置

---
title: 统计学基础与 R-2
mathjax: true
---

这么几步下来,网页上其实已经可以显示一部分公式了。但是在 MathJax 中,包含_(下划线)的下标表示语法还是不能正确识别。

尝试不同的 Markdown 插件

为了解决部分 MathJax 语法不能正确编译的问题,我在 Google 上大致搜了搜,主要意见都是一劳永逸的更换 Hexo 的 Markdown 插件。

第一种可供更换的插件是hexo-renderer-pandocpandoc 可以说是最牛最全的 Markdown 渲染引擎,R Markdown 用的就是它。

首先在电脑上安装 pandoc

然后在 hexo 中进行如下操作

npm un hexo-renderer-marked --save
#卸载旧的
npm install hexo-renderer-pandoc --save
安装新的

然后在后期渲染的过程中,报错了。

INFO Start processing FATAL Something’s wrong. Maybe you can find the solution here: http://hexo.io/docs/troubleshooting.html

Error: [pandoc warning] YAML header is not an object “source” (line 67, column 1)
at ChildProcess. (/Users/sean10/Code/sean10.github.io/node_modules/hexo-renderer-pandoc/index.js:73:20)
at emitTwo (events.js:106:13)
at ChildProcess.emit (events.js:191:7)
at maybeClose (internal/child_process.js:877:16)
at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)

在 pandoc 解析的过程中,渲染出现了问题,很可能是我有些文章写得 Markdown 语言并不完全符合 pandoc, 排查这么多篇文章中的错误太浪费时间,于是放弃。

随后,又找到了另一个插件,hexo-renderer-markdown-it-plus 这个插件支持各种各样的 Markdown 扩展语法,尤其是支持 katex。于是我使用后发现确实解决了部分语法不识别的问题,但是所有数学公式除了渲染输出外还会在输出一遍原始格式。迫于无奈,这个方法也放弃了。

修改默认插件语法规则

更换插件的尝试失败后,回顾问题所在其实是默认搜索引擎的下划线语法和 mathjax 的下标语法冲突。也就是说当我在一个公式中出现了两次下标,输入两次_后,默认会把两个下划线之间的部分解析为斜体

如果不想修改默认语法规则,需要在数学公式中使用\__进行转义,这么做实在是有点麻烦。干脆修改原始的默认语法规则,不让_斜体_转义为斜体字,而是只采用*斜体*的方式。

找到配置文件node_modules\marked\lib\marked.js,对escape,strong 和 em进行如下修改

var inline = {
  //escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
  escape: /^\\([`*{}\[\]()# +\-.!_>])/,
  autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
  url: noop,
  tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
  link: /^!?\[(inside)\]\(href\)/,
  reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
  nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
  //strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
  strong: /^\*\*([\s\S]+?)\*\*(?!\*)/,
  //em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
  em: /^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
  code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
  br: /^ {2,}\n(?!\s*$)/,
  del: noop,
  text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
};

保存之后,清空 hexo 缓存,重新部署一次就可以了。最后的效果,可以参考文章 统计学基础与 R-2

后续

配合默认 Markdown 渲染引擎和 MathJax 使用,其实还有一个问题,支持行内公式,但是即便修改了源代码也没有实现多行书写(\\换行),比如


$$
H=-\sum_{i=1}^N (\sigma_{i}^x \sigma_{i+1}^x+g \sigma_{i}^z)
$$

## 用 \\ 没有正常换行

$$
f(n) = \begin{cases}
 \frac{n}{2},
 & \text{if } n\text{ is even}
 \\ 3n+1, & \text{if } n\text{ is odd}
 \end{cases}
$$

## 用、\\ 代替正常的、\ 实现换行

$$
f(n) = \begin{cases}
 \frac{n}{2},
 & \text{if } n\text{ is even}
 \\\ 3n+1, & \text{if } n\text{ is odd}
 \end{cases}
$$

$$f(x): \begin{cases} x, x>0 \\\ -x,x<0 \end{cases}$$

目前下面的所有公式都能正常显示,是因为我已经解决了上文提到的问题。可以看最下面的解决方法。

H=i=1N(σixσi+1x+gσiz)H=-\sum_{i=1}^N (\sigma_{i}^x \sigma_{i+1}^x+g \sigma_{i}^z)

f(n)={n2,if n is even3n+1,if n is oddf(n) = \begin{cases} \frac{n}{2}, & \text{if } n\text{ is even} \\ 3n+1, & \text{if } n\text{ is odd} \end{cases}

f(n)={n2,if n is even 3n+1,if n is oddf(n) = \begin{cases} \frac{n}{2}, & \text{if } n\text{ is even} \\\ 3n+1, & \text{if } n\text{ is odd} \end{cases}

f(x):{x,x>0 x,x<0f(x): \begin{cases} x, x>0 \\\ -x,x<0 \end{cases}

但是hexo-renderer-markdown-it-plus是可以解决这个问题,在一篇博客中有比较详细的介绍 hexo-renderer-markdown-it-plus plugin demo,可能未来还是需要弄清楚我安装这个插件时出现重复显示的原因。


最终更新

上面提到在使用hexo-renderer-markdown-it-plus时,遇到了公式重复渲染的问题,目前这个方式已经解决,解决方法如下。

npm un hexo-renderer-marked --save
#卸载旧的默认 Markdown 插件
npm install hexo-renderer--markdown-it-plus --save
安装新的增强型插件

卸载就插件之后,之前修改的marked.js文件已经被随之删除。现在,我们最需要的是hexo-renderer-markdown-it-plus中的 Katex 插件,为了使用 katex 需要在主题中的网页中引入相关 CSS 文件。

Next 主题中,专门为用户准备了一个自定义文件,即themes\next\layout\_custom\header.swig文件。在这个自定义 header 文件中写入如下内容

<link href="https://cdn.bootcss.com/KaTeX/0.7.1/katex.min.css" rel="stylesheet">
# 不要引入最新的 katex 文件,显示效果和插件并不兼容

紧接着在 Hexo 的配置文件中进行配置(可选项)

#markdown 设置
markdown_it_plus:
  highlight: true
  html: true
  xhtmlOut: true
  breaks: true
  langPrefix:
  linkify: true
  typographer:
  quotes: “”‘’
  plugins:
    - plugin:
        name: markdown-it-katex
        enable: true
    - plugin:
        name: markdown-it-mark
        enable: false

因为该插件调用的是KaTeX\KaTeX, 因为可以将主题配置文件修改为

# MathJax Support
mathjax:
  enable: false
  per_page: false
  cdn: //cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML

同时新的文章头部也不再需要添加mathjax=true


本文作者:思考问题的熊

版权声明:本博客所有文章除特别声明外,均采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 (CC BY-NC-ND 4.0) 进行许可。

如果你对这篇文章感兴趣,欢迎通过邮箱或者微信订阅我的 「熊言熊语」会员通讯,我将第一时间与你分享肿瘤生物医药领域最新行业研究进展和我的所思所学所想点此链接即可进行免费订阅。


· 分享链接 https://kaopubear.top/blog/2017-09-19-UseMathJaxinHexo/