Hugo Markdown 中的数学
概述
用 LaTeX 编写的数学方程和表达式在学术和科学出版物中很常见。你的浏览器通常使用开源 JavaScript 显示引擎(如 MathJax 或 KaTeX)来渲染这种数学 markup。
例如,此 LaTeX markup:
\[
\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}
\]渲染为:
方程和表达式可以与其他文本内联显示,或作为独立块显示。块显示也称为"display"模式。
方程或表达式是内联显示还是作为块显示,取决于围绕数学 markup 的分隔符。分隔符成对定义,每对由一个开始和一个结束分隔符组成。开始和结束分隔符可以相同,也可以不同。
你可以配置 Hugo 使用 MathJax 或 KaTeX 显示引擎在客户端渲染数学 markup,或者在构建站点时使用 transform.ToMath 函数渲染 markup。
下面介绍第一种方法。
设置
按照以下说明使用 LaTeX markup 在 Markdown 中包含数学方程和表达式。
- Step 1
- 在站点配置中启用并配置 Goldmark passthrough extension。passthrough 扩展保留原始 Markdown 在 delimited 文本片段中,包括分隔符本身。
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。在基础模板中使用此参数,如 Step 3 所示。上面的配置排除了使用
$...$分隔符对作为内联方程。虽然你可以将此分隔符对添加到配置和 JavaScript 中,但你必须在数学上下文之外使用时双转义$符号以避免意外格式。参见 inline delimiters 部分了解详情。
要禁用内联片段的 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": [ [ "\\[", "\\]" ], [ "$$", "$$" ] ] } } } } } }你可以定义自己的开始和结束分隔符,只要它们与你在 Step 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": [ [ "@", "@" ] ] } } } } } } - Step 2
- 创建 partial 模板来加载 MathJax 或 KaTeX。下面的示例加载 MathJax,或者你可以使用 KaTeX,如 engines 部分所述。
layouts/_partials/math.html
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-chtml.js"></script> <script> MathJax = { tex: { displayMath: [['\\[', '\\]'], ['$$', '$$']], // block inlineMath: [['\\(', '\\)']] // inline }, loader:{ load: ['ui/safe'] }, }; </script>上面的分隔符必须与站点配置中的分隔符匹配。
- Step 3
- 从基础模板有条件地调用 partial 模板。
layouts/baseof.html
<head> ... {{ if .Param "math" }} {{ partialCached "math.html" . }} {{ end }} ... </head>上面的示例如果你在 front matter 中将
math参数设置为true,则加载 partial 模板。如果你没有在 front matter 中设置math参数,条件语句回退到站点配置中的math参数。 - Step 4
- 如果你在站点配置中将
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" } - Step 5
- 使用 LaTeX markup 在 Markdown 中包含数学方程和表达式。
content/math-examples.md
This is an inline \(a^*=x-b^*\) equation. These are block equations: \[a^*=x-b^*\] \[ a^*=x-b^* \] \[ a^*=x-b^* \] These are also block equations: $$a^*=x-b^*$$ $$ a^*=x-b^* $$ $$ a^*=x-b^* $$
内联分隔符
上面的配置、JavaScript 和示例使用 \(...\) 分隔符对作为内联方程。$...$ 分隔符对是常见的替代方案,但如果你在数学上下文之外使用 $ 符号,使用它可能导致意外格式。
如果你将 $...$ 分隔符对添加到配置和 JavaScript 中,你必须在数学上下文之外使用时双转义 $ 符号以避免意外格式。例如:
I will give you \\$2 if you can solve $y = x^2$.如果你使用 $...$ 分隔符对作为内联方程,并且偶尔在数学上下文之外使用 $ 符号,你必须使用 MathJax 而不是 KaTeX 以避免 this KaTeX limitation 导致的意外格式。
引擎
MathJax 和 KaTeX 是开源 JavaScript 显示引擎。
如果你使用 $...$ 分隔符对作为内联方程,并且偶尔在数学上下文之外使用 $ 符号,你必须使用 MathJax 而不是 KaTeX 以避免 this KaTeX limitation 导致的意外格式。
参见 inline delimiters 部分了解详情。
要使用 KaTeX 而不是 MathJax,将 Step 2 中的 partial 模板替换为以下内容:
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/katex@0.16.25/dist/katex.min.css"
integrity="sha384-WcoG4HRXMzYzfCgiyfrySxx90XSl2rxY5mnVY5TwtWE6KLrArNKn0T/mOgNL0Mmi"
crossorigin="anonymous"
>
<script
defer
src="https://cdn.jsdelivr.net/npm/katex@0.16.25/dist/katex.min.js"
integrity="sha384-J+9dG2KMoiR9hqcFao0IBLwxt6zpcyN68IgwzsCSkbreXUjmNVRhPFTssqdSGjwQ"
crossorigin="anonymous">
</script>
<script
defer
src="https://cdn.jsdelivr.net/npm/katex@0.16.25/dist/contrib/auto-render.min.js"
integrity="sha384-hCXGrW6PitJEwbkoStFjeJxv+fSOOQKOPbJxSfM6G5sWZjAyWhXiTIIAmQqnlLlh"
crossorigin="anonymous"
onload="renderMathInElement(document.body);">
</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}$$如上面 Step 2 所示,MathJax 无需额外配置即可支持化学方程。要为 KaTeX 添加化学支持,按照 KaTeX documentation 中的描述启用 mhchem 扩展。