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
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  safeMax,
8
8
  safeMin
9
- } from "./chunk-MJPRWCI5.js";
9
+ } from "./chunk-MUYU4JI5.js";
10
10
 
11
11
  // src/pdf/image-regions.ts
12
12
  import { OPS } from "pdfjs-dist/legacy/build/pdf.mjs";
@@ -68,6 +68,8 @@ var MAX_LINE_WIDTH = 5;
68
68
  function extractLines(fnArray, argsArray) {
69
69
  const horizontals = [];
70
70
  const verticals = [];
71
+ const clipRects = [];
72
+ let pendingClip = false;
71
73
  let lineWidth = 1;
72
74
  let ctm = [1, 0, 0, 1, 0, 0];
73
75
  const ctmStack = [];
@@ -97,9 +99,12 @@ function extractLines(fnArray, argsArray) {
97
99
  }
98
100
  function flushPath(isStroke, fromFill = false) {
99
101
  if (!isStroke) {
102
+ if (pendingClip) captureClipRect(currentPath, clipRects);
103
+ pendingClip = false;
100
104
  currentPath = [];
101
105
  return;
102
106
  }
107
+ pendingClip = false;
103
108
  const effWidth = lineWidth * ctmScale();
104
109
  for (const seg of currentPath) {
105
110
  classifyAndAdd(seg, effWidth, horizontals, verticals, fromFill);
@@ -227,9 +232,29 @@ function extractLines(fnArray, argsArray) {
227
232
  case OPS2.endPath:
228
233
  flushPath(false);
229
234
  break;
235
+ case OPS2.clip:
236
+ case OPS2.eoClip:
237
+ pendingClip = true;
238
+ break;
230
239
  }
231
240
  }
232
- return { horizontals, verticals };
241
+ return { horizontals, verticals, clipRects };
242
+ }
243
+ var CLIP_MIN_W = 4;
244
+ var CLIP_MIN_H = 2;
245
+ function captureClipRect(path, out) {
246
+ if (path.length < 3 || path.length > 5) return;
247
+ let x1 = Infinity, y1 = Infinity, x2 = -Infinity, y2 = -Infinity;
248
+ for (const s of path) {
249
+ const dx = Math.abs(s.x2 - s.x1), dy = Math.abs(s.y2 - s.y1);
250
+ if (dx > ORIENTATION_TOL && dy > ORIENTATION_TOL) return;
251
+ x1 = Math.min(x1, s.x1, s.x2);
252
+ x2 = Math.max(x2, s.x1, s.x2);
253
+ y1 = Math.min(y1, s.y1, s.y2);
254
+ y2 = Math.max(y2, s.y1, s.y2);
255
+ }
256
+ if (x2 - x1 < CLIP_MIN_W || y2 - y1 < CLIP_MIN_H) return;
257
+ out.push({ x1, y1, x2, y2 });
233
258
  }
234
259
  function classifyAndAdd(seg, lineWidth, horizontals, verticals, fromFill = false) {
235
260
  const dx = Math.abs(seg.x2 - seg.x1);
@@ -442,9 +467,9 @@ function mergeParallelLines(lines, dir) {
442
467
  const prevEnd = dir === "h" ? prev.x2 : prev.y2;
443
468
  const currStart = dir === "h" ? curr.x1 : curr.y1;
444
469
  const currEnd = dir === "h" ? curr.x2 : curr.y2;
445
- const overlap = Math.min(prevEnd, currEnd) - Math.max(prevStart, currStart);
470
+ const overlap2 = Math.min(prevEnd, currEnd) - Math.max(prevStart, currStart);
446
471
  const minLen = Math.min(prevEnd - prevStart, currEnd - currStart);
447
- if (overlap > minLen * 0.3) {
472
+ if (overlap2 > minLen * 0.3) {
448
473
  if (dir === "h") {
449
474
  prev.x1 = Math.min(prev.x1, curr.x1);
450
475
  prev.x2 = Math.max(prev.x2, curr.x2);
@@ -933,6 +958,186 @@ function linesIntersect(a, b) {
933
958
  return v.x1 >= h.x1 - tol && v.x1 <= h.x2 + tol && h.y1 >= v.y1 - tol && h.y1 <= v.y2 + tol;
934
959
  }
935
960
 
961
+ // src/pdf/clip-cells.ts
962
+ var CLIP_EDGE_TOL = 1.5;
963
+ var CLIP_MIN_GROUP = 2;
964
+ var CLIP_MAX_PAGE_FRAC = 0.75;
965
+ var CLIP_MIN_W2 = 4;
966
+ var CLIP_MIN_H2 = 2;
967
+ var STROKE_NEAR = 2;
968
+ var STROKE_COVER = 0.5;
969
+ var CLIP_MIN_INVISIBLE = 0;
970
+ var overlap = (a1, a2, b1, b2) => Math.min(a2, b2) - Math.max(a1, b1);
971
+ function adjacent(a, b) {
972
+ 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;
973
+ 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;
974
+ return false;
975
+ }
976
+ function contains(a, b) {
977
+ 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);
978
+ }
979
+ function clusterCoords(values) {
980
+ const sorted = [...values].sort((a, b) => a - b);
981
+ const out = [];
982
+ let run = [];
983
+ for (const v of sorted) {
984
+ if (run.length > 0 && v - run[run.length - 1] > CLIP_EDGE_TOL) {
985
+ out.push(run.reduce((s, x) => s + x, 0) / run.length);
986
+ run = [];
987
+ }
988
+ run.push(v);
989
+ }
990
+ if (run.length > 0) out.push(run.reduce((s, x) => s + x, 0) / run.length);
991
+ return out;
992
+ }
993
+ var nearestIndex = (coords, v) => {
994
+ let best = 0;
995
+ for (let i = 1; i < coords.length; i++) if (Math.abs(coords[i] - v) < Math.abs(coords[best] - v)) best = i;
996
+ return best;
997
+ };
998
+ function edgeStroked(lines, dir, pos, a1, a2) {
999
+ const len = a2 - a1;
1000
+ if (len <= 0) return true;
1001
+ for (const l of lines) {
1002
+ if (dir === "h") {
1003
+ if (Math.abs(l.y1 - pos) <= STROKE_NEAR && overlap(l.x1, l.x2, a1, a2) >= len * STROKE_COVER) return true;
1004
+ } else if (Math.abs(l.x1 - pos) <= STROKE_NEAR && overlap(l.y1, l.y2, a1, a2) >= len * STROKE_COVER) {
1005
+ return true;
1006
+ }
1007
+ }
1008
+ return false;
1009
+ }
1010
+ function buildClipCellGrids(rects, strokedH, strokedV, pageWidth, pageHeight) {
1011
+ const pageArea = pageWidth * pageHeight;
1012
+ 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;
1013
+ const cells = [];
1014
+ for (const r of rects) {
1015
+ if (r.x2 - r.x1 < CLIP_MIN_W2 || r.y2 - r.y1 < CLIP_MIN_H2) continue;
1016
+ if (pageArea > 0 && (r.x2 - r.x1) * (r.y2 - r.y1) >= pageArea * CLIP_MAX_PAGE_FRAC) continue;
1017
+ if (!cells.some((c) => sameRect(c, r))) cells.push(r);
1018
+ }
1019
+ if (cells.length < 1) return { grids: [], containers: [] };
1020
+ const parent = new Array(cells.length).fill(-1);
1021
+ for (let i = 0; i < cells.length; i++) {
1022
+ for (let j = 0; j < cells.length; j++) {
1023
+ if (i === j || !contains(cells[j], cells[i])) continue;
1024
+ const cur = parent[i];
1025
+ if (cur < 0 || contains(cells[cur], cells[j])) parent[i] = j;
1026
+ }
1027
+ }
1028
+ const isContainer = new Array(cells.length).fill(false);
1029
+ for (const p of parent) if (p >= 0) isContainer[p] = true;
1030
+ const root = cells.map((_, i) => i);
1031
+ const find = (i) => {
1032
+ while (root[i] !== i) {
1033
+ root[i] = root[root[i]];
1034
+ i = root[i];
1035
+ }
1036
+ return i;
1037
+ };
1038
+ for (let i = 0; i < cells.length; i++) {
1039
+ for (let j = i + 1; j < cells.length; j++) {
1040
+ if (parent[i] !== parent[j]) continue;
1041
+ if (adjacent(cells[i], cells[j])) {
1042
+ const ra = find(i), rb = find(j);
1043
+ if (ra !== rb) root[ra] = rb;
1044
+ }
1045
+ }
1046
+ }
1047
+ const groups = /* @__PURE__ */ new Map();
1048
+ for (let i = 0; i < cells.length; i++) {
1049
+ const r = find(i);
1050
+ const g = groups.get(r);
1051
+ if (g) g.push(i);
1052
+ else groups.set(r, [i]);
1053
+ }
1054
+ const containers = cells.filter((_, i) => isContainer[i]);
1055
+ const groupSize = (i) => groups.get(find(i))?.length ?? 0;
1056
+ const isGridMember = (i) => groupSize(i) >= CLIP_MIN_GROUP;
1057
+ 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);
1058
+ const loneFrame = (i) => isContainer[i] && !isGridMember(i) && framed(cells[i]);
1059
+ const parentAttachable = (i) => parent[i] >= 0 && (isGridMember(parent[i]) || loneFrame(parent[i]));
1060
+ const onlyChild = (i) => parent[i] >= 0 && parent.filter((p) => p === parent[i]).length === 1;
1061
+ const grids = [];
1062
+ for (const idxs of groups.values()) {
1063
+ const first = idxs[0];
1064
+ const parentRect = parentAttachable(first) ? cells[parent[first]] : void 0;
1065
+ if (idxs.length < CLIP_MIN_GROUP) {
1066
+ if (!loneFrame(first) && !((parentRect || onlyChild(first)) && framed(cells[first]))) continue;
1067
+ const r = cells[first];
1068
+ grids.push({
1069
+ rowYs: [r.y2, r.y1],
1070
+ colXs: [r.x1, r.x2],
1071
+ bbox: { x1: r.x1, y1: r.y1, x2: r.x2, y2: r.y2 },
1072
+ vertexRadius: 1,
1073
+ cells: [{ row: 0, col: 0, rowSpan: 1, colSpan: 1, bbox: { x1: r.x1, y1: r.y1, x2: r.x2, y2: r.y2 } }],
1074
+ ...parentRect ? { clipParent: parentRect } : {}
1075
+ });
1076
+ continue;
1077
+ }
1078
+ const members = idxs.map((i) => cells[i]);
1079
+ let edges = 0, invisible = 0;
1080
+ for (const r of members) {
1081
+ edges += 4;
1082
+ if (!edgeStroked(strokedH, "h", r.y1, r.x1, r.x2)) invisible++;
1083
+ if (!edgeStroked(strokedH, "h", r.y2, r.x1, r.x2)) invisible++;
1084
+ if (!edgeStroked(strokedV, "v", r.x1, r.y1, r.y2)) invisible++;
1085
+ if (!edgeStroked(strokedV, "v", r.x2, r.y1, r.y2)) invisible++;
1086
+ }
1087
+ if (invisible / edges < CLIP_MIN_INVISIBLE) continue;
1088
+ const colXs = clusterCoords(members.flatMap((r) => [r.x1, r.x2]));
1089
+ const rowYs = clusterCoords(members.flatMap((r) => [r.y1, r.y2])).reverse();
1090
+ const numRows = rowYs.length - 1, numCols = colXs.length - 1;
1091
+ if (numRows < 1 || numCols < 1) continue;
1092
+ const occupied = Array.from({ length: numRows }, () => new Array(numCols).fill(false));
1093
+ const out = [];
1094
+ for (const r of members) {
1095
+ const c0 = nearestIndex(colXs, r.x1), c1 = nearestIndex(colXs, r.x2);
1096
+ const r0 = nearestIndex(rowYs, r.y2), r1 = nearestIndex(rowYs, r.y1);
1097
+ if (c1 <= c0 || r1 <= r0) continue;
1098
+ let clash = false;
1099
+ for (let rr = r0; rr < r1 && !clash; rr++) for (let cc = c0; cc < c1; cc++) if (occupied[rr][cc]) {
1100
+ clash = true;
1101
+ break;
1102
+ }
1103
+ if (clash) continue;
1104
+ for (let rr = r0; rr < r1; rr++) for (let cc = c0; cc < c1; cc++) occupied[rr][cc] = true;
1105
+ 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 } });
1106
+ }
1107
+ for (let rr = 0; rr < numRows; rr++) {
1108
+ for (let cc = 0; cc < numCols; cc++) {
1109
+ if (occupied[rr][cc]) continue;
1110
+ 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] } });
1111
+ }
1112
+ }
1113
+ grids.push({
1114
+ rowYs,
1115
+ colXs,
1116
+ bbox: { x1: colXs[0], y1: rowYs[numRows], x2: colXs[numCols], y2: rowYs[0] },
1117
+ vertexRadius: 1,
1118
+ cells: out,
1119
+ ...parentRect ? { clipParent: parentRect } : {}
1120
+ });
1121
+ }
1122
+ return { grids, containers };
1123
+ }
1124
+ function dropGridsInside(lineGrids, clipGrids, containers = []) {
1125
+ if (clipGrids.length === 0 && containers.length === 0) return lineGrids;
1126
+ const area = (b) => Math.max(0, b.x2 - b.x1) * Math.max(0, b.y2 - b.y1);
1127
+ const overlapsHalf = (g, b) => {
1128
+ const ix = Math.min(g.x2, b.x2) - Math.max(g.x1, b.x1);
1129
+ const iy = Math.min(g.y2, b.y2) - Math.max(g.y1, b.y1);
1130
+ if (ix <= 0 || iy <= 0) return false;
1131
+ const ga = area(g);
1132
+ return ga > 0 && ix * iy / ga >= 0.5;
1133
+ };
1134
+ return lineGrids.filter((g) => {
1135
+ if (clipGrids.some((c) => overlapsHalf(g.bbox, c.bbox))) return false;
1136
+ if (containers.some((c) => overlapsHalf(g.bbox, c))) return false;
1137
+ return true;
1138
+ });
1139
+ }
1140
+
936
1141
  // src/pdf/cell-extract.ts
