资讯详情

资讯详情

markdownlint MD040 规则实战:用 allowed_languages 与 language_only 严格校验围栏代码块语言

开发工具代码质量Lint静态分析【免费下载链接】markdownlintA Node.js style checker and lint tool for Markdown/CommonMark files.项目地址https://gitcode.com/gh_mirrors/ma/markdownlint点击查看免费下载本篇技术指南围绕 markdownlint 的MD040 / fenced-code-language规则展开重点讲解如何通过allowed_languages与language_only两个配置参数对 Markdown 围栏代码块fenced code block的 info string信息字符串进行白名单与纯净度双重校验。结合仓库中的规则文档、规则实现源码与测试用例test/md040-language_only.md、test/md040-allowed_languages.md读者可以掌握该规则从触发条件、配置语义到源码判定逻辑的完整链路并能在.markdownlint.json或文件内联配置中落地实战方案。规则概览MD040 到底检查什么MD040的官方描述是 Fenced code blocks should have a language specified即围栏代码块必须显式声明语言标识。它在 markdownlint 中的定位信息如下见 doc/md040.mdTags标签code、languageAliases别名fenced-code-languageParameters参数allowed_languages允许的语言列表string[]默认[]language_only只允许语言标识、禁止附加数据boolean默认false该规则在两种情况下触发使用了围栏代码块但没有指定任何语言。例如 #!/bin/bash echo Hello world 修复方式是补上语言标识bash #!/bin/bash echo Hello world 如果只是想让代码块以纯文本形式展示不做语法高亮官方文档建议使用text语言text Plain text in a code block 规则存在的设计理由Rationale是显式声明语言能让渲染器使用正确的语法高亮从而显著改善内容呈现效果。两个核心参数allowed_languages 与 language_onlyallowed_languages语言白名单allowed_languages用于指定代码块可以使用的语言列表。文档明确指出语言是大小写敏感的Languages are case sensitive例如TS与ts会被视为两个不同的语言标识。默认值为[]即不启用白名单任何语言标识都被视为合法。注意只有当allowed_languages为非空数组时白名单校验才生效。这与规则实现源码中的(allowed.length 0) !allowed.includes(info)逻辑完全对应见 lib/md040.mjs。language_only信息字符串纯净度开关language_only默认值为false。当设置为true时规则会要求围栏代码块的 info string只能包含语言标识本身不能附带任何额外数据。官方文档给出的两个违规示例doc/md040.md带前导/尾随空白的 info string例如js携带额外参数的 info string例如ruby startline3。这两类写法在language_only: true时都会触发MD040。其中前导/尾随空白虽然会被解析器剥离不会计入语言标识本身但信息字符串中若存在 Meta 数据如version5则会命中language_only的校验分支。逐条解读测试用例language_only 的四个判定场景仓库中的 test/md040-language_only.md 正是为验证language_only行为而设计的场景化测试文件。该文件通过 HTML 注释内联配置启用了规则并设置参数随后依次构造四种围栏代码块场景。下面逐条还原并解释判定结果。场景一前导空白 —— 不报 MD040Fence code block information with leading whitespace: html h1markdownlint/h1代码块使用 html 两个反引号序列后跟两个空格再加 html。由于 CommonMark 解析器在提取 info string 时会剥离前导空白实际提取到的语言标识为 html它既在 allowed_languages: [html, css] 白名单内又不含任何 Meta 数据因此该行**不触发 MD040**。 ### 场景二代码内容尾随空格 —— 交给 MD009 处理Fence code block information with trailing whitespace:body {} {MD009:11}这一场景的围栏信息为 css本身合法但在代码内容 body {} 末尾存在一个尾随空格测试用 {MD009:11} 标记断言该问题由 MD009 / no-trailing-spaces 规则在第 11 行报出而不是 MD040。这体现了规则边界清晰、各司其职的设计——**MD040 只负责语言标识行尾空白归 MD009 管**。 ### 场景三额外数据 —— 触发 language_only 报错Fence code block information with extra data:titleMarkdownLint/title {MD040:17}围栏 html version5 的语言标识为 html在白名单内但 info string 中还携带了 version5 这一 Meta 数据。在 language_only: true 下这正是规则要拦截的对象测试断言第 17 行报 MD040错误信息为 Info string contains more than language: html version5见测试快照 [test/markdownlint-test-scenarios.mjs.snapshot](https://link.gitcode.com/i/45e404d226f717d08f2a77d9610f0b3c)。 ### 场景四干净的语言标识 —— 完全通过Fence code block information without whitespaces and extra data:a {} css 的 info string 恰好只有 css无空白、无附加数据完全符合 allowed_languages 白名单与 language_only 的双重约束不产生任何违规。 ### 场景化的内联配置 以上四个场景共同受文件末尾的 HTML 注释配置驱动见 [test/md040-language_only.md](https://link.gitcode.com/i/52a5fc4027e7c6e46c02c9cc019072c7#L27-L35) html !-- markdownlint-configure-file { fenced-code-language: { allowed_languages: [ html, css ], language_only: true } } --这种markdownlint-configure-file注释语法的作用范围是整个文件与注释所在位置无关若一个文件存在多条此类注释则按自上而下的顺序依次应用见 README.md。默认注释内容按 JSON 解析仓库还支持通过configParsers扩展 YAML、TOML 等其他格式。源码级剖析MD040 的判定逻辑规则实现位于 lib/md040.mjs其函数体lib/md040.mjs完整展示了上述行为的底层原理let allowed params.config.allowed_languages; allowed Array.isArray(allowed) ? allowed : []; const languageOnly !!params.config.language_only; const fencedCodes filterByTypesCached([ codeFenced ]); for (const fencedCode of fencedCodes) { const openingFence getDescendantsByType(fencedCode, [ codeFencedFence ])[0]; const { startLine, text } openingFence; const info getDescendantsByType(openingFence, [ codeFencedFenceInfo ])[0]?.text; if (!info) { addErrorContext(onError, startLine, text); } else if ((allowed.length 0) !allowed.includes(info)) { addError(onError, startLine, ${info} is not allowed); } if (languageOnly getDescendantsByType(openingFence, [ codeFencedFenceMeta ]).length 0) { addError(onError, startLine, Info string contains more than language: ${text}); } }关键逻辑可归纳为四点配置归一化allowed_languages若非数组则回退为空数组language_only经!!转换为布尔值保证后续判定的健壮性。token 遍历该规则声明parser: micromark通过filterByTypesCached取出所有类型为codeFenced的围栏代码块 token再借助getDescendantsByType向下钻取codeFencedFence围栏本身、codeFencedFenceInfo语言标识与codeFencedFenceMeta附加数据三类子 token。缺语言判定info为空即报错属于 MD040 最基本的触发路径。双条件交叉校验白名单校验allowed.includes(info)与纯净度校验codeFencedFenceMeta是否存在相互独立、叠加生效——前者过滤不合法语言后者拦截version5之类的附加参数。这也解释了场景三html过了白名单version5却过不了language_only。getDescendantsByType的实现在 helpers/micromark-helpers.cjs它按类型路径逐层过滤子 token是规则从解析树中提取语义信息的通用工具。兄弟用例allowed_languages 的白名单与大小写敏感性language_only与allowed_languages常常搭配使用仓库为此提供了另一份专项测试 test/md040-allowed_languages.md其中对白名单行为进行了更细致的覆盖白名单外语言报错html、css在未加入白名单时分别于第 5、11 行报 MD040错误信息形如html is not allowed大小写敏感验证配置白名单为[js, scss, md, TS]时大写MD、小写ts均被判定为不在白名单而报错反之白名单内的md、TS严格大小写匹配则通过白名单只校验语言标识js foo这种语言 附加数据的写法在未开启language_only时不会触发 MD040因为js在白名单中foo被解析为 Meta 数据这一点恰好与language_only形成互补——若同时开启两个参数这类写法就会被 Meta 校验拦截。该文件同样以markdownlint-configure-file内联注释配置规则见 test/md040-allowed_languages.md。配置落地从全局文件到内联注释MD040有两种常见配置方式项目级配置文件在.markdownlint.json或.markdownlint.jsonc中按别名或规则号配置{ MD040: { allowed_languages: [html, css, bash, json], language_only: true } }也可以写作别名形式fenced-code-language: { ... }。文件级内联配置在单个 Markdown 文件内使用markdownlint-configure-file注释适用于只想对特定文件收紧约束的场景语法与本文测试用例中展示的完全一致。仓库还提供了 JSON Schema 以支持编辑器补全与配置校验fenced-code-language的 schema 定义位于 schema/markdownlint-config-schema.json其中明确了allowed_languagesstring[]默认[]、language_onlyboolean默认false以及enabled、severity等通用属性并限定属性之外不允许额外键additionalProperties: false从配置源头保证参数合法性。如何在本仓库复现与验证仓库的测试体系可以直接运行验证上述行为。场景化测试通过 test/markdownlint-test-scenarios.mjs 驱动它读取测试 Markdown 文件并调用lintAPI解析文件中形如{MD040:17}的行内标记作为预期断言test/markdownlint-test-scenarios.mjs并将实际输出与 test/markdownlint-test-scenarios.mjs.snapshot 中的快照比对。如果想手动查看某个测试文件的结构与 lint 结果可以使用 test/harness.mjs例如node test/harness.mjs test/md040-language_only.md该脚本会先打印文件的 Micromark token 树可见codeFencedFence、codeFencedFenceInfo、codeFencedFenceMeta的分层结构再输出完整的 lint 结果对象是理解规则判定过程最直观的辅助工具。实战建议与总结先白名单、再纯净度allowed_languages适合统一团队代码块语言风格如只允许bash、js、json、htmllanguage_only适合阻止 ruby startline3 这类携带编辑器/渲染器参数的写法。两者叠加使用即可得到语言既受控、且不带杂质的严格校验。牢记大小写敏感白名单匹配是精确字符串比较TS与ts互不通用配置时务必与团队约定保持一致。合理配置默认值allowed_languages默认[]意味着不校验语言种类此时 MD040 只管有没有语言标识只有显式配置白名单后才开始过滤具体语言从源码的allowed.length 0前置条件可以清楚地看到这一语义。用内联注释做局部收紧全局配置保持宽松对需要严格约束的文档如 API 参考、教程用markdownlint-configure-file局部开启language_only灵活且侵入性小。本指南所依托的测试场景、规则文档与实现源码均在仓库内可查规则语义见 doc/md040.md实现见 lib/md040.mjs场景验证见 test/md040-language_only.md 与 test/md040-allowed_languages.md。按上述配置组合实践即可在自己的 Markdown 工程中快速落地围栏代码块语言的规范化检查。赞分享开发工具代码质量Lint静态分析【免费下载链接】markdownlintA Node.js style checker and lint tool for Markdown/CommonMark files.项目地址https://gitcode.com/gh_mirrors/ma/markdownlint点击查看免费下载相关推荐markdownlint MD040 规则详解为围栏代码块指定语言fenced-code-languagemarkdownlint MD040 规则详解为围栏代码块指定语言fenced code language markdownlint 的 MD040 别开发工具代码质量Lint静态分析30 Seconds of Code掌握 JavaScript 同步与异步代码的执行模型与实战要点30 Seconds of Code掌握 JavaScript 同步与异步代码的执行模型与实战要点 理解 JavaScript 中同步synchronous开发工具代码质量Lint静态分析markdownlint 围栏代码块Fenced Code Block检查规则详解MD040、MD048 与 MD031/MD046 实战markdownlint 围栏代码块Fenced Code Block检查规则详解MD040、MD048 与 MD031/MD046 实战 导读 围栏代码开发工具代码质量Lint静态分析上一篇【亲测免费】 Visual Studio Code 设置同步插件指南下一篇如何用uilang在5分钟内为网页添加交互功能面向设计师的完整教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →