背景与前言
在显示公式时,我选择了通过JavaScript在前端渲染公式,这样有以下的优势:
- 显示清晰,不会因为网页的放大或缩小或web端不同设备的差异带来模糊感。
- 避免了复杂的图片管理。
- 公式的可复用性高,自己可以将相关公式代码取出,阅读者也易于复用。
通过网上阅读教程[1]等,我选择了mathjax作为渲染的方式。
如何引入mathjax
引入mathjax可以参考[1]中的步骤,在wordpress的主题相关文件header.php
中添加对应的代码,有必要的话可以采用wordpress的子主题以增强可维护性。
特别是,我启用了单$
的公式定界符,具体配置过程,此处先略去,之后待维护。
实际使用中遇到的问题和处理手段
问题及处理手段
这是这篇记录的关键部分,因为在公式编辑中尝尝出现无法渲染的情况,所以需要在此记录需要注意的事项,以便以后查阅,减少翻看他人博文重复收集资料带来的繁琐流程。
在目前编辑的公式中,发现有四类情况会导致公式渲染失败。通过分析发现,这是markdown的渲染先于mathjax的渲染,会将公式中的一些字符先被markdown渲染而导致mathjax渲染时缺少要素,导致渲染失败。以下mathjax会渲染失败的四种情况:
- 下标标记
_
- 换行标记
\\
- 大括号
{
和}
- 小于号
<
所以这四类情况需要加转义符号\进行转义,转义后变成如下情况,其中换行标记需要加两个转义符:
- 下标标记
\_
- 换行标记
\\\\
- 大括号
\{
和\}
- 小于号
&l
t;
出于简单考虑,我使用了word-mathtype输入公式-剪切复制选项设置为应用于网页的公式-转换为TEX-全部替换以上四种关键词,来实现网页上显示的效果。
虽然这样的可替换性较差,但只是为了在此处可以显示,并且可以让其他人看到,我采用了如上的方式渲染公式。
并且可以修改markdown的渲染方法,取消_
的斜体渲染,但是我没有尝试这个路线。
此外,还有一类特殊情况,就是mathtype转换的独立公式定界符,这类情况不会直接导致渲染公式内部的改变,但是可能导致公式渲染失效,没有被mathjax识别。
在mathtype转换为的独立公式定界符是\[
和\]
,需要替换为\\[
和\\]
,否则会被识别成中括号。某种程度这也是一种渲染失败,可能在早期使用mathjax的过程中,我都手动换成了$$
定界符,导致对这个问题不敏感,直到撰写过程中,调试VBA脚本才意识到这个问题。
效果展示
- 下标标记的替换前后:
转换前:
$ g = \sum\limits_{i = 1}^n {{ci}{1{{E_i}}}} $,
可见i}{1
部分被转换成了斜体,即_
被markdown首先渲染成了下标标记,从而导致公式渲染的失败。
转换后:
$$ g = \sum\limits_{i = 1}^n {{c_i}{1_{{E_i}}}}$$
- 换行标记的替换前后
转换前:$(\begin{array}{l}f\left( x \right) = 1\g\left( x \right) = 2\end{array})$
可以发现\\
被解释成了一个转义\
和一个标记\
,留给mathjax的只有一个\
了。
转换后:
$$
\begin{array}{l}f\left( x \right) = 1\\g\left( x \right) = 2\end{array}
$$
- 大括号的替换前后
转换前:$(f\left( x \right) = \left{ {\sin x} \right.)$
可见left
和{
之间的\
消失了,导致渲染失败。左右{
}
同理。
转换后:
$$
f\left( x \right) = \left\{ {\sin x} \right.
$$
- 小于号的替换前后
转换前:<
会被当做html的标签,导致整体的渲染失败。因为会影响后续页面,不方便单行展示,故不展示。
转换后:
$$1 < 2$$
- 独立公式定界符的替换前后
转换前:[\sin x=x],很显然\[
和\]
没有被当作公式的定界符,需要额外加一个反斜杠,变成\\[
和\\]
转换后:
\[\sin x=x\]
- 其它情况的自行修正处理
由于mathtypo的TEX转换而引入的小括号或中括号,可以在渲染结束后自行检查并视美观程度删除。
批量替换以上符号
可以采用在Word中使用VBA脚本一次性替换掉以上的特殊符号,在Word中点击alt
和F8
,即可唤出VBA控制台,自行添加并运行,VBA代码如下:
Sub EscapeSpecialCharacters()
Dim rng As Range
Set rng = ActiveDocument.Content
With rng.Find
.ClearFormatting
.Replacement.ClearFormatting
.Forward = True
.Wrap = wdFindContinue
.MatchWildcards = False
' 替换下标标记 _ 为 \_
.Text = "_"
.Replacement.Text = "\_"
.Execute Replace:=wdReplaceAll
' 替换换行标记 \ 为 \\\\(两个反斜杠)
.Text = "\\"
.Replacement.Text = "\\\\"
.Execute Replace:=wdReplaceAll
' 替换定界标记 \[ 为 \\[
.Text = "\["
.Replacement.Text = "\\["
.Execute Replace:=wdReplaceAll
' 替换下标标记 \] 为 \_
.Text = "\]"
.Replacement.Text = "\\]"
.Execute Replace:=wdReplaceAll
' 替换大括号 { 为 \{
.Text = "\{"
.Replacement.Text = "\\{"
.Execute Replace:=wdReplaceAll
' 替换大括号 } 为 \}
.Text = "\}"
.Replacement.Text = "\\}"
.Execute Replace:=wdReplaceAll
' 替换小于号 <
为 &l
t;
.Text = "<
"
.Replacement.Text = "&l
t;"
.Execute Replace:=wdReplaceAll
End With
MsgBox "替换完成!", vbInformation
End Sub
请注意:如果复制这个VBA脚本,请留意替换小于号部分。不要用代码块的copy按钮功能,请直接复制文本,否则还会出现&l
t;
的诸多问题。这里仅仅是调整了一些转义符,使得人眼直观可以看到最直接的代码逻辑,copy按钮拷贝出来会是转义了的字符。