markdownlint MD050 规则详解:`strong-style` 加粗样式一致性检查

原创2026-10-14 13:06:101,851 阅读
文章标签:开发工具Lint静态分析代码质量

markdownlint MD050 规则详解:strong-style 加粗样式一致性检查

导读

MD050(别名 strong-style)是 markdownlint 中用于检查加粗(strong)标记符号是否统一的规则:当文档中的加粗使用了与配置不一致的符号(星号 ** 或下划线 __)时,规则会报告违规。本文基于仓库中的规则文档 doc/md050.md 与 doc-build/md050.md,结合规则实现源码 lib/md049-md050.mjs 与测试用例,完整讲解该规则的参数配置、触发场景、自动修复能力与底层实现原理。读完本文,你将能够熟练配置 strong-style,理解其与姊妹规则 MD049(强调样式)的关系,并掌握词内加粗这一特殊边界情况的处理逻辑。

规则元信息一览

根据 doc/Rules.md 与 doc/md050.md,MD050 的元信息如下:

项目 值
规则编号 MD050
别名(Aliases) strong-style
标签(Tags) emphasis
配置参数 style(string,默认 consistent)
是否可自动修复 部分违规可由工具自动修复
解析器 micromark

MD050 的触发条件非常直观:当文档中用于加粗的符号与配置的加粗样式不一致时触发:

**Text**
__Text__

修复方式是在整个文档中统一使用配置的加粗样式:

**Text**
**Text**

style 参数:三种取值与配置方式

style 参数支持三种取值,均以字符串形式写入配置:

取值 行为
asterisk 强制全文档加粗使用 **(星号)
underscore 强制全文档加粗使用 __(下划线)
consistent(默认) 要求后续所有加粗与文档中第一个加粗保持一致

在 .markdownlint.json 等配置文件中,可以按别名或规则编号进行配置:

{
  "MD050": {
    "style": "asterisk"
  }
}

也可以使用别名 strong-style:

{
  "strong-style": {
    "style": "underscore"
  }
}

markdownlint 还支持在 Markdown 文件内部通过 HTML 注释进行单文件内联配置。仓库测试文件 test/strong_style_asterisk.md 展示了 asterisk 模式的内联配置写法:

<!-- markdownlint-configure-file {
  "strong-style": {
    "style": "asterisk"
  }
} -->

同样地,test/strong_style_underscore.md 中则配置为 underscore 模式。

三种模式下违规与合规的实际表现

仓库测试文件给出了不同模式下最直观的判定结果。

asterisk 模式(test/strong_style_asterisk.md)

以下内容全部合规(使用 **):

**This** is fine
This **is** fine
This is **fine**

以下内容全部违规(使用 __),分别在第 9、11、13 行报告 {MD050}:

__This__ is not
This __is__ not
This is __not__

underscore 模式(test/strong_style_underscore.md)

判定完全镜像:__This__ is fine、This __is__ fine、This is __fine__ 合规;而 **This** is not、This **is** not、This is **not** 在第 9、11、13 行分别报告 {MD050}。

consistent 模式(默认)

consistent 模式的规则是:以文档中第一个加粗的符号为准。因此,只要后续加粗与第一个加粗符号一致,即使第一个加粗使用了 __,也不视为违规。这也是 style/all.json 等默认风格配置没有单独为 MD050 指定取值时采用的默认行为。

需要特别说明的是,在 consistent 模式下,规则源码会在遍历到第一个 strong 令牌时“锁定”其符号风格(见下文实现解析),之后再遇到不同符号的加粗即报告违规。

词内加粗的特殊约束:为何必须用 asterisk

原文档特别注明了一条边界规则:

Note: Emphasis within a word is restricted to asterisk in order to avoid unwanted emphasis for words containing internal underscores like__this__one.

即:出现在单词内部的强调/加粗只能使用星号。以 like__this__one 为例,如果允许在词内使用 __,Markdown 解析器会把 __this__ 误判为加粗,从而在正常单词中间插入不必要的强调效果,破坏文档语义。

这条约束在实现中对应 lib/md049-md050.mjs 的正则:

const intrawordRe = /^\w$/;

当配置样式为 underscore 时,规则会检查加粗起始序列前一字符、结束序列后一字符是否为单词字符(\w,即字母、数字、下划线)。只要任一侧命中词内场景,就不报告违规、也不提供自动修复,从而避免把 like__this__one 这类正常文本误判为不一致的加粗。

源码实现解析:与 MD049 共享同一套核心逻辑

MD050 的实现位于 lib/md049-md050.mjs,它与姊妹规则 MD049(emphasis-style,强调样式) 定义在同一个文件中,两者共用同一个 impl 核心函数(lib/md049-md050.mjs)。MD050 的函数入口在 lib/md049-md050.mjs:

