release: 发布 v0.6.2 DOCX 真实文档修复

新增能力:将 DOCX 发布验收拆分为四套独立 140,支持真实语料冻结、指纹复用、失败与基础设施错误独立统计,并为表格换行、全 JSON 围栏、代码连续性和长文档分页建立通用门禁。

问题修复:冻结 Paged.js 分片前的逻辑表格列轨并传递打印几何,统一 Markdown 表格换行、代码、段落与 OOXML 翻译;改进 PDF 文本流排序、语义块映射、颜色与栅格比较,消除窄字符重叠和跨行范围符号误报。

兼容与部署:版本统一为 0.6.2;正式 Docker 镜像内置固定 Chromium、Pandoc 3.9.0.2 和 Serif/Sans/Mono 字体;Desktop NSIS 与 ZIP 继续直接内置字体,无需系统字体安装。

验证结果:合成基线与长庆严格 280/280,M4N 140/140;健康数据残余误报 6/115(5.22%),均核查为重复表头自动对齐/取样误报且基础设施错误为 0。全项目测试、类型检查、生产构建和 git diff --check 通过;正式 Docker、NSIS、ZIP、离线镜像、部署包、清单及 SHA-256 均已生成并校验。
This commit is contained in:
SkyJourney
2026-08-26 10:50:20 +08:00
parent 01b06abc2c
commit 64445322eb
75 changed files with 9255 additions and 298 deletions
@@ -40,9 +40,88 @@ describe("PDF 文本行聚合", () => {
]);
});
it("合并 Office 同一视觉行内小于字体高度两成的基线漂移", () => {
const left = item("源系统", 10, 100, 30, 10);
const middle = item("nut_pickup_order.meal_type", 42, 101.8, 140, 10);
const right = item("原值", 184, 100, 20, 10);
const lines = aggregatePdfTextLines([left, middle, right], 842);
expect(lines).toHaveLength(1);
expect(lines[0]?.normalizedText).toBe(
"源系统nut_pickup_order.meal_type原值",
);
});
it("将同行公式的上标片段按横坐标并回正文", () => {
const lines = aggregatePdfTextLines(
[
item("减因子", 10, 100, 42, 12),
item("e", 53, 97, 8, 15),
item("−λΔt", 62, 96, 24, 10),
item("的动态权重", 87, 100, 70, 12),
],
842,
);
expect(lines).toHaveLength(1);
expect(lines[0]?.normalizedText).toBe("减因子e−λΔt的动态权重");
});
it("将超出正文右缘但紧邻行末的公式片段并回正文", () => {
const lines = aggregatePdfTextLines(
[
item("性、记忆重要程度、时效性衰减权重(须支持基于时间衰减因子 e", 150, 469.5, 346, 12),
item("−λΔt", 495.7, 466.1, 26, 10.2),
item("下一视觉行", 150, 489.7, 60, 12),
],
842,
);
expect(lines.map((line) => line.normalizedText)).toEqual([
"性、记忆重要程度、时效性衰减权重(须支持基于时间衰减因子 e−λΔt",
"下一视觉行",
]);
});
it("将字体 ToUnicode 中的传统户部件归一为简体字符", () => {
expect(normalizePdfText("戶⼾")).toBe("户户");
expect(normalizePdfText("⻅⻆⻓⻔⻚⻛")).toBe("见角长门页风");
expect(normalizePdfText("⻅⻆⻓⻔⻚⻛⻝⻣⻋⻬")).toBe(
"见角长门页风食骨车齐",
);
});
it("统一 Chromium 与 Office PDF 文本层的中英文弯引号", () => {
expect(normalizePdfText("“记录”与‘计算’")).toBe('"记录"与\'计算\'');
});
it("保留与全角括号重叠的窄引号文本流顺序", () => {
const lines = aggregatePdfTextLines(
[
item("主观定性判断", 532.3, 151.5, 58.5),
item("”", 590.8, 151.5, 3.4),
item("(如", 589.3, 151.5, 19.5),
item("“", 608.8, 151.5, 3.4),
item("高心率占比", 612.2, 151.5, 48.8),
],
595,
);
expect(lines).toHaveLength(1);
expect(lines[0]?.normalizedText).toBe('主观定性判断"(如"高心率占比');
});
it("忽略 Emoji 文本层可选的变体选择符", () => {
expect(normalizePdfText("⚠️ 提示")).toBe("⚠ 提示");
});
it("统一 CJK 字体文本层的 em dash 与 horizontal bar", () => {
expect(normalizePdfText("仓库―仓区")).toBe("仓库—仓区");
});
it("统一数字区间中被 Chromium 提取为双连字符的 en dash", () => {
expect(normalizePdfText("10% -- 20%")).toBe("10%20%");
expect(normalizePdfText("10% --")).toBe("10%");
expect(normalizePdfText("命令 --flag")).toBe("命令 --flag");
});
it("从可编辑正文契约中移除 Word 自动列表装饰符", () => {