# clreq 符合度声明矩阵

> 依据：W3C《Requirements for Chinese Text Layout / 中文排版需求》。
> 条款编号取自 W3C TR 快照（2026-08-04 抓取；与 gh-pages Editor's Draft
> 在本文涉及的条款上无实质差异）。
> 对象：`luatex-cn` main 分支（v0.3.8 + 未发布改动）。
> 配套内部文档：`CLREQ-GAP-ANALYSIS.md`（差距分析与规划）、
> `CLREQ-HORIZONTAL-PLAN.md`（横排实施）、`ai_must_read/clreq-shared-core.md`（共享内核契约）。

---

## 0. 声明口径

### 0.1 后端列

| 列 | 指代 | 说明 |
|----|------|------|
| **横排** | `\usepackage{luatex-cn}`（统一入口的默认分支；实现在 `tex/hori/` + `tex/shared/`，内部名 `luatex-cn-hori` 仍可直接加载） | 挂在任意 LaTeX 横排文档类上 |
| **竖排** | `ltc-cn-vbook` / `ltc-tw-vbook` 文档类（`tex/core/` + `tex/shared/`） | 现代竖排书 |

**`ltc-guji` / `ltc-guji-digital` 不在本矩阵声明范围内。** clreq 明确写道
「至于古籍排版，非本文件所及」；古籍类以复刻底本版面为最高优先级，标点挤压
保持 `squeeze-mode=legacy`（无条件挤压）等历史行为，**不宣称 clreq 符合**。
用户可通过与竖排列相同的配置键显式启用各项新规则。

### 0.2 状态取值

| 记号 | 含义 |
|------|------|
| ✅ 实现 | 条款的规范性要求已实现，且有可核查证据（断言/单测/回归用例） |
| 🟡 部分实现 | 条款的一部分要求已实现；备注列说明缺哪一部分 |
| ⚠️ 有意偏离 | 已实现但与 clreq 字面不一致，偏离内容与理由见第 9 节 |
| ❌ 未实现 | 未实现，在路线图内（见差距分析 P1–P7 / H4–H6） |
| 🚫 不实现 | 有意不实现，理由见第 10 节 |
| ➖ 不适用 | 对该后端无意义（如直排专属条款之于横排），或非排版引擎职责 |

### 0.3 证据与复核

「证据」列给出实现位置与测试位置。所有声明可用以下命令复核：

```bash
texlua test/run_all.lua                  # 单元测试（43 个文件）
python3 test/clreq_test.py               # clreq 度量断言（119 条，每条注明条款）
python3 test/geometry_test.py            # 列内基线等距自校验
python3 test/regression_test.py check    # 像素回归（basic/past_issue/complete）
```

断言测试直接解析 PDF 内容流度量「行末逗号占多宽」「中西间距是否在
[1/8, 1/2] em 内」等规范量，并带负对照（关闭开关后断言应失败）证明区分力。

### 0.4 统计速览（2026-08-05）

对每个后端只统计其适用条款（剔除 ➖ 与 🚫），✅ 计 1、🟡/⚠️ 计 0.5、❌ 计 0，
各条款等权：

| 后端 | 适用条款 | ✅ | 🟡/⚠️ | ❌ | 覆盖率 |
|------|---------|----|-------|----|--------|
| 横排 `luatex-cn-hori` | 43 | 29 | 5 | 9 | **≈ 73%** |
| 竖排 `ltc-cn-vbook` / `ltc-tw-vbook` | 43 | 22 | 10 | 11 | **≈ 63%** |
| 两后端合并 | 86 | 51 | 15 | 20 | **≈ 68%** |

百分比只是速览，**逐条状态与证据（下文各表）才是本文的声明本体**；
条款等权也意味着它与工作量完成度（见差距分析第 7 节，按人日约 54%）不是
同一口径——剩余条款集中在实现成本最高的中西混排、注音与标题层。

---

## 1. 第 2 章 · 文本方向

