kordoc 4.16.2 → 4.17.0
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 +14 -13
- package/dist/{-4G6MA4X6.js → -PRAKO6M4.js} +11 -11
- package/dist/{chunk-AUWGDP4G.js → chunk-2KF5WZCR.js} +2 -2
- package/dist/{chunk-UTP2WCHS.js → chunk-4GSF2R7T.js} +4 -4
- package/dist/{chunk-TXUKTOG2.js → chunk-4XVNQAK5.js} +219 -23
- package/dist/chunk-4XVNQAK5.js.map +1 -0
- package/dist/chunk-5CDUL6PH.js +250 -0
- package/dist/chunk-5CDUL6PH.js.map +1 -0
- package/dist/{chunk-4VODJKFL.js → chunk-6RGGYQQC.js} +3 -3
- package/dist/{chunk-DES2LGFZ.js → chunk-A55JGNKD.js} +2 -2
- package/dist/chunk-AKB72TEH.cjs +248 -0
- package/dist/chunk-AKB72TEH.cjs.map +1 -0
- package/dist/{chunk-LEIAEWZ7.js → chunk-BFT5IM2R.js} +2 -2
- package/dist/{chunk-KIOQ4N37.js → chunk-BLPR4HRF.js} +2 -2
- package/dist/{chunk-JELRWAZC.js → chunk-BZG7K44Z.js} +2 -2
- package/dist/{chunk-F4NRLLY4.js → chunk-EFO6JZY6.js} +2 -2
- package/dist/chunk-GS7T56RP.cjs.map +1 -1
- package/dist/{chunk-JFLAM3MM.js → chunk-I5DJOP62.js} +2 -2
- package/dist/chunk-I5DJOP62.js.map +1 -0
- package/dist/chunk-J55UQC5H.cjs.map +1 -1
- package/dist/{chunk-QOCS7W7R.js → chunk-K2VYABZ3.js} +86 -43
- package/dist/chunk-K2VYABZ3.js.map +1 -0
- package/dist/chunk-MJBCXW5R.js +248 -0
- package/dist/chunk-MJBCXW5R.js.map +1 -0
- package/dist/{chunk-MLIS253L.js → chunk-ML4NHUR7.js} +2 -2
- package/dist/{chunk-GO5IFOUF.js → chunk-N6V7LQBL.js} +2 -2
- package/dist/{chunk-FKUDAIJI.cjs → chunk-O7OUX6NU.cjs} +12 -12
- package/dist/chunk-O7OUX6NU.cjs.map +1 -0
- package/dist/{chunk-S2PL227Q.js → chunk-PHID6WNG.js} +2 -2
- package/dist/{chunk-IQGIT2VX.js → chunk-QJWVMPB6.js} +34 -17
- package/dist/chunk-QJWVMPB6.js.map +1 -0
- package/dist/{chunk-STM3ORY7.cjs → chunk-QNJLLF4J.cjs} +2 -2
- package/dist/chunk-QNJLLF4J.cjs.map +1 -0
- package/dist/{chunk-FSDJLAOW.js → chunk-QPJXYJIK.js} +55 -1
- package/dist/chunk-QPJXYJIK.js.map +1 -0
- package/dist/{chunk-XTFN5WKS.cjs → chunk-R2BUANHQ.cjs} +6 -6
- package/dist/chunk-R2BUANHQ.cjs.map +1 -0
- package/dist/{chunk-OXLPVQYK.js → chunk-TDQ6XDB3.js} +3 -3
- package/dist/{chunk-SFEQYKYJ.js → chunk-WN6OD2CQ.js} +218 -22
- package/dist/chunk-WN6OD2CQ.js.map +1 -0
- package/dist/{chunk-5KS5PWJR.js → chunk-WY5JAR4O.js} +2 -2
- package/dist/{chunk-CEIATRDW.cjs → chunk-WYON5ANU.cjs} +3 -3
- package/dist/chunk-WYON5ANU.cjs.map +1 -0
- package/dist/{chunk-WDQTFAXY.cjs → chunk-XEPKOC2O.cjs} +240 -44
- package/dist/chunk-XEPKOC2O.cjs.map +1 -0
- package/dist/{chunk-7KNGSQU7.js → chunk-YZ5HHS6A.js} +2 -2
- package/dist/{chunk-P6ZDXTV6.js → chunk-ZF6KHPB7.js} +2 -2
- package/dist/chunks-YBFBLJ4G.js +10 -0
- package/dist/cli.js +36 -54
- package/dist/cli.js.map +1 -1
- package/dist/{formula-NARUOXRX.js → formula-7MMFBRGJ.js} +4 -4
- package/dist/{formula-WIMV5TUX.cjs → formula-ECNOZT36.cjs} +9 -9
- package/dist/formula-ECNOZT36.cjs.map +1 -0
- package/dist/{formula-EPKLPDU7.js → formula-SHBXRXOJ.js} +3 -3
- package/dist/{image-ocr-3WJ4QH3T.js → image-ocr-P6ECJCT2.js} +8 -8
- package/dist/{image-ocr-5BUJQ4TK.js → image-ocr-QCT3A7X5.js} +6 -6
- package/dist/{image-ocr-AXWXR6JV.cjs → image-ocr-VUDSP2B4.cjs} +15 -15
- package/dist/image-ocr-VUDSP2B4.cjs.map +1 -0
- package/dist/index.cjs +768 -710
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +106 -48
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +38 -43
- package/dist/mcp.js.map +1 -1
- package/dist/{model-bundle-IMBW7D2Z.js → model-bundle-OUHGCEZY.js} +5 -5
- package/dist/{models-SY75IBOE.js → models-6D6LMOTH.js} +5 -5
- package/dist/page-range-QHHFTL7X.cjs.map +1 -1
- package/dist/{parser-ZQM3664Z.js → parser-CTRB7PKD.js} +257 -46
- package/dist/parser-CTRB7PKD.js.map +1 -0
- package/dist/{parser-2LU4EVU3.cjs → parser-RQ4PJRTJ.cjs} +411 -200
- package/dist/parser-RQ4PJRTJ.cjs.map +1 -0
- package/dist/{parser-N6476XAC.js → parser-ZPRQ3SSU.js} +260 -49
- package/dist/parser-ZPRQ3SSU.js.map +1 -0
- package/dist/pdf-ocr-462ZFSHX.js +15 -0
- package/dist/pdf-ocr-L35FQYGP.js +18 -0
- package/dist/pdf-ocr-STK5EQFF.cjs +16 -0
- package/dist/pdf-ocr-STK5EQFF.cjs.map +1 -0
- package/dist/{profile-io-GJPKCYPT.js → profile-io-YZUW6MAN.js} +3 -3
- package/dist/{rasterize-UOALJQDS.js → rasterize-OUR2QJXX.js} +3 -3
- package/dist/{redact-doc-22SYW3KH.js → redact-doc-4OQKG4SM.js} +11 -11
- package/dist/{render-MJ4H3R23.js → render-XNO6PZJO.js} +7 -7
- package/dist/seal-CJ7C44JN.js +10 -0
- package/dist/{setup-2URYVUEO.js → setup-UU3EIHNI.js} +3 -3
- package/dist/visual-QRMRFPUK.js +20 -0
- package/dist/{watch-ALXZGTOB.js → watch-SR6Q5SQN.js} +12 -12
- package/package.json +2 -2
- package/dist/chunk-3IB7LBHC.js +0 -57
- package/dist/chunk-3IB7LBHC.js.map +0 -1
- package/dist/chunk-62W7QCEX.cjs +0 -57
- package/dist/chunk-62W7QCEX.cjs.map +0 -1
- package/dist/chunk-CEIATRDW.cjs.map +0 -1
- package/dist/chunk-FKUDAIJI.cjs.map +0 -1
- package/dist/chunk-FSDJLAOW.js.map +0 -1
- package/dist/chunk-IQGIT2VX.js.map +0 -1
- package/dist/chunk-J3IF6KGW.js +0 -59
- package/dist/chunk-J3IF6KGW.js.map +0 -1
- package/dist/chunk-JFLAM3MM.js.map +0 -1
- package/dist/chunk-QOCS7W7R.js.map +0 -1
- package/dist/chunk-SFEQYKYJ.js.map +0 -1
- package/dist/chunk-STM3ORY7.cjs.map +0 -1
- package/dist/chunk-TXUKTOG2.js.map +0 -1
- package/dist/chunk-WDQTFAXY.cjs.map +0 -1
- package/dist/chunk-XTFN5WKS.cjs.map +0 -1
- package/dist/chunks-NUNIKS2J.js +0 -10
- package/dist/formula-WIMV5TUX.cjs.map +0 -1
- package/dist/image-ocr-AXWXR6JV.cjs.map +0 -1
- package/dist/parser-2LU4EVU3.cjs.map +0 -1
- package/dist/parser-N6476XAC.js.map +0 -1
- package/dist/parser-ZQM3664Z.js.map +0 -1
- package/dist/pdf-ocr-6DEE23IP.js +0 -15
- package/dist/pdf-ocr-GHEJVPX2.cjs +0 -16
- package/dist/pdf-ocr-GHEJVPX2.cjs.map +0 -1
- package/dist/pdf-ocr-MQTWODVU.js +0 -18
- package/dist/seal-XWMRUTI4.js +0 -10
- package/dist/visual-USPS4QRC.js +0 -20
- /package/dist/{-4G6MA4X6.js.map → -PRAKO6M4.js.map} +0 -0
- /package/dist/{chunk-AUWGDP4G.js.map → chunk-2KF5WZCR.js.map} +0 -0
- /package/dist/{chunk-UTP2WCHS.js.map → chunk-4GSF2R7T.js.map} +0 -0
- /package/dist/{chunk-4VODJKFL.js.map → chunk-6RGGYQQC.js.map} +0 -0
- /package/dist/{chunk-DES2LGFZ.js.map → chunk-A55JGNKD.js.map} +0 -0
- /package/dist/{chunk-LEIAEWZ7.js.map → chunk-BFT5IM2R.js.map} +0 -0
- /package/dist/{chunk-KIOQ4N37.js.map → chunk-BLPR4HRF.js.map} +0 -0
- /package/dist/{chunk-JELRWAZC.js.map → chunk-BZG7K44Z.js.map} +0 -0
- /package/dist/{chunk-F4NRLLY4.js.map → chunk-EFO6JZY6.js.map} +0 -0
- /package/dist/{chunk-MLIS253L.js.map → chunk-ML4NHUR7.js.map} +0 -0
- /package/dist/{chunk-GO5IFOUF.js.map → chunk-N6V7LQBL.js.map} +0 -0
- /package/dist/{chunk-S2PL227Q.js.map → chunk-PHID6WNG.js.map} +0 -0
- /package/dist/{chunk-OXLPVQYK.js.map → chunk-TDQ6XDB3.js.map} +0 -0
- /package/dist/{chunk-5KS5PWJR.js.map → chunk-WY5JAR4O.js.map} +0 -0
- /package/dist/{chunk-7KNGSQU7.js.map → chunk-YZ5HHS6A.js.map} +0 -0
- /package/dist/{chunk-P6ZDXTV6.js.map → chunk-ZF6KHPB7.js.map} +0 -0
- /package/dist/{chunks-NUNIKS2J.js.map → chunks-YBFBLJ4G.js.map} +0 -0
- /package/dist/{formula-NARUOXRX.js.map → formula-7MMFBRGJ.js.map} +0 -0
- /package/dist/{formula-EPKLPDU7.js.map → formula-SHBXRXOJ.js.map} +0 -0
- /package/dist/{image-ocr-3WJ4QH3T.js.map → image-ocr-P6ECJCT2.js.map} +0 -0
- /package/dist/{image-ocr-5BUJQ4TK.js.map → image-ocr-QCT3A7X5.js.map} +0 -0
- /package/dist/{model-bundle-IMBW7D2Z.js.map → model-bundle-OUHGCEZY.js.map} +0 -0
- /package/dist/{models-SY75IBOE.js.map → models-6D6LMOTH.js.map} +0 -0
- /package/dist/{pdf-ocr-6DEE23IP.js.map → pdf-ocr-462ZFSHX.js.map} +0 -0
- /package/dist/{pdf-ocr-MQTWODVU.js.map → pdf-ocr-L35FQYGP.js.map} +0 -0
- /package/dist/{profile-io-GJPKCYPT.js.map → profile-io-YZUW6MAN.js.map} +0 -0
- /package/dist/{rasterize-UOALJQDS.js.map → rasterize-OUR2QJXX.js.map} +0 -0
- /package/dist/{redact-doc-22SYW3KH.js.map → redact-doc-4OQKG4SM.js.map} +0 -0
- /package/dist/{render-MJ4H3R23.js.map → render-XNO6PZJO.js.map} +0 -0
- /package/dist/{seal-XWMRUTI4.js.map → seal-CJ7C44JN.js.map} +0 -0
- /package/dist/{setup-2URYVUEO.js.map → setup-UU3EIHNI.js.map} +0 -0
- /package/dist/{visual-USPS4QRC.js.map → visual-QRMRFPUK.js.map} +0 -0
- /package/dist/{watch-ALXZGTOB.js.map → watch-SR6Q5SQN.js.map} +0 -0
|
@@ -6,7 +6,12 @@ import {
|
|
|
6
6
|
EMPTY_PARTS,
|
|
7
7
|
FILLER_CELLS,
|
|
8
8
|
IMAGE_CELLS,
|
|
9
|
+
NO_EDGES,
|
|
10
|
+
PART_COLXS,
|
|
11
|
+
ROW_RULES,
|
|
9
12
|
TABLE_COLXS,
|
|
13
|
+
TABLE_ROWYS,
|
|
14
|
+
TABLE_TAIL,
|
|
10
15
|
TOC_BLOCKS,
|
|
11
16
|
WrapLexicon,
|
|
12
17
|
collapseEvenSpacing,
|
|
@@ -24,6 +29,7 @@ import {
|
|
|
24
29
|
extractLines,
|
|
25
30
|
extractPageBlocksWithLines,
|
|
26
31
|
filterHiddenText,
|
|
32
|
+
joinCellEdges,
|
|
27
33
|
joinPageBreakWraps,
|
|
28
34
|
latinSoftWrap,
|
|
29
35
|
mergeStackedHeadingLines,
|
|
@@ -33,21 +39,24 @@ import {
|
|
|
33
39
|
startsNewItem,
|
|
34
40
|
trimTrailingEmptyTableCols,
|
|
35
41
|
wrapJoiner
|
|
36
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-WN6OD2CQ.js";
|
|
37
43
|
import {
|
|
38
44
|
ocrModelsCached
|
|
39
|
-
} from "./chunk-
|
|
40
|
-
import "./chunk-
|
|
41
|
-
import "./chunk-
|
|
45
|
+
} from "./chunk-A55JGNKD.js";
|
|
46
|
+
import "./chunk-BLPR4HRF.js";
|
|
47
|
+
import "./chunk-BZG7K44Z.js";
|
|
42
48
|
import {
|
|
43
49
|
blocksToPages
|
|
44
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-2KF5WZCR.js";
|
|
45
51
|
import {
|
|
46
52
|
encodePng
|
|
47
53
|
} from "./chunk-7FCNOKOR.js";
|
|
48
54
|
import {
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
CELL_EDGES,
|
|
56
|
+
CONTENT_CELLS,
|
|
57
|
+
stripScriptTags,
|
|
58
|
+
unframeLayoutTables
|
|
59
|
+
} from "./chunk-5CDUL6PH.js";
|
|
51
60
|
import {
|
|
52
61
|
hasRequestedPagesAfter,
|
|
53
62
|
parsePageRange
|
|
@@ -56,11 +65,11 @@ import {
|
|
|
56
65
|
WINGDINGS,
|
|
57
66
|
blocksToMarkdown,
|
|
58
67
|
escapeLiteralDollar
|
|
59
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-BFT5IM2R.js";
|
|
60
69
|
import {
|
|
61
70
|
KordocError,
|
|
62
71
|
sanitizeHref
|
|
63
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-ZF6KHPB7.js";
|
|
64
73
|
|
|
65
74
|
// src/pdf/ocr-region-merge.ts
|
|
66
75
|
function mergeOcrImageRegions(blocks, page, regions, ocrBlocks) {
|
|
@@ -681,6 +690,7 @@ function splitContactTables(blocks) {
|
|
|
681
690
|
|
|
682
691
|
// src/pdf/table-parts.ts
|
|
683
692
|
var PART_COL_TOL = 1;
|
|
693
|
+
var PART_COL_SNAP = 0.3;
|
|
684
694
|
function anchorsOf(table) {
|
|
685
695
|
const out = [];
|
|
686
696
|
const covered = /* @__PURE__ */ new Set();
|
|
@@ -698,9 +708,22 @@ function anchorsOf(table) {
|
|
|
698
708
|
return out;
|
|
699
709
|
}
|
|
700
710
|
function unionCoords(a, b) {
|
|
711
|
+
const drift = a.length === b.length && a.every((x, i) => Math.abs(x - b[i]) <= PART_COL_TOL);
|
|
712
|
+
const tol = drift ? PART_COL_TOL : PART_COL_SNAP;
|
|
713
|
+
const pairs = [];
|
|
714
|
+
for (const v of b) for (const x of a) if (Math.abs(x - v) <= tol) pairs.push([Math.abs(x - v), v, x]);
|
|
715
|
+
pairs.sort((p, q) => p[0] - q[0]);
|
|
716
|
+
const map = /* @__PURE__ */ new Map(), taken = /* @__PURE__ */ new Set();
|
|
717
|
+
for (const [, v, x] of pairs) if (!map.has(v) && !taken.has(x)) {
|
|
718
|
+
map.set(v, x);
|
|
719
|
+
taken.add(x);
|
|
720
|
+
}
|
|
701
721
|
const out = [...a];
|
|
702
|
-
for (const v of b) if (!
|
|
703
|
-
|
|
722
|
+
for (const v of b) if (!map.has(v)) {
|
|
723
|
+
map.set(v, v);
|
|
724
|
+
out.push(v);
|
|
725
|
+
}
|
|
726
|
+
return { U: out.sort((x, y) => x - y), map };
|
|
704
727
|
}
|
|
705
728
|
var indexOf = (coords, x) => {
|
|
706
729
|
let best = -1, bestD = Infinity;
|
|
@@ -717,18 +740,31 @@ var rowText = (anchors, r) => anchors.filter((a) => a.r === r).map((a) => a.cell
|
|
|
717
740
|
var hasText = (t) => t.replace(/\|/g, "") !== "";
|
|
718
741
|
function joinSplitParts(prev, pcx, curr, ccx, dx = 0, prevBottom, lex) {
|
|
719
742
|
if (pcx.length !== prev.cols + 1 || ccx.length !== curr.cols + 1) return null;
|
|
720
|
-
const U = unionCoords(pcx, ccx);
|
|
743
|
+
const { U, map } = unionCoords(pcx, ccx);
|
|
744
|
+
const cxU = ccx.map((v) => map.get(v) ?? v);
|
|
721
745
|
const cols = U.length - 1;
|
|
722
746
|
if (cols < 1) return null;
|
|
723
747
|
const pa = anchorsOf(prev), ca = anchorsOf(curr);
|
|
724
|
-
let skip = 0;
|
|
748
|
+
let skip = 0, head = 0;
|
|
725
749
|
while (skip < Math.min(3, curr.rows - 1, prev.rows) && rowText(ca, skip) !== "" && rowText(ca, skip) === rowText(pa, skip)) skip++;
|
|
726
750
|
for (let h = 1; h <= 2 && !skip; h++) {
|
|
751
|
+
head = h;
|
|
727
752
|
while (skip < Math.min(3, curr.rows - 1, prev.rows - h) && hasText(rowText(ca, skip)) && rowText(ca, skip) === rowText(pa, h + skip)) skip++;
|
|
728
753
|
}
|
|
754
|
+
const sameSpans = (u, d) => {
|
|
755
|
+
if (u.length !== d.length || !u.length) return false;
|
|
756
|
+
const shift = pcx[u[u.length - 1].c + u[u.length - 1].cs] - ccx[d[d.length - 1].c + d[d.length - 1].cs];
|
|
757
|
+
return u.every((a, n) => Math.abs(pcx[a.c] - ccx[d[n].c] - shift) <= CONTINUATION_COL_TOL && Math.abs(pcx[a.c + a.cs] - ccx[d[n].c + d[n].cs] - shift) <= CONTINUATION_COL_TOL);
|
|
758
|
+
};
|
|
759
|
+
for (let k = 0; k < skip; k++) {
|
|
760
|
+
if (sameSpans(pa.filter((a) => a.r === head + k), ca.filter((a) => a.r === k))) continue;
|
|
761
|
+
if (hasText(rowText(ca, k))) return null;
|
|
762
|
+
skip = k;
|
|
763
|
+
}
|
|
729
764
|
const rows = prev.rows + curr.rows - skip;
|
|
730
765
|
const grid = Array.from({ length: rows }, () => Array.from({ length: cols }, () => ({ text: "", colSpan: 1, rowSpan: 1 })));
|
|
731
766
|
const owner = Array.from({ length: rows }, () => new Array(cols).fill(null));
|
|
767
|
+
let edged = false;
|
|
732
768
|
const place = (a, x, rowOff, shift = 0) => {
|
|
733
769
|
const c1 = indexOf(U, x[a.c]), c2 = indexOf(U, x[a.c + a.cs]);
|
|
734
770
|
if (c1 < 0 || c2 <= c1) return false;
|
|
@@ -741,12 +777,17 @@ function joinSplitParts(prev, pcx, curr, ccx, dx = 0, prevBottom, lex) {
|
|
|
741
777
|
const lines = CELL_LINES.get(a.cell);
|
|
742
778
|
if (lines) CELL_LINES.set(grid[r][c1], shift ? lines.map((l) => ({ ...l, l: l.l + shift, r: l.r + shift })) : lines);
|
|
743
779
|
if (IMAGE_CELLS.has(a.cell)) IMAGE_CELLS.add(grid[r][c1]);
|
|
780
|
+
const edges = CELL_EDGES.get(a.cell);
|
|
781
|
+
if (edges) {
|
|
782
|
+
CELL_EDGES.set(grid[r][c1], edges);
|
|
783
|
+
edged = true;
|
|
784
|
+
}
|
|
744
785
|
return true;
|
|
745
786
|
};
|
|
746
787
|
for (const a of pa) if (!FILLER_CELLS.has(a.cell) && !place(a, pcx, 0)) return null;
|
|
747
788
|
for (const a of ca) {
|
|
748
789
|
if (a.r < skip || FILLER_CELLS.has(a.cell)) continue;
|
|
749
|
-
if (!place(a,
|
|
790
|
+
if (!place(a, cxU, prev.rows - skip, dx)) return null;
|
|
750
791
|
}
|
|
751
792
|
const first = prev.rows;
|
|
752
793
|
for (let c = 0; c < cols; c++) {
|
|
@@ -770,12 +811,32 @@ function joinSplitParts(prev, pcx, curr, ccx, dx = 0, prevBottom, lex) {
|
|
|
770
811
|
for (let rr = above.r; rr < above.r + newRs; rr++) for (let dc = above.c; dc < above.c + above.cs; dc++) owner[rr][dc] = grown;
|
|
771
812
|
}
|
|
772
813
|
for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) if (owner[r][c] === null) FILLER_CELLS.add(grid[r][c]);
|
|
814
|
+
if (edged) {
|
|
815
|
+
for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) if (owner[r][c] === null) CELL_EDGES.set(grid[r][c], NO_EDGES);
|
|
816
|
+
}
|
|
817
|
+
for (let c = 0; c < cols && U[c + 1] <= pcx[0] + PART_COL_TOL; c++) {
|
|
818
|
+
let r = prev.rows;
|
|
819
|
+
while (r < rows && owner[r][c] === null) r++;
|
|
820
|
+
const through = { r: 0, c, rs: r, cs: 1, cell: grid[0][c] };
|
|
821
|
+
for (let rr = 0; rr < r; rr++) owner[rr][c] = through;
|
|
822
|
+
}
|
|
773
823
|
const table = { rows, cols, cells: grid, hasHeader: prev.hasHeader, ...prev.caption ? { caption: prev.caption } : {} };
|
|
774
|
-
|
|
775
|
-
|
|
824
|
+
const pr = ROW_RULES.get(prev), cr = ROW_RULES.get(curr);
|
|
825
|
+
const shifted = dx !== 0;
|
|
826
|
+
const cut = {
|
|
827
|
+
open: !!pr && !!cr && !pr.bottom && !cr.top && pr.innerOpen + cr.innerOpen === 0 && pr.innerRuled + cr.innerRuled > 0,
|
|
828
|
+
ruled: !!pr && !!cr && pr.bottom && cr.top,
|
|
829
|
+
list: !shifted ? "any" : skip > 0 && ca.filter((a) => a.r < skip && a.cell.text.trim()).length < 2 ? "none" : "multi"
|
|
830
|
+
};
|
|
831
|
+
let split = rows > prev.rows && mergeSplitRow(table, owner, prev.rows, U, false, cut);
|
|
832
|
+
if (rows > prev.rows && !split && prevBottom !== void 0 && mergeStraddlingCells(table, owner, prev.rows, prevBottom, lex, U)) split = mergeSplitRow(table, owner, prev.rows, U, true, { ...cut, open: false });
|
|
833
|
+
if (pr && cr) {
|
|
834
|
+
const cutRuled = pr.bottom || cr.top;
|
|
835
|
+
ROW_RULES.set(table, { top: pr.top, bottom: cr.bottom, innerRuled: pr.innerRuled + cr.innerRuled + (!split && cutRuled ? 1 : 0), innerOpen: pr.innerOpen + cr.innerOpen + (!split && !cutRuled ? 1 : 0) });
|
|
836
|
+
}
|
|
776
837
|
return { table, colXs: U, split, header: ca.filter((a) => a.r < skip && a.cell.text.trim()).length >= 2 };
|
|
777
838
|
}
|
|
778
|
-
function mergeStraddlingCells(table, owner, first, prevBottom, lex) {
|
|
839
|
+
function mergeStraddlingCells(table, owner, first, prevBottom, lex, colXs) {
|
|
779
840
|
const last = first - 1;
|
|
780
841
|
const straddles = owner[first].some((o, c) => o !== null && o === owner[last][c]);
|
|
781
842
|
let firstNew = table.cols;
|
|
@@ -799,6 +860,19 @@ function mergeStraddlingCells(table, owner, first, prevBottom, lex) {
|
|
|
799
860
|
const tail = table.cells[u.r][u.c].text.trim().split(/\s+/).pop() ?? "", head = table.cells[first][d.c].text.trim().split(/\s+/)[0] ?? "";
|
|
800
861
|
if (/^[가-힣]{2,}$/.test(tail) && /^[가-힣]{2,}/.test(head) && lex.evidence2(tail, head) === "") midWord = true;
|
|
801
862
|
}
|
|
863
|
+
const crossed = /* @__PURE__ */ new Set();
|
|
864
|
+
const shape = (u, d) => `${u.r}:${u.rs}:${d.rs}`;
|
|
865
|
+
if (straddles && colXs) for (let c = 0; c < table.cols; ) {
|
|
866
|
+
const u = owner[last][c], d = owner[first][c];
|
|
867
|
+
if (!u) {
|
|
868
|
+
c++;
|
|
869
|
+
continue;
|
|
870
|
+
}
|
|
871
|
+
c = u.c + u.cs;
|
|
872
|
+
if (!d || d === u || u.r + u.rs - 1 !== last || d.r !== first || d.c !== u.c || d.cs !== u.cs || u.rs < 2) continue;
|
|
873
|
+
const a = table.cells[u.r][u.c], b = table.cells[first][d.c];
|
|
874
|
+
if (hasContent(a) && hasContent(b) && continuesAcross(a, b, colXs[u.c], colXs[u.c + u.cs])) crossed.add(shape(u, d));
|
|
875
|
+
}
|
|
802
876
|
let merged = false;
|
|
803
877
|
for (let c = 0; c < table.cols; ) {
|
|
804
878
|
const u = owner[last][c], d = owner[first][c];
|
|
@@ -809,13 +883,16 @@ function mergeStraddlingCells(table, owner, first, prevBottom, lex) {
|
|
|
809
883
|
c = u.c + u.cs;
|
|
810
884
|
if (!d || d === u || u.r + u.rs - 1 !== last || d.r !== first || d.c !== u.c || d.cs !== u.cs) continue;
|
|
811
885
|
const a = table.cells[u.r][u.c], b = table.cells[first][d.c];
|
|
812
|
-
if (!(u.rs >= 2 && u.c + u.cs <= firstNew && hasContent(a) && !hasContent(b))) {
|
|
886
|
+
if (!crossed.has(shape(u, d)) && !(u.rs >= 2 && u.c + u.cs <= firstNew && hasContent(a) && !hasContent(b))) {
|
|
813
887
|
if (!straddles && !midWord) continue;
|
|
814
888
|
if (u.r >= last && d.rs < 2) continue;
|
|
815
889
|
const U = CELL_LINES.get(a);
|
|
816
|
-
if (!U?.length ||
|
|
817
|
-
|
|
818
|
-
|
|
890
|
+
if (!U?.length || !hasContent(b)) continue;
|
|
891
|
+
if (!(straddles && filledToBottom(U, prevBottom) && clauseContinues(a, b))) {
|
|
892
|
+
if (U.length > STRADDLE_MAX_LINES) continue;
|
|
893
|
+
const lu = U[U.length - 1];
|
|
894
|
+
if (!midWord && lu.y - prevBottom > (u.r >= last ? STRADDLE_BOTTOM_ONE_ROW : STRADDLE_BOTTOM) * (lu.h || 10)) continue;
|
|
895
|
+
}
|
|
819
896
|
}
|
|
820
897
|
appendCell(a, b);
|
|
821
898
|
a.rowSpan = first + d.rs - u.r;
|
|
@@ -826,6 +903,11 @@ function mergeStraddlingCells(table, owner, first, prevBottom, lex) {
|
|
|
826
903
|
}
|
|
827
904
|
return merged;
|
|
828
905
|
}
|
|
906
|
+
function filledToBottom(U, bottom) {
|
|
907
|
+
if (U.length < 2) return false;
|
|
908
|
+
const lu = U[U.length - 1];
|
|
909
|
+
return lu.y - bottom < (U[0].y - lu.y) / (U.length - 1) + FILL_SLACK * (lu.h || 10);
|
|
910
|
+
}
|
|
829
911
|
var FULL_LINE_TOL = 1;
|
|
830
912
|
var FULL_LINE_MIN_FRAC = 0.5;
|
|
831
913
|
var FULL_LINE_EDGE_MIN = 12;
|
|
@@ -834,6 +916,7 @@ var SHORT_LINE_GAP = 1.5;
|
|
|
834
916
|
var STRADDLE_MAX_LINES = 3;
|
|
835
917
|
var STRADDLE_BOTTOM = 1.2;
|
|
836
918
|
var STRADDLE_BOTTOM_ONE_ROW = 0.55;
|
|
919
|
+
var FILL_SLACK = 0.5;
|
|
837
920
|
var CARRIED_MIN_COL_W = 4;
|
|
838
921
|
var LABEL_ROOM = 1.5;
|
|
839
922
|
var HANGING_MIN = 0.5;
|
|
@@ -855,10 +938,16 @@ function continuesAcross(u, d, x1, x2) {
|
|
|
855
938
|
maxR = Math.max(maxR, x2 - (minL - x1));
|
|
856
939
|
if (maxR - last.r > FULL_LINE_TOL * fs) return false;
|
|
857
940
|
if (U.length === 1 && x2 - last.r > Math.max(FULL_LINE_EDGE_MIN, SINGLE_LINE_WORD_GAP * fs)) return false;
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
const
|
|
861
|
-
|
|
941
|
+
const indented = last.l - minL >= HANGING_MIN * fs;
|
|
942
|
+
if (last.r - last.l < FULL_LINE_MIN_FRAC * (indented ? x2 - last.l : x2 - x1)) return false;
|
|
943
|
+
const newItem = startsNewItem(u.text, d.text);
|
|
944
|
+
const all = D.length ? U.concat(D) : U;
|
|
945
|
+
const leftAligned = (l) => maxR - l.r > SHORT_LINE_GAP * fs && (l.l - minL <= fs || !newItem && all.some((o) => o !== l && Math.abs(o.l - l.l) <= HANGING_TOL && Math.abs(o.r - l.r) >= HANGING_MIN * fs));
|
|
946
|
+
const hanging = U.length >= 2 && U.every((l) => maxR - l.r <= FULL_LINE_TOL * fs) && indented && Math.abs(D[0].l - last.l) <= HANGING_TOL;
|
|
947
|
+
const hangingHead = !indented && D.length >= 2 && D[0].l - last.l >= HANGING_MIN * fs && maxR - D[0].r <= FULL_LINE_TOL * fs && D.every((l) => Math.abs(l.l - D[0].l) <= HANGING_TOL);
|
|
948
|
+
const d0 = D[0];
|
|
949
|
+
const hangStart = U.length === 1 && !newItem && d0.l - last.l >= HANGING_MIN * fs && D.every((l) => l.l >= d0.l - HANGING_TOL) && (Math.abs(d0.r - last.r) <= HANGING_TOL && d0.r - d0.l >= FULL_LINE_MIN_FRAC * (x2 - x1) || last.r - d0.r > SHORT_LINE_GAP * fs && Math.abs(d0.l + d0.r - last.l - last.r) / 2 >= HANGING_MIN * fs);
|
|
950
|
+
return U.some(leftAligned) || D.some(leftAligned) || hanging || hangingHead || hangStart;
|
|
862
951
|
}
|
|
863
952
|
var OUTLINE_HEAD = /^[□■]\s*\S/;
|
|
864
953
|
var OUTLINE_ITEM = /^[ㅇ○◦\-‐–·․‧※*]\s*\S/;
|
|
@@ -867,14 +956,19 @@ function outlineContinues(u, d) {
|
|
|
867
956
|
const D = d.text.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
868
957
|
return U.length >= 2 && D.length >= 1 && U.some((l) => OUTLINE_HEAD.test(l)) && OUTLINE_ITEM.test(D[0]);
|
|
869
958
|
}
|
|
870
|
-
function lineEnded(c, x1, x2, next
|
|
959
|
+
function lineEnded(c, x1, x2, next) {
|
|
871
960
|
const L = CELL_LINES.get(c);
|
|
872
961
|
if (!L || L.length !== 1) return false;
|
|
873
962
|
const l = L[0], h = l.h || 10;
|
|
874
|
-
const
|
|
963
|
+
const d0 = next ? CELL_LINES.get(next)?.[0] : void 0;
|
|
964
|
+
if (d0 && d0.l - l.l >= HANGING_MIN * h) return false;
|
|
965
|
+
return x2 - l.r - (l.l - x1) >= Math.max(LABEL_ROOM, firstWordUnits(next?.text ?? "")) * h;
|
|
966
|
+
}
|
|
967
|
+
function firstWordUnits(text) {
|
|
968
|
+
const word = text.trim().replace(/^([(\[「『<〈])\s+/, "$1").split(/\s+/)[0] ?? "";
|
|
875
969
|
let units = 0;
|
|
876
970
|
for (const ch of word) units += /[가-힣\u3400-\u9fff]/.test(ch) ? 1 : 0.55;
|
|
877
|
-
return
|
|
971
|
+
return units;
|
|
878
972
|
}
|
|
879
973
|
function appendCell(a, b) {
|
|
880
974
|
if (a.blocks?.length || b.blocks?.length) {
|
|
@@ -882,6 +976,7 @@ function appendCell(a, b) {
|
|
|
882
976
|
a.blocks = [...asBlocks(a), ...asBlocks(b)];
|
|
883
977
|
}
|
|
884
978
|
if (b.text.trim()) a.text = a.text.trim() ? a.text + "\n" + b.text : b.text;
|
|
979
|
+
joinCellEdges(a, b);
|
|
885
980
|
}
|
|
886
981
|
var hasContent = (cell) => !!cell.text.trim() || !!cell.blocks?.length || IMAGE_CELLS.has(cell);
|
|
887
982
|
var CLAUSE_OPEN_ENDING = /(?:하는|되는|하고|하며|하여|되어|되고|되며|이며|으며|어야|아야|여야)$/;
|
|
@@ -895,11 +990,42 @@ function clauseContinues(u, d) {
|
|
|
895
990
|
const last = tail[tail.length - 1], before = tail[tail.length - 2];
|
|
896
991
|
return last === "\uC744" && batchim(before) || last === "\uB97C" && !batchim(before) || CLAUSE_OPEN_ENDING.test(tail);
|
|
897
992
|
}
|
|
993
|
+
function wordOverflows(u, d, x1, x2) {
|
|
994
|
+
const U = CELL_LINES.get(u);
|
|
995
|
+
if (!U?.length || startsNewItem(u.text, d.text)) return false;
|
|
996
|
+
const last = U[U.length - 1], units = firstWordUnits(d.text);
|
|
997
|
+
return units > 0 && last.r - last.l + units * (last.h || 10) > x2 - x1;
|
|
998
|
+
}
|
|
999
|
+
var KO_ORDER = "\uAC00\uB098\uB2E4\uB77C\uB9C8\uBC14\uC0AC\uC544\uC790\uCC28\uCE74\uD0C0\uD30C\uD558";
|
|
1000
|
+
function itemMark(line) {
|
|
1001
|
+
let m = /^(\d{1,2})([.)])(?!\d)/.exec(line);
|
|
1002
|
+
if (m) return { style: "1" + m[2], n: +m[1] };
|
|
1003
|
+
if (m = /^\((\d{1,2})\)/.exec(line)) return { style: "(1)", n: +m[1] };
|
|
1004
|
+
if ((m = /^([가-하])([.)])/.exec(line)) && KO_ORDER.includes(m[1])) return { style: "\uAC00" + m[2], n: KO_ORDER.indexOf(m[1]) };
|
|
1005
|
+
if ((m = /^\(([가-하])\)/.exec(line)) && KO_ORDER.includes(m[1])) return { style: "(\uAC00)", n: KO_ORDER.indexOf(m[1]) };
|
|
1006
|
+
if (m = /^[①-⑳]/.exec(line)) return { style: "\u2460", n: m[0].charCodeAt(0) };
|
|
1007
|
+
if (m = /^([A-Z])\.\s/.exec(line)) return { style: "A.", n: m[1].charCodeAt(0) };
|
|
1008
|
+
return null;
|
|
1009
|
+
}
|
|
1010
|
+
function listContinues(u, d, multi = false) {
|
|
1011
|
+
const head = itemMark(d.text.trim());
|
|
1012
|
+
if (!head) return false;
|
|
1013
|
+
const marks = u.text.split("\n").map((l) => itemMark(l.trim()));
|
|
1014
|
+
let last = -1, count = 0;
|
|
1015
|
+
marks.forEach((m, i) => {
|
|
1016
|
+
if (m?.style === head.style) {
|
|
1017
|
+
last = i;
|
|
1018
|
+
count++;
|
|
1019
|
+
}
|
|
1020
|
+
});
|
|
1021
|
+
return last >= 0 && marks[last].n + 1 === head.n && (count >= 2 || !multi && last > 0);
|
|
1022
|
+
}
|
|
898
1023
|
function outlineOnly(pairs, cell) {
|
|
899
1024
|
const filled = pairs.filter(([, d]) => hasContent(d.cell));
|
|
900
1025
|
return filled.length === 1 && outlineContinues(cell(filled[0][0]), cell(filled[0][1]));
|
|
901
1026
|
}
|
|
902
|
-
|
|
1027
|
+
var NO_CUT = { open: false, ruled: false, list: "any" };
|
|
1028
|
+
function mergeSplitRow(table, owner, first, colXs, textOnly = false, cut = NO_CUT) {
|
|
903
1029
|
const last = first - 1;
|
|
904
1030
|
const pairs = [];
|
|
905
1031
|
let carried = false;
|
|
@@ -912,19 +1038,30 @@ function mergeSplitRow(table, owner, first, colXs, textOnly = false) {
|
|
|
912
1038
|
}
|
|
913
1039
|
if (!a || !b) return false;
|
|
914
1040
|
if (a !== b) {
|
|
915
|
-
if (a.c !== b.c || a.cs !== b.cs || a.r + a.rs - 1 !== last || b.r !== first
|
|
1041
|
+
if (a.c !== b.c || a.cs !== b.cs || a.r + a.rs - 1 !== last || b.r !== first) return false;
|
|
1042
|
+
if (b.rs > 1 && (a.rs > 1 || !hasContent(a.cell))) return false;
|
|
916
1043
|
pairs.push([a, b]);
|
|
917
1044
|
} else if (a.r === last && a.rs === 2) carried = true;
|
|
918
1045
|
c = a.c + a.cs;
|
|
919
1046
|
}
|
|
920
|
-
const
|
|
1047
|
+
const newCell = pairs.some(([u, d]) => !hasContent(u.cell) && hasContent(d.cell));
|
|
921
1048
|
const cell = (a) => table.cells[a.r][a.c];
|
|
1049
|
+
const contentPairs = pairs.filter(([u, d]) => hasContent(u.cell) && hasContent(d.cell));
|
|
1050
|
+
const carriedSplit = !textOnly && carried && !newCell && (contentPairs.length <= 1 || contentPairs.every(([, d]) => d.rs > 1) || !cut.ruled && contentPairs.some(([u, d]) => wordOverflows(cell(u), cell(d), colXs[u.c], colXs[u.c + u.cs])));
|
|
922
1051
|
if (!carriedSplit) {
|
|
923
1052
|
const norm = (c) => c.text.replace(/\s+/g, "");
|
|
924
|
-
if (pairs.some(([u, d]) => hasContent(d.cell) && norm(cell(d)) !== norm(cell(u)) && lineEnded(cell(u), colXs[u.c], colXs[u.c + u.cs], cell(d)
|
|
925
|
-
|
|
1053
|
+
if (pairs.some(([u, d]) => hasContent(d.cell) && norm(cell(d)) !== norm(cell(u)) && lineEnded(cell(u), colXs[u.c], colXs[u.c + u.cs], cell(d)))) return false;
|
|
1054
|
+
const flows = ([u, d]) => continuesAcross(cell(u), cell(d), colXs[u.c], colXs[u.c + u.cs]) || clauseContinues(cell(u), cell(d));
|
|
1055
|
+
if (!(cut.open && !newCell)) {
|
|
1056
|
+
if (pairs.some((p) => p[1].rs > 1 && !flows(p))) return false;
|
|
1057
|
+
const one = pairs.filter(([, d]) => d.rs === 1);
|
|
1058
|
+
if (!outlineOnly(pairs, cell) && !one.some(flows) && (cut.list === "none" || !one.some(([u, d]) => listContinues(cell(u), cell(d), cut.list === "multi")))) return false;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
for (const [u, d] of pairs) {
|
|
1062
|
+
appendCell(table.cells[u.r][u.c], table.cells[d.r][d.c]);
|
|
1063
|
+
if (d.rs > 1) table.cells[u.r][u.c].rowSpan = u.rs + d.rs;
|
|
926
1064
|
}
|
|
927
|
-
for (const [u, d] of pairs) appendCell(table.cells[u.r][u.c], table.cells[d.r][d.c]);
|
|
928
1065
|
for (let r = 0; r < first; r++) for (let c = 0; c < table.cols; c++) {
|
|
929
1066
|
const o = owner[r][c];
|
|
930
1067
|
if (o && o.r === r && o.c === c && r + table.cells[r][c].rowSpan > first) table.cells[r][c].rowSpan--;
|
|
@@ -972,11 +1109,14 @@ function sameHeadShape(a, b) {
|
|
|
972
1109
|
function mergeCrossPageTables(blocks, pageHeights, lex) {
|
|
973
1110
|
mergeColumnFlow(blocks, pageHeights, lex);
|
|
974
1111
|
for (let i = blocks.length - 2; i >= 0; i--) {
|
|
975
|
-
const
|
|
976
|
-
if (
|
|
1112
|
+
const tail = tailOf(blocks[i]);
|
|
1113
|
+
if (tail.type !== "table" || !tail.table || !tail.bbox || !tail.pageNumber) continue;
|
|
977
1114
|
let j = i + 1;
|
|
978
|
-
|
|
1115
|
+
const skip = (b) => b.type !== "table" || [blocks[i], tail].some((t) => insideTable(b, t) || leftColumnOf(b, t));
|
|
1116
|
+
while (j < blocks.length && skip(blocks[j]) && (blocks[j].pageNumber ?? 0) <= tail.pageNumber + 1) j++;
|
|
979
1117
|
const curr = blocks[j];
|
|
1118
|
+
const prev = tail !== blocks[i] && curr?.pageNumber === tail.pageNumber ? blocks[i] : tail;
|
|
1119
|
+
if (!prev.table || !prev.bbox || !prev.pageNumber) continue;
|
|
980
1120
|
if (!curr || curr.type !== "table" || !curr.table || !curr.bbox || curr.pageNumber !== prev.pageNumber + 1) continue;
|
|
981
1121
|
if (startsWithUnitRow(prev.table) && startsWithUnitRow(curr.table)) continue;
|
|
982
1122
|
const joined = j === i + 1 || blocks.slice(i + 1, j).every((b) => besideOwn(b, prev, curr) || insideTable(b, prev)) ? looksContinued(prev, curr, pageHeights) && !restartsTable(blocks, i, curr.table, pageHeights) ? joinClipParts(prev, curr, pageHeights, lex) ?? false : null : null;
|
|
@@ -1059,24 +1199,36 @@ function joinClipParts(prev, curr, pageHeights, lex) {
|
|
|
1059
1199
|
if (!CLIP_TABLES.has(pt) || !CLIP_TABLES.has(ct)) return null;
|
|
1060
1200
|
const px = TABLE_COLXS.get(pt), cx = TABLE_COLXS.get(ct);
|
|
1061
1201
|
if (!px || !cx) return null;
|
|
1062
|
-
let xs = cx, shifted = false, dx = 0, foreign = false;
|
|
1202
|
+
let xs = cx, shifted = false, dx = 0, foreign = false, within = false;
|
|
1063
1203
|
if (!shiftedSame(px, cx, false)) {
|
|
1064
1204
|
if (!pageHeights?.get(prev.pageNumber) || !pageHeights?.get(curr.pageNumber)) return null;
|
|
1065
1205
|
dx = px[px.length - 1] - cx[cx.length - 1];
|
|
1066
|
-
|
|
1206
|
+
within = Math.abs(dx) > CONTINUATION_COL_TOL && cx.length >= 3 && cx.every((x) => px.some((p) => Math.abs(p - x) <= CONTINUATION_COL_TOL));
|
|
1207
|
+
if (Math.abs(dx) > CONTINUATION_COL_TOL && !within) {
|
|
1067
1208
|
xs = cx.map((x) => x + dx);
|
|
1068
1209
|
shifted = true;
|
|
1069
1210
|
} else dx = 0;
|
|
1070
|
-
if (!px.some((x) => Math.abs(x - xs[0]) <= CONTINUATION_COL_TOL)) return null;
|
|
1071
|
-
const
|
|
1072
|
-
|
|
1211
|
+
if (!px.some((x) => Math.abs(x - xs[0]) <= CONTINUATION_COL_TOL) && !prevLacksLeftCols(prev, px, xs, pageHeights)) return null;
|
|
1212
|
+
const unrelated = (b) => {
|
|
1213
|
+
const inner = b.slice(1, -1).map((x) => x + dx);
|
|
1214
|
+
return inner.length > 0 && !inner.some((x) => px.some((p) => Math.abs(p - x) <= CONTINUATION_COL_TOL));
|
|
1215
|
+
};
|
|
1216
|
+
foreign = unrelated(cx) && unrelated(PART_COLXS.get(ct) ?? cx) && (headingRow(ct.cells[0] ?? []) || px.length > FOREIGN_FIRST_ROW_CELLS && anchorsOf(ct).filter((a) => a.r === 0).length >= FOREIGN_FIRST_ROW_CELLS);
|
|
1073
1217
|
}
|
|
1074
1218
|
const res = joinSplitParts(pt, px, ct, xs, dx, prev.bbox?.y, lex);
|
|
1075
|
-
if (!res || (shifted || foreign) && !res.split && !res.header) return null;
|
|
1219
|
+
if (!res || (shifted || foreign || within) && !res.split && !res.header) return null;
|
|
1076
1220
|
TABLE_COLXS.set(res.table, res.colXs);
|
|
1221
|
+
const ys = TABLE_ROWYS.get(pt);
|
|
1222
|
+
if (ys) TABLE_ROWYS.set(res.table, ys);
|
|
1223
|
+
PART_COLXS.set(res.table, PART_COLXS.get(pt) ?? px);
|
|
1077
1224
|
CLIP_TABLES.add(res.table);
|
|
1078
1225
|
return res.table;
|
|
1079
1226
|
}
|
|
1227
|
+
function prevLacksLeftCols(prev, px, xs, pageHeights) {
|
|
1228
|
+
const ph = pageHeights?.get(prev.pageNumber);
|
|
1229
|
+
if (!ph || prev.bbox.y + prev.bbox.height < ph * (1 - PAGE_EDGE_BAND)) return false;
|
|
1230
|
+
return xs[0] < px[0] && xs.slice(1, -1).some((x) => Math.abs(x - px[0]) <= CONTINUATION_COL_TOL);
|
|
1231
|
+
}
|
|
1080
1232
|
function headingRow(row) {
|
|
1081
1233
|
const heads = row.map((c) => c.text.replace(/\s+/g, "")).filter(Boolean);
|
|
1082
1234
|
if (heads.length === 1) return heads[0].length <= 8 || /^[①-⑳❶-❿]/.test(heads[0]);
|
|
@@ -1085,13 +1237,36 @@ function headingRow(row) {
|
|
|
1085
1237
|
var ANNEX_HEAD_RE = /^\s*[<\[(【]?\s*(?:붙\s*임|참\s*고|별\s*첨|별\s*지|별\s*표|첨\s*부|부\s*록)(?:\s*\d|\s*$|\s*[>\])】])|^\s*■/;
|
|
1086
1238
|
function looksContinued(prev, curr, pageHeights) {
|
|
1087
1239
|
const ph = pageHeights?.get(prev.pageNumber), ch = pageHeights?.get(curr.pageNumber);
|
|
1088
|
-
if (ph && ch && (prev.bbox.y > ph * PAGE_EDGE_BAND || curr.bbox.y + curr.bbox.height < ch * (1 - PAGE_EDGE_BAND))) return false;
|
|
1240
|
+
if (ph && ch && (prev.bbox.y > ph * PAGE_EDGE_BAND && !pushedLead(prev, curr) || curr.bbox.y + curr.bbox.height < ch * (1 - PAGE_EDGE_BAND))) return false;
|
|
1089
1241
|
const firstRow = curr.table.cells[0] ?? [];
|
|
1090
1242
|
const firstText = firstRow.find((c) => c.text.trim())?.text ?? "";
|
|
1091
1243
|
if (!ANNEX_HEAD_RE.test(firstText)) return true;
|
|
1092
1244
|
const filled = firstRow.map((c) => c.text.replace(/\s+/g, "")).filter(Boolean);
|
|
1093
1245
|
return filled.length >= 2 && filled.every((t) => t === filled[0]);
|
|
1094
1246
|
}
|
|
1247
|
+
function pushedLead(prev, curr) {
|
|
1248
|
+
if (!CLIP_TABLES.has(prev.table) || !CLIP_TABLES.has(curr.table)) return false;
|
|
1249
|
+
const lead = leadRows(curr.table);
|
|
1250
|
+
return lead.image && lead.height > prev.bbox.y;
|
|
1251
|
+
}
|
|
1252
|
+
function leadRows(t) {
|
|
1253
|
+
const ys = TABLE_ROWYS.get(t);
|
|
1254
|
+
if (!ys || ys.length < 2) return { height: 0, image: false };
|
|
1255
|
+
const anchors = anchorsOf(t);
|
|
1256
|
+
let end = 1, image = false;
|
|
1257
|
+
for (let r = 0; r < end; r++) {
|
|
1258
|
+
for (const a of anchors) {
|
|
1259
|
+
if (a.r !== r) continue;
|
|
1260
|
+
end = Math.max(end, r + a.rs);
|
|
1261
|
+
if (IMAGE_CELLS.has(a.cell)) image = true;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
return { height: ys[0] - ys[Math.min(end, ys.length - 1)], image };
|
|
1265
|
+
}
|
|
1266
|
+
function tailOf(b) {
|
|
1267
|
+
const t = b.table && TABLE_TAIL.get(b.table);
|
|
1268
|
+
return t && b.bbox ? { ...b, pageNumber: t.page, bbox: { ...b.bbox, page: t.page, y: t.y, height: t.height } } : b;
|
|
1269
|
+
}
|
|
1095
1270
|
function firstRowSig(t) {
|
|
1096
1271
|
const x = TABLE_COLXS.get(t);
|
|
1097
1272
|
if (!x || x.length !== t.cols + 1) return null;
|
|
@@ -1142,14 +1317,14 @@ function chainHead(blocks, i, pageHeights) {
|
|
|
1142
1317
|
break;
|
|
1143
1318
|
}
|
|
1144
1319
|
}
|
|
1145
|
-
const pb = blocks[p];
|
|
1320
|
+
const pb = tailOf(blocks[p]);
|
|
1146
1321
|
if (pb.pageNumber !== (cur.pageNumber ?? 0) - 1) break;
|
|
1147
1322
|
if (!blocks.slice(p + 1, k).every((b) => besideOwn(b, pb, cur) || insideTable(b, pb))) break;
|
|
1148
1323
|
if (!looksContinued(pb, cur, pageHeights)) break;
|
|
1149
1324
|
const px = TABLE_COLXS.get(pb.table), cx = TABLE_COLXS.get(cur.table);
|
|
1150
1325
|
if (!px || !cx) break;
|
|
1151
1326
|
const dx = px[px.length - 1] - cx[cx.length - 1];
|
|
1152
|
-
if (!shiftedSame(px, cx) && !px.some((x) => Math.abs(x - (cx[0] + dx)) <= CONTINUATION_COL_TOL)) break;
|
|
1327
|
+
if (!shiftedSame(px, cx) && !px.some((x) => Math.abs(x - (cx[0] + dx)) <= CONTINUATION_COL_TOL) && !prevLacksLeftCols(pb, px, cx, pageHeights)) break;
|
|
1153
1328
|
k = p;
|
|
1154
1329
|
}
|
|
1155
1330
|
return k;
|
|
@@ -1163,6 +1338,7 @@ function rowTextsEqual(a, b) {
|
|
|
1163
1338
|
return a.some((c) => c.text.trim() !== "");
|
|
1164
1339
|
}
|
|
1165
1340
|
var CONTINUATION_COL_TOL = 2;
|
|
1341
|
+
var FOREIGN_FIRST_ROW_CELLS = 3;
|
|
1166
1342
|
function shiftedSame(px, cx, allowShift = true) {
|
|
1167
1343
|
if (px.length !== cx.length) return false;
|
|
1168
1344
|
const dx = allowShift ? px[px.length - 1] - cx[cx.length - 1] : 0;
|
|
@@ -1207,6 +1383,10 @@ function mergeContinuedCells(blocks, pageHeights) {
|
|
|
1207
1383
|
const at = cell.blocks || add.blocks ? cellBlocks(cell, prev.pageNumber).length : -1;
|
|
1208
1384
|
if (cell.blocks || add.blocks) cell.blocks = [...cellBlocks(cell, prev.pageNumber), ...cellBlocks(add, part.pageNumber)];
|
|
1209
1385
|
cell.text = [cell.text, add.text].filter((s) => s.trim()).join("\n");
|
|
1386
|
+
joinCellEdges(cell, add);
|
|
1387
|
+
const lines = CELL_LINES.get(add);
|
|
1388
|
+
if (lines?.length) CELL_LINES.set(cell, [...CELL_LINES.get(cell) ?? [], ...lines]);
|
|
1389
|
+
if (part.pageNumber && part.bbox) TABLE_TAIL.set(prev.table, TABLE_TAIL.get(part.table) ?? { page: part.pageNumber, y: part.bbox.y, height: part.bbox.height });
|
|
1210
1390
|
if (cell.text.trim() || cell.blocks?.length) EMPTY_PARTS.delete(prev.table);
|
|
1211
1391
|
blocks.splice(j, 1);
|
|
1212
1392
|
if (cell.blocks && at > 0) {
|
|
@@ -1239,6 +1419,7 @@ function fillNestedContinuation(blocks, at) {
|
|
|
1239
1419
|
if (!cell || !add || cell.text.trim() || cell.blocks?.length) return;
|
|
1240
1420
|
cell.text = add.text;
|
|
1241
1421
|
if (add.blocks) cell.blocks = add.blocks;
|
|
1422
|
+
joinCellEdges(cell, add);
|
|
1242
1423
|
blocks.splice(at, 1);
|
|
1243
1424
|
}
|
|
1244
1425
|
|
|
@@ -2515,7 +2696,7 @@ function mergeLinkRuns(markdown) {
|
|
|
2515
2696
|
|
|
2516
2697
|
// src/pdf/formula-ocr.ts
|
|
2517
2698
|
async function applyFormulaOcr(buffer, blocks, pageFilter, effectivePageCount, warnings, _onProgress) {
|
|
2518
|
-
const formulaMod = await import("./formula-
|
|
2699
|
+
const formulaMod = await import("./formula-7MMFBRGJ.js");
|
|
2519
2700
|
const { FormulaPipeline, ensureFormulaModels } = formulaMod;
|
|
2520
2701
|
await ensureFormulaModels((p) => {
|
|
2521
2702
|
if (p.phase === "download" && p.total) {
|
|
@@ -2898,7 +3079,7 @@ async function parsePdfDocument(buffer, options) {
|
|
|
2898
3079
|
}
|
|
2899
3080
|
if (targets.size > 0) {
|
|
2900
3081
|
try {
|
|
2901
|
-
const { runPdfOcr } = await import("./pdf-ocr-
|
|
3082
|
+
const { runPdfOcr } = await import("./pdf-ocr-L35FQYGP.js");
|
|
2902
3083
|
const mode = typeof options?.ocr === "function" ? options.ocr : "builtin";
|
|
2903
3084
|
const regionPages = new Map([...ocrRegions].filter(([p]) => options?.ocr !== "force" && !isImageBased && !pageQuality.find((q) => q.page === p)?.needsOcr));
|
|
2904
3085
|
const ocrPageBlocks = await runPdfOcr(ocrBuffer, targets, mode, warnings, options?.onProgress, options?.tables !== false, vectorPageOps, regionPages);
|
|
@@ -3023,6 +3204,28 @@ async function parsePdfDocument(buffer, options) {
|
|
|
3023
3204
|
return b.bbox.y > h * 0.1 && b.bbox.y + b.bbox.height < h * 0.9;
|
|
3024
3205
|
});
|
|
3025
3206
|
joinLatinCellWraps(outBlocks);
|
|
3207
|
+
if (options?.layoutTables !== "keep" && await isHancomPdf(doc)) {
|
|
3208
|
+
const shown = /* @__PURE__ */ new Map();
|
|
3209
|
+
const markContent = (bs) => {
|
|
3210
|
+
for (const b of bs ?? []) if (b.table) for (const row of b.table.cells) for (const c of row) {
|
|
3211
|
+
if (IMAGE_CELLS.has(c)) CONTENT_CELLS.add(c);
|
|
3212
|
+
markContent(c.blocks);
|
|
3213
|
+
}
|
|
3214
|
+
};
|
|
3215
|
+
const visual = (bs) => bs.flatMap((b) => {
|
|
3216
|
+
if (b.type !== "table") return [b];
|
|
3217
|
+
let v = shown.get(b);
|
|
3218
|
+
if (!v) {
|
|
3219
|
+
markContent([b]);
|
|
3220
|
+
shown.set(b, v = unframeLayoutTables([b], !!options?.keepTrailingEmptyCols));
|
|
3221
|
+
}
|
|
3222
|
+
return v;
|
|
3223
|
+
});
|
|
3224
|
+
outBlocks = visual(outBlocks);
|
|
3225
|
+
const kept = visual(blocks);
|
|
3226
|
+
blocks.length = 0;
|
|
3227
|
+
for (const b of kept) blocks.push(b);
|
|
3228
|
+
}
|
|
3026
3229
|
const finishMarkdown = (bs) => mergeLinkRuns(cleanPdfText(blocksToMarkdown(bs), { keepLoneNumbers: true }));
|
|
3027
3230
|
let markdown = finishMarkdown(outBlocks);
|
|
3028
3231
|
return {
|
|
@@ -3059,6 +3262,14 @@ async function extractPdfMetadata(doc, metadata) {
|
|
|
3059
3262
|
} catch {
|
|
3060
3263
|
}
|
|
3061
3264
|
}
|
|
3265
|
+
async function isHancomPdf(doc) {
|
|
3266
|
+
try {
|
|
3267
|
+
const info = (await doc.getMetadata())?.info;
|
|
3268
|
+
return [info?.Producer, info?.Creator].some((v) => typeof v === "string" && /^\s*(?:hancom\b|hwp\b)/i.test(v));
|
|
3269
|
+
} catch {
|
|
3270
|
+
return false;
|
|
3271
|
+
}
|
|
3272
|
+
}
|
|
3062
3273
|
function parsePdfDate(dateStr) {
|
|
3063
3274
|
const m = dateStr.match(/D:(\d{4})(\d{2})?(\d{2})?(\d{2})?(\d{2})?(\d{2})?/);
|
|
3064
3275
|
if (!m) return void 0;
|
|
@@ -3098,4 +3309,4 @@ export {
|
|
|
3098
3309
|
parsePdfDocument,
|
|
3099
3310
|
removeHeaderFooterBlocks
|
|
3100
3311
|
};
|
|
3101
|
-
//# sourceMappingURL=parser-
|
|
3312
|
+
//# sourceMappingURL=parser-ZPRQ3SSU.js.map
|