一个用于 Markdown/CommonMark 文件的 Node.js 样式检查器和 lint 工具。
安装
npm install markdownlint --save-dev概述
Markdown 标记语言设计初衷是易于阅读、编写和理解。它确实做到了这一点,但其灵活性既是优点也是缺点。多种样式可能导致格式不一致;某些结构在所有解析器中表现不佳,应避免使用。
markdownlint 是一个针对 Node.js 的静态分析工具,包含一系列规则,用于强制执行 Markdown 文件的标准和一致性。它受到 Mark Harrison 的 Ruby 版 markdownlint 的启发和影响。初始规则、规则文档和测试用例均来自该项目。
markdownlint 使用 micromark 解析器,并遵循 Markdown 的 CommonMark 规范。此外,它还支持流行的 GitHub Flavored Markdown (GFM) 语法(如自动链接和表格),以及指令、脚注和数学语法——这些功能均由 micromark 扩展实现。
相关工具
- CLI
- markdownlint-cli Node.js 命令行工具(支持 pre-commit)
- markdownlint-cli2 Node.js 命令行工具(支持 pre-commit)
- GitHub
- 编辑器
- 工具链
- Ruby
参考规范
以下规范在歧义情况下被视为权威:
演示
markdownlint 演示,一个交互式的浏览器学习与探索工具。
规则 / 别名
- MD001 heading-increment - 标题级别应逐级递增
- MD003 heading-style - 标题样式
- MD004 ul-style - 无序列表样式
- MD005 list-indent - 同级列表项缩进不一致
- MD007 ul-indent - 无序列表缩进
- MD009 no-trailing-spaces - 行尾空格
- MD010 no-hard-tabs - 硬制表符
- MD011 no-reversed-links - 反向链接语法
- MD012 no-multiple-blanks - 多个连续空行
- MD013 line-length - 行长度
- MD014 commands-show-output - 命令前使用美元符号但未显示输出
- MD018 no-missing-space-atx - ATX 风格标题的井号后缺少空格
- MD019 no-multiple-space-atx - ATX 风格标题的井号后多个空格
- MD020 no-missing-space-closed-atx - 闭合 ATX 风格标题的井号内缺少空格
- MD021 no-multiple-space-closed-atx - 闭合 ATX 风格标题的井号内多个空格
- MD022 blanks-around-headings - 标题周围应有空行
- MD023 heading-start-left - 标题必须从行首开始
- MD024 no-duplicate-heading - 多个标题内容重复
- MD025 single-title/single-h1 - 同一文档中多个顶级标题
- MD026 no-trailing-punctuation - 标题末尾标点符号
- MD027 no-multiple-space-blockquote - 块引用符号后多个空格
- MD028 no-blanks-blockquote - 块引用内空行
- MD029 ol-prefix - 有序列表项前缀
- MD030 list-marker-space - 列表标记后空格
- MD031 blanks-around-fences - 围栏代码块周围应有空行
- MD032 blanks-around-lists - 列表周围应有空行
- MD033 no-inline-html - 内联 HTML
- MD034 no-bare-urls - 使用裸 URL
- MD035 hr-style - 水平线样式
- MD036 no-emphasis-as-heading - 使用强调代替标题
- MD037 no-space-in-emphasis - 强调标记内空格
- MD038 no-space-in-code - 代码跨度元素内空格
- MD039 no-space-in-links - 链接文本内空格
- MD040 fenced-code-language - 围栏代码块应指定语言
- MD041 first-line-heading/first-line-h1 - 文件首行应为顶级标题
- MD042 no-empty-links - 空链接
- MD043 required-headings - 必需的标题结构
- MD044 proper-names - 专有名词应正确大写
- MD045 no-alt-text - 图片应包含替代文本(alt text)
- MD046 code-block-style - 代码块样式
- MD047 single-trailing-newline - 文件应以单个换行符结尾
- MD048 code-fence-style - 围栏代码样式
- MD049 emphasis-style - 强调样式
- MD050 strong-style - 粗体样式
- MD051 link-fragments - 链接片段应有效
- MD052 reference-links-images - 引用链接和图片应使用已定义的标签
- MD053 link-image-reference-definitions - 链接和图片引用定义应被需要
- MD054 link-image-style - 链接和图片样式
- MD055 table-pipe-style - 表格管道样式
- MD056 table-column-count - 表格列数
- MD058 blanks-around-tables - 表格周围应有空行
更多细节请参见 Rules.md。
自定义规则
除了内置规则,还可以使用自定义规则以满足项目特定需求。要查找社区开发的规则,请在 npm 上使用关键字 markdownlint-rule。要自行实现规则,请参考 CustomRules.md。
标签
标签用于分组相关规则,可以一次性启用/禁用多个规则。
accessibility-MD045atx-MD018,MD019atx_closed-MD020,MD021blank_lines-MD012,MD022,MD031,MD032,MD047blockquote-MD027,MD028bullet-MD004,MD005,MD007,MD032code-MD014,MD031,MD038,MD040,MD046,MD048emphasis-MD036,MD037,MD049,MD050hard_tab-MD010headings-MD001,MD003,MD018,MD019,MD020,MD021,MD022,MD023,MD024,MD025,MD026,MD036,MD041,MD043hr-MD035html-MD033images-MD045,MD052,MD053,MD054indentation-MD005,MD007,MD027language-MD040line_length-MD013links-MD011,MD034,MD039,MD042,MD051,MD052,MD053,MD054ol-MD029,MD030,MD032spaces-MD018,MD019,MD020,MD021,MD023spelling-MD044table-MD055,MD056,MD058ul-MD004,MD005,MD007,MD030,MD032url-MD034whitespace-MD009,MD010,MD012,MD027,MD028,MD030,MD037,MD038,MD039
配置
传递给 markdownlint 的文本会被解析为 Markdown,分析后报告任何问题。大多数规则会忽略以下两种文本:
- HTML 注释
- Front matter(见
options.frontMatter)
可以通过 options.config(如下所述)启用、禁用和配置规则,以定义一组输入的预期行为。要在文件中的特定位置启用或禁用规则,请在适当位置添加以下标记之一(HTML 注释不会出现在最终标记中):
- 禁用所有规则:
<!-- markdownlint-disable --> - 启用所有规则:
<!-- markdownlint-enable --> - 禁用当前行的所有规则:
<!-- markdownlint-disable-line --> - 禁用下一行的所有规则:
<!-- markdownlint-disable-next-line --> - 按名称禁用一个或多个规则:
<!-- markdownlint-disable MD001 MD005 --> - 按名称启用一个或多个规则:
<!-- markdownlint-enable MD001 MD005 --> - 按名称禁用当前行的一个或多个规则:
<!-- markdownlint-disable-line MD001 MD005 --> - 按名称禁用下一行的一个或多个规则:
<!-- markdownlint-disable-next-line MD001 MD005 --> - 捕获当前规则配置:
<!-- markdownlint-capture --> - 恢复捕获的规则配置:
<!-- markdownlint-restore -->
例如:
<!-- markdownlint-disable-next-line no-space-in-emphasis -->
space * in * emphasis或:
space * in * emphasis <!-- markdownlint-disable-line no-space-in-emphasis -->或:
<!-- markdownlint-disable no-space-in-emphasis -->
space * in * emphasis
<!-- markdownlint-enable no-space-in-emphasis -->要临时禁用规则,然后恢复之前的配置:
<!-- markdownlint-capture -->
<!-- markdownlint-disable -->
any violations you want
<!-- markdownlint-restore -->默认情况下会捕获初始配置(如同每个文档都以 <!-- markdownlint-capture --> 开头),因此上述模式可以简化为:
<!-- markdownlint-disable -->
any violations you want
<!-- markdownlint-restore -->更改从注释所在的行开始生效,因此以下代码无效:
space * in * emphasis <!-- markdownlint-disable --> <!-- markdownlint-enable -->要应用于整个文件,无论注释位于何处,支持以下语法:
- 禁用所有规则:
<!-- markdownlint-disable-file --> - 启用所有规则:
<!-- markdownlint-enable-file --> - 按名称禁用一个或多个规则:
<!-- markdownlint-disable-file MD001 --> - 按名称启用一个或多个规则:
<!-- markdownlint-enable-file MD001 -->
这可用于将 markdownlint 注释“隐藏”在文件底部。
如果需要为一个文件更改一个或多个规则的配置,支持以下更高级的语法:
- 配置:
<!-- markdownlint-configure-file { options.config JSON } -->
例如:
<!-- markdownlint-configure-file { "hr-style": { "style": "---" } } -->或:
<!-- markdownlint-configure-file
{
"hr-style": {
"style": "---"
},
"no-trailing-spaces": false
}
-->这些更改应用于整个文件,无论注释位于何处。如果存在多个此类注释,则按从上到下的顺序应用。默认情况下,markdownlint-configure-file 的内容假定为 JSON,但可以使用 options.configParsers 支持其他格式。
API
Linting
异步 API 通过 import { lint } from "markdownlint/async":
/**
* 检查指定的 Markdown 文件。
*
* @param {Options | null} options 配置选项。
* @param {LintCallback} callback 回调函数 (err, result)。
* @returns {void}
*/
function lint(options, callback) { ... }同步 API 通过 import { lint } from "markdownlint/sync":
/**
* 检查指定的 Markdown 文件。
*
* @param {Options | null} options 配置选项。
* @returns {LintResults} 结果对象。
*/
function lint(options) { ... }Promise API 通过 import { lint } from "markdownlint/promise":
/**
* 检查指定的 Markdown 文件。
*
* @param {Options | null} options 配置选项。
* @returns {Promise<LintResults>} 结果对象。
*/
function lint(options) { ... }options
类型:Object
配置函数。所有属性都是可选的,但至少应设置 files 或 strings 之一以提供输入。
options.config
类型:Object 映射 String 到 Boolean | Object
配置要使用的规则。
对象键是规则名称/别名;对象值是规则的配置。值 false 禁用规则,true 启用其默认配置,传递对象值则自定义该规则。将特殊 default 规则设置为 true 或 false 会默认包含/排除所有规则。在没有配置对象的情况下,所有规则均启用。启用或禁用标签名称(如 whitespace)会影响所有具有该标签的规则。
default 规则首先应用,然后键从上到下处理,后面的值覆盖前面的值。键(包括规则名称、别名、标签和 default)不区分大小写。
示例:
{
"default": true,
"MD003": { "style": "atx_closed" },
"MD007": { "indent": 4 },
"no-hard-tabs": false,
"whitespace": false
}参见 .markdownlint.jsonc 和/或 .markdownlint.yaml 查看所有属性设置为默认值的示例配置对象。
规则集(称为“样式”)可以单独存储并作为 JSON 加载。
从 JavaScript 引用内置样式的示例:
const options = {
files: ['...'],
config: require('style/relaxed.json')
}通过 .markdownlint.json 中的 extends 实现相同功能的示例(更多信息见下文):
{
"extends": "markdownlint/style/relaxed"
}更多示例请参见 style 目录。
参见 markdownlint-config-schema.json 了解 options.config 对象的 JSON Schema。
参见 ValidatingConfiguration.md 了解如何使用 JSON Schema 验证配置。
对于更高级的场景,样式可以引用和扩展其他样式。可以使用 readConfig 和 readConfigSync 函数读取此类样式。
例如,假设有一个 base.json 配置文件:
{
"default": true
}和一个 custom.json 配置文件:
{
"extends": "base.json",
"line-length": false
}然后执行以下代码:
const options = {
config: markdownlint.readConfigSync('./custom.json')
}将合并 custom.json 和 base.json,等效于:
const options = {
config: {
'default': true,
'line-length': false
}
}options.configParsers
类型:可选 Array of Function 接受 (String) 并返回 Object
解析 markdownlint-configure-file 块内容的函数数组。
如 配置 部分所示,内联注释可用于自定义文档的 配置对象。默认使用内置的 JSON.parse,但可以指定自定义解析器。内容会传递给每个解析器函数,直到其中一个返回值(而不是抛出异常)。因此,严格的解析器应排在灵活的解析器之前。
例如:
[JSON.parse, require('toml').parse, require('js-yaml').load]options.customRules
类型:Array of Object
与默认规则集一起包含的自定义规则列表。
每个数组元素应定义一个规则。规则通常由其他包导出,但也可以本地定义。
示例:
const extraRules = require('extraRules')
const options = {
customRules: [extraRules.one, extraRules.two]
}参见 CustomRules.md 了解如何编写自定义规则。
options.files
类型:Array of String
要检查的文件列表。
每个数组元素应为单个文件(通过相对或绝对路径);通配符 由调用者负责。
示例:[ "one.md", "dir/two.md" ]
options.frontMatter
类型:RegExp
匹配文件开头找到的任何 front matter。
某些 Markdown 内容以元数据开头;此选项的默认 RegExp 忽略常见的“front matter”形式。要匹配不同的模式,请指定自定义 RegExp 或使用值 null 禁用此功能。
默认值:
/((^---[^\S\r\n\u2028\u2029]*$[\s\S]+?^---\s*)|(^\+\+\+[^\S\r\n\u2028\u2029]*$[\s\S]+?^(\+\+\+|\.\.\.)\s*)|(^\{[^\S\r\n\u2028\u2029]*$[\s\S]+?^\}\s*))(\r\n|\r|\n|$)/m忽略 YAML、TOML 和 JSON front matter,例如:
---
layout: post
title: Title
---注意:匹配必须从文件开头开始。
options.fs
类型:Object 实现 文件系统 API
在高级场景中,可能需要绕过默认的文件系统 API。如果提供了自定义文件系统实现,markdownlint 将使用该实现而不是 node:fs。
注意:唯一调用的方法是 readFile 和 readFileSync。
options.handleRuleFailures
类型:Boolean
捕获规则处理期间抛出的异常,并将问题报告为规则违规。
默认情况下,规则(或库本身)抛出的异常不会被处理,会以常规方式向上冒泡到调用者。通过将 handleRuleFailures 设置为 true,失败规则抛出的异常将由库处理,并将异常消息记录为规则违规。此设置在存在(自定义)规则遇到意外语法并失败时非常有用。启用此选项后,linting 过程可以继续并报告发现的任何违规。
options.markdownItPlugins
类型:Array of Array of Function 和插件参数
指定解析输入时要使用的其他 markdown-it 插件。插件可用于支持高级场景的额外语法和功能。已弃用。
每个顶层 Array 的项应为以下形式:
[ require("markdown-it-plugin"), plugin_param_0, plugin_param_1, ... ]注意,
markdown-it插件仅在调用markdown-it解析器时调用。内置规则均不使用markdown-it解析器,因此markdown-it插件仅在存在一个或多个使用markdown-it解析器的 自定义规则 时调用。
options.noInlineConfig
类型:Boolean
禁用使用 HTML 注释(如 <!-- markdownlint-enable -->)在 Markdown 内容正文中切换规则。
默认情况下,格式正确的内联注释可用于为文档的某些部分创建例外。将 noInlineConfig 设置为 true 会忽略所有此类注释。
options.resultVersion
类型:Number
指定返回的 result 对象的版本(参见下面的“用法”部分以获取示例)。
传递 resultVersion 为 0 对应于原始的简单格式,其中每个错误由规则名称和行号标识。已弃用
传递 resultVersion 为 1 对应于详细格式,其中每个错误包括行号、规则名称、别名、描述以及任何可用的其他详细信息或上下文。已弃用
传递 resultVersion 为 2 对应于详细格式,其中每个错误包括行号、规则名称、描述以及任何可用的其他详细信息或上下文。已弃用
传递 resultVersion 为 3 对应于详细版本 2 格式,并包含有关如何自动修复可自动修复的错误的信息。在此模式下,报告每行发生的所有错误(其他版本仅报告每个规则的第一个错误)。这是默认行为。
options.strings
类型:Object 映射 String 到 String
用于检查的标识符到字符串的映射。
当 Markdown 内容不可用为文件时,可以将其作为字符串传递。strings 对象的键用于在 result 摘要中标识每个输入值。
示例:
{
"readme": "# README\n...",
"changelog": "# CHANGELOG\n..."
}callback
类型:Function 接受 (Error, Object)
标准完成回调。
result
类型:Object
调用 result.toString() 以方便使用,或参见下面的 result 对象结构示例。将 true 传递给 toString() 会使用规则别名(如 no-hard-tabs)而不是名称(如 MD010)。
Config
options.config 配置对象简单,可以存储在文件中以提高可读性和易于重用。readConfig 和 readConfigSync 函数加载配置设置,并支持 extends 关键字引用其他文件(见上文)。
默认情况下,配置文件解析为 JSON(并命名为 .markdownlint.json)。可以提供自定义解析器来处理其他格式,如 JSONC、YAML 和 TOML。
异步 API 通过 import { readConfig } from "markdownlint/async":
/**
* 读取指定的配置文件。
*
* @param {string} file 配置文件名。
* @param {ConfigurationParser[] | ReadConfigCallback} [parsers] 解析函数。
* @param {Object} [fs] 文件系统实现。
* @param {ReadConfigCallback} [callback] 回调函数 (err, result)。
* @returns {void}
*/
function readConfig(file, parsers, fs, callback) { ... }同步 API 通过 import { readConfig } from "markdownlint/sync":
/**
* 读取指定的配置文件。
*
* @param {string} file 配置文件名。
* @param {ConfigurationParser[]} [parsers] 解析函数。
* @param {Object} [fs] 文件系统实现。
* @returns {Configuration} 配置对象。
*/
function readConfig(file, parsers, fs) { ... }Promise API 通过 import { readConfig } from "markdownlint/promise":
/**
* 读取指定的配置文件。
*
* @param {string} file 配置文件名。
* @param {ConfigurationParser[]} [parsers] 解析函数。
* @param {Object} [fs] 文件系统实现。
* @returns {Promise<Configuration>} 配置对象。
*/
function readConfig(file, parsers, fs) { ... }file
类型:String
要读取的配置文件位置。
file 相对于当前工作目录解析。如果读取后存在 extends 键,其值将作为相对于 file 的路径解析并递归加载。由 extends 引用的文件的设置首先应用,然后 file 的设置在其基础上应用(覆盖引用文件中出现的相同键)。如果 file 或 extends 路径以 ~ 目录开头,它将作为主目录的占位符。
parsers
类型:可选 Array of Function 接受 (String) 并返回 Object
解析配置文件的函数数组。
配置文件的内容传递给每个解析器函数,直到其中一个返回值(而不是抛出异常)。因此,严格的解析器应排在灵活的解析器之前。
例如:
[JSON.parse, require('toml').parse, require('js-yaml').load]fs
类型:可选 Object 实现 文件系统 API
在高级场景中,可能需要绕过默认的文件系统 API。如果提供了自定义文件系统实现,markdownlint 将使用该实现而不是调用 node:fs。
注意:唯一调用的方法是 readFile、readFileSync、access 和 accessSync。
callback
类型:Function 接受 (Error, Object)
标准完成回调。
result
类型:Object
配置对象。
Fixing
可以自动修复的规则包括一个 fixInfo 属性,该属性在 自定义规则文档 中概述。要一致地应用修复,可以使用 applyFix/applyFixes 方法,通过 import { applyFix, applyFixes } from "markdownlint":
/**
* 将指定的修复应用于 Markdown 内容行。
*
* @param {string} line Markdown 内容行。
* @param {RuleOnErrorFixInfo} fixInfo RuleOnErrorFixInfo 实例。
* @param {string} [lineEnding] 使用的行尾符号。
* @returns {string | null} 修复后的内容或 null(如果删除)。
*/
function applyFix(line, fixInfo, lineEnding = "\n") { ... }
/**
* 尽可能将指定的修复应用于 Markdown 内容。
*
* @param {string} input Markdown 内容行。
* @param {RuleOnErrorInfo[]} errors RuleOnErrorInfo 实例。
* @returns {string} 修复后的内容。
*/
function applyFixes(input, errors) { ... }使用 lint 调用的结果调用 applyFixes 可以如下所示:
import { applyFixes } from 'markdownlint'
import { lint as lintSync } from 'markdownlint/sync'
const results = lintSync({ strings: { content: original } })
const fixed = applyFixes(original, results.content)其他功能
要获取库的 语义版本,可以使用 getVersion 方法:
/**
* 获取库的(语义)版本。
*
* @returns {string} SemVer 字符串。
*/
function getVersion() { ... }调用 getVersion 很简单:
import { getVersion } from 'markdownlint'
// 显示库版本
console.log(getVersion())用法
调用 lint 并使用 result 对象的 toString 方法:
import { lint as lintAsync } from 'markdownlint/async'
const options = {
files: ['good.md', 'bad.md'],
strings: {
'good.string': '# good.string\n\nThis string passes all rules.',
'bad.string': '#bad.string\n\n#This string fails\tsome rules.'
}
}
lintAsync(options, (error, results) => {
if (!error && results) {
console.log(results.toString())
}
})输出:
bad.string: 3: MD010/no-hard-tabs 硬制表符 [列: 19]
bad.string: 1: MD018/no-missing-space-atx ATX 风格标题的井号后缺少空格 [上下文: "#bad.string"]
bad.string: 3: MD018/no-missing-space-atx ATX 风格标题的井号后缺少空格 [上下文: "#This string fails some rules."]
bad.string: 1: MD041/first-line-heading/first-line-h1 文件首行应为顶级标题 [上下文: "#bad.string"]
bad.md: 3: MD010/no-hard-tabs 硬制表符 [列: 17]
bad.md: 1: MD018/no-missing-space-atx ATX 风格标题的井号后缺少空格 [上下文: "#bad.md"]
bad.md: 3: MD018/no-missing-space-atx ATX 风格标题的井号后缺少空格 [上下文: "#This file fails some rules."]
bad.md: 1: MD041/first-line-heading/first-line-h1 文件首行应为顶级标题 [上下文: "#bad.md"]或作为同步调用:
import { lint as lintSync } from 'markdownlint/sync'
const results = lintSync(options)
console.log(results.toString())要通过基于 Promise 的调用直接检查 result 对象:
import { lint as lintPromise } from 'markdownlint/promise'
const results = await lintPromise(options)
console.dir(results, { colors: true, depth: null })输出:
{
"good.md": [],
"bad.md": [
{
"lineNumber": 3,
"ruleNames": ["MD010", "no-hard-tabs"],
"ruleDescription": "硬制表符",
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md010.md",
"errorDetail": "列: 17",
"errorContext": null,
"errorRange": [17, 1]
},
{
"lineNumber": 1,
"ruleNames": ["MD018", "no-missing-space-atx"],
"ruleDescription": "ATX 风格标题的井号后缺少空格",
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md018.md",
"errorDetail": null,
"errorContext": "#bad.md",
"errorRange": [1, 2]
},
{
"lineNumber": 3,
"ruleNames": ["MD018", "no-missing-space-atx"],
"ruleDescription": "ATX 风格标题的井号后缺少空格",
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md018.md",
"errorDetail": null,
"errorContext": "#This file fails\tsome rules.",
"errorRange": [1, 2]
},
{
"lineNumber": 1,
"ruleNames": ["MD041", "first-line-heading", "first-line-h1"],
"ruleDescription": "文件首行应为顶级标题",
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md041.md",
"errorDetail": null,
"errorContext": "#bad.md",
"errorRange": null
}
]
}与 gulp 构建系统的集成很简单:gulpfile.cjs。
与 Grunt 构建系统的集成类似:Gruntfile.cjs。
浏览器
markdownlint 也可以在浏览器中工作。
生成普通和压缩脚本:
npm run build-demo然后引用 markdownlint-browser 脚本:
<script src="demo/markdownlint-browser.min.js"></script>并按如下方式调用:
const options = {
strings: {
content: 'Some Markdown to lint.'
}
}
const results = globalThis.markdownlint.lintSync(options).toString()示例
有关如何将 markdownlint 集成到工作流中的想法,请参考以下项目或 相关工具 中的某个工具:
- .NET 文档 (搜索仓库)
- ally.js (搜索仓库)
- Apache Airflow (搜索仓库)
- Boostnote (搜索仓库)
- CodiMD (搜索仓库)
- Electron (搜索仓库)
- ESLint (搜索仓库)
- Garden React 组件 (搜索仓库)
- MDN Web 文档 (搜索仓库)
- MkDocs (搜索仓库)
- Mocha (搜索仓库)
- Pi-hole 文档 (搜索仓库)
- Reactable (搜索仓库)
- V8 (搜索仓库)
- webhint (搜索仓库)
- webpack (搜索仓库)
- WordPress (搜索仓库)
更高级的集成场景:
贡献
更多信息请参见 CONTRIBUTING.md。
发布
更多信息请参见 ReleaseProcess.md。
历史
参见 CHANGELOG.md。