kordoc 4.15.2 → 4.15.4

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 (132) hide show
  1. package/README.md +8 -0
  2. package/dist/{-5HJYDZKM.js → -D6YMPGTL.js} +10 -10
  3. package/dist/{chunk-GYZCXVJX.js → chunk-2UV6BAIF.js} +2 -2
  4. package/dist/{chunk-B4LHTFLY.cjs → chunk-5GZ46MZC.cjs} +6 -6
  5. package/dist/chunk-5GZ46MZC.cjs.map +1 -0
  6. package/dist/{chunk-TCMEK4LF.js → chunk-6SRFRNYO.js} +5 -5
  7. package/dist/{chunk-MJHUOAAI.js → chunk-7DCD22JJ.js} +2 -2
  8. package/dist/{chunk-WQWWVZ6Y.js → chunk-7LTOY7WS.js} +3 -3
  9. package/dist/{chunk-2WERADM4.js → chunk-CY2BMAZ3.js} +9 -9
  10. package/dist/{chunk-GFBLDBL2.js → chunk-H3G7TK5V.js} +2 -2
  11. package/dist/{chunk-GS7T56RP.cjs → chunk-H4Q6UCNU.cjs} +2 -2
  12. package/dist/chunk-H4Q6UCNU.cjs.map +1 -0
  13. package/dist/{chunk-VTUADXSS.js → chunk-IHVWE3C5.js} +2 -2
  14. package/dist/chunk-J55UQC5H.cjs.map +1 -1
  15. package/dist/{chunk-MRPDMIMN.cjs → chunk-JHGTA4RV.cjs} +3 -3
  16. package/dist/chunk-JHGTA4RV.cjs.map +1 -0
  17. package/dist/{chunk-PTN7YG24.js → chunk-JO3MKOBE.js} +177 -13
  18. package/dist/chunk-JO3MKOBE.js.map +1 -0
  19. package/dist/{chunk-ZVN2H7XL.js → chunk-KLNW5H4Q.js} +3 -3
  20. package/dist/{chunk-VRZEPD4K.js → chunk-KR2KUR2L.js} +2 -2
  21. package/dist/{chunk-SX2KSBMO.js → chunk-KYS6DOIU.js} +2 -2
  22. package/dist/{chunk-KY6HUZZR.js → chunk-NK2T4NTO.js} +2 -2
  23. package/dist/chunk-PY2M7YVN.cjs.map +1 -1
  24. package/dist/{chunk-JPJNZXCC.js → chunk-QLLCAEQJ.js} +2 -2
  25. package/dist/{chunk-3Y26ICMC.cjs → chunk-RWDDVTBH.cjs} +6 -6
  26. package/dist/chunk-RWDDVTBH.cjs.map +1 -0
  27. package/dist/{chunk-NYNJP45T.js → chunk-S7HVJQ6Y.js} +177 -13
  28. package/dist/chunk-S7HVJQ6Y.js.map +1 -0
  29. package/dist/{chunk-AS66S3HA.js → chunk-SIQAT7KT.js} +3 -3
  30. package/dist/{chunk-VSI5SRP2.cjs → chunk-SRITXAMQ.cjs} +202 -38
  31. package/dist/chunk-SRITXAMQ.cjs.map +1 -0
  32. package/dist/{chunk-CODOAMAV.js → chunk-UBB7BAFA.js} +2 -2
  33. package/dist/{chunk-73K6BXEQ.js → chunk-UEBFU2U3.js} +2 -2
  34. package/dist/{chunk-VGU4FLLD.cjs → chunk-UUNEKQUU.cjs} +2 -2
  35. package/dist/chunk-UUNEKQUU.cjs.map +1 -0
  36. package/dist/{chunk-KKQBQY32.js → chunk-VFNMPG22.js} +2 -2
  37. package/dist/{chunk-GWTN34UT.js → chunk-YIFFNFEO.js} +2 -2
  38. package/dist/{chunk-N4WZZ2PR.js → chunk-YNAIAEOA.js} +2 -2
  39. package/dist/chunks-AGZD5STK.js +10 -0
  40. package/dist/cli.js +25 -25
  41. package/dist/{formula-D4PUT5J3.js → formula-CJSQ7UOL.js} +3 -3
  42. package/dist/{formula-DYVJSHWN.cjs → formula-CZLVSDDH.cjs} +10 -10
  43. package/dist/formula-CZLVSDDH.cjs.map +1 -0
  44. package/dist/{formula-QVHAUNK6.js → formula-ZMFDYMTE.js} +4 -4
  45. package/dist/{image-ocr-5BHKFZL6.js → image-ocr-BPYZH6CJ.js} +7 -7
  46. package/dist/{image-ocr-SGANCWQ5.cjs → image-ocr-RE27IJJL.cjs} +14 -14
  47. package/dist/image-ocr-RE27IJJL.cjs.map +1 -0
  48. package/dist/{image-ocr-TNNFV5VQ.js → image-ocr-YFRXHIMH.js} +5 -5
  49. package/dist/index.cjs +236 -236
  50. package/dist/index.cjs.map +1 -1
  51. package/dist/index.js +4 -4
  52. package/dist/mcp.js +21 -21
  53. package/dist/{model-bundle-ISGAMXQS.js → model-bundle-5ZXMHOCZ.js} +5 -5
  54. package/dist/{models-LI5INKZM.js → models-2SR5HYEU.js} +5 -5
  55. package/dist/{page-range-QHHFTL7X.cjs → page-range-WO7ADTXZ.cjs} +2 -2
  56. package/dist/page-range-WO7ADTXZ.cjs.map +1 -0
  57. package/dist/{parser-GW3KRTXY.js → parser-5CPM5VTB.js} +31 -8
  58. package/dist/parser-5CPM5VTB.js.map +1 -0
  59. package/dist/{parser-EYJID4YX.js → parser-M77PHHCS.js} +30 -7
  60. package/dist/parser-M77PHHCS.js.map +1 -0
  61. package/dist/{parser-XCXDSKQ3.cjs → parser-OJ4GRFTO.cjs} +115 -92
  62. package/dist/parser-OJ4GRFTO.cjs.map +1 -0
  63. package/dist/pdf-ocr-N7ZSSU4B.js +15 -0
  64. package/dist/pdf-ocr-PZMP333N.cjs +16 -0
  65. package/dist/pdf-ocr-PZMP333N.cjs.map +1 -0
  66. package/dist/pdf-ocr-W4V5AT24.js +18 -0
  67. package/dist/{profile-io-DBN56Y2Z.js → profile-io-JNHSNLKB.js} +3 -3
  68. package/dist/{rasterize-BYRCKQIW.js → rasterize-3L6X4SMV.js} +3 -3
  69. package/dist/{redact-doc-UP2J6RRP.js → redact-doc-YALOOA37.js} +10 -10
  70. package/dist/{render-WGD5DN4G.js → render-Q26GOZ2V.js} +6 -6
  71. package/dist/seal-GY2J6TFW.js +10 -0
  72. package/dist/{setup-E5JILUAN.js → setup-U4OZBOVP.js} +3 -3
  73. package/dist/visual-5AUY4EQJ.js +20 -0
  74. package/dist/{watch-LKWPCU42.js → watch-NXLLPCQG.js} +11 -11
  75. package/package.json +1 -1
  76. package/dist/chunk-3Y26ICMC.cjs.map +0 -1
  77. package/dist/chunk-B4LHTFLY.cjs.map +0 -1
  78. package/dist/chunk-GS7T56RP.cjs.map +0 -1
  79. package/dist/chunk-MRPDMIMN.cjs.map +0 -1
  80. package/dist/chunk-NYNJP45T.js.map +0 -1
  81. package/dist/chunk-PTN7YG24.js.map +0 -1
  82. package/dist/chunk-VGU4FLLD.cjs.map +0 -1
  83. package/dist/chunk-VSI5SRP2.cjs.map +0 -1
  84. package/dist/chunks-C3AW42QH.js +0 -10
  85. package/dist/formula-DYVJSHWN.cjs.map +0 -1
  86. package/dist/image-ocr-SGANCWQ5.cjs.map +0 -1
  87. package/dist/page-range-QHHFTL7X.cjs.map +0 -1
  88. package/dist/parser-EYJID4YX.js.map +0 -1
  89. package/dist/parser-GW3KRTXY.js.map +0 -1
  90. package/dist/parser-XCXDSKQ3.cjs.map +0 -1
  91. package/dist/pdf-ocr-JCJAME6Q.js +0 -15
  92. package/dist/pdf-ocr-K7MJFRBS.cjs +0 -16
  93. package/dist/pdf-ocr-K7MJFRBS.cjs.map +0 -1
  94. package/dist/pdf-ocr-TC3BN2MV.js +0 -18
  95. package/dist/seal-5GAFTYQO.js +0 -10
  96. package/dist/visual-FKV2TRYY.js +0 -20
  97. /package/dist/{-5HJYDZKM.js.map → -D6YMPGTL.js.map} +0 -0
  98. /package/dist/{chunk-GYZCXVJX.js.map → chunk-2UV6BAIF.js.map} +0 -0
  99. /package/dist/{chunk-TCMEK4LF.js.map → chunk-6SRFRNYO.js.map} +0 -0
  100. /package/dist/{chunk-MJHUOAAI.js.map → chunk-7DCD22JJ.js.map} +0 -0
  101. /package/dist/{chunk-WQWWVZ6Y.js.map → chunk-7LTOY7WS.js.map} +0 -0
  102. /package/dist/{chunk-2WERADM4.js.map → chunk-CY2BMAZ3.js.map} +0 -0
  103. /package/dist/{chunk-GFBLDBL2.js.map → chunk-H3G7TK5V.js.map} +0 -0
  104. /package/dist/{chunk-VTUADXSS.js.map → chunk-IHVWE3C5.js.map} +0 -0
  105. /package/dist/{chunk-ZVN2H7XL.js.map → chunk-KLNW5H4Q.js.map} +0 -0
  106. /package/dist/{chunk-VRZEPD4K.js.map → chunk-KR2KUR2L.js.map} +0 -0
  107. /package/dist/{chunk-SX2KSBMO.js.map → chunk-KYS6DOIU.js.map} +0 -0
  108. /package/dist/{chunk-KY6HUZZR.js.map → chunk-NK2T4NTO.js.map} +0 -0
  109. /package/dist/{chunk-JPJNZXCC.js.map → chunk-QLLCAEQJ.js.map} +0 -0
  110. /package/dist/{chunk-AS66S3HA.js.map → chunk-SIQAT7KT.js.map} +0 -0
  111. /package/dist/{chunk-CODOAMAV.js.map → chunk-UBB7BAFA.js.map} +0 -0
  112. /package/dist/{chunk-73K6BXEQ.js.map → chunk-UEBFU2U3.js.map} +0 -0
  113. /package/dist/{chunk-KKQBQY32.js.map → chunk-VFNMPG22.js.map} +0 -0
  114. /package/dist/{chunk-GWTN34UT.js.map → chunk-YIFFNFEO.js.map} +0 -0
  115. /package/dist/{chunk-N4WZZ2PR.js.map → chunk-YNAIAEOA.js.map} +0 -0
  116. /package/dist/{chunks-C3AW42QH.js.map → chunks-AGZD5STK.js.map} +0 -0
  117. /package/dist/{formula-D4PUT5J3.js.map → formula-CJSQ7UOL.js.map} +0 -0
  118. /package/dist/{formula-QVHAUNK6.js.map → formula-ZMFDYMTE.js.map} +0 -0
  119. /package/dist/{image-ocr-5BHKFZL6.js.map → image-ocr-BPYZH6CJ.js.map} +0 -0
  120. /package/dist/{image-ocr-TNNFV5VQ.js.map → image-ocr-YFRXHIMH.js.map} +0 -0
  121. /package/dist/{model-bundle-ISGAMXQS.js.map → model-bundle-5ZXMHOCZ.js.map} +0 -0
  122. /package/dist/{models-LI5INKZM.js.map → models-2SR5HYEU.js.map} +0 -0
  123. /package/dist/{pdf-ocr-JCJAME6Q.js.map → pdf-ocr-N7ZSSU4B.js.map} +0 -0
  124. /package/dist/{pdf-ocr-TC3BN2MV.js.map → pdf-ocr-W4V5AT24.js.map} +0 -0
  125. /package/dist/{profile-io-DBN56Y2Z.js.map → profile-io-JNHSNLKB.js.map} +0 -0
  126. /package/dist/{rasterize-BYRCKQIW.js.map → rasterize-3L6X4SMV.js.map} +0 -0
  127. /package/dist/{redact-doc-UP2J6RRP.js.map → redact-doc-YALOOA37.js.map} +0 -0
  128. /package/dist/{render-WGD5DN4G.js.map → render-Q26GOZ2V.js.map} +0 -0
  129. /package/dist/{seal-5GAFTYQO.js.map → seal-GY2J6TFW.js.map} +0 -0
  130. /package/dist/{setup-E5JILUAN.js.map → setup-U4OZBOVP.js.map} +0 -0
  131. /package/dist/{visual-FKV2TRYY.js.map → visual-5AUY4EQJ.js.map} +0 -0
  132. /package/dist/{watch-LKWPCU42.js.map → watch-NXLLPCQG.js.map} +0 -0