| 条款 | 要求 | 横排 | 竖排 | 证据 / 备注 |
|------|------|------|------|------------|
| 2.1.1 | 中文的行文模式（横排左起 / 直排右起换列向左） | ✅ | ✅ | 竖排网格引擎（`core/luatex-cn-layout-grid.lua`）；直排列右→左、页序右翻 |
| 2.1.2 | 横直排差异点（标点直排形式、装订方向、页面镜像） | ➖ | 🟡 | vert 形替换 + PUA/tounicode 还原（`core/luatex-cn-core-punct.lua`）、`twoside` 镜像边距；个别标点直排形式依赖字体，缺字时对 `—`/`…` 退化为旋转 |
| 2.1.3 | 直排的中、西文混排配置（全角直立 / 旋转 90° / 中横排；汉字与西文间距） | ➖ | ✅ | **中西间距已实现**（P3 第一步）：汉字与西文字母/数字边界 1/4em、可挤 1/8 拉 1/2、点号旁与夹注号内侧不加——规则本体 `shared/luatex-cn-cjk-western.lua` 与横排同源，`western-space` 键可关，仅 context 挡位生效；断言 8 条 + 负对照。三种西文配置：全角直立 = 默认逐字入格；**旋转 90° 已实现**（`\横置`/`\Sideways`：字幅 = advance、串内零字距、共用竖直基线，断言「字母连排步长 0.5em vs 直立 1.1em」，回归 `sideways.tex`）；**中横排已实现**（`\中横排`/`\CombineUpright`：整组共占一个字幅，超 1em 只做横向压缩、字高不变，适合两三位数字/极短西文；断言 6 条含负对照——跨组步长 2.5em vs 直立 3.6em，回归 `combine-upright.tex`）。三种西文配置至此齐备 |
| （2 章相关） | 双向文本（bidi） | 🚫 | 🚫 | 见第 10 节 |

## 2. 第 3 章 · 字形的变形与定位

| 条款 | 要求 | 横排 | 竖排 | 证据 / 备注 |
|------|------|------|------|------------|
| 3.1.1 | 宋 / 楷 / 黑 / 仿宋四体及其用途 | 🟡 | 🟡 | 字体族探测与回退完善（`fonts/`，Linux 方案全开放授权字体）；缺「宋体作正文、黑体作强调」的语义化字体角色层 |

## 3. 第 4 章 · 排版单元

| 条款 | 要求 | 横排 | 竖排 | 证据 / 备注 |
|------|------|------|------|------------|
| 4.1 | 字符与编码（以 Unicode 字符为排版单元） | ✅ | ✅ | LuaTeX 原生按 Unicode 处理 |
| 4.1.1 | 儿化小字（U+16FF2/3） | 🚫 | 🚫 | 见第 10 节 |

## 4. 第 5 章 · 标点符号与其他行内特性

