琉璃幻影237 downloads让文件浏览器按「第一章 / 第二章 / 第十章」的中文数字自然排序。不改文件名、不改内容、零配置,直接接管 Obsidian 自身的排序逻辑。
Chinese-aware natural ordering for the file explorer: 第一章, 第二章 … 第十章, (一)(二)(三), 第一单元/第二单元, Lecture 2/9/10, Part I/II/X — all appear in numeric order, not code-point order.
中文名:中文自然排序。让文件浏览器按人类直觉排序,而不是按 Unicode 码点。
The file explorer orders items by Unicode code points, so Chinese numerals like 第一章, 第二章 … 第十章 come out shuffled. This plugin replaces the explorer's own sort routine so numbers — Arabic, Chinese and Roman alike — are compared by value:
Obsidian default (by code point) CN Natural Sort
───────────────────────────────── ─────────────────────────────────
第一章 第一章
第三章 第二章
第二章 第三章
第十章 第十章
Lecture 2 < Lecture 9 < Lecture 10, 拼音 order for pure Chinese).| Pattern | Example | Sorts as |
|---|---|---|
| 第 X 章/节/卷/篇/回/部/集/单元 | 第一章, 第十章, 第一单元 | 1, 10 / 1 |
| Leading numeral | 一、绪论, 1. 概述, 12. 小结 | 1 / 1 / 12 |
| Parenthesized numeral | (一)(二)…, (三), 笔记(十) | 1, 2 … 10 |
| Trailing numeral | 附录一, 笔记2 | by value |
| Arabic numerals | Lecture 2/9/10, v1.2/v1.10, A-2/A-10 | 2 < 9 < 10 etc. |
| Roman numerals* | I. II. III., Part I/II/X, (IV), 笔记II | 1, 2, 3, 4, 10 |
| Chinese numerals, incl. traditional & banker's | 貳拾參, 伍佰, 廿三, 卅五, 皕 | 23, 500, 23, 35, 200 |
| Multi-level numbers | 笔记(二):第一单元, 第二单元 3-2 | 2,1 / 2,3,2 |
| Year / digit-string numerals | 二〇二四年总结, 一九九九, 一〇〇 | 2024, 1999, 100 |
| Colloquial shorthand | 三百二 (=320), 一万二 (=12000), 百二十三 (=123) | 320, 12000, 123 |
| Fullwidth digits | 123 (normalized to halfwidth) | 123 |
| Chinese dates & durations | 2026年十月六日, 九月三十日, 三小时, 十分钟 | 2026/10/6, 9/30, 3, 10 |
| Numeral + measure word | 一项, 两项, 三项, 三页, 十册, 3号, 三周 | 1 < 2 < 3 |
| Letter suffixes | 附录A, 附录B, 附录J, 方案C | A < B < C < J |
| Roman numerals after Chinese | 卷I, 卷II, 卷IX | 1 < 2 < 9 |
| Mixed date formats | 2026-10-06, 2026.10.06, 2026年十月六日 | all on one axis |
* Roman numerals are only treated as numbers when they look like ordinal labels:
at the start of a name followed by a separator, inside parentheses, or after a prefix
word (Chapter, Part, Unit, Lecture, Lesson, Section, Book, Volume …).
This avoids mangling words like DLL, CLI, XML, CIVIL or sentences like
I have a dream.
After Chinese text, Roman vs letter is ambiguous (附录C = letter C, or Roman 100?),
so the whole folder decides — see “How it works”.
Deciding whether a run of characters is a number is the whole problem, and a yes/no
guess is not enough — a wrong guess does not shift a file slightly, it demotes the
number to text and the name falls back to pinyin, which for Chinese numerals is close
to random (一→yi sorts after 三→san). So the pipeline has three stages.
1 · Segment. The name is split into segments. Each numeral is tagged with the evidence found for it instead of getting an immediate verdict:
strong — hard syntax: after an ordinal lead (第), inside brackets ((三)), at
the start followed by a separator (一、), a year form (二〇二四), or part of a
multi-level chain (十月六日).weak — only “numeral + measure word” (十分钟, 一项, 三页). Which measure word
it is makes no difference.三体, 万一).2 · Compare segments. Number vs number by value; text vs text with the same
Intl.Collator Obsidian itself uses; a number beats a text segment. Comparing segment
by segment through the whole name is what makes nesting work.
3 · Adjudicate the folder. The weak segments are resolved against the rest of the folder in one pass, before sorting starts:
卷II) the whole
prefix is read as Roman; if it shows a non-Roman letter (附录A) the whole prefix is
read as letters. Never both — mixing them makes the same pair of names compare
differently in different folders, and the order stops being self-consistent.?分, ?项, ?月?日). A group of two or
more with differing values is a real numbering series and is adopted; a group of
identical values (十分满意, 十分感谢, 十分准确 — all 10) is an adjective and is
demoted back to text. A lone member is left alone.That last rule is why there is no list of “trustworthy measure words”:
一项/两项/三项 read as 1/2/3 even though 项 was never whitelisted, and
十分满意 survives intact without 分 needing an exemption.
Nothing to configure. Once enabled, the file explorer sorts itself. To force a re-sort, run the command "CN Natural Sort: re-sort" (or click the ribbon icon). A "diagnose" command prints the current order of a couple of folders to the console.
The plugin only takes over alphabetical sorting. If you switch the file explorer to Modified time / Created time, this plugin steps aside and Obsidian's own order is left untouched (including their Reverse variants).
Obsidian 社区插件。让**文件浏览器(左侧文件列表)**按「人类直觉的自然顺序」排序:
第二章、第十章、第一单元一、绪论、1. 概述(一)(二)(三)…、笔记(四)、(三)Lecture 2/9/10、v1.2/v1.10(按 2<9<10、1.2<1.10 排)I. II. III.、Part I/II/X、(IV)、X - 结语附录A/B/C、方案A/B/C 按字母走;卷I/II/…/IX 按罗马数值走
(同一前缀自动二选一,见下方已知边界)2026年十月六日 = 2026 / 10 / 6、九月三十日 = 9 / 30,
与 2026-10-06、2026年10月6日 按同一数值轴混排一项 两项 三项、三页 十册、十分钟 三小时、
3号 三周 —— 不靠「哪个单位可信」判定,由整批一致性裁决(见下方算法第 3 层)俩=2、仨=3、皕=200貳拾參=23、伍佰=500、廿三=23笔记(二):第二单元 会排在 笔记(二):第一单元 之后
(外层相同再比内层)v2.0 把「这段到底算不算数字」从 if 分支决策树 换成 切段 → 打分 → 整批裁决 三层。
动机很直接:判断一旦漏掉,退化的不是「排偏一点」,而是整段变成文本、转按拼音排 ——
而中文数字的读音和大小毫无关系(一→yi 排在 三→san 之后),一次漏判就是整列乱序。
第 1 层 · 切段:把名字切成「数值段 / 文本段」交替的序列。数值段不立刻定性, 只记录它拿到了哪些证据:
| 证据 | 触发条件 | 例子 |
|---|---|---|
| strong | 序数引导词 第 |
第一章、第3章 |
| strong | 括号包裹 | (三)、(II) |
| strong | 行首 + 分隔符 | 一、、1. |
| strong | 年份写法(连续 3 位以上数字字 + 时间单位) | 二〇二四年 |
| strong | 多级链(单位字 + 数字串 反复出现) | 十月六日 = ?月?日 |
| strong | 一侧不挨着汉字 | 笔记一、一 基础 |
| weak | 只是「数字 + 量词/时间单位」 | 十分钟、一项、三页 |
| 无 | 以上都没有 | 三体、万一 → 按文本 |
注意 weak 那行:不区分是哪个单位。以前要维护「可信单位白名单」,
分 因为会撞上「十分满意」就被排除,于是「十分钟」跟着受牵连 —— 补一个坑坏一片。
第 2 层 · 逐段比较:数值段按值比,文本段交给与 Obsidian 同款的 Intl.Collator
(中文拼音、忽略大小写),数值段遇文本段在前,前段相等则继续比下一段。
因为是对整个名字逐段比较,内层序号天然参与排序:笔记(二):第二单元 排在
笔记(二):第一单元 之后。数值相等但写法不同(10 与 十)只记为 tie,
延后到所有段比完才用 —— 否则 2026年10月16日 会在第 3 段就因写法分出胜负,
根本走不到第 5 段去比 16 和 6。
第 3 层 · 整批裁决:排序开始前,把这批文件里的 weak 段一次性判完:
附录A 的 A),整个前缀按字母序;
若全是罗马字母且有 ≥2 字符的(卷II),整个前缀按罗马数值。两套逻辑绝不混用。?分、?项、?月?日)。同组 ≥2 个成员且数值不全相同
→ 判定为真编号,采纳;数值全同(十分满意 十分感谢 十分准确 都是 10)→ 判定为
副词用法,降级回文本;只有 1 个成员 → 孤证不足,保持文本。这就是「不需要单位白名单」的原因:一项/两项/三项 的 1、2、3 递增本身就是最强证据,
而「十分满意」那组三个值都是 10,重复本身就是它不是编号的证据。
因为是对整个名字逐段比较,内层序号也能正确参与排序(层级正确性),且 「第三章」与「第 3 章」可以按同一个数值混排。
插件只接管「按文件名」排序:在文件浏览器里切换成「修改时间 / 创建时间」排序时, 插件会完全放行,不再重排(含对应的 Reverse)。这是刻意设计 —— 不覆盖原生功能。
中文数字是否被当「数字」取决于语境,防止把普通词拆坏:
十分钟.md 独自存在时无从判断,
保守按文本处理(排在数字区之后);同目录出现 二十分钟 后,两者一起被认定为编号。
这是有意的取舍:宁可暂时少认,也不要把 十分满意 拆成 10。十分钟(时长)和 十分满意(副词)模式都是 ?分,
组里出现了不同值,于是整组被当作编号,十分满意 会被排到 10 附近而不是纯文本区。
只影响排序位置,不丢数据;把副词型文件名改掉即可(README 建议避免同一前缀混写)。十月六日 不等裁决就拆开,所以 十月怀胎 这类含「十月」的
成语也会被拆成 10 + 月怀胎。三分之一、百分之三十、三分之一之二 —— 分子分母都不会被当成序号。
判据是 分之 这个分数独有的连接词:既能挡住分数,又不会牵连 十分满意 / 十分钟。甲乙丙丁戊 的拼音序是 丙丁甲戊乙,当编号用会乱。
属于语义序,插件不处理;甲方 / 乙方 这类固定配对恰好拼音也一致,不受影响。Chapter|Part|Unit| Lecture… 前缀词后),避免把 DLL/CLI/XML/MIX 这类恰好由罗马字母组成的
技术缩写、或 CIVIL、I have a dream 这类词误判成数字。卷、附录、表…)下 —— 只要出现一个非罗马字母(附录A 的 A),
整个前缀就按字母序;全是罗马字母、且至少有一个多字符(卷II、卷IX)时,才按
罗马数值排。两套逻辑绝不混用:混用会让同一对名字在不同上下文里得出相反结果,
排序就不自洽了(例如 附录V/附录L/附录N 同在时会互相打转)。
因此 附录A/B/C 与 卷I/II/…/IX 能各自排对,也能在同一目录共存;
但不鼓励在同一前缀下混写 附录A 与 附录II —— 此时该前缀整体退化为字母序。已知会误判的少数成语(无法在不加词典的前提下消除,影响很小 —— 只是该文件会 被排进数字区,不会丢数据):
七七八八 杂项),或加前缀词。明确不支持(属于领域语义,交给用户而非猜):
兆/京/垓/秭 —— 古今含义不同(兆 既可能是 10⁶ 也可能是 10¹²),不猜。Two、Three)—— 不当数值处理。同一序号的不同写法会「聚拢」但不会合并成一档:第3章 与 第三章 相邻,
Ch3 / PART 3 也会各自成簇,但中文档与拉丁前缀分属两簇(前缀文本不同,
按拼音/字母序先分簇,簇内再按数值)。
无需配置。启用后文件浏览器自动排序;如需强制重排,运行命令「CN Natural Sort: re-sort」或点左侧栏图标;「CN Natural Sort: diagnose」可在控制台输出当前排序。
node test/run-tests.js # 74 项单元测试
node test/corpus.js # 50 个真实场景语料库(社区命名协议 / 出版 / 日期 / 反误伤)
node test/matrix.js # 29 种编号形态 + 9 项反误伤
node test/fuzz.js # 严格弱序 fuzz:同一批任意排列结果必须一致
node test/bench.js # 性能基准,阈值 = 重构前(1.3.2)实测中位数
重构前后同机交替实测(Node 22,混合语料):
| 指标 | 1.3.2 | 2.0 |
|---|---|---|
| 冷 token 化 500 个不重复名 | 1.29 ms | 1.02 ms |
| 整批排序 200 个新文件 | 1.63 ms | 0.76 ms |
| 热缓存重排 200×200 | 46.6 ms | 17.1 ms |
热缓存快了 2.7 倍,因为整批裁决按「裁决签名」分桶缓存,不再像 1.3.x 那样
每次上下文一变就 keyCache.clear()。
FileExplorerView.getSortedFolderItems,不改任何 DOM,禁用后立即还原。