ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

markdownlint 与 Prettier `--tab-width=4` 的列表缩进配置实战

markdownlint 与 Prettier `--tab-width=4` 的列表缩进配置实战
  • 开发工具
  • 代码质量
  • Lint
  • 静态分析

【免费下载链接】markdownlint

A Node.js style checker and lint tool for Markdown/CommonMark files.

项目地址:https://gitcode.com/gh_mirrors/ma/markdownlint
点击查看免费下载

本指南围绕仓库 doc/Prettier.md 中记录的 Prettier 兼容性场景,以测试夹具 test/prettier-tab-width-4.md 为实例,讲解当 Prettier 以--tab-width=4格式化 Markdown 时,如何通过list-marker-space(MD030)与ul-indent(MD007)两个规则的配置,让 markdownlint 与 Prettier 的输出完全兼容、零告警。阅读完你将掌握:两种 tab-width 下列表格式的差异、对应规则的参数含义与默认值、内联配置文件markdownlint-configure-file的用法,以及如何用仓库自带测试与快照验证配置的正确性。

背景:markdownlint 与 Prettier 的协作方式

Prettier 是广受欢迎的代码格式化工具,而 markdownlint 是面向 Markdown/CommonMark 文件的 lint 工具。两者在绝大多数场景下可以无缝协作:markdownlint 负责"检查"风格问题,Prettier 负责"重排"格式,各司其职。

仓库中的 doc/Prettier.md 给出了两种协作策略:

  1. 直接扩展官方预置样式:在 markdownlint 配置中extend仓库自带的 style/prettier.json,该样式会将所有与 Prettier 存在重叠的规则一次性禁用,包括line-length、list-indent、list-marker-space、ul-indent、no-trailing-spaces等 22 条规则。适合"格式化交给 Prettier、lint 只管 Prettier 不管的规则"的团队。
  2. 针对特定场景微调:如果仍需保留列表相关规则做 lint,则按本文介绍的参数组合进行配置。

问题场景:--tab-width=4与默认缩进不一致

Prettier 的 Markdown 列表默认按--tab-width=2排版,这与 markdownlint 的默认配置天然兼容,不会产生任何 lint 告警(对应测试夹具 test/prettier-tab-width-2-default.md,其格式为- Item、两级嵌套缩进 2 空格)。

但当 Prettier 以--tab-width=4运行时,无序列表的排版变为:

- Item - Item - Item

此时默认配置的 markdownlint 会立即报告两条规则违规:

  • MD030 / list-marker-space:默认要求列表标记(-、*、+、1.)后只有 1 个空格,而 Prettier 在-后写了 3 个空格;
  • MD007 / ul-indent:默认要求嵌套无序列表每层缩进 2 个空格,而 Prettier 每层缩进 4 个空格。

官方推荐的配置方案

doc/Prettier.md给出的解决方案是以下 JSON 配置片段:

{ "list-marker-space": { "ul_multi": 3, "ul_single": 3 }, "ul-indent": { "indent": 4 } }

该配置以options.config传入lintAPI,或写入任意 markdownlint 配置文件(.markdownlint.json/.markdownlintrc等)。它只调整了无序列表的规则,有序列表无需改动——原因见下文"对齐原理"。

参数逐项解析:两个规则、四个开关

MD030list-marker-space:标记后的空格数

规则文档见 doc/md030.md,实现见 lib/md030.mjs。该规则检查列表标记与列表项文本之间的空格数量,共 4 个参数,默认值均为1:

参数含义默认值
ul_single单行无序列表项标记后空格数1
ul_multi多行无序列表项标记后空格数1
ol_single单行有序列表项标记后空格数1
ol_multi多行有序列表项标记后空格数1

源码中"单行 / 多行"的判定逻辑为:列表总行数等于列表项数量时视为单行(allSingleLine),否则视为多行(包含子列表、代码块、多段落的情况)。因此在--tab-width=4的文档里:

  • 顶部无嵌套的简单列表- Item属于单行列表,需要ul_single: 3;
  • 含嵌套子列表的列表跨越多个行,属于多行列表,需要ul_multi: 3。

两个值都必须设置为3,缺一不可。

MD007ul-indent:无序列表缩进

规则文档见 doc/md007.md,实现见 lib/md007.mjs。该规则检查无序列表项的缩进,参数如下:

参数含义默认值
indent每层嵌套的缩进空格数2
start_indented首层列表是否也缩进(布尔值)false
start_indent首层列表的缩进空格数(仅start_indented开启时生效)2

--tab-width=4场景只需将indent设为4。源码中预期缩进按expectedIndent = baseIndent + (startIndented ? startIndent : 0) + (nesting * indent)计算,即嵌套深度乘以indent参数;同时该规则会输出fixInfo,因此违规项可以被applyFixes自动修复。另外注意:MD007 只在其父列表也全为无序列表时生效,混入有序列表的层级不受影响。