| 条款 | 要求 | 横排 | 竖排 | 证据 / 备注 |
|------|------|------|------|------------|
| 5.1 | 点号 / 标号分类与基本用法 | ✅ | ✅ | 共享标点全表 24 类单一数据源（`shared/luatex-cn-punct-table.lua`）；竖排分类从表派生（PR #126）；单测 `shared/punct-table-test` |
| 5.1.1.1 | 科技文献（句点作 `.` 等特殊体例） | ❌ | ❌ | 低优先级，未列入近期路线图 |
| 5.1.1.2 | 港台出版品的特殊情况（点号居中、`？！` 不调整等） | ✅ | ✅ | `style=taiwan` 预设；断言「台式？！固定一字宽」「台式行末 0.75em 占位」；回归 `hori-taiwan.tex`、`tw-vbook.tex` |
| 5.1.1.3 | 叹问号叠加（？？ ！！ ？！ ！？ 及 ‼ ⁇） | ✅ | ✅ | 两字宽刚性整体（PR #139 共享层；竖排经 `ATTR_RIGID_PREV=2` 落地）；压力用例相位扫描 23 处 + 负对照 |
| 5.1.1.4 | 示亡号 | ❌ | ❌ | 竖排可用 `\decorate` 手工近似；未做自动排版 |
| 5.2 | 引文（引号体例；直排用直角引号） | ✅ | ✅ | 横排 `quote-style`（keep/auto/curly/corner，默认不改来稿）；竖排弯引号→直角引号替换；断言「台湾用传统引号先单后双」 |
| 5.3.1 | 着重号（字下/右侧圆点、标点上不加、逐字对心） | ✅ | ✅ | 横排 `\着重`；竖排 `\着重号` 在 vbook 两类的 cfg 里配 `char=●, skip-punct=true`（clreq 规定的 U+25CF/U+2022，直排在右侧 + 标点上不加），判定走共享标点表 `decorate.is_punct_char`。`ltc-guji` 保持古籍圈点体例（`○`、标点也圈）。回归 `emphasis-clreq.tex`（含 `skip-punct=false` 负对照）。**台湾式依据不同**：clreq 注明台湾《重订标点符号手册》未收录着重号，此处取通用形态，见第 9 节第 6 条 |
| 5.4.1 | 省略号（占两字、不可拆、不可置行首末拆开） | ✅ | ✅ | 两字宽整体单元（横排 penalty 包裹；竖排 #119 不拆列、内部字距归零）；断言「总占位 ≈ 2em、内部零间隙」 |
| 5.5.1–5.5.2 | 行间注用途与排版概述 | ➖ | ➖ | 描述性条款，无独立规范量 |
| 5.5.3.1–.5 | 注音符号标音（位置、3:10 比例、声调号、分离禁则） | ❌ | ❌ | 度量常量已入 `shared/luatex-cn-ruby-metrics.lua`，排布未做。规划 H4 收尾 / P4 |
| 5.5.4.1–.3 | 罗马拼音标音（基本规则、单字标音、分词连写标音） | 🟡 | ➖ | `\拼音` 已实现基本规则与词对齐；缺注文悬伸与单字标音的正文字距联动。clreq 规定罗马拼音仅用于横排，竖排不适用 |
| 5.5.5 | 汉字标音的非典型情况（儿化标音等） | 🚫 | 🚫 | 随 4.1.1，见第 10 节 |
| 5.5.6 / 5.5.6.1 | 中外文对照与词的对齐 | ✅ | ❌ | `\对照`：注文短于基文加大注文字距、长于基文加大基文字距；断言「注文块与基文块中心对齐 ≤ 0.1em」 |
| 5.5.7 | 行间批语（直排位基文左侧、长度不拘、可换色） | ❌ | ✅ | 竖排侧批 / 夹注 / 眉批体系（`core/luatex-cn-core-sidenote.lua`、`guji/`）能力超出条款要求；横排批语未做 |
| 5.6.1 | 行间标点（专名号 / 书名号甲式；相邻标注两侧缩短 ≤1/8em；行距下限） | ✅ | 🟡 | 横排 `\专名` `\书名号甲` 单面装、相邻各缩 1/16em、行距 ≥0.5em 校验 + warning（`hori/luatex-cn-hori-linemark.lua`）；竖排 `\专名号` `\书名号` 线左着重右、分段正确，但相邻缩短与行距校验未做。双面装为直排概念，横排 ➖ |
| 5.7 | 数据格式与数字（数字串整体性等） | 🟡 | 🟡 | 数字串不拆已由 6.1.2.2 覆盖；全半角数字选用属作者/上游职责，引擎不转换 |

## 5. 第 6 章 · 行与段落版式