937
1142
  function extractCells(grid, horizontals, verticals) {
938
1143
  const { rowYs, colXs } = grid;
@@ -1011,8 +1216,8 @@ function hasVerticalLine(verticals, x, topY, botY, vertexRadius) {
1011
1216
  if (cellH < 0.1) continue;
1012
1217
  const overlapTop = Math.min(v.y2, topY);
1013
1218
  const overlapBot = Math.max(v.y1, botY);
1014
- const overlap = overlapTop - overlapBot;
1015
- if (overlap >= cellH * 0.75) return true;
1219
+ const overlap2 = overlapTop - overlapBot;
1220
+ if (overlap2 >= cellH * 0.75) return true;
1016
1221
  }
1017
1222
  }
1018
1223
  return false;
@@ -1025,8 +1230,8 @@ function hasHorizontalLine(horizontals, y, leftX, rightX, vertexRadius) {
1025
1230
  if (cellW < 0.1) continue;
1026
1231
  const overlapLeft = Math.max(h.x1, leftX);
1027
1232
  const overlapRight = Math.min(h.x2, rightX);
1028
- const overlap = overlapRight - overlapLeft;
1029
- if (overlap >= cellW * 0.75) return true;
1233
+ const overlap2 = overlapRight - overlapLeft;
1234
+ if (overlap2 >= cellW * 0.75) return true;
1030
1235
  }