对齐原理:为什么无序用 3 空格、有序不用改

以--tab-width=4排版时,Prettier 让嵌套列表内容按 4 列对齐:

  • 无序标记-占 1 列,标记后补 3 个空格,内容起始于第 4 列;
  • 嵌套列表每层缩进 4 个空格,子列表的标记与内容正好与父级内容列对齐:
- Item <- 标记 1 列 + 3 空格 = 4 列 - Item <- 缩进 4 列,子标记对齐父内容
  • 有序标记如1.占 2 列,标记后仅需 1 个空格即可让内容落在第 4 列,因此ol_single/ol_multi保持默认值1即可。

这正是配置中只调整ul_*与ul-indent的原因。

实测夹具:内联配置文件markdownlint-configure-file

仓库以测试夹具形式固化了这个场景。文件 test/prettier-tab-width-4.md 完整复现了 Prettier--tab-width=4的格式化输出,并在文件末尾使用 markdownlint 的内联文件级配置语法(详见 README.md 的 Configuration 一节):

<!-- markdownlint-configure-file { "list-marker-space": { "ul_multi": 3, "ul_single": 3 }, "ul-indent": { "indent": 4 } } -->

该注释的语义:配置作用于整个文件,与注释所在位置无关;默认按 JSON 解析,可通过options.configParsers扩展为 YAML/TOML 等格式。在源码 lib/markdownlint.mjs 的configureFile函数中,解析结果会与既有配置做浅合并({ ...config, ...parsed }),因此内联配置可与全局配置叠加使用。

夹具正文覆盖了五种典型结构:

  1. 无嵌套的简单无序列表;
  2. 含两层嵌套的多项无序列表;
  3. 无嵌套的简单有序列表;
  4. 含两层嵌套的多项有序列表;
  5. 无序、有序两种结构的混合。

测试验证:快照确认真零告警

每个.md测试文件都会被 test/markdownlint-test-scenarios.mjs 中的createTestForFile读取并执行 lint、applyFixes,再与快照文件 test/markdownlint-test-scenarios.mjs.snapshot 比对。其中prettier-tab-width-4.md对应的快照结果为:

{ "errors": [], "fixed": "# Prettier `--tab-width=4`\n\nText\n\n- Item\n - Item\n..." }
  • "errors": []:在文件内联配置生效后,五种列表结构全部通过校验,零告警;
  • "fixed"与原文完全一致:无需任何自动修复,证明配置已与 Prettier 输出完全对齐。

对照 test/prettier-tab-width-2-default.md(--tab-width=2默认场景)的快照同样是errors: [],两者共同验证了 markdownlint 默认配置与--tab-width=2兼容、经本文配置后与--tab-width=4兼容的结论。

实操清单:三步完成兼容配置

  1. 确定 Prettier 的 tab-width:--tab-width=2为默认值,无需任何 markdownlint 调整;--tab-width=4时按下文配置。
  2. 写入配置:将上文 JSON 片段放入 markdownlint 配置文件;或如测试夹具所示,在文件顶部/底部用markdownlint-configure-file注释做单文件内联配置。
  3. 验证:运行 markdownlint 确认零告警;若使用 CLI 的--fix或 API 的applyFixes(用法见 README.md 的 Fixing 一节),自动修复也不会改动 Prettier 已格式化的内容。

延伸:与prettier.json预置样式的取舍

如果团队希望彻底避免规则冲突,可以直接在配置中extendstyle/prettier.json。该文件以注释形式说明了用途:"Disables rules that may conflict with Prettier",将blanks-around-lists、code-fence-style、list-marker-space、ul-indent、line-length等 22 条规则全部置false。

两条路线对比:

  • extendprettier.json:放弃全部重叠规则的检查,简单彻底,适合完全信任 Prettier 输出;
  • 本文的精调方案:保留列表规则,仅调整参数适配--tab-width=4,lint 能力更完整,适合希望列表结构仍受约束的团队。

无论选择哪条路线,--tab-width=4都是唯一需要额外配置参数的非默认场景;其余 Prettier 选项(如--prose-wrap、--print-width)不会与 markdownlint 的默认配置产生列表类冲突。

  • 开发工具
  • 代码质量
  • Lint
  • 静态分析

【免费下载链接】markdownlint

A Node.js style checker and lint tool for Markdown/CommonMark files.

项目地址:https://gitcode.com/gh_mirrors/ma/markdownlint
点击查看免费下载

相关推荐

上一篇:Modin 革命:高性能分布式 DataFrame 库如何重塑 Pandas 并行计算生态
下一篇:MFE-starter性能优化:Ahead of Time编译实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进