Markdown 中的数学公式
概述
在学术和科学出版物中,使用 LaTeX 或 TeX 编写的数学方程式和表达式很常见。您的浏览器通常使用开源JavaScript显示引擎(例如 MathJax 或 KaTeX )来呈现此数学标记。
例如,这是本页顶部显示的方程式的数学标记:
\[
\begin{aligned}
KL(\hat{y} || y) &= \sum_{c=1}^{M}\hat{y}_c \log{\frac{\hat{y}_c}{y_c}} \\
JS(\hat{y} || y) &= \frac{1}{2}(KL(y||\frac{y+\hat{y}}{2}) + KL(\hat{y}||\frac{y+\hat{y}}{2}))
\end{aligned}
\]
方程式和表达式可以与其他文本内联显示,也可以作为独立的块显示。块呈现也称为“显示”模式。
方程式或表达式是内联显示还是块显示,取决于围绕数学标记的分隔符。分隔符成对定义,每一对包含一个起始分隔符和一个结束分隔符。起始和结束分隔符可以相同,也可以不同。常见的分隔符对在 步骤1 中显示。
以下描述的方法避免依赖于平台特定的功能,例如简码或代码块渲染钩子。相反,它使用标准化的数学方程式和表达式的标记格式,与GitHub、GitLab、 Microsoft VS Code 、 Obsidian 、 Typora 等使用的渲染引擎兼容。
设置
按照以下说明,使用LaTeX或TeX排版语法在Markdown中包含数学方程式和表达式。
步骤1
在您的站点配置中启用并配置Goldmark passthrough扩展 。passthrough扩展保留分隔文本片段内的原始Markdown,包括分隔符本身。
markup:
goldmark:
extensions:
passthrough:
delimiters:
block:
- - \[
- \]
- - $$
- $$
inline:
- - \(
- \)
enable: true
params:
math: true
[markup]
[markup.goldmark]
[markup.goldmark.extensions]
[markup.goldmark.extensions.passthrough]
enable = true
[markup.goldmark.extensions.passthrough.delimiters]
block = [['\[', '\]'], ['$$', '$$']]
inline = [['\(', '\)']]
[params]
math = true
{
"markup": {
"goldmark": {
"extensions": {
"passthrough": {
"delimiters": {
"block": [
[
"\\[",
"\\]"
],
[
"$$",
"$$"
]
],
"inline": [
[
"\\(",
"\\)"
]
]
},
"enable": true
}
}
}
},
"params": {
"math": true
}
}
除非您在 front matter 中将 math
参数设置为 false
,否则上述配置将在每个页面上启用数学渲染。要根据需要启用数学渲染,请在站点配置中将 math
参数设置为 false
,并在front matter中将 math
参数设置为 true
。如 步骤3 所示,在您的基础模板中使用此参数。
要禁用内联片段的passthrough,请从配置中省略 inline
键:
markup:
goldmark:
extensions:
passthrough:
delimiters:
block:
- - \[
- \]
- - $$
- $$
[markup]
[markup.goldmark]
[markup.goldmark.extensions]
[markup.goldmark.extensions.passthrough]
[markup.goldmark.extensions.passthrough.delimiters]
block = [['\[', '\]'], ['$$', '$$']]
{
"markup": {
"goldmark": {
"extensions": {
"passthrough": {
"delimiters": {
"block": [
[
"\\[",
"\\]"
],
[
"$$",
"$$"
]
]
}
}
}
}
}
}
您可以定义自己的起始和结束分隔符,前提是它们与您在 步骤2 中设置的分隔符匹配。
markup:
goldmark:
extensions:
passthrough:
delimiters:
block:
- - '@@'
- '@@'
inline:
- - '@'
- '@'
[markup]
[markup.goldmark]
[markup.goldmark.extensions]
[markup.goldmark.extensions.passthrough]
[markup.goldmark.extensions.passthrough.delimiters]
block = [['@@', '@@']]
inline = [['@', '@']]
{
"markup": {
"goldmark": {
"extensions": {
"passthrough": {
"delimiters": {
"block": [
[
"@@",
"@@"
]
],
"inline": [
[
"@",
"@"
]
]
}
}
}
}
}
}
步骤2
创建一个加载MathJax或KaTeX的部分模板。下面的示例加载MathJax,或者您可以按照 引擎 部分中的说明使用KaTeX。
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
<script>
MathJax = {
tex: {
displayMath: [['\\[', '\\]'], ['$$', '$$']], // block
inlineMath: [['\\(', '\\)']] // inline
}
};
</script>
上述分隔符必须与站点配置中的分隔符匹配。
步骤3
从基础模板有条件地调用部分模板。
<head>
...
{{ if .Param "math" }}
{{ partialCached "math.html" . }}
{{ end }}
...
</head>
上面的示例在您已将front matter中的 math
参数设置为 true
时加载部分模板。如果您没有在front matter中设置 math
参数,则条件语句将回退到站点配置中的 math
参数。
步骤4
使用LaTeX或TeX排版语法在Markdown中包含数学方程式和表达式。
这是一个内联\(a^*=x-b^*\)方程式。
这些是块方程式:
\[a^*=x-b^*\]
\[ a^*=x-b^* \]
\[
a^*=x-b^*
\]
这些也是块方程式:
$$a^*=x-b^*$$
$$ a^*=x-b^* $$
$$
a^*=x-b^*
$$
如果在站点配置中将 math
参数设置为 false
,则必须在front matter中将 math
参数设置为 true
。例如:
---
date: 2024-01-24T18:09:49-08:00
params:
math: true
title: Math examples
---
+++
date = 2024-01-24T18:09:49-08:00
title = 'Math examples'
[params]
math = true
+++
{
"date": "2024-01-24T18:09:49-08:00",
"params": {
"math": true
},
"title": "Math examples"
}
内联分隔符
上述配置、JavaScript和示例使用 \(...\)
分隔符对内联方程式。 $...$
分隔符对是常见的替代方案,但如果在数学上下文之外使用 $
符号,则使用它可能会导致意外的格式化。
如果将 $...$
分隔符对添加到配置和JavaScript中,则无论页面上是否启用了数学渲染,在数学上下文之外都必须对 $
进行双重转义。例如:
A \\$5 bill _saved_ is a \\$5 bill _earned_.
引擎
MathJax和KaTeX是开源JavaScript显示引擎。这两个引擎都很快,但在撰写本文时,MathJax v3.2.2略快于KaTeX v0.16.9。
要使用KaTeX而不是MathJax,请将 步骤2 中的部分模板替换为此:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css" integrity="sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js" integrity="sha384-XjKyOOlGwcjNTAIQHIpgOno0Hl1YQqzUOEleOLALmuqehneUG+vnGctmUb0ZY0l8" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
renderMathInElement(document.body, {
delimiters: [
{left: '\\[', right: '\\]', display: true}, // block
{left: '$$', right: '$$', display: true}, // block
{left: '\\(', right: '\\)', display: false}, // inline
],
throwOnError : false
});
});
</script>
上述分隔符必须与站点配置中的分隔符匹配。
化学
MathJax和KaTeX都支持化学方程式。例如:
$$C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}$$
如上 步骤2 所示,MathJax无需额外配置即可支持化学方程式。要向KaTeX添加化学支持,请按照KaTeX 文档 中的说明启用mhchem扩展。