关于 writing-comments
这项面向贡献者的技能用于编写和维护 Astro TypeScript 与 JavaScript 源码注释。它区分注释类型,规定文档惯例,并指出应避免的写法。
主要功能
- 01区分概览、条目和行内注释职责
- 02清晰记录行为与理由
- 03避免变更历史和面向审查者的注释
- 04为变通方案附上问题链接
- 05用删除测试检查注释
适用场景
- 01编写面向贡献者的源码注释
- 02审查或修改现有 Astro 注释
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ withastro/ astro --skill writing-comments安装后在 Claude Code 中输入/writing-comments确认已加载。
附带文件evals/evals.json
详细介绍
编写注释
目的
此仓库中的注释是写给数月或数年后阅读它们的贡献者的。届时,他们并不了解你现在掌握的任何背景信息。本规范说明读者是谁、各类注释的用途,以及哪些写法是禁止的。
适用范围
本规范适用于 TypeScript/JavaScript 源码中面向贡献者的注释,不适用于面向最终用户的文档:
packages/astro/src/types/public/config.ts和packages/astro/src/core/errors/errors-data.ts中带有@docs标记的 JSDoc 块会由外部docgen工具抓取,并发布到 Astro 文档网站。此类文档请遵循packages/astro/src/core/errors/README.md中的说明,并请文档团队审核——当types/public/**发生更改时,CI 会重新生成参考文档。types/public/**中的其他 JSDoc 会通过编辑器 IntelliSense 呈现给用户。编写时应面向使用 Astro 构建网站的用户,而非阅读源码的贡献者。
以下内容均针对贡献者在 HEAD 版本中阅读的源码。
读者
注释应面向熟悉 TypeScript、但无法获取你当前背景信息的 Astro 贡献者:他们看不到这段对话、拉取请求、议题或差异。他们只能看到 HEAD 版本的仓库。
由此直接得出两点:
- 切勿叙述更改历史。“现在”“以前”“不再”“新方案”等词在 HEAD 中毫无意义,因为那里只有一种方案。应说明代码如何工作,而非它如何演变而来。(
@deprecated提示除外——请参阅本代码库中的约定——因为它描述了读者需要了解的契约未来状态。) - **切勿直接对审核者说话。**为更改辩护的注释(例如“此处正确处理了 X”)应放在拉取请求说明中,而不是源码中。注释必须说明代码当前状态的合理性,并且长期有效。
三类注释,各司其职
| 类型 | 语法 | 用途 | 内容 |
|---|---|---|---|
| 文件/模块概述 | 文件顶部的 /** */ | 说明 | 模块的存在原因、其定义的概念和术语、各部分之间的关系、设计依据 |
| 条目文档 | 声明正上方的 /** */ | 参考说明 | 契约:行为、参数、返回值、抛出的错误、不变量。保持中立、客观 |
| 行内注释 | 函数体内的 // | 说明原因 | 仅说明代码本身无法表达的内容:限制、变通方案(附议题链接)、不明显的耦合 |
不要混淆这些用途。实现细节不应放在 /** */ 契约中——应在函数体内使用 // 注释。契约也不应散落在行内注释中——应写在声明上方。
行为文档
需要为条目编写文档时,应面向人类读者描述契约,而不是翻译实现。这并不意味着每个函数都要写 JSDoc;名称、类型和结构本身应能清楚地表达直观行为。
- 用通俗的语言说明函数返回什么或实现什么。
- 使用简短或中等长度的句子,每句只表达一个主要观点。
- 调用方不需要了解的 Astro 内部术语应避免使用。如果必须使用某个技术术语,请在同一段中加以解释。
- 描述可能让调用方意外的可见限制:回退行为、工作量限制、含糊不清的结果、重载顺序、副作用,以及在什么条件下会返回
undefined、null、空结果或其他不确定值。 - 如果调用方需要区分或处理抛出的错误,请记录这些错误。
- 除非调用方需要了解实现细节才能理解行为或安全地使用 API,否则不要描述这些细节。
如果行为取决于签名无法清楚表达的关系,请添加示例。常见的 Astro 和 TypeScript 场景包括:
- 选择了哪个重载;
- 参数如何对应可选参数或剩余参数;
- 哪个公开的 Astro 入口点会公开在其他位置实现或重新导出的符号;
- 对于含糊的路由、不完整的配置或缺失的内容,如何执行回退;
- 结果的含义无法从其类型中明显看出。
在代码块前用文字引出示例。说明示例演示的内容和预期结果。代码片段应尽量简洁、独立,并从 Astro 用户或负责该契约的内部调用方的视角编写。
模块文档应描述持久的概念、架构边界或设计原因。不要逐一列出导出项来概括文件;随着符号添加或重命名,这类清单会过时。如果模块没有值得说明的持久概念,请用一句简短描述,或不写概述。
删除测试
编写任何注释前,先问:这条信息是否无法从代码本身得知?
- 如果名称、类型或结构已经表达了这条信息,就不要写注释。如果名称未能表达清楚,请改进名称。
- 确实需要注释的信息包括:不变量、理由、与其他位置代码的耦合、带链接的变通方案、依赖项令人意外的行为,以及模块定义的专业术语。
之后编辑时也应反向应用同一项测试:不再符合测试的注释应删除,而不是留着逐渐过时。
为变通方案链接相关议题
本代码库始终会为变通方案标注其出处。任何说明变通方案、HACK、回归保护措施或依赖项令人意外的行为的注释,都必须链接到促成该做法的 GitHub issue 或 PR。有了链接,后续读者才能判断该变通方案是否仍有必要。
// Handle recommended nanostores. Only @nanostores/preact is required from our testing!
// Full explanation and related bug report: https://github.com/withastro/astro/pull/3667
'@nanostores/preact',
没有链接的变通方案与错误无从区分。
禁止的模式
叙述下一行代码。 看到就删:
// Increment the generation counter
generation += 1;
叙述变更历史。 改写为现在时的理由说明:
// BAD: We now resolve lightningcss from the user's root instead of ours.
// GOOD: lightningcss is an optional peer dep, so it resolves from the user's project root.
面向审阅者的辩解。 将理由放到 PR 中:
// BAD: This correctly handles the multi-encoded path from the bug report.
// GOOD: A path still encoded after MAX_DECODE_ITERATIONS is rejected, so
// middleware and routing can never disagree on the decoded path.
重复 JSDoc。 只是改述声明名称的 /** */ 注释块毫无信息量:
// BAD:
/** Compiles the styles. */
function compileStyles(...)
// GOOD:
/** Rewrites relative `url()` references in `css` against `base`, leaving
* absolute and data URLs untouched. */
function compileStyles(...)
含糊其辞。 “某些情况”“各种原因”“处理边缘情况”“等等”等说法——要么明确指出具体内容,要么删掉句子。
表情符号。 源代码中禁止使用,包括注释(全仓库政策)。
随意添加章节横幅(// ----- helpers -----、// ==== TYPES ====)。
本代码库没有使用 // #region 折叠区域的惯例;不要添加横幅。如果文件长到让你想加横幅,这说明应该拆分文件,而不是加以装饰。
此代码库中的约定
JSDoc 标签。 @param name - description、@returns 和 @throws 用于说明约定。仅当签名本身存在歧义时,才为类型加上花括号(@returns {Promise<string>})。对于不明显的用法,使用带围栏的 ```js 代码块编写 @example。
交叉引用。 使用 {@link Symbol} / {@linkcode Symbol},而不是直接写名称,这样重命名时会更新引用,编辑器也能跳转到目标。
@internal。 标记不属于公共接口的 API。这只是一项约定——这里没有 typedoc 或 api-extractor 来移除它——因此它用于记录意图,但不能替代访问修饰符。
@deprecated。 说明迁移方式,然后说明移除时间范围:
/** @deprecated Use the instance method `cookies.consume()` instead. This will be removed in Astro 7 */
明确说明应改用什么,而不只是说该符号已弃用。这条关于未来的说明属于读者需要了解的约定信息,不是禁止提及的变更历史叙述。
TODO。 对于延期工作,使用 // TODO:;如果有跟踪该工作的议题,请附上链接。对于受破坏性变更窗口限制的工作,使用既定写法 // TODO: remove in Astro <N>。此代码库中没有 FIXME——请勿引入。
编辑现有代码
- 保留现有注释。如果你的更改改变了行为,请扩展或修正具体说明,切勿用笼统文本替换。删掉来之不易的上下文,比留下一条稍显过时的注释更糟。
- 如果你的更改导致某条注释不再正确,请在同一 diff 中修正。过时的注释比没有注释更糟。
- 保持与周围内容相同的详略程度。文档详尽的模块中,新增内容也应达到同等详尽程度;不要给注释稀少的模块大量添加注释。
完成前的自查
完成任何涉及注释的任务后,请脱离代码更改,重新阅读 仅限 diff 中的注释:
- 每条注释是否都通过了删除测试?
- 是否有注释提及对话、更改本身或审阅者?
- 每项变通方案是否都链接到对应议题或 PR?
- 没有看到 diff 的读者能否理解每条注释?
修正或删除不符合要求的内容。默认选择删除;缺少注释的代价低于误导性注释。
参考资料
- Diátaxis —— 上述解释 / 参考 / 原理划分背后的框架。
packages/astro/src/core/errors/README.md—— 关于带有@docs标签的错误条目,这些条目属于面向最终用户的文档。- TSDoc —— TypeScript 文档注释的标签参考。