markdownlint MD050 规则详解:`strong-style` 加粗样式一致性检查
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
asteriskin 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
);
}
}
整个检查流程可以拆解为以下几步:
- 声明使用 micromark 解析器:规则对象中的
"parser": "micromark"表明该规则基于 micromark 生成的令牌(token)树进行判定,而非传统的 markdown-it 令牌流。 - 筛选 strong 令牌:通过 helpers/micromark-helpers.cjs 中的
filterByPredicate遍历 micromark 令牌树,过滤出类型为strong的令牌;同时跳过htmlFlow令牌内的内容,即 HTML 块中的加粗符号不会被检查。 - 定位序列令牌:使用
getDescendantsByType(helpers/micromark-helpers.cjs)取出每个 strong 令牌内部的strongSequence子令牌,其中第一个序列是起始标记、最后一个序列是结束标记。 - 判定符号风格:
emphasisOrStrongStyleFor(lib/md049-md050.mjs)根据序列文本的首字符判断风格——*对应asterisk,其余情况视为underscore。 - 与配置比较:若配置为
consistent,则用当前标记的风格更新style(即“锁定第一个加粗的风格”);随后若style与当前标记风格不一致,且不满足上述“词内加粗”豁免条件,则报告违规。 - 报告违规并附带修复信息:对起始、结束两个序列分别调用
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,直接采用该预置风格即可避免规则冲突。
实际使用建议
- 新文档建议显式配置
asterisk或underscore:consistent虽然省心,但判定结果取决于“第一个加粗”,容易因历史文档起始位置不同而产生漂移;显式指定符号可获得稳定的检查结果。 - 不要修改 Prettier 托管的内容:如果文档由 Prettier 格式化,请保留 style/prettier.json 中
strong-style: false的默认关闭状态。 - 善用自动修复:对于非词内场景的违规,可直接运行 markdownlint 的自动修复模式一键统一加粗符号;词内加粗(如
like__this__one)则会被规则安全豁免,避免误伤。 - 注意与 MD049 的联动:MD049 负责单星号/单下划线(强调),MD050 负责双星号/双下划线(加粗),二者共用同一实现。若你的团队文档同时涉及两者,建议一并配置
emphasis-style与strong-style,保持整体标记风格一致。