Skip to content

Math Preview

zhangxh edited this page Aug 17, 2026 · 5 revisions

Math Preview

TeXLeaf 1.0.0 内置活动公式预览。它的产品方向受到 Ultra Math Previewhscopes-booster 启发;当前版本使用随 VSIX 提供的 MathJax 4.1.3 和 New Computer Modern SVG 字体渲染活动公式。更完整的来源说明见 致谢与联合开发

预览只读当前活动公式,不修改 TeX 文档、字符偏移、选择区或撤销历史。

支持的公式

扫描器识别:

  • $...$
  • $$...$$
  • \(...\)
  • \[...\]
  • math
  • displaymath
  • equation
  • alignalignatalignedalignedat
  • gathergathered
  • multlineflalignsplit
  • casesarray
  • matrixpmatrixbmatrixBmatrixvmatrixVmatrixsmallmatrix
  • 上述常见环境的星号形式。

扫描会跳过注释、\verb、verbatim、Verbatim、lstlisting 和 minted 内容。嵌套 matrix/cases 等作为同一外层公式的一部分处理,避免显示重复卡片。

Math Preview 只在已保存的 .tex 文档、LaTeX/TeX language ID 和启用设置下运行;.bib、Untitled 或 Markdown 不显示。

显示模式

texleaf.mathPreview.presentation 有三种值:

行为
cursor 默认;光标进入公式时显示浮动卡片
hover 使用 VS Code 原生 Hover 显示无光标公式
both 同时注册 cursor 和 Hover

默认 cursor 可以减少与 LaTeX Workshop 等扩展自带 Hover 的重复。若主题或某版 VS Code 与浮动 decoration 不兼容,可切到 hover 作为稳定降级路径。

预览中的光标

cursor 模式会把编辑器光标位置规划到安全 TeX 边界,再向 MathJax 输入中插入一条窄的 \rule

  • 形状类似 |
  • 深色主题使用鲜艳青色 #00e5ff
  • 浅色主题使用洋红色 #e0005a
  • 不把标记插入命令名、环境名、\left/\right 定界符、分数参数边界、注释、verb、UTF-16 surrogate pair 等危险位置;
  • 带光标渲染失败时自动回退到无光标公式,而不是只剩空框。

Hover 模式不显示光标标记。

行内公式定位

