kordoc 4.21.8 → 4.21.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +15 -11
  2. package/dist/{-7C4HXU7Z.js → -3K3QNRP7.js} +11 -11
  3. package/dist/{chunk-II5FJO2S.js → chunk-3DIAVYHS.js} +3 -3
  4. package/dist/{chunk-JLVX2T4V.js → chunk-4IQHSBGA.js} +59 -23
  5. package/dist/chunk-4IQHSBGA.js.map +1 -0
  6. package/dist/{chunk-73KIFZ3I.js → chunk-5BDCETE5.js} +2 -2
  7. package/dist/{chunk-SM6R2TTK.js → chunk-5SGREZ36.js} +60 -24
  8. package/dist/chunk-5SGREZ36.js.map +1 -0
  9. package/dist/{chunk-TX4BEMSL.js → chunk-7F56Y2VV.js} +2 -2
  10. package/dist/{chunk-JYZCQ7W3.js → chunk-AOWEFVJX.js} +2 -2
  11. package/dist/{chunk-UNOSHFZ3.js → chunk-B375LJ27.js} +3 -3
  12. package/dist/{chunk-BLAILU6W.js → chunk-D234SVXL.js} +2 -2
  13. package/dist/{chunk-4B5XTUM3.js → chunk-DT4UY5MZ.js} +2 -2
  14. package/dist/{chunk-L2QGHHWS.js → chunk-EPPNA2KB.js} +2 -2
  15. package/dist/{chunk-L2QGHHWS.js.map → chunk-EPPNA2KB.js.map} +1 -1
  16. package/dist/{chunk-QC3CWCPK.js → chunk-FXWRLGQF.js} +2 -2
  17. package/dist/{chunk-64POCX2L.js → chunk-FZQV2ZO6.js} +2 -2
  18. package/dist/{chunk-BNSJ5NJD.cjs → chunk-MGVFUAWH.cjs} +3 -3
  19. package/dist/{chunk-BNSJ5NJD.cjs.map → chunk-MGVFUAWH.cjs.map} +1 -1
  20. package/dist/{chunk-7PLEBAU5.cjs → chunk-NFIOC6CS.cjs} +3 -3
  21. package/dist/{chunk-7PLEBAU5.cjs.map → chunk-NFIOC6CS.cjs.map} +1 -1
  22. package/dist/{chunk-JDZFYVYC.cjs → chunk-ONQS3YOG.cjs} +2 -2
  23. package/dist/{chunk-JDZFYVYC.cjs.map → chunk-ONQS3YOG.cjs.map} +1 -1
  24. package/dist/{chunk-QTIPY5LH.js → chunk-PFG6AN6H.js} +2 -2
  25. package/dist/{chunk-FW7NJPIA.js → chunk-PGPGPM5J.js} +2 -2
  26. package/dist/{chunk-G23YYJXZ.js → chunk-Q2DQ3NZB.js} +4 -4
  27. package/dist/{chunk-KRSSVUPV.js → chunk-QMWVKGXI.js} +6 -6
  28. package/dist/{chunk-5C4W5S34.cjs → chunk-RDTXIMMP.cjs} +6 -6
  29. package/dist/{chunk-5C4W5S34.cjs.map → chunk-RDTXIMMP.cjs.map} +1 -1
  30. package/dist/{chunk-XGVDKRIS.js → chunk-RU3ESQI3.js} +2 -2
  31. package/dist/{chunk-XGVDKRIS.js.map → chunk-RU3ESQI3.js.map} +1 -1
  32. package/dist/{chunk-GZQAE5M7.js → chunk-RUPSY4T4.js} +2 -2
  33. package/dist/{chunk-BX4LK3XX.js → chunk-VRWHLWSW.js} +10 -10
  34. package/dist/{chunk-H7WK4BYC.js → chunk-WP7JK5ZR.js} +3 -3
  35. package/dist/{chunk-X4MTGJD2.js → chunk-WZTRVWKQ.js} +2 -2
  36. package/dist/{chunk-K5O4DWPN.cjs → chunk-X33QDIUK.cjs} +206 -170
  37. package/dist/chunk-X33QDIUK.cjs.map +1 -0
  38. package/dist/{chunk-XLKLESIG.js → chunk-X4TZEAYE.js} +2 -2
  39. package/dist/{chunk-D6UUPJXL.cjs → chunk-XG55OZTQ.cjs} +13 -13
  40. package/dist/{chunk-D6UUPJXL.cjs.map → chunk-XG55OZTQ.cjs.map} +1 -1
  41. package/dist/{chunk-QSVI22OY.js → chunk-ZPB5MTYP.js} +2 -2
  42. package/dist/chunks-RA26PEF7.js +10 -0
  43. package/dist/cli.js +30 -30
  44. package/dist/{formula-7W52NUG7.cjs → formula-5RQKN6UM.cjs} +9 -9
  45. package/dist/{formula-7W52NUG7.cjs.map → formula-5RQKN6UM.cjs.map} +1 -1
  46. package/dist/{formula-LMVH3EAJ.js → formula-AFDU5B2J.js} +3 -3
  47. package/dist/{formula-ZWXACY7X.js → formula-WXHFQE4T.js} +4 -4
  48. package/dist/{image-ocr-HKIJRUS5.js → image-ocr-2BC7V7J4.js} +9 -9
  49. package/dist/{image-ocr-BAHUQ2OR.cjs → image-ocr-7OWBI7DA.cjs} +15 -15
  50. package/dist/{image-ocr-BAHUQ2OR.cjs.map → image-ocr-7OWBI7DA.cjs.map} +1 -1
  51. package/dist/{image-ocr-V4LM2FGJ.js → image-ocr-EGSQRSZ7.js} +6 -6
  52. package/dist/index.cjs +276 -276
  53. package/dist/index.js +5 -5
  54. package/dist/mcp.js +22 -22
  55. package/dist/{model-bundle-W7HODZJ4.js → model-bundle-C4K4X224.js} +5 -5
  56. package/dist/{models-S5VGNH7N.js → models-VC7YQO2Y.js} +5 -5
  57. package/dist/{parse-worker-v2-QXT74KBZ.js → parse-worker-v2-QIA6PYGX.js} +12 -12
  58. package/dist/{parser-TJRYXAYM.cjs → parser-S53VTR67.cjs} +130 -130
  59. package/dist/{parser-TJRYXAYM.cjs.map → parser-S53VTR67.cjs.map} +1 -1
  60. package/dist/{parser-YNIBEROQ.js → parser-WBDZCJND.js} +11 -11
  61. package/dist/{parser-YRGFCT3A.js → parser-XXBATYBM.js} +8 -8
  62. package/dist/pdf-ocr-K7EZB4BO.js +22 -0
  63. package/dist/pdf-ocr-SXQWKEUL.cjs +19 -0
  64. package/dist/{pdf-ocr-2ROSGLM4.cjs.map → pdf-ocr-SXQWKEUL.cjs.map} +1 -1
  65. package/dist/pdf-ocr-YETVVNZV.js +18 -0
  66. package/dist/{profile-io-YGEHOOTS.js → profile-io-FRKYLVXA.js} +3 -3
  67. package/dist/{rasterize-2QT2K6PA.js → rasterize-OIFQKD2Z.js} +3 -3
  68. package/dist/{redact-doc-YIDHJEOP.js → redact-doc-3772TKD5.js} +11 -11
  69. package/dist/{render-7KABKIXJ.js → render-76VTZCV3.js} +7 -7
  70. package/dist/seal-SB45RMGC.js +10 -0
  71. package/dist/{setup-VGPI2IUL.js → setup-6LCBF5RS.js} +3 -3
  72. package/dist/visual-CMXPHRYA.js +20 -0
  73. package/dist/{watch-G27DA3AE.js → watch-4KAUOPTD.js} +12 -12
  74. package/package.json +1 -1
  75. package/dist/chunk-JLVX2T4V.js.map +0 -1
  76. package/dist/chunk-K5O4DWPN.cjs.map +0 -1
  77. package/dist/chunk-SM6R2TTK.js.map +0 -1
  78. package/dist/chunks-O66WNWJQ.js +0 -10
  79. package/dist/pdf-ocr-2ROSGLM4.cjs +0 -19
  80. package/dist/pdf-ocr-FYBNCV75.js +0 -18
  81. package/dist/pdf-ocr-XPMKGAMM.js +0 -22
  82. package/dist/seal-NTLA3FRC.js +0 -10
  83. package/dist/visual-UAE6G2GM.js +0 -20
  84. /package/dist/{-7C4HXU7Z.js.map → -3K3QNRP7.js.map} +0 -0
  85. /package/dist/{chunk-II5FJO2S.js.map → chunk-3DIAVYHS.js.map} +0 -0
  86. /package/dist/{chunk-73KIFZ3I.js.map → chunk-5BDCETE5.js.map} +0 -0
  87. /package/dist/{chunk-TX4BEMSL.js.map → chunk-7F56Y2VV.js.map} +0 -0
  88. /package/dist/{chunk-JYZCQ7W3.js.map → chunk-AOWEFVJX.js.map} +0 -0
  89. /package/dist/{chunk-UNOSHFZ3.js.map → chunk-B375LJ27.js.map} +0 -0
  90. /package/dist/{chunk-BLAILU6W.js.map → chunk-D234SVXL.js.map} +0 -0
  91. /package/dist/{chunk-4B5XTUM3.js.map → chunk-DT4UY5MZ.js.map} +0 -0
  92. /package/dist/{chunk-QC3CWCPK.js.map → chunk-FXWRLGQF.js.map} +0 -0
  93. /package/dist/{chunk-64POCX2L.js.map → chunk-FZQV2ZO6.js.map} +0 -0
  94. /package/dist/{chunk-QTIPY5LH.js.map → chunk-PFG6AN6H.js.map} +0 -0
  95. /package/dist/{chunk-FW7NJPIA.js.map → chunk-PGPGPM5J.js.map} +0 -0
  96. /package/dist/{chunk-G23YYJXZ.js.map → chunk-Q2DQ3NZB.js.map} +0 -0
  97. /package/dist/{chunk-KRSSVUPV.js.map → chunk-QMWVKGXI.js.map} +0 -0
  98. /package/dist/{chunk-GZQAE5M7.js.map → chunk-RUPSY4T4.js.map} +0 -0
  99. /package/dist/{chunk-BX4LK3XX.js.map → chunk-VRWHLWSW.js.map} +0 -0
  100. /package/dist/{chunk-H7WK4BYC.js.map → chunk-WP7JK5ZR.js.map} +0 -0
  101. /package/dist/{chunk-X4MTGJD2.js.map → chunk-WZTRVWKQ.js.map} +0 -0
  102. /package/dist/{chunk-XLKLESIG.js.map → chunk-X4TZEAYE.js.map} +0 -0
  103. /package/dist/{chunk-QSVI22OY.js.map → chunk-ZPB5MTYP.js.map} +0 -0
  104. /package/dist/{chunks-O66WNWJQ.js.map → chunks-RA26PEF7.js.map} +0 -0
  105. /package/dist/{formula-LMVH3EAJ.js.map → formula-AFDU5B2J.js.map} +0 -0
  106. /package/dist/{formula-ZWXACY7X.js.map → formula-WXHFQE4T.js.map} +0 -0
  107. /package/dist/{image-ocr-HKIJRUS5.js.map → image-ocr-2BC7V7J4.js.map} +0 -0
  108. /package/dist/{image-ocr-V4LM2FGJ.js.map → image-ocr-EGSQRSZ7.js.map} +0 -0
  109. /package/dist/{model-bundle-W7HODZJ4.js.map → model-bundle-C4K4X224.js.map} +0 -0
  110. /package/dist/{models-S5VGNH7N.js.map → models-VC7YQO2Y.js.map} +0 -0
  111. /package/dist/{parse-worker-v2-QXT74KBZ.js.map → parse-worker-v2-QIA6PYGX.js.map} +0 -0
  112. /package/dist/{parser-YNIBEROQ.js.map → parser-WBDZCJND.js.map} +0 -0
  113. /package/dist/{parser-YRGFCT3A.js.map → parser-XXBATYBM.js.map} +0 -0
  114. /package/dist/{pdf-ocr-FYBNCV75.js.map → pdf-ocr-K7EZB4BO.js.map} +0 -0
  115. /package/dist/{pdf-ocr-XPMKGAMM.js.map → pdf-ocr-YETVVNZV.js.map} +0 -0
  116. /package/dist/{profile-io-YGEHOOTS.js.map → profile-io-FRKYLVXA.js.map} +0 -0
  117. /package/dist/{rasterize-2QT2K6PA.js.map → rasterize-OIFQKD2Z.js.map} +0 -0
  118. /package/dist/{redact-doc-YIDHJEOP.js.map → redact-doc-3772TKD5.js.map} +0 -0
  119. /package/dist/{render-7KABKIXJ.js.map → render-76VTZCV3.js.map} +0 -0
  120. /package/dist/{seal-NTLA3FRC.js.map → seal-SB45RMGC.js.map} +0 -0
  121. /package/dist/{setup-VGPI2IUL.js.map → setup-6LCBF5RS.js.map} +0 -0
  122. /package/dist/{visual-UAE6G2GM.js.map → visual-CMXPHRYA.js.map} +0 -0
  123. /package/dist/{watch-G27DA3AE.js.map → watch-4KAUOPTD.js.map} +0 -0
