mathjax/MathJax-src · 上手攻略

  • 仓库:mathjax/MathJax-src
  • 链接:https://github.com/mathjax/MathJax-src
  • 分类:academic-writing / 渲染引擎
  • 作者:spark
  • 更新:2026-08-20

是什么

mathjax/MathJax-srcMathJax v3 及之后版本的源代码仓库(TypeScript 编写)。MathJax 本身是一个开源的浏览器/Node.js 数学公式渲染引擎,支持 LaTeX、MathML、AsciiMath 三种输入语法,自带无障碍支持(屏幕阅读器 + expression explorer),浏览器用户零安装(纯 CDN <script> 即可)。

需要特别注意区分两个仓库:

仓库 用途
mathjax/MathJax-src(本文) 源代码仓库,作者从源码构建、贡献 TS 代码、自定义 component 时使用
mathjax/MathJax 预编译 component 仓库,日常 CDN/npm 装包走这里

日常开发者一般不需要 clone MathJax-src,只 npm install mathjax@4 或加 CDN script 即可。本攻略主要面向想读源码 / 自定义 component / 贡献 PR 的读者。

解决什么问题

  1. 浏览器端数学公式排版:论文博客(博客园、知乎、Hexo、Jekyll、Hugo、Quarto)需要 LaTeX → SVG/HTML 渲染,MathJax 是事实标准。
  2. 学术写作工具链的"公式段":tikzplotlib(matlibplot → TikZ)、kingyiusuen/image-to-latex(图片 → LaTeX)负责"产出",MathJax 负责"在网页里显示"。
  3. Node.js 端离线公式→SVG:mathjax 包提供 tex2svgPromise,适合 SSR、报告生成、PDF 流水线的前置步骤。
  4. 可访问性 / 屏幕阅读器:MathJax 内建 ARIA、speech、explorer,远比手写 MathML 友好。

快速安装

方式 A:浏览器端最简方案(90% 用户只用这个)

<script src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-chtml.js" defer></script>

无需 git clone、无需 npm install。jsDelivr / unpkg 都托管了官方 component bundle。

方式 B:Node.js 端(SSR / 报告生成)

npm install mathjax@4

最小调用:

import MathJax from 'mathjax';
await MathJax.init({
  loader: { load: ['input/tex', 'output/svg'] }
});
const svg = await MathJax.tex2svgPromise('\\frac{1}{x^2-1}', { display: true });
console.log(MathJax.startup.adaptor.serializeXML(svg));

ES5 环境用 require('mathjax') + .then() 链,文档里有等价样例。

方式 C:从源码安装(贡献者)

git clone https://github.com/mathjax/MathJax-src.git
cd MathJax-src
npm install
npm install @mathjax/src

@mathjax/src 包提供:

  • ts/ —— TypeScript 源码
  • js/ —— 已编译 JavaScript
  • components/ —— component 构建工具 + 控制文件
  • bundle/ —— 打包产物

核心用法

1. 浏览器端 TeX 输入

直接在网页写:

<p>When \(a \ne 0\), there are two solutions to \(ax^2 + bx + c = 0\).</p>

<script>
window.MathJax = {
  tex: {
    inlineMath: [['\(', '\)']],
    displayMath: [['$$', '$$'], ['\[', '\]']]
  }
};
</script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-chtml.js" defer></script>

2. MathML + AsciiMath 混合输入

加载 mml-chtml.js(只 MathML)或 tex-mml-chtml.js(全功能):

<script src="https://cdn.jsdelivr.net/npm/mathjax@4/mml-chtml.js" defer></script>

3. Node.js 批量转换(适合 Quarto / Pandoc 流水线前置)

import MathJax from 'mathjax';
import { promises as fs } from 'fs';

await MathJax.init({ loader: { load: ['input/tex', 'output/svg'] } });

const tex = await fs.readFile('equation.tex', 'utf8');
const svg = await MathJax.tex2svgPromise(tex, { display: true });
await fs.writeFile('equation.svg', MathJax.startup.adaptor.serializeXML(svg));

4. 自定义 Component(高级)

源码仓提供了 component 构建工具链(components/ 目录 + 控制文件),常见需求:

  • 裁剪 input/output 模块,把 bundle 缩到最小
  • 替换字体
  • 加自定义 TeX 宏

构建示例(以官方 docs 为准):

npm run make-component   # 或 ts-node components/make-component.ts src/components/my-min.ts

⚠️ 自定义 component 的官方文档在 docs/mathjax/components/,社区经验显示这是 v3 → v4 最容易踩坑的地方,直接复用官方 component + lazy loader 通常比手搓更划算

