Reactive Resume 的 Semantic CSS 语言参考与统一文档生成设计:一篇权威参考页加一条 `pnpm docs:gen` 流水线
本篇解读 Reactive Resume 仓库中「Semantic CSS Author Reference and Unified Documentation Generation」设计文档(状态:Approved,2026-07-29):它将 Semantic CSS 的作者级语言参考收敛为一个规范页面,并把 Semantic CSS 参考表、AI 技能 Schema 参考、公开 JSON Schema 指南和 OpenAPI 规范四类生成物统一到根命令 pnpm docs:gen 之下。读完后你会掌握:参考页的十节信息架构、基于标记(marker)的确定性 Markdown 生成机制、Zod 到 JSON Schema 的单一规范源设计,以及「全量计算后再落盘」的失败安全策略及其测试验证方式。
一、设计目标:一份面向作者的规范参考
设计文档明确了两条原则:
- 受众是简历作者(resume authors),不是编译器贡献者。参考页是语言参考(language reference),而非贡献者文档:编译器架构、AST 实现细节、内部适配器名称和包归属关系都不得出现在公开页面中。
- 单一规范入口,扩展而非重复。参考内容不新开页面、不拆分多页,而是扩展现有页面(原文设计为
docs/guides/semantic-css-reference.mdx,公开路由https://docs.rxresu.me/guides/semantic-css-reference),把手写解释、可复制粘贴的示例,与从运行时注册表(runtime registries)和 PDF 模板清单(template manifests)生成的表格合并在同一页中。
参考页必须让作者能够:
- 发现存在哪些选择器、属性、值和指令(directive);
- 理解哪些语义节点和模板部件可以被定向;
- 复制针对常见定制目标的可运行示例;
- 诊断无效或不起作用的样式;
- 理解可移植性、last-valid(最后一次有效样式)行为、资源限制与不支持的语法。
一个关键的边界约束值得注意:生成的属性表格不得把宽松的注册表提示(registry hint)呈现为穷尽的值文法。凡是值语法实际上由解析器或级联逻辑实现、且没有权威共享元数据的,必须保留手写说明。这一条防止了「生成表格看似精确、实际并不精确」的文档失真。
二、规范参考页的十节信息架构
参考页按「查」而非「顺读」组织,共十节。这是整份设计的主体骨架,完整继承如下:
- 一分钟了解 Semantic CSS(Semantic CSS in one minute)
@version 1;指令;- 一份完整、可移植的样式表示例;
- 可编辑源码(editable source)、实际生效源码(applied source)、预览与导出四者之间的关系。
- 选择器文法(Selector grammar)
- 通配、语义类型、ID、属性选择器;
- 支持的属性操作符;
- 后代、子代、相邻兄弟、泛型兄弟四种组合器;
- 选择器列表;
- 支持的功能性与结构性伪类;
- 大小写敏感行为;
- 明确列出不支持的选择器语法;
- 合法与非法示例成对给出。
- 语义元素目录(Semantic element catalog)
- 生成的父子关系、属性与角色(roles);
- 已知属性值域;
- 可移植的 section 类型选择器 vs 简历专属 ID 的区分;
- 富文本结构,特别是
list-item行与list-item-content两种不同语义(后续计划文档还要求保留list-marker的独立作者语义)。
- 级联与值(Cascade and values)
- 特异性、源码顺序、选择器列表特异性、继承、
!important; initial、inherit、unset、revert在 Semantic CSS 中的行为;- 作者自定义属性、嵌套
var()回退、未解析变量与循环; - 只读系统变量
--resume-*; - 数字、长度、单位、颜色、函数与简写。
- 特异性、源码顺序、选择器列表特异性、继承、
- 属性参考(Property reference)
- 按类别分组的生成属性表;
- 按语义节点标注适用性;
- 继承性;
- 有权威元数据时标注可接受单位与受约束关键字;
- 文本、间距、边框、Flex 布局、图片、变换与结构性属性的示例。
- PDF 行为
- 页面尺寸;
- 隐藏节点与稳定的兄弟排序;
- 分页、固定内容、最小存在性(minimum presence ahead)、孤行与寡行;
- 媒体查询文法、求值顺序与页面尺寸行为;
- 影响作者的 React PDF 特有布局限制。
- 模板专属选择器
- 覆盖全部 15 个模板的生成矩阵;
- 精确的模板部件名、选择器形态、归属或放置条件、允许的语义子节点;
- 可移植性警告与受保护(guarded)的选择器示例。 矩阵从真实模板清单生成,而不是单独维护的一份列表。
- 诊断与限制(Diagnostics and limits)
- 稳定的编译器与预检(preflight)诊断码、严重级别、含义与建议修复动作;
- 源码、选择器、声明、节点、页面、尺寸、超时与内存限制;
- 无效编辑之后 last-valid 预览与导出的行为。
- 复制粘贴配方(Copy-paste recipes)
- 重排 section 标题、按类型定向 section、定向单个 section/条目/字段、按位置定制侧栏内容、定制富文本列表、修改页面尺寸、避免尴尬分页、定制模板装饰、用
@media按尺寸应用 PDF 样式。
- 重排 section 标题、按类型定向 section、定向单个 section/条目/字段、按位置定制侧栏内容、定制富文本列表、修改页面尺寸、避免尴尬分页、定制模板装饰、用
- 不支持的能力与可移植性清单
- 不支持的选择器、at-rule、布局、资源、字体、脚本、交互与网络能力;
- 保持样式表跨模板可移植的建议。
三、统一文档生成架构:pnpm docs:gen
设计将原先的 docs:semantic-css 命令替换为根命令 pnpm docs:gen,留下唯一规范文档生成入口。该命令一次性再生四类生成物:
- Semantic CSS 参考表;
- resume-builder 技能的 Schema 参考;
- 嵌入公开 Schema 指南的完整 JSON Schema;
- 签入仓库的 OpenAPI 规范。
3.1 仓库中的实际命令编排
当前仓库根 package.json 中该命令的实现是一条两级编排:
"docs:gen": "pnpm --filter server docs:gen && pnpm --filter @reactive-resume/tooling docs:gen"
- server 侧 apps/server/package.json 的
docs:gen为tsx src/openapi/generate-spec.ts,负责 OpenAPI 规范; - tooling 侧 tooling/package.json 的
docs:gen为tsx semantic-css/generate-reference.ts,负责 Semantic CSS 与 Schema 文档。
两个生成器分属不同工作区包,但由根命令串联,保证「一次命令刷新全部文档产物」。
3.2 Semantic CSS 参考数据:从权威运行时元数据生成
生成器消费既有的权威来源(而非新建数据源):
- 受支持的版本与编译限制;
- 语义元素注册表;
- 属性注册表;
- 只读系统变量注册表;
- PDF 模板清单;
- 共享的编译器与预检诊断目录。
生成器把确定性的、标记分隔的段落写入参考页 MDX。生成式事实章节包括:语义元素(含父元素、属性、角色、已知值域)、属性(类别、适用性、继承、单位、受约束关键字)、系统变量、逐模板的模板部件、诊断、编译与预检限制。手写叙述始终保留在生成标记之外。
这些权威来源在仓库中的实际位置可以印证:Semantic CSS 编译器(解析、选择器、级联、诊断、限制、注册表)位于 packages/resume/src/stylesheet/,包含 compile.ts、selector.ts、cascade.ts、diagnostics.ts、limits.ts、version.ts 与 registry/ 子目录;PDF 侧的语义渲染与模板清单位于 packages/pdf/src/semantic/。
3.3 标记替换机制与「全量计算后落盘」
tooling/semantic-css/generate-reference.ts 是 tooling 侧生成器。其核心是 replaceGeneratedBlock(source, name, body, path) 函数,以 HTML 注释形式的一对标记界定生成区:
const start = `<!-- ${name}:START -->`;
const end = `<!-- ${name}:END -->`;
if (startMatches === 0 || endMatches === 0) throw new Error(`Missing generated markers ${name} in ${path}.`);
if (startMatches !== 1 || endMatches !== 1) throw new Error(`Duplicate generated markers ${name} in ${path}.`);
// ...
if (endIndex < startIndex) throw new Error(`Generated markers ${name} are out of order in ${path}.`);
三种失败(缺失、重复、顺序颠倒)都会抛错,精确对应设计文档「要求每个预期标记存在、重复或缺失即失败」的确定性要求。
失败安全策略在 buildGeneratedDocumentation 与 updateGeneratedDocumentation 的拆分中体现:前者先计算全部输出文本(读取源文件、生成 JSON Schema、渲染 Markdown),后者才写入目标文件。设计文档明确「不引入通用事务框架」,只做「任一来源非法则零写入」。tooling/semantic-css/generate-reference.test.ts 中有直接对应测试:
it("does not write any output when one source is invalid", async () => {
// 写入缺少标记的源文件
await expect(updateGeneratedDocumentation(paths)).rejects.toThrow(/Missing generated markers/);
// 断言所有目标文件内容与失败前完全一致
expect(await readTargets(paths)).toEqual(before);
});
另有「两次构建输出完全相等」的确定性测试,以及「签入的生成文档必须与重新生成的结果逐字节一致」的同步性测试,对应设计中「非变更测试生成到临时文件并与签入输出逐字节比较」的验证要求。
3.4 Resume JSON Schema:一个规范源,两个输出
生成器使用 createResumeDataJsonSchema()(来自 @reactive-resume/schema/resume/json-schema,即从 resumeDataSchema 经 Zod JSON Schema 转换得到的唯一规范输入端 Schema)驱动两份输出:
- skills/resume-builder/references/schema.md——面向 AI 的紧凑 Markdown 参考:字段层级、类型、必填字段、约束与代表性结构。
renderSchemaReference的输出包含「Required top-level fields」「Union variant shapes」「Field catalog」三节,且对联合类型(anyOf/oneOf)按变体标注必填性(如variant 1 at items[]),对customSections[] 的 13 种条目类型(summary、profiles、experience……cover-letter)按类型键映射到具名条目 Schema(experienceItemSchema` 等),而非匿名的「variant N」——这部分由 tooling/semantic-css/generate-reference.test.ts 逐类型断言覆盖。 - docs/guides/json-resume-schema.mdx——完整规范 JSON Schema 放在标记
<!-- RESUME-JSON-SCHEMA:START/END -->之间的生成式 JSON 代码块中,人手写的解释留在块外。
测试还校验了文档与契约的一致性:引导文必须提到 draft 2020-12、不得残留 draft 7 字样、并明确「Resume 文档不包含顶层 version 属性」。
3.5 OpenAPI 规范:运行时与签入产物共用一个纯生成器
设计的 OpenAPI 部分要求消除「运行时 /api/openapi/spec.json 输出」与「签入的 docs/spec.json」之间的漂移(陈旧版本号、localhost 服务器 URL)。实现上由 apps/server/src/openapi/ 拥有一个可复用、纯函数式的生成器:运行时 handler 以 env.APP_URL 调用它,而文档生成脚本 apps/server/src/openapi/generate-spec.ts 以生产 URL 调用它并写入 docs/spec.json:
const spec = await generateOpenApiSpec({ appUrl: "https://rxresu.me", version: packageJson.version });
await writeFile(target, `${JSON.stringify(spec, null, "\t")}\n`);
版本号取自根 package.json 的当前应用版本;脚本在缺失 APP_URL、DATABASE_URL、AUTH_SECRET 时注入仅用于隔离文档生成进程的值,因此该命令可在无真实环境变量的机器上执行。签入产物 docs/spec.json 即由此生成。
四、Custom Styles 帮助提示
设计在样式表编辑器的共享外壳(shared chrome)中、代码编辑器正上方加了一条提示:
Not sure what to write? Browse the Semantic CSS language reference.
链接契约非常具体:
- 目标是
https://docs.rxresu.me/guides/semantic-css-reference; - 新标签页打开,
rel="noopener noreferrer"; - 使用现有
BookOpenIcon并标记为装饰性(decorative); - 可见文本经 i18n 翻译,屏幕阅读器文本额外说明「在新标签页打开」;
- 因为桌面标准编辑器与移动端聚焦面板共用同一套编辑器外壳,所以一处实现两处生效。
设计上刻意保持实现局部化于样式表编辑器内部,不为一条链接引入共享组件或中央 URL 注册表——这是「不引入无关文档架构」原则的具体体现。
五、导航、验证门禁与验收标准
导航:docs/docs.json 将参考页列在 using-custom-styles 之后。当前仓库的 docs/docs.json 可印证该设计的后续演化:/guides/semantic-css-reference 现已配置为重定向至 /applying-custom-styles,即参考内容已并入 docs/applying-custom-styles.mdx(对应仓库中 2026-07-30 的完整重命名设计),导航契约「紧跟 using-custom-styles」保持不变。
验证门禁分四层:
- 生成器验证:
pnpm docs:gen再生全部四组产物;临时文件逐字节比较;重复运行确定性;每个运行时模板部件都出现在模板矩阵中;跨注册表检查拒绝不一致的父子覆盖;签入 OpenAPI 与运行时生成器对同一 URL 与版本一致;两个 Schema Markdown 目标派生自同一规范 Schema。 - 示例验证:标注为合法(valid)的完整复制粘贴示例必须编译成功;选定的故意非法示例必须产出其文档化诊断;非完整样式表的小片段不强制过完整编译器。当前测试即从公开指南提取全部
```css代码块并逐一断言compileStylesheet无 error 诊断(见 tooling/semantic-css/generate-reference.test.ts 的 "compiles every Semantic CSS example in the public guide" 用例,调用来自 packages/resume/src/stylesheet/ 的编译器)。 - UI 验证:样式表编辑器测试校验可访问链接名、精确公开 URL、新标签页目标、
noopener noreferrer,以及在标准编辑器与移动端聚焦面板中均存在。 - 聚焦门禁:tooling 测试与类型检查、受导出元数据影响的 resume/schema 测试与类型检查、PDF 清单/参考一致性测试、API/server OpenAPI 测试、web 编辑器测试、工作区边界检查、聚焦格式化与 Markdown 校验;Chrome 验证不是必需的。
验收标准(完整继承):参考页记录全部作者可见的选择器、语义元素、属性、变量、指令、值族、模板部件、诊断族、限制与不支持语法类别;含常见作者目标的复制粘贴示例;生成式事实来自权威运行时元数据且有陈旧性覆盖;pnpm docs:gen 刷新 Semantic CSS 表、两份 Resume JSON Schema 参考与 docs/spec.json;运行时与签入 OpenAPI 共享一个生成器;参考页在文档导航中可见;桌面与移动端 Custom Styles 编辑器都链接到精确的公开参考路由;不引入无关产品行为或文档架构。
范围外(同样完整列出,避免误实现):贡献者/编译器架构文档;第二个 Semantic CSS 参考路由;把参考拆成多页;交互式文档 playground;新的编辑器补全或悬停功能;除「修正为生成准确参考所必需的注册表事实不一致」之外的新 Syntax 或渲染行为;通用文档 URL 集中化。
六、设计要点回顾
从这份设计与仓库实现对照,可以提炼出三条可复用的工程决策:
- 单一事实源优先于文档完整性:所有生成式表格都从运行时注册表与模板清单派生,并配以「签入产物必须与再生成结果逐字节一致」的同步测试,从机制上杜绝文档陈旧;
- 标记区 + 失败即中止:HTML 注释标记划定的生成区、缺失/重复/乱序即抛错、先全量计算后统一写入,是低成本实现「原子性文档更新」的实用方案,且被专门测试锁定;
- 按受众切分文档:作者参考页严格排除编译器内部概念,同时用「不支持清单 + 可移植性检查清单」明确语言边界,让参考页既是发现入口也是排错手册。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00