功能价格文档博客
获取 mote
← 博客
工程·2026年7月14日·阅读需 4 分钟

不使用 Web 引擎快速渲染公式的方法

很多应用为了绘制一个公式,就得带上完整的浏览器引擎。mote 走不通这条路,所以必须寻找另一种方法。

m
mote
阅读模式中的公式。混排在句子中的行内公式和位于下方中央的块级公式,都由同一个布局引擎生成。
阅读模式中的公式。混排在句子中的行内公式和位于下方中央的块级公式,都由同一个布局引擎生成。

mote 有一条绝对规则。那就是不依赖网页引擎。

制作原型时,我发现了这一点。在这类应用中,内置浏览器引擎占据了大部分成本。所以从一开始就决定将它排除在外。

问题出在公式上。通常会把 KaTeX 或 MathJax 放进浏览器中来绘制公式。但这种方法在 mote 中无法使用。

其他方法也不合适。如果使用自己的字体渲染器,字符的形状就会与系统中的其他应用不同。因为 mote 决定使用平台的文本引擎来绘制所有字符。

最终,我们选择了最难的一条路。

mote 负责布局,平台负责字符

公式语法采用了大家熟悉的方式。在句子中,用一对美元符号包裹;单独显示时,则用两对美元符号包裹。

开始符号之后和结束符号之前不能留空格。这是为了避免把 $5$6 这样的金额误识别为公式。在人们亲手编写的 Markdown 中,这种细小的区分很重要。

绘制公式的工作被分成了两部分。

mote 的核心负责计算字符和线条的位置。实际字符则由各个平台的文本引擎绘制。

核心中包含了经过简化的 TeX 排版规则。包括四个字号层级、将符号分成八类以确定间距的表格、上下标、分数和根式的位置,以及会根据内容自动变大的括号等。

但字符的实际尺寸并不由核心决定。因为同一个字符的大小会因字体和平台而异。核心询问“以这个字号绘制这个字符时,它有多大?”,平台则给出答案。核心根据这个值完成布局,平台再在指定的位置绘制字符和线条。

因此,即使支持的平台不断增加,也只需要维护一套布局。

在编辑器中,原文也会原样保留。即使在实时模式中显示了公式,源文件的字节仍然位于该行中。只是在相应位置预留出与公式尺寸相同的空间。

所以,插入光标能够停在准确的位置,也能准确找到被点击的字符。这遵守了“即使装饰画面,也不改变文件”的原则。阅读模式和 PDF 也使用相同的布局。

实时模式中插入光标所在的行——行内公式保持原文显示,下方的块级公式则显示为排版后的分数
实时模式中插入光标所在的行——行内公式保持原文显示,下方的块级公式则显示为排版后的分数

斜体也不会被强行倾斜。它使用 Unicode 数学字符,绘制字体中实际存在的数学字形。

不会隐藏不认识的公式

公式如果悄无声息地出错,就很难被发现。

如果把不支持的命令显示为空白,用户就无法知道这是输入错误,还是应用本身的限制。所以 mote 会用红色原样显示无法识别的命令名称。

即使括号不匹配,应用也不会停止运行。我们把这类输入保留为测试用例,避免同样的问题再次发生。

性能方面的原则也得到了遵守。系统会按照公式和字号,最多保存 512 个计算结果。输入时不会反复计算相同的公式,用户没有进行任何操作时,也不会在后台运行任何任务。

导出为 HTML 时使用 MathML。由于浏览器会直接绘制公式,因此不需要脚本。即使没有网络,公式也能照常显示。

也有一些功能尚未实现

mote 并不支持完整的 TeX。

目前还不支持用户自定义命令、颜色指定、公式编号、多行上下标、字符上方的符号,以及箭头上方的文字。

也没有能够根据宽度伸展的重音符号。宽帽符看起来也会像窄帽符一样。大型求和符号和积分符号没有使用专用字形,而是放大到 1.45 倍进行绘制。本应只沿纵向伸展的括号,也会同时沿横向和纵向变大。

行内分数会像 TeX 一样显示得较小。如果想让它显示得更大,就需要通过单独的命令进行指定。

我们不会把这些功能说成已经存在。收到相关需求后,会逐一添加。

我们没有因为一个公式而改变整个应用的成本结构。相反,我们改变了绘制公式的方式。

虽然这是一条更难的路,但我们相信它是一条能够长久走下去的路。

← 较早为了在其他工具中也显示为相同段落,我们定义了 Enter 键的规则较新 →0.9.0-beta.1:首次公开测试版包含的内容
通过RSS持续关注。
只留下文字
简体中文
© 2026 mote