kordoc 4.12.0 → 4.12.2

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 +26 -5
  2. package/dist/{-B3EUUBPV.js → -EZH6NKTE.js} +8 -8
  3. package/dist/{chunk-HGUNWAXK.js → chunk-2B7OIEJJ.js} +9 -5
  4. package/dist/chunk-2B7OIEJJ.js.map +1 -0
  5. package/dist/{chunk-QKFCGJJY.js → chunk-2HBYWA5X.js} +2 -2
  6. package/dist/{chunk-HFJWCAJ2.cjs → chunk-2LKYJ4G3.cjs} +6 -6
  7. package/dist/chunk-2LKYJ4G3.cjs.map +1 -0
  8. package/dist/{chunk-COGFPMEB.js → chunk-2LO525TL.js} +2 -2
  9. package/dist/{chunk-TROD36DK.cjs → chunk-2LPBIW2B.cjs} +3 -3
  10. package/dist/chunk-2LPBIW2B.cjs.map +1 -0
  11. package/dist/{chunk-BQSWSMRG.cjs → chunk-62IU4NV3.cjs} +2 -2
  12. package/dist/chunk-62IU4NV3.cjs.map +1 -0
  13. package/dist/{chunk-SMGSCP57.js → chunk-7XUXSDH5.js} +308 -53
  14. package/dist/chunk-7XUXSDH5.js.map +1 -0
  15. package/dist/{chunk-YASFVKDT.js → chunk-DBGEUDBY.js} +2 -2
  16. package/dist/chunk-DCZVOIEO.cjs.map +1 -1
  17. package/dist/{chunk-4PKNWBXJ.js → chunk-FBLMVHDK.js} +2 -2
  18. package/dist/{chunk-I2OETEEL.js → chunk-FVBR7SC3.js} +2 -2
  19. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  20. package/dist/{chunk-46UDI56N.js → chunk-IOJX4Q63.js} +3 -3
  21. package/dist/{chunk-BQE7AMFS.js → chunk-JCMBQC5N.js} +2 -2
  22. package/dist/{chunk-TF5DS74F.js → chunk-KX7IYCCZ.js} +3 -3
  23. package/dist/{chunk-PFUW4I4I.js → chunk-LD2K4K5V.js} +170 -18
  24. package/dist/chunk-LD2K4K5V.js.map +1 -0
  25. package/dist/{chunk-MJPRWCI5.js → chunk-MUYU4JI5.js} +2 -2
  26. package/dist/{chunk-SKGYPM6L.js → chunk-OEYECZGV.js} +308 -53
  27. package/dist/chunk-OEYECZGV.js.map +1 -0
  28. package/dist/{chunk-AT23GFSK.cjs → chunk-ONNAHSPV.cjs} +323 -68
  29. package/dist/chunk-ONNAHSPV.cjs.map +1 -0
  30. package/dist/{chunk-GHVXLV52.js → chunk-Q6ETEJFK.js} +9 -5
  31. package/dist/chunk-Q6ETEJFK.js.map +1 -0
  32. package/dist/{chunk-2IR3PEZU.js → chunk-QBCMFNHS.js} +2 -2
  33. package/dist/{chunk-DRLKMFDV.js → chunk-QM2RSJ2S.js} +3 -3
  34. package/dist/chunk-T7GRHAIW.cjs.map +1 -1
  35. package/dist/{chunk-TJYZY2O6.js → chunk-UL2MDA5C.js} +3 -3
  36. package/dist/{chunk-TYYJSOZS.cjs → chunk-V5BUPZ6I.cjs} +23 -19
  37. package/dist/chunk-V5BUPZ6I.cjs.map +1 -0
  38. package/dist/{chunk-7JQ2ITT2.js → chunk-XXDZ2KTW.js} +2 -2
  39. package/dist/chunks-TT7ZE5QQ.js +10 -0
  40. package/dist/cli.js +21 -21
  41. package/dist/cli.js.map +1 -1
  42. package/dist/{formula-WGKKR5OQ.js → formula-6RQX4NMJ.js} +4 -4
  43. package/dist/{formula-YMGXXRBQ.cjs → formula-NBEO6CFC.cjs} +9 -9
  44. package/dist/formula-NBEO6CFC.cjs.map +1 -0
  45. package/dist/{formula-G4CD5KQ6.js → formula-NW33S4TA.js} +3 -3
  46. package/dist/{image-ocr-MBWZK3ZT.js → image-ocr-CAVU2TNZ.js} +5 -5
  47. package/dist/{image-ocr-M4RP4INO.js → image-ocr-SO56VETS.js} +7 -7
  48. package/dist/{image-ocr-BE2HHMVN.cjs → image-ocr-V4KY373B.cjs} +11 -11
  49. package/dist/image-ocr-V4KY373B.cjs.map +1 -0
  50. package/dist/index.cjs +547 -395
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +5 -2
  53. package/dist/index.d.ts +5 -2
  54. package/dist/index.js +166 -14
  55. package/dist/index.js.map +1 -1
  56. package/dist/mcp.js +15 -15
  57. package/dist/{model-bundle-BIMP5DIH.js → model-bundle-EIJF34DR.js} +5 -5
  58. package/dist/{models-QPOEGHVA.js → models-6V4CPQXC.js} +5 -5
  59. package/dist/page-range-P7SDW6LR.cjs.map +1 -1
  60. package/dist/{parser-CMNHBVTL.js → parser-GIREMEPD.js} +307 -6
  61. package/dist/parser-GIREMEPD.js.map +1 -0
  62. package/dist/{parser-NR3XO4SM.js → parser-OBHNXEQM.js} +307 -6
  63. package/dist/parser-OBHNXEQM.js.map +1 -0
  64. package/dist/{parser-QJY5W47V.cjs → parser-OMT25WH2.cjs} +334 -33
  65. package/dist/parser-OMT25WH2.cjs.map +1 -0
  66. package/dist/pdf-ocr-IRXQ5GBM.js +13 -0
  67. package/dist/pdf-ocr-SL4GCOGS.js +16 -0
  68. package/dist/pdf-ocr-TFYVK4FI.cjs +14 -0
  69. package/dist/pdf-ocr-TFYVK4FI.cjs.map +1 -0
  70. package/dist/{profile-io-UZ43CLWX.js → profile-io-PZVMM66V.js} +3 -3
  71. package/dist/{rasterize-JC2JVVOF.js → rasterize-NRWP2C6L.js} +2 -2
  72. package/dist/render-V5ZPTZQ7.js +10 -0
  73. package/dist/seal-LVG2DGAB.js +10 -0
  74. package/dist/{setup-WDUVPFX3.js → setup-V55AJP6H.js} +3 -3
  75. package/dist/{watch-UI7OXIES.js → watch-7CQSMDDP.js} +9 -9
  76. package/package.json +1 -1
  77. package/dist/chunk-AT23GFSK.cjs.map +0 -1
  78. package/dist/chunk-BQSWSMRG.cjs.map +0 -1
  79. package/dist/chunk-GHVXLV52.js.map +0 -1
  80. package/dist/chunk-HFJWCAJ2.cjs.map +0 -1
  81. package/dist/chunk-HGUNWAXK.js.map +0 -1
  82. package/dist/chunk-PFUW4I4I.js.map +0 -1
  83. package/dist/chunk-SKGYPM6L.js.map +0 -1
  84. package/dist/chunk-SMGSCP57.js.map +0 -1
  85. package/dist/chunk-TROD36DK.cjs.map +0 -1
  86. package/dist/chunk-TYYJSOZS.cjs.map +0 -1
  87. package/dist/chunks-Q4GCPRRU.js +0 -10
  88. package/dist/formula-YMGXXRBQ.cjs.map +0 -1
  89. package/dist/image-ocr-BE2HHMVN.cjs.map +0 -1
  90. package/dist/parser-CMNHBVTL.js.map +0 -1
  91. package/dist/parser-NR3XO4SM.js.map +0 -1
  92. package/dist/parser-QJY5W47V.cjs.map +0 -1
  93. package/dist/pdf-ocr-DF3OTBKH.js +0 -13
  94. package/dist/pdf-ocr-R4DIKF4Q.js +0 -16
  95. package/dist/pdf-ocr-T3RHIZKY.cjs +0 -14
  96. package/dist/pdf-ocr-T3RHIZKY.cjs.map +0 -1
  97. package/dist/render-KSQ6UGCP.js +0 -10
  98. package/dist/seal-EOFFQ4JR.js +0 -10
  99. /package/dist/{-B3EUUBPV.js.map → -EZH6NKTE.js.map} +0 -0
  100. /package/dist/{chunk-QKFCGJJY.js.map → chunk-2HBYWA5X.js.map} +0 -0
  101. /package/dist/{chunk-COGFPMEB.js.map → chunk-2LO525TL.js.map} +0 -0
  102. /package/dist/{chunk-YASFVKDT.js.map → chunk-DBGEUDBY.js.map} +0 -0
  103. /package/dist/{chunk-4PKNWBXJ.js.map → chunk-FBLMVHDK.js.map} +0 -0
  104. /package/dist/{chunk-I2OETEEL.js.map → chunk-FVBR7SC3.js.map} +0 -0
  105. /package/dist/{chunk-46UDI56N.js.map → chunk-IOJX4Q63.js.map} +0 -0
  106. /package/dist/{chunk-BQE7AMFS.js.map → chunk-JCMBQC5N.js.map} +0 -0
  107. /package/dist/{chunk-TF5DS74F.js.map → chunk-KX7IYCCZ.js.map} +0 -0
  108. /package/dist/{chunk-MJPRWCI5.js.map → chunk-MUYU4JI5.js.map} +0 -0
  109. /package/dist/{chunk-2IR3PEZU.js.map → chunk-QBCMFNHS.js.map} +0 -0
  110. /package/dist/{chunk-DRLKMFDV.js.map → chunk-QM2RSJ2S.js.map} +0 -0
  111. /package/dist/{chunk-TJYZY2O6.js.map → chunk-UL2MDA5C.js.map} +0 -0
  112. /package/dist/{chunk-7JQ2ITT2.js.map → chunk-XXDZ2KTW.js.map} +0 -0
  113. /package/dist/{chunks-Q4GCPRRU.js.map → chunks-TT7ZE5QQ.js.map} +0 -0
  114. /package/dist/{formula-WGKKR5OQ.js.map → formula-6RQX4NMJ.js.map} +0 -0
  115. /package/dist/{formula-G4CD5KQ6.js.map → formula-NW33S4TA.js.map} +0 -0
  116. /package/dist/{image-ocr-MBWZK3ZT.js.map → image-ocr-CAVU2TNZ.js.map} +0 -0
  117. /package/dist/{image-ocr-M4RP4INO.js.map → image-ocr-SO56VETS.js.map} +0 -0
  118. /package/dist/{model-bundle-BIMP5DIH.js.map → model-bundle-EIJF34DR.js.map} +0 -0
  119. /package/dist/{models-QPOEGHVA.js.map → models-6V4CPQXC.js.map} +0 -0
  120. /package/dist/{pdf-ocr-DF3OTBKH.js.map → pdf-ocr-IRXQ5GBM.js.map} +0 -0
  121. /package/dist/{pdf-ocr-R4DIKF4Q.js.map → pdf-ocr-SL4GCOGS.js.map} +0 -0
  122. /package/dist/{profile-io-UZ43CLWX.js.map → profile-io-PZVMM66V.js.map} +0 -0
  123. /package/dist/{rasterize-JC2JVVOF.js.map → rasterize-NRWP2C6L.js.map} +0 -0
  124. /package/dist/{render-KSQ6UGCP.js.map → render-V5ZPTZQ7.js.map} +0 -0
  125. /package/dist/{seal-EOFFQ4JR.js.map → seal-LVG2DGAB.js.map} +0 -0
  126. /package/dist/{setup-WDUVPFX3.js.map → setup-V55AJP6H.js.map} +0 -0
  127. /package/dist/{watch-UI7OXIES.js.map → watch-7CQSMDDP.js.map} +0 -0
