Markdownlint

← 返回目录 > ← 返回总览

相关工具推荐

工具 说明
Prettier 通用代码格式化工具,支持 Markdown 格式化,可与 markdownlint 配合使用
Pre-commit 多语言 Git 钩子管理框架,markdownlint 的主流集成方式之一
Codespell 拼写检查工具,可与 markdownlint 互补检查 Markdown 文件中的拼写错误
Typos 源代码拼写纠正工具,适合与 markdownlint 配合进行文档质量检查

1. 简介

markdownlint(DavidAnson/markdownlint)是一个基于 Node.js 的 Markdown/CommonMark 静态分析工具,通过丰富的内置规则库检测 Markdown 文件中的格式违规和风格不一致问题。该项目使用 micromark 解析器,遵循 CommonMark 规范,同时兼容 GitHub Flavored Markdown(GFM)语法(如自动链接、表格),以及 directives、footnotes、math 语法。

markdownlint 最初灵感来源于 Mark Harrison 编写的 Ruby 版 markdownlint,继承了其初始规则、文档和测试用例。

  • 主要检查语言:Markdown
  • 主要检查能力:对 Markdown 文件进行静态分析,检测格式违规和风格不一致问题;涵盖Markdown 格式化检查和风格类检查
  • 核心检查原理:基于 micromark 解析器生成 AST,遵循 CommonMark 规范
  • 检查规则/选项:53 条内置规则(MD001–MD060,当前版本 v0.41.0),全部默认启用,全量规则列表
  • GitHub 仓库https://github.com/DavidAnson/markdownlint(6,119 stars)
  • 开源协议:MIT
  • 最新稳定版本:markdownlint v0.41.0 / markdownlint-cli v0.48.0 / markdownlint-cli2 v0.22.1
  • 运行环境要求:Node.js 18+
  • 误报率:低

2. 官方文档

资源 链接 说明
核心库(markdownlint) https://github.com/DavidAnson/markdownlint 核心库源码、API 文档、配置说明
规则文档(Rules.md) https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md 所有规则的详细说明、参数、示例
命令行工具 v1(markdownlint-cli) https://github.com/igorshubovych/markdownlint-cli 传统 CLI,支持 pre-commit
命令行工具 v2(markdownlint-cli2) https://github.com/DavidAnson/markdownlint-cli2 推荐的 CLI,更快更灵活
VS Code 扩展 https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint VS Code 官方扩展
GitHub Action https://github.com/marketplace/actions/markdownlint-cli2-action markdownlint-cli2-action
自定义规则文档 https://github.com/DavidAnson/markdownlint/blob/main/doc/CustomRules.md 如何编写自定义规则
在线演示 https://dlaa.me/markdownlint/ 交互式在线体验
与 Prettier 兼容性 https://github.com/DavidAnson/markdownlint/blob/main/doc/Prettier.md 与 Prettier 共存时的规则冲突说明

3. 社区优秀实践

3.1 markdownlint 官方仓库自身

markdownlint 官方仓库自身就是最佳实践的参考,其 .markdownlint.json 配置文件展示了完整的规则配置方式。

3.2 markdownlint-cli2 官方仓库

markdownlint-cli2 仓库使用 .markdownlint-cli2.jsonc 配置文件,展示了 markdownlint-cli2 的推荐配置方式。

3.3 ESLint

ESLint 是 JavaScript 生态中最主流的代码检查工具,其项目自身使用 markdownlint 来检查项目中的 Markdown 文件质量。

3.4 GitHub Super-Linter

GitHub Super-Linter 是 GitHub 官方维护的统一代码检查工具,内置了 markdownlint 作为 Markdown 文件的检查引擎。

4. 工具配置说明

4.1 配置文件说明

markdownlint 支持多种配置文件格式,按优先级从高到低排列。

markdownlint-cli2 配置文件(完整控制,支持 globs/ignores 等)

配置文件 格式 用途
.markdownlint-cli2.jsonc JSON with Comments 完整控制:规则、globs、ignores,支持注释
.markdownlint-cli2.yaml YAML 同上,YAML 格式
.markdownlint-cli2.cjs CommonJS 同上,JS 动态生成配置
.markdownlint-cli2.mjs ESM 同上,ESM 动态生成配置

markdownlint 规则配置文件(仅控制规则)

配置文件 格式 用途
.markdownlint.jsonc JSON with Comments 规则配置,支持注释
.markdownlint.json JSON 规则配置,最常用
.markdownlint.yaml / .markdownlint.yml YAML 规则配置,YAML 格式可读性更好
.markdownlint.cjs / .markdownlint.mjs JavaScript 规则配置,JS 动态生成

markdownlint-cli2 配置示例(.markdownlint-cli2.jsonc,支持注释和完整控制)

{
  // markdownlint-cli2 配置
  "globs": ["**/*.md", "#node_modules", "#.git"],

  "config": {
    "default": true,
    "MD013": false, // 关闭行长度限制
    "MD024": {
      // 仅检查兄弟标题不重复
      "siblings_only": true,
    },
    "MD033": false, // 允许内联 HTML
    "MD041": false, // 不要求首行必须是标题
  },

  "ignores": ["CHANGELOG.md", "**/vendor/**/*.md"],
}

4.2 配置文件详解

markdownlint 配置文件控制规则启用、禁用及参数化设置。规则可通过 ID(如 MD013)或别名(如 line-length)引用。

配置项说明

配置项 类型 说明
default bool 是否启用所有默认规则
MD0xx / 规则别名 bool/object 单条规则配置,false 禁用,true 启用默认参数,对象形式传入参数
globs string[] (markdownlint-cli2)扫描的文件 glob 列表,# 前缀表示排除
config map (markdownlint-cli2)规则配置,等同于 .markdownlint.json 的内容
ignores string[] (markdownlint-cli2)忽略的文件 glob 列表

推荐配置示例(通用项目,JSON 格式)

适用于大多数开源项目和个人项目,在严格性和灵活性之间取得平衡。

文件.markdownlint.json

{
  "default": true,
  "MD003": { "style": "atx" },
  "MD004": { "style": "consistent" },
  "MD007": { "indent": 2 },
  "MD009": { "br_spaces": 2 },
  "MD010": { "code_blocks": true },
  "MD012": { "maximum": 1 },
  "MD013": {
    "line_length": 120,
    "code_blocks": false,
    "tables": false
  },
  "MD022": { "lines_above": 1, "lines_below": 1 },
  "MD024": { "siblings_only": true },
  "MD026": { "punctuation": ".,;:!?" },
  "MD029": { "style": "ordered" },
  "MD030": { "ul_multi": 3, "ol_multi": 2 },
  "MD033": false,
  "MD035": { "style": "---" },
  "MD041": false,
  "MD043": false,
  "MD044": { "names": [] },
  "MD046": { "style": "fenced" },
  "MD047": true,
  "MD048": { "style": "backtick" },
  "MD049": { "style": "consistent" },
  "MD050": { "style": "consistent" },
  "MD054": { "style": "consistent" },
  "MD055": { "style": "consistent" }
}

规则说明

规则 别名 说明 配置值含义
MD003 heading-style 标题风格统一 "atx" = 统一使用 # 风格
MD004 ul-style 无序列表符号统一 "consistent" = 整个文档一致
MD007 ul-indent 无序列表嵌套缩进 "indent": 2 = 缩进 2 空格
MD009 no-trailing-spaces 行尾空格 "br_spaces": 2 = 允许 2 个空格用于换行
MD010 no-hard-tabs 禁止硬 Tab "code_blocks": true = 代码块内也检查
MD012 no-multiple-blanks 禁止连续空行 "maximum": 1 = 最多 1 个连续空行
MD013 line-length 行长度限制 120 = 最大 120 字符,代码块和表格不检查
MD022 blanks-around-headings 标题前后需有空行 上下各 1 个空行
MD024 no-duplicate-heading 禁止重复标题 "siblings_only": true = 仅检查同级别兄弟标题
MD026 no-trailing-punctuation 标题末尾不能有标点 允许的标点:. , ; : ! ?
MD029 ol-prefix 有序列表前缀样式 "ordered" = 编号递增(1. 2. 3.)
MD030 list-marker-space 列表标记后空格数 多行列表项内容对齐
MD033 no-inline-html 禁止内联 HTML false = 允许(很多文档需要 HTML)
MD035 hr-style 水平线风格统一 "---" = 统一使用 ---
MD041 first-line-heading 文件首行应为一级标题 false = 不强制(很多文档以元数据开头)
MD043 required-headings 要求特定标题结构 false = 不强制
MD044 proper-names 专有名词大小写正确 "names": [] = 不检查
MD046 code-block-style 代码块风格统一 "fenced" = 使用围栏式
MD047 single-trailing-newline 文件末尾需有换行符 true = 启用
MD048 code-fence-style 代码围栏风格统一 "backtick" = 使用反引号
MD049 emphasis-style 斜体风格统一 "consistent" = 整个文档一致
MD050 strong-style 粗体风格统一 "consistent" = 整个文档一致
MD054 link-image-style 链接/图片风格统一 "consistent" = 整个文档一致
MD055 table-pipe-style 表格管道符风格统一 "consistent" = 整个文档一致