{
  "names": [ "MD050", "strong-style" ],
  "description": "Strong style",
  "tags": [ "emphasis" ],
  "parser": "micromark",
  "function": function MD050(params, onError) {
    return impl(
      params,
      onError,
      "strong",
      "strongSequence",
      "**",
      "__",
      params.config.style || undefined
    );
  }
}

整个检查流程可以拆解为以下几步:

  1. 声明使用 micromark 解析器:规则对象中的 "parser": "micromark" 表明该规则基于 micromark 生成的令牌(token)树进行判定,而非传统的 markdown-it 令牌流。
  2. 筛选 strong 令牌:通过 helpers/micromark-helpers.cjs 中的 filterByPredicate 遍历 micromark 令牌树,过滤出类型为 strong 的令牌;同时跳过 htmlFlow 令牌内的内容,即 HTML 块中的加粗符号不会被检查。
  3. 定位序列令牌:使用 getDescendantsByType(helpers/micromark-helpers.cjs)取出每个 strong 令牌内部的 strongSequence 子令牌,其中第一个序列是起始标记、最后一个序列是结束标记。
  4. 判定符号风格:emphasisOrStrongStyleFor(lib/md049-md050.mjs)根据序列文本的首字符判断风格——* 对应 asterisk,其余情况视为 underscore。
  5. 与配置比较:若配置为 consistent,则用当前标记的风格更新 style(即“锁定第一个加粗的风格”);随后若 style 与当前标记风格不一致,且不满足上述“词内加粗”豁免条件,则报告违规。
  6. 报告违规并附带修复信息:对起始、结束两个序列分别调用 addError,并携带 editColumn、deleteCount、insertText 修复信息(lib/md049-md050.mjs),从而支撑 markdownlint 的 --fix 自动修复能力——这正对应原文档中“Fixable: Some violations can be fixed by tooling”的说明。由于词内下划线场景被显式豁免,所以是“部分违规可修复”。

值得注意的是,impl 对 strong 传入的修复符号分别是 "**"(asterisk 模式)与 "__"(underscore 模式);而 MD049 对强调(emphasis)传入的是 "*" 与 "_"(lib/md049-md050.mjs),两者仅在此处与令牌类型上存在差异,核心判定逻辑完全一致。

测试用例与预期结果验证

仓库通过大量测试文件对 MD050 的行为进行了验证,主要分布在 test/ 目录:

  • test/strong_style_asterisk.md:asterisk 模式下的合规/违规样例及内联配置;
  • test/strong_style_underscore.md:underscore 模式下的对应样例;
  • test/emphasis-markers.md:验证多行代码跨度内及 HTML 块(<p>)中的 __bad__ 均被正确标记 {MD050},印证了实现中对 htmlFlow 内容的跳过逻辑;
  • test/mixed-emphasis-markers.md:验证嵌套场景,如 **nests both __kinds__ of emphasis** 在第 11 行报告 {MD050},而 *nests both __kinds__ of emphasis* 不触发(因为外层是强调、内层加粗与文档首个符号 * 体系相关);
  • test/break-all-the-rules.md:在全规则破坏文件中,第 94 行 Strong **with** different style 被标记 {MD050}(前面第 92 行使用了 __);
  • test/markdownlint-test.mjs:在 styleRelaxed 测试中断言 MD050 违规位于第 94 行,对修复信息与结果对象的一致性进行回归校验。

运行项目测试命令(如 node --test test/markdownlint-test.mjs)即可复现上述断言。

与 Prettier 风格的关系:默认关闭

在 style/prettier.json 中,"strong-style": false 表明:使用 Prettier 风格配置时,MD050 被显式关闭。原因是 Prettier 在格式化 Markdown 时会统一改写强调/加粗标记,因此无需 markdownlint 再对加粗符号做一致性约束;若你在 Prettier 工作流中同时启用 markdownlint,直接采用该预置风格即可避免规则冲突。

实际使用建议

  1. 新文档建议显式配置 asterisk 或 underscore:consistent 虽然省心,但判定结果取决于“第一个加粗”,容易因历史文档起始位置不同而产生漂移;显式指定符号可获得稳定的检查结果。
  2. 不要修改 Prettier 托管的内容:如果文档由 Prettier 格式化,请保留 style/prettier.json 中 strong-style: false 的默认关闭状态。
  3. 善用自动修复:对于非词内场景的违规,可直接运行 markdownlint 的自动修复模式一键统一加粗符号;词内加粗(如 like__this__one)则会被规则安全豁免,避免误伤。
  4. 注意与 MD049 的联动:MD049 负责单星号/单下划线(强调),MD050 负责双星号/双下划线(加粗),二者共用同一实现。若你的团队文档同时涉及两者,建议一并配置 emphasis-style 与 strong-style,保持整体标记风格一致。
登录后查看全文
markdownlint