kordoc 4.21.11 → 4.21.13

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 (127) hide show
  1. package/README.md +21 -5
  2. package/dist/{-VONBNRVD.js → -4UPN43UD.js} +11 -11
  3. package/dist/{chunk-PUAKSOZD.js → chunk-3YD3SAQW.js} +178 -170
  4. package/dist/chunk-3YD3SAQW.js.map +1 -0
  5. package/dist/{chunk-KGA6PQUQ.cjs → chunk-57EOUEB4.cjs} +13 -13
  6. package/dist/{chunk-KGA6PQUQ.cjs.map → chunk-57EOUEB4.cjs.map} +1 -1
  7. package/dist/{chunk-J772QFJ5.js → chunk-6EB77P5L.js} +2 -2
  8. package/dist/{chunk-N2GL4NZH.js → chunk-B7CZZBKZ.js} +2 -2
  9. package/dist/{chunk-4UMTGSRH.js → chunk-C7OK4MBX.js} +3 -3
  10. package/dist/{chunk-S7J7VI4R.js → chunk-DAR2TMBL.js} +10 -10
  11. package/dist/{chunk-FUXOABQZ.js → chunk-DI7WHDXG.js} +2 -2
  12. package/dist/{chunk-OZG342GJ.cjs → chunk-DU2HC36X.cjs} +196 -108
  13. package/dist/chunk-DU2HC36X.cjs.map +1 -0
  14. package/dist/{chunk-2LFYBDX2.js → chunk-FFBZG5MK.js} +2 -2
  15. package/dist/{chunk-4U5ISDBU.js → chunk-FW7QWLBL.js} +3 -3
  16. package/dist/{chunk-5MNDRMFV.js → chunk-HCCQTNDS.js} +2 -2
  17. package/dist/{chunk-YRWSOFJW.js → chunk-HIUHLJQD.js} +2 -2
  18. package/dist/{chunk-5JRL2VQ6.cjs → chunk-IS2EXA5D.cjs} +6 -6
  19. package/dist/{chunk-5JRL2VQ6.cjs.map → chunk-IS2EXA5D.cjs.map} +1 -1
  20. package/dist/{chunk-OEF4V654.js → chunk-JGAY3BHY.js} +3 -3
  21. package/dist/{chunk-LZGPS3FH.js → chunk-JQBUWC6W.js} +2 -2
  22. package/dist/{chunk-WAYSJYK4.js → chunk-K23A2CP7.js} +2 -2
  23. package/dist/{chunk-BVWRQNWQ.cjs → chunk-LOO3UV25.cjs} +3 -3
  24. package/dist/{chunk-BVWRQNWQ.cjs.map → chunk-LOO3UV25.cjs.map} +1 -1
  25. package/dist/{chunk-L652BNX6.js → chunk-LXYM2EST.js} +2 -2
  26. package/dist/{chunk-6FUFKXB2.js → chunk-N4UL5NEO.js} +258 -90
  27. package/dist/chunk-N4UL5NEO.js.map +1 -0
  28. package/dist/{chunk-B6UZYIAR.js → chunk-NX5A22B6.js} +2 -2
  29. package/dist/{chunk-ZTNZ4UZM.js → chunk-QOIZF57S.js} +2 -2
  30. package/dist/{chunk-Q2F3ZGGS.js → chunk-RMMMNE2V.js} +4 -4
  31. package/dist/{chunk-NI3RMQTS.js → chunk-UAEY6VPV.js} +6 -6
  32. package/dist/{chunk-MZPJOJO2.cjs → chunk-V7LTELVS.cjs} +3 -3
  33. package/dist/{chunk-MZPJOJO2.cjs.map → chunk-V7LTELVS.cjs.map} +1 -1
  34. package/dist/{chunk-GLZ4XPKX.js → chunk-VC2SS3OH.js} +2 -2
  35. package/dist/{chunk-JDEWFE46.js → chunk-VXNR2JYB.js} +2 -2
  36. package/dist/{chunk-WSSCBJSU.cjs → chunk-WPZOIIM2.cjs} +2 -2
  37. package/dist/{chunk-WSSCBJSU.cjs.map → chunk-WPZOIIM2.cjs.map} +1 -1
  38. package/dist/{chunk-NMXMBYRP.js → chunk-YJ4J6EG5.js} +2 -2
  39. package/dist/{chunk-SWV27B56.js → chunk-YM4AEOS4.js} +2 -2
  40. package/dist/chunks-A67IJS56.js +10 -0
  41. package/dist/cli.js +30 -30
  42. package/dist/{formula-AYKY6JN4.cjs → formula-BCWYXJPE.cjs} +9 -9
  43. package/dist/{formula-AYKY6JN4.cjs.map → formula-BCWYXJPE.cjs.map} +1 -1
  44. package/dist/{formula-E7IFGURT.js → formula-N4TZPWWU.js} +4 -4
  45. package/dist/{formula-ROYY4OPC.js → formula-ZFB6JGOW.js} +3 -3
  46. package/dist/{image-ocr-SIO5GLQK.js → image-ocr-4Y23NCW4.js} +9 -9
  47. package/dist/{image-ocr-YZHJHHPA.js → image-ocr-7YHK7Q4C.js} +6 -6
  48. package/dist/{image-ocr-CVVWQHOV.cjs → image-ocr-RE7BFBGV.cjs} +15 -15
  49. package/dist/{image-ocr-CVVWQHOV.cjs.map → image-ocr-RE7BFBGV.cjs.map} +1 -1
  50. package/dist/index.cjs +276 -276
  51. package/dist/index.js +5 -5
  52. package/dist/mcp.js +22 -22
  53. package/dist/{model-bundle-5JREYZVZ.js → model-bundle-WISSN6YF.js} +5 -5
  54. package/dist/{models-MW56BJEC.js → models-SG4VHU65.js} +5 -5
  55. package/dist/{parse-worker-v2-MGIF63HD.js → parse-worker-v2-VNLAK2VC.js} +33 -16
  56. package/dist/parse-worker-v2-VNLAK2VC.js.map +1 -0
  57. package/dist/{parser-VUJQJDZI.cjs → parser-KYZD3NNB.cjs} +257 -234
  58. package/dist/parser-KYZD3NNB.cjs.map +1 -0
  59. package/dist/{parser-53TGQ4FC.js → parser-V3R7TKU5.js} +37 -14
  60. package/dist/parser-V3R7TKU5.js.map +1 -0
  61. package/dist/{parser-W46CWSPY.js → parser-VPVVJDB3.js} +34 -11
  62. package/dist/parser-VPVVJDB3.js.map +1 -0
  63. package/dist/pdf-ocr-G2SX5FKB.cjs +19 -0
  64. package/dist/{pdf-ocr-BQG3O6HQ.cjs.map → pdf-ocr-G2SX5FKB.cjs.map} +1 -1
  65. package/dist/pdf-ocr-KNNBYXVO.js +22 -0
  66. package/dist/pdf-ocr-PP2GGLS3.js +18 -0
  67. package/dist/{profile-io-AYQO4RLD.js → profile-io-72YURUWT.js} +3 -3
  68. package/dist/{rasterize-U23B3ZK4.js → rasterize-UPE2IZLP.js} +3 -3
  69. package/dist/{redact-doc-FV5NHVRH.js → redact-doc-GW6ILR52.js} +11 -11
  70. package/dist/{render-TLLHZCMS.js → render-2XLPO3ZA.js} +7 -7
  71. package/dist/seal-VLJCGOP7.js +10 -0
  72. package/dist/{setup-HWI3THDP.js → setup-GE4JKPHY.js} +3 -3
  73. package/dist/visual-7NPMIPSC.js +20 -0
  74. package/dist/{watch-7UBV5B5E.js → watch-XBVNOG6B.js} +12 -12
  75. package/package.json +7 -2
  76. package/dist/chunk-6FUFKXB2.js.map +0 -1
  77. package/dist/chunk-OZG342GJ.cjs.map +0 -1
  78. package/dist/chunk-PUAKSOZD.js.map +0 -1
  79. package/dist/chunks-CKWDRCT2.js +0 -10
  80. package/dist/parse-worker-v2-MGIF63HD.js.map +0 -1
  81. package/dist/parser-53TGQ4FC.js.map +0 -1
  82. package/dist/parser-VUJQJDZI.cjs.map +0 -1
  83. package/dist/parser-W46CWSPY.js.map +0 -1
  84. package/dist/pdf-ocr-BQG3O6HQ.cjs +0 -19
  85. package/dist/pdf-ocr-EWS374FU.js +0 -22
  86. package/dist/pdf-ocr-GKRBJXT4.js +0 -18
  87. package/dist/seal-BLZIPLWT.js +0 -10
  88. package/dist/visual-PW74S3AP.js +0 -20
  89. /package/dist/{-VONBNRVD.js.map → -4UPN43UD.js.map} +0 -0
  90. /package/dist/{chunk-J772QFJ5.js.map → chunk-6EB77P5L.js.map} +0 -0
  91. /package/dist/{chunk-N2GL4NZH.js.map → chunk-B7CZZBKZ.js.map} +0 -0
  92. /package/dist/{chunk-4UMTGSRH.js.map → chunk-C7OK4MBX.js.map} +0 -0
  93. /package/dist/{chunk-S7J7VI4R.js.map → chunk-DAR2TMBL.js.map} +0 -0
  94. /package/dist/{chunk-FUXOABQZ.js.map → chunk-DI7WHDXG.js.map} +0 -0
  95. /package/dist/{chunk-2LFYBDX2.js.map → chunk-FFBZG5MK.js.map} +0 -0
  96. /package/dist/{chunk-4U5ISDBU.js.map → chunk-FW7QWLBL.js.map} +0 -0
  97. /package/dist/{chunk-5MNDRMFV.js.map → chunk-HCCQTNDS.js.map} +0 -0
  98. /package/dist/{chunk-YRWSOFJW.js.map → chunk-HIUHLJQD.js.map} +0 -0
  99. /package/dist/{chunk-OEF4V654.js.map → chunk-JGAY3BHY.js.map} +0 -0
  100. /package/dist/{chunk-LZGPS3FH.js.map → chunk-JQBUWC6W.js.map} +0 -0
  101. /package/dist/{chunk-WAYSJYK4.js.map → chunk-K23A2CP7.js.map} +0 -0
  102. /package/dist/{chunk-L652BNX6.js.map → chunk-LXYM2EST.js.map} +0 -0
  103. /package/dist/{chunk-B6UZYIAR.js.map → chunk-NX5A22B6.js.map} +0 -0
  104. /package/dist/{chunk-ZTNZ4UZM.js.map → chunk-QOIZF57S.js.map} +0 -0
  105. /package/dist/{chunk-Q2F3ZGGS.js.map → chunk-RMMMNE2V.js.map} +0 -0
  106. /package/dist/{chunk-NI3RMQTS.js.map → chunk-UAEY6VPV.js.map} +0 -0
  107. /package/dist/{chunk-GLZ4XPKX.js.map → chunk-VC2SS3OH.js.map} +0 -0
  108. /package/dist/{chunk-JDEWFE46.js.map → chunk-VXNR2JYB.js.map} +0 -0
  109. /package/dist/{chunk-NMXMBYRP.js.map → chunk-YJ4J6EG5.js.map} +0 -0
  110. /package/dist/{chunk-SWV27B56.js.map → chunk-YM4AEOS4.js.map} +0 -0
  111. /package/dist/{chunks-CKWDRCT2.js.map → chunks-A67IJS56.js.map} +0 -0
  112. /package/dist/{formula-E7IFGURT.js.map → formula-N4TZPWWU.js.map} +0 -0
  113. /package/dist/{formula-ROYY4OPC.js.map → formula-ZFB6JGOW.js.map} +0 -0
  114. /package/dist/{image-ocr-SIO5GLQK.js.map → image-ocr-4Y23NCW4.js.map} +0 -0
  115. /package/dist/{image-ocr-YZHJHHPA.js.map → image-ocr-7YHK7Q4C.js.map} +0 -0
  116. /package/dist/{model-bundle-5JREYZVZ.js.map → model-bundle-WISSN6YF.js.map} +0 -0
  117. /package/dist/{models-MW56BJEC.js.map → models-SG4VHU65.js.map} +0 -0
  118. /package/dist/{pdf-ocr-EWS374FU.js.map → pdf-ocr-KNNBYXVO.js.map} +0 -0
  119. /package/dist/{pdf-ocr-GKRBJXT4.js.map → pdf-ocr-PP2GGLS3.js.map} +0 -0
  120. /package/dist/{profile-io-AYQO4RLD.js.map → profile-io-72YURUWT.js.map} +0 -0
  121. /package/dist/{rasterize-U23B3ZK4.js.map → rasterize-UPE2IZLP.js.map} +0 -0
  122. /package/dist/{redact-doc-FV5NHVRH.js.map → redact-doc-GW6ILR52.js.map} +0 -0
  123. /package/dist/{render-TLLHZCMS.js.map → render-2XLPO3ZA.js.map} +0 -0
  124. /package/dist/{seal-BLZIPLWT.js.map → seal-VLJCGOP7.js.map} +0 -0
  125. /package/dist/{setup-HWI3THDP.js.map → setup-GE4JKPHY.js.map} +0 -0
  126. /package/dist/{visual-PW74S3AP.js.map → visual-7NPMIPSC.js.map} +0 -0
  127. /package/dist/{watch-7UBV5B5E.js.map → watch-XBVNOG6B.js.map} +0 -0
