junzi-ana1 downloadsAutomatic equation numbering and cross-references for display math. Write \label and \ref, get numbered tags at render time — the note itself stays standard LaTeX.
Numbered equations with \label and \ref for display math in Obsidian.
Write ordinary LaTeX inside $$...$$. The plugin works out the number and renders the tag at display time — nothing is written back to the note, so the file you keep is the source you could paste into a paper.
English | 中文
MathJax renders \tag{...}, but it has no per-note equation counter, and \label / \ref do not behave the way they do in LaTeX. The usual workaround is typing \tag{1}, \tag{2}, … by hand and renumbering everything whenever a formula is inserted in the middle.
Equation Ordinal moves the whole job into the rendering layer:
\label declarations in the file;\ref resolves to the same number, already wrapped in parentheses;\tags and you keep full control when you export.Manual
manifest.json, main.js and styles.css from this repository.<vault>/.obsidian/plugins/equation-ordinal/.BRAT
Add Junzi-ana/equation-ordinal as a beta plugin.
From source
npm install
npm run build
$$
\mathrm{d}Y_t = Z_t\,\mathrm{d}W_t - F(t, Y_t, Z_t)\,\mathrm{d}t,\qquad Y_T = \xi
\label{eq:bsde}
$$
\label may sit anywhere inside the display block — at the end, in the middle, or on its own line. It is removed and the tag is placed where MathJax expects it.
Combining $\ref{eq:bsde}$ with the estimate above, ...
Works in inline math and in display math. \eqref{...} is accepted as an alias.
The output is already parenthesised — write $\ref{eq:bsde}$, not $(\ref{eq:bsde})$.
The counter starts at 1 and increments once per labelled display block.
\label{name}[N] sets the counter to N instead of incrementing it. N is a sequence of numbers and dots; only the segment after the last dot is incremented afterwards.
| Source order | Markup | Rendered |
|---|---|---|
| 1 | \label{a} |
(1) |
| 2 | \label{b} |
(2) |
| 3 | \label{c}[5.1.10] |
(5.1.10) |
| 4 | \label{d} |
(5.1.11) |
| 5 | \label{e}[A.1] |
(A.1) |
| 6 | \label{f} |
(A.2) |
| 7 | \label{g}[7] |
(7) |
| 8 | \label{h} |
(8) |
Rules for N:
3, 4.2, 5.1.10 are fine;A.1, A.B.3 are fine;1.2., .1, 1..2, 3a.The counter belongs to the note, not to the file name, so a note that starts with \label{x}[5.1] produces (5.1), (5.2), … in any vault.
Problems are reported in place and in the console (with file name and line number). Nothing is silently dropped.
| Code | Cause |
|---|---|
E01 |
\label used inside inline math $...$ |
E02 |
more than one \label in a single $$ block |
E03 |
duplicate label name — the first occurrence wins |
E04 |
empty label name, or one containing { } \ $ or whitespace |
E05 |
invalid counter [N] |
E06 |
\ref points to a label that does not exist |
E07 |
\ref points to a label that is itself invalid |
An invalid declaration does not consume a number, so one typo never shifts the numbering of everything after it.
| Setting | Default | Meaning |
|---|---|---|
| Reference template | ({n}) |
How \ref expands; {n} is the number |
| Show error codes in formulas | on | When off, an error renders as ? |
| Refresh when numbering changes | on | Re-render visible formulas after an insertion shifts the numbers |
| Refresh debounce | 400 ms |
Delay after typing stops |
| Debug log | off | Print every rewrite (before / after) to the console |
Two commands are available in the command palette: rescan the current file, and print the label table to the console.
Obsidian renders math with MathJax. The plugin calls loadMathJax(), then wraps MathJax.tex2chtml — the function every formula passes through on its way from TeX to CHTML:
label → number table is built. Code blocks, inline code, frontmatter and HTML comments are skipped. Because the table depends only on source order, scrolling, incremental re-rendering and full re-renders can never produce an inconsistent numbering.\label{...}[N] is stripped and \tag{number} is appended at a position MathJax accepts — before \end{align} for aligned environments, at the top level for everything else, so cases and aligned inside \left\{ … \right. keep working.The note file is read-only for this plugin. There is no \tag written into your Markdown, and no separate numbering syntax to learn.
\ref is not supported.$$ block may hold at most one \label. Aligned environments share one number.\label inside \text{...} is still recognised, since the scanner works on the TeX string.npm install
npm test # unit tests for the counter, scanner and rewriter (node --test)
npm run typecheck
npm run build # writes main.js next to manifest.json
The pure logic (counter.ts, scanner.ts, rewriter.ts) has no dependency on Obsidian and is tested directly. To develop against a vault, point the build at the plugin folder:
VAULT_PLUGIN_DIR="<vault>/.obsidian/plugins/equation-ordinal" npm run build
MIT
给 Obsidian 的行间公式做自动编号,并支持 LaTeX 风格的 \label / \ref 交叉引用。
在 $$...$$ 里写普通的 LaTeX 就行。编号和标签是在渲染时算出来并画上去的,不会写回笔记文件——所以文件里保存的仍然是可以直接粘进论文的那份源码。
MathJax 能渲染 \tag{...},但它没有"整篇笔记的公式计数器",\label / \ref 也不像在 LaTeX 里那样工作。常见的替代做法是手写 \tag{1}、\tag{2},然后每次在中间插入一个公式,就得把后面全改一遍。
Equation Ordinal 把这件事放到渲染层:
\label 在文件中的出现顺序决定;\ref 解析成同一个编号,并自动带上括号;\tag,导出时你仍然完全掌握编号。手动
manifest.json、main.js、styles.css;<vault>/.obsidian/plugins/equation-ordinal/;BRAT
把 Junzi-ana/equation-ordinal 添加为 beta 插件。
从源码构建
npm install
npm run build
$$
\mathrm{d}Y_t = Z_t\,\mathrm{d}W_t - F(t, Y_t, Z_t)\,\mathrm{d}t,\qquad Y_T = \xi
\label{eq:bsde}
$$
\label 可以写在行间公式的任意位置——末尾、中间、单独一行都行。插件会把它删掉,再把 \tag 插到 MathJax 能接受的位置。
结合 $\ref{eq:bsde}$ 与上面的估计可得……
行内公式和行间公式都支持,\eqref{...} 是同义词。
输出本身已带括号,写 $\ref{eq:bsde}$ 即可,不要再套一层 $(\ref{eq:bsde})$。
计数器从 1 开始,每遇到一个带 \label 的行间公式就加一。
\label{name}[N] 不递增,而是把计数器直接设为 N。N 由数字和小数点组成,之后只递增最后一个小数点后的那一段。
| 源码顺序 | 写法 | 渲染结果 |
|---|---|---|
| 1 | \label{a} |
(1) |
| 2 | \label{b} |
(2) |
| 3 | \label{c}[5.1.10] |
(5.1.10) |
| 4 | \label{d} |
(5.1.11) |
| 5 | \label{e}[A.1] |
(A.1) |
| 6 | \label{f} |
(A.2) |
| 7 | \label{g}[7] |
(7) |
| 8 | \label{h} |
(8) |
N 的约束:
3、4.2、5.1.10 都可以;A.1、A.B.3 都可以;1.2.、.1、1..2、3a。计数器属于笔记本身,与文件名无关。笔记从 \label{x}[5.1] 开始,就会依次得到 (5.1)、(5.2)……
问题会在公式里就地标出,同时写进控制台(带文件名和行号),不会被静默吞掉。
| 码 | 含义 |
|---|---|
E01 |
\label 写在了行内公式 $...$ 里 |
E02 |
同一个 $$ 块里出现了多个 \label |
E03 |
label 名重复,首个生效 |
E04 |
label 名为空,或含 { } \ $、空白 |
E05 |
计数器 [N] 不合法 |
E06 |
\ref 指向不存在的 label |
E07 |
\ref 指向的 label 本身有错 |
无效的声明不占用编号,所以一个笔误不会让后面所有公式跟着跳号。
| 设置项 | 默认 | 说明 |
|---|---|---|
| 引用模板 | ({n}) |
\ref 展开成什么,{n} 是编号 |
| 在公式内显示错误码 | 开 | 关闭后错误处只显示 ? |
| 编号变化时自动刷新 | 开 | 插入公式导致后续编号变化时,重渲已显示的公式 |
| 刷新防抖 | 400 ms |
停止输入后等多久 |
| 调试日志 | 关 | 在控制台打印每次改写的前后对比 |
命令面板里有两个命令:重新扫描当前文件、在控制台打印编号表。
Obsidian 用 MathJax 渲染数学。插件先 loadMathJax(),然后包住 MathJax.tex2chtml——每个公式从 TeX 变成 CHTML 都要经过这个函数:
label → 编号 的表。代码块、行内代码、frontmatter、HTML 注释都会被跳过。因为这张表只依赖源码顺序,滚动、增量渲染、整篇重渲都不可能产生前后不一致的编号。\label{...}[N],把 \tag{编号} 插到 MathJax 接受的位置——对齐环境插在 \end{align} 之前,其余情况插在顶层末尾,所以 \left\{ … \right. 里的 cases、aligned 都能正常工作。整个过程里笔记文件是只读的:Markdown 里不会多出 \tag,也没有额外的编号语法要学。
\ref。$$ 块最多一个 \label;对齐环境整体共用一个编号。\text{...} 里的 \label 同样会被识别,因为扫描器工作在 TeX 字符串层面。npm install
npm test # counter / scanner / rewriter 的单元测试(node --test)
npm run typecheck
npm run build # 在 manifest.json 旁边生成 main.js
纯逻辑部分(counter.ts、scanner.ts、rewriter.ts)不依赖 Obsidian,可以直接测试。要在 vault 里边改边看,把构建指向插件目录:
VAULT_PLUGIN_DIR="<vault>/.obsidian/plugins/equation-ordinal" npm run build
MIT