典型适用场景

  1. 学术博客 / 笔记软件:Hugo、Hexo、Jekyll、Quarto 内置 MathJax 支持,加一行 frontmatter 即可。
  2. 学术 paper 写作:arXiv 编译、PDF 生成(MathJax 输出 SVG 再交给 LaTeX 模板)。
  3. AI 生成的数学教学页面:LLM 写 LaTeX 公式 → 直接渲染在页面,无需服务端。
  4. 图像公式转 LaTeX 后的浏览器复核:kingyiusuen/image-to-latex 等工具输出 LaTeX 后,用 MathJax 在浏览器里复核,比硬读 LaTeX 快。
  5. Node.js SSR / 静态站点生成:在构建时把 .tex 一次性烘焙成 SVG,运行时无 JS 依赖。
  6. 可访问性需求强的政府 / 高校站点:MathJax 的 speech + explorer 满足 WCAG / Section 508 合规。

坑与注意

⚠️ MathJax-src ≠ MathJax:多数用户应该用 mathjax/MathJax(预编译)或 npm 包 mathjax,而不是 clone 源码仓。源码仓 2k+ stars 大部分是 contributor,不是 end user。

⚠️ v4 与 v2/v3 API 差异显著:v2 的 MathJax.Hub 在 v3 已被 mathjax.init() 取代,旧教程基本失效。如果维护老项目遇到 MathJax.Hub.Config 之类的写法,说明是 v2 时代,迁移指南见 docs.mathjax.org。

⚠️ CDN 选择:jsDelivr / unpkg 都行,但不要混用不同版本:同一个页面同时加载 mathjax@3mathjax@4 会冲突,只显示先加载的版本。

⚠️ Node 端的 DOM 依赖:MathJax.init() 在 Node 下需要 alternate DOM 实现(linkededom 或 jsdom),这是 Node-only 路径。在浏览器里 require('mathjax') 跑 init() 是错的,浏览器应该用 component bundle + lazy config。

⚠️ CHTML vs SVG vs CommonHTML:输出格式影响可访问性 + 排版精度。CHTML(CommonHTML)最像 LaTeX 排版;SVG 矢量、可独立嵌入;HTML/CSS 输出文件最小但屏幕阅读器支持弱。

⚠️ 大型文档性能:几百 KB 的论文 MathJax 化时,首屏渲染可能卡顿。解决:loader.load 分块、按页 lazy、defer script 标签。

⚠️ 分支与版本:main 分支为开发版,develop 分支为下一个 minor 发布,生产环境钉死某个 release(如 mathjax@4.x)。

与同类对比

项目 输入 输出 浏览器/Node 依赖
MathJax v3/v4(本文) LaTeX/MathML/AsciiMath SVG/CHTML/HTML 都支持 TS → JS,bundle 自带字体
KaTeX LaTeX 子集 HTML + CSS 都支持 更快、更小,但 LaTeX 不完全
MathML 原生 MathML HTML 浏览器原生 0 依赖,但支持度参差(Chrome 强、Safari 弱)
LaTeX → 图片(server) LaTeX PNG/SVG 服务端 需要 LaTeX 编译器,慢且重
MathJax v2 同上 同上 都支持 已 EOL,API 与 v3+ 不兼容

MathJax 的核心优势是 LaTeX 兼容性最广(几乎完整 TeX 语义),KaTeX 更快更轻但复杂公式会渲染失败;选择标准:你的公式如果含 \label/\refaligncases、自定义宏,MathJax 几乎是唯一靠谱选择;纯分数/上下标/根号/积分,KaTeX 更快。

一句话推荐结论

学术博客 + 复杂 LaTeX 公式用 MathJax;博客渲染速度优先 + 公式简单的场景用 KaTeX;只 clone MathJax-src 的场景是"我要改源码或贡献 PR"。


进阶:MathJax 的架构与扩展点

读完 README + 仓库结构后,有几个工程决策值得工程团队理解:

1. TypeScript 编译链

ts/ 是 TS 源码,js/ 是编译产物,用户拿到的 npm install mathjax 是组件化的 bundle,不是源码。意味着:

  • 普通用户不能直接 hack MathJax 行为——必须 fork 源码仓,改 TS,重新 build component。
  • 自定义扩展要走"扩展包"机制(window.MathJax = { ... } 注册 loader),而不是 monkey patch。
  • 编译链对贡献者要求较高,PR 评审周期长(issue 跟踪看,平均 1-3 周)。

2. Component 抽象

MathJax v3+ 引入了"Component"概念:一组 input/output/extension 的可重用单元。常见 component:

Component 名 输入 输出 体积
tex-mml-chtml.js TeX + MathML + AsciiMath CHTML ~250KB gzip
tex-svg.js TeX SVG ~400KB gzip
mml-chtml.js MathML CHTML ~150KB gzip
tex-chtml.js TeX CHTML ~200KB gzip