推荐配置示例(宽松配置,YAML 格式)

适用于个人笔记、博客等场景,放宽行长度等限制。

文件.markdownlint.yaml

# 默认启用所有规则
default: true

# MD013 - 不限制行长度(个人写作场景)
line-length: false

# MD024 - 仅检查兄弟标题不重复
no-duplicate-heading:
  siblings_only: true

# MD033 - 允许内联 HTML(博客/文档常用)
no-inline-html: false

# MD041 - 不要求首行必须是标题
first-line-heading: false

# MD043 - 不强制特定标题结构
required-headings: false

# MD044 - 不检查专有名词
proper-names:
  names: []

# MD029 - 有序列表使用递增编号
ol-prefix:
  style: "ordered"

# MD048 - 代码块使用反引号
code-fence-style:
  style: "backtick"

推荐配置示例(严格配置,适用于团队协作文档)

适用于需要严格规范的大型团队文档项目,如 API 文档、技术规范等。

文件.markdownlint.json

{
  "default": true,
  "MD003": { "style": "atx" },
  "MD004": { "style": "asterisk" },
  "MD007": { "indent": 2 },
  "MD009": { "br_spaces": 0 },
  "MD010": { "code_blocks": true },
  "MD012": { "maximum": 1 },
  "MD013": {
    "line_length": 80,
    "code_blocks": false,
    "tables": false
  },
  "MD022": { "lines_above": 1, "lines_below": 1 },
  "MD024": true,
  "MD026": { "punctuation": ".,;:!?" },
  "MD029": { "style": "ordered" },
  "MD030": { "ul_multi": 3, "ol_multi": 2 },
  "MD033": false,
  "MD035": { "style": "---" },
  "MD040": true,
  "MD041": true,
  "MD046": { "style": "fenced" },
  "MD047": true,
  "MD048": { "style": "backtick" },
  "MD049": { "style": "underscore" },
  "MD050": { "style": "asterisk" },
  "MD055": { "style": "consistent" }
}

与通用配置的主要差异

  • MD009"br_spaces": 0 -- 严格禁止行尾空格(不允许用 2 个空格换行)
  • MD013"line_length": 80 -- 严格限制行长度为 80 字符
  • MD024true -- 严格禁止任何重复标题(不限于兄弟标题)
  • MD041true -- 强制要求文件首行必须是一级标题
  • MD004"style": "asterisk" -- 强制无序列表统一使用 * 符号

5. 主流集成方式

5.1 npm 集成(生态主流)

markdownlint 是 Node.js 生态工具,npm 是其最主流的集成方式。

安装

# 安装 markdownlint-cli(传统 CLI)
npm install markdownlint-cli --save-dev

# 安装 markdownlint-cli2(推荐,更快更灵活)
npm install markdownlint-cli2 --save-dev

在 package.json 中添加 lint 脚本

{
  "scripts": {
    "lint:md": "markdownlint-cli2 \"**/*.md\" \"#node_modules\"",
    "lint:md:fix": "markdownlint-cli2 --fix \"**/*.md\" \"#node_modules\""
  },
  "devDependencies": {
    "markdownlint-cli2": "^0.22.1"
  }
}

