任务:adoc 生产器(K4)
依据:
docs/hub-r4-kb-direction.md第一、三、七节:作者结构由 Hub 直接把 adoc 转为结构化数据,同样的输入给出同样的字节;身份耦合、同批换代、fail-closed;docs/hub-r4-research/kb-real-sources.md:真实 adoc 的形状,调研 2、3 定下的落点和适用条件规则;docs/hub-r4-research/adoc-sandbox.md:asciidoctor.js 4.1.1 浏览器 ESM 单文件、受限 include 展开器、sourcemap 行号回核、拒绝时间类属性;- K01、K02、K04(
node tools/show-element.ts K01 K02 K04)。
前提:kb-sections(K1,带章节路径的文档模型和章节落点)和 kb-svn(SVN 只读系统包)已经合并进 hub-redesign。这一件只把 adoc 转成同一个文档模型,落点代码不改。
- 分支和工作树:
kb-adoc,目录circle-hub-kb-adoc(从合并了 K1 和 kb-svn 的 hub-redesign 开出,依赖已装好) - 可以改的路径:
packs/product/famx/**:adoc 生产器、同步计划里的 adoc 源、README、样例;- asciidoctor.js 的单文件放在包里,带许可证和摘要,不加 npm 运行依赖;
- 对应的测试。
hub/**和contracts/**缺什么先回报。 - 规则:同前(不推送、不建 PR、不发布、不部署;不碰 7420、钥匙串、环境配置文件和任何真实系统;测试只用合成 adoc;
git commit -s)。 - 验证:
npx tsc --noEmit;node tools/gen-contracts.ts --check;node --test --test-concurrency=1对packs/product/**、hub/refs/**、hub/knowledge/**。
要做的
- 输入:一组手册在同一个 SVN 修订号上的文件表,包括主文件和目录里的全部 adoc,加一份声明的属性集。属性集默认为空,也就是和现在的 md 一样“全不设”;哪个名称族用哪组开关待所有者定。
- include:从主文件开始,用受限展开器按主文件的 include 次序展开,不按文件名里的数字,只从文件表里读,每一行记下原文件名和行号。下面这些情况都拒绝,这一组算失败:
- include 的文件不在表里;
- include 带选项(tags、lines、leveloffset 等);
- include 写在条件里;
- 循环;
- 超过深度上限;
- 展开后的总字节超过上限。
- 条件和属性:
- ifdef 和 ifndef 交给 asciidoctor 按声明的属性集求值;
- 生产报告里逐个写明条件分支:条件原文、按声明的属性集保留还是去掉、去掉的原文件和行号范围、行数;嵌套分支分别报,不汇总成整书差值,不悄悄丢段;
- 属性按源里的定义处理;正文里的属性变化按 adoc-sandbox 调研里说的回放;
- 遇到时间类属性(docdate、localtime 等)就拒绝;
- 属性集和引擎版本进组成记录。
- 文档模型:输出和 markdown@1 合并后的模型同形,块带章节路径,K1 的落点代码原样适用。
- 章节层级取自源:
==是一级章节,依次往下; - discrete 标题照源标出;
- 等号超过合法层级的行不是标题,写进报告。
- 章节层级取自源:
- 片段引用:用 text@1 的行号选择器(
l/<a>-<b>)指向各章原件。sourcemap 给出的行号必须回读原件逐字核对,核不上就不用这个行号,并写进报告。 - 签名、取值域和示例:
- 只从显式结构里取:命令表、签名块,以及能逐字核对的加粗或等宽签名行;
- 标题、普通加粗说明和示例都不自动当作签名;
- 示例只作参考,不参与判定;
- 这一件做完以后,catalog.json 的过渡读法(K1 第 4 条)对有 adoc 源的版本线停用。
- 身份和 fail-closed:
- 组成记录写下修订号、每个文件的摘要、属性集和引擎版本;
- 组里任何一章失败,整组生产失败,保留旧根;
- 同样的输入跑两次,字节相同。
- 源数据问题照实报:NUL 字节按文件计数(text@1 已经去掉并计数);CRLF 照原样核对行号。主文件没有 include 的文件列出来,不并进书里。
- 沙箱:在现有生产器档内运行,不联网、不写文件、不起子进程。用一份约 3 MB、表格密集的合成组测时间和内存,写进 README。
- 测试:全部用合成 adoc。要覆盖:
- 主文件加十来章,带属性和 ifdef;
- 表格里的签名和多命令行;
- NUL 字节和 CRLF;
- include 的各种失败;
- 两次产出的字节相同;
- 换了属性集,身份也跟着变。
真实手册上的核对由集成者做:同一组的 adoc 产出和现在 md 产出的章节、签名逐项比。完成后在终端里回报:提交号、测试数量、没做完或拿不准的地方。
分两步做(集成者 2026-10-23 晚)
K1 还在改,这一件先做和 K1 的文档模型无关的部分。
- 分支从
kb-sections开出(目录circle-hub-kb-adoc);K1 再有提交时把 kb-sections 合进来,合并时排在 K1 后面。 - 第一步(现在):第 1、2、3、5、7、8、9 条和对应的测试。
- 输出一份中间的展开模型:每块的种类、章节层级、原文件和行号,以及每个条件分支去掉的行(第 3 条的口径);
- 新文件放在
packs/product/famx/functions/adoc/下,K1 正在改的文件不动; - pack.json 的签名放到最后做,K1 合并以后再重签一次。
- 第二步(K1 合并以后,集成者通知):第 4、6 条,映射到 K1 的文档模型,并对有 adoc 源的版本线停用 catalog.json 的过渡读法。
- 引擎文件:
- 在仓库外的暂存目录里
npm pack @asciidoctor/core@4.1.1,取build/browser/index.js,核对 sha256 等于docs/hub-r4-research/adoc-sandbox.md29 行记的摘要,核不上就停下回报; - 许可证照那份调研第 37 行,从上游 v4.1.1 标签取 LICENSE,和单文件一起放进包里;
- 不跑包的安装脚本,不加 npm 依赖。
- 在仓库外的暂存目录里
决定 35 加的
决定 35 知识库第 3 项:adoc 按名称族各设本族的品牌属性,两族各产出一份,属性集进组成记录;属性名由集成者从源里只读整理,作为部署数据。它取代第 1 条里“哪个名称族用哪组开关待所有者定”。放在第二步做:
- 属性集按名称族给:adoc 生产器的参数里每个名称族一份,键用
product.json的names里的名字。包里的默认值只放空集(全不设,和现在的 md 一样)或合成的;真实的属性名和取值是部署数据,由集成者只读整理后写进去,照 famx-deployment-conventions 第一步的机制覆盖参数。- 次序:famx-deployment-conventions 第一步单独先合并。合并以后(集成者通知),再在
product.json里接上 adoc 生产器的槽,并照那一件的写法把每族一个键(例如attributes.<族名>)声明为可由部署给。在那之前,测试只用参数里的合成属性集。 - 测试:键不是产品名字的属性集被拒;两族的合成属性集各自生效。
- 次序:famx-deployment-conventions 第一步单独先合并。合并以后(集成者通知),再在
- 两族各产出一份:每个名称族用自己的属性集跑一遍第 2、3 条的展开,各得一份文档模型。根按产品线和基础构建建,FAMY 的构建多是 FAMX 构建的别名,所以两份都挂进同一版本线的每个根:在手册命名空间下各用自己的手册名(手册名带上名称族,写法写进 README),章节路径照 K1。测试:品牌词和条件分支在两份里各自对;两份里文字相同的章节条目摘要相同;两次产出字节相同。
- 组成记录:每个名称族用的属性集(属性名和值)和它从哪来,由 Hub 照 famx-deployment-conventions 第一步写进组成记录(每个参数键的
param_sources),生产器不自己记来源,只在报告里照 ProducerInput 收到的param_sources写。条件分支的报告按名称族分开写,口径照第 3 条。测试:只改一族的属性集,只有那一份子树和组成记录的身份变。 - 没配属性集的名称族:这一族的键在
param_sources里是 null(取包的默认值),就按默认值产出,报告写明“这一族的属性集没有配置”,下一步是管理员配上以后重新同步;不记未知。测试:一族没配时照默认值产出,并写明。 - 整组失败照旧:任一族展开失败,整组失败,保留旧根(第 7 条)。测试:只让一族失败,旧根不动。
可以改的路径不变;要动 hub/**、contracts/** 的地方先回报。param_sources 由 famx-deployment-conventions 第一步加,这一件只读它。
第 44 项注:这一件照现在的样子合并(第二步和决定 35 的几条,fb17a2f4 到 e570fc87 已经做完)。接线挪到 famx-deployment-conventions 的 FAMX 那一步:product.json 接上 adoc 生产器的槽,每个名称族声明一个变量 FAMX_ADOC_ATTRIBUTES_<族名的大写>,params.attributes.<族名> 写引用;families.ts 的说明、families.test.ts 92 行一带和 README 不再提 param_sources,属性集的来历由 Hub 组成记录的 variables 写。真实同步时每族的变量都要设置,第 4 条“没配属性集”的情形只在试运行和样例里出现。