| 条款 | 要求 | 横排 | 竖排 | 证据 / 备注 |
|------|------|------|------|------------|
| 6.1.1 | 行首行尾禁则（不处理 / 基本 / GB / 严格 四级） | ✅ | 🟡⚠️ | 共享 `shared/luatex-cn-kinsoku.lua`；横排 `kinsoku-level` 四级可配、penalty 注入、TeX 全局最优；竖排已接 `kinsoku.resolve_overflow`（先挤进后推出的比价），但**级别硬编码为基本级**。禁则解决方式用词典序比价，对 clreq 字面有意偏离（第 9 节第 1 条）。断言：行首禁则相位扫描 + 负对照 |
| 6.1.2.1 | 符号分离禁则 · 两字宽标点不可拆 | ✅ | ✅ | 破折号/省略号/叹问号叠加整体单元（横排 penalty；竖排 #119）；断言「两字宽标点同行零间隙」；回归 `dash_continuity_issue119.tex` |
| 6.1.2.2 | 符号分离禁则 · 数字及前后缀（数字串、%/°/℃、±、货币） | ✅ | ✅ | 共享层字符集判定；竖排经 `ATTR_RIGID_PREV=1` 锁死字距；断言「数字串/单位/货币同行零间隙」+ 负对照（关禁则后确实拆行） |
| 6.1.2.3 | 符号分离禁则 · 注释符号（上下标、注号不与被注文字分离） | ❌ | ❌ | 需要 node 级属性，共享层明确留给后端（`kinsoku.lua` 头注释），两后端均未实现 |
| 6.1.3 | 行尾点号悬挂 | ✅⚠️ | ✅⚠️ | 两后端均由 `hanging-punct` / `标点悬挂` 开关控制，**默认关**（第 9 节第 2 条）。竖排开启时列末点号整幅出列（`ATTR_PUNCT_HANG` → `build_column_gaps` 令 rigid 归零），正文不因它被压缩——clreq 注明悬挂正适用于直排。断言 3 条 + 负对照；回归 `hanging-punct.tex` |
| 6.1.4 | 西文比例字体的断词连字 | ✅ | ❌ | 横排交 TeX 断行器原生处理；竖排无西文断词（规划 P3） |
| 6.2.1.1 | 段首缩排 | ✅ | ✅ | 横排 `paragraph-indent`；竖排缩进体系（含抬头/挪抬） |
| 6.2.1.2 | 段落缩排 / 凸排 | ✅ | 🟡 | 横排 `凸排` / `段落缩排` 环境；竖排段落缩排有、凸排需手工 |
| 6.2.1.3 | 单行对齐（居中 / 行首 / 行尾 / 均排四种） | ✅ | 🟡 | 横排前三种由行盒对齐、`\均排` + `last-line=left/center/right/justify`；竖排 `vertical-align` 提供前三种，均排无用户级开关（引擎层已有，见 6.3.1.2） |
| 6.2.2.1–.2 | 行内调整的必要性 / 挤压与拉伸处理 | ✅ | ✅ | 共享求解器 `shared/luatex-cn-adjust.lua`；横排在 `post_linebreak_filter` 覆写 TeX 比例分配；竖排 `build_column_gaps` + `adjust.solve`（PR #143） |
| 6.2.2.3 | 挤压优先顺序（7 级：行末标点 → 西文词距 → 间隔号 → 夹注符号 → 逗顿分号 → 中西间距 → 句问叹号） | ✅ | ✅⚠️ | 同上；竖排在 clreq 七步之后追加「字距」为最后手段（项目版式选择，第 9 节第 3 条）。断言：挤压行标点空白先于字距被压缩 |
| 6.2.2.4 | 拉伸优先顺序（西文词距 → 中西间距 → 兜底均分；不可拉伸不可分离单元） | ✅ | ✅ | 同上；刚性单元 shrink/stretch 全清零 |
| 6.2.3 | 对齐时西文词距参与行内调整 | ✅ | ❌ | 横排西文词距列挤压第 2 级 / 拉伸第 1 级；竖排无西文词距概念（规划 P3） |
| 6.2.4 | 纵横对齐下的中西文混排（西文占汉字整数倍） | ❌ | ❌ | 规划 P3 |
| 6.3.1.1 | 增加字距（疏排） | ❌ | 🟡 | 竖排可用 `cell_gap` 近似；两侧均无专用「疏排」键 |
| 6.3.1.2 | 均排 | ✅ | 🟡 | 横排 `\均排{}`；竖排引擎层已做（写满换列的列均排到列底，段末列不均排——符合 clreq 正文末行不均排），缺用户级命令 |
| 6.3.1.3 | 减少字距（紧排） | ❌ | ❌ | 两侧均无负字距键；默认密排（无附加字距）两侧 ✅ |
| 6.3.2.1 | 标点符号的调整空间（字面分布与可调空白） | ✅ | ✅ | 墨心度量锚定 `shared/luatex-cn-punct-anchors.lua`（PR #138 中国大陆/台湾 × 横/竖全矩阵；#145 直排夹注号归上/下半格，图 30）。横排夹注号不锚为有意决定（第 9 节第 4 条）。断言「中国大陆式偏靠 Tm 右移 >0.2em」；回归 `bracket_ink_issue105.tex` |
| 6.3.2.2 | 连续标点符号的调整（2 → 1.5 字宽，挤压方向） | ✅ | ✅ | `shared/luatex-cn-punct-squeeze.lua`（PR #132）；`adjacent-punct=1` 可收到 1 字宽；「空白在哪侧就往哪边让」；断言「连续标点 1.5 字幅 + 挤压方向」 |
| 6.3.2.3 | 行首行尾标点挤压（行首开始夹注号半字、行末点号半字） | ✅ | ✅ | 横排 H2（行末标点 ≤ 半字宽为强制断言）；竖排 flatten 预算 `ATTR_PUNCT_TRIM_START/END`、flush 按断列结果取用（PR #143）；断言「行首夹注符号只占半字幅」 |
| 6.3.3 | 横排的中、西文混排配置（1/4em，可挤 1/8、拉 1/2，三类例外） | ✅ | ➖ | `hori/luatex-cn-hori-spacing.lua`；断言「中西间距 ∈ [1/8, 1/2] em」「点号旁不加」「夹注号内侧不加」。直排的对应间距已实现，见 2.1.3 |
| 6.4 | 基线、行高等 | 🟡 | 🟡 | 竖排格内垂直居中按 em 框基线对齐（#113，`geometry_test.py` 自校验）；横排交 TeX 行高模型；未逐条核对本节全部细则 |