@@ -1,88 +1,15 @@
1
+ #!/usr/bin/env node
1
2
  import {
2
3
  CELL_EDGES,
3
4
  HEADING_RATIO_H1,
4
5
  HEADING_RATIO_H2,
5
6
  HEADING_RATIO_H3,
6
7
  tidyScriptTags
7
- } from "./chunk-FUXOABQZ.js";
8
- import {
9
- ensureModelsIn,
10
- getModelsDir
11
- } from "./chunk-N2GL4NZH.js";
8
+ } from "./chunk-YM4AEOS4.js";
12
9
  import {
13
10
  safeMax,
14
11
  safeMin
15
- } from "./chunk-LZGPS3FH.js";
16
-
17
- // src/ocr/models.ts
18
- import { join } from "path";
19
- import { stat } from "fs/promises";
20
- var OCR_DET_MODEL = {
21
- name: "PP-OCRv5 mobile det",
22
- filename: "det.onnx",
23
- url: "https://huggingface.co/PaddlePaddle/PP-OCRv5_mobile_det_onnx/resolve/main/inference.onnx",
24
- sha256: "a431985659dc921974177a95adcfbb90fd9e51989a5e04d70d0b75f597b6e61d",
25
- sizeMb: 5
26
- };
27
- var OCR_REC_MODEL = {
28
- name: "PP-OCRv5 korean rec",
29
- filename: "rec_korean.onnx",
30
- url: "https://huggingface.co/PaddlePaddle/korean_PP-OCRv5_mobile_rec_onnx/resolve/main/inference.onnx",
31
- sha256: "92f0b7785e64fc9090106a241cf4c1eb97472824558272751b88a2a4476d3a08",
32
- sizeMb: 13
33
- };
34
- var OCR_REC_DICT = {
35
- name: "PP-OCRv5 korean dict",
36
- filename: "rec_korean.yml",
37
- url: "https://huggingface.co/PaddlePaddle/korean_PP-OCRv5_mobile_rec_onnx/resolve/main/inference.yml",
38
- sha256: "f757fa1c40e99edcf27e9cce879b93eb2a51fa46f5ef39095689b8c37dd75998",
39
- sizeMb: 1
40
- };
41
- var ALL_OCR_MODELS = [OCR_DET_MODEL, OCR_REC_MODEL, OCR_REC_DICT];
42
- function getOcrModelsDir() {
43
- return getModelsDir("ppocr");
44
- }
45
- async function ensureOcrModels(onProgress) {
46
- return ensureModelsIn(getOcrModelsDir(), ALL_OCR_MODELS, onProgress);
47
- }
48
- async function ocrModelsCached() {
49
- const dir = getOcrModelsDir();
50
- for (const spec of ALL_OCR_MODELS) {
51
- try {
52
- if (!(await stat(join(dir, spec.filename))).size) return false;
53
- } catch {
54
- return false;
55
- }
56
- }
57
- return true;
58
- }
59
- function parseCharacterDict(yml) {
60
- const lines = yml.split("\n");
61
- const chars = [];
62
- let inDict = false;
63
- let dictIndent = -1;
64
- for (const line of lines) {
65
- if (!inDict) {
66
- const m2 = /^(\s*)character_dict:\s*$/.exec(line);
67
- if (m2) {
68
- inDict = true;
69
- dictIndent = m2[1].length;
70
- }
71
- continue;
72
- }
73
- const m = /^(\s*)- (.*)$/.exec(line);
74
- if (m && m[1].length >= dictIndent) {
75
- let v = m[2];
76
- if (v.length >= 2 && (v.startsWith("'") && v.endsWith("'") || v.startsWith('"') && v.endsWith('"'))) {
77
- v = v.slice(1, -1).replace(/''/g, "'");
78
- }
79
- chars.push(v);
80
- continue;
81
- }
82
- if (line.trim() !== "") break;
83
- }
84
- return chars;
85
- }
12
+ } from "./chunk-LXYM2EST.js";
86
13
 
87
14
  // src/pdf/line-extract.ts
88
15
  import { OPS } from "pdfjs-dist/legacy/build/pdf.mjs";
@@ -1128,21 +1055,21 @@ var SHADE_CLIP_TOL = 1.5;
1128
1055
  var SHADE_CLIP_MAX_AREA = 0.5;
