Storybook 文档风格规范:docs-review Skill 的 storybook-style.md 规则与自动校验实现全解
【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook
本文深入讲解 Storybook 仓库中docs-reviewAgent Skill 的核心参考文件 storybook-style.md。该文件定义了 Storybook 官方文档(/docs目录下的 MDX 页面)的编辑语气、标题、链接、MDX 自定义组件、frontmatter 与块级 JSX 排版规则。读完后,你将掌握这套文档风格规范的每一条规则与正反示例,并能理解规则中标注[auto]的检查项是如何被 check-docs.ts 逐条实现、通过yarn docs:check自动校验的。
这套风格指南在整个 Skill 体系中的位置
storybook-style.md是 SKILL.md 定义的docs-review文档审查技能下的四个参考文件之一,它"拥有"(owns)Storybook 特有的编辑、MDX 组件、frontmatter 与校验规则,但不拥有文档类型识别、模式路由或干预逻辑——那些属于 docs-strategy.md。按 SKILL.md 的加载表:
| 参考文件 | 负责内容 | 加载时机 |
|---|---|---|
| docs-principles.md | 北极星目标、质量维度、双读者要求 | 总是最先读取 |
| docs-strategy.md | 模式、文档类型、干预阈值、页面形态指导 | 总是第二读取 |
| docs-antipatterns.md | 诊断模式与纠正手段 | 诊断薄弱或混乱草稿时 |
| storybook-style.md | 编辑、MDX 组件、frontmatter、格式、校验规则 | maintenance模式,或各编辑模式的最后收尾 |
所有权规则(Ownership Rules)明确划界:策略类参考文件不拥有格式或组件规则,storybook-style.md不拥有文档类型或干预逻辑,SKILL.md本身只拥有工作流与交接。对应地,在 SKILL.md 的工作流中,第 6 步"应用 Storybook 风格"永远位于结构性、编辑性工作之后——"这一步永远不是第一遍"。
语气与文风(Voice and Tone)
人称(Point of View)
- 第二人称("you")——面向读者的默认形式。
- 第一人称复数("we")——代表 Storybook 团队发言时使用(如 "We recommend…"),或表示"我们一起看看"(如 "Let's take a look…")。
- 禁用第一人称单数("I")和以第三人称称呼读者("the user")。
语气(Tone)
- 专业但口语化——像给同事讲解,而非写教科书。
- 鼓励但不夸张——偶尔一句 "That's great!" 可以,避免过度热情的表达。
- 解决方案导向——强调读者能做什么,而非限制。
- 直接且自信——清晰给出建议("We recommend…"),不做不必要的含糊。
句式(Sentence Structure)
- 优先主动语态:写 "Storybook renders the component",而不是 "The component is rendered by Storybook"。
- 用短而直接的句子做强调和引入。
- 解释复杂关系时允许长句,但避免冗长的连缀句(run-ons)。
- 以目的开头——章节开篇先说清"这是什么、为什么重要",而不是铺陈背景。
指令措辞(Instructions)
- 分步指令用祈使句:"Run this command"、"Add the following"、"Create a new file"。
- 可选或替代方案用建议式措辞:"You can also…"、"You might want to…"。
- 引入代码示例时用陈述句带上下文:"To define the args of a single story, use the
argsCSF story key:"。
缩写(Contractions)
- 自然地使用缩写(don't, can't, won't, you'll, it's, we're)——它们强化口语化语气。
- 在 callout 警告等需要精确表达的严肃/警示语境中避免缩写。
技术术语(Technical Terms)
- 关键术语首次出现时给出定义,之后可自由使用(例如先写 "Component Story Format (CSF)",之后直接用 "CSF")。
- 链接到相关概念,而不是在正文中重复解释。
- 假定读者具备基础 Web 开发知识(HTML、CSS、JavaScript、组件),不过度解释 fundamentals。
- 所有代码性质的术语使用反引号包裹(对应下文"行内格式"一节)。
措辞的确定性(Hedging)
- 表达能力用 "can",表达可能结果用 "may" 或 "might"。
- 表达建议用 "should",表达硬性要求用 "must"。
- 描述存在例外的常见模式时用 "typically" 或 "generally"。
- 陈述本身直接时不要加缓冲——写 "This adds…" 而不是 "This should add…"。
选词(Word Choice)
- 避免弱化语("simply"、"just"、"easily"、"obviously")——对一位读者简单的事,对另一位读者未必如此。
- "powerful"、"useful"、"great" 要节制使用,且仅在确实成立时使用。
- 具体优于模糊——写 "renders in under 2 seconds" 而不是 "renders quickly"。
引入示例(Introducing Examples)
- 先交代为什么,再展示怎么做——代码块之前给一句简短的上下文。
- 常用句式:"Here's how you could…"、"For example, if you…"、"To do X, use Y:"。
- 当代码块紧随其后时,引导句以冒号结尾。
章节开头(Section Openings)
- 用 1–2 句总结本章讲什么、为什么重要。
- 快速进入正题,把铺垫压到最小。
- 第一句应当能独立成立,本身就是一个定义或价值陈述。
段落长度(Paragraph Length)
- 段落保持 2–4 句,保证可扫读性。
- 引导段应为 1–2 句。
- 较长的解释用标题、列表或 callout 切分。
标题、链接、列表与行内格式
标题(Headings)
- H1 只能来自 frontmatter 的
title;正文中绝不使用# Heading。[auto] - H2/H3 使用句子式大小写(sentence case,仅首字母和专有名词大写)。
- 不得跳级使用标题(例如 H2 后直接 H4)。
[auto]
链接(Links)
- 内部链接:指向
.mdx文件的相对路径,例如text。[auto] - 外部链接:完整 URL,必须始终包裹在 Markdown 链接语法中(正文中不允许裸 URL)。
[auto]
列表(Lists)
- 无序列表使用
-(不要用*或+)。[oxfmt]
行内格式(Inline Formatting)
- 文件路径、函数名、变量名、组件名、CLI 命令、配置键、类型名一律用反引号。
- UI 标签和强调用粗体;斜体节制使用。
自定义 MDX 组件
Callout 组件
- 必须指定
variant("info"或"warning");裸写<Callout>不允许。 - 图标使用有标准化映射:
- 💡——技巧与有用信息(
variant="info") - 🧪——实验性/预览功能(
variant="info"或variant="warning") - ℹ️——补充背景(
variant="info") - 📣——公告,需配合
title属性(variant="info") - ♿——可访问性(无障碍)专用(
variant="info") - ⚠️——必须配
variant="warning",不得配variant="info"。[auto] - 图标本身是可选的;若使用,必须遵循上述映射。
- 💡——技巧与有用信息(
variant="positive"是非标准写法,应改用variant="info"。[auto]
其他组件
<If renderer={[...]}>/<If notRenderer={[...]}>——按渲染器条件渲染(替代已废弃的<IfRenderer>)。<CodeSnippets path="..." />——path必须真实存在于docs/_snippets/目录。[auto]<Video src="..." />——嵌入视频。<YouTubeCallout id="..." title="..." />——YouTube 嵌入。
Frontmatter 规则
- 值不加引号,除非值包含需要加引号的特殊字符(如
&、|、:、逗号)。[auto] - 需要加引号时使用单引号。
- 仅当
sidebar.title与title不同时才写sidebar.title;两者相同则省略。[auto]
正例:
--- title: Component Story Format (CSF) sidebar: title: CSF order: 2 ---反例:
--- title: "ArgTypes" sidebar: title: "ArgTypes" order: 2 ---块级 JSX 元素的换行规则
块级 JSX 元素(如<Callout>、<details>、<If>)遵循三条排版规则:
- 元素前后要各空一行——除非前后紧邻的内容是注释,此时注释与元素之间不空行。
- 元素内部内容的前后要各空一行——
<summary>是例外:<details>开始标签与<summary>标签之间不空行。 - 内部内容不缩进——除非内容本身应当缩进(如嵌套列表项、代码块内部)。
正例:
<If renderer={['react']}> Other content. <Callout variant="info"> This is a callout. - This is a list item inside the callout - This is a nested list item inside the callout ```json { "key": "value" } ``` </Callout> More other content. <details> <summary>This is a summary</summary> This is content inside the details element. </details> More other content. </If> {/* End supported renderers */}反例(对比可见:元素前后未空行、<Callout>缺少variant、<summary>与内容之间未空行、注释前多空了一行等):
<If renderer={['react']}> Other content. <Callout> This is a callout. - This is a list item inside the callout - This is a nested list item inside the callout ```json { "key": "value" } ``` </Callout> More other content. <details> <summary>This is a summary</summary> This is content inside the details element. </details> More other content. </If> {/* End supported renderers */}校验:yarn docs:check与[auto]/[oxfmt]标记的实现
文档末尾声明:标记[auto]的条目由yarn docs:check检查(实现在 check-docs.ts),标记[oxfmt]的条目由yarn fmt:write处理。并强调这些是最终阶段的校验工具——应在结构性与编辑性工作完成后再运行,而不是第一步。
命令链路
根目录 package.json 中定义了根级入口:
"docs:check": "yarn --cwd scripts docs:check"——转发到 scripts 工作区;- 在 scripts/package.json 中,
"docs:check": "jiti ./docs/check-docs.ts",即通过 jiti 直接执行 TypeScript 校验脚本; "fmt:check": "oxfmt --check ."与"fmt:write": "oxfmt ."——由 oxfmt 完成格式归一化(包括列表符号等[oxfmt]规则)。
check-docs.ts的 CLI 入口会以仓库docs/目录为目标运行runAllChecks,汇总所有检查;发现任何错误即以退出码 1 结束,使检查可接入 CI。
[auto]标记与代码实现的逐条对应
将文档中各[auto]标记与check-docs.ts导出的检查函数对照,可以看到规则与实现的一一映射:
| 规则(来自 storybook-style.md) | 检查函数 | 实现要点 |
|---|---|---|
H1 仅来自 frontmattertitle,正文禁用# | checkNoBodyH1 | 仅在content上下文中匹配^#\s+,代码块内不误报 |
| 不跳级使用标题 | checkHeadingHierarchy | 从 H1(frontmatter 标题)起跟踪prevLevel,level > prevLevel + 1即报错,同时识别<h2>等 HTML 标签 |
内部相对链接指向.mdx文件 | checkRelativeLinks | 校验目标文件存在,并进一步校验#anchor片段能否在目标文件标题 slug 中找到 |
| 外部链接必须包裹在链接语法中(无裸 URL) | checkBareUrls | 跳过 import/export、引用链接定义、表格行、反引号内、JSX 属性值等场景后,检测正文裸http(s)://URL |
无序列表用-([oxfmt],非 auto) | — | 由oxfmt(yarn fmt:write)负责归一化 |
<CodeSnippets path="..." />路径必须存在于docs/_snippets/ | checkCodeSnippetPaths | 以docs/_snippets/为基准解析 path,缺失即报Missing snippet |
裸<Callout>不允许,必须带variant | checkCalloutVariant | 收集可能跨多行的完整开标签,缺少variant=即报错 |
variant="positive"非标准 | checkCalloutVariantPositive | 匹配variant="positive"并提示改用variant="info" |
⚠️ 图标不得配variant="info" | checkCalloutIconMismatch | 同行同时出现<Callout、⚠️ 与variant="info"即报错 |
| frontmatter 值不必要的引号 | checkFrontmatterQuotes | 仅当title值不含&、|、:、逗号等字符却加了引号时报错,与文档"特殊字符才引号"规则一致 |
与title相同的sidebar.title应省略 | checkRedundantSidebarTitle | 解析 frontmatter 中title与sidebar.title,去引号后相等即报冗余 |
此外,runAllChecks还会执行一个文档正文未直接列出的检查 checkDeprecatedIfRenderer:检测到已废弃的<IfRenderer>用法即提示改用<If>——这与"其他组件"一节推荐的<If renderer={[...]}>写法互为印证。
值得注意的源码实现细节
从源码结构看,有两处细节让校验更健壮:
- 跨版本链接豁免:
checkRelativeLinks中定义了crossVersionRegex = /^(?:\.\.\/)+release-[\w.-]+\//(见 check-docs.ts),指向其他发布分支(如../../../release-8-6/docs/...)的跨版本文档链接无法在本地验证,会被直接跳过。 - 行上下文感知:多个检查依赖 utils.ts 中的
getLineContexts(getLineContexts),它把每一行标注为frontmatter、codeblock或content,因此"正文 H1"、"裸 URL"等检查不会误伤代码块与 frontmatter 内的内容;而slugify(slugify)模拟了 rehype-slug 的标题 slug 行为,支撑锚点片段校验。
实践流程:规则如何落到一次文档编辑上
结合 SKILL.md 定义的工作流,storybook-style.md的正确使用时机是:
- 先完成模式判定(
maintenance/improve/rewrite/author/strategy)、主文档类型判定与草稿诊断(这些由 docs-strategy.md 与 docs-principles.md 指导); - 完成结构性与编辑性修改后,加载
storybook-style.md,按本文"语气与文风 → 标题/链接/列表/行内格式 → 自定义组件 → frontmatter → 块级 JSX 换行"的顺序做风格收尾; - 运行
yarn fmt:write与yarn docs:check,修复报告中的错误后再跑一次确认。注意:不要在strategy模式或没有编辑任何文件时运行校验。
这套"风格规则文件 + 自动校验脚本"的组合,让 Storybook 仓库中docs/下数千个 MDX 页面与docs/_snippets/下的代码片段示例保持统一语感、统一组件用法和可机器验证的链接/格式合规性——写文档(或为 Agent 编写文档审查规则)时,都值得借鉴这一"规则即代码"的做法。
【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考