@@ -6,10 +6,10 @@ import {
6
6
  ensureOcrModels,
7
7
  getOcrModelsDir,
8
8
  parseCharacterDict
9
- } from "./chunk-VTUADXSS.js";
9
+ } from "./chunk-IHVWE3C5.js";
10
10
  import {
11
11
  extractPageBlocksWithLines
12
- } from "./chunk-PTN7YG24.js";
12
+ } from "./chunk-JO3MKOBE.js";
13
13
 
14
14
  // src/ocr/ruling-lines.ts
15
15
  var INK_LUMA_MAX = 205;
@@ -1307,4 +1307,4 @@ export {
1307
1307
  runPdfOcr,
1308
1308
  ocrItemsToBlocks
1309
1309
  };
1310
- //# sourceMappingURL=chunk-AS66S3HA.js.map
1310
+ //# sourceMappingURL=chunk-SIQAT7KT.js.map
@@ -6,7 +6,7 @@ var _chunkPY2M7YVNcjs = require('./chunk-PY2M7YVN.cjs');
6
6
 
7
7
 
8
8
 
9
- var _chunkVGU4FLLDcjs = require('./chunk-VGU4FLLD.cjs');
9
+ var _chunkUUNEKQUUcjs = require('./chunk-UUNEKQUU.cjs');
10
10
 
11
11
  // src/pdf/image-regions.ts
12
12
  var _pdfmjs = require('pdfjs-dist/legacy/build/pdf.mjs');
@@ -824,9 +824,20 @@ function buildTableGrids(horizontals, verticals) {
824
824
  }
825
825
  const groupRadius = groupVertices.length > 0 ? groupVertices.reduce((max, v) => Math.max(max, v.radius), 1) : globalRadius;
826
826
  const coordMergeTol = Math.max(VERTEX_MERGE_FACTOR * groupRadius, MIN_COORD_MERGE_TOL);
