markdownlint MD034 规则详解:从 bare-urls 测试用例理解“裸 URL“检测与修复

发布时间:2026/10/15 6:41:28
markdownlint MD034 规则详解:从 bare-urls 测试用例理解“裸 URL“检测与修复
开发工具代码质量Lint静态分析【免费下载链接】markdownlintA Node.js style checker and lint tool for Markdown/CommonMark files.项目地址https://gitcode.com/gh_mirrors/ma/markdownlint点击查看免费下载导读MD034no-bare-urls是 markdownlint 中专门检测裸 URL未用尖括号包裹的 URL 或邮箱地址的规则它在纯文本 Markdown 文档、博客草稿与文档站源码中是高频命中项。本文将依托 test/bare-urls.md 这一官方详细测试文档逐条拆解 MD034 的违规边界、修复手法与大量看似裸 URL 却不报错的例外场景并结合 doc/md034.md 规则文档与 lib/md034.mjs 源码讲清规则背后的 micromark token 判定原理、自动修复fixInfo行为与实测验证方法。一、规则概览MD034 是什么MD034 - Bare URL used属于links与url两个标签组别名no-bare-urls其官方定义位于 doc/md034.md在 doc/Rules.md 中也收录了完整条目。规则说明中有一句核心的触发条件只要一个 URL 或邮箱地址没有用尖括号包裹出现就会触发该规则。官方文档给出的触发示例For more info, visit https://www.example.com/ or email userexample.com.修复方式是为 URL 与邮箱补上尖括号For more info, visit https://www.example.com/ or email userexample.com.规则动机Rationale没有尖括号的裸 URL/邮箱在部分 Markdown 解析器中不会自动转换为可点击链接作者意图希望它是链接与渲染结果可能不一致。MD034 通过强制要么写成交互式链接、要么显式包裹来消除这种歧义。二、测试文档的定位与运行方式test/bare-urls.md 是 MD034 规则的官方详细结果Detailed Results测试文档它的地位很特殊不同于普通规则测试文件只验证哪一行报错这份文件几乎每一行都在演示一个判定场景行尾以{MD034}标注该行应命中规则未标注的行则是应当放行的对照用例。该文件由测试框架自动执行。仓库中的测试入口是 test/markdownlint-test-scenarios.mjs其预期结果快照保存在 test/markdownlint-test-scenarios.mjs.snapshot 中开发者也可以用通用跑批脚本 test/harness.mjs 单独对这份文件执行 lint 并打印结构化结果# 在仓库根目录执行对 bare-urls.md 运行 markdownlint 并打印完整结果 node test/harness.mjs test/bare-urls.mdharness 会调用markdownlint/promise的lint接口并以depth: null深度打印结果对象快照文件则记录了精确到列的errorRange与自动修复信息是验证规则实现与文档预期完全一致的黄金依据。三、逐类用例哪些写法会被判定为裸 URL以下分类整理自 test/bare-urls.md 的全部用例每一类都附带触发或放行的原因。3.1 基础违规任何形式的裸 URL 都会被标记不带任何修饰的 URL 自然命中 MD034For more, see https://example.com. {MD034} For more, see https://example.com/. {MD034} For more, see https://example.com/?querystring#hash. {MD034} For more, see https://example.com/info.htm. {MD034}注意路径、查询串?querystring#hash与文件名/info.htm并不会改变判定结果——只要是裸的完整 URL整体都会被标记。对应快照显示这些用例的fixInfo.insertText依次为https://example.com、https://example.com/、https://example.com/?querystring#hash、https://example.com/info.htm即自动修复会精确地为整段 URL 加回尖括号。3.2 URL 位于句子中间或被括号包围URL 出现在句中、紧邻标点时同样违规Visit https://example.com, then refresh. {MD034} The site (https://example.com) is down. {MD034}即使被普通圆括号包裹URL 依然是裸的圆括号不是 Markdown 的尖括号语法照样触发规则。3.3 夹杂 HTML 行内标签br时依然违规行内 HTML 标签不会庇护其两侧的裸 URLbr Another violation: https://example.com. {MD034} br br/ Another violation: https://example.com. {MD034} br/在 test/bare-urls-in-html.md 中还有同样的验证Text br text https://example.com/fail br text. {MD034}。这说明只有 HTML 标签内部属性值中的 URL 才能豁免标签外的裸 URL 一律照报。3.4 URL 以连字符结尾URLs may end with a dash: https://example.com#heading- {MD034}URL 的 fragment 以-结尾时依然被识别为完整 URL 并报错而用尖括号显式包裹后即可放行... when explicit: https://example.com#heading- ... when embedded: codehttps://example.com#heading-/code四、例外场景哪些像 URL的写法不会触发测试文档用大量篇幅给出了应当放行的对照用例这些是误报排查时的重点。4.1 链接与图片的文本、目标中不报URL 出现在 Markdown 链接的显示文本、图片替代文本或链接目标里都不算裸 URLText [link to https://example.com site](https://example.com) text. Image ![for https://example.com site](https://example.com) text. This is not a bare link. Nor is [link](https://example.com/path-with(parens)). Or https://example.com/path-with(parens). Links with spaces inside angle brackets are okay: blue jay这里有几个值得注意的细节链接目标里的 URL 即使带着空格用尖括号包裹目标也是合法的链接语法而非裸 URL链接目标中的括号(parens)不会被误判链接显示文本中出现 URL 是允许的它已经是链接的一部分。4.2 HTML 属性值中的 URL 不报element-name first-attribute https://example.com/first second-attribute https://example.com/second Text /element-name以及跨行的属性写法element-name换行后继续写属性同样放行。HTML 标签属性值中的 URL 属于 HTML 语法的一部分不是 Markdown 文本中的裸 URL。4.3 HTML 块中的 URL 大多放行测试文档演示了code、pre包裹以及p、div块内的 URLNot codehttps://example.com/code bare. Not prehttps://example.com/pre bare. p Not bare due to being in an HTML block: https://example.com codehttps://example.com/code prehttps://example.com/pre /p其中p块内紧贴内容的 URL上方p后无空行被放行因为整段被解析为 HTML 块htmlFlow。但只要 HTML 块与 URL 之间出现空行URL 就脱离 HTML 块、重新成为 Markdown 文本立刻恢复违规div https://example.com /div !-- 放行 -- div https://example.com {MD034} !-- 空行后违规 -- /div div https://example.com {MD034} /div这正是 lib/md034.mjs 中inHtmlFlow(token)判定的实际体现token 是否位于 HTML 流htmlFlow内直接决定其是否被过滤。4.4 邮件地址与尖括号邮箱地址与 URL 同等对待Email addresses are treated similarly: userexample.com {MD034} Angle brackets work the same for email: userexample.com Unusual email addresses are handled: user.com裸邮箱报错包裹尖括号后放行即使是user.com这类非常规邮箱只要被尖括号显式包裹也能通过校验。4.5 shortcut link 的边界最内层优先绑定测试文档最后一段非常精巧地演示了 shortcut link快捷引用链接优先级导致的判定差异[is-a-valid]: https://example.com Links bind to the innermost [link that [is-a-valid] link](https://example.com) {MD034} But not if the [link [is-not-a-valid] link](https://example.com) Escaping both inner square brackets avoids confusion: [link \[is-not-a-valid\] link](https://example.com)这里的机理与 doc/md034.md 的两条 Note 一一对应是外层是[link ... ](https://example.com)行内链接内层[is-a-valid]因存在对应引用定义会被解析为 shortcut link 并优先绑定到最内层于是[is-a-valid]从外层链接文本中逃逸出来成为独立的裸文本从而触发 MD034若内层[is-not-a-valid]没有引用定义则不会成为 shortcut link整段仍是合法的行内链接不报错用\[转义内层方括号后[is-not-a-valid]不再可能被当作 shortcut link 语法同样不报错。五、源码级原理MD034 是如何判定的5.1 基于 micromark 的 token 扫描MD034 的规则实现位于 lib/md034.mjs它声明parser: micromark意味着依赖仓库自带的 micromark 解析管线见 lib/micromark-parse.mjs产出的 token 树。核心逻辑是通过filterByPredicate定义于 helpers/micromark-helpers.cjs深度遍历 token 树筛出所有类型为literalAutolink且不在 HTML 流内!inHtmlFlow(token)的 token对每个命中 token 生成fixInfoeditColumn为 URL 起始列deleteCount为 URL 长度insertText为url调用addErrorContext来自 helpers/helpers.cjs输出带上下文、范围和修复信息的 lint 错误。也就是说裸 URL的本质是 micromark 的 GFM autolink 扩展识别出的literalAutolinktoken——凡是被解析器认定为字面量自动链接却没有尖括号的文本就是 MD034 的目标。5.2 对 HTML 内容的双层过滤源码中filterByPredicate的第二个参数transformChildren实现了对行内 HTML 标签内容的剥离遍历 token 子节点遇到开标签getHtmlTagInfo返回非 null 且!close就跳过直到配对的闭标签从而把codehttps://example.com/code等 HTML 包裹内容排除在扫描范围之外。同时inHtmlFlow负责过滤 HTML 块如div、p整体这解释了 4.3 节中空行决定是否违规的现象。还有一个细节源码对literalAutolink的兄弟节点做了检查若前一个data节点以结尾、后一个data节点以开头则忽略该 token规避 micromark 上游 issue #164 的已知边界问题保证user.com这类显式包裹写法不被误报。5.3 自动修复的实测证据在 test/markdownlint-test-scenarios.mjs.snapshot 的bare-urls.md快照中每条错误都携带结构化fixInfo。例如第 3 行的记录{ lineNumber: 3, ruleNames: [MD034, no-bare-urls], ruleDescription: Bare URL used, errorContext: https://example.com, errorRange: [15, 19], fixInfo: { editColumn: 15, deleteCount: 19, insertText: https://example.com }, severity: error }errorRange的[列, 长度]与fixInfo完全对应说明该规则支持工具化自动修复doc/md034.md 中标注为 Fixable: Some violations can be fixed by tooling。在测试文档 test/MD031-MD040.md 中也包含基础的Bare https://example.com link {MD034}断言。六、如何修复与规避误报6.1 标准修复方式想让 URL 可点击加尖括号https://example.com→https://example.com想保持纯文本用行内代码code span包裹https://example.com包含非 ASCII 字符的 URL/邮箱即使加了尖括号某些解析器也可能无法正确处理此时建议使用百分号编码Percent-encoding转义以满足 URL/邮箱的语法要求见 doc/md034.md 的补充说明。6.2 不会被误报的放心写法综合测试文档可以总结出以下安全区场景示例是否触发 MD034行内链接目标[link](https://example.com)否链接显示文本https://example.com site否尖括号 autolinkhttps://example.com否行内代码https://example.com否HTML 属性值a hrefhttps://example.com否无定义的 shortcut[link [x] link](https://example.com)x 无定义否转义内层括号[link \[x\] link](https://example.com)否6.3 已知必须注意的边界内层方括号若对应已定义的引用标签会因 shortcut link 优先级逃逸并触发 MD034与div等 HTML 块之间隔了空行的 URL 会重新视为裸 URLbr行内标签夹住的裸 URL 照报不误以连字符结尾的 URL fragment 仍是裸 URL。七、在项目中使用与验证在 markdownlint 中MD034 默认启用属于默认配置规则集无需额外开关即可生效如需整体关闭可配置MD034: false。该规则归类于url标签也可通过标签级配置统一控制参见 README.md 中的规则与标签清单。验证方式有两种标准 CLI / API运行node test/harness.mjs test/bare-urls.md用仓库自带的测试管线输出带fixInfo的完整结果快照回归test/markdownlint-test-scenarios.mjs 的测试快照bare-urls.md 1段锁定了本文件每一行的期望错误与修复信息任何实现改动都会导致快照不一致从而保证文档与实现长期同步。结语从 test/bare-urls.md 这份详细结果测试文档可以看出MD034 远不止见到 URL 就报错这么简单它建立在 micromark 的literalAutolinktoken 识别之上通过inHtmlFlow与 HTML 标签剥离实现精准的例外判定并为绝大多数命中提供了可落地的fixInfo自动修复。理解这 60 余行用例背后的分类逻辑既能帮你在日常写作中一次性写出不触规的链接写法也能在遇到误报时快速定位是HTML 块边界shortcut link 绑定还是标点包裹在起作用。赞分享开发工具代码质量Lint静态分析【免费下载链接】markdownlintA Node.js style checker and lint tool for Markdown/CommonMark files.项目地址https://gitcode.com/gh_mirrors/ma/markdownlint点击查看免费下载相关推荐markdownlint MD034 规则详解裸 URL 与裸邮箱地址的检测与修复markdownlint MD034 规则详解裸 URL 与裸邮箱地址的检测与修复 本文是 markdownlint 规则系列指南之一围绕 MD034 规则开发工具代码质量Lint静态分析markdownlint MD034 裸 URL 检测规则详解HTML 上下文判定边界与自动修复markdownlint MD034 裸 URL 检测规则详解HTML 上下文判定边界与自动修复 MD034 别名 no bare urls 是 mark开发工具代码质量Lint静态分析markdownlint MD010 Hard tabs 规则详解制表符检测、spaces_per_tab 自动修复与测试夹具验证markdownlint MD010 Hard tabs 规则详解制表符检测、 spaces_per_tab 自动修复与测试夹具验证 本文以测试夹具 4 ta开发工具代码质量Lint静态分析上一篇从0到1掌握gh_mirrors/ui2/ui开发一个完整的桌面应用下一篇如何快速开始使用Tess-4-27B-OptiQ-4bit从安装到第一个推理的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考