NautilusTrader Markdown 风格规范:基于 markdownlint 的文档编写与自动化校验指南
【免费下载链接】nautilus_traderProduction-grade Rust-native trading engine with deterministic event-driven architecture项目地址: https://gitcode.com/GitHub_Trending/na/nautilus_trader
本文是 NautilusTrader 仓库内 Markdown 文档的编写基准(baseline)说明,适用于所有在仓库文档范围内撰写、修改 Markdown 文件的开发者与 AI 协作场景。文章以 docs/developer_guide/markdown_style.md 为骨架,结合仓库根目录的 .markdownlint.jsonc 配置、Makefile 中的check-markdown目标以及 scripts/check-markdown-tables.py 脚本,完整讲解规则层级、语法基线、各类元素的书写要求、自动化强制机制与过渡性采用策略。读完本文,你将能写出既符合 CommonMark/GFM 规范、又能通过本仓库 markdownlint 检查的文档,并理解每一条规则背后的工具实现。
规范定位:一份可复制的共享基线
markdown_style.md是一份"标准修订版(Standard revision: 1)"的共享 Markdown 基线文档,设计目标是被多个采用该文档副本的仓库共同维护。因此它明确要求:
- 各仓库的副本必须与被维护的源逐字节(byte-for-byte)保持一致;
- 仓库特有的补充内容必须写在单独的本地指南中,而不是混入共享基线。
在 NautilusTrader 中,这份仓库本地补充指南就是 docs/developer_guide/docs.md。docs.md 在开篇即声明:markdown_style.md是 Markdown 语法与格式的共享基线,.markdownlint.jsonc强制执行其机械子集,而 docs.md 只覆盖 NautilusTrader 文档特有的约定(文档类型体系、语气、MDX 组件、支持矩阵表格等),不重复基线内容。这种"共享基线 + 本地指南"的分层结构,既保证了跨仓库风格统一,又为项目保留了定制空间。
规则层级:Required、Preferred 与 Transitional
规范将每一条规则划分为三个层级,理解层级是阅读全部规则的前提:
| 层级 | 含义 | 判定标志 |
|---|---|---|
| Required(必需) | 适用于范围内每个文件,不满足即不合规 | 无条件祈使句("Use"、"Do not")或含 "must" 的表述 |
| Preferred(首选) | 存在多种合法写法时的默认选择 | 使用 "Prefer" 措辞,不影响合规判定 |
| Transitional(过渡) | 仅适用于新增或大幅编辑的指定构造 | 明确标注Transitional或描述为 transitional;既有实例可保留至单独迁移 |
此外,规范对措辞的含义边界做了精确定义:
- 含 "may" 或 "allowed" 的表述授予有限许可而非义务;任何限制该许可的条件都属于 Required;
- 仓库可以在其渲染器、生成内容或导入材料确有需要的场景下,记录更窄的本地例外。
语言与扩展:CommonMark 为基,GFM 为扩展
规范对 Markdown 方言的选择非常明确:
- 以CommonMark作为基础规范;
- 使用GitHub Flavored Markdown(GFM)来支持表格、任务列表、删除线和自动链接;
- 额外的 front matter、Markdown 扩展或渲染器组件,仅当仓库有文档说明并支持时才可使用;
- 禁止引入依赖未文档化渲染器扩展的语法。
规范还特意提醒:文首链接的两个规范是"参考资料"而非"常规前置条件"——只有遇到本地指南、上下文内容和 markdownlint 都无法回答的具体解析器/渲染器歧义时,才需要打开它们查阅。这也意味着绝大多数日常写作不需要翻阅规范原文。
强制机制:从配置文件到命令行
风格规范本身是"意图",而自动化工具是其"机械子集的执行者"。仓库的强制链路由三层构成。
1. 仓库级 markdownlint 配置
仓库根目录的 .markdownlint.jsonc 采用"默认全关("default": false)+ 显式开启"的策略,即只启用仓库确认需要的规则。已启用的规则及其配置覆盖了本规范的所有机械性要求,例如:
MD001/heading-increment:标题层级每次只能递增一级;MD003/heading-style:ATX 标题风格(style: "atx");MD004/ul-style:无序列表用-(style: "dash");MD009/no-trailing-spaces:禁止行尾空格,br_spaces: 0同时禁止用尾随空格制造硬换行,并启用strict;MD012/no-multiple-blanks:连续空行最多 1 行;MD031/MD032:围栏代码块与列表前后必须有空行;MD034/no-bare-urls:禁止裸 URL;MD035/hr-style:分隔线风格固定为---;MD046/code-block-style:代码块使用围栏风格(fenced);MD049/MD050:强调与加粗统一使用星号(*italic*、**bold**);MD055/MD056/MD058:表格必须有首尾竖线、列数一致、表格前后有空行;MD059/descriptive-link-text:链接文本必须具有描述性;MD060/table-column-alignment:表格列对齐风格为aligned。
2. make check-markdown 目标
Makefile 中的check-markdown目标把两条检查串联起来:
check-markdown: #-- Lint Markdown with markdownlint-cli2 and check table delimiter padding @$(MARKDOWNLINT) --config .markdownlint.jsonc $(MARKDOWNLINT_FILES) @python3 -B scripts/check-markdown-tables.py $(MARKDOWN_FILES)- 第一条命令用
markdownlint-cli2配合.markdownlint.jsonc检查全部 Markdown 文件,其版本通过 pre-commit hook 的 rev 固定(Makefile 中从 pre-commit 配置解析MARKDOWNLINT_VERSION); - 第二条命令运行 scripts/check-markdown-tables.py,专门规整表格的列宽填充与分隔行内边距。
3. pre-commit 钩子与生成文件
normalize markdown table paddingpre-commit 钩子会自动把表格重写为规范要求的填充形式(最宽单元格 + 两侧各一空格),因此手写时无需人工数空格;- 规范同时要求:不要手工编辑生成的 Markdown,应修改其源文件后重新运行生成器;生成的、导入的第三方文档与渲染器夹具可使用文档化的仓库排除规则。
4. 配置与规范冲突的处理
规范给出了三条明确准则:
- 遵循仓库的
.markdownlint.jsonc或等价本地配置; - 将本规范视为"预期风格",将 markdownlint 视为其机械子集的自动化执行;
- 规范与本地配置之间存在未文档化冲突时,视为需要解决的漂移(drift),而不是默认的例外;
- 确保仓库 lint 范围内所有作者编写的 Markdown 都通过配置的 Markdown 检查。
标题:ATX 风格与大小写约定
- 使用 ATX 标题(
#、##、###等),对应MD003; - 每篇文档的第一个 Markdown 标题必须是唯一的 H1,对应
MD025/single-title; - H1 使用 Title Case(每个实词首字母大写);
- H2 及以下使用 Sentence case(仅首字母与专有名词大写);
- 保持逻辑层级,不跳级(对应
MD001); - 每个标题上下各留一个空行(对应
MD022,lines_above: 1、lines_below: 1)。
docs.md 补充了本地约定:无论标题层级,专有名词(产品名、技术名、公司名、缩写)始终大写,这一条优先于大小写规则。
段落与换行
- 段落之间用一个空行分隔;
- 不要出现连续空行(对应
MD012,maximum: 1); - 散文行长度目标为100–120 字符(Preferred 级);
- 优先在自然断点换行,避免一行末尾只留 1–3 个词;
- 代码块、表格和长链接目标可以超出该目标(Allowed)。
值得注意的是,docs.md 中 NautilusTrader 的源码注释规范要求行宽低于 100 字符,而 Markdown 散文的行宽目标稍宽(100–120),两者适用对象不同,不应混淆。
列表:破折号与"全部写 1."
- 无序列表项统一使用
-(对应MD004的dash风格;NautilusTrader 的编码规范同样在 Rust/Python/Shell 注释中坚持用-而非*); - 仅当顺序有意义时才使用有序列表;
- Transitional 规则:有序列表的每个源行都写
1.,由渲染器自动编号(对应MD029的行为,但该规则当前仍被禁用,见下文"过渡性采用"); - 列表的缩进与间距与本地 markdownlint 配置保持一致(
MD007配置为 2 空格缩进、首层不缩进、MD030配置列表标记后 1 空格); - 列表前后各留一个空行(对应
MD032)。
示例(规范原文):
- First item - Second item 1. First step 1. Second stepAdmonitions(提示块):GitHub Alert 与可移植回退
Admonition 的使用必须遵循"只使用仓库有文档说明且能渲染的语法"这一总原则,具体分三种情形:
- 仓库文档化并支持 GitHub Alerts 时:使用 GitHub blockquote alert 形式,类型限定为
NOTE、TIP、IMPORTANT、WARNING、CAUTION之一; - 该扩展不存在或未确认支持时:使用可移植的 blockquote + 粗体文本标签形式;
- 多段落 admonition:每个内容行和空行续行都要以
>开头;一个裸空行即结束该 admonition。
规范还强调两点:类型标签必须在源码和渲染输出中都保留(不能只靠颜色或图标传达含义);在窄幅编辑中要保留已确立且受支持的既有 admonition 语法,不要仅为套用回退形式而转换它。
> [!WARNING] > Back up the database before running the migration.可移植回退形式:
> **Warning:** Back up the database before running the migration.需要注意:NautilusTrader 的文档站(fumadocs,见 docs.md)在 MDX 环境中使用的是:::note、:::info、:::tip、:::warning、:::danger这组 admonition 语法,并警告"过度使用 admonition 会削弱其影响力"。这两套语法服务于不同场景——markdown_style.md是面向所有采用该基线的仓库的可移植基准,而 docs.md 的 MDX admonition 是本地文档站的既定扩展,写作时需根据目标文件所在的渲染环境选择正确的形式。
表格:GFM 管道表格与对齐规范
表格是 NautilusTrader 文档中出现频率最高的元素之一(能力矩阵、支持表、参数表),规范与工具对它的约束也最细:
- 使用 GFM 管道表格;
- 包含首尾竖线(对应
MD055的leading_and_trailing风格); - 竖线垂直对齐;
- 每列填充到最宽单元格宽度 + 两侧各一空格(与 Prettier 的默认表格输出一致)。
MD060只检查竖线对齐、不检查单元格内容宽度,因此列可以比内容更宽; - 分隔行单元格两侧也要填充空格(
| ----- |而不是|-----|),MD060同样不检查此项; - 文本列默认左对齐,数字列按需右对齐(分隔行右侧冒号
----:表示右对齐),分隔行与预期的渲染对齐方式保持一致; - 避免使用 HTML 表格,除非 Markdown 无法表达所需结构或仓库有文档说明。
规范原文示例:
| Name | Value | | ----- | ----: | | Alpha | 42 | | Beta | 17 |表格的自动化规整
scripts/check-markdown-tables.py 提供了比 markdownlint 更进一步的保障,它的实现细节印证了规范中的陈述:
- 使用正则
DELIMITER_RE识别分隔行,并用围栏检测(FENCE_RE)跳过代码块内的表格; - 按列宽计算时使用
utf16_width(对 BMP 之外的字符(如✓)按宽度 2 计数),确保✓、-这类支持矩阵符号不会破坏对齐; cell_alignment根据单元格两侧空格数推断左/右/居中对齐,分隔行冒号位置决定渲染对齐;- 规整结果为"最宽单元格 + 2"的列宽、
MIN_DASHES = 3的最小分隔线长度,与规范"每列填充到最宽单元格加一空格"完全对应; - 脚本发现需要规整的文件时返回退出码 1,从而让
check-markdown目标失败并提示normalized table column widths。
docs.md 还补充了支持矩阵的语义约定:用✓表示支持、用-表示不支持(而非✗),不支持的说明用斜体*Not supported*强调,并按原因细化——*Not supported by <venue>*表示交易所能力缺口、*Not currently implemented*表示适配器尚未实现。
代码:围栏、语言标注与行内代码
- 使用反引号围栏代码块,不用缩进代码块(对应
MD046的fenced风格;MD048规定围栏符号为反引号); - Transitional 规则:每个开围栏都必须标注语言;无更具体语法的纯文本或输出使用
text; - 当文档本身要展示带围栏的 Markdown 时,使用更长的外层围栏(例如四反引号包三反引号);
- 命令、文件名、函数、类型、环境变量、配置键和标识符使用行内代码。
嵌套围栏示例:
```rust fn main() { println!("Hello"); }docs.md 对代码引用还有一条实用约定:引用代码位置时使用 `file_path::function_name` 或 `file_path::ClassName` 形式,而**不用行号**——行号会随代码变更而过时。这与本文章前面引用 Makefile 目标、脚本函数的方式一致。 ## 强调、分隔线与链接图片 - 强调用 `*italic*`,强强调用 `**bold**`(对应 `MD049`/`MD050` 的 `asterisk` 风格); - 避免无意义的强调; - 分隔线使用三个连字符 `---`(对应 `MD035` 的 `hr-style`); - 链接使用描述性文本(对应 `MD059`,例如用"账户配置文档"而非"点击这里"); - 优先行内链接;同一目标在文档中出现多次时,优先引用式链接(对应 `MD052`/`MD053` 对引用定义的要求); - 避免裸 URL(对应 `MD034`); - 渲染器支持时保持内部链接为相对路径; - 图片必须有有用的替代文本(alt text),纯装饰图片才允许使用空 alt(对应 `MD045`)。 ## HTML:优先可移植 Markdown - 优先使用可移植的 Markdown 语法,而非原始 HTML; - 仅当 Markdown 无法表达所需结果、或仓库有文档说明该元素/组件时才使用原始 HTML; - 在编辑周边内容时,保留受支持的 front matter、MDX 组件、围栏属性和其他仓库扩展(这些在 NautilusTrader 的 fumadocs 文档站中广泛存在,例如 docs.md 记录的 `Tabs`、`Steps`、`Accordions`、`Files`、`Cards`、`TypeTable` 组件)。 ## 文件级别要求:编码、换行与空白 - 使用 **UTF-8** 编码; - 使用 **LF** 行尾(对应 `check-markdown-tables.py` 写入时显式指定 `newline="\n"`); - 文件以**一个换行符结尾**(对应 `MD047`); - 不遗留行尾空格,也不使用尾随空格制造 Markdown 硬换行(对应 `MD009` 的 `br_spaces: 0`)。 ## 编辑指引:窄幅修改与结构重构的不同策略 规范针对"创建或修改 Markdown"给出了场景化的操作建议: - **窄幅修改(narrow edits)**:保留周边风格,直接用 markdownlint 检查即可,不必通读整份指南——除非两者都留下具体未决问题; - **创建或大幅重构文档之前**:只查阅仓库本地 Markdown 指南的相关章节(对 NautilusTrader 而言是 docs.md 与 markdown_style.md 的对应小节); - **保留既有文档结构**,除非任务本身要求变更; - 格式与周边内容和受支持的渲染器扩展保持一致; - **不要重排无关章节**; - 可用时运行仓库的聚焦 Markdown 检查(即 `make check-markdown`)。 这套指引同样适用于 AI 辅助写作场景:小范围修订交给 linter 把关,大范围创作先对齐本地风格指南,始终把变更面控制在任务范围内。 ## 过渡性采用(Transitional adoption):规则与迁移的平衡 规范最后说明了哪些规则立即生效、哪些处于过渡状态: - **ATX 标题通过 `MD003` 立即强制执行**(非过渡); - **重复的 `1.` 有序列表标记**和**开围栏语言标注**是过渡性规则——它们对应的 `MD029`(有序列表前缀)与 `MD040`(围栏代码语言)**在既有文档完成单独机械迁移之前保持禁用**; - 因此,不要为了迁移那些既有构造而扩大一次窄幅文档修改的范围。 这一设计与 `.markdownlint.jsonc` 的配置完全吻合:`MD003` 处于开启状态,而 `MD029`、`MD040` 未出现在启用清单中。它体现了规范制定的核心理念——**风格演进应当是"新增内容先守新规、存量内容分批迁移",而不是一次性大规模重写**,既保证了向前的一致性,又避免了对既有文档的破坏性变更。 ## 小结:一条从规范到工具的完整链路 NautilusTrader 的 Markdown 风格管理是一套自洽的工程体系: 1. **意图层**:[docs/developer_guide/markdown_style.md](https://link.gitcode.com/i/a180ffb7d2b019812178e043c6647c7e) 定义共享基线(规则层级、语法选择、元素写法); 2. **本地化层**:[docs/developer_guide/docs.md](https://link.gitcode.com/i/f36463b1018f39ae057e7dcf0922efac) 定义 NautilusTrader 文档特有约定(文档类型、语气、MDX 组件、支持矩阵); 3. **机械层**:[.markdownlint.jsonc](https://link.gitcode.com/i/b539fbf43efe8d3462c23ed78c64cfe0) 以"默认关闭 + 显式启用"方式固化规则子集; 4. **执行层**:[Makefile](https://link.gitcode.com/i/fe64e26fff4e32bdd7e81cef055be655#L654-L658) 的 `check-markdown` 串联 markdownlint-cli2 与 [scripts/check-markdown-tables.py](https://link.gitcode.com/i/a2b7cbe199552f293ee9a5e65e9b8769),配合 pre-commit 钩子实现提交前自动规整。 对贡献者而言,日常写作只需遵循两条主线:**新增内容按规范书写(过渡规则对新内容立即生效)**,**提交前运行 `make check-markdown` 并通过**。把握住"共享基线 + 本地指南 + 自动化强制"的分层思想,就能在保持文档风格统一的同时,让每一次文档变更都可验证、可追踪。【免费下载链接】nautilus_traderProduction-grade Rust-native trading engine with deterministic event-driven architecture项目地址: https://gitcode.com/GitHub_Trending/na/nautilus_trader
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考