ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

genoffice pdf2docx Latin 黄金用例指南:从词间距阈值到流式表格检测的回归语料设计

genoffice pdf2docx Latin 黄金用例指南:从词间距阈值到流式表格检测的回归语料设计 人工智能AI 应用桌面应用AI AgentMCP 服务AI 技能【免费下载链接】genofficeFree, open-source AI Office suite: Docs, Sheets, Slides, PDF, Markdown and HTML editors with a built-in AI agent, plus a genoffice CLI and agent skill so Claude Code, Codex and Cursor can create and edit real .docx/.xlsx/.pptx files locally. Bring your own key. macOS, Windows Linux.项目地址https://gitcode.com/gh_mirrors/ge/genoffice点击查看免费下载packages/pdf2docx是 genoffice 中负责「PDF → DOCX」本地转换的纯函数包字节进、字节出PDFium wasm 由调用方初始化并注入。本文以其测试语料目录tests/golden/en/Latin 黄金用例为骨架讲解该目录承载的回归覆盖目标——自适应词间距阈值、行尾连字符拼接、左/中/右对齐、首行缩进以及三个 P3 布局夹具booktabs 流式表格、两栏文本、before_space 间距链的检测预期并结合 fixtures.ts、integration.test.ts、stream.test.ts 与 stream.ts、words.ts、spacing.ts 等源码还原每条断言背后的实现原理。读完本文你将理解这套语料库如何以「宁可漏检、不可误检」为基调用最少的人工 PDF 样本覆盖 PDF→DOCX 转换中最容易翻车的拉丁排版场景。golden/en 的定位拉丁文字的回归主战场tests/golden/是 pdf2docx 的多语言黄金回归语料库每个语言目录存放一对输入name.pdf输入文档与name.expected.json期望断言段落文本顺序、逐段对齐/缩进、图片数量、预期 warnings。golden/README.md 明确定义了各语言的覆盖分工en/—— 拉丁文本词间距阈值、连字符、对齐用例zh/—— 简体中文不插入多余空格、eastAsia 字体槽、中英混排 run 切分ja/—— 日文假名/汉字混排竖排页面降级为位图ko/—— 韩文保留真实谚文词间空格ar/—— 阿拉伯文P1 阶段预期降级位图P2 起输出真实 RTL 文本。golden/en/README.md 把拉丁侧的目标收敛为四类核心能力自适应词间距阈值tight/loose tracking紧排/松排字距、大字号下词与词之间的判断不能依赖固定阈值行尾连字符拼接断行连字符hyphenation必须被还原为无缝的词拼接对齐还原left/center/right 三种对齐方式首行缩进first-line indent 的正确继承。同时给出移植约定把上游 pdf2docx 的 issue #103丢失/多余的词空格移植为issue-103-*用例作为本目录的命名起点。自适应词间距阈值为什么固定阈值会翻车拉丁文本重建时最典型的缺陷是「丢空格」或「多空格」。pdf2docx 上游 issue #103 正是此类问题视觉上紧排tight tracking的排版容易被固定阈值误判为词内间距导致两个单词被粘成一个松排loose tracking则反过来可能把词内字距误判为词间空格。en 语料库的第一项覆盖目标就是针对这个失败模式。genoffice 的实现把阈值设计成「随字体与行内字距自适应」核心代码在 words.tsexport function spaceGapThreshold(fontSize: number, medianCharGap: number): number { const base 0.18 * fontSize if (medianCharGap 0.06 * fontSize) return Math.max(base, medianCharGap 0.1 * fontSize) return base }基础阈值是字号的一个比例0.18 * fontSize因此随大字号自然放大不会在小字下误切、大字下漏切当该行自身字距中位数tracking偏松超过0.06 * fontSize时阈值被进一步抬高为medianCharGap 0.1 * fontSize避免把字距当作词距medianCharGapwords.ts L110-L121只统计「明确的词内相邻字形间隙」且排除空格字符两侧防止一个真词距混入小样本把阈值自己抬高。除词距外words.ts 还处理了「字距拉开的大标题」如A TOAST TO THE JOURNEY AHEAD当一行内足够多的词内字形间隙落在 0.5–2 em 区间且围绕中位数均匀分布时判定为 letter-spaced 展示行——这些间隙既不能切分行单元也不能被推断为空格整行保持一个 run由 spans 层在 DOCX 中还原为w:spacing字距。这正是 en 语料「loose tracking」与「大字号」两类目标的底层支撑。行尾连字符两个层面的拼接策略连字符断行在 PDF 中由 PDFium 的文本提取标记承载HYPHEN_MARKER 0x02是 PDFium 生成的连字符标记符不带字形靠行级标志保留lines.ts L23-L24、words.ts L26-L27。但仅靠 PDFium 标志不够——blocks.ts L358-L384 注释指出PDFium 的行尾连字符标志会漏掉大量真实连字符断行重建后的文本会读出ex pected这样的残词。因此 genoffice 加了一层保守的文本级回退P21 Bconst LATIN_THEN_HYPHEN /\p{ScriptLatin}[-‐]$/u const SOFT_HYPHEN_END /\u00AD$/ const LOWER_LATIN /^\p{Ll}$/u function isTextHyphenation(prev: Line, next: Line): boolean { const prevText lineText(prev).trimEnd() if (SOFT_HYPHEN_END.test(prevText)) return true if (!LATIN_THEN_HYPHEN.test(prevText)) return false const first [...lineText(next).trimStart()][0] return first ! undefined LOWER_LATIN.test(first) /\p{ScriptLatin}/u.test(first) }规则刻意收窄避免误拼前一行以「拉丁字母 连字符」结尾且下一行以小写拉丁字母开头 → 判定为断行中间词无缝拼接软连字符 U00AD 只用于标记换行点总是拼接下一行以大写字母或数字开头则保持原样——那更可能是复合词或列表项拼了反而错。该判定结果写入endsWithHyphen行标志供groups、词距等下游层共享例如诗歌verse检测会显式排除连字符行blocks.ts L411a hyphen wrap is prose by definition。P3 布局用例三个夹具与它们的端到端断言en 目录的 P3 布局用例不落地静态 PDF 文件而是由 fixtures.ts 用 pdf-lib在测试时现场生成再经 integration.test.ts 走「真实 PDFium wasm →convertPdfToDocx→ docx-engineparseDocx」全链路断言。三个夹具分别对应三个最易误判的版面结构。buildStreamTablePdfbooktabs 式无边框表格必须成表夹具代码在 fixtures.ts L289-L312一页上先画一行正文Quarterly results follow:再画 3 行 2 列文本Region/Revenue、North/1200、South/890列锚点 x72 与 x300最后只画三条水平线顶部规则、表头下规则、底部规则x 从 68 到 360——没有任何竖线因此传统的 lattice格线检测通道永远无法认领它必须由 stream流式检测器出手。integration.test.ts L174-L195 的端到端断言result.warnings为空正文段Quarterly results follow:留在表格之前的流中生成真实的 docx 表格块3 行、表头[Region, Revenue]、末行[South, 890]。buildTwoColumnPdf两栏文本必须成节绝不误判成表夹具在 fixtures.ts L314-L340左右两栏各 6 行等长文本x72 与 x320列主序写入先左栏 6 行再右栏 6 行行高均匀 14pt——外观上与 6×2 的表格网格几乎无法区分。这正是上游 pdf2docx issue #136 的「假表格」fake table失败模式两栏版式被误检为表格导致整页排版错乱。integration.test.ts L205-L222 断言通过 docx-engine 的readSectionSettings读回columns 2输出w:cols分节阅读顺序严格「左栏整列在前、右栏整列在后」smooth grey stones左栏末尾必须出现在Right column starts右栏开头之前integration.test.ts L197-L202 同时确认此页绝不产出 table 块。这个「既要两栏成节、又要拒绝成表」的双重断言把列检测与表检测两个模块钉在正确分工上。buildSpacedPdf大段留白必须还原为段落间距夹具在 fixtures.ts L342-L358页面下方画一个 18pt 粗体标题Spaced Titley640再隔一大段空白画三行正文y500 起。PDF 是绝对定位而 DOCX 是流式排版——两者之间的大段垂直空白必须被「before_space 链」转成下方块block的spacingBefore否则正文会直接贴到标题上。integration.test.ts L224-L243 的断言量化了转换结果标题的spaceBefore 300 twips 且 1000 twips页顶空白减去钳制到 108pt 的页边距后约 31pt ≈ 620 twips正文的spaceBefore 2000 twips 且 3000 twips标题与正文间约 127pt 减去正常行距 ≈ 2500 twips。底层实现在 spacing.ts L38-L66applySpacingChain逐节逐列扫描流内块把「上一块 ink 底边到下块 ink 顶边」的完整间隙写入spacingBeforePtrebuild 层用精确行高重建所以间隙是 ink-to-ink 全额传递。同时有三个工程细节间隙小于EMIT_MIN_PT 2pt视为噪声不写字段负间隙块重叠钳到 0 并返回 warning上限钳在 1584对应 DOCX 合法上限非有限值Infinity跳过浮动图片float与「微文本块」所有 run 字号 2.5pt 的隐藏 fidelity 微文本不参与链避免把不可见内容撑成页面空白。流式表格检测器的负例族宁可漏检不可误检en 目录最后一部分指出的负例族negative family位于 stream.test.ts普通段落、诗歌、TOC 点线、代码块、2 行 label/value 无规则对全部必须被流式检测器拒绝。未来上游新的误检misfire报告都作为issue-n-*用例移植进这个文件。该基调在源码里写得很直白——stream.ts L1-L11 的模块注释The bias isMISS RATHER THAN MISFIRE宁可漏检不可误检对齐的正文行、页面分栏、TOC 引导点、诗歌都必须被拒绝因此一个候选区域要同时通过所有硬门控hard gate与置信度阈值。门控体系stream.ts L25-L52包括常量含义STREAM_MIN_ROWS / STREAM_MIN_COLS 2最小网格尺寸比它小的永远不是表格COL_ALIGN_MIN_ROW_RATIO 0.6每列主边缘至少 60% 的行对齐ALIGN_TOL_EMS 0.4列边缘在该 em 数内视为对齐ROW_GAP_MAX_RATIO 1.6垂直间隙超过较高行高 1.6 倍则断开区域CONTENT_GAP_RATIO_MAX 10中位单元格宽 ÷ 中位列间隙超过 10 散文PARA_FILL_MIN 0.85PROSE_WIDTH_EMS 10列被文本填满 85% 且单元达 10 em 段落PAGE_COVER_RATIO 0.7区域覆盖页面 70% 单元时触发「页面分栏」检验STREAM_CONF_MIN 0.5接受候选的最低置信度检测主流程是findCandidates → collectCandidates(solveColumns) → 门控 → confidenceOf候选构造stream.ts L136-L215连续多单元行按垂直间隙成 run2 行候选只有在「有矢量证据」时才被接受见下列求解solveColumnsstream.ts L275-L302用 XY-Cut 风格的 x 投影mergeIntervals把候选区域切成列间隙小于VALLEY_MIN_EMS 0.4em的谷视为列内噪声散文否决isParagraphLikestream.ts L362-L365拒绝「列被持续填满且单元句子长度」的区域isPageColumnsstream.ts L387-L404专门拒绝整页覆盖、行距均匀、单元多词的分栏文本——即 issue #136 的假表格isMajorityFullProsestream.ts L375-L379兜住 P23 类「多数行都是整句」的页尾残带矢量证据加分findEvidencestream.ts L513-L532区域内水平线booktabs 规则横跨区宽 50% 以上计 stroke 证据行带填充计 fill 证据置信度公式confidenceOfstream.ts L539-L547基础 0.33 行起加 0.15 深度奖励对齐率线性加分stroke 0.2、fill 0.15。2 行候选在无证据时最多0.3 0.15 0.45 0.5必然被拒——这解释了为什么裸 2×2 网格会被放弃miss而三条横线的 booktabs 2 行表会被接受。负例族在 stream.test.ts L228-L412 中逐一落地普通段落行、诗歌短行、TOC 点线点距 6pt 的小间隙不切分单元见 stream.test.ts L51-L56、缩进代码块、两栏正文stream.test.ts L327-L349、以及 P23 的「页面分栏尾部 页脚行」幻影表格回归stream.test.ts L351-L375。诗歌场景还有专门分支并排诗节side-by-side stanzasP22 E经isVerseColumns判定后不按普通表重建而是重建为单行精确几何的堆叠单元格保住每节诗的整体性与逐行断行stream.ts L462-L505。黄金用例的命名与移植约定golden/README.md 给出两条语料维护约定en 目录是第一条的实例上游负例按 issue 号命名移植来自 pdf2docx 上游 issue 的负例丢失/翻倍空格 #103、RTL 反转 #73命名为issue-n-*en 目录当前以issue-103-*为第一个目标PDF 来源两可夹具见tests/helpers/fixtures.ts或自由许可样本均可入库P1 阶段以「现场生成夹具 结构」发货随每次修复逐步沉淀提交样本配套的目录遍历 runner 在首个提交样本时落地。负例的命名归属也做了分流P3 布局负例两栏误检等走 fixtures integration 全链路而 stream 检测器单元级负例诗歌、TOC、代码块、label/value 对集中在stream.test.ts未来上游新的误检报告统一加为issue-n-*用例golden/en/README.md L17-L20。如何运行与扩展这套用例本包是纯函数包不依赖 Electron。运行测试前需要先构建 PDFium wasm 模块并让测试 helper 能加载它helpers/wasm.ts经loadPdfium注入convertPdfToDocx。在仓库根目录cd packages/pdf2docx npx vitest run tests/integration.test.ts # P3 端到端stream 表 / 两栏 / before_space npx vitest run tests/stream.test.ts # 流式检测器单元级正负例 npx vitest run tests/spacing.test.ts tests/words.test.ts扩展新回归用例的路径也很清晰版面级场景在 fixtures.ts 增加一个buildXxxPdf()用 pdf-lib 的PDFDocumentStandardFonts即可确定性生成拉丁页再在 integration.test.ts 用parseDocx断言段落文本、readSectionSettings断言分节、表格模型断言行列检测器门控场景直接复用 helpers/chars.ts 的mkText/mkChar手工构造字形流在 stream.test.ts 以detectStreamTables(unitsOf(chars), shapesOf(...))断言tables/remainingUnits无需启动 wasm上游回归按issue-n-*命名规则移植到对应目录与文件保持语料可追溯。小结tests/golden/en/表面上是几个夹具与一段覆盖说明背后是 pdf2docx 拉丁重建三条主线的测试契约词间距与连字符的文字保真words.ts自适应阈值 blocks.ts保守拼接、版面结构的分工stream.ts与columns.ts各自认领表格与分栏两栏页绝不产出 table 块、流式排版的间距还原spacing.ts的 before_space 链。其「miss rather than misfire」的检测哲学与issue-n-*的移植约定让它既是回归测试集也是新 PDF 场景接入转换管线的第一道准入门——这正是阅读并维护该语料库时最值得掌握的心智模型。赞分享人工智能AI 应用桌面应用AI AgentMCP 服务AI 技能【免费下载链接】genofficeFree, open-source AI Office suite: Docs, Sheets, Slides, PDF, Markdown and HTML editors with a built-in AI agent, plus a genoffice CLI and agent skill so Claude Code, Codex and Cursor can create and edit real .docx/.xlsx/.pptx files locally. Bring your own key. macOS, Windows Linux.项目地址https://gitcode.com/gh_mirrors/ge/genoffice点击查看免费下载相关推荐如何用MarkItDown快速将PowerPoint转换为结构化Markdown文档如何用MarkItDown快速将PowerPoint转换为结构化Markdown文档 你是否经常需要将PowerPoint演示文稿转换为Markdown格式却人工智能AI 应用桌面应用AI AgentMCP 服务AI 技能量化金融策略测试完整指南从计划到用例设计的黄金法则量化金融策略测试完整指南从计划到用例设计的黄金法则 在量化金融领域构建稳健的交易策略需要系统化的测试方法。gs quant作为专业的Python量化工具包金融科技数据分析告别无效压缩Luban ignoreBy参数的黄金阈值设置指南告别无效压缩Luban ignoreBy参数的黄金阈值设置指南 你是否遇到过这样的困境使用Luban压缩图片时小图被过度压缩导致模糊大图却因未触发压缩而图像处理移动开发上一篇Qwen2.5-VL-7B-Instruct-quantized.w8a8终极评估报告MMLU和MGSM基准测试性能深度解析下一篇Unity3DTraining 设计模式全景指南23 种经典模式的 C 源码实现与游戏实战解读创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表