package/README.md CHANGED
@@ -12,7 +12,7 @@ HWP 3.x·5.x, HWPX, HWPML, PDF, XLS·XLSX, DOCX, PPTX, PNG·JPG·WebP를 Markdow
12
12
  [English](README-EN.md) · [상세 사용법](docs/usage.md) · [벤치마크](docs/benchmarks.md) · [변경 이력](CHANGELOG.md)
13
13
 
14
14
  - 📊 **PDF 공개 벤치 종합 0.963** — opendataloader-bench 200문서. 공개 12개 파서 비교 1위(2026-09-29 기록). [측정 조건](docs/benchmarks.md)
15
- - 🇰🇷 **한국 공문서 표 구조 100%** — 원본 HWPX 2,286문서의 보이는 표 **9,865개 전부 구조 일치**. [4.18.8 검증](docs/release-4.18.8.json)
15
+ - 🇰🇷 **한국 공문서 표 구조 100%** — 원본 HWPX 2,424문서의 보이는 표 **10,342개 전부 구조 일치**. [4.21.10 검증](docs/benchmarks.md)
16
16
 
17
17
  [![Kordoc 활용하기 — 영상 보기](./docs/video-demo.jpg)](https://youtu.be/Q13GmgDcIw0)
18
18
 
@@ -98,27 +98,31 @@ await writeFile("보고서.hwpx", Buffer.from(hwpx))
98
98
 
99
99
  ## 검증 결과
100
100
 
101
- **4.18.8 · 2026-10-02 배포 검증**. 고정 코퍼스와 참조 기준으로 측정한 결과입니다.
101
+ **4.21.10 · 2026-10-10 배포 검증**. 고정 코퍼스와 참조 기준으로 측정한 결과입니다.
102
102
 
103
103
  | 대상 | 규모 | 결과 |
104
104
  | --- | --- | --- |
105
- | HWPX | 2,286문서 · 9,865표 | 표 구조 일치 **9,865/9,865 · 100%** |
106
- | HWP 5.x ↔ HWPX | 1,120쌍 · 4,258표 | 짝 문서의 표 구조 일치 **100%** |
107
- | PDF 글 | 744쌍 | 글자 재현율 **99.83%** · 읽기 순서 **99.15%** |
108
- | PDF 표 | 708쌍 · 2,331표 | 표 탐지 **99.83%** · 구조 일치 **97.94%** |
105
+ | HWPX | 2,424문서 · 10,342표 | 표 구조 일치 **10,342/10,342 · 100%** |
106
+ | HWP 5.x ↔ HWPX | 1,130쌍 · 4,315표 | 짝 문서의 표 구조 일치 **100%** |
107
+ | PDF 글 | 744쌍 | 글자 재현율 **99.83%** · 정확도 **99.58%** · 읽기 순서 **99.16%** · 어절 F1 **98.85%** |
108
+ | PDF 표 | 708쌍 · 2,331표 | 표 탐지 **99.83%** · 구조 일치 **97.98%** · 칸 F1 **0.991** |
109
+ | PDF 전체 | 1,911문서 중 1,729건 채점 | 글 커버리지 **99.80%** |
110
+ | OCR | 53문서 · 102쪽 | CER **0.0421** · 글자 재현율 **99.03%** |
109
111
 
110
- 표 구조 점수와 셀 내용·화면 재현은 별도 지표입니다. 채점 범위·제외 기준·OCR 결과는 [벤치마크 상세](docs/benchmarks.md), 실제 게시 검증은 [4.18.8 기록](docs/release-4.18.8.json)에 있습니다.
112
+ 표 구조 점수와 셀 내용·화면 재현은 별도 지표입니다. 채점 범위·제외 기준·전 벤치 문서별 비교는 [벤치마크 상세](docs/benchmarks.md)에 있습니다.
111
113
 
112
- 외부 PDF 벤치 **opendataloader-bench 200문서**는 4.21.5 별도 측정에서 기본값 종합 **0.963**, OCR 끔 **0.939**입니다. [옵션별 결과와 재현 방법](docs/benchmarks.md#pdf--markdown--opendataloader-bench)
114
+ 외부 PDF 벤치 **opendataloader-bench 200문서**는 4.21.10 배포 측정에서 기본값 종합 **0.963**, OCR 끔 **0.939**입니다. [옵션별 결과와 재현 방법](docs/benchmarks.md#pdf--markdown--opendataloader-bench)
113
115
 
114
116
  ## 최근 업데이트
115
117
 
116
- 최신 배포: **[4.21.8](https://github.com/chrisryugj/kordoc/releases/tag/v4.21.8)** · 2026-10-10
118
+ 최신 배포: **[4.21.10](https://github.com/chrisryugj/kordoc/releases/tag/v4.21.10)** · 2026-10-10
117
119
 
118
120
  | 버전 | 주요 변경 |
119
121
  | --- | --- |
120
- | 4.21.8 | PDF 표 묶음 — 돌려 찍은 가로 표 세우기·데이터 표의 차트 오판·좁은 숫자 열·칸 걸친 한 조각·칸 안 쌓인 금액 (문서별 하락 0) |
121
- | 4.21.7 | PDF 토막 괘선 칸·글 조각 클립·연락처 표 — 예산서 상세 칸(OCR CER 0.0512 → 0.0445), ezPDF·MS Print 글 조각 클립이 만든 가짜 표, 연락처 6열 (문서별 하락 0) |
122
+ | 4.21.10 | PDF 흐름도 표·괄호 풀이 — 선 격자 표를 품은 클러스터 후보 거름, 짧은 괄호 풀이 앞 줄 꺾임 이음 (PDF 어절 F1 98.84 → 98.85%·OCR CER 0.0443 → 0.0421, 문서별 하락 0) |
123
+ | 4.21.9 | PDF 줄 꺾임 이음 — 낱말 가운데 꺾임·겹조사·계사·접미사·명사+하다, 본문 위 첨자 행 흡수 (PDF 어절 F1 98.81 → 98.84%·글 커버리지 99.79 → 99.80%, 문서별 하락 0) |
124
+ | 4.21.8 | PDF 표 묶음 — 돌려 찍은 가로 표 세우기·데이터 표의 차트 오판·좁은 숫자 열·칸 걸친 한 조각·칸 안 쌓인 금액 (OCR CER 0.0445 → 0.0443·열화 OCR scan 0.0821 → 0.0805, 문서별 하락 0) |
125
+ | 4.21.7 | PDF 토막 괘선 칸·글 조각 클립·연락처 표 — 예산서 상세 칸(OCR CER 0.0512 → 0.0445), ezPDF·MS Print 글 조각 클립이 만든 가짜 표, 연락처 6열 (열화 OCR scan 0.0954 → 0.0821·글 커버리지 99.78 → 99.79%, 문서별 하락 0) |
122
126
  | 4.21.6 | 연락처 표 부서별 병합·여러 사람 칸 분할(PDF 표 구조 일치 97.94→97.98%), XLSX·XLS 200열 밖 칸 유실 수리, HWP3 포함 그림 추출, 수식 OCR LaTeX 명령 쪼개기·영역 상한 수리, PPTX 서식 트랙·코퍼스 보강(HWP3 75·서식 58·rhwp 230) |
123
127
  | 4.21.5 | PDF 품질 묶음 — OCR 두 단 가짜 표(#141 부작용)·그림 OCR 라벨 묶음·한 자리 눈금, 주소 링크·벡터 차트 값 축·단 끝줄·각주 순서 (ODL 기본 0.958 → 0.963, 문서별 하락 0) · 개조식·보고서 요약 상자가 md→hwpx→md→hwpx 왕복에서 유지 |
124
128
  | 4.21.4 | MCP `fill_form` 값 파일 입력 `fields_file`(값이 대화에 안 남고 응답은 글자 수만), 전 벤치 묶음 러너·문서별 비교기 `bench/suite.mjs` |
@@ -54,17 +54,17 @@ import {
54
54
  unknownFontWarnings,
55
55
  usesGaejosikMunche,
56
56
  validateHwpx
57
- } from "./chunk-BX4LK3XX.js";
57
+ } from "./chunk-VRWHLWSW.js";
58
58
  import {
59
59
  blocksToPages
60
- } from "./chunk-GZQAE5M7.js";
60
+ } from "./chunk-RUPSY4T4.js";
61
61
  import {
62
62
  applySplices,
63
63
  buildParagraphSplices,
64
64
  buildRangeSplices,
65
65
  placeSealHwpx,
66
66
  scanSectionXml
67
- } from "./chunk-UNOSHFZ3.js";
67
+ } from "./chunk-B375LJ27.js";
68
68
  import {
69
69
  DEFAULT_REDACT_RULES,
70
70
  redactMarkdown,
@@ -72,7 +72,7 @@ import {
72
72
  } from "./chunk-3WSNLH4B.js";
73
73
  import {
74
74
  blocksToChunks
75
- } from "./chunk-FW7NJPIA.js";
75
+ } from "./chunk-PGPGPM5J.js";
76
76
  import {
77
77
  SPACE_EM_FIXED,
78
78
  SPACE_EM_FONT,
@@ -97,20 +97,20 @@ import {
97
97
  renderSceneToHtml,
98
98
  simulateWrap,
99
99
  simulateWrapKeepWord
100
- } from "./chunk-KRSSVUPV.js";
100
+ } from "./chunk-QMWVKGXI.js";
101
101
  import "./chunk-7FCNOKOR.js";
102
- import "./chunk-QTIPY5LH.js";
102
+ import "./chunk-PFG6AN6H.js";
103
103
  import "./chunk-VQFA55IC.js";
104
- import "./chunk-QC3CWCPK.js";
104
+ import "./chunk-FXWRLGQF.js";
105
105
  import {
106
106
  blocksToMarkdown,
107
107
  flattenLayoutTables,
108
108
  hasStructuredCellContent
109
- } from "./chunk-QSVI22OY.js";
110
- import "./chunk-64POCX2L.js";
109
+ } from "./chunk-ZPB5MTYP.js";
110
+ import "./chunk-FZQV2ZO6.js";
111
111
  import {
112
112
  VERSION
113
- } from "./chunk-L2QGHHWS.js";
113
+ } from "./chunk-EPPNA2KB.js";
114
114
  export {
115
115
  AGENCY_COMMON_NAME,
116
116
  BUILTIN_TEMPLATES,
@@ -204,4 +204,4 @@ export {
204
204
  usesGaejosikMunche,
205
205
  validateHwpx
206
206
  };
207
- //# sourceMappingURL=-7C4HXU7Z.js.map
207
+ //# sourceMappingURL=-3K3QNRP7.js.map
@@ -10,10 +10,10 @@ import {
10
10
  extractPageBlocksWithLines,
11
11
  getOcrModelsDir,
12
12
  parseCharacterDict
13
- } from "./chunk-SM6R2TTK.js";
13
+ } from "./chunk-5SGREZ36.js";
14
14
  import {
15
15
  OPTIONAL_DEP_INSTALL_HINT
16
- } from "./chunk-XGVDKRIS.js";
16
+ } from "./chunk-RU3ESQI3.js";
17
17
 
