ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Biome Markdown 格式化器有序列表编号重排机制深度解析

Biome Markdown 格式化器有序列表编号重排机制深度解析 开发工具Lint格式化静态分析代码质量前端【免费下载链接】biomeA toolchain for web projects, aimed to provide functionalities to maintain them. Biome offers formatter and linter, usable via CLI and LSP.项目地址https://gitcode.com/gh_mirrors/bi/biome点击查看免费下载有序列表编号是 Markdown 格式化中最容易被忽视、却最容易产生破坏性改动的细节之一源文件里写的是5. 6. 7.还是1. 1. 1.渲染结果相同但格式化器必须决定保留哪个起始数字、后续项如何编号。本文以 Biome 仓库中的测试夹具 start.md 及其预期输出为研究对象结合 bullet_list.rs 的实现源码完整讲解 Biome Markdown 格式化器对有序列表编号的三条核心规则保留起始编号、顺序递增、Git diff-friendly 编号并给出可复现的验证方法。读完本文你将理解 Biome 在什么情况下会把999. 145. 69.重排成999. 1000. 1001.又为什么对1. 1. 1.这类列表保持原样不动。一、测试夹具一次覆盖 19 种编号形态的输入start.md是一份纯编号测试文件全文没有标题、没有段落只用---分隔线把 19 组有序列表隔开每组 1 到 3 个列表项。它刻意覆盖了编号的极端取值0、1、2、5、999以及同一列表内混合编号如0, 1, 2、999, 145, 69、999, 1。该文件的预期输出记录在同目录的start.md.prettier-snap中。.prettier-snap后缀意味着这份期望来自上游 Prettier 的格式化结果Biome 用它作为对照基准详见下文第四节。输入与输出的逐组对比如下组输入源文件输出prettier-snap行为归类15. 6. 7.5. 6. 7.保留起始编号 5顺序递增20. 0. 0.0. 1. 2.保留起始编号 0顺序递增31. 1. 1.1. 1. 1.Git diff-friendly保持原样42. 2. 2.2. 3. 4.保留起始编号 2顺序递增50. 1. 2.0. 1. 2.本就是顺序编号保持不变60. 1. 1.0. 1. 1.Git diff-friendly保持原样71. 2. 3.1. 2. 3.本就是顺序编号保持不变82. 3. 4.2. 3. 4.本就是顺序编号保持不变9999. 145. 69.999. 1000. 1001.保留起始编号 999顺序递增100.0.单元素列表原样保留111.1.单元素列表原样保留122.2.单元素列表原样保留13999.999.单元素列表原样保留140. 1.0. 1.顺序编号保持不变151. 2.1. 2.顺序编号保持不变161. 1.1. 1.Git diff-friendly保持原样172. 3.2. 3.顺序编号保持不变18999. 1.999. 1.Git diff-friendly保持原样19999. 2.999. 1000.非 Git diff-friendly顺序递增从这张对照表可以直观看出 Biome 的策略第一项的编号永远保留后续项的编号要么全部变成 1Git diff-friendly要么从起始编号连续递增。判定走哪条路取决于源文件作者是否显式表达了保持编号恒定的意图。二、Git diff-friendly 编号规则与判定算法2.1 什么是 Git diff-friendly 编号Git diff-friendlyGit 差异友好编号是指这种写法1. 第一个条目 1. 第二个条目 1. 第三个条目Markdown 渲染时仍然显示为1、2、3但源文件里每个标记都是1。好处体现在版本控制上在列表中间插入一个新条目时只有新增的那一行会出现在 diff 中而顺序编号1. 2. 3.的列表在中间插入后后续所有行都要被重写diff 噪声很大。这正是 Prettier 与 Biome 在 Markdown 格式化中共同采纳的实践。2.2 判定函数与逐 case 分析核心判定逻辑位于 bullet_list.rs 的has_git_diff_friendly_ordered_list函数fn has_git_diff_friendly_ordered_list(numbers: [usize]) - bool { if numbers.len() 2 || numbers[1] ! 1 { return false; } if numbers[0] ! 0 { return true; } numbers.get(2).is_some_and(|number| *number 1) }该函数只读取列表前三个marker 数字from_list中使用.take(3)截取逐条对照start.md的 19 组用例少于两个数字或第二项不是 1直接判为顺序编号。对应第 10–15、17、19 组。特别注意第 19 组999, 2第二项是 2 而非 1作者意图显然是递增因此被重排为999, 1000。第二项是 1且第一项不是 0判为 Git diff-friendly。对应第 31,1,1、161,1、18999,1组输出保持1, 1与999, 1不变。第一项是 0 时需要再看第三项第三项也是 1即0,1,1才判为 Git diff-friendly第 6 组保持0. 1. 1.第三项不存在或不是 1如0,1,2、0,1则判为顺序编号第 2、5、14 组输出0, 1, 2与0, 1。源码注释对这一点解释得很清楚0, 1是顺序的因为 1 本来就自然跟在 0 后面而0, 1, 1中第三个 1 暴露了作者想让编号恒定的意图。值得注意的是判定依据的是源文件的 marker 数字而非格式化后的数字。这意味着该函数本质上是在猜测作者风格全部写1的列表保持1写0或999开头的递增列表则被规范化为连续的等差数列。2.3 编号输出起始值保留 饱和递增在 OrderedMarkerPlan::marker_for_index 中每个列表项最终输出的数字按如下规则计算let number if index 0 { self.start } else if self.use_git_diff_friendly_numbering { 1 } else { self.start.saturating_add(index) };第 0 项列表第一项永远输出start——即源文件中第一项的原始编号。这是必须保留的因为 CommonMark 规范用第一项的编号作为列表的start属性999.开头的列表渲染出来依然从 999 开始Git diff-friendly 列表的后续项全部输出1顺序列表的后续项输出start index且使用saturating_add防止极端大编号溢出。start的取值来自OrderedMarkerPlan::from_list它取列表前三个有序 marker 数字中的第一个numbers.first().copied()?因此第 1、4、9 组的5、2、999得以保留第 2 组的0也原样保留。三、编号之外分隔符与相邻列表的防合并策略start.md中所有列表都使用.分隔符但实现层面对分隔符也有一套完整策略与编号判定相互独立ordered_delimiter_for_list 根据相邻同类型列表的兄弟序号交替选择分隔符偶数位置的解析列表用.奇数位置用)。原因是如果两个相邻的有序列表都输出1.Markdown 重新解析时可能把它们合并成一个宽松列表交替使用1.与1)能在格式化文本中保住列表边界。兄弟序号由 list_sibling_index 计算它向上扫描前驱兄弟节点跳过换行与缩进延续节点只统计同为有序列表的相邻解析列表个数。FmtAnyList::new与BulletListPrinter::new把该序号传入保证每个解析列表整体采用同一套 marker 计划——同一个解析列表内的条目绝不会出现一半.一半)的情况。这套防合并策略同样服务于一个目标格式化后的文本再次被 CommonMark 解析时列表结构与源文件一致这也是start.md用---分隔 19 组列表的隐含测试点——每组的独立列表边界在格式化后都必须依然存在。四、快照测试机制.prettier-snap 与 .snap 的分工理解了规则还需要知道start.md是如何被验证的。Biome 的 Markdown 格式化测试通过宏自动发现测试文件spec_tests.rs 用tests_macros::gen_tests!扫描tests/specs/markdown/**/*.md为每个.md文件生成一个测试用例并统一调用 spec_test.rs 中的runrun会构造一个启用了 Markdown 格式化的ConfigurationMarkdownFormatterConfiguration { enabled: Some(true.into()) }然后交给SpecSnapshot::test()执行格式化并比对期望。期望文件的分工逻辑在 utils.rs 的get_prettier_diff中格式化结果会与同目录下的.prettier-snap文件逐字符比较比较前会剥离 Prettier 占位符。如果两者完全一致说明 Biome 的输出与 Prettier 基准一致此时不会生成冗余的.snap快照只有存在差异时才生成.snap快照与 unified diff 报告。这解释了list/目录中文件的分布规律start.md、ordered.md、align.md、checkbox.md等一批用例只有.prettier-snap而没有.snap说明 Biome 在这些场景下与 Prettier 输出完全对齐而indent.md、nested.md、tab.md等用例同时存在.prettier-snap与.snap说明这些场景存在有意的行为差异Biome 用自己的快照固化输出。就有序列表编号而言start.md与 ordered.md1. 1. 1.保持原样均与 Prettier 基准完全一致。五、手动验证如何在本地复现格式化结果如果你想在本地验证本文的对照表有两种途径运行完整快照测试在仓库根目录执行cargo test -p biome_markdown_formatter其中会包含由宏生成的markdown_module测试套件自动覆盖list/start.md用例。若输出与.prettier-snap不一致测试会失败并给出 Prettier 与 Biome 两侧的 unified diff。使用 Biome CLI 直接格式化仓库发布的可执行文件支持 Markdown 格式化。先执行biome format或带--write写入作用于包含上述列表的文件再观察输出是否与start.md.prettier-snap一致。注意所有格式化选项均可通过项目根目录的biome.json或biome.jsonc中的formatter/markdown.formatter配置控制例如lineWidth会影响列表项内文本的折行但不会影响编号重排逻辑本身。六、总结start.md虽只是一份 98 行的测试输入但它浓缩了 Biome Markdown 格式化器有序列表编号的全部设计决策起始编号保留第一项数字决定列表start格式化后不变5.仍是5.999.仍是999.顺序递增作者按递增书写的列表被规范化为从起始值连续递增999, 145, 69→999, 1000, 1001Git diff-friendly 保持作者全部写1或999, 1、0, 1, 1的列表保持编号恒定最大限度降低版本控制 diff 噪声一致性保证同一解析列表整体采用同一 marker 计划相邻列表通过交替分隔符防止格式化后被合并。这些规则共同保证了 Biome 输出的 Markdown 既美观、又可读、还能被 CommonMark 重新解析出与源文件一致的结构——这也是它在列表格式化上与 Prettier 基准保持对齐见 list/start.md.prettier-snap的底气所在。后续阅读可继续深入 bullet_list.rs 中无序列表 marker 交替策略unordered_marker_for_list与缩进代码块对齐逻辑理解同一份代码如何支撑起整个列表家族的一致性输出。赞分享开发工具Lint格式化静态分析代码质量前端【免费下载链接】biomeA toolchain for web projects, aimed to provide functionalities to maintain them. Biome offers formatter and linter, usable via CLI and LSP.项目地址https://gitcode.com/gh_mirrors/bi/biome点击查看免费下载相关推荐Biome Markdown 格式化器深度解析有序列表标记的 9 位数字上限与重编号行为issue-17778Biome Markdown 格式化器深度解析有序列表标记的 9 位数字上限与重编号行为issue 17778 有序列表是 Markdown 中最常用的块开发工具Lint格式化静态分析代码质量前端Biome Markdown 格式化器的有序列表Ordered List格式化规则全解析Biome Markdown 格式化器的有序列表Ordered List格式化规则全解析 本篇技术指南以 Biome 仓库中的 Markdown 格式化规格开发工具Lint格式化静态分析代码质量前端Biome Markdown 格式化器的有序列表编号策略从测试规范到源码实现Biome Markdown 格式化器的有序列表编号策略从测试规范到源码实现 本文围绕 Biome 仓库中 Markdown 格式化器的有序列表编号测试规范开发工具Lint格式化静态分析代码质量前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表