827
+ const leftEdge = Math.min(...vLines.map((v) => v.x1));
828
+ const rightEdge = Math.max(...vLines.map((v) => v.x1));
829
+ const underlines = hLines.filter((h) => {
830
+ const crossings = /* @__PURE__ */ new Set();
831
+ for (const v of vLines) {
832
+ if (v.x1 >= h.x1 - CONNECT_TOL && v.x1 <= h.x2 + CONNECT_TOL && h.y1 >= v.y1 - CONNECT_TOL && h.y1 <= v.y2 + CONNECT_TOL) crossings.add(v.x1);
833
+ }
834
+ return crossings.size === 1 && Math.abs(h.x2 - rightEdge) <= CONNECT_TOL && h.x1 > (leftEdge + rightEdge) / 2 && h.x2 - h.x1 < (rightEdge - leftEdge) * 0.6;
835
+ });
836
+ const rowLines = underlines.length >= 3 && hLines.length - underlines.length <= 4 ? hLines.filter((h) => !underlines.includes(h)) : hLines;
837
+ const rowVertices = rowLines.length === hLines.length ? groupVertices : groupVertices.filter((v) => rowLines.some((h) => Math.abs(v.y - h.y1) <= CONNECT_TOL));
827
838
  const rawYs = [
828
- ...hLines.map((l) => l.y1),
829
- ...groupVertices.map((v) => v.y)
839
+ ...rowLines.map((l) => l.y1),
840
+ ...rowVertices.map((v) => v.y)
830
841
  ];
831
842
  const rowYs = clusterCoordinates(rawYs, coordMergeTol).sort((a, b) => b - a);
832
843
  const rawXs = [
@@ -861,7 +872,7 @@ function dropShadingClipGrids(clipGrids, lineGrids, fillRects, verticals = []) {
861
872
  if (!shaded) return true;
862
873
  const ruled = c.cells.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));
863
874
  if (!ruled) return true;
864
- const host = lineGrids.find((l) => 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 + inter(o.bbox, l.bbox), 0) <= area(l.bbox) * SHADE_CLIP_MAX_AREA);
875
+ const host = lineGrids.find((l) => 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 + 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)));
865
876
  return !host;
866
877
  });
867
878
  }
@@ -1148,10 +1159,28 @@ function buildClipCellGrids(rects, strokedH, strokedV, pageWidth, pageHeight, te
1148
1159
  const pageArea = pageWidth * pageHeight;
1149
1160
  const sameRect = (a, b) => Math.abs(a.x1 - b.x1) <= CLIP_EDGE_TOL && Math.abs(a.x2 - b.x2) <= CLIP_EDGE_TOL && Math.abs(a.y1 - b.y1) <= CLIP_EDGE_TOL && Math.abs(a.y2 - b.y2) <= CLIP_EDGE_TOL;
1150
1161
  const cells = [];
1162
+ const buckets = /* @__PURE__ */ new Map();
1151
1163
  for (const r of rects) {
1152
1164
  if (r.x2 - r.x1 < CLIP_MIN_W2 || r.y2 - r.y1 < CLIP_MIN_H2) continue;
1153
1165
  if (pageArea > 0 && (r.x2 - r.x1) * (r.y2 - r.y1) >= pageArea * CLIP_MAX_PAGE_FRAC) continue;
1154
- if (!cells.some((c) => sameRect(c, r))) cells.push(r);
1166
+ const bx = Math.floor(r.x1 / CLIP_EDGE_TOL), by = Math.floor(r.y1 / CLIP_EDGE_TOL);
1167
+ let duplicate = false;
1168
+ for (let dx = -1; dx <= 1 && !duplicate; dx++) {
1169
+ const ys2 = buckets.get(bx + dx);
1170
+ for (let dy = -1; dy <= 1 && !duplicate; dy++) {
1171
+ duplicate = _nullishCoalesce(_optionalChain([ys2, 'optionalAccess', _12 => _12.get, 'call', _13 => _13(by + dy), 'optionalAccess', _14 => _14.some, 'call', _15 => _15((c) => sameRect(c, r))]), () => ( false));
1172
+ }
1173
+ }
1174
+ if (duplicate) continue;
1175
+ cells.push(r);
1176
+ let ys = buckets.get(bx);
1177
+ if (!ys) {
1178
+ ys = /* @__PURE__ */ new Map();
1179
+ buckets.set(bx, ys);
1180
+ }
1181
+ const row = ys.get(by);
1182
+ if (row) row.push(r);
1183
+ else ys.set(by, [r]);
1155
1184
  }
1156
1185
  if (cells.length < 1) return { grids: [], containers: [], page: { lastCells: [], clips: [] } };
1157
1186
  const parent = new Array(cells.length).fill(-1);
@@ -1210,9 +1239,32 @@ function buildClipCellGrids(rects, strokedH, strokedV, pageWidth, pageHeight, te
1210
1239
  }
1211
1240
  return i;
1212
1241
  };
