likes
comments
collection
share

MathJax与KaTex的对比与选型

作者站长头像
站长
· 阅读数 19

一、背景

有道小P(小P官网 )是新一代AI全科学习助手,通过拍题答疑、AI查词和翻译等工具提升学习能力,提供用户在学习或者工作中,不同细分场景下需求的解决。 该项目中涉及到流式回答中公式的渲染。目前主流的公式语言是LaTex、TEX、MathML与AsciiMath四种。在项目中,我们用到的是LaTex公式。 MathJax与KaTex的对比与选型 MathJax与KaTex的对比与选型

二、公式语言介绍

LaTeX、TeX、MathML 和 AsciiMath 都是与文档排版和数学公式表示相关的技术,但它们各自有不同的用途和特点:

1. LaTeX (LAh-TEK or LAY-tek):

  • LaTeX 是一种基于 TeX 的排版系统,由 Leslie Lamport 于1985年开发。
  • 它提供了一套丰富的宏包和文档类,使得用户可以方便地创建具有复杂排版需求的文档,如学术论文、书籍和技术报告。
  • LaTeX 特别适合数学、物理和计算机科学等领域的文档排版,因为它具有强大的数学公式排版能力。

2. TeX (TEKH):

  • TeX 是由 Donald E. Knuth 开发的一种排版系统,最初设计用于生成高质量的数学和科学文献。
  • 它是一种编程语言,具有强大的排版功能,包括宏定义和自动化排版特性。
  • TeX 是 LaTeX 和其他许多排版系统的基础。

3. MathML (Math Markup Language):

  • MathML 是一种基于 XML 的标记语言,用于在互联网上表示数学公式和符号。
  • 它被设计为与其他 XML 技术一起使用,并可以被浏览器和其他软件解析以显示数学内容。
  • MathML 支持复杂的数学表达式,并可以用于创建可访问的数学内容。

4. AsciiMath:

  • AsciiMath 是一种轻量级的数学标记语言,使用简单的 ASCII 字符来表示数学公式。
  • 它易于编写和阅读,适合在不支持 LaTeX 或 MathML 的环境中使用,如电子邮件、论坛帖子或简单的文本编辑器。
  • AsciiMath 可以被特定的软件或服务转换为 LaTeX 或 MathML,以便进一步处理和显示。

5. 小结

  • LaTeX 和 TeX 主要用于创建具有高质量排版的复杂文档,特别是在学术领域。
  • MathML 提供了一种在互联网上表示数学内容的标准方式,支持复杂的数学表达式和可访问性。
  • AsciiMath 是一种简单易用的数学标记方法,适用于快速的文本交流和笔记。
  • 每种技术都有其适用场景,选择哪一种取决于具体的需求、目标受众和期望的排版质量。

三、LaTex的一些基础用法介绍

可将公式复制到这里实时查看渲染效果

1. 数学表达式

  • $\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}$
  • $E = mc^2$。

2. 希腊字母

$\alpha, \beta, \gamma, \delta, \epsilon$

3. 数学符号

$\sum, \prod, \lim, \infty, \triangle, \pm, \times, \div, \neq$

4. 上标和下标

x_i 表示第 \(i\) 个 \(x\) 的值。 $f(x) = ax^2 + bx + c$

5. 括号与矩阵

  • 括号: $\left( \frac{a}{b} \right)$
  • 矩阵:
\begin{matrix}
a & b \\
c & d
\end{matrix} 

6. 运算符

$\frac{a}{b}, \sqrt{a}, \overline{AB}, \underline{AB}, \oint, \bigcap, \bigcup$

7. 分数与根号

$\frac{1}{2}, \dfrac{\partial f}{\partial x}$ ,$\sqrt{2}, \sqrt[3]{x}$

8. 渲染效果

MathJax与KaTex的对比与选型

四、主流工具MathJaxKaTex的对比

1. 体量不同

  • KaTeX 仅仅支持关于 TeX/LaTeX 输入和 HTML、MathMl 的输出,更加轻量化,不会支持Latex的所有功能,特别是一些高级宏包和命令
  • MathJax更加综合,还支持 MathML 和 AsciiMath 的输入,且输出格式还支持 svg、mathML,还提供了对辅助技术的支持(例如,为数学生成语音文本,或为它输出盲文,并提供数学的交互式探索,等等)