1129
1056
  function dropShadingClipGrids(clipGrids, lineGrids, fillRects, verticals = []) {
1130
1057
  if (clipGrids.length === 0 || lineGrids.length === 0 || fillRects.length === 0) return clipGrids;
1131
- const near = (a, b) => Math.abs(a - b) <= SHADE_CLIP_TOL;
1058
+ const near2 = (a, b) => Math.abs(a - b) <= SHADE_CLIP_TOL;
1132
1059
  const area = (b) => Math.max(0, b.x2 - b.x1) * Math.max(0, b.y2 - b.y1);
1133
1060
  const inter = (a, b) => area({ x1: Math.max(a.x1, b.x1), y1: Math.max(a.y1, b.y1), x2: Math.min(a.x2, b.x2), y2: Math.min(a.y2, b.y2) });
1134
1061
  return clipGrids.filter((c) => {
1135
1062
  if (!c.cells?.length || c.clipParent) return true;
1136
1063
  const sourceCells = c.cells.filter((cell) => !cell.filler);
1137
1064
  if (sourceCells.length === 0) return true;
1138
- const shaded = sourceCells.every((cell) => fillRects.some((f) => near(f.x1, cell.bbox.x1) && near(f.x2, cell.bbox.x2) && near(f.y1, cell.bbox.y1) && near(f.y2, cell.bbox.y2)));
1065
+ const shaded = sourceCells.every((cell) => fillRects.some((f) => near2(f.x1, cell.bbox.x1) && near2(f.x2, cell.bbox.x2) && near2(f.y1, cell.bbox.y1) && near2(f.y2, cell.bbox.y2)));
1139
1066
  if (!shaded) return true;
1140
1067
  const ruled = sourceCells.every((cell) => cell.bbox.x2 >= c.bbox.x2 - SHADE_CLIP_TOL || verticals.some((v) => Math.abs(v.x1 - cell.bbox.x2) <= SHADE_CLIP_TOL * 2 && Math.min(v.y2, cell.bbox.y2) - Math.max(v.y1, cell.bbox.y1) >= (cell.bbox.y2 - cell.bbox.y1) * 0.75));
1141
1068
  if (!ruled) return true;
1142
1069
  const host = lineGrids.find((l) => (
1143
1070
  // Inferred filler cells carry no boundary evidence. Replace their frame only
1144
1071
  // with a finer ruled grid of the same extent, never a larger surrounding form.
1145
- (!c.cells.some((cell) => cell.filler) || near(c.bbox.x1, l.bbox.x1) && near(c.bbox.x2, l.bbox.x2) && near(c.bbox.y1, l.bbox.y1) && near(c.bbox.y2, l.bbox.y2) && l.rowYs.length > c.rowYs.length && sourceCells.every((cell) => [cell.bbox.y1, cell.bbox.y2].every((y) => l.rowYs.some((ly) => near(y, ly))))) && c.bbox.x1 >= l.bbox.x1 - SHADE_CLIP_TOL && c.bbox.x2 <= l.bbox.x2 + SHADE_CLIP_TOL && c.bbox.y1 >= l.bbox.y1 - SHADE_CLIP_TOL && c.bbox.y2 <= l.bbox.y2 + SHADE_CLIP_TOL && c.colXs.every((x) => l.colXs.some((lx) => near(lx, x))) && (clipGrids.reduce((s, o) => s + (o.cells?.some((cell) => cell.filler) ? o.cells.filter((cell) => !cell.filler).reduce((a, cell) => a + inter(cell.bbox, l.bbox), 0) : inter(o.bbox, l.bbox)), 0) <= area(l.bbox) * SHADE_CLIP_MAX_AREA || l.rowYs.length === c.rowYs.length + 1 && c.rowYs.every((y, i) => near(y, l.rowYs[i])) && l.colXs.length === c.colXs.length && c.colXs.every((x, i) => near(x, l.colXs[i])) && !clipGrids.some((o) => o !== c && inter(o.bbox, l.bbox) > 0))
1072
+ (!c.cells.some((cell) => cell.filler) || near2(c.bbox.x1, l.bbox.x1) && near2(c.bbox.x2, l.bbox.x2) && near2(c.bbox.y1, l.bbox.y1) && near2(c.bbox.y2, l.bbox.y2) && l.rowYs.length > c.rowYs.length && sourceCells.every((cell) => [cell.bbox.y1, cell.bbox.y2].every((y) => l.rowYs.some((ly) => near2(y, ly))))) && c.bbox.x1 >= l.bbox.x1 - SHADE_CLIP_TOL && c.bbox.x2 <= l.bbox.x2 + SHADE_CLIP_TOL && c.bbox.y1 >= l.bbox.y1 - SHADE_CLIP_TOL && c.bbox.y2 <= l.bbox.y2 + SHADE_CLIP_TOL && c.colXs.every((x) => l.colXs.some((lx) => near2(lx, x))) && (clipGrids.reduce((s, o) => s + (o.cells?.some((cell) => cell.filler) ? o.cells.filter((cell) => !cell.filler).reduce((a, cell) => a + inter(cell.bbox, l.bbox), 0) : inter(o.bbox, l.bbox)), 0) <= area(l.bbox) * SHADE_CLIP_MAX_AREA || l.rowYs.length === c.rowYs.length + 1 && c.rowYs.every((y, i) => near2(y, l.rowYs[i])) && l.colXs.length === c.colXs.length && c.colXs.every((x, i) => near2(x, l.colXs[i])) && !clipGrids.some((o) => o !== c && inter(o.bbox, l.bbox) > 0))
1146
1073
  ));
1147
1074
  return !host;
1148
1075
  });
@@ -1150,14 +1077,14 @@ function dropShadingClipGrids(clipGrids, lineGrids, fillRects, verticals = []) {
1150
1077
  var INSET_CLIP_MIN = 2;
1151
1078
  function dropInsetClipGrids(clipGrids, lineGrids) {
1152
1079
  if (clipGrids.length === 0 || lineGrids.length === 0) return clipGrids;
1153
- const near = (a, b) => Math.abs(a - b) <= SHADE_CLIP_TOL;
1154
- return clipGrids.filter((c) => c.clipParent || c.rowYs.length !== 2 || !lineGrids.some((l) => l.rowYs.length >= 3 && near(c.bbox.x1, l.bbox.x1) && near(c.bbox.x2, l.bbox.x2) && l.rowYs.some((top, r) => r + 1 < l.rowYs.length && top - c.bbox.y2 >= INSET_CLIP_MIN && c.bbox.y1 - l.rowYs[r + 1] >= INSET_CLIP_MIN)));
1080
+ const near2 = (a, b) => Math.abs(a - b) <= SHADE_CLIP_TOL;
1081
+ return clipGrids.filter((c) => c.clipParent || c.rowYs.length !== 2 || !lineGrids.some((l) => l.rowYs.length >= 3 && near2(c.bbox.x1, l.bbox.x1) && near2(c.bbox.x2, l.bbox.x2) && l.rowYs.some((top, r) => r + 1 < l.rowYs.length && top - c.bbox.y2 >= INSET_CLIP_MIN && c.bbox.y1 - l.rowYs[r + 1] >= INSET_CLIP_MIN)));
1155
1082
  }
1156
1083
  function dropHeadBandClipGrids(clipGrids, lineGrids) {
1157
1084
  if (clipGrids.length === 0 || lineGrids.length === 0) return clipGrids;
1158
- const near = (a, b) => Math.abs(a - b) <= SHADE_CLIP_TOL;
1085
+ const near2 = (a, b) => Math.abs(a - b) <= SHADE_CLIP_TOL;
1159
1086
  const overlaps = (a, b) => Math.min(a.x2, b.x2) > Math.max(a.x1, b.x1) && Math.min(a.y2, b.y2) > Math.max(a.y1, b.y1);
1160
- return clipGrids.filter((c) => c.clipParent || !c.cells?.length || !lineGrids.some((l) => l.rowYs.length > c.rowYs.length && l.colXs.length === c.colXs.length && c.colXs.every((x, k) => near(x, l.colXs[k])) && c.rowYs.every((y, k) => near(y, l.rowYs[k])) && !clipGrids.some((o) => o !== c && overlaps(o.bbox, l.bbox))));
1087
+ return clipGrids.filter((c) => c.clipParent || !c.cells?.length || !lineGrids.some((l) => l.rowYs.length > c.rowYs.length && l.colXs.length === c.colXs.length && c.colXs.every((x, k) => near2(x, l.colXs[k])) && c.rowYs.every((y, k) => near2(y, l.rowYs[k])) && !clipGrids.some((o) => o !== c && overlaps(o.bbox, l.bbox))));
1161
1088
  }
1162
1089
  function enforceMinWidth(colXs, minWidth, narrowRuns = true) {
1163
1090
  if (colXs.length <= 2) return colXs;
@@ -1372,17 +1299,17 @@ function groupConnectedLines(lines, tol = CONNECT_TOL) {
1372
1299
  const ra = find(a), rb = find(b);
1373
1300
  if (ra !== rb) parent[ra] = rb;
1374
1301
  }
1375
- const span = lines.map((l) => [
1302
+ const span2 = lines.map((l) => [
1376
1303
  Math.floor((Math.min(l.x1, l.x2) - CONNECT_TOL) / GROUP_BUCKET_CELL),
1377
1304
  Math.floor((Math.max(l.x1, l.x2) + CONNECT_TOL) / GROUP_BUCKET_CELL),
1378
1305
  Math.floor((Math.min(l.y1, l.y2) - CONNECT_TOL) / GROUP_BUCKET_CELL),
1379
1306
  Math.floor((Math.max(l.y1, l.y2) + CONNECT_TOL) / GROUP_BUCKET_CELL)
1380
1307
  ]);
1381
- const startXs = [...new Set(span.map((s) => s[0]))].filter(Number.isFinite).sort((a, b) => a - b);
1382
- const startYs = [...new Set(span.map((s) => s[2]))].filter(Number.isFinite).sort((a, b) => a - b);
1308
+ const startXs = [...new Set(span2.map((s) => s[0]))].filter(Number.isFinite).sort((a, b) => a - b);
1309
+ const startYs = [...new Set(span2.map((s) => s[2]))].filter(Number.isFinite).sort((a, b) => a - b);
1383
1310
  const cellMap = /* @__PURE__ */ new Map();
1384
1311
  for (let i = 0; i < lines.length; i++) {
1385
- const [cx1, cx2, cy1, cy2] = span[i];
1312
+ const [cx1, cx2, cy1, cy2] = span2[i];
1386
1313
  for (let a = lowerBound(startXs, cx1); a < startXs.length && startXs[a] <= cx2; a++) {
1387
1314
  for (let b = lowerBound(startYs, cy1); b < startYs.length && startYs[b] <= cy2; b++) {
1388
1315
  const key = startXs[a] + "," + startYs[b];
@@ -1596,14 +1523,14 @@ function buildClipCellGrids(rects, strokedH, strokedV, pageWidth, pageHeight, te
1596
1523
  for (let i = 0; i < cells.length; i++) {
1597
1524
  if (tableClip[i]) continue;
1598
1525
  const candidates = /* @__PURE__ */ new Set();
1599
- const near = (map, v) => {
1526
+ const near2 = (map, v) => {
1600
1527
  const k = edgeBin(v);
1601
1528
  for (let d = -1; d <= 1; d++) for (const j of map.get(k + d) ?? []) if (j > i) candidates.add(j);
1602
1529
  };
1603
- near(startsX, cells[i].x2);
1604
- near(endsX, cells[i].x1);
1605
- near(startsY, cells[i].y2);
1606
- near(endsY, cells[i].y1);
1530
+ near2(startsX, cells[i].x2);
1531
+ near2(endsX, cells[i].x1);
1532
+ near2(startsY, cells[i].y2);
1533
+ near2(endsY, cells[i].y1);
1607
1534
  for (const j of [...candidates].sort((a, b) => a - b)) {
1608
1535
  if (tableClip[j] || parent[i] !== parent[j]) continue;
1609
1536
  if (adjacent(cells[i], cells[j])) {
@@ -1858,13 +1785,13 @@ function closeGaps(members, gaps) {
1858
1785
  if (repeatedBlankColumn(l) && !atLo && !atHi) continue;
1859
1786
  const to = atLo && !atHi ? l.lo : atHi && !atLo ? l.hi : l.to;
1860
1787
  const onEdge = (r) => l.axis === "y" ? al(r.y2, l.lo) || al(r.y1, l.hi) : al(r.x2, l.lo) || al(r.x1, l.hi);
1861
- const span = (r) => l.axis === "y" ? [r.x1, r.x2] : [r.y1, r.y2];
1788
+ const span2 = (r) => l.axis === "y" ? [r.x1, r.x2] : [r.y1, r.y2];
1862
1789
  const take = /* @__PURE__ */ new Set();
1863
1790
  for (let grew = true; grew; ) {
1864
1791
  grew = false;
1865
1792
  for (let n = 0; n < members.length; n++) {
1866
1793
  if (take.has(n) || !onEdge(members[n])) continue;
1867
- const [a1, a2] = span(members[n]);
1794
+ const [a1, a2] = span2(members[n]);
1868
1795
  if (overlap(a1, a2, l.e1, l.e2) <= -(CLIP_SPACING_MAX + CLIP_COORD_TOL)) continue;
1869
1796
  take.add(n);
1870
1797
  l.e1 = Math.min(l.e1, a1);
@@ -2730,8 +2657,10 @@ function mergeCellTextLines(textLines, wrap) {
2730
2657
  merged[merged.length - 1] = prev + curr.trim();
2731
2658
  } else if (!wrap && /[,(]$/.test(prev.trim()) && curr.trim().length <= 15) {
2732
2659
  merged[merged.length - 1] = prev + curr.trim();
2733
- } else if (/[\d,]$/.test(prev) && /^[\d,]+[)\]]?$/.test(curr.trim()) && curr.trim().length <= 10 && !(/\d,\d{3}$/.test(prev) && /^\d/.test(curr.trim())) && !(/(?:^|[^\d,])\d{1,3}$/.test(prev) && /^(\d{1,3}(,\d{3})+|\d{1,3})$/.test(curr.trim()) && !numberWrapped(i - 1)) && !(/(?:^|\s)\d{1,7}$/.test(prev) && /^\d{1,7}$/.test(curr.trim()) && !numberWrapped(i - 1))) {
2660
+ } else if (/[\d,]$/.test(prev) && /^[\d,]+[)\]]?$/.test(curr.trim()) && curr.trim().length <= 10 && !(/\d,\d{3}$/.test(prev) && /^\d/.test(curr.trim())) && !(wrap && !numberWrapped(i - 1)) && !(/(?:^|[^\d,])\d{1,3}$/.test(prev) && /^(\d{1,3}(,\d{3})+|\d{1,3})$/.test(curr.trim()) && !numberWrapped(i - 1)) && !(/(?:^|\s)\d{1,7}$/.test(prev) && /^\d{1,7}$/.test(curr.trim()) && !numberWrapped(i - 1))) {
2734
2661
  merged[merged.length - 1] = prev + curr.trim();
2662
+ } else if (wrap && /[A-Za-z가-힣]/.test(prev) && /,$/.test(prev.trim()) && /^[\d,]+[)\]]?$/.test(curr.trim()) && curr.trim().length <= 10) {
2663
+ merged[merged.length - 1] = prev.trimEnd() + " " + curr.trim();
2735
2664
  } else {
2736
2665
  merged.push(curr);
2737
2666
  }
@@ -3178,7 +3107,7 @@ function isAttachedScripts(line, host) {
3178
3107
  if (n > 8 || !n) return false;
3179
3108
  return host.some((h) => {
3180
3109
  const after = i.x - (h.x + h.w), before = h.x - (i.x + i.w);
3181
- 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;
3110
+ return n <= 3 && after <= h.fontSize * 0.35 && after >= -h.fontSize * 0.25 || PREFIX_SCRIPT.test(t) && before <= h.fontSize * 0.6 && before >= -h.fontSize * 0.25;
3182
3111
  });
3183
3112
  });
3184
3113
  }
@@ -4505,12 +4434,12 @@ function figureColumnBands(items, figures) {
4505
4434
  const lines = groupByY([...items].sort((a, b) => b.y - a.y || a.x - b.x));
4506
4435
  if (lines.length < 10) return null;
4507
4436
  const minX = Math.min(...items.map((i) => i.x)), maxX = Math.max(...items.map((i) => i.x + i.w));
4508
- const span = maxX - minX;
4509
- if (span < 200) return null;
4437
+ const span2 = maxX - minX;
4438
+ if (span2 < 200) return null;
4510
4439
  const full = (line) => {
4511
4440
  const s = [...line].sort((a, b) => a.x - b.x);
4512
4441
  const fs = Math.max(...s.map((i) => i.fontSize));
4513
- if (s[s.length - 1].x + s[s.length - 1].w - s[0].x < span * 0.75) return false;
4442
+ if (s[s.length - 1].x + s[s.length - 1].w - s[0].x < span2 * 0.75) return false;
4514
4443
  const sizeOf = (part) => {
4515
4444
  const by = /* @__PURE__ */ new Map();
4516
4445
  for (const it of part) by.set(it.fontSize, (by.get(it.fontSize) ?? 0) + it.text.length);
@@ -4539,11 +4468,11 @@ function figureColumnBands(items, figures) {
4539
4468
  ...figures.filter((f) => f.y < top && f.y + f.h > bottom)
4540
4469
  ];
4541
4470
  let best = null, run = null;
4542
- const step = Math.max(2, span * 0.4 / 400);
4543
- for (let x = minX + span * 0.3; x <= minX + span * 0.7; x += step) {
4471
+ const step = Math.max(2, span2 * 0.4 / 400);
4472
+ for (let x = minX + span2 * 0.3; x <= minX + span2 * 0.7; x += step) {
4544
4473
  const empty = !rects.some((r) => r.x < x && r.x + r.w > x);
4545
4474
  if (empty && run === null) run = x;
4546
- if ((!empty || x + step > minX + span * 0.7) && run !== null) {
4475
+ if ((!empty || x + step > minX + span2 * 0.7) && run !== null) {
4547
4476
  if (x - run >= 8 && (!best || x - run > best.w)) best = { x: (run + x) / 2, w: x - run };
4548
4477
  run = null;
4549
4478
  }
@@ -5005,8 +4934,8 @@ function isProseGutter(items, x) {
5005
4934
  return full >= lines.length * 0.6;
5006
4935
  };
5007
4936
  if (!prose(left) || !prose(right)) return false;
5008
- const span = (lines) => [Math.min(...lines.map((l) => l.y)), Math.max(...lines.map((l) => l.y))];
5009
- const [l0, l1] = span(left), [r0, r1] = span(right);
4937
+ const span2 = (lines) => [Math.min(...lines.map((l) => l.y)), Math.max(...lines.map((l) => l.y))];
4938
+ const [l0, l1] = span2(left), [r0, r1] = span2(right);
5010
4939
  return Math.min(l1, r1) - Math.max(l0, r0) >= Math.min(l1 - l0, r1 - r0) * 0.5;
5011
4940
  }
5012
4941
  function splitEdgeSpannedColumns(items, gapThreshold, depth) {
@@ -5718,9 +5647,9 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables =
5718
5647
  const repeatedPatterns = /* @__PURE__ */ new Set();
5719
5648
  for (const [p, count] of patternCount) {
5720
5649
  const pages = [...patternPages.get(p) ?? []];
5721
- const span = pages.length ? Math.max(...pages) - Math.min(...pages) + 1 : 0;
5650
+ const span2 = pages.length ? Math.max(...pages) - Math.min(...pages) + 1 : 0;
5722
5651
  const pageNumbered = !tables && (patternNumbers.get(p)?.size ?? 0) > 1;
5723
- if (count >= MIN_REPEAT2 && pages.length >= MIN_REPEAT2 && (pages.length >= span * 0.4 || pageNumbered)) {
5652
+ if (count >= MIN_REPEAT2 && pages.length >= MIN_REPEAT2 && (pages.length >= span2 * 0.4 || pageNumbered)) {
5724
5653
  repeatedPatterns.add(p);
5725
5654
  }
5726
5655
  }
@@ -6099,12 +6028,12 @@ function arrowDirection(image) {
6099
6028
  const points = ink.map((p) => ({ x: mirror ? x0 + x1 - p.x : p.x, y: p.y }));
6100
6029
  const tail = points.filter((p) => p.x <= x0 + w * 0.25), tip = points.filter((p) => p.x >= x1 - w * 0.1);
6101
6030
  if (!tail.length || !tip.length) return false;
6102
- const span = (points2) => Math.max(...points2.map((p) => p.y)) - Math.min(...points2.map((p) => p.y)) + 1;
6103
- if (span(tail) > h * 0.4 || span(tip) > h * 0.45 || Math.abs((Math.max(...tail.map((p) => p.y)) + Math.min(...tail.map((p) => p.y))) / 2 - centerY) > h * 0.1 || Math.abs((Math.max(...tip.map((p) => p.y)) + Math.min(...tip.map((p) => p.y))) / 2 - centerY) > h * 0.1) return false;
6031
+ const span2 = (points2) => Math.max(...points2.map((p) => p.y)) - Math.min(...points2.map((p) => p.y)) + 1;
6032
+ if (span2(tail) > h * 0.4 || span2(tip) > h * 0.45 || Math.abs((Math.max(...tail.map((p) => p.y)) + Math.min(...tail.map((p) => p.y))) / 2 - centerY) > h * 0.1 || Math.abs((Math.max(...tip.map((p) => p.y)) + Math.min(...tip.map((p) => p.y))) / 2 - centerY) > h * 0.1) return false;
6104
6033
  let head = 0;
6105
6034
  for (let x = Math.ceil(x0 + w * 0.45); x <= x0 + w * 0.75; x++) {
6106
6035
  const column = points.filter((p) => p.x === x);
6107
- if (column.length) head = Math.max(head, span(column));
6036
+ if (column.length) head = Math.max(head, span2(column));
6108
6037
  }
6109
6038
  const middle = new Set(points.filter((p) => Math.abs(p.y - centerY) <= 1).map((p) => p.x));
6110
6039
  return head >= h * 0.8 && middle.size >= w * 0.9;
@@ -6245,15 +6174,15 @@ function detectColumnGutter(rects) {
6245
6174
  if (r.x < minX) minX = r.x;
6246
6175
  if (r.x + r.w > maxX) maxX = r.x + r.w;
6247
6176
  }
6248
- const span = maxX - minX;
6249
- if (!Number.isFinite(span) || span < MIN_CONTENT_SPAN) return null;
6250
- const narrow = rects.filter((r) => r.w < span * WIDE_RECT_RATIO && r.w > 0 && r.h > 0);
6177
+ const span2 = maxX - minX;
6178
+ if (!Number.isFinite(span2) || span2 < MIN_CONTENT_SPAN) return null;
6179
+ const narrow = rects.filter((r) => r.w < span2 * WIDE_RECT_RATIO && r.w > 0 && r.h > 0);
6251
6180
  if (narrow.length < SIDE_MIN_COUNT * 2) return null;
6252
6181
  let totalH = 0;
6253
6182
  for (const r of narrow) totalH += r.h;
6254
6183
  if (totalH <= 0) return null;
6255
- const lo = minX + span * GUTTER_SCAN_LO;
6256
- const hi = minX + span * GUTTER_SCAN_HI;
6184
+ const lo = minX + span2 * GUTTER_SCAN_LO;
6185
+ const hi = minX + span2 * GUTTER_SCAN_HI;
6257
6186
  const step = Math.max(2, (hi - lo) / GUTTER_MAX_SAMPLES);
6258
6187
  let gutterX = 0;
6259
6188
  let bestCover = Infinity;
@@ -6336,14 +6265,14 @@ function detectPersistentColumnGutter(rects) {
6336
6265
  if (r.y < minY) minY = r.y;
6337
6266
  if (r.y > maxY) maxY = r.y;
6338
6267
  }
6339
- const span = maxY - minY;
6340
- if (!Number.isFinite(span) || span < 200) return null;
6341
- const upper80 = detectColumnGutter(rects.filter((r) => r.y >= minY + span * 0.2));
6342
- const upper60 = upper80 === null ? null : detectColumnGutter(rects.filter((r) => r.y >= minY + span * 0.4));
6268
+ const span2 = maxY - minY;
6269
+ if (!Number.isFinite(span2) || span2 < 200) return null;
6270
+ const upper80 = detectColumnGutter(rects.filter((r) => r.y >= minY + span2 * 0.2));
6271
+ const upper60 = upper80 === null ? null : detectColumnGutter(rects.filter((r) => r.y >= minY + span2 * 0.4));
6343
6272
  if (upper80 !== null && upper60 !== null && Math.abs(upper80 - upper60) <= 10) return (upper80 + upper60) / 2;
6344
- const lower80 = detectColumnGutter(rects.filter((r) => r.y <= maxY - span * 0.2));
6273
+ const lower80 = detectColumnGutter(rects.filter((r) => r.y <= maxY - span2 * 0.2));
6345
6274
  if (lower80 === null) return null;
6346
- const lower60 = detectColumnGutter(rects.filter((r) => r.y <= maxY - span * 0.4));
6275
+ const lower60 = detectColumnGutter(rects.filter((r) => r.y <= maxY - span2 * 0.4));
6347
6276
  return lower60 !== null && Math.abs(lower80 - lower60) <= 10 ? (lower80 + lower60) / 2 : null;
6348
6277
  }
6349
6278
  function orderByGutter(units, rectOf, gutterX) {
@@ -6385,8 +6314,8 @@ function detectPanelGutters(rects) {
6385
6314
  if (r.x < minX) minX = r.x;
6386
6315
  if (r.x + r.w > maxX) maxX = r.x + r.w;
6387
6316
  }
6388
- const span = maxX - minX;
6389
- if (!Number.isFinite(span) || span < MIN_CONTENT_SPAN) return null;
6317
+ const span2 = maxX - minX;
6318
+ if (!Number.isFinite(span2) || span2 < MIN_CONTENT_SPAN) return null;
6390
6319
  const wideLine = (r) => {
6391
6320
  const same = rects.filter((o) => Math.abs(o.y - r.y) <= 3).sort((a, b) => a.x - b.x);
6392
6321
  let start = same[0].x, end = same[0].x + same[0].w;
@@ -6397,17 +6326,17 @@ function detectPanelGutters(rects) {
6397
6326
  }
6398
6327
  end = Math.max(end, o.x + o.w);
6399
6328
  }
6400
- return r.x >= start && r.x + r.w <= end + 1 && end - start >= span * 0.5;
6329
+ return r.x >= start && r.x + r.w <= end + 1 && end - start >= span2 * 0.5;
6401
6330
  };
6402
- const narrow = rects.filter((r) => r.w < span * WIDE_RECT_RATIO && r.w > 0 && r.h > 0 && !wideLine(r));
6331
+ const narrow = rects.filter((r) => r.w < span2 * WIDE_RECT_RATIO && r.w > 0 && r.h > 0 && !wideLine(r));
6403
6332
  for (const r of narrow) {
6404
6333
  if (r.y < minY) minY = r.y;
6405
6334
  if (r.y + r.h > maxY) maxY = r.y + r.h;
6406
6335
  }
6407
6336
  const gutters = [];
6408
6337
  let runStart = null;
6409
- const step = Math.max(2, span * 0.7 / 400);
6410
- for (let x = minX + span * 0.15; x <= maxX - span * 0.15; x += step) {
6338
+ const step = Math.max(2, span2 * 0.7 / 400);
6339
+ for (let x = minX + span2 * 0.15; x <= maxX - span2 * 0.15; x += step) {
6411
6340
  const empty = !narrow.some((r) => r.x < x && r.x + r.w > x);
6412
6341
  if (empty && runStart === null) runStart = x;
6413
6342
  if (!empty && runStart !== null) {
@@ -6924,6 +6853,80 @@ function headerLineAbove(free, colXs, top) {
6924
6853
  return cols;
6925
6854
  }
6926
6855
 
6856
+ // src/pdf/crossing-frames.ts
6857
+ var TOL = 2;
6858
+ var near = (a, b) => Math.abs(a - b) <= TOL;
6859
+ var span = (a, b) => a <= b ? [a, b] : [b, a];
6860
+ function closedRects(hs, vs) {
6861
+ const covers = (v, x, y1, y2) => {
6862
+ const [lo, hi] = span(v.y1, v.y2);
6863
+ return near(v.x1, x) && lo <= y1 + TOL && hi >= y2 - TOL;
6864
+ };
6865
+ const out = [];
6866
+ for (let i = 0; i < hs.length; i++) {
6867
+ const [ax1, ax2] = span(hs[i].x1, hs[i].x2);
6868
+ for (let j = i + 1; j < hs.length; j++) {
6869
+ const [bx1, bx2] = span(hs[j].x1, hs[j].x2);
6870
+ if (!near(ax1, bx1) || !near(ax2, bx2) || near(hs[i].y1, hs[j].y1)) continue;
6871
+ const y1 = Math.min(hs[i].y1, hs[j].y1), y2 = Math.max(hs[i].y1, hs[j].y1);
6872
+ if (!vs.some((v) => covers(v, ax1, y1, y2)) || !vs.some((v) => covers(v, ax2, y1, y2))) continue;
6873
+ if (!out.some((o) => near(o.x1, ax1) && near(o.x2, ax2) && near(o.y1, y1) && near(o.y2, y2))) out.push({ x1: ax1, x2: ax2, y1, y2 });
6874
+ }
6875
+ }
6876
+ return out;
6877
+ }
6878
+ function freeCorner(x, y, dx, dy, hs, vs) {
6879
+ const beyondX = x + dx * 3 * TOL, beyondY = y + dy * 3 * TOL;
6880
+ const h = hs.some((l) => {
6881
+ const [lo, hi] = span(l.x1, l.x2);
6882
+ return near(l.y1, y) && lo <= beyondX && hi >= beyondX;
6883
+ });
6884
+ const v = vs.some((l) => {
6885
+ const [lo, hi] = span(l.y1, l.y2);
6886
+ return near(l.x1, x) && lo <= beyondY && hi >= beyondY;
6887
+ });
6888
+ return !h && !v;
6889
+ }
6890
+ var strictlyInside = (x, y, r) => x > r.x1 + TOL && x < r.x2 - TOL && y > r.y1 + TOL && y < r.y2 - TOL;
6891
+ var contains3 = (a, b) => a.x1 <= b.x1 + TOL && a.x2 >= b.x2 - TOL && a.y1 <= b.y1 + TOL && a.y2 >= b.y2 - TOL;
6892
+ function cornerIn(a, b, hs, vs) {
6893
+ for (const [x, dx] of [[a.x1, -1], [a.x2, 1]]) for (const [y, dy] of [[a.y1, -1], [a.y2, 1]]) {
6894
+ if (strictlyInside(x, y, b) && freeCorner(x, y, dx, dy, hs, vs)) return true;
6895
+ }
6896
+ return false;
6897
+ }
6898
+ function hasCrossingFrames(grid, horizontals, verticals) {
6899
+ const b = grid.bbox;
6900
+ const inside = (l) => Math.min(l.x1, l.x2) >= b.x1 - TOL && Math.max(l.x1, l.x2) <= b.x2 + TOL && Math.min(l.y1, l.y2) >= b.y1 - TOL && Math.max(l.y1, l.y2) <= b.y2 + TOL;
6901
+ const hs = horizontals.filter(inside), vs = verticals.filter(inside);
6902
+ const rects = closedRects(hs, vs);
6903
+ for (let i = 0; i < rects.length; i++) for (let j = i + 1; j < rects.length; j++) {
6904
+ const a = rects[i], c = rects[j];
6905
+ if (contains3(a, c) || contains3(c, a)) continue;
6906
+ if (cornerIn(a, c, hs, vs) || cornerIn(c, a, hs, vs)) return true;
6907
+ }
6908
+ return false;
6909
+ }
6910
+
6911
+ // src/pdf/spread-labels.ts
6912
+ var NUMBER = /^[-+△▲▽]?\d[\d,]*(?:\.\d+)?%?$/;
6913
+ var SPREAD = /^([가-힣]) ([가-힣])$/;
6914
+ function joinSpreadRowLabels(grid, lex, regions, boxOf, spaced) {
6915
+ for (const row of grid) {
6916
+ if (row.filter((c) => NUMBER.test(c.text.trim())).length < 2) continue;
6917
+ for (const cell of row) {
6918
+ const m = SPREAD.exec(cell.text.trim());
6919
+ if (!m) continue;
6920
+ const lines = CELL_LINES.get(cell), box = boxOf(cell);
6921
+ if (!lines || lines.length !== 1 || !box || spaced(cell)) continue;
6922
+ const { l, r, h } = lines[0];
6923
+ if (r - l < 3 * h || r - l < box.x2 - box.x1 - 2 * h) continue;
6924
+ const word = m[1] + m[2];
6925
+ if (lex.startsWord(word) || lex.isWord(word) || regions.has(word)) cell.text = word;
6926
+ }
6927
+ }
6928
+ }
6929
+
6927
6930
  // src/pdf/cell-edges.ts
6928
6931
  var CLIP_CELL_EDGES = /* @__PURE__ */ new WeakMap();
6929
6932
  var NO_EDGES = Object.freeze({ t: false, b: false, l: false, r: false });
@@ -6936,21 +6939,21 @@ function rules(lines, dir) {
6936
6939
  const sorted = [...lines].sort((a, b) => dir === "h" ? a.y1 - b.y1 : a.x1 - b.x1);
6937
6940
  return { dir, pos: sorted.map((l) => dir === "h" ? l.y1 : l.x1), lines: sorted };
6938
6941
  }
6939
- function seen(r, at, a1, a2, near = EDGE_NEAR2) {
6942
+ function seen(r, at, a1, a2, near2 = EDGE_NEAR2) {
6940
6943
  const len = a2 - a1;
6941
6944
  if (len <= 0) return false;
6942
- const covered = coverage(r, at, a1, a2, near);
6945
+ const covered = coverage(r, at, a1, a2, near2);
6943
6946
  return covered >= len * EDGE_COVER && len - covered <= EDGE_SLACK;
6944
6947
  }
6945
- function coverage(r, at, a1, a2, near) {
6948
+ function coverage(r, at, a1, a2, near2) {
6946
6949
  let i = 0, j = r.pos.length;
6947
6950
  while (i < j) {
6948
6951
  const m = i + j >> 1;
6949
- if (r.pos[m] < at - near) i = m + 1;
6952
+ if (r.pos[m] < at - near2) i = m + 1;
6950
6953
  else j = m;
6951
6954
  }
6952
6955
  const spans = [];
6953
- for (; i < r.pos.length && r.pos[i] <= at + near; i++) {
6956
+ for (; i < r.pos.length && r.pos[i] <= at + near2; i++) {
6954
6957
  const l = r.lines[i];
6955
6958
  const l1 = r.dir === "h" ? Math.min(l.x1, l.x2) : Math.min(l.y1, l.y2), l2 = r.dir === "h" ? Math.max(l.x1, l.x2) : Math.max(l.y1, l.y2);
6956
6959
  const lo = Math.max(a1, l1), hi = Math.min(a2, l2);
@@ -6983,8 +6986,8 @@ function recordClipCellEdges(grids, horizontals, verticals, nonRules) {
6983
6986
  const h = rules(nonRules?.size ? horizontals.filter((l) => !nonRules.has(l)) : horizontals, "h");
6984
6987
  const v = rules(nonRules?.size ? verticals.filter((l) => !nonRules.has(l)) : verticals, "v");
6985
6988
  for (const g of grids) for (const c of g.cells ?? []) {
6986
- const near = c.filler ? Math.min(EDGE_NEAR2, (c.bbox.y2 - c.bbox.y1) / 3) : EDGE_NEAR2;
6987
- CLIP_CELL_EDGES.set(c, edgesOf(c.bbox, h, v, near));
6989
+ const near2 = c.filler ? Math.min(EDGE_NEAR2, (c.bbox.y2 - c.bbox.y1) / 3) : EDGE_NEAR2;
6990
+ CLIP_CELL_EDGES.set(c, edgesOf(c.bbox, h, v, near2));
6988
6991
  }
6989
6992
  }
6990
6993
  function takeClipCellEdges(from, to) {
@@ -7046,38 +7049,38 @@ function isPageFrameGrid(grid, cells, pageWidth, pageHeight, items = []) {
7046
7049
 
7047
7050
  // src/pdf/shaded-open-table.ts
7048
7051
  function closeShadedTableEdges(clipGrids, horizontals, verticals, fillRects) {
7049
- const near = (a, b) => Math.abs(a - b) <= 1.5;
7052
+ const near2 = (a, b) => Math.abs(a - b) <= 1.5;
7050
7053
  let hs = horizontals, vs = verticals;
7051
7054
  const restored = [];
7052
7055
  for (const grid of clipGrids) {
7053
7056
  if (grid.clipParent || grid.rowYs.length !== 2 || grid.colXs.length < 3 || !grid.cells?.length || grid.cells.some((c) => c.filler || c.rowSpan !== 1 || c.colSpan !== 1)) continue;
7054
7057
  const { x1, x2, y1: mid, y2: top } = grid.bbox;
7055
- if (!grid.cells.every((c) => fillRects.some((f) => near(f.x1, c.bbox.x1) && near(f.x2, c.bbox.x2) && near(f.y1, c.bbox.y1) && near(f.y2, c.bbox.y2)))) continue;
7056
- const topRule = hs.find((h) => near(h.y1, top) && near(h.x1, x1) && near(h.x2, x2));
7058
+ if (!grid.cells.every((c) => fillRects.some((f) => near2(f.x1, c.bbox.x1) && near2(f.x2, c.bbox.x2) && near2(f.y1, c.bbox.y1) && near2(f.y2, c.bbox.y2)))) continue;
7059
+ const topRule = hs.find((h) => near2(h.y1, top) && near2(h.x1, x1) && near2(h.x2, x2));
7057
7060
  if (!topRule) continue;
7058
- const dividers = grid.colXs.slice(1, -1).map((x) => vs.find((v) => near(v.x1, x) && near(v.y2, top) && v.y1 <= mid - 6));
7061
+ const dividers = grid.colXs.slice(1, -1).map((x) => vs.find((v) => near2(v.x1, x) && near2(v.y2, top) && v.y1 <= mid - 6));
7059
7062
  if (dividers.some((v) => !v)) continue;
7060
7063
  const bottom = dividers[0].y1;
7061
- if (!dividers.every((v) => near(v.y1, bottom))) continue;
7062
- const bottomRule = hs.find((h) => near(h.y1, bottom) && near(h.x1, x1) && near(h.x2, x2));
7064
+ if (!dividers.every((v) => near2(v.y1, bottom))) continue;
7065
+ const bottomRule = hs.find((h) => near2(h.y1, bottom) && near2(h.x1, x1) && near2(h.x2, x2));
7063
7066
  if (!bottomRule) continue;
7064
- const missing = [x1, x2].filter((x) => !vs.some((v) => near(v.x1, x) && v.y1 <= bottom + 1.5 && v.y2 >= top - 1.5));
7067
+ const missing = [x1, x2].filter((x) => !vs.some((v) => near2(v.x1, x) && v.y1 <= bottom + 1.5 && v.y2 >= top - 1.5));
7065
7068
  if (!missing.length) continue;
7066
7069
  restored.push({ x1, x2, y1: bottom, y2: top });
7067
7070
  vs = vs.concat(missing.map((x) => ({ x1: x, x2: x, y1: bottom, y2: top, lineWidth: topRule.lineWidth })));
7068
- if (!hs.some((h) => near(h.y1, mid) && near(h.x1, x1) && near(h.x2, x2))) {
7071
+ if (!hs.some((h) => near2(h.y1, mid) && near2(h.x1, x1) && near2(h.x2, x2))) {
7069
7072
  hs = hs.concat({ x1, x2, y1: mid, y2: mid, lineWidth: topRule.lineWidth });
7070
7073
  }
7071
7074
  }
7072
7075
  return { horizontals: hs, verticals: vs, restored };
7073
7076
  }
7074
7077
  function nestRestoredShadedGrids(grids, restored, horizontals, verticals) {
7075
- const near = (a, b) => Math.abs(a - b) <= 1.5;
7078
+ const near2 = (a, b) => Math.abs(a - b) <= 1.5;
7076
7079
  if (restored.length === 0) return;
7077
7080
  const nested = /* @__PURE__ */ new Set();
7078
7081
  for (const grid of grids) {
7079
7082
  const b = grid.bbox;
7080
- if (!restored.some((r) => near(r.x1, b.x1) && near(r.x2, b.x2) && near(r.y1, b.y1) && near(r.y2, b.y2))) continue;
7083
+ if (!restored.some((r) => near2(r.x1, b.x1) && near2(r.x2, b.x2) && near2(r.y1, b.y1) && near2(r.y2, b.y2))) continue;
7081
7084
  if (grids.some((g) => g !== grid && b.x1 - g.bbox.x1 >= 0.8 && g.bbox.x2 - b.x2 >= 0.8 && b.y1 - g.bbox.y1 >= 0.8 && g.bbox.y2 - b.y2 >= 0.8)) {
7082
7085
  grid.lineNested = true;
7083
7086
  nested.add(grid);
@@ -7086,10 +7089,10 @@ function nestRestoredShadedGrids(grids, restored, horizontals, verticals) {
7086
7089
  for (const frame of grids) {
7087
7090
  const b = frame.bbox;
7088
7091
  if (frame.lineNested || ![...nested].some((g) => g.bbox.x1 > b.x1 && g.bbox.x2 < b.x2 && g.bbox.y1 > b.y1 && g.bbox.y2 < b.y2)) continue;
7089
- const fullH = horizontals.filter((h) => near(h.x1, b.x1) && near(h.x2, b.x2) && h.y1 >= b.y1 - 1.5 && h.y1 <= b.y2 + 1.5);
7090
- if (!fullH.some((h) => near(h.y1, b.y1)) || !fullH.some((h) => near(h.y1, b.y2)) || fullH.some((h) => h.y1 > b.y1 + 1.5 && h.y1 < b.y2 - 1.5)) continue;
7092
+ const fullH = horizontals.filter((h) => near2(h.x1, b.x1) && near2(h.x2, b.x2) && h.y1 >= b.y1 - 1.5 && h.y1 <= b.y2 + 1.5);
7093
+ if (!fullH.some((h) => near2(h.y1, b.y1)) || !fullH.some((h) => near2(h.y1, b.y2)) || fullH.some((h) => h.y1 > b.y1 + 1.5 && h.y1 < b.y2 - 1.5)) continue;
7091
7094
  const fullV = verticals.filter((v) => v.y1 <= b.y1 + 1.5 && v.y2 >= b.y2 - 1.5 && v.x1 >= b.x1 - 1.5 && v.x1 <= b.x2 + 1.5);
7092
- if (!fullV.some((v) => near(v.x1, b.x1)) || !fullV.some((v) => near(v.x1, b.x2)) || fullV.some((v) => v.x1 > b.x1 + 1.5 && v.x1 < b.x2 - 1.5)) continue;
7095
+ if (!fullV.some((v) => near2(v.x1, b.x1)) || !fullV.some((v) => near2(v.x1, b.x2)) || fullV.some((v) => v.x1 > b.x1 + 1.5 && v.x1 < b.x2 - 1.5)) continue;
7093
7096
  frame.colXs = [b.x1, b.x2];
7094
7097
  frame.rowYs = [b.y2, b.y1];
7095
7098
  }
@@ -7265,7 +7268,7 @@ function buildRow(rowItems, bounds, colSpans) {
7265
7268
  const cols = bounds.length + 1;
7266
7269
  const colOf = (x) => bounds.filter((b) => x > b).length;
7267
7270
  const cells = Array.from({ length: cols }, () => []);
7268
- const span = new Array(cols).fill(1);
7271
+ const span2 = new Array(cols).fill(1);
7269
7272
  for (const it of rowItems) {
7270
7273
  let first = colOf(it.x + EDGE_TOL3), last = colOf(it.x + it.w - EDGE_TOL3);
7271
7274
  if (last > first && colSpans) {
@@ -7279,11 +7282,11 @@ function buildRow(rowItems, bounds, colSpans) {
7279
7282
  }
7280
7283
  }
7281
7284
  cells[first].push(it);
7282
- if (last > first) span[first] = Math.max(span[first], last - first + 1);
7285
+ if (last > first) span2[first] = Math.max(span2[first], last - first + 1);
7283
7286
  }
7284
7287
  const row = [];
7285
7288
  for (let c = 0; c < cols; ) {
7286
- const n = Math.min(span[c], cols - c);
7289
+ const n = Math.min(span2[c], cols - c);
7287
7290
  const items = cells.slice(c, c + n).flat();
7288
7291
  row.push({ text: cellTextToString(items.map((it) => ({ ...it }))), colSpan: n, rowSpan: 1 });
7289
7292
  for (let k = 1; k < n; k++) row.push({ text: "", colSpan: 1, rowSpan: 1 });
@@ -7458,7 +7461,7 @@ function takeFrameSpanningText(items, cutX, pageNum, lex) {
7458
7461
  minX = Math.min(minX, item.x);
7459
7462
  maxR = Math.max(maxR, item.x + item.w);
7460
7463
  }
7461
- const span = maxR - minX;
7464
+ const span2 = maxR - minX;
7462
7465
  const rows = groupByY([...items].sort((a, b) => b.y - a.y || a.x - b.x)).map((line) => {
7463
7466
  const runs = [];
7464
7467
  for (const item of [...line].sort((a, b) => a.x - b.x)) {
@@ -7473,7 +7476,7 @@ function takeFrameSpanningText(items, cutX, pageNum, lex) {
7473
7476
  if (taken.has(run[0]) || run[0].x >= cutX || Math.max(...run.map((i) => i.x + i.w)) <= cutX) continue;
7474
7477
  const lines = [run], fs = Math.max(...run.map((i) => i.fontSize));
7475
7478
  const left = run[0].x, right = Math.max(...run.map((i) => i.x + i.w));
7476
- if (right - left < span * 0.75) continue;
7479
+ if (right - left < span2 * 0.75) continue;
7477
7480
  let prevY = run[0].y;
7478
7481
  for (let next = r + 1; next < rows.length && rows[next].length === 1; next++) {
7479
7482
  const tail = rows[next][0], y = tail[0].y;
@@ -7596,15 +7599,15 @@ function buildFrameCellBlocks(cellItems, nested, pageNum, lex) {
7596
7599
 
7597
7600
  // src/pdf/nested-shaded-headers.ts
7598
7601
  function extendNestedShadedHeaders(clipGrids, lineGrids, horizontals, verticals, fills) {
7599
- const near = (a, b) => Math.abs(a - b) <= 1.5;
7600
- const contains3 = (a, b) => b.x1 >= a.x1 - 1.5 && b.x2 <= a.x2 + 1.5 && b.y1 >= a.y1 - 1.5 && b.y2 <= a.y2 + 1.5;
7602
+ const near2 = (a, b) => Math.abs(a - b) <= 1.5;
7603
+ const contains4 = (a, b) => b.x1 >= a.x1 - 1.5 && b.x2 <= a.x2 + 1.5 && b.y1 >= a.y1 - 1.5 && b.y2 <= a.y2 + 1.5;
7601
7604
  const extended = [];
7602
7605
  for (let i = 0; i < clipGrids.length; i++) {
7603
7606
  const c = clipGrids[i], parent = c.clipParent;
7604
7607
  if (!parent || c.rowYs.length !== 2 || c.colXs.length < 3 || !c.cells?.length || c.cells.some((cell) => cell.filler || cell.rowSpan !== 1 || cell.colSpan !== 1)) continue;
7605
- if (!clipGrids.some((g) => g.rowYs.length === 2 && g.colXs.length === 2 && near(g.bbox.x1, parent.x1) && near(g.bbox.x2, parent.x2) && near(g.bbox.y1, parent.y1) && near(g.bbox.y2, parent.y2))) continue;
7606
- if (!c.cells.every((cell) => fills.some((f) => near(f.x1, cell.bbox.x1) && near(f.x2, cell.bbox.x2) && near(f.y1, cell.bbox.y1) && near(f.y2, cell.bbox.y2)))) continue;
7607
- const host = lineGrids.find((l) => l.rowYs.length > 2 && l.colXs.length === c.colXs.length && c.colXs.every((x, k) => near(x, l.colXs[k])) && c.rowYs.every((y, k) => near(y, l.rowYs[k])) && contains3(parent, l.bbox) && l.rowYs.every((y) => horizontals.some((h) => near(h.y1, y) && near(h.x1, l.bbox.x1) && near(h.x2, l.bbox.x2))) && l.colXs.every((x) => verticals.some((v) => near(v.x1, x) && v.y1 <= l.bbox.y1 + 1.5 && v.y2 >= l.bbox.y2 - 1.5)) && !clipGrids.some((o) => o !== c && !contains3(o.bbox, l.bbox) && Math.min(o.bbox.x2, l.bbox.x2) > Math.max(o.bbox.x1, l.bbox.x1) && Math.min(o.bbox.y2, l.bbox.y2) > Math.max(o.bbox.y1, l.bbox.y1)));
7608
+ if (!clipGrids.some((g) => g.rowYs.length === 2 && g.colXs.length === 2 && near2(g.bbox.x1, parent.x1) && near2(g.bbox.x2, parent.x2) && near2(g.bbox.y1, parent.y1) && near2(g.bbox.y2, parent.y2))) continue;
7609
+ if (!c.cells.every((cell) => fills.some((f) => near2(f.x1, cell.bbox.x1) && near2(f.x2, cell.bbox.x2) && near2(f.y1, cell.bbox.y1) && near2(f.y2, cell.bbox.y2)))) continue;
7610
+ const host = lineGrids.find((l) => l.rowYs.length > 2 && l.colXs.length === c.colXs.length && c.colXs.every((x, k) => near2(x, l.colXs[k])) && c.rowYs.every((y, k) => near2(y, l.rowYs[k])) && contains4(parent, l.bbox) && l.rowYs.every((y) => horizontals.some((h) => near2(h.y1, y) && near2(h.x1, l.bbox.x1) && near2(h.x2, l.bbox.x2))) && l.colXs.every((x) => verticals.some((v) => near2(v.x1, x) && v.y1 <= l.bbox.y1 + 1.5 && v.y2 >= l.bbox.y2 - 1.5)) && !clipGrids.some((o) => o !== c && !contains4(o.bbox, l.bbox) && Math.min(o.bbox.x2, l.bbox.x2) > Math.max(o.bbox.x1, l.bbox.x1) && Math.min(o.bbox.y2, l.bbox.y2) > Math.max(o.bbox.y1, l.bbox.y1)));
7608
7611
  if (!host) continue;
7609
7612
  const grid = { ...host, clipParent: parent, cells: extractCells(host, horizontals, verticals) };
7610
7613
  clipGrids[i] = grid;
@@ -7829,8 +7832,8 @@ function isProseBoxGrid(grid, verticals, table, items) {
7829
7832
  const numCols = grid.colXs.length - 1;
7830
7833
  if (numCols < 2 || grid.rowYs.length < 3) return false;
7831
7834
  const gyMax = grid.rowYs[0], gyMin = grid.rowYs[grid.rowYs.length - 1];
7832
- const span = gyMax - gyMin;
7833
- if (span <= 0) return false;
7835
+ const span2 = gyMax - gyMin;
7836
+ if (span2 <= 0) return false;
7834
7837
  const interior = grid.colXs.slice(1, -1);
7835
7838
  let fullWidthHeight = 0;
7836
7839
  const divided = [];
@@ -7841,19 +7844,19 @@ function isProseBoxGrid(grid, verticals, table, items) {
7841
7844
  divided.push(hasDivider);
7842
7845
  if (h > 0 && !hasDivider) fullWidthHeight += h;
7843
7846
  }
7844
- if (fullWidthHeight < span * PROSEBOX_FULLWIDTH_MIN) return false;
7845
- if (isLabelTabBox(grid, divided, items, span)) return true;
7847
+ if (fullWidthHeight < span2 * PROSEBOX_FULLWIDTH_MIN) return false;
7848
+ if (isLabelTabBox(grid, divided, items, span2)) return true;
7846
7849
  const texts = table.cells.flat().map((c) => c.text.trim()).filter(Boolean);
7847
7850
  const longCells = texts.filter((s) => s.length > PROSEBOX_LONG_CELL_CHARS).length;
7848
7851
  if (longCells < PROSEBOX_LONG_CELL_MIN || longCells < texts.length * PROSEBOX_LONG_CELL_RATIO) return false;
7849
7852
  return true;
7850
7853
  }
7851
- function isLabelTabBox(grid, divided, items, span) {
7854
+ function isLabelTabBox(grid, divided, items, span2) {
7852
7855
  let k = divided.length;
7853
7856
  while (k > 0 && !divided[k - 1]) k--;
7854
7857
  if (k === 0 || k === divided.length) return false;
7855
7858
  const bodyTop = grid.rowYs[k], b = grid.bbox;
7856
- if (bodyTop - grid.rowYs[grid.rowYs.length - 1] < 0.8 * span) return false;
7859
+ if (bodyTop - grid.rowYs[grid.rowYs.length - 1] < 0.8 * span2) return false;
7857
7860
  const label = items.filter((it) => {
7858
7861
  const cx = it.x + it.w / 2, cy = it.y + it.h / 2;
7859
7862
  return cy > bodyTop && cy < b.y2 && cx > b.x1 && cx < b.x2 && it.text.trim();
@@ -7970,6 +7973,14 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
7970
7973
  if (cellItems.length) recordCellLines(irGrid[cell.row][cell.col], cellItems);
7971
7974
  takeClipCellEdges(cell, irGrid[cell.row][cell.col]);
7972
7975
  }
7976
+ if (lex) {
7977
+ const boxes = new Map(cells.map((c) => [irGrid[c.row][c.col], c.bbox]));
7978
+ const spaced = new Set(cells.filter((c) => {
7979
+ const its = [...cellTextMap.get(c) ?? []].sort((a, b) => a.x - b.x);
7980
+ return its.length === 2 && !!its[1].hasSpaceBefore && !its[1].syntheticSpace;
7981
+ }).map((c) => irGrid[c.row][c.col]));
7982
+ joinSpreadRowLabels(irGrid, lex, REGION_LABELS, (cell) => boxes.get(cell), (cell) => spaced.has(cell));
7983
+ }
7973
7984
  let finalGrid = irGrid;
7974
7985
  let finalRows = numRows;
7975
7986
  let rebuiltUsed = false;
@@ -8077,6 +8088,10 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
8077
8088
  blocks.push(chartBlock([...tableItems, ...axis].sort((a, b) => b.y - a.y || a.x - b.x), pageNum, { page: pageNum, x: x1, y: grid.bbox.y1, width: x2 - x1, height: grid.bbox.y2 - grid.bbox.y1 }));
8078
8089
  continue;
8079
8090
  }
8091
+ if (!grid.cells && !nestedAttached && hasCrossingFrames(grid, horizontals, verticals)) {
8092
+ for (const it of tableItems) usedItems.delete(it);
8093
+ continue;
8094
+ }
8080
8095
  const tableBbox = {
8081
8096
  page: pageNum,
8082
8097
  x: grid.bbox.x1,
@@ -8680,13 +8695,6 @@ function rowParagraphs(block) {
8680
8695
  }
8681
8696
 
8682
8697
  export {
8683
- OCR_DET_MODEL,
8684
- OCR_REC_MODEL,
8685
- OCR_REC_DICT,
8686
- getOcrModelsDir,
8687
- ensureOcrModels,
8688
- ocrModelsCached,
8689
- parseCharacterDict,
8690
8698
  extractLines,
8691
8699
  extractImageRegions,
8692
8700
  filterHiddenText,
@@ -8738,4 +8746,4 @@ export {
8738
8746
  UNRULED_REGION_TABLES,
8739
8747
  mergeOcrImageRegions
8740
8748
  };
8741
- //# sourceMappingURL=chunk-PUAKSOZD.js.map
8749
+ //# sourceMappingURL=chunk-3YD3SAQW.js.map