1242
+ const edgeBin = (v) => Math.floor(v / CLIP_ADJ_GAP);
1243
+ const startsX = /* @__PURE__ */ new Map(), endsX = /* @__PURE__ */ new Map();
1244
+ const startsY = /* @__PURE__ */ new Map(), endsY = /* @__PURE__ */ new Map();
1245
+ const addEdge = (map, v, i) => {
1246
+ const k = edgeBin(v), row = map.get(k);
1247
+ if (row) row.push(i);
1248
+ else map.set(k, [i]);
1249
+ };
1250
+ for (let i = 0; i < cells.length; i++) {
1251
+ addEdge(startsX, cells[i].x1, i);
1252
+ addEdge(endsX, cells[i].x2, i);
1253
+ addEdge(startsY, cells[i].y1, i);
1254
+ addEdge(endsY, cells[i].y2, i);
1255
+ }
1213
1256
  for (let i = 0; i < cells.length; i++) {
1214
1257
  if (tableClip[i]) continue;
1215
- for (let j = i + 1; j < cells.length; j++) {
1258
+ const candidates = /* @__PURE__ */ new Set();
1259
+ const near = (map, v) => {
1260
+ const k = edgeBin(v);
1261
+ for (let d = -1; d <= 1; d++) for (const j of _nullishCoalesce(map.get(k + d), () => ( []))) if (j > i) candidates.add(j);
1262
+ };
1263
+ near(startsX, cells[i].x2);
1264
+ near(endsX, cells[i].x1);
1265
+ near(startsY, cells[i].y2);
1266
+ near(endsY, cells[i].y1);
1267
+ for (const j of [...candidates].sort((a, b) => a - b)) {
1216
1268
  if (tableClip[j] || parent[i] !== parent[j]) continue;
1217
1269
  if (adjacent(cells[i], cells[j])) {
1218
1270
  const ra = find(i), rb = find(j);
@@ -1233,7 +1285,7 @@ function buildClipCellGrids(rects, strokedH, strokedV, pageWidth, pageHeight, te
1233
1285
  else groups.set(r, [i]);
1234
1286
  }
1235
1287
  const containers = cells.filter((_, i) => isContainer[i]);
1236
- const groupSize = (i) => _nullishCoalesce(_optionalChain([groups, 'access', _12 => _12.get, 'call', _13 => _13(find(i)), 'optionalAccess', _14 => _14.length]), () => ( 0));
1288
+ const groupSize = (i) => _nullishCoalesce(_optionalChain([groups, 'access', _16 => _16.get, 'call', _17 => _17(find(i)), 'optionalAccess', _18 => _18.length]), () => ( 0));
1237
1289
  const isGridMember = (i) => groupSize(i) >= CLIP_MIN_GROUP;
1238
1290
  const framed = (r) => edgeStroked(strokedH, "h", r.y1, r.x1, r.x2) && edgeStroked(strokedH, "h", r.y2, r.x1, r.x2) && edgeStroked(strokedV, "v", r.x1, r.y1, r.y2) && edgeStroked(strokedV, "v", r.x2, r.y1, r.y2);
1239
1291
  const titledFrame = (r) => r.y1 >= pageHeight * TITLED_FRAME_MIN_TOP && r.x2 - r.x1 >= pageWidth * TITLED_FRAME_MIN_WIDTH && textPoints.some((p) => p.y < r.y1 && p.y > pageHeight * HEADER_BAND && p.x >= r.x1 - CLIP_EDGE_TOL && p.x <= r.x2 + CLIP_EDGE_TOL) && textPoints.some((p) => p.x > r.x1 && p.x < r.x2 && p.y > r.y1 && p.y < r.y2);
@@ -1664,7 +1716,7 @@ var WrapLexicon = (_class = class {constructor() { _class.prototype.__init.call(
1664
1716
  const n = left.length;
1665
1717
  if (n >= 2 && right.length >= 2) {
1666
1718
  const k1 = pairKey(left.charCodeAt(n - 2), left.charCodeAt(n - 1)), k2 = pairKey(right.charCodeAt(0), right.charCodeAt(1));
1667
- const v = decideCounts(_nullishCoalesce(_optionalChain([this, 'access', _15 => _15.joined2, 'access', _16 => _16.get, 'call', _17 => _17(k1), 'optionalAccess', _18 => _18.get, 'call', _19 => _19(k2)]), () => ( 0)), _nullishCoalesce(_optionalChain([this, 'access', _20 => _20.spaced2, 'access', _21 => _21.get, 'call', _22 => _22(k1), 'optionalAccess', _23 => _23.get, 'call', _24 => _24(k2)]), () => ( 0)));
1719
+ const v = decideCounts(_nullishCoalesce(_optionalChain([this, 'access', _19 => _19.joined2, 'access', _20 => _20.get, 'call', _21 => _21(k1), 'optionalAccess', _22 => _22.get, 'call', _23 => _23(k2)]), () => ( 0)), _nullishCoalesce(_optionalChain([this, 'access', _24 => _24.spaced2, 'access', _25 => _25.get, 'call', _26 => _26(k1), 'optionalAccess', _27 => _27.get, 'call', _28 => _28(k2)]), () => ( 0)));
1668
1720
  if (v !== null) return v;
1669
1721
  }
1670
1722
  if (n && right.length) {
@@ -1735,7 +1787,7 @@ function wrapJoiner(prevText, nextText, lex) {
1735
1787
  if (endsAsWord(left)) return " ";
1736
1788
  if (/[·ㆍ‧-]/.test(a) && !/[·ㆍ‧…]{2}$/.test(prev) && /[가-힣A-Za-z0-9]/.test(b)) return "";
1737
1789
  if (/[A-Za-z]/.test(a) && /[A-Za-z]/.test(b) || /\d/.test(a) && /\d/.test(b)) return " ";
1738
- const ev = _optionalChain([lex, 'optionalAccess', _25 => _25.evidence, 'call', _26 => _26(left, right)]);
1790
+ const ev = _optionalChain([lex, 'optionalAccess', _29 => _29.evidence, 'call', _30 => _30(left, right)]);
1739
1791
  if (ev != null) return ev;
1740
1792
  if (lex && /[가-힣A-Za-z0-9]$/.test(left) && /^[가-힣A-Za-z0-9]/.test(right) && lex.joinedWord(left, right.replace(/[.,)」』’”;:]+$/, ""))) return "";
1741
1793
  if (/\d$/.test(left) && COUNTER.test(right)) return "";
@@ -1757,7 +1809,7 @@ function joinPageBreakWraps(blocks, lex) {
1757
1809
  if (a.type !== "paragraph" && a.type !== "list" || b.type !== "paragraph") continue;
1758
1810
  const last = a.bbox && PARA_LAST_LINE.get(a.bbox), fs = last ? last.fontSize : 0;
1759
1811
  if (!last || fs <= 0 || (_nullishCoalesce(pageRight.get(a.pageNumber), () => ( Infinity))) - last.right >= BODY_FULL_TOL * fs) continue;
1760
- if (last.width < BODY_MIN_WIDTH_EM * fs || Math.abs((_nullishCoalesce(_optionalChain([b, 'access', _27 => _27.style, 'optionalAccess', _28 => _28.fontSize]), () => ( 0))) - fs) > 0.15 * fs) continue;
1812
+ if (last.width < BODY_MIN_WIDTH_EM * fs || Math.abs((_nullishCoalesce(_optionalChain([b, 'access', _31 => _31.style, 'optionalAccess', _32 => _32.fontSize]), () => ( 0))) - fs) > 0.15 * fs) continue;
1761
1813
  if (startsNewItem(a.text, b.text)) continue;
1762
1814
  a.text += wrapJoiner(a.text, b.text, lex) + b.text;
1763
1815
  const bl = b.bbox && PARA_LAST_LINE.get(b.bbox);
@@ -2051,7 +2103,7 @@ function mergeCellTextLines(textLines, wrap) {
2051
2103
  }
2052
2104
 
2053
2105
  // src/pdf/undersegmented.ts
2054
- var MAX_UNDERSEGMENTED_ROWS = 2;
2106
+ var MAX_UNDERSEGMENTED_ROWS = 5;
2055
2107
  var MIN_UNDERSEGMENTED_COLUMNS = 3;
2056
2108
  var MIN_UNDERSEGMENTED_TEXT_LINES = 8;
2057
2109
  var MIN_ROW_BAND_MISMATCH = 2;
@@ -2099,11 +2151,30 @@ function groupItemsToVisualLines(items) {
2099
2151
  lines.push(cur);
2100
2152
  return lines;
2101
2153
  }
2102
- function normalizeUndersegmentedTable(originalCells, colXs, items) {
2154
+ function normalizeUndersegmentedTable(originalCells, colXs, items, rowYs) {
2103
2155
  const numRows = originalCells.length;
2104
2156
  const numCols = colXs.length - 1;
2105
2157
  if (numRows > MAX_UNDERSEGMENTED_ROWS || numCols < MIN_UNDERSEGMENTED_COLUMNS) return null;
2106
2158
  if (items.length === 0) return null;
2159
+ if (numRows >= 3) {
2160
+ if (_optionalChain([rowYs, 'optionalAccess', _33 => _33.length]) !== numRows + 1) return null;
2161
+ const rebuilt2 = [];
2162
+ let expanded = 0;
2163
+ for (let r = 0; r < numRows; r++) {
2164
+ const row = originalCells[r].map((cell) => cell.text);
2165
+ if (r === 0 || numRows === 3 && r === 1) {
2166
+ rebuilt2.push(row);
2167
+ continue;
2168
+ }
2169
+ const rowItems = items.filter((item) => itemCenterY(item) <= rowYs[r] + 1 && itemCenterY(item) >= rowYs[r + 1] - 1);
2170
+ const body = normalizeUndersegmentedTable([originalCells[r]], colXs, rowItems);
2171
+ if (body) {
2172
+ rebuilt2.push(...body);
2173
+ expanded++;
2174
+ } else rebuilt2.push(row);
2175
+ }
2176
+ return expanded ? rebuilt2 : null;
2177
+ }
2107
2178
  const itemsByCol = Array.from({ length: numCols }, () => []);
2108
2179
  for (const item of items) {
2109
2180
  if (!item.text.trim()) continue;
@@ -2235,7 +2306,7 @@ function dominantStyle(items) {
2235
2306
  }
2236
2307
  }
2237
2308
  if (dominantSize === 0) return void 0;
2238
- const fontName = _optionalChain([items, 'access', _29 => _29.find, 'call', _30 => _30((i) => i.fontSize === dominantSize), 'optionalAccess', _31 => _31.fontName]) || void 0;
2309
+ const fontName = _optionalChain([items, 'access', _34 => _34.find, 'call', _35 => _35((i) => i.fontSize === dominantSize), 'optionalAccess', _36 => _36.fontName]) || void 0;
2239
2310
  return fontName ? { fontSize: dominantSize, fontName } : { fontSize: dominantSize };
2240
2311
  }
2241
2312
  function normalizeItems(rawItems) {
@@ -2344,7 +2415,7 @@ function splitAroundOverlays(c, overlays) {
2344
2415
  const ov = overlays.filter((o) => {
2345
2416
  for (let at = c.text.indexOf(o.text); at >= 0; at = c.text.indexOf(o.text, at + 1)) {
2346
2417
  const prefix = c.text.slice(0, at);
2347
- const est = c.x + glyphUnits(prefix.replace(/\s+/g, "")) * a0 + (_nullishCoalesce(_optionalChain([prefix, 'access', _32 => _32.match, 'call', _33 => _33(/\s+/g), 'optionalAccess', _34 => _34.length]), () => ( 0))) * ws;
2418
+ const est = c.x + glyphUnits(prefix.replace(/\s+/g, "")) * a0 + (_nullishCoalesce(_optionalChain([prefix, 'access', _37 => _37.match, 'call', _38 => _38(/\s+/g), 'optionalAccess', _39 => _39.length]), () => ( 0))) * ws;
2348
2419
  if (Math.abs(est - o.x) <= OVERLAY_DUP_EM * fs) return false;
2349
2420
  }
2350
2421
  return true;
@@ -2457,7 +2528,7 @@ function mergeSuperscriptLines(lines) {
2457
2528
  return result;
2458
2529
  }
2459
2530
  function mergeLineSimple(items) {
2460
- if (items.length <= 1) return _optionalChain([items, 'access', _35 => _35[0], 'optionalAccess', _36 => _36.text]) || "";
2531
+ if (items.length <= 1) return _optionalChain([items, 'access', _40 => _40[0], 'optionalAccess', _41 => _41.text]) || "";
2461
2532
  const sorted = sortLineByX([...items]);
2462
2533
  const isEvenSpaced = detectEvenSpacedItems(sorted);
2463
2534
  let result = sorted[0].text;
@@ -2506,7 +2577,7 @@ function computeMedianFontSizeFromFreq(freq) {
2506
2577
  }
2507
2578
  function detectHeadings(blocks, medianFontSize) {
2508
2579
  for (const block of blocks) {
2509
- if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _37 => _37.style, 'optionalAccess', _38 => _38.fontSize])) continue;
2580
+ if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _42 => _42.style, 'optionalAccess', _43 => _43.fontSize])) continue;
2510
2581
  const text = block.text.trim();
2511
2582
  if (text.length === 0 || text.length > 200) continue;
2512
2583
  if (/^\d+$/.test(text)) continue;
@@ -2522,6 +2593,43 @@ function detectHeadings(blocks, medianFontSize) {
2522
2593
  }
2523
2594
  }
2524
2595
  }
2596
+ function detectTypographyHeadings(blocks) {
2597
+ const byPage = /* @__PURE__ */ new Map();
2598
+ for (const block of blocks) {
2599
+ if (!block.pageNumber) continue;
2600
+ const page = _nullishCoalesce(byPage.get(block.pageNumber), () => ( []));
2601
+ page.push(block);
2602
+ byPage.set(block.pageNumber, page);
2603
+ }
2604
+ for (const page of byPage.values()) {
2605
+ if (page.some((block) => block.type === "heading")) continue;
2606
+ const faceWeight = /* @__PURE__ */ new Map();
2607
+ for (const block of page) {
2608
+ if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _44 => _44.style, 'optionalAccess', _45 => _45.fontName])) continue;
2609
+ const face = block.style.fontName;
2610
+ faceWeight.set(face, (_nullishCoalesce(faceWeight.get(face), () => ( 0))) + block.text.length);
2611
+ }
2612
+ const bodyFace = _optionalChain([[...faceWeight], 'access', _46 => _46.sort, 'call', _47 => _47((a, b) => b[1] - a[1]), 'access', _48 => _48[0], 'optionalAccess', _49 => _49[0]]);
2613
+ if (!bodyFace || (_nullishCoalesce(faceWeight.get(bodyFace), () => ( 0))) < 250) continue;
2614
+ for (let i = 0; i < page.length; i++) {
2615
+ const block = page[i];
2616
+ const { text, bbox, style } = block;
2617
+ if (block.type !== "paragraph" || !text || !bbox || !_optionalChain([style, 'optionalAccess', _50 => _50.fontName]) || !style.fontSize) continue;
2618
+ const title = text.trim();
2619
+ const numbered = /^\d+(?:\.\d+)*\.?\s+[A-Z가-힣]/.test(title);
2620
+ if (style.fontName === bodyFace || title.length < 3 || title.length > 120 || /^\d+$/.test(title) || /^(?:table|figure|fig\.?|표|그림)\s*\d/i.test(title) || /^(?:doi:|https?:|[•●○▪▫])/i.test(title) || /^(?:over|under)\s+\d+$/i.test(title) || /^[\d\s.,:%+\-–]+$/.test(title) || bbox.height > style.fontSize * (numbered ? 2.4 : 1.6) || title.includes("\n")) continue;
2621
+ const centerX = bbox.x + bbox.width / 2;
2622
+ const nearby = page.filter((other) => other !== block && other.bbox && other.type !== "image" && other.type !== "separator" && other.bbox.x < centerX && centerX < other.bbox.x + other.bbox.width);
2623
+ const above = nearby.filter((other) => other.bbox.y >= bbox.y + bbox.height).sort((a, b) => a.bbox.y - b.bbox.y)[0];
2624
+ const below = nearby.filter((other) => other.bbox.y + other.bbox.height <= bbox.y).sort((a, b) => b.bbox.y - a.bbox.y)[0];
2625
+ const gapAbove = above ? above.bbox.y - bbox.y - bbox.height : Infinity;
2626
+ const gapBelow = below ? bbox.y - below.bbox.y - below.bbox.height : Infinity;
2627
+ if (Math.max(gapAbove, gapBelow) < style.fontSize * (numbered ? 0.7 : 1.2)) continue;
2628
+ block.type = "heading";
2629
+ block.level = 2;
2630
+ }
2631
+ }
2632
+ }
2525
2633
  function shouldDemoteTable(table) {
2526
2634
  const allCells = table.cells.flatMap((row) => row.map((c) => c.text.trim())).filter(Boolean);
2527
2635
  const allText = allCells.join(" ");
@@ -2567,7 +2675,7 @@ function detectMarkerHeadings(blocks) {
2567
2675
  block.level = 4;
2568
2676
  continue;
2569
2677
  }
2570
- if (/^[가-힣]{2,6}$/.test(text) && _optionalChain([block, 'access', _39 => _39.style, 'optionalAccess', _40 => _40.fontSize])) {
2678
+ if (/^[가-힣]{2,6}$/.test(text) && _optionalChain([block, 'access', _51 => _51.style, 'optionalAccess', _52 => _52.fontSize])) {
2571
2679
  const prev = blocks[i - 1];
2572
2680
  const next = blocks[i + 1];
2573
2681
  const prevIsStructural = !prev || prev.type === "table" || prev.type === "heading" || prev.type === "separator";
@@ -2822,7 +2930,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings) {
2822
2930
  const bottomEntries = [];
2823
2931
  for (let bi = 0; bi < blocks.length; bi++) {
2824
2932
  const b = blocks[bi];
2825
- if (!b.bbox || !b.pageNumber || !_optionalChain([b, 'access', _41 => _41.text, 'optionalAccess', _42 => _42.trim, 'call', _43 => _43()])) continue;
2933
+ if (!b.bbox || !b.pageNumber || !_optionalChain([b, 'access', _53 => _53.text, 'optionalAccess', _54 => _54.trim, 'call', _55 => _55()])) continue;
2826
2934
  const ph = pageHeights.get(b.bbox.page) || pageHeights.get(b.pageNumber);
2827
2935
  if (!ph) continue;
2828
2936
  const blockTop = ph - (b.bbox.y + b.bbox.height);
@@ -2845,7 +2953,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings) {
2845
2953
  }
2846
2954
  const repeatedPatterns = /* @__PURE__ */ new Set();
2847
2955
  for (const [p, count] of patternCount) {
2848
- if (count >= MIN_REPEAT && (_nullishCoalesce(_optionalChain([patternPages, 'access', _44 => _44.get, 'call', _45 => _45(p), 'optionalAccess', _46 => _46.size]), () => ( 0))) >= MIN_REPEAT) {
2956
+ if (count >= MIN_REPEAT && (_nullishCoalesce(_optionalChain([patternPages, 'access', _56 => _56.get, 'call', _57 => _57(p), 'optionalAccess', _58 => _58.size]), () => ( 0))) >= MIN_REPEAT) {
2849
2957
  repeatedPatterns.add(p);
2850
2958
  }
2851
2959
  }
@@ -2865,7 +2973,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings) {
2865
2973
  if (bi === e.blockIdx) continue;
2866
2974
  const o = blocks[bi];
2867
2975
  if (!o.bbox || o.bbox.page !== cb.page) continue;
2868
- const oNorm = _optionalChain([o, 'access', _47 => _47.text, 'optionalAccess', _48 => _48.trim, 'call', _49 => _49(), 'access', _50 => _50.replace, 'call', _51 => _51(/\d+/g, "#")]);
2976
+ const oNorm = _optionalChain([o, 'access', _59 => _59.text, 'optionalAccess', _60 => _60.trim, 'call', _61 => _61(), 'access', _62 => _62.replace, 'call', _63 => _63(/\d+/g, "#")]);
2869
2977
  if (oNorm && repeatedPatterns.has(oNorm)) continue;
2870
2978
  const overlap2 = Math.min(cb.y + cb.height, o.bbox.y + o.bbox.height) - Math.max(cb.y, o.bbox.y);
2871
2979
  if (overlap2 >= cb.height * 0.5) {
@@ -2908,7 +3016,7 @@ function recordCellLines(cell, items) {
2908
3016
  function markImageCell(cell) {
2909
3017
  IMAGE_CELLS.add(cell);
2910
3018
  }
2911
- var emptyCell = (cell) => !cell || !_optionalChain([cell, 'access', _52 => _52.text, 'optionalAccess', _53 => _53.trim, 'call', _54 => _54()]) && !_optionalChain([cell, 'access', _55 => _55.blocks, 'optionalAccess', _56 => _56.length]) && !IMAGE_CELLS.has(cell);
3019
+ var emptyCell = (cell) => !cell || !_optionalChain([cell, 'access', _64 => _64.text, 'optionalAccess', _65 => _65.trim, 'call', _66 => _66()]) && !_optionalChain([cell, 'access', _67 => _67.blocks, 'optionalAccess', _68 => _68.length]) && !IMAGE_CELLS.has(cell);
2912
3020
  function trimTable(table) {
2913
3021
  let cols = table.cols;
2914
3022
  while (cols > 0 && table.cells.every((row) => emptyCell(row[cols - 1]))) cols--;
@@ -2924,7 +3032,7 @@ function trimTable(table) {
2924
3032
  function trimTrailingEmptyTableCols(blocks) {
2925
3033
  for (const b of blocks) {
2926
3034
  if (b.type !== "table" || !b.table) continue;
2927
- for (const row of b.table.cells) for (const cell of row) if (_optionalChain([cell, 'access', _57 => _57.blocks, 'optionalAccess', _58 => _58.length])) trimTrailingEmptyTableCols(cell.blocks);
3035
+ for (const row of b.table.cells) for (const cell of row) if (_optionalChain([cell, 'access', _69 => _69.blocks, 'optionalAccess', _70 => _70.length])) trimTrailingEmptyTableCols(cell.blocks);
2928
3036
  trimTable(b.table);
2929
3037
  }
2930
3038
  }
@@ -2983,12 +3091,12 @@ function isTwoColumnProse(r) {
2983
3091
  if (t.rows < 8) return false;
2984
3092
  const dense = [];
2985
3093
  for (let c = 0; c < t.cols; c++) {
2986
- const filled = t.cells.filter((row) => _optionalChain([row, 'access', _59 => _59[c], 'optionalAccess', _60 => _60.text, 'access', _61 => _61.trim, 'call', _62 => _62()])).length;
3094
+ const filled = t.cells.filter((row) => _optionalChain([row, 'access', _71 => _71[c], 'optionalAccess', _72 => _72.text, 'access', _73 => _73.trim, 'call', _74 => _74()])).length;
2987
3095
  if (filled / t.rows >= 0.3) dense.push(c);
2988
3096
  }
2989
3097
  if (dense.length !== 2) return false;
2990
3098
  for (const c of dense) {
2991
- const lens = t.cells.map((row) => _nullishCoalesce(_optionalChain([row, 'access', _63 => _63[c], 'optionalAccess', _64 => _64.text, 'access', _65 => _65.replace, 'call', _66 => _66(/\s+/g, ""), 'access', _67 => _67.length]), () => ( 0))).filter((n) => n > 0);
3099
+ const lens = t.cells.map((row) => _nullishCoalesce(_optionalChain([row, 'access', _75 => _75[c], 'optionalAccess', _76 => _76.text, 'access', _77 => _77.replace, 'call', _78 => _78(/\s+/g, ""), 'access', _79 => _79.length]), () => ( 0))).filter((n) => n > 0);
2992
3100
  const avg = lens.reduce((s, v) => s + v, 0) / (lens.length || 1);
2993
3101
  if (avg < 12) return false;
2994
3102
  }
@@ -3463,7 +3571,7 @@ function buildClusterTable(rows, columns, pageNum) {
3463
3571
  const nonEmptyCols = cells[r].filter((c) => c.text.trim()).length;
3464
3572
  if (nonEmptyCols !== 1) continue;
3465
3573
  if (cells[r][0].text.trim() !== "") continue;
3466
- const contentText = _optionalChain([cells, 'access', _68 => _68[r], 'access', _69 => _69.find, 'call', _70 => _70((c) => c.text.trim()), 'optionalAccess', _71 => _71.text, 'access', _72 => _72.trim, 'call', _73 => _73()]) || "";
3574
+ const contentText = _optionalChain([cells, 'access', _80 => _80[r], 'access', _81 => _81.find, 'call', _82 => _82((c) => c.text.trim()), 'optionalAccess', _83 => _83.text, 'access', _84 => _84.trim, 'call', _85 => _85()]) || "";
3467
3575
  if (/^[○●▶\-·]/.test(contentText)) continue;
3468
3576
  for (let pr = r - 1; pr >= 0; pr--) {
3469
3577
  if (cells[pr].some((c) => c.text.trim())) {
@@ -3852,14 +3960,14 @@ function isProseSpread(items) {
3852
3960
  for (let i = 1; i < sorted.length; i++) {
3853
3961
  gaps.push(sorted[i].x - (sorted[i - 1].x + sorted[i - 1].w));
3854
3962
  }
3855
- const maxGap = _chunkVGU4FLLDcjs.safeMax.call(void 0, gaps);
3963
+ const maxGap = _chunkUUNEKQUUcjs.safeMax.call(void 0, gaps);
3856
3964
  const avgLen = items.reduce((s, i) => s + i.text.length, 0) / items.length;
3857
3965
  return maxGap < 40 && avgLen < 5;
3858
3966
  }
3859
3967
  function detectColumns(yLines) {
3860
3968
  const allItems = yLines.flat();
3861
3969
  if (allItems.length === 0) return null;
3862
- const pageWidth = _chunkVGU4FLLDcjs.safeMax.call(void 0, allItems.map((i) => i.x + i.w)) - _chunkVGU4FLLDcjs.safeMin.call(void 0, allItems.map((i) => i.x));
3970
+ const pageWidth = _chunkUUNEKQUUcjs.safeMax.call(void 0, allItems.map((i) => i.x + i.w)) - _chunkUUNEKQUUcjs.safeMin.call(void 0, allItems.map((i) => i.x));
3863
3971
  if (pageWidth < 100) return null;
3864
3972
  let bigoLineIdx = -1;
3865
3973
  for (let i = 0; i < yLines.length; i++) {
@@ -4187,7 +4295,7 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
4187
4295
  for (const line of streamLines(items)) lex.addLine(mergeLineSimple(line));
4188
4296
  const extracted = extractLines(opList.fnArray, opList.argsArray);
4189
4297
  let { horizontals, verticals } = extracted;
4190
- const prevPage = _optionalChain([carry, 'optionalAccess', _74 => _74.page]) === pageNum - 1 ? carry.clip : void 0;
4298
+ const prevPage = _optionalChain([carry, 'optionalAccess', _86 => _86.page]) === pageNum - 1 ? carry.clip : void 0;
4191
4299
  const clipResult = detectTables ? buildClipCellGrids(extracted.clipRects, horizontals, verticals, pageWidth, pageHeight, items.map((it) => ({ x: it.x + it.w / 2, y: it.y + it.h / 2 })), extracted.fillRects, prevPage) : { grids: [], containers: [], page: void 0 };
4192
4300
  if (carry) {
4193
4301
  carry.page = pageNum;
@@ -4422,8 +4530,21 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals, i
4422
4530
  let finalGrid = irGrid;
4423
4531
  let finalRows = numRows;
4424
4532
  let rebuiltUsed = false;
4425
- if (!grid.cells && numRows <= 2 && numCols >= 3 && !nestedAttached) {
4426
- const rebuilt = normalizeUndersegmentedTable(irGrid, grid.colXs, textItems);
4533
+ let unitLine = [];
4534
+ let unitText = "";
4535
+ if (!grid.cells && numRows >= 3 && numRows <= 5 && numCols >= 3) {
4536
+ const nearby = items.filter((item) => item.y >= grid.bbox.y2 && item.y - grid.bbox.y2 <= 18 && item.x >= grid.bbox.x1 - 3 && item.x + item.w <= grid.bbox.x2 + 3);
4537
+ for (const y of [...new Set(nearby.map((item) => Math.round(item.y)))].sort((a, b) => a - b)) {
4538
+ const line = nearby.filter((item) => Math.abs(item.y - y) <= 1).sort((a, b) => a.x - b.x);
4539
+ const text = line.map((item) => item.text).join("");
4540
+ if (!/^\s*\(\s*단위\s*[::]/.test(text)) continue;
4541
+ unitLine = line;
4542
+ unitText = text;
4543
+ break;
4544
+ }
4545
+ }
4546
+ if (!grid.cells && numRows <= 5 && numCols >= 3 && !nestedAttached && (numRows <= 2 || unitLine.length > 0)) {
4547
+ const rebuilt = normalizeUndersegmentedTable(irGrid, grid.colXs, textItems, grid.rowYs);
4427
4548
  if (rebuilt) {
4428
4549
  rebuiltUsed = true;
4429
4550
  finalGrid = rebuilt.map((row) => row.map((rawText) => ({ text: cleanCellText(rawText), colSpan: 1, rowSpan: 1 })));
@@ -4435,6 +4556,11 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals, i
4435
4556
  if (!assignedItems.has(textItems[ti])) usedItems.delete(tableItems[ti]);
4436
4557
  }
4437
4558
  }
4559
+ if (unitLine.length > 0 && rebuiltUsed && !/^\s*\(\s*단위\s*[::]/.test(_nullishCoalesce(_optionalChain([finalGrid, 'access', _87 => _87[0], 'optionalAccess', _88 => _88[0], 'optionalAccess', _89 => _89.text]), () => ( "")))) {
4560
+ finalGrid.unshift(Array.from({ length: numCols }, (_, c) => ({ text: c === 0 ? cleanCellText(unitText) : "", colSpan: c === 0 ? numCols : 1, rowSpan: 1 })));
4561
+ finalRows++;
4562
+ for (const item of unitLine) usedItems.add(item);
4563
+ }
4438
4564
  const irTable = {
4439
4565
  rows: finalRows,
4440
4566
  cols: numCols,
@@ -4517,7 +4643,7 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals, i
4517
4643
  if (gutterX !== null) {
4518
4644
  const gx = gutterX;
4519
4645
  const allY = remaining.map((i) => i.y);
4520
- const pageH = _chunkVGU4FLLDcjs.safeMax.call(void 0, allY) - _chunkVGU4FLLDcjs.safeMin.call(void 0, allY);
4646
+ const pageH = _chunkUUNEKQUUcjs.safeMax.call(void 0, allY) - _chunkUUNEKQUUcjs.safeMin.call(void 0, allY);
4521
4647
  const gapThreshold = Math.max(15, pageH * 0.03);
4522
4648
  const sides = [
4523
4649
  remaining.filter((i) => i.x + i.w <= gx),
@@ -4537,7 +4663,7 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals, i
4537
4663
  finalTextBlocks = detectListBlocks(textBlocks);
4538
4664
  } else {
4539
4665
  const allY = remaining.map((i) => i.y);
4540
- const pageH = _chunkVGU4FLLDcjs.safeMax.call(void 0, allY) - _chunkVGU4FLLDcjs.safeMin.call(void 0, allY);
4666
+ const pageH = _chunkUUNEKQUUcjs.safeMax.call(void 0, allY) - _chunkUUNEKQUUcjs.safeMin.call(void 0, allY);
4541
4667
  const groups = xyCutOrder(remaining, Math.max(15, pageH * 0.03));
4542
4668
  const textBlocks = [];
4543
4669
  for (const group of groups) {
@@ -4671,7 +4797,7 @@ function pushLineParagraphs(out, yLines, pageNum, lex) {
4671
4797
  const lines = yLines.map((items) => ({ items, text: mergeLineSimple(items) })).filter((l) => l.text.trim());
4672
4798
  const geo = lines.map((l) => {
4673
4799
  const b = computeBBox(l.items, pageNum);
4674
- return { text: l.text, left: b.x, right: b.x + b.width, y: l.items.reduce((s, i) => s + i.y, 0) / l.items.length, fontSize: _nullishCoalesce(_optionalChain([dominantStyle, 'call', _75 => _75(l.items), 'optionalAccess', _76 => _76.fontSize]), () => ( 0)) };
4800
+ return { text: l.text, left: b.x, right: b.x + b.width, y: l.items.reduce((s, i) => s + i.y, 0) / l.items.length, fontSize: _nullishCoalesce(_optionalChain([dominantStyle, 'call', _90 => _90(l.items), 'optionalAccess', _91 => _91.fontSize]), () => ( 0)) };
4675
4801
  });
4676
4802
  const joins = bodyLineJoins(geo, lex);
4677
4803
  for (let i = 0; i < lines.length; ) {
@@ -4687,6 +4813,43 @@ function pushLineParagraphs(out, yLines, pageNum, lex) {
4687
4813
  i++;
4688
4814
  }
4689
4815
  }
4816
+ function columnTextToBlocks(text, pageNum, bbox, style) {
4817
+ const lines = text.split("\n");
4818
+ const blocks = [];
4819
+ const prose = [];
4820
+ const flushProse = () => {
4821
+ const content = prose.join("\n").trim();
4822
+ if (content) blocks.push({ type: "paragraph", text: content, pageNumber: pageNum, bbox, style });
4823
+ prose.length = 0;
4824
+ };
4825
+ const cells = (line) => line.trim().slice(1, -1).split(/(?<!\\)\|/).map((c) => c.trim().replace(/\\\|/g, "|"));
4826
+ const tableLine = (line) => /^\|.*\|\s*$/.test(line.trim());
4827
+ for (let i = 0; i < lines.length; ) {
4828
+ if (tableLine(lines[i]) && i + 2 < lines.length && tableLine(lines[i + 1]) && cells(lines[i + 1]).every((c) => /^:?-{3,}:?$/.test(c))) {
4829
+ let end = i + 2;
4830
+ while (end < lines.length && tableLine(lines[end])) end++;
4831
+ const rows = [cells(lines[i]), ...lines.slice(i + 2, end).map(cells)];
4832
+ const cols = rows[0].length;
4833
+ const values = rows.slice(1).flat().filter(Boolean);
4834
+ const numeric = values.filter((value) => value.length <= 24 && /\d/.test(value)).length;
4835
+ if (cols >= 3 && rows.length >= 3 && rows.every((row) => row.length === cols) && rows[0].every((value) => value.length <= 80) && numeric >= 3 && numeric / values.length >= 0.25) {
4836
+ flushProse();
4837
+ blocks.push({ type: "table", pageNumber: pageNum, bbox, table: {
4838
+ rows: rows.length,
4839
+ cols,
4840
+ hasHeader: true,
4841
+ cells: rows.map((row) => row.map((value) => ({ text: value, rowSpan: 1, colSpan: 1 })))
4842
+ } });
4843
+ i = end;
4844
+ continue;
4845
+ }
4846
+ }
4847
+ prose.push(lines[i]);
4848
+ i++;
4849
+ }
4850
+ flushProse();
4851
+ return blocks;
4852
+ }
4690
4853
  function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTables = true, lex) {
4691
4854
  if (items.length === 0) return [];
4692
4855
  const blocks = [];
@@ -4729,10 +4892,10 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
4729
4892
  if (columns && columns.length >= 3) {
4730
4893
  const tableText = extractWithColumns(allYLines, columns);
4731
4894
  const bbox = computeBBox(items, pageNum);
4732
- blocks.push({ type: "paragraph", text: tableText, pageNumber: pageNum, bbox, style: dominantStyle(items) });
4895
+ blocks.push(...columnTextToBlocks(tableText, pageNum, bbox, dominantStyle(items)));
4733
4896
  } else {
4734
4897
  const allY = items.map((i) => i.y);
4735
- const pageHeight = _chunkVGU4FLLDcjs.safeMax.call(void 0, allY) - _chunkVGU4FLLDcjs.safeMin.call(void 0, allY);
4898
+ const pageHeight = _chunkUUNEKQUUcjs.safeMax.call(void 0, allY) - _chunkUUNEKQUUcjs.safeMin.call(void 0, allY);
4736
4899
  const gapThreshold = Math.max(15, pageHeight * 0.03);
4737
4900
  const orderedGroups = proseCutX !== null ? splitTwoColumnProse(items, proseCutX) : xyCutOrder(items, gapThreshold);
4738
4901
  for (const group of orderedGroups) {
@@ -4742,7 +4905,7 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
4742
4905
  if (groupColumns && groupColumns.length >= 3) {
4743
4906
  const tableText = extractWithColumns(yLines, groupColumns);
4744
4907
  const bbox = computeBBox(group, pageNum);
4745
- blocks.push({ type: "paragraph", text: tableText, pageNumber: pageNum, bbox, style: dominantStyle(group) });
4908
+ blocks.push(...columnTextToBlocks(tableText, pageNum, bbox, dominantStyle(group)));
4746
4909
  } else {
4747
4910
  pushLineParagraphs(blocks, yLines, pageNum, lex);
4748
4911
  }
@@ -4775,5 +4938,6 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
4775
4938
 
4776
4939
 
4777
4940
 
4778
- exports.extractImageRegions = extractImageRegions; exports.filterHiddenText = filterHiddenText; exports.collapseEvenSpacing = collapseEvenSpacing; exports.normalizeItems = normalizeItems; exports.WrapLexicon = WrapLexicon; exports.wrapJoiner = wrapJoiner; exports.joinPageBreakWraps = joinPageBreakWraps; exports.computeMedianFontSizeFromFreq = computeMedianFontSizeFromFreq; exports.detectHeadings = detectHeadings; exports.detectMarkerHeadings = detectMarkerHeadings; exports.detectTableCaptions = detectTableCaptions; exports.detectKoreanListBlocks = detectKoreanListBlocks; exports.removeHeaderFooterBlocks = removeHeaderFooterBlocks; exports.CLIP_TABLES = CLIP_TABLES; exports.TABLE_COLXS = TABLE_COLXS; exports.EMPTY_PARTS = EMPTY_PARTS; exports.IMAGE_CELLS = IMAGE_CELLS; exports.FILLER_CELLS = FILLER_CELLS; exports.CONT_PARTS = CONT_PARTS; exports.CELL_LINES = CELL_LINES; exports.trimTrailingEmptyTableCols = trimTrailingEmptyTableCols; exports.extractPageBlocksWithLines = extractPageBlocksWithLines;
4779
- //# sourceMappingURL=chunk-VSI5SRP2.cjs.map
4941
+
4942
+ exports.extractImageRegions = extractImageRegions; exports.filterHiddenText = filterHiddenText; exports.collapseEvenSpacing = collapseEvenSpacing; exports.normalizeItems = normalizeItems; exports.WrapLexicon = WrapLexicon; exports.wrapJoiner = wrapJoiner; exports.joinPageBreakWraps = joinPageBreakWraps; exports.computeMedianFontSizeFromFreq = computeMedianFontSizeFromFreq; exports.detectHeadings = detectHeadings; exports.detectTypographyHeadings = detectTypographyHeadings; exports.detectMarkerHeadings = detectMarkerHeadings; exports.detectTableCaptions = detectTableCaptions; exports.detectKoreanListBlocks = detectKoreanListBlocks; exports.removeHeaderFooterBlocks = removeHeaderFooterBlocks; exports.CLIP_TABLES = CLIP_TABLES; exports.TABLE_COLXS = TABLE_COLXS; exports.EMPTY_PARTS = EMPTY_PARTS; exports.IMAGE_CELLS = IMAGE_CELLS; exports.FILLER_CELLS = FILLER_CELLS; exports.CONT_PARTS = CONT_PARTS; exports.CELL_LINES = CELL_LINES; exports.trimTrailingEmptyTableCols = trimTrailingEmptyTableCols; exports.extractPageBlocksWithLines = extractPageBlocksWithLines;
4943
+ //# sourceMappingURL=chunk-SRITXAMQ.cjs.map