2. 渲染速度不同

  • KaTex 以其快速渲染而闻名,它通常比 MathJax 快得多,因为它使用纯 JavaScript 来生成和渲染数学公式,而不是像 MathJax 那样使用 HTML+CSS 或者 SVG。
  • MathJax 相对会更慢,因为:
    • 使用 MathML 作为其内部格式,因此所有输入格式都被转换为MathML ,输出时候再转成配置的格式如 SVG,这使得耗费的时间更多
    • 渲染时追踪更多的边界信息如高度、深度、宽度和扩展等,来保证正确处理SVG输出以及MathJax的缩放特性
    • MathJax
  • 需要注意的是,MathJax3 是对mathjax2版本的重写,在性能上有了很大的提升,且支持通过单文件配置,两者的速度差已经明显缩小了

3. 支持的语法范围不同。

MathJax可支持更多的语法,如下面的公式,在katex中并不支持,而mathjax中可渲染: K\kern-.2em\raise.21em{\scriptstyle{A}}\kern-.17em T\kern-.14em\lower.5ex{E}\kern-.115em X

  • mathjax渲染结果:MathJax与KaTex的对比与选型
  • KaTex中无法渲染

此外,KaTex 也不支持 \label 等语法,e.g:

\begin{equation}
\frac{\partial^2 u}{\partial t^2} - c^2 \nabla^2 u = 0
\label{wave_eq}
\end{equation}

% 为公式设置一个自定义标签并显示公式
\begin{equation}
\left( \frac{\partial^2}{\partial x^2} - \frac{\partial^2}{\partial y^2} \right) \psi = m^2 \psi
\tag{S}
\label{sch_eq}
\end{equation}

