writing-comments
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWriting Comments
编写注释
Purpose
目的
Comments in this repository are read by contributors, months or years after
they were written, with none of the context you have right now. This skill
defines who that reader is, what each kind of comment is for, and which patterns
are banned.
本仓库中的注释会在编写数月或数年后被贡献者阅读,他们不具备你当下拥有的任何上下文。本指南定义了目标读者、各类注释的用途,以及禁用的模式。
Scope Boundary
范围边界
This skill governs contributor-facing comments in the TypeScript/JavaScript
source. It does not apply to end-user documentation:
- JSDoc blocks tagged in
@docsandpackages/astro/src/types/public/config.tsare scraped by an externalpackages/astro/src/core/errors/errors-data.tstool and published to the Astro docs website. Followdocgenfor those, and get docs-team review — CI regenerates the reference whenpackages/astro/src/core/errors/README.mdchanges.types/public/** - Other JSDoc across is surfaced to users through editor IntelliSense. Write it for Astro users building a site, not for contributors reading the source.
types/public/**
Everything below is about the source a contributor reads at HEAD.
本指南管控TypeScript/JavaScript源码中面向贡献者的注释,不适用于终端用户文档:
- 和
packages/astro/src/types/public/config.ts中标记了packages/astro/src/core/errors/errors-data.ts的JSDoc块会被外部@docs工具抓取,并发布到Astro文档网站。这类注释请遵循docgen的规范,并需获得文档团队的审核——当packages/astro/src/core/errors/README.md目录内容变更时,CI会重新生成参考文档。types/public/** - 目录下的其他JSDoc会通过编辑器的IntelliSense展示给用户。请面向构建站点的Astro用户编写,而非阅读源码的贡献者。
types/public/**
以下所有内容均针对贡献者在HEAD版本中阅读的源码。
The Reader
目标读者
Write for an Astro contributor who is competent in TypeScript but has no
access to your current context: not this conversation, not the pull request,
not the issue, not the diff. They see only the repository at HEAD.
Two consequences follow directly:
- Never narrate change history. Words like "now", "previously", "no
longer", "the new approach" are meaningless at HEAD, where only one approach
exists. State how the code works, not how it came to be. (A notice is the exception — see Conventions — because it describes the contract's future, which the reader needs.)
@deprecated - Never address the reviewer. A comment that argues your change is correct ("this properly handles X") belongs in the PR description, not in the source. The comment must justify the code as it stands, permanently.
请面向精通TypeScript但无法获取你当前上下文的Astro贡献者编写注释:他们看不到本次对话、PR、Issue或代码差异,只能看到HEAD版本的仓库内容。
由此直接得出两个结论:
- 切勿叙述变更历史。像“现在”“之前”“不再”“新方案”这类词汇在HEAD版本中毫无意义,因为此时只存在一种实现方式。请说明代码的工作方式,而非它的演变过程。(注释是例外——详见本代码库约定——因为它描述了合约的未来状态,这是读者需要了解的信息。)
@deprecated - 切勿针对评审者编写。诸如“这能正确处理X场景”这类为变更正确性辩护的注释应放在PR描述中,而非源码里。注释必须永久证明当前代码的合理性。
Three Kinds of Comments, Three Different Jobs
三类注释,三种不同用途
| Kind | Syntax | Job | Contains |
|---|---|---|---|
| File / module overview | | Explanation | Why the module exists, the concepts and terms it defines, how the pieces relate, design rationale |
| Item docs | | Reference | The contract: behavior, parameters, return value, thrown errors, invariants. Neutral and factual |
| Inline comments | | Rationale | Only what the code cannot say: constraints, workarounds (with issue links), non-obvious coupling |
Do not mix the jobs. Implementation details do not belong in the
contract — put them as comments inside the body. The contract does not
belong scattered across inline comments — put it on the declaration.
/** *///| 类型 | 语法格式 | 用途 | 包含内容 |
|---|---|---|---|
| 文件/模块概述 | 文件顶部的 | 解释说明 | 模块存在的原因、定义的概念与术语、各部分的关联、设计思路 |
| 条目文档 | 声明上方的 | 参考说明 | 合约内容:行为、参数、返回值、抛出的错误、不变量。内容需中立且客观 |
| 行内注释 | 代码块内部的 | 原理说明 | 仅包含代码无法表达的信息:约束条件、临时解决方案(需附带Issue链接)、非直观的耦合关系 |
请勿混淆用途。实现细节不属于合约注释的范畴——应放在代码块内部的注释中。合约内容不应分散在行内注释中——应放在声明上方。
/** *///Behavior Documentation
行为文档编写
When item documentation is warranted, write the contract for a human reader,
not as a translation of the implementation. This does not require JSDoc for
every function; names, types, and structure should carry straightforward
behavior on their own.
- Start with a plain-language description of what the function returns or accomplishes.
- Use short or medium-length sentences with one main idea each.
- Avoid internal Astro jargon when callers do not need it. If a technical term is necessary, explain it in the same paragraph.
- Describe caller-visible caveats that can be surprising: fallback behavior,
work limits, ambiguous results, overload ordering, side effects, and the
conditions that return ,
undefined, an empty result, or another indeterminate value.null - Document thrown errors when callers are expected to distinguish or recover from them.
- Do not describe implementation details unless callers need them to understand the behavior or use the API safely.
Add an example when behavior depends on a relationship the signature cannot
show clearly. Common Astro and TypeScript cases include:
- which overload is selected;
- how arguments map to optional or rest parameters;
- which public Astro entrypoint exposes a symbol that is implemented or re-exported elsewhere;
- fallback behavior for ambiguous routes, incomplete configuration, or missing content;
- a result whose meaning is not obvious from its type.
Introduce the example in prose before the code block. State what it demonstrates
and what result is expected. Keep snippets minimal, self-contained, and written
from the perspective of an Astro user or the internal caller that owns the
contract.
Module documentation should describe a durable concept, architectural boundary,
or design reason. Do not list individual exports merely to summarize the file;
such inventories become stale as symbols are added or renamed. If a module has
no durable concept to explain, use a brief one-line description or no overview.
当需要编写条目文档时,请为人类读者编写合约,而非对实现逻辑的直译。并非每个函数都需要JSDoc;函数名、类型和结构应能直接体现简单明了的行为。
- 以平实语言描述函数的返回结果或实现的功能开篇。
- 使用短句或中等长度的句子,每句表达一个核心观点。
- 当调用者无需了解Astro内部术语时,避免使用。若必须使用技术术语,请在同一段落中解释。
- 描述调用者可能会感到意外的可见注意事项:回退行为、工作限制、模糊结果、重载顺序、副作用,以及返回、
undefined、空结果或其他不确定值的条件。null - 当期望调用者区分或从错误中恢复时,需记录抛出的错误。
- 除非调用者需要了解实现细节才能理解行为或安全使用API,否则请勿描述实现细节。
当行为依赖于签名无法清晰展示的关系时,请添加示例。Astro和TypeScript中的常见场景包括:
- 选择哪个重载;
- 参数如何映射到可选参数或剩余参数;
- 哪个公开的Astro入口点暴露了在其他地方实现或重新导出的符号;
- 模糊路由、不完整配置或缺失内容的回退行为;
- 类型无法体现其含义的结果。
在代码块前用 prose 介绍示例,说明示例展示的内容和预期结果。保持代码片段简洁、独立,并从Astro用户或拥有合约的内部调用者的角度编写。
模块文档应描述持久的概念、架构边界或设计原因。请勿仅为总结文件而列出单个导出项;此类清单会随着符号的添加或重命名而过时。如果模块没有需要解释的持久概念,请使用简短的单行描述或不添加概述。
The Deletion Test
删除测试
Before writing any comment, ask: does this state something the reader cannot
recover from the code itself?
- If the information is already carried by names, types, or structure, do not write the comment. If the name fails to carry it, improve the name.
- Information that legitimately needs a comment: an invariant, a rationale, a coupling to code elsewhere, a workaround with a link, surprising behavior of a dependency, a term of art the module defines.
When editing later, the same test applies in reverse: a comment that no longer
passes it should be deleted, not left to rot.
编写任何注释前,请自问:这条注释所陈述的信息是读者无法从代码本身中获取的吗?
- 如果信息已通过命名、类型或结构体现,则无需编写注释。如果命名未能体现,请改进命名。
- 确实需要注释的信息:不变量、设计思路、与其他代码的耦合关系、带链接的临时解决方案、依赖项的意外行为、模块定义的专业术语。
后续编辑时,同样适用反向测试:不再通过测试的注释应删除,而非保留至过时。
Link to the Issue for Workarounds
临时解决方案需链接Issue
This codebase consistently anchors workarounds to a source. Any comment that
explains a workaround, a , a regression guard, or surprising behavior of a
dependency must link the GitHub issue or PR that motivates it. The link is
what lets a future reader tell whether the workaround is still needed.
HACKts
// 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',A workaround with no link is indistinguishable from a mistake.
本代码库始终为临时解决方案锚定来源。任何解释临时解决方案、、回归防护或依赖项意外行为的注释必须链接相关的GitHub Issue或PR。链接能让未来的读者判断该临时解决方案是否仍有必要。
HACKts
// 处理推荐的nanostores。根据我们的测试,仅需@nanostores/preact!
// 完整说明及相关Bug报告:https://github.com/withastro/astro/pull/3667
'@nanostores/preact',没有链接的临时解决方案与错误代码无法区分。
Banned Patterns
禁用模式
Narrating the next line. Delete these on sight:
ts
// Increment the generation counter
generation += 1;Change-history narration. Rewrite as present-tense rationale:
ts
// 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.Reviewer-addressed justification. Move the argument to the PR:
ts
// 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.Restated JSDoc. A block that rewords the declaration name says nothing:
/** */ts
// BAD:
/** Compiles the styles. */
function compileStyles(...)
// GOOD:
/** Rewrites relative `url()` references in `css` against `base`, leaving
* absolute and data URLs untouched. */
function compileStyles(...)Vague hedging. "Some cases", "various reasons", "handles edge cases",
"etc." — either name them or drop the sentence.
Emojis. Banned in source, comments included (repo-wide policy).
Ad-hoc section banners (, ).
This codebase has no folding convention; do not add banners. If a
file is long enough that you reach for one, that is a signal to split the file,
not to decorate it.
// ----- helpers -----// ==== TYPES ====// #region叙述下一行代码。看到此类注释请直接删除:
ts
// 递增生成计数器
generation += 1;叙述变更历史。改写为现在时态的原理说明:
ts
// 错误示例:我们现在从用户根目录而非我们的目录解析lightningcss。
// 正确示例:lightningcss是可选的peer依赖,因此从用户项目根目录解析。针对评审者的辩护内容。将论点移至PR描述中:
ts
// 错误示例:这能正确处理Bug报告中的多重编码路径。
// 正确示例:经过MAX_DECODE_ITERATIONS后仍编码的路径会被拒绝,因此中间件和路由永远不会对解码路径产生分歧。重复JSDoc内容。仅重述声明名称的块毫无意义:
/** */ts
// 错误示例:
/** 编译样式。 */
function compileStyles(...)
// 正确示例:
/** 将css中相对的`url()`引用根据`base`重写,绝对URL和data URL保持不变。 */
function compileStyles(...)模糊的措辞。“某些情况”“各种原因”“处理边缘情况”“等等”——要么明确说明,要么删除句子。
表情符号。源码(包括注释)中禁用(仓库全局政策)。
临时章节横幅(、)。本代码库没有折叠约定;请勿添加横幅。如果文件长到需要使用横幅,这是拆分文件的信号,而非装饰文件。
// ----- helpers -----// ==== TYPES ====// #regionConventions in This Codebase
本代码库约定
JSDoc tags. , , and state the
contract. Brace-wrap a type () only when the
signature alone is ambiguous. Use with a fenced block for
non-obvious usage.
@param name - description@returns@throws@returns {Promise<string>}@example```jsCross-references. Use / rather than a
bare name, so a rename updates the reference and editors can jump to the target.
{@link Symbol}{@linkcode Symbol}@internal@deprecatedts
/** @deprecated Use the instance method `cookies.consume()` instead. This will be removed in Astro 7 */Say what to use instead, not merely that the symbol is deprecated. This
future-tense note is contract information the reader needs, not banned
change-history narration.
TODO. Use for deferred work; link an issue when one tracks it.
For work gated on a breaking-change window, use the established idiom
. There is no in this codebase — do not
introduce it.
// TODO:// TODO: remove in Astro <N>FIXMEJSDoc标签。、和用于声明合约。仅当签名本身不明确时,才用大括号包裹类型()。对于非直观用法,使用并搭配 fenced 块。
@param name - description@returns@throws@returns {Promise<string>}@example```js交叉引用。使用 / 而非裸名,这样重命名时引用会自动更新,编辑器也能跳转到目标位置。
{@link Symbol}{@linkcode Symbol}@internal@deprecatedts
/** @deprecated 改用实例方法`cookies.consume()`。此API将在Astro 7中移除 */请说明替代方案,而非仅标记符号已废弃。这个未来时态的说明是读者需要的合约信息,不属于禁用的变更历史叙述。
TODO。使用标记待完成工作;如有相关Issue,请附带链接。对于需在重大变更窗口处理的工作,请使用既定写法。本代码库中没有——请勿引入。
// TODO:// TODO: remove in Astro <N>FIXMEEditing Existing Code
编辑现有代码
- Preserve existing comments. If your change alters behavior, extend or correct the specific prose — never replace it with generic text. Deleting hard-won context is worse than leaving a comment slightly stale.
- When your change makes a comment false, fix it in the same diff. A stale comment is worse than none.
- Match the surrounding density. A heavily documented module deserves the same level on new items; do not blanket a sparse module with comments.
- 保留现有注释。如果你的变更改变了行为,请扩展或修正特定内容——切勿替换为通用文本。删除来之不易的上下文比保留略有过时的注释更糟糕。
- 当你的变更使注释失效时,请在同一个diff中修复它。过时的注释比没有注释更糟糕。
- 匹配周围的注释密度。注释丰富的模块在新增条目时应保持相同的注释水平;请勿在注释稀疏的模块中批量添加注释。
Self-Check Before Finishing
完成前的自我检查
After completing any task that touched comments, re-read only the comments in
your diff, in isolation from the code changes:
- Does each one pass the deletion test?
- Does any reference the conversation, the change itself, or the reviewer?
- Does every workaround link its issue or PR?
- Would a reader without access to the diff understand each one?
Fix or delete what fails. Deletion is the default; a missing comment is cheaper
than a misleading one.
完成任何涉及注释的任务后,请单独重新阅读你diff中的所有注释,脱离代码变更本身:
- 每条注释都通过删除测试了吗?
- 是否有注释提及对话、变更本身或评审者?
- 每个临时解决方案都链接了相关Issue或PR吗?
- 没有diff上下文的读者能理解每条注释吗?
修复或删除未通过检查的内容。默认选择删除;缺少注释比误导性注释的代价更低。