ADR-0037:编写时解析的语义主题与命名样式
背景
多份报告需要复用正文、标题和表格格式。此前 Document.Builder.bodyFormat 只管理后续正文、列表和便利语义表格;标题独立使用默认值,组件由 Documents 转成 StyleScope。调用方容易在每份报告重复设置相同格式,而一个专用格式的普通段落还需要显式提供 ID。
现有 ParagraphFormat、CellFormat、TableFormat 与 InlineStyle 都是完整不可变值。根据 12 pt、黑色或零缩进猜测调用方是否省略属性,会改变既有显式值的含义。布局时才解析主题也会让模板、DOCX 和组件测量出现不同解释。
决策
在模型模块增加项目自有不可变 DocumentTheme,保存正文、六级标题、便利语义表格的格格式和表格式,以及两类有界命名完整样式。该值只依赖模型与 JDK,不保存字体句柄、组件样式、后端类型或可变回调;不新增模块、依赖或外部资源。
Document.Builder.theme 替换后续内容的默认值。普通段落、列表、标题和便利表格在加入时生成既有完整格式;最终 Document 的 record 分量保持不变,不保留主题或名称引用。.add(Block)、完整格式重载和预建格原样保存。Document.Builder.paragraph(String, ParagraphFormat) 提供自动 ID 的专用格式段落。
六级标题的初值分别为 Heading.defaultFormat(level)。主题标题回调从当前完整值开始,未修改的整段保持及与下一块保持策略继续有效。正文变化不重设标题。完整值中的固定行距也保留,调整字号不会暗中扩大已经明确的行距。
便利语义表格先用当前 CellFormat/TableFormat 初始化新 Table.Builder,再同步执行调用方回调;回调明确设置的值优先,传入 TableCell 保留完整格式。等宽字符串表便利入口使用相同默认值,同时保持既有表头、列宽和校验契约。组件 GridTable 是独立模型,不套用语义表格的 padding、边框或背景。
格格式的显式意图
主题 Builder 未设置 cellFormat 时,在每次 build 从最终正文的字号、行距、对齐和断行规则派生格格式。设置完整格值或执行格回调后,该值独立于后续正文修改;格回调以当前已解析格格式为基底。
DocumentTheme 使用私有显式标记保存这一区别,toBuilder 保留标记。隐式主题复制后改正文会重新派生格格式,显式主题复制后改正文仍保留原格值。主题相等性和哈希包含此意图,不能仅比较当前格的数值,因为后续派生行为不同。无须向用户暴露标记,也不按默认数值猜测它。
Document.Builder.bodyFormat 保留旧范围:更新随后正文、列表和便利语义表格格文字,即使前一次主题配置了专用格格式也如此;主题标题和 TableFormat 保留。调用方需要单表专用格格式时在表回调中明确设置。随后再次调用 theme 会替换未来内容的整组默认值,旧内容不变。
命名完整样式
名称区分大小写,采用 [A-Za-z_][A-Za-z_0-9-]{0,63};段落和行内映射各最多 128 个不同名称,同名 setter 更新已有值且不增加数量。返回映射为按定义顺序保存的不可变快照。null 名称/值/回调抛 NullPointerException,非法、未知或超额名称抛 IllegalArgumentException,不回退到正文。
新的命名段落回调从定义当时的完整正文格式开始;更新同名样式的回调从当前命名值开始。新的行内回调从 InlineStyle.of(当前正文字号) 开始,保持黑色、默认字体角色和无装饰;更新时从当前完整行内值开始。名称和数量验证先于回调,回调同步完成后立即构造完整值。随后修改正文、保留的子 Builder 或主题 Builder 都不会改写旧主题。
查询返回现有完整值,调用方显式传入段落或 InlineText。主题不保存全局文字颜色或默认字体角色,也不把命名行内样式解释为部分声明。例如 11 pt 的强调样式进入 18 pt 标题仍为 11 pt;需要另一字号时显式派生。未知字体角色、固定行框不足和缺字策略继续由既有文字入口验证。
组件入口
Documents.theme 直接初始化语义 Builder,并为随后加入的组件保存正文排版快照。该方法不能再调用 Documents.bodyFormat,否则会用正文覆盖主题专用格格式。
组件映射继续只有字号、固定行距、首行缩进、后续行缩进、对齐和断行规则六项,通过既有 StyleScope 和 TextInheritance 解析;段间距、相邻分页策略、颜色及字体组保持独立。局部声明、完整旧样式和恢复继承的方法继续执行原契约。Documents 同步转发已有富文本段落、标题和列表便利入口,不引入另一套富文本模型。
范围与验证
首批不增加 XML 主题语法、CSS 选择器、主题继承、运行期更新、全局颜色/角色、页区/目录主题、可编辑表单样式或 DOCX 特定主题。Java 模板可直接复用已经主题化的完整原型。GAP-04 保持部分支持,完整样式系统仍需独立验收。
行为验收须证明默认主题与旧默认模型值一致,六级标题保存分页策略,主题/正文设置只影响后续内容,显式 12 pt/黑色/零值不被覆盖,表回调优先,主题复制保留格意图,命名快照、界限和回调顺序确定。组件须按实际测量核对局部覆盖和恢复继承,并保留固定行框、缺字及未知角色诊断。
独立小样比较两套主题下同一报告的实际字号、颜色、行距、表格内边距、来源与分页,检查全部新页。公共 API 验证隔离 Maven 调用方;既有默认样例执行回归,不自动更新视觉基线。