4. 扩展依赖支持程度不同

  • MathJax有更丰富的扩展包,如physics.js,使得可以支持更丰富的物理公式(e.g. \pderivative{x}
  • 对比之下 KaTex 则相对有限

5. 浏览器的兼容性

  • KaTeX 相对是更新的工具,因此对旧版本浏览器兼容较差,但在各种浏览器上的性能表现相对一致。
  • MathJax 支持更广泛的浏览器,包括一些旧版本,但不同浏览器的性能可能会有所不同。

6. 社区和支持:

  • KaTeX 作为一个相对较新的项目,KaTeX 的社区可能没有 MathJax 的社区那么成熟。
  • MathJax 由于存在时间较长,MathJax 拥有一个成熟的社区和大量的用户基础,提供了大量的教程、问答和第三方资源。

7. 小结

综上,KaTex与MathJax各有优劣,综合考虑到如下几个因素,我们在项目中最终使用了 MathJax中的Tex2Svg形式

  1. 历史原因:代码是从其他项目迁移,用的mathjax 2.7.6版本,改成 KaTex 会有一定成本
  2. 场景为h5应用,基本不会出现同时渲染大量公式,渲染速度的差异可以忽略
  3. 流式输出公式内容有较大不确定性,因此需要支持更丰富的MathJax
  4. 体积问题。MathJax 2版本,需要上百M,这是MathJax的劣势,但是在MathJax新版本这个问题并不存在了

五、MathJax的版本对比与升级

1. 版本升级背景

目前主流的是Mathjax 2Mathjax 3 版本,Mathjax 4 仍处于beta版本 有道小P的前端代码是从有道硬件中拉的,用的是mathjax2.7.6版本,压缩前体积有150M,并有数万个小文件。 在ios中,解压后的文件最低占用4.1KB,导致第一版,在ios应用市场上体积去到了300+M。

2. 产生原因

  • mathjax2的使用中,先加载入口文件mathjax/mathjax.js?xxx,再根据实际要展示的内容,加载其他需要的资源文件,实际依赖是不确定的
    • 可以拷贝这份html,修改里面的latex公式后,加载的js文件会有所不同 因此,mathjax2中,哪怕我只需要tex2svg的内容,其他形式的转换并不需要,最稳妥的方法也是将整个文件夹拷贝下来,避免渲染时丢失文件

当然,mathjax2拷贝下来的一些没配置的文件是可以直接删除的: 1.字体文件、其它的的转换方法文件等

  1. 项目中只需要支持latex公式,因此用于支持mathMl、AsciiMath格式的文件也可以直接删掉 在这之后上,难以确定哪些文件是完全不需要的。删除后,仍有近100M的体积

3. MathJax2与3版本的对比

mathjax3与mathjax2主要有有下列区别:  

    1. mathjax3重构了2,渲染流程
    2. 渲染性能优化,特别是在启动时间上,因为采用了新的架构,此外,mathjax2是较早的版本,涉及到IE浏览器等兼容场景,而3并没有
    3. 实现了组件,对不同的转换方式抽离成了单独的文件,配置更灵活
    • 有效解决了使用时不存在依赖不确定的问题
    • 体积更小 -小很多那种小!
  1. 一些需要在mathjax2中额外配置的扩展,在3中是默认加载的
    1. api与配置的变化、兼容性等,需要重新配置效果
    2. mathjax3移除了一些配置
    3. mathjax3并没有完全移植2的内容,因为还在迭代中,如扩展autobold等
    4. mathjax2的HTML-CSS配置中支持STIX与TEX字体,3仅支持TEX字体
    5. mathajx3不支持自动换行 综上分析,升级到mathjax3虽然也有弊,但是影响都不大,体积优化上利大于弊

4. 升级实践

  1. 配置调整:利用官方转换工具得到转换后的配置以及注意事项
  2. 插件扩展: a. 小P项目中,mathajax2使用了如下插件,这些插件都需要额外加载,并在加载成功后重新注入到mathjax中 + ["AMSmath.js","AMSsymbols.js","extpfeil.js","mhchem.js", "autobold.js", "enclose.js", "color.js"] + 上述依赖除不被支持的autobold外,都已经内置到mathjax3中的tex-svg.js文件中,因此不再需要显式引入 b. 将2中显式引入插件的相关代码删除,因为3中被自动引入了
  3. 渲染的写法变了,变成了promise,而不是mathjax2中的callback
const rendMath = (mathEle, callback) => {
  const mathContent = mathEle || document.body;
  if (window.MathJax) {
    // 使用MathJax.typesetPromise进行异步渲染
    window.MathJax.typesetPromise([mathContent]).then(() => {
      // 类型设置完成后,执行回调函数
      if (callback) {
        callback();
      }
    }).catch((error) => {
      console.error('MathJax typesetting failed:', error);
    });
  }
}

5. 升级效果

mathjax2 升级为 mathjax3 后

  1. 同样是tex2svg的功能,mathjax3只需要几百KB,mathjax2在稳妥的情况下则需要100+MB,体积减少了99%
  2. 渲染速度更快
  3. 引入的文件从数万个文件变成一个

六、升级mathjax3后的异常与解决

公式无法自动换行

在升级mathjax3后,发现出现了公式过长时,无法自动换行的问题(Mathjax2没有这个问题) MathJax与KaTex的对比与选型 这是由于mathjax3没有完全迁移mathjax2,因此不支持。

豆包的公式渲染使用的是mathjax3.2.2,一样有这个问题,如下图: MathJax与KaTex的对比与选型

换行问题解决方案

升级至mathjax4。 通过github issue可知,在mathajx4-beta版本已经实现了换行内容

升至mathjax4后的适配

mathjax4的改动内容见文档,对使用中有影响的主要是下面三个

1. 增加自动换行属性,可以这样配置:

MathJax = {
    svg:{
        linebreaks: {                  // options for when overflow is linebreak
          inline: true,                   // true for browser-based breaking of inline equations
          width: '100%',                  // a fixed size or a percentage of the container width
          lineleading: .2,                // the default lineleading in em units
          LinebreakVisitor: null,         // The LinebreakVisitor to use
        }
    }
}

2. 修改了默认字体,且增加了可使用的字体(mathjax3只支持一种字体),可通过下列属性配置

MathJax = {
    ...
      output:{
        font:'mathjax-tex'
      }
    ...
}

3. 点击公式和有较大概率出现弹窗

检查发现是因为4默认启用了无障碍功能,会显示公式字符与盲文(mathjax3也启用了,但点击后不会有弹窗,4会有) a. 点击公式字母后的弹窗示意图 MathJax与KaTex的对比与选型

b. 调用的位置(浏览器中调试后定位到)\ MathJax与KaTex的对比与选型

c. 解决:关闭无障碍配置,因为项目中不考虑该场景(无障碍配置文档:docs.mathjax.org/en/latest/o…)

MathJax = {
  ...
  options: {
    a11y: {
      speech: false,                      // switch on speech output
      braille: false,                     // switch on Braille output
      subtitles: false,                   // show speech as a subtitle
      viewBraille: false,                // display Braille output as subtitles
    }
  }
  ...
};

前面提到,mathjax4处于beta版本,但是实际上该版本已经迭代了两年了,相对比较稳滴,且升级后经测试暂未发现渲染异常的情况

七、 其他流式对话的公式渲染工具

Kimi: KaTex 豆包: MathJax 3.2.2

转载自:https://juejin.cn/post/7397638569732456488
评论
请登录