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.
- package/README.md +26 -5
- package/dist/{-B3EUUBPV.js → -EZH6NKTE.js} +8 -8
- package/dist/{chunk-HGUNWAXK.js → chunk-2B7OIEJJ.js} +9 -5
- package/dist/chunk-2B7OIEJJ.js.map +1 -0
- package/dist/{chunk-QKFCGJJY.js → chunk-2HBYWA5X.js} +2 -2
- package/dist/{chunk-HFJWCAJ2.cjs → chunk-2LKYJ4G3.cjs} +6 -6
- package/dist/chunk-2LKYJ4G3.cjs.map +1 -0
- package/dist/{chunk-COGFPMEB.js → chunk-2LO525TL.js} +2 -2
- package/dist/{chunk-TROD36DK.cjs → chunk-2LPBIW2B.cjs} +3 -3
- package/dist/chunk-2LPBIW2B.cjs.map +1 -0
- package/dist/{chunk-BQSWSMRG.cjs → chunk-62IU4NV3.cjs} +2 -2
- package/dist/chunk-62IU4NV3.cjs.map +1 -0
- package/dist/{chunk-SMGSCP57.js → chunk-7XUXSDH5.js} +308 -53
- package/dist/chunk-7XUXSDH5.js.map +1 -0
- package/dist/{chunk-YASFVKDT.js → chunk-DBGEUDBY.js} +2 -2
- package/dist/chunk-DCZVOIEO.cjs.map +1 -1
- package/dist/{chunk-4PKNWBXJ.js → chunk-FBLMVHDK.js} +2 -2
- package/dist/{chunk-I2OETEEL.js → chunk-FVBR7SC3.js} +2 -2
- package/dist/chunk-GS7T56RP.cjs.map +1 -1
- package/dist/{chunk-46UDI56N.js → chunk-IOJX4Q63.js} +3 -3
- package/dist/{chunk-BQE7AMFS.js → chunk-JCMBQC5N.js} +2 -2
- package/dist/{chunk-TF5DS74F.js → chunk-KX7IYCCZ.js} +3 -3
- package/dist/{chunk-PFUW4I4I.js → chunk-LD2K4K5V.js} +170 -18
- package/dist/chunk-LD2K4K5V.js.map +1 -0
- package/dist/{chunk-MJPRWCI5.js → chunk-MUYU4JI5.js} +2 -2
- package/dist/{chunk-SKGYPM6L.js → chunk-OEYECZGV.js} +308 -53
- package/dist/chunk-OEYECZGV.js.map +1 -0
- package/dist/{chunk-AT23GFSK.cjs → chunk-ONNAHSPV.cjs} +323 -68
- package/dist/chunk-ONNAHSPV.cjs.map +1 -0
- package/dist/{chunk-GHVXLV52.js → chunk-Q6ETEJFK.js} +9 -5
- package/dist/chunk-Q6ETEJFK.js.map +1 -0
- package/dist/{chunk-2IR3PEZU.js → chunk-QBCMFNHS.js} +2 -2
- package/dist/{chunk-DRLKMFDV.js → chunk-QM2RSJ2S.js} +3 -3
- package/dist/chunk-T7GRHAIW.cjs.map +1 -1
- package/dist/{chunk-TJYZY2O6.js → chunk-UL2MDA5C.js} +3 -3
- package/dist/{chunk-TYYJSOZS.cjs → chunk-V5BUPZ6I.cjs} +23 -19
- package/dist/chunk-V5BUPZ6I.cjs.map +1 -0
- package/dist/{chunk-7JQ2ITT2.js → chunk-XXDZ2KTW.js} +2 -2
- package/dist/chunks-TT7ZE5QQ.js +10 -0
- package/dist/cli.js +21 -21
- package/dist/cli.js.map +1 -1
- package/dist/{formula-WGKKR5OQ.js → formula-6RQX4NMJ.js} +4 -4
- package/dist/{formula-YMGXXRBQ.cjs → formula-NBEO6CFC.cjs} +9 -9
- package/dist/formula-NBEO6CFC.cjs.map +1 -0
- package/dist/{formula-G4CD5KQ6.js → formula-NW33S4TA.js} +3 -3
- package/dist/{image-ocr-MBWZK3ZT.js → image-ocr-CAVU2TNZ.js} +5 -5
- package/dist/{image-ocr-M4RP4INO.js → image-ocr-SO56VETS.js} +7 -7
- package/dist/{image-ocr-BE2HHMVN.cjs → image-ocr-V4KY373B.cjs} +11 -11
- package/dist/image-ocr-V4KY373B.cjs.map +1 -0
- package/dist/index.cjs +547 -395
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +166 -14
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +15 -15
- package/dist/{model-bundle-BIMP5DIH.js → model-bundle-EIJF34DR.js} +5 -5
- package/dist/{models-QPOEGHVA.js → models-6V4CPQXC.js} +5 -5
- package/dist/page-range-P7SDW6LR.cjs.map +1 -1
- package/dist/{parser-CMNHBVTL.js → parser-GIREMEPD.js} +307 -6
- package/dist/parser-GIREMEPD.js.map +1 -0
- package/dist/{parser-NR3XO4SM.js → parser-OBHNXEQM.js} +307 -6
- package/dist/parser-OBHNXEQM.js.map +1 -0
- package/dist/{parser-QJY5W47V.cjs → parser-OMT25WH2.cjs} +334 -33
- package/dist/parser-OMT25WH2.cjs.map +1 -0
- package/dist/pdf-ocr-IRXQ5GBM.js +13 -0
- package/dist/pdf-ocr-SL4GCOGS.js +16 -0
- package/dist/pdf-ocr-TFYVK4FI.cjs +14 -0
- package/dist/pdf-ocr-TFYVK4FI.cjs.map +1 -0
- package/dist/{profile-io-UZ43CLWX.js → profile-io-PZVMM66V.js} +3 -3
- package/dist/{rasterize-JC2JVVOF.js → rasterize-NRWP2C6L.js} +2 -2
- package/dist/render-V5ZPTZQ7.js +10 -0
- package/dist/seal-LVG2DGAB.js +10 -0
- package/dist/{setup-WDUVPFX3.js → setup-V55AJP6H.js} +3 -3
- package/dist/{watch-UI7OXIES.js → watch-7CQSMDDP.js} +9 -9
- package/package.json +1 -1
- package/dist/chunk-AT23GFSK.cjs.map +0 -1
- package/dist/chunk-BQSWSMRG.cjs.map +0 -1
- package/dist/chunk-GHVXLV52.js.map +0 -1
- package/dist/chunk-HFJWCAJ2.cjs.map +0 -1
- package/dist/chunk-HGUNWAXK.js.map +0 -1
- package/dist/chunk-PFUW4I4I.js.map +0 -1
- package/dist/chunk-SKGYPM6L.js.map +0 -1
- package/dist/chunk-SMGSCP57.js.map +0 -1
- package/dist/chunk-TROD36DK.cjs.map +0 -1
- package/dist/chunk-TYYJSOZS.cjs.map +0 -1
- package/dist/chunks-Q4GCPRRU.js +0 -10
- package/dist/formula-YMGXXRBQ.cjs.map +0 -1
- package/dist/image-ocr-BE2HHMVN.cjs.map +0 -1
- package/dist/parser-CMNHBVTL.js.map +0 -1
- package/dist/parser-NR3XO4SM.js.map +0 -1
- package/dist/parser-QJY5W47V.cjs.map +0 -1
- package/dist/pdf-ocr-DF3OTBKH.js +0 -13
- package/dist/pdf-ocr-R4DIKF4Q.js +0 -16
- package/dist/pdf-ocr-T3RHIZKY.cjs +0 -14
- package/dist/pdf-ocr-T3RHIZKY.cjs.map +0 -1
- package/dist/render-KSQ6UGCP.js +0 -10
- package/dist/seal-EOFFQ4JR.js +0 -10
- /package/dist/{-B3EUUBPV.js.map → -EZH6NKTE.js.map} +0 -0
- /package/dist/{chunk-QKFCGJJY.js.map → chunk-2HBYWA5X.js.map} +0 -0
- /package/dist/{chunk-COGFPMEB.js.map → chunk-2LO525TL.js.map} +0 -0
- /package/dist/{chunk-YASFVKDT.js.map → chunk-DBGEUDBY.js.map} +0 -0
- /package/dist/{chunk-4PKNWBXJ.js.map → chunk-FBLMVHDK.js.map} +0 -0
- /package/dist/{chunk-I2OETEEL.js.map → chunk-FVBR7SC3.js.map} +0 -0
- /package/dist/{chunk-46UDI56N.js.map → chunk-IOJX4Q63.js.map} +0 -0
- /package/dist/{chunk-BQE7AMFS.js.map → chunk-JCMBQC5N.js.map} +0 -0
- /package/dist/{chunk-TF5DS74F.js.map → chunk-KX7IYCCZ.js.map} +0 -0
- /package/dist/{chunk-MJPRWCI5.js.map → chunk-MUYU4JI5.js.map} +0 -0
- /package/dist/{chunk-2IR3PEZU.js.map → chunk-QBCMFNHS.js.map} +0 -0
- /package/dist/{chunk-DRLKMFDV.js.map → chunk-QM2RSJ2S.js.map} +0 -0
- /package/dist/{chunk-TJYZY2O6.js.map → chunk-UL2MDA5C.js.map} +0 -0
- /package/dist/{chunk-7JQ2ITT2.js.map → chunk-XXDZ2KTW.js.map} +0 -0
- /package/dist/{chunks-Q4GCPRRU.js.map → chunks-TT7ZE5QQ.js.map} +0 -0
- /package/dist/{formula-WGKKR5OQ.js.map → formula-6RQX4NMJ.js.map} +0 -0
- /package/dist/{formula-G4CD5KQ6.js.map → formula-NW33S4TA.js.map} +0 -0
- /package/dist/{image-ocr-MBWZK3ZT.js.map → image-ocr-CAVU2TNZ.js.map} +0 -0
- /package/dist/{image-ocr-M4RP4INO.js.map → image-ocr-SO56VETS.js.map} +0 -0
- /package/dist/{model-bundle-BIMP5DIH.js.map → model-bundle-EIJF34DR.js.map} +0 -0
- /package/dist/{models-QPOEGHVA.js.map → models-6V4CPQXC.js.map} +0 -0
- /package/dist/{pdf-ocr-DF3OTBKH.js.map → pdf-ocr-IRXQ5GBM.js.map} +0 -0
- /package/dist/{pdf-ocr-R4DIKF4Q.js.map → pdf-ocr-SL4GCOGS.js.map} +0 -0
- /package/dist/{profile-io-UZ43CLWX.js.map → profile-io-PZVMM66V.js.map} +0 -0
- /package/dist/{rasterize-JC2JVVOF.js.map → rasterize-NRWP2C6L.js.map} +0 -0
- /package/dist/{render-KSQ6UGCP.js.map → render-V5ZPTZQ7.js.map} +0 -0
- /package/dist/{seal-EOFFQ4JR.js.map → seal-LVG2DGAB.js.map} +0 -0
- /package/dist/{setup-WDUVPFX3.js.map → setup-V55AJP6H.js.map} +0 -0
- /package/dist/{watch-UI7OXIES.js.map → watch-7CQSMDDP.js.map} +0 -0
|
@@ -6,7 +6,7 @@ var _chunkT7GRHAIWcjs = require('./chunk-T7GRHAIW.cjs');
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
var
|
|
9
|
+
var _chunk62IU4NV3cjs = require('./chunk-62IU4NV3.cjs');
|
|
10
10
|
|
|
11
11
|
// src/pdf/image-regions.ts
|
|
12
12
|
var _pdfmjs = require('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 _pdfmjs.OPS.endPath:
|
|
228
233
|
flushPath(false);
|
|
229
234
|
break;
|
|
235
|
+
case _pdfmjs.OPS.clip:
|
|
236
|
+
case _pdfmjs.OPS.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
|
|
470
|
+
const overlap2 = Math.min(prevEnd, currEnd) - Math.max(prevStart, currStart);
|
|
446
471
|
const minLen = Math.min(prevEnd - prevStart, currEnd - currStart);
|
|
447
|
-
if (
|
|
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) => _nullishCoalesce(_optionalChain([groups, 'access', _4 => _4.get, 'call', _5 => _5(find(i)), 'optionalAccess', _6 => _6.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
|
|
1015
|
-
if (
|
|
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
|
|
1029
|
-
if (
|
|
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
|
|
1137
|
-
const prevIsFrag = isFrag(prev) && a.height <= b.height * 0.8 &&
|
|
1138
|
-
const currIsFrag = isFrag(curr) && b.height <= a.height * 0.8 &&
|
|
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) {
|
|
@@ -1387,7 +1595,7 @@ function dominantStyle(items) {
|
|
|
1387
1595
|
}
|
|
1388
1596
|
}
|
|
1389
1597
|
if (dominantSize === 0) return void 0;
|
|
1390
|
-
const fontName = _optionalChain([items, 'access',
|
|
1598
|
+
const fontName = _optionalChain([items, 'access', _7 => _7.find, 'call', _8 => _8((i) => i.fontSize === dominantSize), 'optionalAccess', _9 => _9.fontName]) || void 0;
|
|
1391
1599
|
return fontName ? { fontSize: dominantSize, fontName } : { fontSize: dominantSize };
|
|
1392
1600
|
}
|
|
1393
1601
|
function normalizeItems(rawItems) {
|
|
@@ -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
|
|
1506
|
-
const prevIsFrag = isFrag(prev) && a.height <= b.height * 0.8 &&
|
|
1507
|
-
const currIsFrag = isFrag(curr) && b.height <= a.height * 0.8 &&
|
|
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 {
|
|
@@ -1514,7 +1722,7 @@ function mergeSuperscriptLines(lines) {
|
|
|
1514
1722
|
return result;
|
|
1515
1723
|
}
|
|
1516
1724
|
function mergeLineSimple(items) {
|
|
1517
|
-
if (items.length <= 1) return _optionalChain([items, 'access',
|
|
1725
|
+
if (items.length <= 1) return _optionalChain([items, 'access', _10 => _10[0], 'optionalAccess', _11 => _11.text]) || "";
|
|
1518
1726
|
const sorted = [...items].sort((a, b) => a.x - b.x);
|
|
1519
1727
|
const isEvenSpaced = detectEvenSpacedItems(sorted);
|
|
1520
1728
|
let result = sorted[0].text;
|
|
@@ -1563,7 +1771,7 @@ function computeMedianFontSizeFromFreq(freq) {
|
|
|
1563
1771
|
}
|
|
1564
1772
|
function detectHeadings(blocks, medianFontSize) {
|
|
1565
1773
|
for (const block of blocks) {
|
|
1566
|
-
if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access',
|
|
1774
|
+
if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _12 => _12.style, 'optionalAccess', _13 => _13.fontSize])) continue;
|
|
1567
1775
|
const text = block.text.trim();
|
|
1568
1776
|
if (text.length === 0 || text.length > 200) continue;
|
|
1569
1777
|
if (/^\d+$/.test(text)) continue;
|
|
@@ -1624,7 +1832,7 @@ function detectMarkerHeadings(blocks) {
|
|
|
1624
1832
|
block.level = 4;
|
|
1625
1833
|
continue;
|
|
1626
1834
|
}
|
|
1627
|
-
if (/^[가-힣]{2,6}$/.test(text) && _optionalChain([block, 'access',
|
|
1835
|
+
if (/^[가-힣]{2,6}$/.test(text) && _optionalChain([block, 'access', _14 => _14.style, 'optionalAccess', _15 => _15.fontSize])) {
|
|
1628
1836
|
const prev = blocks[i - 1];
|
|
1629
1837
|
const next = blocks[i + 1];
|
|
1630
1838
|
const prevIsStructural = !prev || prev.type === "table" || prev.type === "heading" || prev.type === "separator";
|
|
@@ -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
|
|
1657
|
-
if (
|
|
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
|
};
|
|
@@ -1879,7 +2087,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings) {
|
|
|
1879
2087
|
const bottomEntries = [];
|
|
1880
2088
|
for (let bi = 0; bi < blocks.length; bi++) {
|
|
1881
2089
|
const b = blocks[bi];
|
|
1882
|
-
if (!b.bbox || !b.pageNumber || !_optionalChain([b, 'access',
|
|
2090
|
+
if (!b.bbox || !b.pageNumber || !_optionalChain([b, 'access', _16 => _16.text, 'optionalAccess', _17 => _17.trim, 'call', _18 => _18()])) continue;
|
|
1883
2091
|
const ph = pageHeights.get(b.bbox.page) || pageHeights.get(b.pageNumber);
|
|
1884
2092
|
if (!ph) continue;
|
|
1885
2093
|
const blockTop = ph - (b.bbox.y + b.bbox.height);
|
|
@@ -1902,7 +2110,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings) {
|
|
|
1902
2110
|
}
|
|
1903
2111
|
const repeatedPatterns = /* @__PURE__ */ new Set();
|
|
1904
2112
|
for (const [p, count] of patternCount) {
|
|
1905
|
-
if (count >= MIN_REPEAT && (_nullishCoalesce(_optionalChain([patternPages, 'access',
|
|
2113
|
+
if (count >= MIN_REPEAT && (_nullishCoalesce(_optionalChain([patternPages, 'access', _19 => _19.get, 'call', _20 => _20(p), 'optionalAccess', _21 => _21.size]), () => ( 0))) >= MIN_REPEAT) {
|
|
1906
2114
|
repeatedPatterns.add(p);
|
|
1907
2115
|
}
|
|
1908
2116
|
}
|
|
@@ -1916,10 +2124,10 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings) {
|
|
|
1916
2124
|
if (bi === e.blockIdx) continue;
|
|
1917
2125
|
const o = blocks[bi];
|
|
1918
2126
|
if (!o.bbox || o.bbox.page !== cb.page) continue;
|
|
1919
|
-
const oNorm = _optionalChain([o, 'access',
|
|
2127
|
+
const oNorm = _optionalChain([o, 'access', _22 => _22.text, 'optionalAccess', _23 => _23.trim, 'call', _24 => _24(), 'access', _25 => _25.replace, 'call', _26 => _26(/\d+/g, "#")]);
|
|
1920
2128
|
if (oNorm && repeatedPatterns.has(oNorm)) continue;
|
|
1921
|
-
const
|
|
1922
|
-
if (
|
|
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
|
}
|
|
@@ -1987,12 +2195,12 @@ function isTwoColumnProse(r) {
|
|
|
1987
2195
|
if (t.rows < 8) return false;
|
|
1988
2196
|
const dense = [];
|
|
1989
2197
|
for (let c = 0; c < t.cols; c++) {
|
|
1990
|
-
const filled = t.cells.filter((row) => _optionalChain([row, 'access',
|
|
2198
|
+
const filled = t.cells.filter((row) => _optionalChain([row, 'access', _27 => _27[c], 'optionalAccess', _28 => _28.text, 'access', _29 => _29.trim, 'call', _30 => _30()])).length;
|
|
1991
2199
|
if (filled / t.rows >= 0.3) dense.push(c);
|
|
1992
2200
|
}
|
|
1993
2201
|
if (dense.length !== 2) return false;
|
|
1994
2202
|
for (const c of dense) {
|
|
1995
|
-
const lens = t.cells.map((row) => _nullishCoalesce(_optionalChain([row, 'access',
|
|
2203
|
+
const lens = t.cells.map((row) => _nullishCoalesce(_optionalChain([row, 'access', _31 => _31[c], 'optionalAccess', _32 => _32.text, 'access', _33 => _33.replace, 'call', _34 => _34(/\s+/g, ""), 'access', _35 => _35.length]), () => ( 0))).filter((n) => n > 0);
|
|
1996
2204
|
const avg = lens.reduce((s, v) => s + v, 0) / (lens.length || 1);
|
|
1997
2205
|
if (avg < 12) return false;
|
|
1998
2206
|
}
|
|
@@ -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
|
|
2195
|
-
const prevIsFrag = isFragmentRow(prev) && a.height <= b.height * 0.8 &&
|
|
2196
|
-
const currIsFrag = isFragmentRow(curr) && b.height <= a.height * 0.8 &&
|
|
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] };
|
|
@@ -2469,7 +2677,7 @@ function buildClusterTable(rows, columns, pageNum) {
|
|
|
2469
2677
|
const nonEmptyCols = cells[r].filter((c) => c.text.trim()).length;
|
|
2470
2678
|
if (nonEmptyCols !== 1) continue;
|
|
2471
2679
|
if (cells[r][0].text.trim() !== "") continue;
|
|
2472
|
-
const contentText = _optionalChain([cells, 'access',
|
|
2680
|
+
const contentText = _optionalChain([cells, 'access', _36 => _36[r], 'access', _37 => _37.find, 'call', _38 => _38((c) => c.text.trim()), 'optionalAccess', _39 => _39.text, 'access', _40 => _40.trim, 'call', _41 => _41()]) || "";
|
|
2473
2681
|
if (/^[○●▶\-·]/.test(contentText)) continue;
|
|
2474
2682
|
for (let pr = r - 1; pr >= 0; pr--) {
|
|
2475
2683
|
if (cells[pr].some((c) => c.text.trim())) {
|
|
@@ -2834,14 +3042,14 @@ function isProseSpread(items) {
|
|
|
2834
3042
|
for (let i = 1; i < sorted.length; i++) {
|
|
2835
3043
|
gaps.push(sorted[i].x - (sorted[i - 1].x + sorted[i - 1].w));
|
|
2836
3044
|
}
|
|
2837
|
-
const maxGap =
|
|
3045
|
+
const maxGap = _chunk62IU4NV3cjs.safeMax.call(void 0, gaps);
|
|
2838
3046
|
const avgLen = items.reduce((s, i) => s + i.text.length, 0) / items.length;
|
|
2839
3047
|
return maxGap < 40 && avgLen < 5;
|
|
2840
3048
|
}
|
|
2841
3049
|
function detectColumns(yLines) {
|
|
2842
3050
|
const allItems = yLines.flat();
|
|
2843
3051
|
if (allItems.length === 0) return null;
|
|
2844
|
-
const pageWidth =
|
|
3052
|
+
const pageWidth = _chunk62IU4NV3cjs.safeMax.call(void 0, allItems.map((i) => i.x + i.w)) - _chunk62IU4NV3cjs.safeMin.call(void 0, allItems.map((i) => i.x));
|
|
2845
3053
|
if (pageWidth < 100) return null;
|
|
2846
3054
|
let bigoLineIdx = -1;
|
|
2847
3055
|
for (let i = 0; i < yLines.length; i++) {
|
|
@@ -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
|
|
3074
|
-
if (
|
|
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
|
|
3119
|
-
if (
|
|
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
|
|
3131
|
-
if (
|
|
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
|
-
|
|
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
|
|
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
|
|
3202
|
-
if (
|
|
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") : _nullishCoalesce(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
|
|
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 = _nullishCoalesce(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
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
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 (
|
|
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 = [];
|
|
@@ -3419,7 +3674,7 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
|
|
|
3419
3674
|
if (gutterX !== null) {
|
|
3420
3675
|
const gx = gutterX;
|
|
3421
3676
|
const allY = remaining.map((i) => i.y);
|
|
3422
|
-
const pageH =
|
|
3677
|
+
const pageH = _chunk62IU4NV3cjs.safeMax.call(void 0, allY) - _chunk62IU4NV3cjs.safeMin.call(void 0, allY);
|
|
3423
3678
|
const gapThreshold = Math.max(15, pageH * 0.03);
|
|
3424
3679
|
const sides = [
|
|
3425
3680
|
remaining.filter((i) => i.x + i.w <= gx),
|
|
@@ -3439,7 +3694,7 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
|
|
|
3439
3694
|
finalTextBlocks = detectListBlocks(textBlocks);
|
|
3440
3695
|
} else {
|
|
3441
3696
|
const allY = remaining.map((i) => i.y);
|
|
3442
|
-
const pageH =
|
|
3697
|
+
const pageH = _chunk62IU4NV3cjs.safeMax.call(void 0, allY) - _chunk62IU4NV3cjs.safeMin.call(void 0, allY);
|
|
3443
3698
|
const groups = xyCutOrder(remaining, Math.max(15, pageH * 0.03));
|
|
3444
3699
|
const textBlocks = [];
|
|
3445
3700
|
for (const group of groups) {
|
|
@@ -3647,7 +3902,7 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
|
|
|
3647
3902
|
blocks.push({ type: "paragraph", text: tableText, pageNumber: pageNum, bbox, style: dominantStyle(items) });
|
|
3648
3903
|
} else {
|
|
3649
3904
|
const allY = items.map((i) => i.y);
|
|
3650
|
-
const pageHeight =
|
|
3905
|
+
const pageHeight = _chunk62IU4NV3cjs.safeMax.call(void 0, allY) - _chunk62IU4NV3cjs.safeMin.call(void 0, allY);
|
|
3651
3906
|
const gapThreshold = Math.max(15, pageHeight * 0.03);
|
|
3652
3907
|
const orderedGroups = proseCutX !== null ? splitTwoColumnProse(items, proseCutX) : xyCutOrder(items, gapThreshold);
|
|
3653
3908
|
for (const group of orderedGroups) {
|
|
@@ -3686,4 +3941,4 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
|
|
|
3686
3941
|
|
|
3687
3942
|
|
|
3688
3943
|
exports.extractImageRegions = extractImageRegions; exports.filterHiddenText = filterHiddenText; exports.collapseEvenSpacing = collapseEvenSpacing; exports.normalizeItems = normalizeItems; exports.computeMedianFontSizeFromFreq = computeMedianFontSizeFromFreq; exports.detectHeadings = detectHeadings; exports.detectMarkerHeadings = detectMarkerHeadings; exports.detectTableCaptions = detectTableCaptions; exports.detectKoreanListBlocks = detectKoreanListBlocks; exports.removeHeaderFooterBlocks = removeHeaderFooterBlocks; exports.extractPageBlocksWithLines = extractPageBlocksWithLines; exports.mergeCrossPageTables = mergeCrossPageTables;
|
|
3689
|
-
//# sourceMappingURL=chunk-
|
|
3944
|
+
//# sourceMappingURL=chunk-ONNAHSPV.cjs.map
|