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
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ALL_OCR_MODELS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-A55JGNKD.js";
|
|
5
5
|
import {
|
|
6
6
|
ALL_FORMULA_MODELS,
|
|
7
7
|
getModelStatusIn,
|
|
8
8
|
getModelsDir
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-BLPR4HRF.js";
|
|
10
|
+
import "./chunk-BZG7K44Z.js";
|
|
11
|
+
import "./chunk-ZF6KHPB7.js";
|
|
12
12
|
|
|
13
13
|
// src/shared/model-bundle.ts
|
|
14
14
|
import { copyFile, mkdir } from "fs/promises";
|
|
@@ -101,4 +101,4 @@ export {
|
|
|
101
101
|
importModels,
|
|
102
102
|
modelCacheStatus
|
|
103
103
|
};
|
|
104
|
-
//# sourceMappingURL=model-bundle-
|
|
104
|
+
//# sourceMappingURL=model-bundle-OUHGCEZY.js.map
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
ocrModelPath,
|
|
11
11
|
ocrModelsCached,
|
|
12
12
|
parseCharacterDict
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-A55JGNKD.js";
|
|
14
|
+
import "./chunk-BLPR4HRF.js";
|
|
15
|
+
import "./chunk-BZG7K44Z.js";
|
|
16
|
+
import "./chunk-ZF6KHPB7.js";
|
|
17
17
|
export {
|
|
18
18
|
ALL_OCR_MODELS,
|
|
19
19
|
OCR_DET_MODEL,
|
|
@@ -26,4 +26,4 @@ export {
|
|
|
26
26
|
ocrModelsCached,
|
|
27
27
|
parseCharacterDict
|
|
28
28
|
};
|
|
29
|
-
//# sourceMappingURL=models-
|
|
29
|
+
//# sourceMappingURL=models-6D6LMOTH.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/
|
|
1
|
+
{"version":3,"sources":["/Users/chris_gomdori/workspace/kordoc/dist/page-range-QHHFTL7X.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACF,qIAAC","file":"/Users/chris_gomdori/workspace/kordoc/dist/page-range-QHHFTL7X.cjs"}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
blocksToPages,
|
|
5
5
|
encodePng,
|
|
6
6
|
escapeLiteralDollar
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YZ5HHS6A.js";
|
|
8
8
|
import {
|
|
9
9
|
hasRequestedPagesAfter,
|
|
10
10
|
parsePageRange
|
|
@@ -16,7 +16,12 @@ import {
|
|
|
16
16
|
EMPTY_PARTS,
|
|
17
17
|
FILLER_CELLS,
|
|
18
18
|
IMAGE_CELLS,
|
|
19
|
+
NO_EDGES,
|
|
20
|
+
PART_COLXS,
|
|
21
|
+
ROW_RULES,
|
|
19
22
|
TABLE_COLXS,
|
|
23
|
+
TABLE_ROWYS,
|
|
24
|
+
TABLE_TAIL,
|
|
20
25
|
TOC_BLOCKS,
|
|
21
26
|
WrapLexicon,
|
|
22
27
|
collapseEvenSpacing,
|
|
@@ -34,6 +39,7 @@ import {
|
|
|
34
39
|
extractLines,
|
|
35
40
|
extractPageBlocksWithLines,
|
|
36
41
|
filterHiddenText,
|
|
42
|
+
joinCellEdges,
|
|
37
43
|
joinPageBreakWraps,
|
|
38
44
|
latinSoftWrap,
|
|
39
45
|
mergeStackedHeadingLines,
|
|
@@ -44,15 +50,18 @@ import {
|
|
|
44
50
|
startsNewItem,
|
|
45
51
|
trimTrailingEmptyTableCols,
|
|
46
52
|
wrapJoiner
|
|
47
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-4XVNQAK5.js";
|
|
48
54
|
import {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
CELL_EDGES,
|
|
56
|
+
CONTENT_CELLS,
|
|
57
|
+
stripScriptTags,
|
|
58
|
+
unframeLayoutTables
|
|
59
|
+
} from "./chunk-MJBCXW5R.js";
|
|
60
|
+
import "./chunk-EFO6JZY6.js";
|
|
52
61
|
import {
|
|
53
62
|
KordocError,
|
|
54
63
|
sanitizeHref
|
|
55
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-ML4NHUR7.js";
|
|
56
65
|
|
|
57
66
|
// src/pdf/ocr-region-merge.ts
|
|
58
67
|
function mergeOcrImageRegions(blocks, page, regions, ocrBlocks) {
|
|
@@ -673,6 +682,7 @@ function splitContactTables(blocks) {
|
|
|
673
682
|
|
|
674
683
|
// src/pdf/table-parts.ts
|
|
675
684
|
var PART_COL_TOL = 1;
|
|
685
|
+
var PART_COL_SNAP = 0.3;
|
|
676
686
|
function anchorsOf(table) {
|
|
677
687
|
const out = [];
|
|
678
688
|
const covered = /* @__PURE__ */ new Set();
|
|
@@ -690,9 +700,22 @@ function anchorsOf(table) {
|
|
|
690
700
|
return out;
|
|
691
701
|
}
|
|
692
702
|
function unionCoords(a, b) {
|
|
703
|
+
const drift = a.length === b.length && a.every((x, i) => Math.abs(x - b[i]) <= PART_COL_TOL);
|
|
704
|
+
const tol = drift ? PART_COL_TOL : PART_COL_SNAP;
|
|
705
|
+
const pairs = [];
|
|
706
|
+
for (const v of b) for (const x of a) if (Math.abs(x - v) <= tol) pairs.push([Math.abs(x - v), v, x]);
|
|
707
|
+
pairs.sort((p, q) => p[0] - q[0]);
|
|
708
|
+
const map = /* @__PURE__ */ new Map(), taken = /* @__PURE__ */ new Set();
|
|
709
|
+
for (const [, v, x] of pairs) if (!map.has(v) && !taken.has(x)) {
|
|
710
|
+
map.set(v, x);
|
|
711
|
+
taken.add(x);
|
|
712
|
+
}
|
|
693
713
|
const out = [...a];
|
|
694
|
-
for (const v of b) if (!
|
|
695
|
-
|
|
714
|
+
for (const v of b) if (!map.has(v)) {
|
|
715
|
+
map.set(v, v);
|
|
716
|
+
out.push(v);
|
|
717
|
+
}
|
|
718
|
+
return { U: out.sort((x, y) => x - y), map };
|
|
696
719
|
}
|
|
697
720
|
var indexOf = (coords, x) => {
|
|
698
721
|
let best = -1, bestD = Infinity;
|
|
@@ -709,18 +732,31 @@ var rowText = (anchors, r) => anchors.filter((a) => a.r === r).map((a) => a.cell
|
|
|
709
732
|
var hasText = (t) => t.replace(/\|/g, "") !== "";
|
|
710
733
|
function joinSplitParts(prev, pcx, curr, ccx, dx = 0, prevBottom, lex) {
|
|
711
734
|
if (pcx.length !== prev.cols + 1 || ccx.length !== curr.cols + 1) return null;
|
|
712
|
-
const U = unionCoords(pcx, ccx);
|
|
735
|
+
const { U, map } = unionCoords(pcx, ccx);
|
|
736
|
+
const cxU = ccx.map((v) => map.get(v) ?? v);
|
|
713
737
|
const cols = U.length - 1;
|
|
714
738
|
if (cols < 1) return null;
|
|
715
739
|
const pa = anchorsOf(prev), ca = anchorsOf(curr);
|
|
716
|
-
let skip = 0;
|
|
740
|
+
let skip = 0, head = 0;
|
|
717
741
|
while (skip < Math.min(3, curr.rows - 1, prev.rows) && rowText(ca, skip) !== "" && rowText(ca, skip) === rowText(pa, skip)) skip++;
|
|
718
742
|
for (let h = 1; h <= 2 && !skip; h++) {
|
|
743
|
+
head = h;
|
|
719
744
|
while (skip < Math.min(3, curr.rows - 1, prev.rows - h) && hasText(rowText(ca, skip)) && rowText(ca, skip) === rowText(pa, h + skip)) skip++;
|
|
720
745
|
}
|
|
746
|
+
const sameSpans = (u, d) => {
|
|
747
|
+
if (u.length !== d.length || !u.length) return false;
|
|
748
|
+
const shift = pcx[u[u.length - 1].c + u[u.length - 1].cs] - ccx[d[d.length - 1].c + d[d.length - 1].cs];
|
|
749
|
+
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);
|
|
750
|
+
};
|
|
751
|
+
for (let k = 0; k < skip; k++) {
|
|
752
|
+
if (sameSpans(pa.filter((a) => a.r === head + k), ca.filter((a) => a.r === k))) continue;
|
|
753
|
+
if (hasText(rowText(ca, k))) return null;
|
|
754
|
+
skip = k;
|
|
755
|
+
}
|
|
721
756
|
const rows = prev.rows + curr.rows - skip;
|
|
722
757
|
const grid = Array.from({ length: rows }, () => Array.from({ length: cols }, () => ({ text: "", colSpan: 1, rowSpan: 1 })));
|
|
723
758
|
const owner = Array.from({ length: rows }, () => new Array(cols).fill(null));
|
|
759
|
+
let edged = false;
|
|
724
760
|
const place = (a, x, rowOff, shift = 0) => {
|
|
725
761
|
const c1 = indexOf(U, x[a.c]), c2 = indexOf(U, x[a.c + a.cs]);
|
|
726
762
|
if (c1 < 0 || c2 <= c1) return false;
|
|
@@ -733,12 +769,17 @@ function joinSplitParts(prev, pcx, curr, ccx, dx = 0, prevBottom, lex) {
|
|
|
733
769
|
const lines = CELL_LINES.get(a.cell);
|
|
734
770
|
if (lines) CELL_LINES.set(grid[r][c1], shift ? lines.map((l) => ({ ...l, l: l.l + shift, r: l.r + shift })) : lines);
|
|
735
771
|
if (IMAGE_CELLS.has(a.cell)) IMAGE_CELLS.add(grid[r][c1]);
|
|
772
|
+
const edges = CELL_EDGES.get(a.cell);
|
|
773
|
+
if (edges) {
|
|
774
|
+
CELL_EDGES.set(grid[r][c1], edges);
|
|
775
|
+
edged = true;
|
|
776
|
+
}
|
|
736
777
|
return true;
|
|
737
778
|
};
|
|
738
779
|
for (const a of pa) if (!FILLER_CELLS.has(a.cell) && !place(a, pcx, 0)) return null;
|
|
739
780
|
for (const a of ca) {
|
|
740
781
|
if (a.r < skip || FILLER_CELLS.has(a.cell)) continue;
|
|
741
|
-
if (!place(a,
|
|
782
|
+
if (!place(a, cxU, prev.rows - skip, dx)) return null;
|
|
742
783
|
}
|
|
743
784
|
const first = prev.rows;
|
|
744
785
|
for (let c = 0; c < cols; c++) {
|
|
@@ -762,12 +803,32 @@ function joinSplitParts(prev, pcx, curr, ccx, dx = 0, prevBottom, lex) {
|
|
|
762
803
|
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;
|
|
763
804
|
}
|
|
764
805
|
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]);
|
|
806
|
+
if (edged) {
|
|
807
|
+
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);
|
|
808
|
+
}
|
|
809
|
+
for (let c = 0; c < cols && U[c + 1] <= pcx[0] + PART_COL_TOL; c++) {
|
|
810
|
+
let r = prev.rows;
|
|
811
|
+
while (r < rows && owner[r][c] === null) r++;
|
|
812
|
+
const through = { r: 0, c, rs: r, cs: 1, cell: grid[0][c] };
|
|
813
|
+
for (let rr = 0; rr < r; rr++) owner[rr][c] = through;
|
|
814
|
+
}
|
|
765
815
|
const table = { rows, cols, cells: grid, hasHeader: prev.hasHeader, ...prev.caption ? { caption: prev.caption } : {} };
|
|
766
|
-
|
|
767
|
-
|
|
816
|
+
const pr = ROW_RULES.get(prev), cr = ROW_RULES.get(curr);
|
|
817
|
+
const shifted = dx !== 0;
|
|
818
|
+
const cut = {
|
|
819
|
+
open: !!pr && !!cr && !pr.bottom && !cr.top && pr.innerOpen + cr.innerOpen === 0 && pr.innerRuled + cr.innerRuled > 0,
|
|
820
|
+
ruled: !!pr && !!cr && pr.bottom && cr.top,
|
|
821
|
+
list: !shifted ? "any" : skip > 0 && ca.filter((a) => a.r < skip && a.cell.text.trim()).length < 2 ? "none" : "multi"
|
|
822
|
+
};
|
|
823
|
+
let split = rows > prev.rows && mergeSplitRow(table, owner, prev.rows, U, false, cut);
|
|
824
|
+
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 });
|
|
825
|
+
if (pr && cr) {
|
|
826
|
+
const cutRuled = pr.bottom || cr.top;
|
|
827
|
+
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) });
|
|
828
|
+
}
|
|
768
829
|
return { table, colXs: U, split, header: ca.filter((a) => a.r < skip && a.cell.text.trim()).length >= 2 };
|
|
769
830
|
}
|
|
770
|
-
function mergeStraddlingCells(table, owner, first, prevBottom, lex) {
|
|
831
|
+
function mergeStraddlingCells(table, owner, first, prevBottom, lex, colXs) {
|
|
771
832
|
const last = first - 1;
|
|
772
833
|
const straddles = owner[first].some((o, c) => o !== null && o === owner[last][c]);
|
|
773
834
|
let firstNew = table.cols;
|
|
@@ -791,6 +852,19 @@ function mergeStraddlingCells(table, owner, first, prevBottom, lex) {
|
|
|
791
852
|
const tail = table.cells[u.r][u.c].text.trim().split(/\s+/).pop() ?? "", head = table.cells[first][d.c].text.trim().split(/\s+/)[0] ?? "";
|
|
792
853
|
if (/^[가-힣]{2,}$/.test(tail) && /^[가-힣]{2,}/.test(head) && lex.evidence2(tail, head) === "") midWord = true;
|
|
793
854
|
}
|
|
855
|
+
const crossed = /* @__PURE__ */ new Set();
|
|
856
|
+
const shape = (u, d) => `${u.r}:${u.rs}:${d.rs}`;
|
|
857
|
+
if (straddles && colXs) for (let c = 0; c < table.cols; ) {
|
|
858
|
+
const u = owner[last][c], d = owner[first][c];
|
|
859
|
+
if (!u) {
|
|
860
|
+
c++;
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
c = u.c + u.cs;
|
|
864
|
+
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;
|
|
865
|
+
const a = table.cells[u.r][u.c], b = table.cells[first][d.c];
|
|
866
|
+
if (hasContent(a) && hasContent(b) && continuesAcross(a, b, colXs[u.c], colXs[u.c + u.cs])) crossed.add(shape(u, d));
|
|
867
|
+
}
|
|
794
868
|
let merged = false;
|
|
795
869
|
for (let c = 0; c < table.cols; ) {
|
|
796
870
|
const u = owner[last][c], d = owner[first][c];
|
|
@@ -801,13 +875,16 @@ function mergeStraddlingCells(table, owner, first, prevBottom, lex) {
|
|
|
801
875
|
c = u.c + u.cs;
|
|
802
876
|
if (!d || d === u || u.r + u.rs - 1 !== last || d.r !== first || d.c !== u.c || d.cs !== u.cs) continue;
|
|
803
877
|
const a = table.cells[u.r][u.c], b = table.cells[first][d.c];
|
|
804
|
-
if (!(u.rs >= 2 && u.c + u.cs <= firstNew && hasContent(a) && !hasContent(b))) {
|
|
878
|
+
if (!crossed.has(shape(u, d)) && !(u.rs >= 2 && u.c + u.cs <= firstNew && hasContent(a) && !hasContent(b))) {
|
|
805
879
|
if (!straddles && !midWord) continue;
|
|
806
880
|
if (u.r >= last && d.rs < 2) continue;
|
|
807
881
|
const U = CELL_LINES.get(a);
|
|
808
|
-
if (!U?.length ||
|
|
809
|
-
|
|
810
|
-
|
|
882
|
+
if (!U?.length || !hasContent(b)) continue;
|
|
883
|
+
if (!(straddles && filledToBottom(U, prevBottom) && clauseContinues(a, b))) {
|
|
884
|
+
if (U.length > STRADDLE_MAX_LINES) continue;
|
|
885
|
+
const lu = U[U.length - 1];
|
|
886
|
+
if (!midWord && lu.y - prevBottom > (u.r >= last ? STRADDLE_BOTTOM_ONE_ROW : STRADDLE_BOTTOM) * (lu.h || 10)) continue;
|
|
887
|
+
}
|
|
811
888
|
}
|
|
812
889
|
appendCell(a, b);
|
|
813
890
|
a.rowSpan = first + d.rs - u.r;
|
|
@@ -818,6 +895,11 @@ function mergeStraddlingCells(table, owner, first, prevBottom, lex) {
|
|
|
818
895
|
}
|
|
819
896
|
return merged;
|
|
820
897
|
}
|
|
898
|
+
function filledToBottom(U, bottom) {
|
|
899
|
+
if (U.length < 2) return false;
|
|
900
|
+
const lu = U[U.length - 1];
|
|
901
|
+
return lu.y - bottom < (U[0].y - lu.y) / (U.length - 1) + FILL_SLACK * (lu.h || 10);
|
|
902
|
+
}
|
|
821
903
|
var FULL_LINE_TOL = 1;
|
|
822
904
|
var FULL_LINE_MIN_FRAC = 0.5;
|
|
823
905
|
var FULL_LINE_EDGE_MIN = 12;
|
|
@@ -826,6 +908,7 @@ var SHORT_LINE_GAP = 1.5;
|
|
|
826
908
|
var STRADDLE_MAX_LINES = 3;
|
|
827
909
|
var STRADDLE_BOTTOM = 1.2;
|
|
828
910
|
var STRADDLE_BOTTOM_ONE_ROW = 0.55;
|
|
911
|
+
var FILL_SLACK = 0.5;
|
|
829
912
|
var CARRIED_MIN_COL_W = 4;
|
|
830
913
|
var LABEL_ROOM = 1.5;
|
|
831
914
|
var HANGING_MIN = 0.5;
|
|
@@ -847,10 +930,16 @@ function continuesAcross(u, d, x1, x2) {
|
|
|
847
930
|
maxR = Math.max(maxR, x2 - (minL - x1));
|
|
848
931
|
if (maxR - last.r > FULL_LINE_TOL * fs) return false;
|
|
849
932
|
if (U.length === 1 && x2 - last.r > Math.max(FULL_LINE_EDGE_MIN, SINGLE_LINE_WORD_GAP * fs)) return false;
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
const
|
|
853
|
-
|
|
933
|
+
const indented = last.l - minL >= HANGING_MIN * fs;
|
|
934
|
+
if (last.r - last.l < FULL_LINE_MIN_FRAC * (indented ? x2 - last.l : x2 - x1)) return false;
|
|
935
|
+
const newItem = startsNewItem(u.text, d.text);
|
|
936
|
+
const all = D.length ? U.concat(D) : U;
|
|
937
|
+
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));
|
|
938
|
+
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;
|
|
939
|
+
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);
|
|
940
|
+
const d0 = D[0];
|
|
941
|
+
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);
|
|
942
|
+
return U.some(leftAligned) || D.some(leftAligned) || hanging || hangingHead || hangStart;
|
|
854
943
|
}
|
|
855
944
|
var OUTLINE_HEAD = /^[□■]\s*\S/;
|
|
856
945
|
var OUTLINE_ITEM = /^[ㅇ○◦\-‐–·․‧※*]\s*\S/;
|
|
@@ -859,14 +948,19 @@ function outlineContinues(u, d) {
|
|
|
859
948
|
const D = d.text.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
860
949
|
return U.length >= 2 && D.length >= 1 && U.some((l) => OUTLINE_HEAD.test(l)) && OUTLINE_ITEM.test(D[0]);
|
|
861
950
|
}
|
|
862
|
-
function lineEnded(c, x1, x2, next
|
|
951
|
+
function lineEnded(c, x1, x2, next) {
|
|
863
952
|
const L = CELL_LINES.get(c);
|
|
864
953
|
if (!L || L.length !== 1) return false;
|
|
865
954
|
const l = L[0], h = l.h || 10;
|
|
866
|
-
const
|
|
955
|
+
const d0 = next ? CELL_LINES.get(next)?.[0] : void 0;
|
|
956
|
+
if (d0 && d0.l - l.l >= HANGING_MIN * h) return false;
|
|
957
|
+
return x2 - l.r - (l.l - x1) >= Math.max(LABEL_ROOM, firstWordUnits(next?.text ?? "")) * h;
|
|
958
|
+
}
|
|
959
|
+
function firstWordUnits(text) {
|
|
960
|
+
const word = text.trim().replace(/^([(\[「『<〈])\s+/, "$1").split(/\s+/)[0] ?? "";
|
|
867
961
|
let units = 0;
|
|
868
962
|
for (const ch of word) units += /[가-힣\u3400-\u9fff]/.test(ch) ? 1 : 0.55;
|
|
869
|
-
return
|
|
963
|
+
return units;
|
|
870
964
|
}
|
|
871
965
|
function appendCell(a, b) {
|
|
872
966
|
if (a.blocks?.length || b.blocks?.length) {
|
|
@@ -874,6 +968,7 @@ function appendCell(a, b) {
|
|
|
874
968
|
a.blocks = [...asBlocks(a), ...asBlocks(b)];
|
|
875
969
|
}
|
|
876
970
|
if (b.text.trim()) a.text = a.text.trim() ? a.text + "\n" + b.text : b.text;
|
|
971
|
+
joinCellEdges(a, b);
|
|
877
972
|
}
|
|
878
973
|
var hasContent = (cell) => !!cell.text.trim() || !!cell.blocks?.length || IMAGE_CELLS.has(cell);
|
|
879
974
|
var CLAUSE_OPEN_ENDING = /(?:하는|되는|하고|하며|하여|되어|되고|되며|이며|으며|어야|아야|여야)$/;
|
|
@@ -887,11 +982,42 @@ function clauseContinues(u, d) {
|
|
|
887
982
|
const last = tail[tail.length - 1], before = tail[tail.length - 2];
|
|
888
983
|
return last === "\uC744" && batchim(before) || last === "\uB97C" && !batchim(before) || CLAUSE_OPEN_ENDING.test(tail);
|
|
889
984
|
}
|
|
985
|
+
function wordOverflows(u, d, x1, x2) {
|
|
986
|
+
const U = CELL_LINES.get(u);
|
|
987
|
+
if (!U?.length || startsNewItem(u.text, d.text)) return false;
|
|
988
|
+
const last = U[U.length - 1], units = firstWordUnits(d.text);
|
|
989
|
+
return units > 0 && last.r - last.l + units * (last.h || 10) > x2 - x1;
|
|
990
|
+
}
|
|
991
|
+
var KO_ORDER = "\uAC00\uB098\uB2E4\uB77C\uB9C8\uBC14\uC0AC\uC544\uC790\uCC28\uCE74\uD0C0\uD30C\uD558";
|
|
992
|
+
function itemMark(line) {
|
|
993
|
+
let m = /^(\d{1,2})([.)])(?!\d)/.exec(line);
|
|
994
|
+
if (m) return { style: "1" + m[2], n: +m[1] };
|
|
995
|
+
if (m = /^\((\d{1,2})\)/.exec(line)) return { style: "(1)", n: +m[1] };
|
|
996
|
+
if ((m = /^([가-하])([.)])/.exec(line)) && KO_ORDER.includes(m[1])) return { style: "\uAC00" + m[2], n: KO_ORDER.indexOf(m[1]) };
|
|
997
|
+
if ((m = /^\(([가-하])\)/.exec(line)) && KO_ORDER.includes(m[1])) return { style: "(\uAC00)", n: KO_ORDER.indexOf(m[1]) };
|
|
998
|
+
if (m = /^[①-⑳]/.exec(line)) return { style: "\u2460", n: m[0].charCodeAt(0) };
|
|
999
|
+
if (m = /^([A-Z])\.\s/.exec(line)) return { style: "A.", n: m[1].charCodeAt(0) };
|
|
1000
|
+
return null;
|
|
1001
|
+
}
|
|
1002
|
+
function listContinues(u, d, multi = false) {
|
|
1003
|
+
const head = itemMark(d.text.trim());
|
|
1004
|
+
if (!head) return false;
|
|
1005
|
+
const marks = u.text.split("\n").map((l) => itemMark(l.trim()));
|
|
1006
|
+
let last = -1, count = 0;
|
|
1007
|
+
marks.forEach((m, i) => {
|
|
1008
|
+
if (m?.style === head.style) {
|
|
1009
|
+
last = i;
|
|
1010
|
+
count++;
|
|
1011
|
+
}
|
|
1012
|
+
});
|
|
1013
|
+
return last >= 0 && marks[last].n + 1 === head.n && (count >= 2 || !multi && last > 0);
|
|
1014
|
+
}
|
|
890
1015
|
function outlineOnly(pairs, cell) {
|
|
891
1016
|
const filled = pairs.filter(([, d]) => hasContent(d.cell));
|
|
892
1017
|
return filled.length === 1 && outlineContinues(cell(filled[0][0]), cell(filled[0][1]));
|
|
893
1018
|
}
|
|
894
|
-
|
|
1019
|
+
var NO_CUT = { open: false, ruled: false, list: "any" };
|
|
1020
|
+
function mergeSplitRow(table, owner, first, colXs, textOnly = false, cut = NO_CUT) {
|
|
895
1021
|
const last = first - 1;
|
|
896
1022
|
const pairs = [];
|
|
897
1023
|
let carried = false;
|
|
@@ -904,19 +1030,30 @@ function mergeSplitRow(table, owner, first, colXs, textOnly = false) {
|
|
|
904
1030
|
}
|
|
905
1031
|
if (!a || !b) return false;
|
|
906
1032
|
if (a !== b) {
|
|
907
|
-
if (a.c !== b.c || a.cs !== b.cs || a.r + a.rs - 1 !== last || b.r !== first
|
|
1033
|
+
if (a.c !== b.c || a.cs !== b.cs || a.r + a.rs - 1 !== last || b.r !== first) return false;
|
|
1034
|
+
if (b.rs > 1 && (a.rs > 1 || !hasContent(a.cell))) return false;
|
|
908
1035
|
pairs.push([a, b]);
|
|
909
1036
|
} else if (a.r === last && a.rs === 2) carried = true;
|
|
910
1037
|
c = a.c + a.cs;
|
|
911
1038
|
}
|
|
912
|
-
const
|
|
1039
|
+
const newCell = pairs.some(([u, d]) => !hasContent(u.cell) && hasContent(d.cell));
|
|
913
1040
|
const cell = (a) => table.cells[a.r][a.c];
|
|
1041
|
+
const contentPairs = pairs.filter(([u, d]) => hasContent(u.cell) && hasContent(d.cell));
|
|
1042
|
+
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])));
|
|
914
1043
|
if (!carriedSplit) {
|
|
915
1044
|
const norm = (c) => c.text.replace(/\s+/g, "");
|
|
916
|
-
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)
|
|
917
|
-
|
|
1045
|
+
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;
|
|
1046
|
+
const flows = ([u, d]) => continuesAcross(cell(u), cell(d), colXs[u.c], colXs[u.c + u.cs]) || clauseContinues(cell(u), cell(d));
|
|
1047
|
+
if (!(cut.open && !newCell)) {
|
|
1048
|
+
if (pairs.some((p) => p[1].rs > 1 && !flows(p))) return false;
|
|
1049
|
+
const one = pairs.filter(([, d]) => d.rs === 1);
|
|
1050
|
+
if (!outlineOnly(pairs, cell) && !one.some(flows) && (cut.list === "none" || !one.some(([u, d]) => listContinues(cell(u), cell(d), cut.list === "multi")))) return false;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
for (const [u, d] of pairs) {
|
|
1054
|
+
appendCell(table.cells[u.r][u.c], table.cells[d.r][d.c]);
|
|
1055
|
+
if (d.rs > 1) table.cells[u.r][u.c].rowSpan = u.rs + d.rs;
|
|
918
1056
|
}
|
|
919
|
-
for (const [u, d] of pairs) appendCell(table.cells[u.r][u.c], table.cells[d.r][d.c]);
|
|
920
1057
|
for (let r = 0; r < first; r++) for (let c = 0; c < table.cols; c++) {
|
|
921
1058
|
const o = owner[r][c];
|
|
922
1059
|
if (o && o.r === r && o.c === c && r + table.cells[r][c].rowSpan > first) table.cells[r][c].rowSpan--;
|
|
@@ -964,11 +1101,14 @@ function sameHeadShape(a, b) {
|
|
|
964
1101
|
function mergeCrossPageTables(blocks, pageHeights, lex) {
|
|
965
1102
|
mergeColumnFlow(blocks, pageHeights, lex);
|
|
966
1103
|
for (let i = blocks.length - 2; i >= 0; i--) {
|
|
967
|
-
const
|
|
968
|
-
if (
|
|
1104
|
+
const tail = tailOf(blocks[i]);
|
|
1105
|
+
if (tail.type !== "table" || !tail.table || !tail.bbox || !tail.pageNumber) continue;
|
|
969
1106
|
let j = i + 1;
|
|
970
|
-
|
|
1107
|
+
const skip = (b) => b.type !== "table" || [blocks[i], tail].some((t) => insideTable(b, t) || leftColumnOf(b, t));
|
|
1108
|
+
while (j < blocks.length && skip(blocks[j]) && (blocks[j].pageNumber ?? 0) <= tail.pageNumber + 1) j++;
|
|
971
1109
|
const curr = blocks[j];
|
|
1110
|
+
const prev = tail !== blocks[i] && curr?.pageNumber === tail.pageNumber ? blocks[i] : tail;
|
|
1111
|
+
if (!prev.table || !prev.bbox || !prev.pageNumber) continue;
|
|
972
1112
|
if (!curr || curr.type !== "table" || !curr.table || !curr.bbox || curr.pageNumber !== prev.pageNumber + 1) continue;
|
|
973
1113
|
if (startsWithUnitRow(prev.table) && startsWithUnitRow(curr.table)) continue;
|
|
974
1114
|
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;
|
|
@@ -1051,24 +1191,36 @@ function joinClipParts(prev, curr, pageHeights, lex) {
|
|
|
1051
1191
|
if (!CLIP_TABLES.has(pt) || !CLIP_TABLES.has(ct)) return null;
|
|
1052
1192
|
const px = TABLE_COLXS.get(pt), cx = TABLE_COLXS.get(ct);
|
|
1053
1193
|
if (!px || !cx) return null;
|
|
1054
|
-
let xs = cx, shifted = false, dx = 0, foreign = false;
|
|
1194
|
+
let xs = cx, shifted = false, dx = 0, foreign = false, within = false;
|
|
1055
1195
|
if (!shiftedSame(px, cx, false)) {
|
|
1056
1196
|
if (!pageHeights?.get(prev.pageNumber) || !pageHeights?.get(curr.pageNumber)) return null;
|
|
1057
1197
|
dx = px[px.length - 1] - cx[cx.length - 1];
|
|
1058
|
-
|
|
1198
|
+
within = Math.abs(dx) > CONTINUATION_COL_TOL && cx.length >= 3 && cx.every((x) => px.some((p) => Math.abs(p - x) <= CONTINUATION_COL_TOL));
|
|
1199
|
+
if (Math.abs(dx) > CONTINUATION_COL_TOL && !within) {
|
|
1059
1200
|
xs = cx.map((x) => x + dx);
|
|
1060
1201
|
shifted = true;
|
|
1061
1202
|
} else dx = 0;
|
|
1062
|
-
if (!px.some((x) => Math.abs(x - xs[0]) <= CONTINUATION_COL_TOL)) return null;
|
|
1063
|
-
const
|
|
1064
|
-
|
|
1203
|
+
if (!px.some((x) => Math.abs(x - xs[0]) <= CONTINUATION_COL_TOL) && !prevLacksLeftCols(prev, px, xs, pageHeights)) return null;
|
|
1204
|
+
const unrelated = (b) => {
|
|
1205
|
+
const inner = b.slice(1, -1).map((x) => x + dx);
|
|
1206
|
+
return inner.length > 0 && !inner.some((x) => px.some((p) => Math.abs(p - x) <= CONTINUATION_COL_TOL));
|
|
1207
|
+
};
|
|
1208
|
+
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);
|
|
1065
1209
|
}
|
|
1066
1210
|
const res = joinSplitParts(pt, px, ct, xs, dx, prev.bbox?.y, lex);
|
|
1067
|
-
if (!res || (shifted || foreign) && !res.split && !res.header) return null;
|
|
1211
|
+
if (!res || (shifted || foreign || within) && !res.split && !res.header) return null;
|
|
1068
1212
|
TABLE_COLXS.set(res.table, res.colXs);
|
|
1213
|
+
const ys = TABLE_ROWYS.get(pt);
|
|
1214
|
+
if (ys) TABLE_ROWYS.set(res.table, ys);
|
|
1215
|
+
PART_COLXS.set(res.table, PART_COLXS.get(pt) ?? px);
|
|
1069
1216
|
CLIP_TABLES.add(res.table);
|
|
1070
1217
|
return res.table;
|
|
1071
1218
|
}
|
|
1219
|
+
function prevLacksLeftCols(prev, px, xs, pageHeights) {
|
|
1220
|
+
const ph = pageHeights?.get(prev.pageNumber);
|
|
1221
|
+
if (!ph || prev.bbox.y + prev.bbox.height < ph * (1 - PAGE_EDGE_BAND)) return false;
|
|
1222
|
+
return xs[0] < px[0] && xs.slice(1, -1).some((x) => Math.abs(x - px[0]) <= CONTINUATION_COL_TOL);
|
|
1223
|
+
}
|
|
1072
1224
|
function headingRow(row) {
|
|
1073
1225
|
const heads = row.map((c) => c.text.replace(/\s+/g, "")).filter(Boolean);
|
|
1074
1226
|
if (heads.length === 1) return heads[0].length <= 8 || /^[①-⑳❶-❿]/.test(heads[0]);
|
|
@@ -1077,13 +1229,36 @@ function headingRow(row) {
|
|
|
1077
1229
|
var ANNEX_HEAD_RE = /^\s*[<\[(【]?\s*(?:붙\s*임|참\s*고|별\s*첨|별\s*지|별\s*표|첨\s*부|부\s*록)(?:\s*\d|\s*$|\s*[>\])】])|^\s*■/;
|
|
1078
1230
|
function looksContinued(prev, curr, pageHeights) {
|
|
1079
1231
|
const ph = pageHeights?.get(prev.pageNumber), ch = pageHeights?.get(curr.pageNumber);
|
|
1080
|
-
if (ph && ch && (prev.bbox.y > ph * PAGE_EDGE_BAND || curr.bbox.y + curr.bbox.height < ch * (1 - PAGE_EDGE_BAND))) return false;
|
|
1232
|
+
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;
|
|
1081
1233
|
const firstRow = curr.table.cells[0] ?? [];
|
|
1082
1234
|
const firstText = firstRow.find((c) => c.text.trim())?.text ?? "";
|
|
1083
1235
|
if (!ANNEX_HEAD_RE.test(firstText)) return true;
|
|
1084
1236
|
const filled = firstRow.map((c) => c.text.replace(/\s+/g, "")).filter(Boolean);
|
|
1085
1237
|
return filled.length >= 2 && filled.every((t) => t === filled[0]);
|
|
1086
1238
|
}
|
|
1239
|
+
function pushedLead(prev, curr) {
|
|
1240
|
+
if (!CLIP_TABLES.has(prev.table) || !CLIP_TABLES.has(curr.table)) return false;
|
|
1241
|
+
const lead = leadRows(curr.table);
|
|
1242
|
+
return lead.image && lead.height > prev.bbox.y;
|
|
1243
|
+
}
|
|
1244
|
+
function leadRows(t) {
|
|
1245
|
+
const ys = TABLE_ROWYS.get(t);
|
|
1246
|
+
if (!ys || ys.length < 2) return { height: 0, image: false };
|
|
1247
|
+
const anchors = anchorsOf(t);
|
|
1248
|
+
let end = 1, image = false;
|
|
1249
|
+
for (let r = 0; r < end; r++) {
|
|
1250
|
+
for (const a of anchors) {
|
|
1251
|
+
if (a.r !== r) continue;
|
|
1252
|
+
end = Math.max(end, r + a.rs);
|
|
1253
|
+
if (IMAGE_CELLS.has(a.cell)) image = true;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
return { height: ys[0] - ys[Math.min(end, ys.length - 1)], image };
|
|
1257
|
+
}
|
|
1258
|
+
function tailOf(b) {
|
|
1259
|
+
const t = b.table && TABLE_TAIL.get(b.table);
|
|
1260
|
+
return t && b.bbox ? { ...b, pageNumber: t.page, bbox: { ...b.bbox, page: t.page, y: t.y, height: t.height } } : b;
|
|
1261
|
+
}
|
|
1087
1262
|
function firstRowSig(t) {
|
|
1088
1263
|
const x = TABLE_COLXS.get(t);
|
|
1089
1264
|
if (!x || x.length !== t.cols + 1) return null;
|
|
@@ -1134,14 +1309,14 @@ function chainHead(blocks, i, pageHeights) {
|
|
|
1134
1309
|
break;
|
|
1135
1310
|
}
|
|
1136
1311
|
}
|
|
1137
|
-
const pb = blocks[p];
|
|
1312
|
+
const pb = tailOf(blocks[p]);
|
|
1138
1313
|
if (pb.pageNumber !== (cur.pageNumber ?? 0) - 1) break;
|
|
1139
1314
|
if (!blocks.slice(p + 1, k).every((b) => besideOwn(b, pb, cur) || insideTable(b, pb))) break;
|
|
1140
1315
|
if (!looksContinued(pb, cur, pageHeights)) break;
|
|
1141
1316
|
const px = TABLE_COLXS.get(pb.table), cx = TABLE_COLXS.get(cur.table);
|
|
1142
1317
|
if (!px || !cx) break;
|
|
1143
1318
|
const dx = px[px.length - 1] - cx[cx.length - 1];
|
|
1144
|
-
if (!shiftedSame(px, cx) && !px.some((x) => Math.abs(x - (cx[0] + dx)) <= CONTINUATION_COL_TOL)) break;
|
|
1319
|
+
if (!shiftedSame(px, cx) && !px.some((x) => Math.abs(x - (cx[0] + dx)) <= CONTINUATION_COL_TOL) && !prevLacksLeftCols(pb, px, cx, pageHeights)) break;
|
|
1145
1320
|
k = p;
|
|
1146
1321
|
}
|
|
1147
1322
|
return k;
|
|
@@ -1155,6 +1330,7 @@ function rowTextsEqual(a, b) {
|
|
|
1155
1330
|
return a.some((c) => c.text.trim() !== "");
|
|
1156
1331
|
}
|
|
1157
1332
|
var CONTINUATION_COL_TOL = 2;
|
|
1333
|
+
var FOREIGN_FIRST_ROW_CELLS = 3;
|
|
1158
1334
|
function shiftedSame(px, cx, allowShift = true) {
|
|
1159
1335
|
if (px.length !== cx.length) return false;
|
|
1160
1336
|
const dx = allowShift ? px[px.length - 1] - cx[cx.length - 1] : 0;
|
|
@@ -1199,6 +1375,10 @@ function mergeContinuedCells(blocks, pageHeights) {
|
|
|
1199
1375
|
const at = cell.blocks || add.blocks ? cellBlocks(cell, prev.pageNumber).length : -1;
|
|
1200
1376
|
if (cell.blocks || add.blocks) cell.blocks = [...cellBlocks(cell, prev.pageNumber), ...cellBlocks(add, part.pageNumber)];
|
|
1201
1377
|
cell.text = [cell.text, add.text].filter((s) => s.trim()).join("\n");
|
|
1378
|
+
joinCellEdges(cell, add);
|
|
1379
|
+
const lines = CELL_LINES.get(add);
|
|
1380
|
+
if (lines?.length) CELL_LINES.set(cell, [...CELL_LINES.get(cell) ?? [], ...lines]);
|
|
1381
|
+
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 });
|
|
1202
1382
|
if (cell.text.trim() || cell.blocks?.length) EMPTY_PARTS.delete(prev.table);
|
|
1203
1383
|
blocks.splice(j, 1);
|
|
1204
1384
|
if (cell.blocks && at > 0) {
|
|
@@ -1231,6 +1411,7 @@ function fillNestedContinuation(blocks, at) {
|
|
|
1231
1411
|
if (!cell || !add || cell.text.trim() || cell.blocks?.length) return;
|
|
1232
1412
|
cell.text = add.text;
|
|
1233
1413
|
if (add.blocks) cell.blocks = add.blocks;
|
|
1414
|
+
joinCellEdges(cell, add);
|
|
1234
1415
|
blocks.splice(at, 1);
|
|
1235
1416
|
}
|
|
1236
1417
|
|
|
@@ -2507,7 +2688,7 @@ function mergeLinkRuns(markdown) {
|
|
|
2507
2688
|
|
|
2508
2689
|
// src/pdf/formula-ocr.ts
|
|
2509
2690
|
async function applyFormulaOcr(buffer, blocks, pageFilter, effectivePageCount, warnings, _onProgress) {
|
|
2510
|
-
const formulaMod = await import("./formula-
|
|
2691
|
+
const formulaMod = await import("./formula-SHBXRXOJ.js");
|
|
2511
2692
|
const { FormulaPipeline, ensureFormulaModels } = formulaMod;
|
|
2512
2693
|
await ensureFormulaModels((p) => {
|
|
2513
2694
|
if (p.phase === "download" && p.total) {
|
|
@@ -2890,7 +3071,7 @@ async function parsePdfDocument(buffer, options) {
|
|
|
2890
3071
|
}
|
|
2891
3072
|
if (targets.size > 0) {
|
|
2892
3073
|
try {
|
|
2893
|
-
const { runPdfOcr } = await import("./pdf-ocr-
|
|
3074
|
+
const { runPdfOcr } = await import("./pdf-ocr-462ZFSHX.js");
|
|
2894
3075
|
const mode = typeof options?.ocr === "function" ? options.ocr : "builtin";
|
|
2895
3076
|
const regionPages = new Map([...ocrRegions].filter(([p]) => options?.ocr !== "force" && !isImageBased && !pageQuality.find((q) => q.page === p)?.needsOcr));
|
|
2896
3077
|
const ocrPageBlocks = await runPdfOcr(ocrBuffer, targets, mode, warnings, options?.onProgress, options?.tables !== false, vectorPageOps, regionPages);
|
|
@@ -3015,6 +3196,28 @@ async function parsePdfDocument(buffer, options) {
|
|
|
3015
3196
|
return b.bbox.y > h * 0.1 && b.bbox.y + b.bbox.height < h * 0.9;
|
|
3016
3197
|
});
|
|
3017
3198
|
joinLatinCellWraps(outBlocks);
|
|
3199
|
+
if (options?.layoutTables !== "keep" && await isHancomPdf(doc)) {
|
|
3200
|
+
const shown = /* @__PURE__ */ new Map();
|
|
3201
|
+
const markContent = (bs) => {
|
|
3202
|
+
for (const b of bs ?? []) if (b.table) for (const row of b.table.cells) for (const c of row) {
|
|
3203
|
+
if (IMAGE_CELLS.has(c)) CONTENT_CELLS.add(c);
|
|
3204
|
+
markContent(c.blocks);
|
|
3205
|
+
}
|
|
3206
|
+
};
|
|
3207
|
+
const visual = (bs) => bs.flatMap((b) => {
|
|
3208
|
+
if (b.type !== "table") return [b];
|
|
3209
|
+
let v = shown.get(b);
|
|
3210
|
+
if (!v) {
|
|
3211
|
+
markContent([b]);
|
|
3212
|
+
shown.set(b, v = unframeLayoutTables([b], !!options?.keepTrailingEmptyCols));
|
|
3213
|
+
}
|
|
3214
|
+
return v;
|
|
3215
|
+
});
|
|
3216
|
+
outBlocks = visual(outBlocks);
|
|
3217
|
+
const kept = visual(blocks);
|
|
3218
|
+
blocks.length = 0;
|
|
3219
|
+
for (const b of kept) blocks.push(b);
|
|
3220
|
+
}
|
|
3018
3221
|
const finishMarkdown = (bs) => mergeLinkRuns(cleanPdfText(blocksToMarkdown(bs), { keepLoneNumbers: true }));
|
|
3019
3222
|
let markdown = finishMarkdown(outBlocks);
|
|
3020
3223
|
return {
|
|
@@ -3051,6 +3254,14 @@ async function extractPdfMetadata(doc, metadata) {
|
|
|
3051
3254
|
} catch {
|
|
3052
3255
|
}
|
|
3053
3256
|
}
|
|
3257
|
+
async function isHancomPdf(doc) {
|
|
3258
|
+
try {
|
|
3259
|
+
const info = (await doc.getMetadata())?.info;
|
|
3260
|
+
return [info?.Producer, info?.Creator].some((v) => typeof v === "string" && /^\s*(?:hancom\b|hwp\b)/i.test(v));
|
|
3261
|
+
} catch {
|
|
3262
|
+
return false;
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3054
3265
|
function parsePdfDate(dateStr) {
|
|
3055
3266
|
const m = dateStr.match(/D:(\d{4})(\d{2})?(\d{2})?(\d{2})?(\d{2})?(\d{2})?/);
|
|
3056
3267
|
if (!m) return void 0;
|
|
@@ -3090,4 +3301,4 @@ export {
|
|
|
3090
3301
|
parsePdfDocument,
|
|
3091
3302
|
removeHeaderFooterBlocks
|
|
3092
3303
|
};
|
|
3093
|
-
//# sourceMappingURL=parser-
|
|
3304
|
+
//# sourceMappingURL=parser-CTRB7PKD.js.map
|