@@ -1,5 +1,5 @@
1
1
  // src/utils.ts
2
- var VERSION = true ? "4.12.0" : "0.0.0-dev";
2
+ var VERSION = true ? "4.12.2" : "0.0.0-dev";
3
3
  function toArrayBuffer(buf) {
4
4
  if (buf.byteOffset === 0 && buf.byteLength === buf.buffer.byteLength) {
5
5
  return buf.buffer;
@@ -121,4 +121,4 @@ export {
121
121
  safeMax,
122
122
  classifyError
123
123
  };
124
- //# sourceMappingURL=chunk-MJPRWCI5.js.map
124
+ //# sourceMappingURL=chunk-MUYU4JI5.js.map
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  safeMax,
9
9
  safeMin
10
- } from "./chunk-4PKNWBXJ.js";
10
+ } from "./chunk-FBLMVHDK.js";
11
11
 
12
12
  // src/pdf/image-regions.ts
13
13
  import { OPS } from "pdfjs-dist/legacy/build/pdf.mjs";
@@ -69,6 +69,8 @@ var MAX_LINE_WIDTH = 5;
69
69
  function extractLines(fnArray, argsArray) {
70
70
  const horizontals = [];
71
71
  const verticals = [];
72
+ const clipRects = [];
73
+ let pendingClip = false;
72
74
  let lineWidth = 1;
73
75
  let ctm = [1, 0, 0, 1, 0, 0];
74
76
  const ctmStack = [];
@@ -98,9 +100,12 @@ function extractLines(fnArray, argsArray) {
98
100
  }
99
101
  function flushPath(isStroke, fromFill = false) {
100
102
  if (!isStroke) {
103
+ if (pendingClip) captureClipRect(currentPath, clipRects);
104
+ pendingClip = false;
101
105
  currentPath = [];
102
106
  return;
103
107
  }
108
+ pendingClip = false;
104
109
  const effWidth = lineWidth * ctmScale();
105
110
  for (const seg of currentPath) {
106
111
  classifyAndAdd(seg, effWidth, horizontals, verticals, fromFill);
@@ -228,9 +233,29 @@ function extractLines(fnArray, argsArray) {
228
233
  case OPS2.endPath:
229
234
  flushPath(false);
230
235
  break;
236
+ case OPS2.clip:
237
+ case OPS2.eoClip:
238
+ pendingClip = true;
239
+ break;
231
240
  }
232
241
  }
233
- return { horizontals, verticals };
242
+ return { horizontals, verticals, clipRects };
243
+ }
244
+ var CLIP_MIN_W = 4;
245
+ var CLIP_MIN_H = 2;
246
+ function captureClipRect(path, out) {
247
+ if (path.length < 3 || path.length > 5) return;
248
+ let x1 = Infinity, y1 = Infinity, x2 = -Infinity, y2 = -Infinity;
249
+ for (const s of path) {
250
+ const dx = Math.abs(s.x2 - s.x1), dy = Math.abs(s.y2 - s.y1);
251
+ if (dx > ORIENTATION_TOL && dy > ORIENTATION_TOL) return;
252
+ x1 = Math.min(x1, s.x1, s.x2);
253
+ x2 = Math.max(x2, s.x1, s.x2);
254
+ y1 = Math.min(y1, s.y1, s.y2);
255
+ y2 = Math.max(y2, s.y1, s.y2);
256
+ }
257
+ if (x2 - x1 < CLIP_MIN_W || y2 - y1 < CLIP_MIN_H) return;
258
+ out.push({ x1, y1, x2, y2 });
234
259
  }
235
260
  function classifyAndAdd(seg, lineWidth, horizontals, verticals, fromFill = false) {
236
261
  const dx = Math.abs(seg.x2 - seg.x1);
@@ -443,9 +468,9 @@ function mergeParallelLines(lines, dir) {
443
468
  const prevEnd = dir === "h" ? prev.x2 : prev.y2;
444
469
  const currStart = dir === "h" ? curr.x1 : curr.y1;
445
470
  const currEnd = dir === "h" ? curr.x2 : curr.y2;
446
- const overlap = Math.min(prevEnd, currEnd) - Math.max(prevStart, currStart);
471
+ const overlap2 = Math.min(prevEnd, currEnd) - Math.max(prevStart, currStart);
447
472
  const minLen = Math.min(prevEnd - prevStart, currEnd - currStart);
448
- if (overlap > minLen * 0.3) {
473
+ if (overlap2 > minLen * 0.3) {
449
474
  if (dir === "h") {
450
475
  prev.x1 = Math.min(prev.x1, curr.x1);
451
476
  prev.x2 = Math.max(prev.x2, curr.x2);
@@ -934,6 +959,186 @@ function linesIntersect(a, b) {
934
959
  return v.x1 >= h.x1 - tol && v.x1 <= h.x2 + tol && h.y1 >= v.y1 - tol && h.y1 <= v.y2 + tol;
935
960
  }
936
961
 
962
+ // src/pdf/clip-cells.ts
963
+ var CLIP_EDGE_TOL = 1.5;
964
+ var CLIP_MIN_GROUP = 2;
965
+ var CLIP_MAX_PAGE_FRAC = 0.75;
966
+ var CLIP_MIN_W2 = 4;
967
+ var CLIP_MIN_H2 = 2;
968
+ var STROKE_NEAR = 2;
969
+ var STROKE_COVER = 0.5;
970
+ var CLIP_MIN_INVISIBLE = 0;
971
+ var overlap = (a1, a2, b1, b2) => Math.min(a2, b2) - Math.max(a1, b1);
972
+ function adjacent(a, b) {
973
+ if ((Math.abs(a.x2 - b.x1) <= CLIP_EDGE_TOL || Math.abs(b.x2 - a.x1) <= CLIP_EDGE_TOL) && overlap(a.y1, a.y2, b.y1, b.y2) > CLIP_EDGE_TOL) return true;
974
+ if ((Math.abs(a.y2 - b.y1) <= CLIP_EDGE_TOL || Math.abs(b.y2 - a.y1) <= CLIP_EDGE_TOL) && overlap(a.x1, a.x2, b.x1, b.x2) > CLIP_EDGE_TOL) return true;
975
+ return false;
976
+ }
977
+ function contains(a, b) {
978
+ return b.x1 >= a.x1 - CLIP_EDGE_TOL && b.x2 <= a.x2 + CLIP_EDGE_TOL && b.y1 >= a.y1 - CLIP_EDGE_TOL && b.y2 <= a.y2 + CLIP_EDGE_TOL && (b.x2 - b.x1 < a.x2 - a.x1 - CLIP_EDGE_TOL || b.y2 - b.y1 < a.y2 - a.y1 - CLIP_EDGE_TOL);
979
+ }
980
+ function clusterCoords(values) {
981
+ const sorted = [...values].sort((a, b) => a - b);
982
+ const out = [];
983
+ let run = [];
984
+ for (const v of sorted) {
985
+ if (run.length > 0 && v - run[run.length - 1] > CLIP_EDGE_TOL) {
986
+ out.push(run.reduce((s, x) => s + x, 0) / run.length);
987
+ run = [];
988
+ }
989
+ run.push(v);
990
+ }
991
+ if (run.length > 0) out.push(run.reduce((s, x) => s + x, 0) / run.length);
992
+ return out;
993
+ }
994
+ var nearestIndex = (coords, v) => {
995
+ let best = 0;
996
+ for (let i = 1; i < coords.length; i++) if (Math.abs(coords[i] - v) < Math.abs(coords[best] - v)) best = i;
997
+ return best;
998
+ };
999
+ function edgeStroked(lines, dir, pos, a1, a2) {
1000
+ const len = a2 - a1;
1001
+ if (len <= 0) return true;
1002
+ for (const l of lines) {
1003
+ if (dir === "h") {
1004
+ if (Math.abs(l.y1 - pos) <= STROKE_NEAR && overlap(l.x1, l.x2, a1, a2) >= len * STROKE_COVER) return true;
1005
+ } else if (Math.abs(l.x1 - pos) <= STROKE_NEAR && overlap(l.y1, l.y2, a1, a2) >= len * STROKE_COVER) {
1006
+ return true;
1007
+ }
1008
+ }
1009
+ return false;
1010
+ }
1011
+ function buildClipCellGrids(rects, strokedH, strokedV, pageWidth, pageHeight) {
1012
+ const pageArea = pageWidth * pageHeight;
1013
+ 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;
1014
+ const cells = [];
1015
+ for (const r of rects) {
1016
+ if (r.x2 - r.x1 < CLIP_MIN_W2 || r.y2 - r.y1 < CLIP_MIN_H2) continue;
1017
+ if (pageArea > 0 && (r.x2 - r.x1) * (r.y2 - r.y1) >= pageArea * CLIP_MAX_PAGE_FRAC) continue;
1018
+ if (!cells.some((c) => sameRect(c, r))) cells.push(r);
1019
+ }
1020
+ if (cells.length < 1) return { grids: [], containers: [] };
1021
+ const parent = new Array(cells.length).fill(-1);
1022
+ for (let i = 0; i < cells.length; i++) {
1023
+ for (let j = 0; j < cells.length; j++) {
1024
+ if (i === j || !contains(cells[j], cells[i])) continue;
1025
+ const cur = parent[i];
1026
+ if (cur < 0 || contains(cells[cur], cells[j])) parent[i] = j;
1027
+ }
1028
+ }
1029
+ const isContainer = new Array(cells.length).fill(false);
1030
+ for (const p of parent) if (p >= 0) isContainer[p] = true;
1031
+ const root = cells.map((_, i) => i);
1032
+ const find = (i) => {
1033
+ while (root[i] !== i) {
1034
+ root[i] = root[root[i]];
1035
+ i = root[i];
1036
+ }
1037
+ return i;
1038
+ };
1039
+ for (let i = 0; i < cells.length; i++) {
1040
+ for (let j = i + 1; j < cells.length; j++) {
1041
+ if (parent[i] !== parent[j]) continue;
1042
+ if (adjacent(cells[i], cells[j])) {
1043
+ const ra = find(i), rb = find(j);
1044
+ if (ra !== rb) root[ra] = rb;
1045
+ }
1046
+ }
1047
+ }
1048
+ const groups = /* @__PURE__ */ new Map();
1049
+ for (let i = 0; i < cells.length; i++) {
1050
+ const r = find(i);
1051
+ const g = groups.get(r);
1052
+ if (g) g.push(i);
1053
+ else groups.set(r, [i]);
1054
+ }
1055
+ const containers = cells.filter((_, i) => isContainer[i]);
1056
+ const groupSize = (i) => groups.get(find(i))?.length ?? 0;
1057
+ const isGridMember = (i) => groupSize(i) >= CLIP_MIN_GROUP;
1058
+ 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);
1059
+ const loneFrame = (i) => isContainer[i] && !isGridMember(i) && framed(cells[i]);
1060
+ const parentAttachable = (i) => parent[i] >= 0 && (isGridMember(parent[i]) || loneFrame(parent[i]));
1061
+ const onlyChild = (i) => parent[i] >= 0 && parent.filter((p) => p === parent[i]).length === 1;
1062
+ const grids = [];
1063
+ for (const idxs of groups.values()) {
1064
+ const first = idxs[0];
1065
+ const parentRect = parentAttachable(first) ? cells[parent[first]] : void 0;
1066
+ if (idxs.length < CLIP_MIN_GROUP) {
1067
+ if (!loneFrame(first) && !((parentRect || onlyChild(first)) && framed(cells[first]))) continue;
1068
+ const r = cells[first];
1069
+ grids.push({
1070
+ rowYs: [r.y2, r.y1],
1071
+ colXs: [r.x1, r.x2],
1072
+ bbox: { x1: r.x1, y1: r.y1, x2: r.x2, y2: r.y2 },
1073
+ vertexRadius: 1,
1074
+ cells: [{ row: 0, col: 0, rowSpan: 1, colSpan: 1, bbox: { x1: r.x1, y1: r.y1, x2: r.x2, y2: r.y2 } }],
1075
+ ...parentRect ? { clipParent: parentRect } : {}
1076
+ });
1077
+ continue;
1078
+ }
1079
+ const members = idxs.map((i) => cells[i]);
1080
+ let edges = 0, invisible = 0;
1081
+ for (const r of members) {
1082
+ edges += 4;
1083
+ if (!edgeStroked(strokedH, "h", r.y1, r.x1, r.x2)) invisible++;
1084
+ if (!edgeStroked(strokedH, "h", r.y2, r.x1, r.x2)) invisible++;
1085
+ if (!edgeStroked(strokedV, "v", r.x1, r.y1, r.y2)) invisible++;
1086
+ if (!edgeStroked(strokedV, "v", r.x2, r.y1, r.y2)) invisible++;
1087
+ }
1088
+ if (invisible / edges < CLIP_MIN_INVISIBLE) continue;
1089
+ const colXs = clusterCoords(members.flatMap((r) => [r.x1, r.x2]));
1090
+ const rowYs = clusterCoords(members.flatMap((r) => [r.y1, r.y2])).reverse();
1091
+ const numRows = rowYs.length - 1, numCols = colXs.length - 1;
1092
+ if (numRows < 1 || numCols < 1) continue;
1093
+ const occupied = Array.from({ length: numRows }, () => new Array(numCols).fill(false));
1094
+ const out = [];
1095
+ for (const r of members) {
1096
+ const c0 = nearestIndex(colXs, r.x1), c1 = nearestIndex(colXs, r.x2);
1097
+ const r0 = nearestIndex(rowYs, r.y2), r1 = nearestIndex(rowYs, r.y1);
1098
+ if (c1 <= c0 || r1 <= r0) continue;
1099
+ let clash = false;
1100
+ for (let rr = r0; rr < r1 && !clash; rr++) for (let cc = c0; cc < c1; cc++) if (occupied[rr][cc]) {
1101
+ clash = true;
1102
+ break;
1103
+ }
1104
+ if (clash) continue;
1105
+ for (let rr = r0; rr < r1; rr++) for (let cc = c0; cc < c1; cc++) occupied[rr][cc] = true;
1106
+ out.push({ row: r0, col: c0, rowSpan: r1 - r0, colSpan: c1 - c0, bbox: { x1: r.x1, y1: r.y1, x2: r.x2, y2: r.y2 } });
1107
+ }
1108
+ for (let rr = 0; rr < numRows; rr++) {
1109
+ for (let cc = 0; cc < numCols; cc++) {
1110
+ if (occupied[rr][cc]) continue;
1111
+ out.push({ row: rr, col: cc, rowSpan: 1, colSpan: 1, bbox: { x1: colXs[cc], y1: rowYs[rr + 1], x2: colXs[cc + 1], y2: rowYs[rr] } });
1112
+ }
1113
+ }
1114
+ grids.push({
1115
+ rowYs,
1116
+ colXs,
1117
+ bbox: { x1: colXs[0], y1: rowYs[numRows], x2: colXs[numCols], y2: rowYs[0] },
1118
+ vertexRadius: 1,
1119
+ cells: out,
1120
+ ...parentRect ? { clipParent: parentRect } : {}
1121
+ });
1122
+ }
1123
+ return { grids, containers };
1124
+ }
1125
+ function dropGridsInside(lineGrids, clipGrids, containers = []) {
1126
+ if (clipGrids.length === 0 && containers.length === 0) return lineGrids;
1127
+ const area = (b) => Math.max(0, b.x2 - b.x1) * Math.max(0, b.y2 - b.y1);
1128
+ const overlapsHalf = (g, b) => {
1129
+ const ix = Math.min(g.x2, b.x2) - Math.max(g.x1, b.x1);
1130
+ const iy = Math.min(g.y2, b.y2) - Math.max(g.y1, b.y1);
1131
+ if (ix <= 0 || iy <= 0) return false;
1132
+ const ga = area(g);
1133
+ return ga > 0 && ix * iy / ga >= 0.5;
1134
+ };
1135
+ return lineGrids.filter((g) => {
1136
+ if (clipGrids.some((c) => overlapsHalf(g.bbox, c.bbox))) return false;
1137
+ if (containers.some((c) => overlapsHalf(g.bbox, c))) return false;
1138
+ return true;
1139
+ });
1140
+ }
1141
+
937
1142
  // src/pdf/cell-extract.ts
938
1143
  function extractCells(grid, horizontals, verticals) {
939
1144
  const { rowYs, colXs } = grid;
@@ -1012,8 +1217,8 @@ function hasVerticalLine(verticals, x, topY, botY, vertexRadius) {
1012
1217
  if (cellH < 0.1) continue;
1013
1218
  const overlapTop = Math.min(v.y2, topY);
1014
1219
  const overlapBot = Math.max(v.y1, botY);
1015
- const overlap = overlapTop - overlapBot;
1016
- if (overlap >= cellH * 0.75) return true;
1220
+ const overlap2 = overlapTop - overlapBot;
1221
+ if (overlap2 >= cellH * 0.75) return true;
1017
1222
  }
1018
1223
  }
1019
1224
  return false;
@@ -1026,8 +1231,8 @@ function hasHorizontalLine(horizontals, y, leftX, rightX, vertexRadius) {
1026
1231
  if (cellW < 0.1) continue;
1027
1232
  const overlapLeft = Math.max(h.x1, leftX);
1028
1233
  const overlapRight = Math.min(h.x2, rightX);
1029
- const overlap = overlapRight - overlapLeft;
1030
- if (overlap >= cellW * 0.75) return true;
1234
+ const overlap2 = overlapRight - overlapLeft;
1235
+ if (overlap2 >= cellW * 0.75) return true;
1031
1236
  }
1032
1237
  }
1033
1238
  return false;
@@ -1134,9 +1339,9 @@ function mergeSuperscriptRows(lines) {
1134
1339
  const curr = lines[i];
1135
1340
  const a = band(prev);
1136
1341
  const b = band(curr);
1137
- const overlap = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
1138
- const prevIsFrag = isFrag(prev) && a.height <= b.height * 0.8 && overlap >= a.height * 0.5;
1139
- const currIsFrag = isFrag(curr) && b.height <= a.height * 0.8 && overlap >= b.height * 0.5;
1342
+ const overlap2 = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
1343
+ const prevIsFrag = isFrag(prev) && a.height <= b.height * 0.8 && overlap2 >= a.height * 0.5;
1344
+ const currIsFrag = isFrag(curr) && b.height <= a.height * 0.8 && overlap2 >= b.height * 0.5;
1140
1345
  if (prevIsFrag || currIsFrag) {
1141
1346
  result[result.length - 1] = [...prev, ...curr];
1142
1347
  } else {
@@ -1355,14 +1560,17 @@ function filterHiddenText(items, pageWidth, pageHeight) {
1355
1560
  function collapseEvenSpacing(text) {
1356
1561
  const tokens = text.split(" ");
1357
1562
  const singleCharCount = tokens.filter((t) => t.length === 1).length;
1358
- if (tokens.length >= 3 && singleCharCount / tokens.length >= 0.7) {
1563
+ if (tokens.length >= 3 && singleCharCount / tokens.length >= 0.7 && !isDateUnitBlank(tokens)) {
1359
1564
  return tokens.join("");
1360
1565
  }
1361
1566
  return text.replace(
1362
1567
  /(?<![가-힣])[가-힣](?: [가-힣\d]){2,}(?![가-힣])/g,
1363
- (match) => match.replace(/ /g, "")
1568
+ (match) => isDateUnitBlank(match.split(" ")) ? match : match.replace(/ /g, "")
1364
1569
  );
1365
1570
  }
1571
+ function isDateUnitBlank(tokens) {
1572
+ return tokens.every((t) => t.length !== 1 || !/[가-힣]/.test(t) || /[년월일시분초]/.test(t));
1573
+ }
1366
1574
  function computeBBox(items, pageNum) {
1367
1575
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
1368
1576
  for (const i of items) {
@@ -1503,9 +1711,9 @@ function mergeSuperscriptLines(lines) {
1503
1711
  const curr = lines[i];
1504
1712
  const a = band(prev);
1505
1713
  const b = band(curr);
1506
- const overlap = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
1507
- const prevIsFrag = isFrag(prev) && a.height <= b.height * 0.8 && overlap >= a.height * 0.5;
1508
- const currIsFrag = isFrag(curr) && b.height <= a.height * 0.8 && overlap >= b.height * 0.5;
1714
+ const overlap2 = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
1715
+ const prevIsFrag = isFrag(prev) && a.height <= b.height * 0.8 && overlap2 >= a.height * 0.5;
1716
+ const currIsFrag = isFrag(curr) && b.height <= a.height * 0.8 && overlap2 >= b.height * 0.5;
1509
1717
  if (prevIsFrag || currIsFrag) {
1510
1718
  result[result.length - 1] = [...prev, ...curr];
1511
1719
  } else {
@@ -1654,8 +1862,8 @@ function detectTableCaptions(blocks) {
1654
1862
  const tblBottom = table.bbox.y;
1655
1863
  const gap = capBottom >= tblTop ? capBottom - tblTop : tblBottom - capTop;
1656
1864
  if (gap > CAPTION_MAX_GAP) return false;
1657
- const overlap = Math.min(b.bbox.x + b.bbox.width, table.bbox.x + table.bbox.width) - Math.max(b.bbox.x, table.bbox.x);
1658
- if (overlap < Math.min(b.bbox.width, table.bbox.width) * 0.3) return false;
1865
+ const overlap2 = Math.min(b.bbox.x + b.bbox.width, table.bbox.x + table.bbox.width) - Math.max(b.bbox.x, table.bbox.x);
1866
+ if (overlap2 < Math.min(b.bbox.width, table.bbox.width) * 0.3) return false;
1659
1867
  }
1660
1868
  return true;
1661
1869
  };
@@ -1919,8 +2127,8 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings) {
1919
2127
  if (!o.bbox || o.bbox.page !== cb.page) continue;
1920
2128
  const oNorm = o.text?.trim().replace(/\d+/g, "#");
1921
2129
  if (oNorm && repeatedPatterns.has(oNorm)) continue;
1922
- const overlap = Math.min(cb.y + cb.height, o.bbox.y + o.bbox.height) - Math.max(cb.y, o.bbox.y);
1923
- if (overlap >= cb.height * 0.5) {
2130
+ const overlap2 = Math.min(cb.y + cb.height, o.bbox.y + o.bbox.height) - Math.max(cb.y, o.bbox.y);
2131
+ if (overlap2 >= cb.height * 0.5) {
1924
2132
  sharesLine = true;
1925
2133
  break;
1926
2134
  }
@@ -2192,9 +2400,9 @@ function mergeOverlappingRows(rows) {
2192
2400
  const curr = rows[i];
2193
2401
  const a = rowBand(prev);
2194
2402
  const b = rowBand(curr);
2195
- const overlap = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
2196
- const prevIsFrag = isFragmentRow(prev) && a.height <= b.height * 0.8 && overlap >= a.height * 0.5;
2197
- const currIsFrag = isFragmentRow(curr) && b.height <= a.height * 0.8 && overlap >= b.height * 0.5;
2403
+ const overlap2 = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
2404
+ const prevIsFrag = isFragmentRow(prev) && a.height <= b.height * 0.8 && overlap2 >= a.height * 0.5;
2405
+ const currIsFrag = isFragmentRow(curr) && b.height <= a.height * 0.8 && overlap2 >= b.height * 0.5;
2198
2406
  if (prevIsFrag || currIsFrag) {
2199
2407
  const baseY = prevIsFrag ? curr.y : prev.y;
2200
2408
  result[result.length - 1] = { y: baseY, items: [...prev.items, ...curr.items] };
@@ -3071,8 +3279,8 @@ function markUnderlineItems(items, horizontals, verticals) {
3071
3279
  if (h <= 0 || item.w <= 0 || !item.text.trim()) continue;
3072
3280
  const below = Math.max(h * UNDER_BELOW_EM, UNDER_BELOW_MIN_PT);
3073
3281
  if (line.y1 < item.y - below || line.y1 > item.y + UNDER_ABOVE_PT) continue;
3074
- const overlap = Math.min(line.x2, item.x + item.w) - Math.max(line.x1, item.x);
3075
- if (overlap / item.w < UNDER_MIN_OVERLAP_RATIO) continue;
3282
+ const overlap2 = Math.min(line.x2, item.x + item.w) - Math.max(line.x1, item.x);
3283
+ if (overlap2 / item.w < UNDER_MIN_OVERLAP_RATIO) continue;
3076
3284
  matches.push(item);
3077
3285
  }
3078
3286
  if (matches.length === 0) continue;
@@ -3116,8 +3324,8 @@ function hasBoxTopPair(line, maxH, horizontals) {
3116
3324
  if (dy < maxH * UNDER_BOX_PAIR_MIN_EM || dy > maxH * UNDER_BOX_PAIR_MAX_EM) continue;
3117
3325
  const ow = o.x2 - o.x1;
3118
3326
  if (ow <= 0) continue;
3119
- const overlap = Math.min(line.x2, o.x2) - Math.max(line.x1, o.x1);
3120
- if (overlap / Math.max(w, ow) >= UNDER_BOX_PAIR_OVERLAP) return true;
3327
+ const overlap2 = Math.min(line.x2, o.x2) - Math.max(line.x1, o.x1);
3328
+ if (overlap2 / Math.max(w, ow) >= UNDER_BOX_PAIR_OVERLAP) return true;
3121
3329
  }
3122
3330
  return false;
3123
3331
  }
@@ -3128,8 +3336,8 @@ function isRepeatedSpanRule(line, horizontals) {
3128
3336
  for (const o of horizontals) {
3129
3337
  const ow = o.x2 - o.x1;
3130
3338
  if (ow <= 0) continue;
3131
- const overlap = Math.min(line.x2, o.x2) - Math.max(line.x1, o.x1);
3132
- if (overlap / Math.max(w, ow) < UNDER_SPAN_OVERLAP_RATIO) continue;
3339
+ const overlap2 = Math.min(line.x2, o.x2) - Math.max(line.x1, o.x1);
3340
+ if (overlap2 / Math.max(w, ow) < UNDER_SPAN_OVERLAP_RATIO) continue;
3133
3341
  if (!ys.some((y) => Math.abs(y - o.y1) < 2)) ys.push(o.y1);
3134
3342
  }
3135
3343
  return ys.length >= UNDER_REPEATED_SPAN_LEVELS;
@@ -3163,7 +3371,10 @@ function wrapUnderlineRuns(items) {
3163
3371
  // src/pdf/page-blocks.ts
3164
3372
  function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeight, extraLines, detectTables = true) {
3165
3373
  if (items.length === 0) return [];
3166
- let { horizontals, verticals } = extractLines(opList.fnArray, opList.argsArray);
3374
+ const extracted = extractLines(opList.fnArray, opList.argsArray);
3375
+ let { horizontals, verticals } = extracted;
3376
+ const clipResult = detectTables ? buildClipCellGrids(extracted.clipRects, horizontals, verticals, pageWidth, pageHeight) : { grids: [], containers: [] };
3377
+ const clipGrids = clipResult.grids;
3167
3378
  if (extraLines) {
3168
3379
  horizontals = horizontals.concat(extraLines.horizontals);
3169
3380
  verticals = verticals.concat(extraLines.verticals);
@@ -3177,7 +3388,8 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
3177
3388
  wrapStrikethroughRuns(items);
3178
3389
  markUnderlineItems(items, horizontals, verticals);
3179
3390
  wrapUnderlineRuns(items);
3180
- const grids = detectTables ? buildTableGrids(horizontals, verticals) : [];
3391
+ const lineGrids = detectTables ? buildTableGrids(horizontals, verticals) : [];
3392
+ const grids = [...clipGrids, ...dropGridsInside(lineGrids, clipGrids, clipResult.containers)];
3181
3393
  if (grids.length > 0) {
3182
3394
  return extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals);
3183
3395
  }
@@ -3199,8 +3411,8 @@ function markStrikethroughItems(items, horizontals) {
3199
3411
  if (line.lineWidth > h * STRIKE_MAX_THICKNESS_RATIO) continue;
3200
3412
  const centerY = item.y + h * 0.4;
3201
3413
  if (Math.abs(line.y1 - centerY) > h * STRIKE_CENTER_TOLERANCE) continue;
3202
- const overlap = Math.min(line.x2, item.x + item.w) - Math.max(line.x1, item.x);
3203
- if (overlap / item.w < STRIKE_MIN_OVERLAP_RATIO) continue;
3414
+ const overlap2 = Math.min(line.x2, item.x + item.w) - Math.max(line.x1, item.x);
3415
+ if (overlap2 / item.w < STRIKE_MIN_OVERLAP_RATIO) continue;
3204
3416
  matches.push(item);
3205
3417
  }
3206
3418
  if (matches.length === 0) continue;
@@ -3274,15 +3486,54 @@ function isProseBoxGrid(grid, verticals, table) {
3274
3486
  if (longCells < PROSEBOX_LONG_CELL_MIN || longCells < texts.length * PROSEBOX_LONG_CELL_RATIO) return false;
3275
3487
  return true;
3276
3488
  }
3489
+ function cleanCellText(text) {
3490
+ const stripped = text.replace(/^[\s]*[-–—]\s*\d+\s*[-–—][\s]*$/gm, "").trim();
3491
+ return stripped.split("\n").map((line) => collapseEvenSpacing(line)).join("\n");
3492
+ }
3493
+ var FRAME_RECT_TOL = 1.5;
3494
+ function takePendingNested(pending, cellBox) {
3495
+ const out = [];
3496
+ for (let i = pending.length - 1; i >= 0; i--) {
3497
+ const p = pending[i].parent;
3498
+ if (Math.abs(p.x1 - cellBox.x1) <= FRAME_RECT_TOL && Math.abs(p.x2 - cellBox.x2) <= FRAME_RECT_TOL && Math.abs(p.y1 - cellBox.y1) <= FRAME_RECT_TOL && Math.abs(p.y2 - cellBox.y2) <= FRAME_RECT_TOL) {
3499
+ out.push(pending[i].block);
3500
+ pending.splice(i, 1);
3501
+ }
3502
+ }
3503
+ return out;
3504
+ }
3505
+ function buildFrameCellBlocks(cellItems, nested, pageNum) {
3506
+ const tables = [...nested].sort((a, b) => b.bbox.y + b.bbox.height - (a.bbox.y + a.bbox.height));
3507
+ const blocks = [];
3508
+ let rest = [...cellItems];
3509
+ const pushParagraphs = (items) => {
3510
+ if (items.length === 0) return;
3511
+ for (const line of cleanCellText(cellTextToString(items)).split("\n")) {
3512
+ const t = line.trim();
3513
+ if (t) blocks.push({ type: "paragraph", text: t, pageNumber: pageNum });
3514
+ }
3515
+ };
3516
+ for (const tb of tables) {
3517
+ const bottom = tb.bbox.y;
3518
+ pushParagraphs(rest.filter((it) => it.y >= bottom));
3519
+ rest = rest.filter((it) => it.y < bottom);
3520
+ blocks.push(tb);
3521
+ }
3522
+ pushParagraphs(rest);
3523
+ const text = blocks.map((b) => b.type === "table" && b.table ? b.table.cells.flat().map((c) => c.text).filter(Boolean).join("\n") : b.text ?? "").filter(Boolean).join("\n");
3524
+ return { blocks, text };
3525
+ }
3277
3526
  function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3278
3527
  const blocks = [];
3279
3528
  const usedItems = /* @__PURE__ */ new Set();
3280
- const sortedGrids = [...grids].sort((a, b) => b.bbox.y2 - a.bbox.y2);
3529
+ const pendingNested = [];
3530
+ const gridArea = (g) => (g.bbox.x2 - g.bbox.x1) * (g.bbox.y2 - g.bbox.y1);
3531
+ const sortedGrids = [...grids].sort((a, b) => (b.cells ? 1 : 0) - (a.cells ? 1 : 0) || (a.cells && b.cells ? gridArea(a) - gridArea(b) : 0) || b.bbox.y2 - a.bbox.y2);
3281
3532
  for (const grid of sortedGrids) {
3282
3533
  const numGridRows = grid.rowYs.length - 1;
3283
3534
  const numGridCols = grid.colXs.length - 1;
3284
- if (numGridRows === 1 && numGridCols >= 2) continue;
3285
- if (numGridCols === 1 && numGridRows >= 2) continue;
3535
+ if (!grid.cells && numGridRows === 1 && numGridCols >= 2) continue;
3536
+ if (!grid.cells && numGridCols === 1 && numGridRows >= 2) continue;
3286
3537
  const tableItems = [];
3287
3538
  const pad = 3;
3288
3539
  const gridW = grid.bbox.x2 - grid.bbox.x1;
@@ -3294,7 +3545,7 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3294
3545
  tableItems.push(item);
3295
3546
  usedItems.add(item);
3296
3547
  }
3297
- const cells = extractCells(grid, horizontals, verticals);
3548
+ const cells = grid.cells ?? extractCells(grid, horizontals, verticals);
3298
3549
  if (cells.length === 0) continue;
3299
3550
  const textItems = tableItems.map((i) => ({
3300
3551
  text: i.text,
@@ -3315,13 +3566,18 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3315
3566
  { length: numRows },
3316
3567
  () => Array.from({ length: numCols }, () => ({ text: "", colSpan: 1, rowSpan: 1 }))
3317
3568
  );
3569
+ let nestedAttached = false;
3318
3570
  for (const cell of cells) {
3319
3571
  const cellItems = cellTextMap.get(cell) || [];
3320
- let text = cellTextToString(cellItems);
3321
- text = text.replace(/^[\s]*[-–—]\s*\d+\s*[-–—][\s]*$/gm, "").trim();
3322
- text = text.split("\n").map((line) => collapseEvenSpacing(line)).join("\n");
3572
+ const nested = grid.cells ? takePendingNested(pendingNested, cell.bbox) : [];
3573
+ if (nested.length > 0) {
3574
+ nestedAttached = true;
3575
+ const built = buildFrameCellBlocks(cellItems, nested, pageNum);
3576
+ irGrid[cell.row][cell.col] = { text: built.text, colSpan: cell.colSpan, rowSpan: cell.rowSpan, blocks: built.blocks };
3577
+ continue;
3578
+ }
3323
3579
  irGrid[cell.row][cell.col] = {
3324
- text,
3580
+ text: cleanCellText(cellTextToString(cellItems)),
3325
3581
  colSpan: cell.colSpan,
3326
3582
  rowSpan: cell.rowSpan
3327
3583
  };
@@ -3329,18 +3585,11 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3329
3585
  let finalGrid = irGrid;
3330
3586
  let finalRows = numRows;
3331
3587
  let rebuiltUsed = false;
3332
- if (numRows <= 2 && numCols >= 3) {
3588
+ if (numRows <= 2 && numCols >= 3 && !nestedAttached) {
3333
3589
  const rebuilt = normalizeUndersegmentedTable(irGrid, grid.colXs, textItems);
3334
3590
  if (rebuilt) {
3335
3591
  rebuiltUsed = true;
3336
- finalGrid = rebuilt.map((row) => row.map((rawText) => {
3337
- const cleaned = rawText.replace(/^[\s]*[-–—]\s*\d+\s*[-–—][\s]*$/gm, "").trim();
3338
- return {
3339
- text: cleaned.split("\n").map((line) => collapseEvenSpacing(line)).join("\n"),
3340
- colSpan: 1,
3341
- rowSpan: 1
3342
- };
3343
- }));
3592
+ finalGrid = rebuilt.map((row) => row.map((rawText) => ({ text: cleanCellText(rawText), colSpan: 1, rowSpan: 1 })));
3344
3593
  finalRows = finalGrid.length;
3345
3594
  }
3346
3595
  }
@@ -3357,7 +3606,12 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3357
3606
  };
3358
3607
  const hasContent = finalGrid.some((row) => row.some((cell) => cell.text.trim() !== ""));
3359
3608
  if (!hasContent) continue;
3360
- if (isProseBoxGrid(grid, verticals, irTable)) {
3609
+ if (grid.clipParent) {
3610
+ const nb = { page: pageNum, x: grid.bbox.x1, y: grid.bbox.y1, width: grid.bbox.x2 - grid.bbox.x1, height: grid.bbox.y2 - grid.bbox.y1 };
3611
+ pendingNested.push({ parent: grid.clipParent, block: { type: "table", table: irTable, pageNumber: pageNum, bbox: nb } });
3612
+ continue;
3613
+ }
3614
+ if (!grid.cells && isProseBoxGrid(grid, verticals, irTable)) {
3361
3615
  for (const it of tableItems) usedItems.delete(it);
3362
3616
  continue;
3363
3617
  }
@@ -3368,7 +3622,7 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3368
3622
  width: grid.bbox.x2 - grid.bbox.x1,
3369
3623
  height: grid.bbox.y2 - grid.bbox.y1
3370
3624
  };
3371
- if (shouldDemoteTable(irTable)) {
3625
+ if (!grid.cells && shouldDemoteTable(irTable)) {
3372
3626
  const demoted = demoteTableToText(irTable);
3373
3627
  if (demoted) {
3374
3628
  const text = numGridRows === 1 ? "\n" + demoted + "\n" : demoted;
@@ -3378,6 +3632,7 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3378
3632
  }
3379
3633
  blocks.push({ type: "table", table: irTable, pageNumber: pageNum, bbox: tableBbox });
3380
3634
  }
3635
+ for (const p of pendingNested) blocks.push(p.block);
3381
3636
  let remaining = items.filter((i) => !usedItems.has(i));
3382
3637
  const groupSizes = [];
3383
3638
  let finalTextBlocks = [];
@@ -3687,4 +3942,4 @@ export {
3687
3942
  extractPageBlocksWithLines,
3688
3943
  mergeCrossPageTables
3689
3944
  };
3690
- //# sourceMappingURL=chunk-SKGYPM6L.js.map
3945
+ //# sourceMappingURL=chunk-OEYECZGV.js.map