ADR-0034:有界块格与原子内表
决策
TableCell 增加不可变 blocks 分量,旧 2—7 参数构造器仍创建行内格。非空 blocks 与 text/inlines/images/fields 互斥,Builder 设置任一分支替换另一分支并即时快照;块格的旧单段访问器明确失败,不返回空值掩盖内容。公共编写先提供具名段落/表格同步回调和显式 ID。
块格只接受 Paragraph/Table,根表算第一层、内表算第二层,第三层拒绝。不同段保留独立格式及 ID,空真实段落保留一行。格段 pageBreakBefore/keepWithNext、含块格表 Auto/allowRowSplit、重复父表头及单向源块格首批拒绝。XML/Markdown 新嵌套语法不随 Java 模型自动开放。
模型 SemanticTree 以真实锚点先序遍历全部后代,不按对象实例去重;Document、跨节、模板、布局及 DOCX 复用它。CellLocation 记录各层 tableId、原始行、物理列和格内块序号,路径外到内,旧行内格序号为 -1。后代 ID 全文档唯一,根索引和叶 UTF-16 保持原义;资源 SHA 去重不允许内容源重复。
CellFragment 使用 Inline/Blocks 两个 IR 内容分支,保留旧构造器和单段访问器;块格单段访问失败。子 ParagraphFragment/TableFragment 坐标相对格 textOrigin,不提前转换成绘制命令。父格扣一次 padding,子表按父内容宽度测量。格内段落边缘间距抑制,相邻段/表间距相加;每个子表完整测量一次,其高度参与父表既有行高及 rowSpan 约束。含它的父连通行组原子移页/移区,超高失败。
全树节点、覆盖槽及叶原文共享结构预算,实际输出行和重复普通表头另计。不可递归调用完整引擎重开预算、页号或最终字段状态。最终锚点、字段替换、生成诊断及图文外链递归遍历同一棵 IR,统一合成平移,在目录偏移/分节后解析。组件语义根拥有全部后代,不把子表重复注册为独立 SemanticPlacement。
DOCX 按标准 tc/p/tbl 顺序保存块内容,每个 tbl 使用自身网格和父格可用宽度。末块为表时生成标准末尾 p,自有结构尾段以私有属性标识,只有已验证的自有标记可归一掉;无元数据真实空段保留。原生书签增加可验证的自有 owner 区分同一首段上的表/段目标,无元数据使用明确规范所有者。图片、关系、字段与书签共享全包注册及预算,未知容器、深度、样式和非空续格不能静默丢弃。
Java 模板递归绑定并累计预算,循环实例给全部后代确定 ID;内部静态引用随同映射重定位,外部目标保持。字节/流/原子文件与执行上下文所有权保持,不引入新依赖。
替代方案与影响
将多段拼成换行会丢失段格式和引用所有者;使用组件插槽不能输出原生 DOCX;递归运行私有文档会重置页号和预算,均不采用。第一批只做原子子树,避免把完整递归续排、两层重复表头及纵向组拆分混入同一变更。
TableCell 和 CellFragment 的 record 分量/canonical descriptor、解构及反射形状变化。保留旧源码构造不等于完全二进制兼容;需要旧源码与新隔离调用方分别编译验证。GAP-03/GAP-12 只关闭所验收子目标,不推定一般 Word 无损互转或与 PDF 同分页。
验收
必须完成公共链式 P/Table/P、Java 模板循环/引用、全树 ID/预算/取消、父子双跨度及非对称 padding、短区原子移页、最终字段/图文链接、标准 DOCX/去元数据输入与尾段/书签归属检查。全部新 PDF 页独立解析、双渲染并逐页复查;历史基线不自动刷新。Word 读取、更新、保存、重开及导出分别登记,失败不改写为通过。