## 6. 第 7 章 · 页面与书籍版式

| 条款 | 要求 | 横排 | 竖排 | 证据 / 备注 |
|------|------|------|------|------------|
| 7.1.1.1–.5 | 页面设计（基本版式：字号 / 行长 / 行数 / 行距 / 栏数 / 栏距 / 定版） | 🟡 | ✅ | 竖排 type area 要素齐备、band 分栏；横排版面交宿主文档类（geometry 等），号数字号 `\字号`（初号…八号）横竖排共享。**术语消歧**：clreq「版心」= type area，本项目「版心」= 书页中缝（鱼尾/象鼻） |
| 7.1.2 | 孤行与孤字处理（孤字不成行、孤行不成页） | ✅ | ❌ | 横排 `orphan-char`（段末借字 + 该行均排）+ `widow/club-penalty`；竖排规划 P5 |
| 7.1.3.1–.5 | 标题处理（种类、突显、单页起 / 换页、前页留空、同行标题） | ❌ | ❌ | 竖排 `\换页` 可手工近似 7.1.3.3；占行 / 单页起 / 同行标题 / 跨栏标题未做（需 sectioning 集成，规划 H5 遗留 / P5） |

## 7. 第 8 章 · 表单与用户交互

| 条款 | 横排 | 竖排 | 备注 |
|------|------|------|------|
| 8（全章） | ➖ | ➖ | 面向浏览器/交互式表单，非批排版引擎职责 |

## 8. 附录 A · 中文标点符号表

| 条款 | 要求 | 横排 | 竖排 | 证据 / 备注 |
|------|------|------|------|------------|
| A.1–A.5 | 标点全表（类别、宽度、可调空间、「不可分离」、「直排时的形式」） | ✅ | ✅ | `shared/luatex-cn-punct-table.lua` 单一数据源；竖排分类从表派生（PR #126），连接号 / 间隔号 / 分隔号扩类已派生（`LEGACY_MAP` → middle，中国大陆式间隔号固定半字宽）；「直排时的形式」经 vert 形替换 + 缺字旋转兜底覆盖。断言：扩类宽度 3 条 |