行内公式的 autoBelow 模式优先使用“活动源码行下方”,autoAbove 则优先使用“活动源码行上方”:

  • 光标在公式起始行:卡片左边缘与 $\( opening delimiter 对齐;
  • 光标在同一多行公式的后续行:卡片移动到该活动行的所选方向,左边缘与该行第一个非空白字符对齐;
  • 不与光标的横坐标对齐;
  • 不强制跑到编辑器第 0 列;
  • 首选侧空间不足时,两种自动模式会按下节规则尝试另一侧;above / below 则固定垂直方向。

卡片绝对定位,不参与 Monaco 的同行文字宽度计算,因此不会像旧版行内附件那样把后续输入推挤、折行或叠成一团。

行间公式定位

行间公式保持 opening delimiter 的静态水平起点:

  • \[ 对齐它的反斜杠;
  • $$ 对齐第一个 $
  • \begin{align}\begin{equation} 等对齐 \begin 的反斜杠;
  • 纵向锚点落在结束行或可见尾部时,会根据 Tab 和缩进计算视觉列补偿,仍保持 opening 列;
  • 最多只注入一个经过数值限制的 ch 平移,不把文档文本或任意 CSS 拼入 decoration。

VS Code 稳定 API 不公开编辑器内容视口的可靠像素右边界。TeXLeaf 因此不做会偶尔跳到第 0 列的伪“右侧空间自动拟合”;超宽卡片保持正确 opening 对齐,右端可能被编辑器裁切。

autoBelowautoAbove 的上下方选择

默认 autoBelow 是“自动(优先下方)”:

  1. 下方能完整容纳预览时显示在下方;
  2. 下方不足时改到上方。

新增的 autoAbove 是“自动(优先上方)”:

  1. 上方能完整容纳预览时显示在上方;
  2. 上方不足时改到下方。

如果上下都不能完整容纳预览,两种自动模式都强制选择上方。对于超高、多行公式,它们共用同一套 overflow-tail 锚点:允许卡片顶部被视口裁切,同时尽量保留预览底部和公式源码最后三行,便于继续写公式尾部。

显式 above / below 严格服从用户选择,不自动改方向,也不会为显示预览而滚动文档。位置选择只依据公式边界、可见空间和设置,不根据原生 Suggest 候选数量猜测小组件方向。

旧设置值 auto 仍作为 autoBelow 的运行时兼容别名生效,避免已有用户配置突然改变方向;它不再出现在设置 UI 的可选值中,新配置应使用对称名称 autoBelow

卡片外观

卡片的背景、边框、内边距和圆角直接画入安全 SVG:

主题 公式 光标 背景 边框
深色 #ffffff #00e5ff #0b0f14,100% 不透明 白色,32%
浅色 #202020 #e0005a #fafafc,100% 不透明 黑色,28%

不透明背景可避免壁纸、透明主题和源码字符穿透公式。MathJax 输出使用真正的 SVG path/use,加上高精度渲染提示;不是公式截图或字体 <text>

最终抗锯齿仍由 VS Code 内嵌 Chromium、操作系统缩放、显示器和 window.zoomLevel 决定。TeXLeaf 不提供单独“硬件加速”开关;GPU/软件渲染由 VS Code 全局控制。关闭 VS Code 硬件加速可能改变抗锯齿,但不应作为 TeXLeaf 的默认排障步骤。

性能模型

渲染架构:

  • 扫描和当前公式选择在扩展侧进行;
  • MathJax 首次需要时才懒加载到 Node Worker Thread;
  • Worker 队列最多 32 个请求;
  • 单次渲染超时 5 秒,超时后重启 Worker,避免扩展宿主永久卡住;
  • 渲染和资产缓存各保留最多 64 项;
  • 失败结果有短暂重试冷却,避免非法 TeX 每次按键反复重算;
  • 文档版本、公式源码、主题、缩放和宏指纹参与缓存 key;
  • 过时 generation 的结果不会覆盖新文档版本;
  • 4,000 行或 1 MiB 以上大文档自动把防抖至少提高到 300 ms。

cursor / both 在连续输入时采用 last-known-good(stale-while-revalidate)策略:文档变化只重新调度,不先清空现有卡片;下一张有效 SVG 通过同一个稳定 decoration 原位换帧。临时不完整 TeX 或中间渲染失败有 750 ms 宽限,新输入或成功渲染会取消旧失败计时;Hover SVG 只在实际请求 Hover 时写入扩展私有缓存,不阻塞 cursor 帧更新。这样可避免每次按键造成“消失—重现”,同时仍拒绝过时 generation 覆盖新内容。

旧卡片不会无限保留:光标离开可识别公式、禁用预览、运行 TeXLeaf: 关闭当前 Math Preview,或停在无效状态超过 750 ms 后都会清理。hover 使用 VS Code 原生 Hover;编辑器在输入时可能主动关闭它,因此连续输入稳定性特指 cursor decoration,不承诺改变原生 Hover 的生命周期。

cursor 卡片宽度超过 40em 时会等比缩放;256em 高度只是异常 TeX 几何的绘制安全上限,不是把普通长公式强行压成 8em。

可通过 texleaf.mathPreview.debounceMsscalemaxSourceLength 调整开销。完整默认值见 配置参考

可以在设置中提供宏:

{
  "texleaf.mathPreview.macros": {
    "RR": "\\mathbb{R}",
    "inner": ["\\left\\langle #1,#2 \\right\\rangle", 2]
  }
}

规则:

  • 键名不含开头反斜杠,只允许字母和 @
  • 最多 128 项;
  • 单个 replacement 最多 2,048 字符;
  • 序列化后总长度最多 16,384 个 UTF-16 字符;
  • 参数个数可以从 #1...#9 推断;
  • 文档前言中受支持的定义覆盖同名设置。

扫描器会从前言解析保守形式的:

  • \newcommand
  • \renewcommand
  • \providecommand
  • \DeclareMathOperator

复杂 TeX 宏展开不等同于真正 LaTeX 引擎;动态包加载、任意代码和递归宏受限。

渲染安全

Worker 只启用明确允许的 MathJax TeX package,例如 base、ams、mathtools、newcommand、color 和受限 configmacros。安全边界包括:

  • 用户设置的最大公式长度,默认 8,192;Worker 硬上限 32,768;
  • MathJax maxBuffer 和宏展开上限;
  • 受限宏数量、名称、替换长度和总序列化长度;
  • 禁用动态 require/autoload 和 HTML 类输入;
  • 输出必须是闭合 SVG;
  • 拒绝 scriptforeignObject、iframe/object/embed、事件属性和外部 URL;
  • decoration 使用 Base64 data: SVG,避免 Windows 长缓存路径导致空框;Hover 资产使用扩展私有缓存。

命令

命令 作用
TeXLeaf: 切换 Math Preview 在当前资源所属范围切换总开关
TeXLeaf: 刷新 Math Preview 清除扫描、SVG、错误和资产缓存并重渲染
TeXLeaf: 关闭当前 Math Preview 暂时隐藏当前卡片;继续编辑或移动光标后可再出现

cursor 卡片显示时按 Escape 可关闭;Suggest、Rename 或 Inline Suggest 活动时不会抢占 Escape。

VS Code API 边界

cursor 预览使用 Monaco decoration 的固定 ::before 兼容层,因为 VS Code 稳定扩展 API 不提供公开 view-zone 或任意编辑器浮层接口。这带来明确限制:

  • 卡片不能给正文真正预留垂直空间;上下紧邻正文时可能暂时遮住相邻行;
  • 无法可靠读取横向视口像素,所以超宽卡片允许右端裁切;
  • 无法读取 Suggest 等原生弹出小组件的公开几何,预览不会跟随其开关或尺寸自动换边;
  • decoration 没有可靠点击回调;
  • 不能在保持 TextEditor 光标、选择、折叠、撤销和诊断语义的同时,把源码范围替换成可点击 MathJax 部件。

因此 TeXLeaf 专注于不改变源码语义的活动公式预览,不提供“光标离开后原地变公式、点击恢复源码”的整篇所见即所得替换,也不内置 PDF Webview 或 Custom Editor。需要 PDF 编译和 SyncTeX 时,请继续使用 LaTeX Workshop 或自己的构建工具。

与其他预览扩展共存

  • 默认使用 cursor,避免重复 Hover;
  • 若 LaTeX Workshop Hover 仍重叠,保持 TeXLeaf cursor 或关闭其中一方 Hover;
  • 如果同时启用其他公式预览扩展,应选择其中一个 cursor/hover 入口,避免重复卡片;
  • 两个 cursor decoration 同时存在时,分别关闭其中一个扩展的预览总开关;
  • 主题透明度不会传入 TeXLeaf 卡片背景,但主题或 VS Code 更新仍可能影响 decoration 定位。

常见问题

症状 处理
只有圆角空框 运行刷新命令;确认当前是 1.0.0;查看 Output 中 MathJax/资产错误
深色公式模糊 检查 VS Code zoom/系统缩放;切换默认主题比较;不要用全局 CSS 给 SVG 加 stroke
卡片遮住相邻行 增加公式附近空白行,改用 hover,或显式 above/below
Suggest 挡住卡片 Suggest 通常出现在光标下方,可改用 autoAbove 优先把预览放在上方;需要完全固定时使用 above。VS Code 不公开小组件几何,预览不会根据它自动换边
行间公式右端被裁切 这是保持 opening 对齐的已知边界;可降低 scale 或临时横向滚动
预览没对齐 检查 opening delimiter、Tab Size;提供最小复现和截图
自定义宏不生效 键不要带 \;检查长度/数量;运行刷新命令;简化定义
持续输入时 cursor 卡片每键消失 确认已升级到 1.0.0;cursor/both 会保留 last-known-good 并原位换帧,短暂失败宽限 750 ms
停在非法公式后旧卡片仍短暂显示 这是 750 ms 宽限;继续完成公式,或等待清理。离开公式、禁用和 Dismiss 会立即清理
原生 Hover 输入时关闭 VS Code 控制 Hover 生命周期;需要连续输入稳定显示时使用 cursorboth
大文档更新慢 大文档自动至少 300 ms;可进一步提高 debounce、降低 maxSourceLength

更详细的日志与平台排查见 故障排查

相关页面

Clone this wiki locally