5.2 husky + lint-staged 集成(Node.js 项目)

对于 Node.js 项目,husky + lint-staged 是与 npm 生态结合更紧密的提交门禁方案。

# 安装依赖
npm install husky lint-staged markdownlint-cli2 --save-dev

# 初始化 husky
npx husky init
// package.json
{
  "lint-staged": {
    "*.md": ["markdownlint-cli2 --fix"]
  }
}
# .husky/pre-commit
npx lint-staged

增量检查:lint-staged 仅对暂存区的变更文件执行配置的命令,天然实现文件级增量检查。配合 markdownlint-cli2 --fix 可在提交前自动修复变更文件的格式问题。

5.3 pre-commit 集成

markdownlint-cli 和 markdownlint-cli2 均官方支持 pre-commit,且各自仓库包含 .pre-commit-hooks.yaml 文件。pre-commit 是 markdownlint 在多语言项目中常见的本地提交门禁集成方式。

方式一:使用 markdownlint-cli2(推荐)

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/DavidAnson/markdownlint-cli2
    rev: v0.22.1
    hooks:
      - id: markdownlint-cli2

依赖来源:language: node,pre-commit 会自动安装 Node.js 环境并执行 npm install 安装 hook 依赖。适用前提:无需本地安装 Node.js,pre-commit 自行管理运行时。

方式二:使用 markdownlint-cli(传统方式)

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/igorshubovych/markdownlint-cli
    rev: v0.48.0
    hooks:
      - id: markdownlint

依赖来源:language: node,pre-commit 会自动安装 Node.js 环境并执行 npm install 安装 hook 依赖。适用前提:无需本地安装 Node.js,pre-commit 自行管理运行时。

方式三:使用 Docker 镜像(无需 Node.js 环境)

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/DavidAnson/markdownlint-cli2
    rev: v0.22.1
    hooks:
      - id: markdownlint-cli2-docker

依赖来源:language: docker_image,使用 Docker 容器运行。适用前提:需要本地安装 Docker。

增量检查:pre-commit 框架默认仅将暂存区中变更的文件传给 hook,无需额外配置即可实现文件级增量检查。如需全量检查,可手动运行 pre-commit run markdownlint-cli2 --all-files

5.4 IDE 集成

VS Code(推荐)

安装官方扩展 DavidAnson.vscode-markdownlint(扩展市场安装量超 1100 万):

  • 扩展 IDDavidAnson.vscode-markdownlint
  • 安装方式:在 VS Code 扩展市场搜索 "markdownlint",认准发布者为 David Anson
  • 命令行安装code --install-extension DavidAnson.vscode-markdownlint

配置保存时自动修复(在 .vscode/settings.json 中):

{
  "[markdown]": {
    "editor.formatOnSave": true
  },
  "editor.codeActionsOnSave": {
    "source.fixAll.markdownlint": "explicit"
  }
}

VS Code 扩展使用 markdownlint-cli2 引擎,与命令行工具共享配置文件(.markdownlint-cli2.jsonc.markdownlint.json 等)。

Vim/Neovim

使用 coc-markdownlint 扩展(基于 coc.nvim):

Emacs

使用 flymake-markdownlint-cli2 扩展:

5.5 命令行使用方式

markdownlint-cli2(推荐)

# 安装
npm install -g markdownlint-cli2

# 检查当前目录下的 Markdown 文件
markdownlint-cli2 "**/*.md" "#node_modules"

# 检查并自动修复
markdownlint-cli2 --fix "**/*.md" "#node_modules"

# 指定配置文件
markdownlint-cli2 --config "config/.markdownlint-cli2.jsonc" "**/*.md"

# 使用 pyproject.toml 中的配置
markdownlint-cli2 --config pyproject.toml --configPointer /tool/markdownlint-cli2 "**/*.md"

# 使用 package.json 中的配置
markdownlint-cli2 --config package.json --configPointer /markdownlint-cli2 "**/*.md"

# Docker 方式运行
docker run --rm -v "$PWD:/workdir" davidanson/markdownlint-cli2:v0.22.1 "**/*.md" "#node_modules"