---

## 9. 有意偏离清单

对外宣称符合度时，下列各条**不得表述为完全符合**：

1. **禁则解决方式用词典序比价（6.1.1）**。clreq 字面是「最后没有挤压机会，
   再从前一行取最后一个字」，即挤得进就挤进；本实现对「挤进 / 推出」两个候选
   各解一次求解器，按 clreq 优先顺序的词典序比价——尽量少动最后手段（字距）。
   分歧发生在「挤进可行、但要把字距压得比推出拉得更狠」时：实测有列挤进须把
   字距从 0.1em 压到 0.048em（−52%），推出只需拉到 0.132em（+32%），本实现
   选推出。理由：−52% 的字距在竖排密排里非常刺眼。
2. **行尾点号悬挂两后端均默认关（6.1.3）**。clreq 注明悬挂适用于直排、
   港台横排因点号居中不宜；故做成 `hanging-punct`（竖排别名 `标点悬挂`）
   开关。横排默认关是规范本身的建议；竖排默认关是本项目的取舍——悬挂会
   改变既有 vbook 文档的版面，留给作者按书体例选择。
3. **竖排挤压顺序在 clreq 七步之后追加「字距」兜底（6.2.2.3）**。直排 0.1em
   基准字距是本项目的版式选择，不在 clreq 步骤内，只作最后手段、绝不先于
   标点空白被压缩。
4. **横排夹注号字面不锚定（6.3.2.1）**。横排 advance 起点即字幅始端，字体
   画在哪就是字面分布；实测四款字体开始夹注号墨心在 0.65–0.75em（空白都在
   外侧），强制统一落点反而破坏更贴紧的字体设计（PR #145 的调查结论）。
5. **`ltc-guji` 整类不宣称符合（0.1 节）**。古籍复刻以底本版面为准，默认
   `squeeze-mode=legacy` 无条件挤压等历史行为；新规则仅显式开启时生效。
6. **台湾式着重号无规范依据（5.3.1）**。clreq 原文注明「台湾教育部的
   《重订标点符号手册》（2008 年修订版）中未收录此符号，但仍可见于部分
   台湾的出版物」——台湾官方规范里没有着重号，clreq 也未为台湾式定义
   另一种形态。`ltc-tw-vbook` 默认取 clreq 的通用形态（`●`），属
   「规范外但实务通行」，不是《重订标点符号手册》背书的行为；作者可用
   `\着重号设置{char=…}` 改成本书体例。另注：clreq 的「标点上不加着重号」
   原文是「**通常**不再添加」（建议而非强制），故做成 `skip-punct` 开关。

## 10. 不实现清单（附理由）

| 条款 | 内容 | 理由 |
|------|------|------|
| 第 2 章相关 | 双向文本（bidi） | 阿拉伯文/希伯来文混排超出本引擎职责，LuaTeX 生态有专门方案（如 luabidi）；与竖排网格模型的交互无实际需求 |
| 4.1.1 / 5.5.5.1 | 儿化小字（U+16FF2/3） | 用字极罕见，几乎没有字体覆盖该码位；普通「儿」字排版不受影响 |
| 第 8 章 | 表单与用户交互 | 面向浏览器渲染，非批排版引擎职责 |

「未实现（❌）」各项不在此列——它们在路线图内，状态与工作量见
`CLREQ-GAP-ANALYSIS.md` 第 6–7 节。

---

## 11. 维护约定

- 每完成一个 clreq 相关 PR，**同步更新本矩阵对应行**（状态、证据、PR 号），
  与 `CLREQ-GAP-ANALYSIS.md` 第 0.1 节进度快照同批提交。
- 新增偏离必须进第 9 节，新增放弃必须进第 10 节并给出理由。
- 断言数、测试计数以实际运行输出为准（0.3 节命令），不手算。
