xaringan 幻灯片行内公式渲染问题的全方案总结

从逻辑冲突到工程化复用的深度排坑

Author

技术笔记

Published

May 11, 2026

1. 核心痛点

在使用 xaringan (基于 remark.js) 编写幻灯片时,常会遇到一行内出现多个行内公式(Inline Math)导致渲染失败的问题。例如: 当 $a=1$ 且 $b=2$ 时... 往往只有第一个 $a=1$ 正常,后续内容保持源码。

这是因为 remark.js 对 $ 符号的识别机制较为保守,容易与 Markdown 语法(如斜体 _)产生解析歧义。

2. 三大处理方案

根据使用场景的不同,我们可以采用以下三种方式来强制 MathJax 正确解析公式。

方案 A:直接在文档中嵌入脚本(快速修复)

如果你只想针对单个 .Rmd 文件快速解决问题,可以直接在文档的第一页幻灯片内容之前(YAML 下方)插入以下 HTML 代码:

<script type="text/x-mathjax-config">
MathJax.Hub.Config({
  tex2jax: {
    inlineMath: [['$','$'], ['\\(','\\)']],
    processEscapes: true
  }
});
</script>

优点:即插即用,无需额外文件。 缺点:如果有多个幻灯片项目,每个文件都要复制这段代码,维护性差。

方案 B:通过 includes 注入(文件解耦)

将上述脚本保存为 mathjax-header.html,然后在 YAML 中引用:

output:
  xaringan::moon_reader:
    includes:
      in_header: mathjax-header.html

注意:此方案的文件内容必须包含 <script> 标签。

方案 C:使用 beforeInit 接口(工程化推荐)

这是最专业的方法,适用于多个项目复用同一套逻辑。创建纯 JavaScript 文件 mathjax-config.js不含 HTML 标签):

/* mathjax-config.js */
window.MathJax = {
  tex2jax: {
    inlineMath: [['$', '$'], ['\\(', '\\)']],
    displayMath: [['$$', '$$'], ['\\[', '\\]']],
    processEscapes: true,
    processEnvironments: true
  }
};

在 YAML 中通过 nature 接口调用:

output:
  xaringan::moon_reader:
    nature:
      beforeInit: "mathjax-config.js"

3. 技术经验与注意事项 (SOP)

无论采用哪种方案,编写公式时仍需遵守 remark.js 的刚性规则:

  1. 紧贴原则$ 必须紧贴公式首尾,中间严禁有空格。
    • $x+y$ | ❌ $ x+y $
  2. 转义下标:公式内包含多个下标 _ 时,务必写成 \_
    • 示例:$x\_i + y\_j$ 防止被识别为 Markdown 斜体。
  3. 禁止跨行:行内公式内容必须在同一行内完成。
  4. 备选定界符:若 $ 依然不稳定,可改用 LaTeX 原生定界符 \( ... \)

4. 方案对比与选择建议

维度 方案 A (直接嵌入) 方案 B (Header 注入) 方案 C (beforeInit)
文件要求 .html (带标签) .js (纯代码)
复用性
适用场景 临时单页测试 静态资源统筹 跨项目标准化开发

总结:针对 xaringan 的数学公式问题,推荐优先使用 方案 C 并配合转义下标的习惯,这能最大程度保证文档在 inf_mr() 实时预览与正式部署时的一致性。