# Homebrew 安装(macOS)
brew install markdownlint-cli2

markdownlint-cli(传统 CLI)

# 安装
npm install -g markdownlint-cli

# 检查所有 Markdown 文件
markdownlint "**/*.md"

# 检查并自动修复
markdownlint --fix "**/*.md"

# 排除 node_modules 目录
markdownlint "**/*.md" --ignore node_modules

# 指定配置文件
markdownlint --config .markdownlint.json "**/*.md"

# 禁用/启用指定规则
markdownlint --disable MD013 -- README.md
markdownlint --enable MD013 -- README.md

# JSON 格式输出
markdownlint --json "**/*.md"

# 检查 stdin
cat README.md | markdownlint --stdin

退出码说明(markdownlint-cli):

退出码 含义
0 检查成功,无错误(可能有警告)
1 检查成功,有错误(可能有警告)
2 无法写入输出文件
3 无法加载自定义规则
4 意外问题(如配置格式错误)

增量检查:可通过 git diff 筛选变更文件后传给 markdownlint-cli2 实现增量检查。

# 检查相对于 main 分支变更的 Markdown 文件
markdownlint-cli2 $(git diff --name-only --diff-filter=ACMR main -- '*.md')

# 检查暂存区的 Markdown 文件
markdownlint-cli2 $(git diff --cached --name-only --diff-filter=ACMR -- '*.md')

# 检查未提交的变更文件
markdownlint-cli2 $(git diff --name-only --diff-filter=ACMR -- '*.md')

注意:当 git diff 返回空结果时,markdownlint-cli2 不带参数会检查当前目录,建议包装为脚本处理空列表情况。

CI 脚本调用

GitLab CI

# .gitlab-ci.yml
markdownlint:
  image: node:22-alpine
  before_script:
    - npm install -g markdownlint-cli2
  script:
    - markdownlint-cli2 "**/*.md" "#node_modules"
  only:
    - merge_requests
    - main

增量检查:CI/CD 场景下可基于变更文件实现增量检查。

GitHub Actions(增量:使用 changed-files)