经验法则:只加载你需要的 input + output。如果只用 TeX + CHTML,不要用 tex-mml-chtml.js(多了 MathML 解析器)。官方提供 component builder 工具裁剪。

3. 浏览器 vs Node 的 init 差异

这是 v3+ 最容易踩的设计点。Node 端需要 alternate DOM(linkedomjsdom):

// Node 端(SSR / 报告生成)
import { JSDOM } from 'jsdom';
const dom = new JSDOM('<!DOCTYPE html>');
global.document = dom.window.document;
global.window = dom.window;
// 然后才能 MathJax.init()

浏览器端不需要这套,直接 <script> 加载即可。这就是 README 强调"this method sets up an alternative DOM implementation which you don't need in the browser"的原因。

4. 输出格式选择决策树

需要矢量缩放? → SVG
  ↓ 否
需要屏幕阅读器支持? → CHTML
  ↓ 否
需要最小 bundle? → HTML(纯 CSS,仅限简单公式)

多数学术场景选 CHTML:屏幕阅读器支持最好、文本可选中复制、align 等环境排版最准。

5. 与学术写作工具链的协同

本仓库目录的兄弟项目:

  • mathjax/MathJax-demos-web —— 浏览器端 demo
  • mathjax/MathJax-demos-node —— Node 端 demo
  • nschloe/tikzplotlib(同目录选榜)—— matlibplot → TikZ,前端用 MathJax 渲染 TikZ 输出
  • kingyiusuen/image-to-latex(同目录选榜)—— 图片公式 → LaTeX 源码,仍需 MathJax 在浏览器复核

工作流示意:

matlibplot → tikzplotlib → .tex 源码
                              ↓
                    MathJax 浏览器渲染
                              ↓
                         最终页面

或者:

公式截图 → image-to-latex → .tex 源码
                              ↓
                    MathJax 浏览器复核
                              ↓
                         修正后嵌入论文

6. 字体与本地化

MathJax 默认走 CDN 字体(Web Font)。如果你的场景要求完全离线(政府内网、企业内网、教学专网),需要:

  1. 从 GitHub release 下载字体文件(STIX 或 TeX 字体)
  2. 配置 MathJax.startup.output.font.URL 指到本地路径
  3. 关闭 CDN 引用

7. 性能:大文档的渲染策略

几百 KB 文档 MathJax 化时,首屏渲染可能卡顿。常见优化:

  • 分块渲染:MathJax.typesetPromise(elements) 只 typeset 指定 DOM 节点,而不是全文档
  • 延迟渲染:滚动到公式可视区才渲染(IntersectionObserver + lazy typeset)
  • 服务端预渲染:Node 端在 build 时把 .tex → SVG,运行时无 JS 依赖

8. v2 → v3+ 迁移要点

如果你接手 v2 老项目,迁移指南核心差异:

v2 API v3+ API
MathJax.Hub.Config({...}) window.MathJax = {...} 在 script 加载前声明
MathJax.Hub.Queue(["Typeset", ...]) MathJax.startup.promisetypesetPromise(...)
MathJax.Hub.Register.StartupHook(...) MathJax.startup.registerStartupListener(...)
TeX 配置在 tex2jax TeX 配置在 tex
MathJax.Hub.processSectionDelay 等价 MathJax.startup.adaptiveCSSrenderActions

不要在 v3+ 写 MathJax.Hub,那是 v2 残留。


决策清单:什么时候用 / 不用

用 MathJax v4: - 论文博客 / 学术 Wiki - 公式含 align / cases / array / 自定义宏 - 需要可访问性(政府 / 高校 / 无障碍合规) - 团队对 TypeScript 工具链熟悉

不用 / 用 KaTeX: - 公式简单(分数 / 上下标 / 根号 / 积分) - 渲染速度敏感(评论区 / 实时聊天 / 移动端) - 不需要屏幕阅读器支持 - bundle 体积敏感(嵌入式场景)

不要 clone MathJax-src: - 普通用户(用 mathjax/MathJaxnpm install mathjax@4) - 只想要 component 裁剪(用官方 component builder,不需要源码)


主要来源 - 仓库 README:https://github.com/mathjax/MathJax-src - 官方文档:https://docs.mathjax.org - npm:mathjax@4(运行时)、@mathjax/src(源码包) - CDN:jsDelivr https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-chtml.js - Node Demos:https://github.com/mathjax/MathJax-demos-node - Web Demos:https://github.com/mathjax/MathJax-demos-web - 当前 release 分支:release-v4(npm 主版本)