列表的格式化規(guī)則)
Biome Markdown 格式化器深度解析嵌套列表與 GFM 任務(wù)列表的格式化規(guī)則【免費(fèi)下載鏈接】biomeA toolchain for web projects, aimed to provide functionalities to maintain them. Biome offers formatter and linter, usable via CLI and LSP.項(xiàng)目地址: https://gitcode.com/gh_mirrors/bi/biome導(dǎo)讀Biome 的 Markdown 格式化器biome_markdown_formatter負(fù)責(zé)將 Markdown 源碼規(guī)范化為統(tǒng)一風(fēng)格其中嵌套列表與GFM 任務(wù)列表Task List / Checkbox是最容易產(chǎn)生風(fēng)格分歧的場(chǎng)景。本文以倉(cāng)庫(kù)測(cè)試套件中的nested-checkbox.md用例為切入點(diǎn)逐行解讀其輸入、輸出快照與 Prettier 行為差異并深入src源碼剖析列表標(biāo)記歸一化、縮進(jìn)重排、空行處理與[X]/[x]狀態(tài)歸一化的底層實(shí)現(xiàn)。讀完本文你將掌握 Biome 對(duì)嵌套無(wú)序列表與任務(wù)列表的完整格式化決策鏈并能通過(guò) spec 測(cè)試機(jī)制自行驗(yàn)證任意 Markdown 列表寫(xiě)法。測(cè)試用例概覽一個(gè)用例覆蓋兩類(lèi)嵌套場(chǎng)景關(guān)聯(lián)文檔位于crates/biome_markdown_formatter/tests/specs/prettier/markdown/list/nested-checkbox.md共 11 行構(gòu)造了兩個(gè)結(jié)構(gòu)完全對(duì)稱(chēng)的嵌套列表塊* parent list item parent list item parent list item parent list item parent list item parent list item * child list item child list item child list item child list item child list item child list item paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph * [x] parent task list item parent task list item parent task list item parent task list item * [x] child task list item child task list item child task list item child task list item paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph該用例刻意設(shè)計(jì)了三個(gè)壓力點(diǎn)用于驗(yàn)證格式化器的魯棒性父項(xiàng)后緊跟空行 縮進(jìn)子項(xiàng)測(cè)試松散列表loose list與嵌套子列表同時(shí)出現(xiàn)時(shí)的空行去留長(zhǎng)文本父項(xiàng)、子項(xiàng)與后續(xù)段落全部使用超長(zhǎng)文本用于檢驗(yàn)行寬80 字符約束下格式化器是否強(qiáng)制換行[x]任務(wù)列表嵌套父項(xiàng)與子項(xiàng)同時(shí)攜帶 GFM 復(fù)選框標(biāo)記驗(yàn)證任務(wù)列表在嵌套結(jié)構(gòu)中的縮進(jìn)與標(biāo)記輸出。輸入刻意使用*作為列表標(biāo)記、5 空格縮進(jìn)子項(xiàng)、4 空格縮進(jìn)段落而輸出快照顯示 Biome 會(huì)將其全部歸一化為-標(biāo)記與 2 空格縮進(jìn)——這正是理解整個(gè)格式化流程的最佳樣本。輸出快照解讀Biome 的四條歸一化規(guī)則同目錄下的nested-checkbox.md.snap記錄了該輸入的格式化結(jié)果# Output部分如下- parent list item parent list item parent list item parent list item parent list item parent list item - child list item child list item child list item child list item child list item child list item paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph - [x] parent task list item parent task list item parent list item parent task list item parent list item - [x] child task list item child list item child list item child list item paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph對(duì)比輸入與輸出可提煉出 Biome 的 4 條核心歸一化規(guī)則規(guī)則 1列表標(biāo)記統(tǒng)一為-輸入使用*作為無(wú)序列表標(biāo)記輸出統(tǒng)一改寫(xiě)為-。這是 Biome Markdown 格式化器默認(rèn)的 bullet 風(fēng)格選擇。同目錄下其他用例如unordered.md、nested.md也遵循同一約定說(shuō)明該規(guī)則是全局性的而非本用例特例。規(guī)則 2子項(xiàng)與后續(xù)段落統(tǒng)一縮進(jìn)為 2 空格子列表項(xiàng)輸入縮進(jìn) 5 空格 → 輸出縮進(jìn) 2 空格相對(duì)父項(xiàng)標(biāo)記緊隨列表塊的段落輸入縮進(jìn) 4 空格 → 輸出縮進(jìn) 2 空格。Biome 對(duì)嵌套列表與列表后續(xù)縮進(jìn)段落采用一致的 2 空格縮進(jìn)基準(zhǔn)消除了手寫(xiě) Markdown 中常見(jiàn)的縮進(jìn)隨意性4 空格、5 空格、tab 混用等。規(guī)則 3父項(xiàng)與子項(xiàng)之間的空行被移除輸入中父項(xiàng)與子項(xiàng)之間、父項(xiàng)與任務(wù)子項(xiàng)之間均有空行輸出中這些空行被刪除子項(xiàng)直接緊貼父項(xiàng)而子項(xiàng)之后與段落之間、兩個(gè)列表塊之間的空行則被保留。這說(shuō)明 Biome 能區(qū)分塊內(nèi)結(jié)構(gòu)空行可移除與塊間分隔空行必須保留。規(guī)則 4GFM 任務(wù)列表標(biāo)記原樣保留[x]標(biāo)記在嵌套結(jié)構(gòu)中完整保留父項(xiàng)與子項(xiàng)均如此說(shuō)明任務(wù)列表狀態(tài)在縮進(jìn)重排過(guò)程中不會(huì)被破壞且輸出為小寫(xiě)x形態(tài)見(jiàn)下文源碼部分關(guān)于normalize_task_state的說(shuō)明。與 Prettier 的行為差異一處刻意保留的分歧快照中的# Prettier differences部分以 diff 形式記錄了 Biome 與 Prettier 對(duì)同一輸入的分歧--- Prettier Biome -1,11 1,9 - parent list item parent list item parent list item parent list item parent list item parent list item - - child list item child list item child list item child list item child list item child list item paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph - [x] parent task list item parent task list item parent task list item parent task list item - - [x] child task list item child task list item child task list item child task list item paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph差異點(diǎn)非常集中Prettier 會(huì)在父列表項(xiàng)與其第一個(gè)嵌套子項(xiàng)之間保留一個(gè)空行而 Biome 選擇移除該空行使父子列表項(xiàng)緊湊相連。這是該用例被歸入prettier目錄表示與 Prettier 對(duì)照但不要求完全一致的原因——Biome 在列表緊湊性上采用了與 Prettier 不同的取舍且通過(guò) spec 快照將這一分歧顯式固化防止未來(lái)改動(dòng)無(wú)意中抹平或擴(kuò)大差異。源碼級(jí)剖析歸一化規(guī)則在何處實(shí)現(xiàn)任務(wù)列表標(biāo)記normalize_task_state與小寫(xiě)化GFM 任務(wù)列表的格式化實(shí)現(xiàn)在crates/biome_markdown_formatter/src/gfm/auxiliary/task_list_item.rs的FormatGfmTaskListItem中write!( f, [ fields.l_bracket_token.format(), state.format().with_options(FormatMdTextualOptions { normalize_task_state: true, ..FormatMdTextualOptions::default() }), fields.r_bracket_token.format(), ] )它通過(guò)FormatRuleWithOptions機(jī)制向FormatMdTextual傳入normalize_task_state: true選項(xiàng)。真正的狀態(tài)歸一化邏輯位于crates/biome_markdown_formatter/src/markdown/auxiliary/textual.rs的fmt_fields中if self.normalize_task_state value_token.text() X { write!( f, [format_replaced( value_token, text(x, Some(value_token.text_range().start())) )] ) }即當(dāng)復(fù)選框狀態(tài)為大寫(xiě)X時(shí)會(huì)通過(guò)format_replaced生成一個(gè)替換 token將X規(guī)范化為小寫(xiě)x同時(shí)保留原始文本范圍用于診斷定位。[ ]未選中狀態(tài)則不受影響直接原樣輸出。這正是本用例輸出中[x]穩(wěn)定存在、且用戶手寫(xiě)[X]也能被統(tǒng)一風(fēng)格的實(shí)現(xiàn)依據(jù)。列表分發(fā)機(jī)制FmtAnyList與 debug_assert 護(hù)欄bullet_list.rs中的FormatMdBulletList與bullet_list_item.rs中的FormatMdBulletListItem均以debug_assert!(false, This node should be formatted via FmtAnyList...)開(kāi)頭——它們不是實(shí)際的格式化入口而是用于攔截直接格式化列表節(jié)點(diǎn)的錯(cuò)誤路徑。真正的分發(fā)發(fā)生在FmtAnyList匹配AnyMdBlock并調(diào)用as_any_list_item之后由生成的container_block.rs、block.rs等文件按節(jié)點(diǎn)類(lèi)型逐層下派。這種入口斷言 統(tǒng)一分發(fā)的結(jié)構(gòu)保證嵌套列表的縮進(jìn)與項(xiàng)間空行決策集中在同一路徑處理避免了多種列表寫(xiě)法各走各的邏輯??s進(jìn)與空行容器塊的連續(xù)化輸出從快照輸出可以看到Biome 將父項(xiàng) → 子項(xiàng) → 段落在滿足規(guī)則的前提下盡量連續(xù)輸出。結(jié)合FormatAnyMdContainerBlock對(duì)MdBulletListItem、MdOrderedListItem、MdQuote的分派可以推斷嵌套列表項(xiàng)作為容器塊container block被遞歸格式化子塊的縮進(jìn)通過(guò)continuation_indent等輔助節(jié)點(diǎn)按 2 空格基準(zhǔn)計(jì)算而空行處理則依據(jù)塊級(jí)節(jié)點(diǎn)的松散loose屬性決定去留。nested-checkbox.md恰好同時(shí)覆蓋了松散列表 嵌套的組合是驗(yàn)證這條決策鏈?zhǔn)欠褡郧⒌年P(guān)鍵回歸用例。行寬約束80 字符上限下的不重排策略快照末尾的# Lines exceeding max width of 80 characters部分列出了輸出中超過(guò) 80 字符的行1: - parent list item parent list item parent list item parent list item parent list item parent list item 2: - child list item child list item child list item child list item child list item child list item 4: paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph paragraph ...這揭示了一個(gè)重要事實(shí)Biome 的 Markdown 格式化器目前采用檢測(cè)并報(bào)告超寬行、但不強(qiáng)制重排文本的策略。這些構(gòu)造的超長(zhǎng)行在輸出中原樣保留僅被快照機(jī)制標(biāo)記為超出line_width默認(rèn) 80。這與 Prettier 的盡量折行理念不同——Biome 在 Markdown 階段優(yōu)先保證結(jié)構(gòu)歸一化標(biāo)記、縮進(jìn)、空行、任務(wù)狀態(tài)而把段落級(jí)文本換行視為更高風(fēng)險(xiǎn)、更低收益的操作選擇保守處理。同一list目錄下的long-paragraph.md用例也印證了這一行為的一致性。如何在本地復(fù)現(xiàn)與驗(yàn)證本用例由biome_markdown_formatter的 spec 測(cè)試框架驅(qū)動(dòng)入口位于crates/biome_markdown_formatter/tests/spec_tests.rs快照由crates/biome_formatter_test/src/snapshot_builder.rs生成見(jiàn).snap文件頭部的source字段。驗(yàn)證方式直接運(yùn)行 CLI將任意包含嵌套列表與任務(wù)列表的.md文件交給biome format觀察*是否歸一化為-、子項(xiàng)是否縮進(jìn) 2 空格、[X]是否變?yōu)閇x]運(yùn)行 spec 測(cè)試在倉(cāng)庫(kù)根目錄執(zhí)行針對(duì) markdown formatter 的 cargo 測(cè)試命令測(cè)試框架會(huì)自動(dòng)比對(duì)nested-checkbox.md輸入與.snap快照任何格式化行為變化都會(huì)以快照 diff 形式暴露對(duì)照 Prettier同時(shí)查看nested-checkbox.md.prettier-snap即可快速定位 Biome 與 Prettier 在空行處理上的唯一分歧點(diǎn)。修改或新增類(lèi)似用例時(shí)只需在tests/specs/prettier/markdown/list/目錄下添加輸入文件并運(yùn)行測(cè)試即可自動(dòng)生成對(duì)應(yīng)的.snap與.prettier-snap實(shí)現(xiàn)以測(cè)試固化格式化決策的回歸保障??偨Y(jié)nested-checkbox.md雖只有 11 行卻是理解 Biome Markdown 格式化器嵌套結(jié)構(gòu)處理的一把鑰匙它同時(shí)驗(yàn)證了標(biāo)記歸一化*→-、縮進(jìn)歸一化→ 2 空格、松散列表空行處理、GFM 任務(wù)列表狀態(tài)保留[x]、超寬行不重排策略以及與 Prettier 在父子項(xiàng)空行上的刻意分歧。配合task_list_item.rs的normalize_task_state選項(xiàng)與textual.rs的大寫(xiě)X替換邏輯開(kāi)發(fā)者可以清楚回答B(yǎng)iome 格式化一段嵌套任務(wù)列表時(shí)每一步做了什么這個(gè)問(wèn)題并借助 spec 快照機(jī)制為自己的 Markdown 項(xiàng)目建立可驗(yàn)證的格式化預(yù)期?!久赓M(fèi)下載鏈接】biomeA toolchain for web projects, aimed to provide functionalities to maintain them. Biome offers formatter and linter, usable via CLI and LSP.項(xiàng)目地址: https://gitcode.com/gh_mirrors/bi/biome創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考