name: Markdown Lint (Incremental)
on: [push, pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: tj-actions/changed-files@v47
        id: changed-files
        with:
          files: "**/*.md"
          separator: ","
      - uses: DavidAnson/markdownlint-cli2-action@v23
        if: steps.changed-files.outputs.any_changed == 'true'
        with:
          globs: ${{ steps.changed-files.outputs.all_changed_files }}
          separator: ","

此方案来自 markdownlint-cli2-action 官方仓库的 changed.yml 示例。

GitLab CI(增量)

# .gitlab-ci.yml
markdownlint:
  image: node:22-alpine
  before_script:
    - npm install -g markdownlint-cli2
  script:
    - CHANGED=$(git diff --name-only --diff-filter=ACMR origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME -- '*.md')
    - |
      if [ -n "$CHANGED" ]; then
        markdownlint-cli2 $CHANGED
      fi
  only:
    - merge_requests

5.6 GitHub Action 插件

# .github/workflows/markdownlint.yml
name: Markdown Lint
on: [push, pull_request]

jobs:
  markdownlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: DavidAnson/markdownlint-cli2-action@v23

使用自定义配置文件:

jobs:
  markdownlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: DavidAnson/markdownlint-cli2-action@v23
        with:
          config: ".markdownlint-cli2.jsonc"
          globs: "**/*.md"

6. 告警抑制(屏蔽)方法

6.1 通过代码内联注释屏蔽(HTML 注释)

在 Markdown 文件中使用 HTML 注释临时禁用/启用规则,这是最灵活的抑制方式。

官方文档:Configuration - Disabling Rules

<!-- 禁用所有规则 -->
<!-- markdownlint-disable -->

这段内容不会触发任何规则检查
<!-- markdownlint-enable -->

<!-- 禁用指定规则 -->
<!-- markdownlint-disable MD013 MD024 -->

这段长行不会触发 MD013(行长度)检查
<!-- markdownlint-enable MD013 MD024 -->

<!-- 仅禁用下一行 -->
<!-- markdownlint-disable-next-line MD013 -->

这是一行非常非常非常长的内容,不会触发 MD013 检查

<!-- 仅禁用当前行 -->

这段内容 <!-- markdownlint-disable-line MD013 --> 是一行很长的内容

<!-- 禁用整个文件 -->
<!-- markdownlint-disable-file -->

<!-- 禁用整个文件中的指定规则 -->
<!-- markdownlint-disable-file MD013 MD024 -->

<!-- 启用整个文件中的指定规则 -->
<!-- markdownlint-enable-file MD013 MD024 -->

<!-- 记录并恢复配置 -->
<!-- markdownlint-capture -->
<!-- markdownlint-disable MD013 -->

长行内容...
<!-- markdownlint-restore -->

<!-- 文件级配置覆盖 -->
<!-- markdownlint-configure-file { "MD013": false, "MD033": false } -->

行内注释速查表

注释语法 作用范围 说明
<!-- markdownlint-disable --> 之后所有行 禁用所有规则
<!-- markdownlint-enable --> 之后所有行 重新启用所有规则
<!-- markdownlint-disable MD001 --> 之后所有行 禁用指定规则
<!-- markdownlint-enable MD001 --> 之后所有行 重新启用指定规则
<!-- markdownlint-disable-next-line MD001 --> 下一行 仅在下一行禁用指定规则
<!-- markdownlint-disable-line MD001 --> 当前行 仅在当前行禁用指定规则
<!-- markdownlint-disable-file --> 整个文件 禁用整个文件的所有规则
<!-- markdownlint-disable-file MD001 --> 整个文件 禁用整个文件的指定规则
<!-- markdownlint-enable-file MD001 --> 整个文件 启用整个文件的指定规则
<!-- markdownlint-capture --> - 记录当前规则配置
<!-- markdownlint-restore --> - 恢复之前记录的配置
<!-- markdownlint-configure-file { ... } --> 整个文件 文件级配置覆盖

6.2 通过工具配置文件屏蔽

在配置文件中将规则设为 false 即可全局禁用,或通过 ignores 字段排除文件/目录。

官方文档:markdownlint Configuration / markdownlint-cli2 Configuration

禁用规则(.markdownlint.json

{
  "MD013": false,
  "MD033": false,
  "MD041": false
}

排除文件/目录(.markdownlint-cli2.jsonc

{
  "globs": ["**/*.md"],
  "ignores": ["CHANGELOG.md", "**/vendor/**/*.md", "**/third-party/**/*.md"],
}

使用标签批量禁用规则

{
  "whitespace": false,
  "headings": false
}

6.3 通过工具命令行参数屏蔽(markdownlint-cli)

使用 --disable / --enable 参数在命令行中覆盖规则配置。

官方文档:markdownlint-cli Usage

# 禁用指定规则
markdownlint --disable MD013 --disable MD033 "**/*.md"

# 启用指定规则(覆盖配置文件中的禁用)
markdownlint --enable MD001 --enable MD022 -- README.md

6.4 通过命令行 glob 排除(markdownlint-cli2)

在命令行中使用 #! 前缀排除文件或目录。

官方文档:markdownlint-cli2 Command Line

# 排除 node_modules 和 CHANGELOG.md
markdownlint-cli2 "**/*.md" "#node_modules" "#CHANGELOG.md"

6.5 通过 .markdownlintignore 文件排除(markdownlint-cli)

在项目根目录创建 .markdownlintignore 文件,语法与 .gitignore 相同。

官方文档:markdownlint-cli Ignoring files

# .markdownlintignore
CHANGELOG.md
node_modules/
vendor/
*.min.md

6.6 通过 pre-commit 配置屏蔽

.pre-commit-config.yaml 中通过 hook 级别的 filesexcludetypes 控制检查范围。

官方文档:pre-commit Hooks - Configuring hooks

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/DavidAnson/markdownlint-cli2
    rev: v0.22.1
    hooks:
      - id: markdownlint-cli2
        files: ^(docs|README).*
        exclude: ^docs/legacy/
        types: [markdown]

← 返回目录 | ← 返回总览