18
18
  // src/ocr/ruling-lines.ts
19
19
  var INK_LUMA_MAX = 205;
@@ -2130,4 +2130,4 @@ export {
2130
2130
  groupOcrLines,
2131
2131
  ocrItemsToBlocks
2132
2132
  };
2133
- //# sourceMappingURL=chunk-II5FJO2S.js.map
2133
+ //# sourceMappingURL=chunk-3DIAVYHS.js.map
@@ -5,11 +5,11 @@ import {
5
5
  HEADING_RATIO_H2,
6
6
  HEADING_RATIO_H3,
7
7
  tidyScriptTags
8
- } from "./chunk-QTIPY5LH.js";
8
+ } from "./chunk-PFG6AN6H.js";
9
9
  import {
10
10
  safeMax,
11
11
  safeMin
12
- } from "./chunk-L2QGHHWS.js";
12
+ } from "./chunk-EPPNA2KB.js";
13
13
 
14
14
  // src/pdf/line-extract.ts
15
15
  import { OPS } from "pdfjs-dist/legacy/build/pdf.mjs";
@@ -2074,14 +2074,26 @@ var WrapLexicon = class {
2074
2074
  words = /* @__PURE__ */ new Map();
2075
2075
  /** 줄 안에서 이웃한 두 어절("개인정보 처리") — 이어 붙인 꼴 증거(joinedWord)의 거부권 */
2076
2076
  pairs = /* @__PURE__ */ new Set();
2077
+ /** 줄 안 어절 첫머리 한글(두~여섯 음절) — 꺾인 두 조각이 어절 머리로 이어지나(startsWord) */
2078
+ heads = /* @__PURE__ */ new Set();
2079
+ /** 줄 안 이웃 어절의 앞 어절 한글 꼬리 + 뒤 어절 첫 음절("지식재산 보") — 어절 머리 증거의 거부권 */
2080
+ spacedHeads = /* @__PURE__ */ new Set();
2077
2081
  /** 줄 글 한 줄을 증거로 더한다 — 탭(큰 갭)으로 나뉜 조각은 다른 칸·단이라 조각 사이는 어절 경계 증거로 쓰지 않는다 */
2078
2082
  addLine(text) {
2079
2083
  for (const seg of text.replace(MARKUP, "").split(" ")) {
2080
2084
  const toks = seg.split(" ").filter((t) => t && !t.includes("]("));
2081
2085
  for (let i = 0; i < toks.length; i++) {
2082
2086
  const t = toks[i], n = t.length;
2083
- if (i > 0 && i < toks.length - 1) bump(this.words, t);
2084
- if (i + 1 < toks.length) this.pairs.add(t + " " + toks[i + 1]);
2087
+ if (i > 0 && i < toks.length - 1) {
2088
+ bump(this.words, t);
2089
+ const run = t.match(/^[가-힣]+/)?.[0] ?? "";
2090
+ for (let j = 2; j <= Math.min(run.length, 6); j++) this.heads.add(run.slice(0, j));
2091
+ }
2092
+ if (i + 1 < toks.length) {
2093
+ this.pairs.add(t + " " + toks[i + 1]);
2094
+ const tail = t.match(/[가-힣]+$/)?.[0];
2095
+ if (tail) this.spacedHeads.add(tail + " " + toks[i + 1].charAt(0));
2096
+ }
2085
2097
  for (let a = 0; a + 1 < n; a++) {
2086
2098
  const c1 = t.charCodeAt(a), c2 = t.charCodeAt(a + 1);
2087
2099
  bump(this.joined1, pairKey(c1, c2));
@@ -2103,6 +2115,14 @@ var WrapLexicon = class {
2103
2115
  joinedWord(left, right) {
2104
2116
  return this.isWord(left + right) && !this.pairs.has(left + " " + right);
2105
2117
  }
2118
+ /** 줄 안 어절이 이 한글로 시작한 적 있나 */
2119
+ startsWord(head) {
2120
+ return this.heads.has(head);
2121
+ }
2122
+ /** 줄 안에서 이 한글 꼬리로 끝난 어절 뒤에 이 음절로 시작하는 어절을 띄어 쓴 적 있나 */
2123
+ spacedHead(tail, syllable) {
2124
+ return this.spacedHeads.has(tail + " " + syllable);
2125
+ }
2106
2126
  /** 두 글자+두 글자 증거만 — 한 글자 쌍으로 물러서지 않는다 (표 칸 조각처럼 줄 꺾임이 아닌 자리에 쓸 때) */
2107
2127
  evidence2(left, right) {
2108
2128
  const n = left.length;
@@ -2134,15 +2154,17 @@ var CJK = /[\u3000-\u303F\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF\uF
2134
2154
  var unspacedCjkBoundary = (prev, next) => CJK.test(prev.trimEnd().slice(-1)) && CJK.test(next.trimStart().charAt(0)) && !/[가-힣ㄱ-ㅎㅏ-ㅣ]/.test(prev + next);
2135
2155
  var CLOSE_TAIL = /[’”」』)\]〉》>]+$/;
2136
2156
  var TAIL = "[.,)\u300D\u300F\u2019\u201D]*";
2137
- var PARTICLE = new RegExp(`^(?:\uB2E4\\.|\uC758|\uC5D0|\uC5D0\uC11C|\uC5D0\uB294|\uC5D0\uAC8C|\uC5D0\uB3C4|\uC5D0\uC11C\uB294|\uAE4C\uC9C0|\uBD80\uD130|\uCC98\uB7FC|\uB9C8\uB2E4|\uB9CC|\uB3C4|\uB4E4|\uB4E4\uC774|\uB4E4\uC758|\uB4E4\uC740|\uB4E4\uC744|\uB4E4\uC5D0\uAC8C|\uC11C\uB294|\uC11C\uB3C4|\uB77C\uACE0|\uB77C\uBA70|\uC740|\uB294|\uC744|\uB97C|\uC73C\uB85C|\uB85C|\uC73C\uB85C\uC11C|\uB85C\uC11C|\uC73C\uB85C\uC368|\uB85C\uC368)${TAIL}$`);
2138
- var PARTICLE_AFTER_CONS = new RegExp(`^(?:\uC774|\uACFC|\uC774\uB2E4|\uC774\uBA70|\uC774\uACE0|\uC774\uB098|\uC774\uB77C\uB294|\uC774\uB77C\uACE0|\uC774\uB77C\uBA70|\uC778|\uC778\uB370|\uC778\uC9C0|\uC784|\uC774\uC5B4\uC57C|\uC774\uBBC0\uB85C|\uC774\uC9C0\uB9CC|\uC774\uBA74\uC11C)${TAIL}$`);
2139
- var PARTICLE_AFTER_VOWEL = new RegExp(`^(?:\uAC00|\uC640|\uB77C\uB294)${TAIL}$`);
2140
- var ENDING = new RegExp(`^(?:\uC5B4\uC57C|\uC544\uC57C|\uC5EC\uC57C|\uBBC0\uB85C|\uC73C\uBBC0\uB85C|\uC9C0\uB9CC|\uBA74\uC11C|\uC73C\uBA74\uC11C|\uC73C\uBA70|\uAC70\uB098|\uB354\uB77C\uB3C4|\uB4E0\uC9C0|\uC5C8\uB2E4|\uC558\uB2E4|\uC600\uB2E4|\uC5C8\uC73C\uBA70|\uC558\uC73C\uBA70|\uC600\uC73C\uBA70|\uC5C8\uACE0|\uC558\uACE0|\uC600\uACE0|\uACA0\uB2E4|\uACA0\uACE0|\uACA0\uC73C\uBA70|\uC2B5\uB2C8\uB2E4|\uB2C8\uB2E4|\uB2C8\uAE4C)${TAIL}$`);
2157
+ var PARTICLE = new RegExp(`^(?:\uB2E4\\.|\uC758|\uC5D0|\uC5D0\uC11C|\uC5D0\uB294|\uC5D0\uAC8C|\uC5D0\uB3C4|\uC5D0\uC11C\uB294|\uAE4C\uC9C0|\uBD80\uD130|\uCC98\uB7FC|\uB9C8\uB2E4|\uB9CC|\uB3C4|\uB4E4|\uB4E4\uC774|\uB4E4\uC758|\uB4E4\uC740|\uB4E4\uC744|\uB4E4\uC5D0\uAC8C|\uC11C\uB294|\uC11C\uB3C4|\uB77C\uACE0|\uB77C\uBA70|\uC740|\uB294|\uC744|\uB97C|\uC73C\uB85C|\uB85C|\uC73C\uB85C\uC11C|\uB85C\uC11C|\uC73C\uB85C\uC368|\uB85C\uC368|\uC5D0\uC11C\uB3C4|\uC5D0\uC11C\uC758|\uC5D0\uC11C\uB9CC|\uC5D0\uC11C\uBD80\uD130|\uC5D0\uB9CC|\uC5D0\uC758|\uC5D0\uAC8C\uB294|\uC5D0\uAC8C\uB3C4|\uAED8\uC11C|\uAED8\uC11C\uB294|\uAED8\uC11C\uB3C4|\uC73C\uB85C\uB294|\uB85C\uB294|\uC73C\uB85C\uB3C4|\uB85C\uB3C4|\uC73C\uB85C\uBD80\uD130|\uB85C\uBD80\uD130|\uBD80\uD130\uB294|\uAE4C\uC9C0\uB294|\uAE4C\uC9C0\uB3C4|\uBCF4\uB2E4\uB3C4|\uB77C\uB3C4|\uC774\uB77C\uB3C4|\uB4E4\uACFC|\uB4E4\uACFC\uC758|\uB4E4\uB85C|\uB4E4\uB3C4|\uB4E4\uC5D0|\uB4E4\uC5D0\uC11C|\uB4E4\uB9CC|\uC774\uB2E4|\uC774\uBA70|\uC774\uB098|\uC774\uB77C\uB294|\uC774\uB77C\uACE0|\uC774\uB77C\uBA70|\uC778\uB370|\uC774\uBBC0\uB85C|\uC774\uC9C0\uB9CC|\uC774\uBA74\uC11C)${TAIL}$`);
2158
+ var PARTICLE_AFTER_CONS = new RegExp(`^(?:\uC774|\uACFC|\uACFC\uC758|\uC774\uACE0|\uC778|\uC778\uC9C0|\uC784|\uC784\uC744|\uC784\uC5D0\uB3C4|\uC774\uC5B4\uC57C)${TAIL}$`);
2159
+ var PARTICLE_AFTER_VOWEL = new RegExp(`^(?:\uAC00|\uC640|\uC640\uC758|\uB77C\uB294)${TAIL}$`);
2160
+ var ENDING = new RegExp(`^(?:\uC5B4\uC57C|\uC544\uC57C|\uC5EC\uC57C|\uBBC0\uB85C|\uC73C\uBBC0\uB85C|\uC9C0\uB9CC|\uBA74\uC11C|\uC73C\uBA74\uC11C|\uC73C\uBA70|\uAC70\uB098|\uB354\uB77C\uB3C4|\uB4E0\uC9C0|\uC5C8\uB2E4|\uC558\uB2E4|\uC600\uB2E4|\uC5C8\uC73C\uBA70|\uC558\uC73C\uBA70|\uC600\uC73C\uBA70|\uC5C8\uACE0|\uC558\uACE0|\uC600\uACE0|\uC600\uB358|\uACA0\uB2E4|\uACA0\uACE0|\uACA0\uC73C\uBA70|\uC2B5\uB2C8\uB2E4|\uB2C8\uB2E4|\uB2C8\uAE4C)${TAIL}$`);
2141
2161
  var ADNOMINAL_HAN = new RegExp(`^\uD55C${TAIL}$`);
2142
2162
  var SUFFIX_JEOK = new RegExp(`^\uC801(?:\uC778|\uC73C\uB85C|\uC774\uB2E4|\uC774\uBA70|\uC774\uACE0|\uC784|\uC778\uB370|\uC774\uB77C|\uC774\uC9C0\uB9CC|\uC73C\uB85C\uC11C)${TAIL}$`);
2163
+ var SUFFIX_NOUN = new RegExp(`^(?:\uD654(?:\uD558|\uD55C|\uD560|\uD568|\uD588|\uD574|\uB41C|\uB418|\uB428|\uB3FC|\uB410)[\uAC00-\uD7A3]*|[\uB7C9\uB960\uC728](?:\uC744|\uC774|\uC740|\uC758|\uC5D0|\uB3C4|\uACFC|\uC73C\uB85C|\uC774\uB2E4)|\uC131(?:\uC744|\uC774|\uC740|\uC758|\uC5D0|\uB3C4|\uC73C\uB85C|\uC774\uB2E4))${TAIL}$`);
2143
2164
  var SPLIT_PARTICLE = [["\uC5D0", new RegExp(`^\uC11C(?:\uB294|\uB3C4|\uC758|\uBD80\uD130|\uB9CC)?${TAIL}$`)], ["\uC774", new RegExp(`^\uB098${TAIL}$`)]];
2144
2165
  var VERB_FORM = new RegExp(`^(?:\uD558\uB294|\uD558\uC5EC|\uD558\uACE0|\uD558\uBA70|\uD558\uC600\uB2E4|\uD558\uC600\uC73C\uBA70|\uD558\uC600\uACE0|\uD558\uC600\uB2E4\uACE0|\uD588\uB2E4|\uD588\uC73C\uBA70|\uD588\uACE0|\uD588\uB2E4\uACE0|\uD588\uB2E4\uBA70|\uD55C\uB2E4|\uD55C\uB2E4\uACE0|\uD55C\uB2E4\uBA70|\uD55C\uB2E4\uB294|\uD560|\uD568|\uD558\uACA0\uB2E4|\uD558\uACA0\uB2E4\uACE0|\uD558\uACA0\uC2B5\uB2C8\uB2E4|\uD558\uAE30\uB85C|\uD558\uBA74|\uD558\uBA74\uC11C|\uD558\uB3C4\uB85D|\uD574\uC57C|\uB418\uB294|\uB418\uC5B4|\uB41C|\uB41C\uB2E4|\uB41C\uB2E4\uACE0|\uB41C\uB2E4\uB294|\uB418\uC5C8\uB2E4|\uB418\uC5C8\uC73C\uBA70|\uB418\uC5C8\uACE0|\uB410\uB2E4|\uB410\uC73C\uBA70|\uB418\uBA70|\uB418\uACE0|\uB418\uBA74|\uB428|\uB3FC|\uD558\uAE30|\uD558\uAC8C|\uD558\uC9C0|\uD558\uAC70\uB098|\uD574\uC11C|\uD558\uB294\uB370|\uD568\uC73C\uB85C\uC368|\uD568\uC5D0|\uD568\uC744|\uD568\uC774|\uD558\uAE30\uC5D0|\uD558\uAE30\uB3C4|\uB418\uC9C0|\uB418\uAE30|\uB418\uB3C4\uB85D|\uB418\uAC70\uB098|\uB418\uBA74\uC11C)${TAIL}$`);
2145
- var AUX_BEFORE = /(?:야|록|로|게|도|히|자|를|을|면|서|고|며|라|려|까지)$/;
2166
+ var AUX_BEFORE = /(?:야|도록|토록|로|게|도|히|고자|를|을|면|서|라고|다고|려고|자고|냐고|며|라|려|까지)$/;
2167
+ var auxBefore = (h) => AUX_BEFORE.test(h.replace(/[”’"」』“‘]/g, ""));
2146
2168
  var BECOME = /^[되된됐됨돼]/;
2147
2169
  var STANDALONE_SYLLABLE = /^(?:및|등|수|것|그|이|저|더|또|각|약|총|중|간|때|뿐|듯|채|전|후|내|외|한|두|세|네|몇|새|첫|온|본|곧|꼭|잘|못|안|좀|늘|다|왜|뭐|시|할|데|뒤|된)$/;
2148
2170
  var DATE_DAY_END = /(?:^|\s)\d*월\s+\d*일$/;
@@ -2163,21 +2185,21 @@ function particleContinues(left, rightWord) {
2163
2185
  if (!last || !/[가-힣A-Za-z0-9]/.test(last)) return false;
2164
2186
  if (PARTICLE.test(right)) return true;
2165
2187
  if (!/[가-힣]/.test(last)) return false;
2166
- if (SUFFIX_JEOK.test(right)) return true;
2188
+ if (SUFFIX_JEOK.test(right) || h.length >= 2 && SUFFIX_NOUN.test(right)) return true;
2167
2189
  if (ENDING.test(right)) return true;
2168
2190
  if (/^다[.;:!?]/.test(right)) return true;
2169
2191
  if (SPLIT_PARTICLE.some(([a, b]) => last === a && b.test(right))) return true;
2170
2192
  if (PARTICLE_AFTER_CONS.test(right)) return hasBatchim(last);
2171
2193
  if (PARTICLE_AFTER_VOWEL.test(right)) return !hasBatchim(last);
2172
- if (ADNOMINAL_HAN.test(right)) return h.length >= 2 && !AUX_BEFORE.test(h) && !/(?:는|은|한|다|어|년)$/.test(h);
2173
- return VERB_FORM.test(right) && !AUX_BEFORE.test(h) && !((last === "\uC774" || last === "\uAC00" && h.length >= 3) && BECOME.test(right));
2194
+ if (ADNOMINAL_HAN.test(right)) return h.length >= 2 && !auxBefore(h) && !/(?:는|은|한|다|어|년)$/.test(h);
2195
+ return VERB_FORM.test(right) && !auxBefore(h) && !((last === "\uC774" || last === "\uAC00" && h.length >= 3) && BECOME.test(right));
2174
2196
  }
2175
2197
  var ITEM_HEAD = /^(?:[□■◆◇○●◎◦▪▫•※▶▷►❍❏❑✓✔➢➤☞]|[①-⑳]|[-–·∙ㆍ*](?=\s)|\(?\d{1,2}[.)](?!\d)|\(?[가-하][.)]|\([가-하\d]{1,2}\)|[ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ]|제\d+[조항호장절])/;
2176
2198
  function startsNewItem(prevText, nextText) {
2177
2199
  const t = nextText.replace(MARKUP, "").trimStart();
2178
2200
  return ITEM_HEAD.test(t) && !(/^다\./.test(t) && /[가-힣]$/.test(prevText.replace(MARKUP, "").trimEnd()));
2179
2201
  }
2180
- function wrapJoiner(prevText, nextText, lex) {
2202
+ function wrapJoiner(prevText, nextText, lex, heads = true) {
2181
2203
  const prev = prevText.replace(MARKUP, "").trimEnd(), next = nextText.replace(MARKUP, "").trimStart();
2182
2204
  const a = prev[prev.length - 1], b = next[0];
2183
2205
  if (!a || !b || /[,;:!?]/.test(a) || DATE_DAY_END.test(prev) && b !== "(") return " ";
@@ -2199,8 +2221,14 @@ function wrapJoiner(prevText, nextText, lex) {
2199
2221
  if (lex && /^[가-힣]$/.test(left) && /^[가-힣]/.test(right) && !STANDALONE_SYLLABLE.test(left) && ([...right].length === 1 || !lex.isWord(left))) return "";
2200
2222
  const r1 = right.replace(/[.,)」』’”]+$/, "");
2201
2223
  if (lex && /[가-힣]$/.test(left) && /^[가-힣]$/.test(r1) && !STANDALONE_SYLLABLE.test(r1) && !lex.isWord(r1) && !lex.isWord(right)) return "";
2224
+ if (lex && heads) {
2225
+ const tail = left.match(/[가-힣]+$/)?.[0], run = right.match(/^[가-힣]+/)?.[0];
2226
+ if (tail && run && !STANDALONE_SYLLABLE.test(tail) && lex.startsWord(tail + run.slice(0, 2)) && !lex.spacedHead(tail, run[0])) return "";
2227
+ if (/[가-힣]{2}$/.test(left) && /^\([^()\s]*\)/.test(right) && !endsAsWord(left) && !/(?:함|음|됨|임|다)$/.test(left) && !BARE_UNIT_PAREN.test(right) && !/^\(\d/.test(right)) return "";
2228
+ }
2202
2229
  return " ";
2203
2230
  }
2231
+ var BARE_UNIT_PAREN = /^\((?:%|‰|[가-힣]{1,3}|[A-Za-z]{1,5}|[A-Za-z]+\/[A-Za-z]+)\)[.,]?$/;
2204
2232
  var PARA_LAST_LINE = /* @__PURE__ */ new WeakMap();
2205
2233
  var PARA_FIRST_LEFT = /* @__PURE__ */ new WeakMap();
2206
2234
  var PAGE_REF_TAIL = /(?:\t|…|·{2}|\.{3})\s*\d{1,4}(?:\s*\/\s*\d{1,4})?\s*$/;
@@ -2622,7 +2650,7 @@ function mergeCellTextLines(textLines, wrap) {
2622
2650
  for (let i = 1; i < textLines.length; i++) {
2623
2651
  const prev = merged[merged.length - 1];
2624
2652
  const curr = textLines[i];
2625
- if (wrap ? wrap.wraps[i - 1] && !startsNewItem(prev, curr) && wrapJoiner(prev, curr, wrap.lex) === "" : /[가-힣]$/.test(prev) && /^[가-힣]+$/.test(curr) && curr.length <= 8 && !curr.includes(" ")) {
2653
+ if (wrap ? wrap.wraps[i - 1] && !startsNewItem(prev, curr) && wrapJoiner(prev, curr, wrap.lex, false) === "" : /[가-힣]$/.test(prev) && /^[가-힣]+$/.test(curr) && curr.length <= 8 && !curr.includes(" ")) {
2626
2654
  merged[merged.length - 1] = prev + curr;
2627
2655
  } else if (curr.trim().length <= 3 && /^[)\]%}]/.test(curr.trim())) {
2628
2656
  merged[merged.length - 1] = prev + curr.trim();
@@ -3069,6 +3097,7 @@ function groupByY(items) {
3069
3097
  if (curLine.length > 0) lines.push(curLine);
3070
3098
  return lines;
3071
3099
  }
3100
+ var PREFIX_SCRIPT = /^[^A-Za-z+=×÷<>≤≥∫∑∏√∞^_{}\\/]+$/;
3072
3101
  function mergeSuperscriptLines(lines) {
3073
3102
  if (lines.length <= 1) return lines;
3074
3103
  const band = (line) => {
@@ -3087,10 +3116,11 @@ function mergeSuperscriptLines(lines) {
3087
3116
  return total > 0 && total <= 10;
3088
3117
  };
3089
3118
  const isMarkers = (line, host) => line.length > 1 && line.length <= 16 && line.every((i) => {
3090
- if (i.text.trim().length > 3 || !i.text.trim()) return false;
3119
+ const t = i.text.trim(), n = t.length;
3120
+ if (n > 8 || !n) return false;
3091
3121
  return host.some((h) => {
3092
- const g = i.x - (h.x + h.w);
3093
- return g <= h.fontSize * 0.35 && g >= -h.fontSize * 0.1;
3122
+ const after = i.x - (h.x + h.w), before = h.x - (i.x + i.w);
3123
+ return n <= 3 && after <= h.fontSize * 0.35 && after >= -h.fontSize * 0.1 || PREFIX_SCRIPT.test(t) && before <= h.fontSize * 0.6 && before >= -h.fontSize * 0.1;
3094
3124
  });
3095
3125
  });
3096
3126
  const result = [lines[0]];
@@ -3739,8 +3769,8 @@ function mergeOverlappingRows(rows) {
3739
3769
  const a = rowBand(prev);
3740
3770
  const b = rowBand(curr);
3741
3771
  const overlap2 = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
3742
- const prevIsFrag = isFragmentRow(prev) && a.height <= b.height * 0.8 && overlap2 >= a.height * 0.5;
3743
- const currIsFrag = isFragmentRow(curr) && b.height <= a.height * 0.8 && overlap2 >= b.height * 0.5;
3772
+ const prevIsFrag = isFragmentRow(prev, curr) && a.height <= b.height * 0.8 && overlap2 >= a.height * 0.5;
3773
+ const currIsFrag = isFragmentRow(curr, prev) && b.height <= a.height * 0.8 && overlap2 >= b.height * 0.5;
3744
3774
  if (prevIsFrag || currIsFrag) {
3745
3775
  const baseY = prevIsFrag ? curr.y : prev.y;
3746
3776
  result[result.length - 1] = { y: baseY, items: [...prev.items, ...curr.items] };
@@ -3750,8 +3780,13 @@ function mergeOverlappingRows(rows) {
3750
3780
  }
3751
3781
  return result;
3752
3782
  }
3753
- function isFragmentRow(row) {
3754
- return row.items.length <= 3 && row.items.every((i) => i.text.length <= 8);
3783
+ function isFragmentRow(row, host) {
3784
+ if (!row.items.every((i) => i.text.length <= 8)) return false;
3785
+ return row.items.length <= 3 || row.items.length <= 16 && row.items.every((i) => PREFIX_SCRIPT.test(i.text.trim()) && host.items.some((h) => scriptAttached(i, h)));
3786
+ }
3787
+ function scriptAttached(i, h) {
3788
+ const after = i.x - (h.x + h.w), before = h.x - (i.x + i.w);
3789
+ return after <= h.fontSize * 0.35 && after >= -h.fontSize * 0.1 || before <= h.fontSize * 0.6 && before >= -h.fontSize * 0.1;
3755
3790
  }
3756
3791
  function rowBand(row) {
3757
3792
  let bottom = Infinity, top = -Infinity;
@@ -8017,7 +8052,8 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
8017
8052
  const proseColumns = findTwoColumnProseCutX(clusterItems) !== null || detectPersistentColumnGutter(remaining.map((i) => ({ x: i.x, y: i.y, w: i.w, h: i.h > 0 ? i.h : i.fontSize }))) !== null;
8018
8053
  const clusterResults = (proseColumns ? [] : detectClusterTables(clusterItems, pageNum)).filter((cr) => {
8019
8054
  const b = cr.bbox;
8020
- return !blocks.some((x) => x.type === "paragraph" && x.bbox && (x.text?.match(/\p{L}/gu)?.length ?? 0) >= 10 && Math.min(x.bbox.x + x.bbox.width, b.x + b.width) - Math.max(x.bbox.x, b.x) >= 0.8 * b.width && x.bbox.y >= b.y - 2 && x.bbox.y + x.bbox.height <= b.y + b.height + 2);
8055
+ const overlapX = (x) => Math.min(x.x + x.width, b.x + b.width) - Math.max(x.x, b.x);
8056
+ return !blocks.some((x) => x.bbox && x.bbox.y >= b.y - 2 && x.bbox.y + x.bbox.height <= b.y + b.height + 2 && (x.type === "paragraph" ? (x.text?.match(/\p{L}/gu)?.length ?? 0) >= 10 && overlapX(x.bbox) >= 0.8 * b.width : x.type === "table" && !ocrPage && x.table?.cols === cr.table.cols && overlapX(x.bbox) >= 0.5 * Math.min(x.bbox.width, b.width)));
8021
8057
  });
8022
8058
  if (clusterResults.length > 0) {
8023
8059
  const ciToIdx = /* @__PURE__ */ new Map();
@@ -8600,4 +8636,4 @@ export {
8600
8636
  UNRULED_REGION_TABLES,
8601
8637
  mergeOcrImageRegions
8602
8638
  };
8603
- //# sourceMappingURL=chunk-JLVX2T4V.js.map
8639
+ //# sourceMappingURL=chunk-4IQHSBGA.js.map