1031
1236
  }
1032
1237
  return false;
@@ -1133,9 +1338,9 @@ function mergeSuperscriptRows(lines) {
1133
1338
  const curr = lines[i];
1134
1339
  const a = band(prev);
1135
1340
  const b = band(curr);
1136
- const overlap = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
1137
- const prevIsFrag = isFrag(prev) && a.height <= b.height * 0.8 && overlap >= a.height * 0.5;
1138
- const currIsFrag = isFrag(curr) && b.height <= a.height * 0.8 && overlap >= b.height * 0.5;
1341
+ const overlap2 = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
1342
+ const prevIsFrag = isFrag(prev) && a.height <= b.height * 0.8 && overlap2 >= a.height * 0.5;
1343
+ const currIsFrag = isFrag(curr) && b.height <= a.height * 0.8 && overlap2 >= b.height * 0.5;
1139
1344
  if (prevIsFrag || currIsFrag) {
1140
1345
  result[result.length - 1] = [...prev, ...curr];
1141
1346
  } else {
@@ -1354,14 +1559,17 @@ function filterHiddenText(items, pageWidth, pageHeight) {
1354
1559
  function collapseEvenSpacing(text) {
1355
1560
  const tokens = text.split(" ");
1356
1561
  const singleCharCount = tokens.filter((t) => t.length === 1).length;
1357
- if (tokens.length >= 3 && singleCharCount / tokens.length >= 0.7) {
1562
+ if (tokens.length >= 3 && singleCharCount / tokens.length >= 0.7 && !isDateUnitBlank(tokens)) {
1358
1563
  return tokens.join("");
1359
1564
  }
1360
1565
  return text.replace(
1361
1566
  /(?<![가-힣])[가-힣](?: [가-힣\d]){2,}(?![가-힣])/g,
1362
- (match) => match.replace(/ /g, "")
1567
+ (match) => isDateUnitBlank(match.split(" ")) ? match : match.replace(/ /g, "")
1363
1568
  );
1364
1569
  }
1570
+ function isDateUnitBlank(tokens) {
1571
+ return tokens.every((t) => t.length !== 1 || !/[가-힣]/.test(t) || /[년월일시분초]/.test(t));
1572
+ }
1365
1573
  function computeBBox(items, pageNum) {
1366
1574
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
1367
1575
  for (const i of items) {
@@ -1502,9 +1710,9 @@ function mergeSuperscriptLines(lines) {
1502
1710
  const curr = lines[i];
1503
1711
  const a = band(prev);
1504
1712
  const b = band(curr);
1505
- const overlap = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
1506
- const prevIsFrag = isFrag(prev) && a.height <= b.height * 0.8 && overlap >= a.height * 0.5;
1507
- const currIsFrag = isFrag(curr) && b.height <= a.height * 0.8 && overlap >= b.height * 0.5;
1713
+ const overlap2 = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
1714
+ const prevIsFrag = isFrag(prev) && a.height <= b.height * 0.8 && overlap2 >= a.height * 0.5;
1715
+ const currIsFrag = isFrag(curr) && b.height <= a.height * 0.8 && overlap2 >= b.height * 0.5;
1508
1716
  if (prevIsFrag || currIsFrag) {
1509
1717
  result[result.length - 1] = [...prev, ...curr];
1510
1718
  } else {
@@ -1653,8 +1861,8 @@ function detectTableCaptions(blocks) {
1653
1861
  const tblBottom = table.bbox.y;
1654
1862
  const gap = capBottom >= tblTop ? capBottom - tblTop : tblBottom - capTop;
1655
1863
  if (gap > CAPTION_MAX_GAP) return false;
1656
- const overlap = Math.min(b.bbox.x + b.bbox.width, table.bbox.x + table.bbox.width) - Math.max(b.bbox.x, table.bbox.x);
1657
- if (overlap < Math.min(b.bbox.width, table.bbox.width) * 0.3) return false;
1864
+ const overlap2 = Math.min(b.bbox.x + b.bbox.width, table.bbox.x + table.bbox.width) - Math.max(b.bbox.x, table.bbox.x);
1865
+ if (overlap2 < Math.min(b.bbox.width, table.bbox.width) * 0.3) return false;
1658
1866
  }
1659
1867
  return true;
1660
1868
  };
@@ -1918,8 +2126,8 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings) {
1918
2126
  if (!o.bbox || o.bbox.page !== cb.page) continue;
1919
2127
  const oNorm = o.text?.trim().replace(/\d+/g, "#");
1920
2128
  if (oNorm && repeatedPatterns.has(oNorm)) continue;
1921
- const overlap = Math.min(cb.y + cb.height, o.bbox.y + o.bbox.height) - Math.max(cb.y, o.bbox.y);
1922
- if (overlap >= cb.height * 0.5) {
2129
+ const overlap2 = Math.min(cb.y + cb.height, o.bbox.y + o.bbox.height) - Math.max(cb.y, o.bbox.y);
2130
+ if (overlap2 >= cb.height * 0.5) {
1923
2131
  sharesLine = true;
1924
2132
  break;
1925
2133
  }
@@ -2191,9 +2399,9 @@ function mergeOverlappingRows(rows) {
2191
2399
  const curr = rows[i];
2192
2400
  const a = rowBand(prev);
2193
2401
  const b = rowBand(curr);
2194
- const overlap = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
2195
- const prevIsFrag = isFragmentRow(prev) && a.height <= b.height * 0.8 && overlap >= a.height * 0.5;
2196
- const currIsFrag = isFragmentRow(curr) && b.height <= a.height * 0.8 && overlap >= b.height * 0.5;
2402
+ const overlap2 = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
2403
+ const prevIsFrag = isFragmentRow(prev) && a.height <= b.height * 0.8 && overlap2 >= a.height * 0.5;
2404
+ const currIsFrag = isFragmentRow(curr) && b.height <= a.height * 0.8 && overlap2 >= b.height * 0.5;
2197
2405
  if (prevIsFrag || currIsFrag) {
2198
2406
  const baseY = prevIsFrag ? curr.y : prev.y;
2199
2407
  result[result.length - 1] = { y: baseY, items: [...prev.items, ...curr.items] };
@@ -3070,8 +3278,8 @@ function markUnderlineItems(items, horizontals, verticals) {
3070
3278
  if (h <= 0 || item.w <= 0 || !item.text.trim()) continue;
3071
3279
  const below = Math.max(h * UNDER_BELOW_EM, UNDER_BELOW_MIN_PT);
3072
3280
  if (line.y1 < item.y - below || line.y1 > item.y + UNDER_ABOVE_PT) continue;
3073
- const overlap = Math.min(line.x2, item.x + item.w) - Math.max(line.x1, item.x);
3074
- if (overlap / item.w < UNDER_MIN_OVERLAP_RATIO) continue;
3281
+ const overlap2 = Math.min(line.x2, item.x + item.w) - Math.max(line.x1, item.x);
3282
+ if (overlap2 / item.w < UNDER_MIN_OVERLAP_RATIO) continue;
3075
3283
  matches.push(item);
3076
3284
  }
3077
3285
  if (matches.length === 0) continue;
@@ -3115,8 +3323,8 @@ function hasBoxTopPair(line, maxH, horizontals) {
3115
3323
  if (dy < maxH * UNDER_BOX_PAIR_MIN_EM || dy > maxH * UNDER_BOX_PAIR_MAX_EM) continue;
3116
3324
  const ow = o.x2 - o.x1;
3117
3325
  if (ow <= 0) continue;
3118
- const overlap = Math.min(line.x2, o.x2) - Math.max(line.x1, o.x1);
3119
- if (overlap / Math.max(w, ow) >= UNDER_BOX_PAIR_OVERLAP) return true;
3326
+ const overlap2 = Math.min(line.x2, o.x2) - Math.max(line.x1, o.x1);
3327
+ if (overlap2 / Math.max(w, ow) >= UNDER_BOX_PAIR_OVERLAP) return true;
3120
3328
  }
3121
3329
  return false;
3122
3330
  }
@@ -3127,8 +3335,8 @@ function isRepeatedSpanRule(line, horizontals) {
3127
3335
  for (const o of horizontals) {
3128
3336
  const ow = o.x2 - o.x1;
3129
3337
  if (ow <= 0) continue;
3130
- const overlap = Math.min(line.x2, o.x2) - Math.max(line.x1, o.x1);
3131
- if (overlap / Math.max(w, ow) < UNDER_SPAN_OVERLAP_RATIO) continue;
3338
+ const overlap2 = Math.min(line.x2, o.x2) - Math.max(line.x1, o.x1);
3339
+ if (overlap2 / Math.max(w, ow) < UNDER_SPAN_OVERLAP_RATIO) continue;
3132
3340
  if (!ys.some((y) => Math.abs(y - o.y1) < 2)) ys.push(o.y1);
3133
3341
  }
3134
3342
  return ys.length >= UNDER_REPEATED_SPAN_LEVELS;
@@ -3162,7 +3370,10 @@ function wrapUnderlineRuns(items) {
3162
3370
  // src/pdf/page-blocks.ts
3163
3371
  function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeight, extraLines, detectTables = true) {
3164
3372
  if (items.length === 0) return [];
3165
- let { horizontals, verticals } = extractLines(opList.fnArray, opList.argsArray);
3373
+ const extracted = extractLines(opList.fnArray, opList.argsArray);
3374
+ let { horizontals, verticals } = extracted;
3375
+ const clipResult = detectTables ? buildClipCellGrids(extracted.clipRects, horizontals, verticals, pageWidth, pageHeight) : { grids: [], containers: [] };
3376
+ const clipGrids = clipResult.grids;
3166
3377
  if (extraLines) {
3167
3378
  horizontals = horizontals.concat(extraLines.horizontals);
3168
3379
  verticals = verticals.concat(extraLines.verticals);
@@ -3176,7 +3387,8 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
3176
3387
  wrapStrikethroughRuns(items);
3177
3388
  markUnderlineItems(items, horizontals, verticals);
3178
3389
  wrapUnderlineRuns(items);
3179
- const grids = detectTables ? buildTableGrids(horizontals, verticals) : [];
3390
+ const lineGrids = detectTables ? buildTableGrids(horizontals, verticals) : [];
3391
+ const grids = [...clipGrids, ...dropGridsInside(lineGrids, clipGrids, clipResult.containers)];
3180
3392
  if (grids.length > 0) {
3181
3393
  return extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals);
3182
3394
  }
@@ -3198,8 +3410,8 @@ function markStrikethroughItems(items, horizontals) {
3198
3410
  if (line.lineWidth > h * STRIKE_MAX_THICKNESS_RATIO) continue;
3199
3411
  const centerY = item.y + h * 0.4;
3200
3412
  if (Math.abs(line.y1 - centerY) > h * STRIKE_CENTER_TOLERANCE) continue;
3201
- const overlap = Math.min(line.x2, item.x + item.w) - Math.max(line.x1, item.x);
3202
- if (overlap / item.w < STRIKE_MIN_OVERLAP_RATIO) continue;
3413
+ const overlap2 = Math.min(line.x2, item.x + item.w) - Math.max(line.x1, item.x);
3414
+ if (overlap2 / item.w < STRIKE_MIN_OVERLAP_RATIO) continue;
3203
3415
  matches.push(item);
3204
3416
  }
3205
3417
  if (matches.length === 0) continue;
@@ -3273,15 +3485,54 @@ function isProseBoxGrid(grid, verticals, table) {
3273
3485
  if (longCells < PROSEBOX_LONG_CELL_MIN || longCells < texts.length * PROSEBOX_LONG_CELL_RATIO) return false;
3274
3486
  return true;
3275
3487
  }
3488
+ function cleanCellText(text) {
3489
+ const stripped = text.replace(/^[\s]*[-–—]\s*\d+\s*[-–—][\s]*$/gm, "").trim();
3490
+ return stripped.split("\n").map((line) => collapseEvenSpacing(line)).join("\n");
3491
+ }
3492
+ var FRAME_RECT_TOL = 1.5;
3493
+ function takePendingNested(pending, cellBox) {
3494
+ const out = [];
3495
+ for (let i = pending.length - 1; i >= 0; i--) {
3496
+ const p = pending[i].parent;
3497
+ 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) {
3498
+ out.push(pending[i].block);
3499
+ pending.splice(i, 1);
3500
+ }
3501
+ }
3502
+ return out;
3503
+ }
3504
+ function buildFrameCellBlocks(cellItems, nested, pageNum) {
3505
+ const tables = [...nested].sort((a, b) => b.bbox.y + b.bbox.height - (a.bbox.y + a.bbox.height));
3506
+ const blocks = [];
3507
+ let rest = [...cellItems];
3508
+ const pushParagraphs = (items) => {
3509
+ if (items.length === 0) return;
3510
+ for (const line of cleanCellText(cellTextToString(items)).split("\n")) {
3511
+ const t = line.trim();
3512
+ if (t) blocks.push({ type: "paragraph", text: t, pageNumber: pageNum });
3513
+ }
3514
+ };
3515
+ for (const tb of tables) {
3516
+ const bottom = tb.bbox.y;
3517
+ pushParagraphs(rest.filter((it) => it.y >= bottom));
3518
+ rest = rest.filter((it) => it.y < bottom);
3519
+ blocks.push(tb);
3520
+ }
3521
+ pushParagraphs(rest);
3522
+ 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");
3523
+ return { blocks, text };
3524
+ }
3276
3525
  function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3277
3526
  const blocks = [];
3278
3527
  const usedItems = /* @__PURE__ */ new Set();
3279
- const sortedGrids = [...grids].sort((a, b) => b.bbox.y2 - a.bbox.y2);
3528
+ const pendingNested = [];
3529
+ const gridArea = (g) => (g.bbox.x2 - g.bbox.x1) * (g.bbox.y2 - g.bbox.y1);
3530
+ 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);
3280
3531
  for (const grid of sortedGrids) {
3281
3532
  const numGridRows = grid.rowYs.length - 1;
3282
3533
  const numGridCols = grid.colXs.length - 1;
3283
- if (numGridRows === 1 && numGridCols >= 2) continue;
3284
- if (numGridCols === 1 && numGridRows >= 2) continue;
3534
+ if (!grid.cells && numGridRows === 1 && numGridCols >= 2) continue;
3535
+ if (!grid.cells && numGridCols === 1 && numGridRows >= 2) continue;
3285
3536
  const tableItems = [];
3286
3537
  const pad = 3;
3287
3538
  const gridW = grid.bbox.x2 - grid.bbox.x1;
@@ -3293,7 +3544,7 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3293
3544
  tableItems.push(item);
3294
3545
  usedItems.add(item);
3295
3546
  }
3296
- const cells = extractCells(grid, horizontals, verticals);
3547
+ const cells = grid.cells ?? extractCells(grid, horizontals, verticals);
3297
3548
  if (cells.length === 0) continue;
3298
3549
  const textItems = tableItems.map((i) => ({
3299
3550
  text: i.text,
@@ -3314,13 +3565,18 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3314
3565
  { length: numRows },
3315
3566
  () => Array.from({ length: numCols }, () => ({ text: "", colSpan: 1, rowSpan: 1 }))
3316
3567
  );
3568
+ let nestedAttached = false;
3317
3569
  for (const cell of cells) {
3318
3570
  const cellItems = cellTextMap.get(cell) || [];
3319
- let text = cellTextToString(cellItems);
3320
- text = text.replace(/^[\s]*[-–—]\s*\d+\s*[-–—][\s]*$/gm, "").trim();
3321
- text = text.split("\n").map((line) => collapseEvenSpacing(line)).join("\n");
3571
+ const nested = grid.cells ? takePendingNested(pendingNested, cell.bbox) : [];
3572
+ if (nested.length > 0) {
3573
+ nestedAttached = true;
3574
+ const built = buildFrameCellBlocks(cellItems, nested, pageNum);
3575
+ irGrid[cell.row][cell.col] = { text: built.text, colSpan: cell.colSpan, rowSpan: cell.rowSpan, blocks: built.blocks };
3576
+ continue;
3577
+ }
3322
3578
  irGrid[cell.row][cell.col] = {
3323
- text,
3579
+ text: cleanCellText(cellTextToString(cellItems)),
3324
3580
  colSpan: cell.colSpan,
3325
3581
  rowSpan: cell.rowSpan
3326
3582
  };
@@ -3328,18 +3584,11 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3328
3584
  let finalGrid = irGrid;
3329
3585
  let finalRows = numRows;
3330
3586
  let rebuiltUsed = false;
3331
- if (numRows <= 2 && numCols >= 3) {
3587
+ if (numRows <= 2 && numCols >= 3 && !nestedAttached) {
3332
3588
  const rebuilt = normalizeUndersegmentedTable(irGrid, grid.colXs, textItems);
3333
3589
  if (rebuilt) {
3334
3590
  rebuiltUsed = true;
3335
- finalGrid = rebuilt.map((row) => row.map((rawText) => {
3336
- const cleaned = rawText.replace(/^[\s]*[-–—]\s*\d+\s*[-–—][\s]*$/gm, "").trim();
3337
- return {
3338
- text: cleaned.split("\n").map((line) => collapseEvenSpacing(line)).join("\n"),
3339
- colSpan: 1,
3340
- rowSpan: 1
3341
- };
3342
- }));
3591
+ finalGrid = rebuilt.map((row) => row.map((rawText) => ({ text: cleanCellText(rawText), colSpan: 1, rowSpan: 1 })));
3343
3592
  finalRows = finalGrid.length;
3344
3593
  }
3345
3594
  }
@@ -3356,7 +3605,12 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3356
3605
  };
3357
3606
  const hasContent = finalGrid.some((row) => row.some((cell) => cell.text.trim() !== ""));
3358
3607
  if (!hasContent) continue;
3359
- if (isProseBoxGrid(grid, verticals, irTable)) {
3608
+ if (grid.clipParent) {
3609
+ 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 };
3610
+ pendingNested.push({ parent: grid.clipParent, block: { type: "table", table: irTable, pageNumber: pageNum, bbox: nb } });
3611
+ continue;
3612
+ }
3613
+ if (!grid.cells && isProseBoxGrid(grid, verticals, irTable)) {
3360
3614
  for (const it of tableItems) usedItems.delete(it);
3361
3615
  continue;
3362
3616
  }
@@ -3367,7 +3621,7 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3367
3621
  width: grid.bbox.x2 - grid.bbox.x1,
3368
3622
  height: grid.bbox.y2 - grid.bbox.y1
3369
3623
  };
3370
- if (shouldDemoteTable(irTable)) {
3624
+ if (!grid.cells && shouldDemoteTable(irTable)) {
3371
3625
  const demoted = demoteTableToText(irTable);
3372
3626
  if (demoted) {
3373
3627
  const text = numGridRows === 1 ? "\n" + demoted + "\n" : demoted;
@@ -3377,6 +3631,7 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3377
3631
  }
3378
3632
  blocks.push({ type: "table", table: irTable, pageNumber: pageNum, bbox: tableBbox });
3379
3633
  }
3634
+ for (const p of pendingNested) blocks.push(p.block);
3380
3635
  let remaining = items.filter((i) => !usedItems.has(i));
3381
3636
  const groupSizes = [];
3382
3637
  let finalTextBlocks = [];
@@ -3686,4 +3941,4 @@ export {
3686
3941
  extractPageBlocksWithLines,
3687
3942
  mergeCrossPageTables
3688
3943
  };
3689
- //# sourceMappingURL=chunk-SMGSCP57.js.map
3944
+ //# sourceMappingURL=chunk-7XUXSDH5.js.map