kordoc 4.17.1 → 4.17.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 +3 -0
- package/dist/{-UNMTWAEI.js → -2UA2JHVA.js} +10 -10
- package/dist/{chunk-B4PUQ4FP.js → chunk-2XHXABCX.js} +2 -2
- package/dist/{chunk-MPAN6S5O.js → chunk-3N272C5L.js} +243 -114
- package/dist/chunk-3N272C5L.js.map +1 -0
- package/dist/{chunk-EULS3PDF.js → chunk-4HRJISJF.js} +3 -3
- package/dist/{chunk-KBIQGGNY.js → chunk-4TSYMJDL.js} +242 -113
- package/dist/chunk-4TSYMJDL.js.map +1 -0
- package/dist/{chunk-3M2BMQJY.js → chunk-5JZEY5IL.js} +119 -77
- package/dist/chunk-5JZEY5IL.js.map +1 -0
- package/dist/{chunk-5FCLQVT5.cjs → chunk-6DOCSYEM.cjs} +113 -71
- package/dist/chunk-6DOCSYEM.cjs.map +1 -0
- package/dist/{chunk-N6MPDM55.js → chunk-6OCKAXIS.js} +2 -2
- package/dist/{chunk-QXNQ2HNB.js → chunk-A2W2JQ3S.js} +2 -2
- package/dist/{chunk-66YTQ3NQ.js → chunk-C4MVZXB5.js} +2 -2
- package/dist/{chunk-GYHY2YLV.js → chunk-FGL4IGOT.js} +4 -4
- package/dist/{chunk-BEJYCCDN.cjs → chunk-GPC72VSF.cjs} +6 -6
- package/dist/chunk-GPC72VSF.cjs.map +1 -0
- package/dist/chunk-GS7T56RP.cjs.map +1 -1
- package/dist/{chunk-FMP4POMD.js → chunk-GYTL6WT3.js} +3 -3
- package/dist/{chunk-4NH45EEB.cjs → chunk-HAW2VL62.cjs} +12 -12
- package/dist/chunk-HAW2VL62.cjs.map +1 -0
- package/dist/chunk-J55UQC5H.cjs.map +1 -1
- package/dist/{chunk-ELNYQRBN.js → chunk-JY2NBFIG.js} +14 -12
- package/dist/chunk-JY2NBFIG.js.map +1 -0
- package/dist/{chunk-BQAJHAWR.js → chunk-KQIYC2ZU.js} +2 -2
- package/dist/{chunk-GRHSVGSB.cjs → chunk-KZVQK5NS.cjs} +2 -2
- package/dist/chunk-KZVQK5NS.cjs.map +1 -0
- package/dist/{chunk-AUFO5LVN.js → chunk-MDCTITUG.js} +2 -2
- package/dist/{chunk-OVSCNCT6.js → chunk-O4CB7D2Q.js} +2 -2
- package/dist/{chunk-3J3BJIOZ.js → chunk-SDRKHEVT.js} +2 -2
- package/dist/{chunk-HAPCN7BD.js → chunk-VU26WGE5.js} +37 -15
- package/dist/chunk-VU26WGE5.js.map +1 -0
- package/dist/{chunk-BHUYJBSQ.js → chunk-WJLICIYV.js} +2 -2
- package/dist/{chunk-ZRXQDJPM.cjs → chunk-WWMKIHF7.cjs} +336 -207
- package/dist/chunk-WWMKIHF7.cjs.map +1 -0
- package/dist/{chunk-MY6Q2HFW.js → chunk-XZA6X34R.js} +121 -77
- package/dist/chunk-XZA6X34R.js.map +1 -0
- package/dist/{chunk-4CSY3QUO.js → chunk-YGKC6E6A.js} +2 -2
- package/dist/chunk-YIANW5QX.cjs.map +1 -1
- package/dist/{chunk-E6TJNN2U.js → chunk-ZDX5PIWR.js} +2 -2
- package/dist/chunks-EBWJR55V.js +10 -0
- package/dist/cli.js +25 -25
- package/dist/{formula-K7UF5MBF.cjs → formula-5RETDCIC.cjs} +9 -9
- package/dist/formula-5RETDCIC.cjs.map +1 -0
- package/dist/{formula-VH545WNH.js → formula-MBLN2DG4.js} +4 -4
- package/dist/{formula-3GB47YTH.js → formula-QZZDW5GW.js} +3 -3
- package/dist/{image-ocr-6AKQWAU2.js → image-ocr-CJSO3QSR.js} +7 -7
- package/dist/{image-ocr-VJFZCFAI.js → image-ocr-EREKAS47.js} +5 -5
- package/dist/{image-ocr-ZPQTFYSK.cjs → image-ocr-PSPVRLB5.cjs} +14 -14
- package/dist/image-ocr-PSPVRLB5.cjs.map +1 -0
- package/dist/index.cjs +612 -588
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +41 -17
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +21 -21
- package/dist/{model-bundle-P2XOZ76Q.js → model-bundle-MA4MMCRJ.js} +5 -5
- package/dist/{models-GPHBC2YJ.js → models-SEJ7LNSN.js} +5 -5
- package/dist/page-range-QHHFTL7X.cjs.map +1 -1
- package/dist/{parser-YIIRSBZS.js → parser-M5WHRX25.js} +40 -22
- package/dist/parser-M5WHRX25.js.map +1 -0
- package/dist/{parser-6SPYH3RU.cjs → parser-QILYPWSI.cjs} +211 -193
- package/dist/parser-QILYPWSI.cjs.map +1 -0
- package/dist/{parser-BVUFTU2O.js → parser-VH3F4EQU.js} +37 -19
- package/dist/parser-VH3F4EQU.js.map +1 -0
- package/dist/pdf-ocr-3SZUM3CN.cjs +16 -0
- package/dist/pdf-ocr-3SZUM3CN.cjs.map +1 -0
- package/dist/pdf-ocr-QB2TB5W5.js +18 -0
- package/dist/pdf-ocr-XC33L43D.js +15 -0
- package/dist/{profile-io-GU45HTYP.js → profile-io-5YB627EO.js} +3 -3
- package/dist/{rasterize-OWHFWG6R.js → rasterize-V2XHHS2I.js} +3 -3
- package/dist/{redact-doc-YTP6AAUP.js → redact-doc-5MK5L5IQ.js} +10 -10
- package/dist/{render-525LXDMV.js → render-SYZMHYK6.js} +6 -6
- package/dist/seal-IPKIQHYB.js +10 -0
- package/dist/{setup-NOXZLS7G.js → setup-ZPLJENSK.js} +3 -3
- package/dist/visual-RTTGNOAE.js +20 -0
- package/dist/{watch-NDRTCLVT.js → watch-FNWHVKK3.js} +11 -11
- package/package.json +1 -1
- package/dist/chunk-3M2BMQJY.js.map +0 -1
- package/dist/chunk-4NH45EEB.cjs.map +0 -1
- package/dist/chunk-5FCLQVT5.cjs.map +0 -1
- package/dist/chunk-BEJYCCDN.cjs.map +0 -1
- package/dist/chunk-ELNYQRBN.js.map +0 -1
- package/dist/chunk-GRHSVGSB.cjs.map +0 -1
- package/dist/chunk-HAPCN7BD.js.map +0 -1
- package/dist/chunk-KBIQGGNY.js.map +0 -1
- package/dist/chunk-MPAN6S5O.js.map +0 -1
- package/dist/chunk-MY6Q2HFW.js.map +0 -1
- package/dist/chunk-ZRXQDJPM.cjs.map +0 -1
- package/dist/chunks-P5Y7V73K.js +0 -10
- package/dist/formula-K7UF5MBF.cjs.map +0 -1
- package/dist/image-ocr-ZPQTFYSK.cjs.map +0 -1
- package/dist/parser-6SPYH3RU.cjs.map +0 -1
- package/dist/parser-BVUFTU2O.js.map +0 -1
- package/dist/parser-YIIRSBZS.js.map +0 -1
- package/dist/pdf-ocr-5YBMXW54.js +0 -18
- package/dist/pdf-ocr-EAVNHK3V.js +0 -15
- package/dist/pdf-ocr-J5GB5BW6.cjs +0 -16
- package/dist/pdf-ocr-J5GB5BW6.cjs.map +0 -1
- package/dist/seal-S4KJGZUI.js +0 -10
- package/dist/visual-AU3NH6EO.js +0 -20
- /package/dist/{-UNMTWAEI.js.map → -2UA2JHVA.js.map} +0 -0
- /package/dist/{chunk-B4PUQ4FP.js.map → chunk-2XHXABCX.js.map} +0 -0
- /package/dist/{chunk-EULS3PDF.js.map → chunk-4HRJISJF.js.map} +0 -0
- /package/dist/{chunk-N6MPDM55.js.map → chunk-6OCKAXIS.js.map} +0 -0
- /package/dist/{chunk-QXNQ2HNB.js.map → chunk-A2W2JQ3S.js.map} +0 -0
- /package/dist/{chunk-66YTQ3NQ.js.map → chunk-C4MVZXB5.js.map} +0 -0
- /package/dist/{chunk-GYHY2YLV.js.map → chunk-FGL4IGOT.js.map} +0 -0
- /package/dist/{chunk-FMP4POMD.js.map → chunk-GYTL6WT3.js.map} +0 -0
- /package/dist/{chunk-BQAJHAWR.js.map → chunk-KQIYC2ZU.js.map} +0 -0
- /package/dist/{chunk-AUFO5LVN.js.map → chunk-MDCTITUG.js.map} +0 -0
- /package/dist/{chunk-OVSCNCT6.js.map → chunk-O4CB7D2Q.js.map} +0 -0
- /package/dist/{chunk-3J3BJIOZ.js.map → chunk-SDRKHEVT.js.map} +0 -0
- /package/dist/{chunk-BHUYJBSQ.js.map → chunk-WJLICIYV.js.map} +0 -0
- /package/dist/{chunk-4CSY3QUO.js.map → chunk-YGKC6E6A.js.map} +0 -0
- /package/dist/{chunk-E6TJNN2U.js.map → chunk-ZDX5PIWR.js.map} +0 -0
- /package/dist/{chunks-P5Y7V73K.js.map → chunks-EBWJR55V.js.map} +0 -0
- /package/dist/{formula-VH545WNH.js.map → formula-MBLN2DG4.js.map} +0 -0
- /package/dist/{formula-3GB47YTH.js.map → formula-QZZDW5GW.js.map} +0 -0
- /package/dist/{image-ocr-6AKQWAU2.js.map → image-ocr-CJSO3QSR.js.map} +0 -0
- /package/dist/{image-ocr-VJFZCFAI.js.map → image-ocr-EREKAS47.js.map} +0 -0
- /package/dist/{model-bundle-P2XOZ76Q.js.map → model-bundle-MA4MMCRJ.js.map} +0 -0
- /package/dist/{models-GPHBC2YJ.js.map → models-SEJ7LNSN.js.map} +0 -0
- /package/dist/{pdf-ocr-5YBMXW54.js.map → pdf-ocr-QB2TB5W5.js.map} +0 -0
- /package/dist/{pdf-ocr-EAVNHK3V.js.map → pdf-ocr-XC33L43D.js.map} +0 -0
- /package/dist/{profile-io-GU45HTYP.js.map → profile-io-5YB627EO.js.map} +0 -0
- /package/dist/{rasterize-OWHFWG6R.js.map → rasterize-V2XHHS2I.js.map} +0 -0
- /package/dist/{redact-doc-YTP6AAUP.js.map → redact-doc-5MK5L5IQ.js.map} +0 -0
- /package/dist/{render-525LXDMV.js.map → render-SYZMHYK6.js.map} +0 -0
- /package/dist/{seal-S4KJGZUI.js.map → seal-IPKIQHYB.js.map} +0 -0
- /package/dist/{setup-NOXZLS7G.js.map → setup-ZPLJENSK.js.map} +0 -0
- /package/dist/{visual-AU3NH6EO.js.map → visual-RTTGNOAE.js.map} +0 -0
- /package/dist/{watch-NDRTCLVT.js.map → watch-FNWHVKK3.js.map} +0 -0
|
@@ -8,11 +8,11 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
ensureModelsIn,
|
|
10
10
|
getModelsDir
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-5JZEY5IL.js";
|
|
12
12
|
import {
|
|
13
13
|
safeMax,
|
|
14
14
|
safeMin
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-YGKC6E6A.js";
|
|
16
16
|
|
|
17
17
|
// src/ocr/models.ts
|
|
18
18
|
import { join } from "path";
|
|
@@ -728,19 +728,34 @@ function multiplyTransform(m, t) {
|
|
|
728
728
|
m[1] * t[4] + m[3] * t[5] + m[5]
|
|
729
729
|
];
|
|
730
730
|
}
|
|
731
|
-
function
|
|
731
|
+
function transformedRect(ctm, x, y, w, h) {
|
|
732
|
+
const corners = [[x, y], [x + w, y], [x, y + h], [x + w, y + h]];
|
|
733
|
+
const xs = corners.map(([u, v]) => ctm[0] * u + ctm[2] * v + ctm[4]);
|
|
734
|
+
const ys = corners.map(([u, v]) => ctm[1] * u + ctm[3] * v + ctm[5]);
|
|
735
|
+
return { x1: Math.min(...xs), y1: Math.min(...ys), x2: Math.max(...xs), y2: Math.max(...ys) };
|
|
736
|
+
}
|
|
737
|
+
function intersect(a, b) {
|
|
738
|
+
return b ? { x1: Math.max(a.x1, b.x1), y1: Math.max(a.y1, b.y1), x2: Math.min(a.x2, b.x2), y2: Math.min(a.y2, b.y2) } : a;
|
|
739
|
+
}
|
|
740
|
+
function extractImageRegions(fnArray, argsArray, respectClip = false) {
|
|
732
741
|
const regions = [];
|
|
733
742
|
let ctm = [1, 0, 0, 1, 0, 0];
|
|
743
|
+
let clip = null;
|
|
734
744
|
const stack = [];
|
|
745
|
+
let pathRect;
|
|
746
|
+
let pendingClip = false;
|
|
735
747
|
for (let i = 0; i < fnArray.length; i++) {
|
|
736
748
|
const op = fnArray[i];
|
|
737
749
|
switch (op) {
|
|
738
750
|
case OPS2.save:
|
|
739
|
-
stack.push(ctm);
|
|
751
|
+
stack.push({ ctm, clip });
|
|
740
752
|
break;
|
|
741
|
-
case OPS2.restore:
|
|
742
|
-
|
|
753
|
+
case OPS2.restore: {
|
|
754
|
+
const state = stack.pop();
|
|
755
|
+
ctm = state?.ctm ?? [1, 0, 0, 1, 0, 0];
|
|
756
|
+
clip = state?.clip ?? null;
|
|
743
757
|
break;
|
|
758
|
+
}
|
|
744
759
|
case OPS2.transform: {
|
|
745
760
|
const t = argsArray[i];
|
|
746
761
|
if (Array.isArray(t) && t.length >= 6) ctm = multiplyTransform(ctm, t);
|
|
@@ -748,28 +763,44 @@ function extractImageRegions(fnArray, argsArray) {
|
|
|
748
763
|
}
|
|
749
764
|
// Form XObject 는 /Matrix 공간에서 그린다 — pdfjs 인자 [matrix, bbox], End 에서 복원 (line-extract.ts 와 같음)
|
|
750
765
|
case OPS2.paintFormXObjectBegin: {
|
|
751
|
-
stack.push(ctm);
|
|
766
|
+
stack.push({ ctm, clip });
|
|
752
767
|
const m = argsArray[i]?.[0];
|
|
753
768
|
if (Array.isArray(m) && m.length >= 6) ctm = multiplyTransform(ctm, m);
|
|
754
769
|
break;
|
|
755
770
|
}
|
|
756
|
-
case OPS2.paintFormXObjectEnd:
|
|
757
|
-
|
|
771
|
+
case OPS2.paintFormXObjectEnd: {
|
|
772
|
+
const state = stack.pop();
|
|
773
|
+
ctm = state?.ctm ?? [1, 0, 0, 1, 0, 0];
|
|
774
|
+
clip = state?.clip ?? null;
|
|
775
|
+
break;
|
|
776
|
+
}
|
|
777
|
+
case OPS2.constructPath: {
|
|
778
|
+
const [ops, coords] = argsArray[i];
|
|
779
|
+
pathRect = pathRect === void 0 && ops?.length === 1 && ops[0] === OPS2.rectangle && coords?.length >= 4 ? transformedRect(ctm, coords[0], coords[1], coords[2], coords[3]) : null;
|
|
780
|
+
break;
|
|
781
|
+
}
|
|
782
|
+
case OPS2.clip:
|
|
783
|
+
case OPS2.eoClip:
|
|
784
|
+
pendingClip = true;
|
|
785
|
+
break;
|
|
786
|
+
case OPS2.endPath:
|
|
787
|
+
case OPS2.stroke:
|
|
788
|
+
case OPS2.closeStroke:
|
|
789
|
+
case OPS2.fill:
|
|
790
|
+
case OPS2.eoFill:
|
|
791
|
+
case OPS2.fillStroke:
|
|
792
|
+
case OPS2.eoFillStroke:
|
|
793
|
+
case OPS2.closeFillStroke:
|
|
794
|
+
case OPS2.closeEOFillStroke:
|
|
795
|
+
if (respectClip && pendingClip && pathRect) clip = intersect(pathRect, clip);
|
|
796
|
+
pathRect = void 0;
|
|
797
|
+
pendingClip = false;
|
|
758
798
|
break;
|
|
759
799
|
case OPS2.paintImageXObject:
|
|
760
800
|
case OPS2.paintInlineImageXObject:
|
|
761
801
|
case OPS2.paintImageMaskXObject:
|
|
762
802
|
case OPS2.paintImageXObjectRepeat: {
|
|
763
|
-
const
|
|
764
|
-
let x1 = Infinity, y1 = Infinity, x2 = -Infinity, y2 = -Infinity;
|
|
765
|
-
for (const [u, v] of corners) {
|
|
766
|
-
const x = ctm[0] * u + ctm[2] * v + ctm[4];
|
|
767
|
-
const y = ctm[1] * u + ctm[3] * v + ctm[5];
|
|
768
|
-
if (x < x1) x1 = x;
|
|
769
|
-
if (x > x2) x2 = x;
|
|
770
|
-
if (y < y1) y1 = y;
|
|
771
|
-
if (y > y2) y2 = y;
|
|
772
|
-
}
|
|
803
|
+
const { x1, y1, x2, y2 } = intersect(transformedRect(ctm, 0, 0, 1, 1), clip);
|
|
773
804
|
if (x2 - x1 > 0 && y2 - y1 > 0) regions.push({ x1, y1, x2, y2 });
|
|
774
805
|
break;
|
|
775
806
|
}
|
|
@@ -2278,6 +2309,10 @@ function cellLineFills(box, contentLeft, cellRight, lineRight, fontSize) {
|
|
|
2278
2309
|
// src/pdf/cell-text.ts
|
|
2279
2310
|
var REGION_LABELS = /* @__PURE__ */ new Set(["\uC11C\uC6B8", "\uBD80\uC0B0", "\uB300\uAD6C", "\uC778\uCC9C", "\uAD11\uC8FC", "\uB300\uC804", "\uC6B8\uC0B0", "\uC138\uC885", "\uACBD\uAE30", "\uAC15\uC6D0", "\uCDA9\uBD81", "\uCDA9\uB0A8", "\uC804\uBD81", "\uC804\uB0A8", "\uACBD\uBD81", "\uACBD\uB0A8", "\uC81C\uC8FC", "\uC804\uAD6D"]);
|
|
2280
2311
|
var CELL_PADDING = 2;
|
|
2312
|
+
function cleanCellText(text) {
|
|
2313
|
+
const stripped = text.replace(/^[\s]*[-–—]\s*\d+\s*[-–—][\s]*$/gm, "").trim();
|
|
2314
|
+
return stripped.split("\n").map((line) => collapseEvenSpacing(line)).join("\n");
|
|
2315
|
+
}
|
|
2281
2316
|
var SPACE_GAP_RATIO = 0.17;
|
|
2282
2317
|
function spaceGapThreshold(fontSize) {
|
|
2283
2318
|
return Math.max(fontSize * SPACE_GAP_RATIO, 1);
|
|
@@ -2287,11 +2322,12 @@ function mapTextToCells(items, cells) {
|
|
|
2287
2322
|
for (const cell of cells) {
|
|
2288
2323
|
result.set(cell, []);
|
|
2289
2324
|
}
|
|
2325
|
+
const candidates = items.length * cells.length >= 5e3 ? cellBandLookup(cells) : () => cells;
|
|
2290
2326
|
for (const item of items) {
|
|
2291
2327
|
const pad = CELL_PADDING;
|
|
2292
2328
|
let bestCell = null;
|
|
2293
2329
|
let bestScore = 0;
|
|
2294
|
-
for (const cell of
|
|
2330
|
+
for (const cell of candidates(item.y - pad, item.y + (item.h || item.fontSize) + pad)) {
|
|
2295
2331
|
const ix1 = Math.max(item.x, cell.bbox.x1 - pad);
|
|
2296
2332
|
const ix2 = Math.min(item.x + item.w, cell.bbox.x2 + pad);
|
|
2297
2333
|
const iy1 = Math.max(item.y, cell.bbox.y1 - pad);
|
|
@@ -2312,6 +2348,39 @@ function mapTextToCells(items, cells) {
|
|
|
2312
2348
|
keepWordsInOneCell(result);
|
|
2313
2349
|
return result;
|
|
2314
2350
|
}
|
|
2351
|
+
function cellBandLookup(cells) {
|
|
2352
|
+
const sorted = cells.map((cell, index) => ({ cell, index })).sort((a, b) => a.cell.bbox.y1 - b.cell.bbox.y1);
|
|
2353
|
+
const build = (start, end) => {
|
|
2354
|
+
let lo = Infinity, hi = -Infinity;
|
|
2355
|
+
for (let i = start; i < end; i++) {
|
|
2356
|
+
lo = Math.min(lo, sorted[i].cell.bbox.y1);
|
|
2357
|
+
hi = Math.max(hi, sorted[i].cell.bbox.y2);
|
|
2358
|
+
}
|
|
2359
|
+
const band = { start, end, lo, hi };
|
|
2360
|
+
if (end - start > 8) {
|
|
2361
|
+
const mid = start + end >> 1;
|
|
2362
|
+
band.left = build(start, mid);
|
|
2363
|
+
band.right = build(mid, end);
|
|
2364
|
+
}
|
|
2365
|
+
return band;
|
|
2366
|
+
};
|
|
2367
|
+
const root = build(0, sorted.length);
|
|
2368
|
+
return (lo, hi) => {
|
|
2369
|
+
const found = [];
|
|
2370
|
+
const visit = (band) => {
|
|
2371
|
+
if (band.hi <= lo || band.lo >= hi) return;
|
|
2372
|
+
if (band.left && band.right) {
|
|
2373
|
+
visit(band.left);
|
|
2374
|
+
visit(band.right);
|
|
2375
|
+
} else for (let i = band.start; i < band.end; i++) {
|
|
2376
|
+
const entry = sorted[i];
|
|
2377
|
+
if (entry.cell.bbox.y2 > lo && entry.cell.bbox.y1 < hi) found.push(entry);
|
|
2378
|
+
}
|
|
2379
|
+
};
|
|
2380
|
+
visit(root);
|
|
2381
|
+
return found.sort((a, b) => a.index - b.index).map((entry) => entry.cell);
|
|
2382
|
+
};
|
|
2383
|
+
}
|
|
2315
2384
|
function keepWordsInOneCell(result) {
|
|
2316
2385
|
const owner = /* @__PURE__ */ new Map();
|
|
2317
2386
|
for (const [cell, arr] of result) for (const it of arr) owner.set(it, cell);
|
|
@@ -2367,9 +2436,8 @@ function cellTextToString(items, wrap) {
|
|
|
2367
2436
|
}
|
|
2368
2437
|
}
|
|
2369
2438
|
lines.push(curLine);
|
|
2370
|
-
const merged = mergeSuperscriptRows(lines);
|
|
2371
|
-
const textLines = merged.map((
|
|
2372
|
-
const s = sortLineByX(line);
|
|
2439
|
+
const merged = mergeSuperscriptRows(lines).map((line) => sortLineByX(line));
|
|
2440
|
+
const textLines = merged.map((s) => {
|
|
2373
2441
|
if (s.length === 1) return s[0].text;
|
|
2374
2442
|
if (s.length === 2 && /^[가-힣]$/.test(s[0].text) && /^[가-힣]$/.test(s[1].text) && !!wrap?.lex && (wrap.lex.isWord(s[0].text + s[1].text) || wrap.lex.evidence(s[0].text, s[1].text) === "" || REGION_LABELS.has(s[0].text + s[1].text)) && s[1].x - (s[0].x + s[0].w) >= Math.max(s[0].fontSize, s[1].fontSize) * 1.5 && s[1].x + s[1].w - s[0].x >= wrap.box.x2 - wrap.box.x1 - Math.max(s[0].fontSize, s[1].fontSize) * 2) return s[0].text + s[1].text;
|
|
2375
2443
|
const evenSpaced = detectEvenSpacedItems(s, true);
|
|
@@ -2393,16 +2461,16 @@ function cellTextToString(items, wrap) {
|
|
|
2393
2461
|
}
|
|
2394
2462
|
return result;
|
|
2395
2463
|
});
|
|
2396
|
-
const scripted = (s) => tagScripts(s, merged
|
|
2464
|
+
const scripted = (s) => tagScripts(s, merged);
|
|
2397
2465
|
if (!wrap) return scripted(mergeCellTextLines(textLines));
|
|
2398
2466
|
let contentLeft = Infinity;
|
|
2399
2467
|
for (const it of items) if (it.x < contentLeft) contentLeft = it.x;
|
|
2400
|
-
const lineEnds = merged.map((
|
|
2401
|
-
const s = sortLineByX(line);
|
|
2468
|
+
const lineEnds = merged.map((s) => {
|
|
2402
2469
|
let right = -Infinity;
|
|
2403
2470
|
for (const it of s) if (it.x + it.w > right) right = it.x + it.w;
|
|
2404
2471
|
const first = s[0];
|
|
2405
|
-
|
|
2472
|
+
const visible = first.text.replace(/<\/?u>|~~/g, "");
|
|
2473
|
+
return { right, fontSize: first.fontSize, firstCharW: first.w / Math.max(1, [...visible].length) };
|
|
2406
2474
|
});
|
|
2407
2475
|
let cellRight = -Infinity;
|
|
2408
2476
|
for (const e of lineEnds) if (e.right > cellRight) cellRight = e.right;
|
|
@@ -2446,15 +2514,16 @@ function mergeSuperscriptRows(lines) {
|
|
|
2446
2514
|
function detectEvenSpacedItems(items, cellLine = false) {
|
|
2447
2515
|
const result = new Array(items.length).fill(false);
|
|
2448
2516
|
if (items.length < 3) return result;
|
|
2449
|
-
|
|
2450
|
-
|
|
2517
|
+
const visible = items.map((it) => it.text.replace(/<\/?u>|~~/g, ""));
|
|
2518
|
+
if (cellLine && visible.every((text) => /^[가-힣]$/.test(text)) && items.slice(1).every((it) => !it.hasSpaceBefore || it.syntheticSpace) && items.slice(1).every((it, k) => it.x - (items[k].x + items[k].w) >= it.fontSize * 0.1)) {
|
|
2519
|
+
markEvenRun(items, visible, result, 0, items.length);
|
|
2451
2520
|
if (result.some(Boolean)) return result;
|
|
2452
2521
|
}
|
|
2453
2522
|
let runStart = -1;
|
|
2454
2523
|
for (let i = 0; i < items.length; i++) {
|
|
2455
|
-
const isShortKorean = /^[가-힣]{1}$/.test(
|
|
2524
|
+
const isShortKorean = /^[가-힣]{1}$/.test(visible[i]) || /^[\d]{1}$/.test(visible[i]);
|
|
2456
2525
|
if (isShortKorean && runStart >= 0 && items[i].hasSpaceBefore) {
|
|
2457
|
-
if (i - runStart >= 3) markEvenRun(items, result, runStart, i);
|
|
2526
|
+
if (i - runStart >= 3) markEvenRun(items, visible, result, runStart, i);
|
|
2458
2527
|
runStart = i;
|
|
2459
2528
|
continue;
|
|
2460
2529
|
}
|
|
@@ -2462,7 +2531,7 @@ function detectEvenSpacedItems(items, cellLine = false) {
|
|
|
2462
2531
|
const gap = items[i].x - (items[i - 1].x + items[i - 1].w);
|
|
2463
2532
|
const maxRunGap = Math.max(items[i].fontSize * 3, 30);
|
|
2464
2533
|
if (gap > maxRunGap) {
|
|
2465
|
-
if (i - runStart >= 3) markEvenRun(items, result, runStart, i);
|
|
2534
|
+
if (i - runStart >= 3) markEvenRun(items, visible, result, runStart, i);
|
|
2466
2535
|
runStart = i;
|
|
2467
2536
|
continue;
|
|
2468
2537
|
}
|
|
@@ -2471,19 +2540,19 @@ function detectEvenSpacedItems(items, cellLine = false) {
|
|
|
2471
2540
|
if (runStart < 0) runStart = i;
|
|
2472
2541
|
} else {
|
|
2473
2542
|
if (runStart >= 0 && i - runStart >= 3) {
|
|
2474
|
-
markEvenRun(items, result, runStart, i);
|
|
2543
|
+
markEvenRun(items, visible, result, runStart, i);
|
|
2475
2544
|
}
|
|
2476
2545
|
runStart = -1;
|
|
2477
2546
|
}
|
|
2478
2547
|
}
|
|
2479
2548
|
if (runStart >= 0 && items.length - runStart >= 3) {
|
|
2480
|
-
markEvenRun(items, result, runStart, items.length);
|
|
2549
|
+
markEvenRun(items, visible, result, runStart, items.length);
|
|
2481
2550
|
}
|
|
2482
2551
|
return result;
|
|
2483
2552
|
}
|
|
2484
|
-
function markEvenRun(items, result, start, end) {
|
|
2553
|
+
function markEvenRun(items, visible, result, start, end) {
|
|
2485
2554
|
let dateOnly = true;
|
|
2486
|
-
for (let i = start; i < end; i++) if (!/^[년월일시분초]$/.test(
|
|
2555
|
+
for (let i = start; i < end; i++) if (!/^[년월일시분초]$/.test(visible[i])) {
|
|
2487
2556
|
dateOnly = false;
|
|
2488
2557
|
break;
|
|
2489
2558
|
}
|
|
@@ -2705,14 +2774,20 @@ function filterHiddenText(items, pageWidth, pageHeight, originX = 0, originY = 0
|
|
|
2705
2774
|
return { visible, hiddenCount };
|
|
2706
2775
|
}
|
|
2707
2776
|
function collapseEvenSpacing(text, whole = true) {
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2777
|
+
if (whole) {
|
|
2778
|
+
const tokens = text.split(" ");
|
|
2779
|
+
const visible = tokens.map((t) => t.replace(/<\/?u>|~~/g, ""));
|
|
2780
|
+
const singleCharCount = visible.filter((t) => t.length === 1).length;
|
|
2781
|
+
if (tokens.length >= 3 && singleCharCount / tokens.length >= 0.7 && !isDateUnitBlank(visible)) return tokens.join("");
|
|
2712
2782
|
}
|
|
2713
2783
|
return text.replace(
|
|
2714
2784
|
/(?<![^\s>])[가-힣](?: [가-힣\d]){2,}(?![^\s<])/g,
|
|
2715
|
-
(match) =>
|
|
2785
|
+
(match, offset) => {
|
|
2786
|
+
const before = text.slice(0, offset).replace(/(?:<\/?u>|~~)+$/, "");
|
|
2787
|
+
const after = text.slice(offset + match.length).replace(/^(?:<\/?u>|~~)+/, "");
|
|
2788
|
+
if (/\S$/.test(before) || /^\S/.test(after)) return match;
|
|
2789
|
+
return isDateUnitBlank(match.split(" ")) ? match : match.replace(/ /g, "");
|
|
2790
|
+
}
|
|
2716
2791
|
);
|
|
2717
2792
|
}
|
|
2718
2793
|
function isDateUnitBlank(tokens) {
|
|
@@ -5075,27 +5150,6 @@ function splitEdgeSpannedColumns(items, gapThreshold, depth) {
|
|
|
5075
5150
|
];
|
|
5076
5151
|
}
|
|
5077
5152
|
|
|
5078
|
-
// src/pdf/blank-fills.ts
|
|
5079
|
-
var FILL_EDGE_GAP = 6;
|
|
5080
|
-
var FILL_MAX_THICKNESS = 2;
|
|
5081
|
-
function fillBlanks(items, horizontals, verticals = []) {
|
|
5082
|
-
const widened = /* @__PURE__ */ new Map();
|
|
5083
|
-
const used = /* @__PURE__ */ new Set();
|
|
5084
|
-
for (const h of horizontals) {
|
|
5085
|
-
if (h.lineWidth > FILL_MAX_THICKNESS || Math.abs(h.y1 - h.y2) > 1) continue;
|
|
5086
|
-
const x1 = Math.min(h.x1, h.x2), x2 = Math.max(h.x1, h.x2);
|
|
5087
|
-
const row = items.filter((i) => i.y >= h.y1 && i.y - h.y1 <= Math.max(3, i.fontSize * 0.5));
|
|
5088
|
-
const left = row.find((i) => i.x + i.w <= x1 + 1 && x1 - (i.x + i.w) <= FILL_EDGE_GAP);
|
|
5089
|
-
const right = row.find((i) => i.x >= x2 - 1 && i.x - x2 <= FILL_EDGE_GAP);
|
|
5090
|
-
if (!left || !right || widened.has(left) || row.some((i) => i.x < x2 && i.x + i.w > x1) || x2 - x1 < 2 * left.fontSize) continue;
|
|
5091
|
-
if (verticals.some((v) => (Math.abs(v.x1 - x1) <= 3 || Math.abs(v.x1 - x2) <= 3) && Math.min(v.y1, v.y2) - 3 <= h.y1 && Math.max(v.y1, v.y2) + 3 >= h.y1)) continue;
|
|
5092
|
-
widened.set(left, { ...left, text: left.text.trimEnd() + " ", w: x2 - left.x });
|
|
5093
|
-
used.add(h);
|
|
5094
|
-
}
|
|
5095
|
-
if (!used.size) return { items, horizontals };
|
|
5096
|
-
return { items: items.map((i) => widened.get(i) ?? i), horizontals: horizontals.filter((h) => !used.has(h)) };
|
|
5097
|
-
}
|
|
5098
|
-
|
|
5099
5153
|
// src/pdf/two-column.ts
|
|
5100
5154
|
var GUTTER_SCAN_LO = 0.3;
|
|
5101
5155
|
var GUTTER_SCAN_HI = 0.7;
|
|
@@ -5330,6 +5384,55 @@ function orderByPanels(units, rectOf, gutters) {
|
|
|
5330
5384
|
return ordered;
|
|
5331
5385
|
}
|
|
5332
5386
|
|
|
5387
|
+
// src/pdf/image-panels.ts
|
|
5388
|
+
function splitImagePanels(items, figures) {
|
|
5389
|
+
if (figures.length === 0) return null;
|
|
5390
|
+
const rects = items.map((i) => ({ x: i.x, y: i.y, w: i.w, h: i.h > 0 ? i.h : i.fontSize }));
|
|
5391
|
+
const cuts = detectPanelGutters([...rects, ...figures]);
|
|
5392
|
+
if (!cuts || cuts.length !== 2 || items.some((i) => cuts.some((x) => i.x < x && i.x + i.w > x))) return null;
|
|
5393
|
+
const groups = [
|
|
5394
|
+
items.filter((i) => i.x + i.w <= cuts[0]),
|
|
5395
|
+
items.filter((i) => i.x >= cuts[0] && i.x + i.w <= cuts[1]),
|
|
5396
|
+
items.filter((i) => i.x >= cuts[1])
|
|
5397
|
+
];
|
|
5398
|
+
const rows = groupByY(items);
|
|
5399
|
+
const sharedRows = rows.filter((row) => new Set(row.map((i) => i.x >= cuts[1] ? 2 : i.x >= cuts[0] ? 1 : 0)).size === 3).length;
|
|
5400
|
+
if (sharedRows / Math.min(...groups.map((group) => groupByY(group).length)) > 0.65) return null;
|
|
5401
|
+
for (const row of rows) {
|
|
5402
|
+
const ordered = [...row].sort((a, b) => a.x - b.x);
|
|
5403
|
+
let start = ordered[0].x, end = start + ordered[0].w, height = ordered[0].h || ordered[0].fontSize;
|
|
5404
|
+
for (const i of ordered.slice(1)) {
|
|
5405
|
+
const h = i.h || i.fontSize;
|
|
5406
|
+
if (i.x - end > Math.max(height, h) * 2) start = i.x;
|
|
5407
|
+
end = Math.max(end, i.x + i.w);
|
|
5408
|
+
height = h;
|
|
5409
|
+
if (cuts.some((x) => start < x && end > x)) return null;
|
|
5410
|
+
}
|
|
5411
|
+
}
|
|
5412
|
+
return groups;
|
|
5413
|
+
}
|
|
5414
|
+
|
|
5415
|
+
// src/pdf/blank-fills.ts
|
|
5416
|
+
var FILL_EDGE_GAP = 6;
|
|
5417
|
+
var FILL_MAX_THICKNESS = 2;
|
|
5418
|
+
function fillBlanks(items, horizontals, verticals = []) {
|
|
5419
|
+
const widened = /* @__PURE__ */ new Map();
|
|
5420
|
+
const used = /* @__PURE__ */ new Set();
|
|
5421
|
+
for (const h of horizontals) {
|
|
5422
|
+
if (h.lineWidth > FILL_MAX_THICKNESS || Math.abs(h.y1 - h.y2) > 1) continue;
|
|
5423
|
+
const x1 = Math.min(h.x1, h.x2), x2 = Math.max(h.x1, h.x2);
|
|
5424
|
+
const row = items.filter((i) => i.y >= h.y1 && i.y - h.y1 <= Math.max(3, i.fontSize * 0.5));
|
|
5425
|
+
const left = row.find((i) => i.x + i.w <= x1 + 1 && x1 - (i.x + i.w) <= FILL_EDGE_GAP);
|
|
5426
|
+
const right = row.find((i) => i.x >= x2 - 1 && i.x - x2 <= FILL_EDGE_GAP);
|
|
5427
|
+
if (!left || !right || widened.has(left) || row.some((i) => i.x < x2 && i.x + i.w > x1) || x2 - x1 < 2 * left.fontSize) continue;
|
|
5428
|
+
if (verticals.some((v) => (Math.abs(v.x1 - x1) <= 3 || Math.abs(v.x1 - x2) <= 3) && Math.min(v.y1, v.y2) - 3 <= h.y1 && Math.max(v.y1, v.y2) + 3 >= h.y1)) continue;
|
|
5429
|
+
widened.set(left, { ...left, text: left.text.trimEnd() + " ", w: x2 - left.x });
|
|
5430
|
+
used.add(h);
|
|
5431
|
+
}
|
|
5432
|
+
if (!used.size) return { items, horizontals };
|
|
5433
|
+
return { items: items.map((i) => widened.get(i) ?? i), horizontals: horizontals.filter((h) => !used.has(h)) };
|
|
5434
|
+
}
|
|
5435
|
+
|
|
5333
5436
|
// src/pdf/columns.ts
|
|
5334
5437
|
function isProseSpread(items) {
|
|
5335
5438
|
if (items.length < 3) return false;
|
|
@@ -5575,8 +5678,8 @@ function markUnderlineItems(items, horizontals, verticals) {
|
|
|
5575
5678
|
if (items.length === 0 || horizontals.length === 0) return underlines;
|
|
5576
5679
|
for (const line of horizontals) {
|
|
5577
5680
|
if (line.lineWidth > UNDER_MAX_THICKNESS) continue;
|
|
5578
|
-
|
|
5579
|
-
if (isRepeatedSpanRule(line, horizontals)) continue;
|
|
5681
|
+
const enclosed = insideTallCell(line, verticals, 0);
|
|
5682
|
+
if (!enclosed && (touchesVertical(line, verticals) || isRepeatedSpanRule(line, horizontals))) continue;
|
|
5580
5683
|
const matches = [];
|
|
5581
5684
|
for (const item of items) {
|
|
5582
5685
|
const h = item.h > 0 ? item.h : item.fontSize;
|
|
@@ -5595,10 +5698,12 @@ function markUnderlineItems(items, horizontals, verticals) {
|
|
|
5595
5698
|
maxH = Math.max(maxH, m.h > 0 ? m.h : m.fontSize);
|
|
5596
5699
|
covered += m.w;
|
|
5597
5700
|
}
|
|
5701
|
+
const inset = enclosed && insideTallCell(line, verticals, maxH);
|
|
5702
|
+
if (enclosed && !inset && (touchesVertical(line, verticals) || isRepeatedSpanRule(line, horizontals))) continue;
|
|
5598
5703
|
const pad = Math.max(maxH * UNDER_OWNER_PAD_EM, UNDER_OWNER_PAD_MIN_PT);
|
|
5599
5704
|
if (line.x1 < x1 - pad || line.x2 > x2 + pad) continue;
|
|
5600
5705
|
if (covered < (line.x2 - line.x1) * UNDER_MIN_COVERAGE) continue;
|
|
5601
|
-
if (hasBoxTopPair(line, maxH, horizontals)) continue;
|
|
5706
|
+
if (hasBoxTopPair(line, maxH, horizontals, inset ? items : void 0)) continue;
|
|
5602
5707
|
matches.sort((a, b) => a.x - b.x);
|
|
5603
5708
|
let hole = false;
|
|
5604
5709
|
for (let i = 1; i < matches.length; i++) {
|
|
@@ -5613,6 +5718,18 @@ function markUnderlineItems(items, horizontals, verticals) {
|
|
|
5613
5718
|
}
|
|
5614
5719
|
return underlines;
|
|
5615
5720
|
}
|
|
5721
|
+
function insideTallCell(line, verticals, em) {
|
|
5722
|
+
let left = false, right = false;
|
|
5723
|
+
for (const v of verticals) {
|
|
5724
|
+
const lo = Math.min(v.y1, v.y2), hi = Math.max(v.y1, v.y2);
|
|
5725
|
+
if (lo > line.y1 || hi < line.y1) continue;
|
|
5726
|
+
if (v.x1 >= line.x1 - 0.5 && v.x1 <= line.x2 + 0.5) return false;
|
|
5727
|
+
if (hi - lo <= em * UNDER_BOX_PAIR_MAX_EM) continue;
|
|
5728
|
+
if (v.x1 < line.x1 - 0.5) left = true;
|
|
5729
|
+
if (v.x1 > line.x2 + 0.5) right = true;
|
|
5730
|
+
}
|
|
5731
|
+
return left && right;
|
|
5732
|
+
}
|
|
5616
5733
|
function touchesVertical(line, verticals) {
|
|
5617
5734
|
for (const v of verticals) {
|
|
5618
5735
|
if (v.x1 < line.x1 - UNDER_GRID_EPS || v.x1 > line.x2 + UNDER_GRID_EPS) continue;
|
|
@@ -5621,7 +5738,7 @@ function touchesVertical(line, verticals) {
|
|
|
5621
5738
|
}
|
|
5622
5739
|
return false;
|
|
5623
5740
|
}
|
|
5624
|
-
function hasBoxTopPair(line, maxH, horizontals) {
|
|
5741
|
+
function hasBoxTopPair(line, maxH, horizontals, cellItems) {
|
|
5625
5742
|
const w = line.x2 - line.x1;
|
|
5626
5743
|
if (w <= 0) return false;
|
|
5627
5744
|
for (const o of horizontals) {
|
|
@@ -5631,7 +5748,13 @@ function hasBoxTopPair(line, maxH, horizontals) {
|
|
|
5631
5748
|
const ow = o.x2 - o.x1;
|
|
5632
5749
|
if (ow <= 0) continue;
|
|
5633
5750
|
const overlap2 = Math.min(line.x2, o.x2) - Math.max(line.x1, o.x1);
|
|
5634
|
-
if (overlap2 / Math.max(w, ow)
|
|
5751
|
+
if (overlap2 / Math.max(w, ow) < UNDER_BOX_PAIR_OVERLAP) continue;
|
|
5752
|
+
const covered = cellItems?.reduce((sum, item) => {
|
|
5753
|
+
const below = item.y - o.y1;
|
|
5754
|
+
if (below < 0.5 || below > 3 || !item.text.trim()) return sum;
|
|
5755
|
+
return sum + Math.max(0, Math.min(o.x2, item.x + item.w) - Math.max(o.x1, item.x));
|
|
5756
|
+
}, 0) ?? 0;
|
|
5757
|
+
if (covered < ow * UNDER_MIN_COVERAGE) return true;
|
|
5635
5758
|
}
|
|
5636
5759
|
return false;
|
|
5637
5760
|
}
|
|
@@ -5712,21 +5835,21 @@ function rules(lines, dir) {
|
|
|
5712
5835
|
const sorted = [...lines].sort((a, b) => dir === "h" ? a.y1 - b.y1 : a.x1 - b.x1);
|
|
5713
5836
|
return { dir, pos: sorted.map((l) => dir === "h" ? l.y1 : l.x1), lines: sorted };
|
|
5714
5837
|
}
|
|
5715
|
-
function seen(r, at, a1, a2) {
|
|
5838
|
+
function seen(r, at, a1, a2, near = EDGE_NEAR2) {
|
|
5716
5839
|
const len = a2 - a1;
|
|
5717
5840
|
if (len <= 0) return false;
|
|
5718
|
-
const covered = coverage(r, at, a1, a2);
|
|
5841
|
+
const covered = coverage(r, at, a1, a2, near);
|
|
5719
5842
|
return covered >= len * EDGE_COVER && len - covered <= EDGE_SLACK;
|
|
5720
5843
|
}
|
|
5721
|
-
function coverage(r, at, a1, a2) {
|
|
5844
|
+
function coverage(r, at, a1, a2, near) {
|
|
5722
5845
|
let i = 0, j = r.pos.length;
|
|
5723
5846
|
while (i < j) {
|
|
5724
5847
|
const m = i + j >> 1;
|
|
5725
|
-
if (r.pos[m] < at -
|
|
5848
|
+
if (r.pos[m] < at - near) i = m + 1;
|
|
5726
5849
|
else j = m;
|
|
5727
5850
|
}
|
|
5728
5851
|
const spans = [];
|
|
5729
|
-
for (; i < r.pos.length && r.pos[i] <= at +
|
|
5852
|
+
for (; i < r.pos.length && r.pos[i] <= at + near; i++) {
|
|
5730
5853
|
const l = r.lines[i];
|
|
5731
5854
|
const l1 = r.dir === "h" ? Math.min(l.x1, l.x2) : Math.min(l.y1, l.y2), l2 = r.dir === "h" ? Math.max(l.x1, l.x2) : Math.max(l.y1, l.y2);
|
|
5732
5855
|
const lo = Math.max(a1, l1), hi = Math.min(a2, l2);
|
|
@@ -5746,10 +5869,10 @@ function coverage(r, at, a1, a2) {
|
|
|
5746
5869
|
}
|
|
5747
5870
|
return covered + e - s;
|
|
5748
5871
|
}
|
|
5749
|
-
function edgesOf(box, h, v) {
|
|
5872
|
+
function edgesOf(box, h, v, hNear = EDGE_NEAR2) {
|
|
5750
5873
|
return {
|
|
5751
|
-
t: seen(h, box.y2, box.x1, box.x2),
|
|
5752
|
-
b: seen(h, box.y1, box.x1, box.x2),
|
|
5874
|
+
t: seen(h, box.y2, box.x1, box.x2, hNear),
|
|
5875
|
+
b: seen(h, box.y1, box.x1, box.x2, hNear),
|
|
5753
5876
|
l: seen(v, box.x1, box.y1, box.y2),
|
|
5754
5877
|
r: seen(v, box.x2, box.y1, box.y2)
|
|
5755
5878
|
};
|
|
@@ -5758,7 +5881,10 @@ function recordClipCellEdges(grids, horizontals, verticals, nonRules) {
|
|
|
5758
5881
|
if (!grids.some((g) => g.cells)) return;
|
|
5759
5882
|
const h = rules(nonRules?.size ? horizontals.filter((l) => !nonRules.has(l)) : horizontals, "h");
|
|
5760
5883
|
const v = rules(nonRules?.size ? verticals.filter((l) => !nonRules.has(l)) : verticals, "v");
|
|
5761
|
-
for (const g of grids) for (const c of g.cells ?? [])
|
|
5884
|
+
for (const g of grids) for (const c of g.cells ?? []) {
|
|
5885
|
+
const near = c.filler ? Math.min(EDGE_NEAR2, (c.bbox.y2 - c.bbox.y1) / 3) : EDGE_NEAR2;
|
|
5886
|
+
CLIP_CELL_EDGES.set(c, edgesOf(c.bbox, h, v, near));
|
|
5887
|
+
}
|
|
5762
5888
|
}
|
|
5763
5889
|
function takeClipCellEdges(from, to) {
|
|
5764
5890
|
const e = CLIP_CELL_EDGES.get(from);
|
|
@@ -5770,6 +5896,36 @@ function joinCellEdges(a, b) {
|
|
|
5770
5896
|
CELL_EDGES.set(a, { t: u.t, b: d.b, l: u.l || d.l, r: u.r || d.r });
|
|
5771
5897
|
}
|
|
5772
5898
|
|
|
5899
|
+
// src/pdf/table-unit-row.ts
|
|
5900
|
+
var UNIT = /^\s*\(\s*단위\s*[::]/;
|
|
5901
|
+
function rebuildUnitLine(items, grid) {
|
|
5902
|
+
const nearby = items.filter((item) => item.y >= grid.bbox.y2 && item.y - grid.bbox.y2 <= 18 && item.x >= grid.bbox.x1 - 3 && item.x + item.w <= grid.bbox.x2 + 3);
|
|
5903
|
+
for (const y of [...new Set(nearby.map((item) => Math.round(item.y)))].sort((a, b) => a - b)) {
|
|
5904
|
+
const line = nearby.filter((item) => Math.abs(item.y - y) <= 1).sort((a, b) => a.x - b.x);
|
|
5905
|
+
if (UNIT.test(line.map((item) => item.text).join(""))) return line;
|
|
5906
|
+
}
|
|
5907
|
+
return [];
|
|
5908
|
+
}
|
|
5909
|
+
function prependUnitRow(cells, cols, line, usedItems) {
|
|
5910
|
+
const text = cleanCellText(line.map((item) => item.text).join(""));
|
|
5911
|
+
cells.unshift(Array.from({ length: cols }, (_, c) => ({ text: c === 0 ? text : "", colSpan: c === 0 ? cols : 1, rowSpan: 1 })));
|
|
5912
|
+
for (const cell of cells[0]) CELL_EDGES.set(cell, NO_EDGES);
|
|
5913
|
+
for (const item of line) usedItems.add(item);
|
|
5914
|
+
}
|
|
5915
|
+
function attachUnitRow(items, grid, cells, cols, usedItems) {
|
|
5916
|
+
const all = cells.flat();
|
|
5917
|
+
if (all.filter((c) => c.text.trim()).length * 2 < all.length || UNIT.test(cells[0]?.[0]?.text ?? "")) return false;
|
|
5918
|
+
const above = items.filter((it) => !usedItems.has(it) && it.y >= grid.bbox.y2 && it.y - grid.bbox.y2 <= 8 && it.x >= grid.bbox.x1 - 3 && it.x + it.w <= grid.bbox.x2 + 3);
|
|
5919
|
+
let nearest = Infinity;
|
|
5920
|
+
for (const it of above) nearest = Math.min(nearest, it.y);
|
|
5921
|
+
const line = above.filter((it) => Math.abs(it.y - nearest) <= 1).sort((a, b) => a.x - b.x);
|
|
5922
|
+
const text = line.map((it) => it.text).join("");
|
|
5923
|
+
const inset = line.length ? grid.bbox.x2 - (line[line.length - 1].x + line[line.length - 1].w) : 0;
|
|
5924
|
+
if (!line.length || !UNIT.test(text) || inset < 4.6 || inset > 5.6) return false;
|
|
5925
|
+
prependUnitRow(cells, cols, line, usedItems);
|
|
5926
|
+
return true;
|
|
5927
|
+
}
|
|
5928
|
+
|
|
5773
5929
|
// src/pdf/page-frame.ts
|
|
5774
5930
|
function isPageFrameGrid(grid, cells, pageWidth, pageHeight, items = []) {
|
|
5775
5931
|
const b = grid.bbox;
|
|
@@ -6494,8 +6650,9 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
|
|
|
6494
6650
|
const lineGrids = detectTables ? buildTableGrids(horizontals, verticals) : [];
|
|
6495
6651
|
const tableClipGrids = dropHeadBandClipGrids(dropInsetClipGrids(dropShadingClipGrids(clipGrids, lineGrids, extracted.fillRects, verticals), lineGrids), lineGrids);
|
|
6496
6652
|
const grids = [...tableClipGrids, ...dropGridsInside(lineGrids, tableClipGrids, clipResult.containers)];
|
|
6653
|
+
const figures = () => extractImageRegions(opList.fnArray, opList.argsArray, true).filter((r) => r.x2 - r.x1 >= 40 && r.y2 - r.y1 >= 40).map((r) => ({ x: r.x1, y: r.y1, w: r.x2 - r.x1, h: r.y2 - r.y1 }));
|
|
6497
6654
|
if (grids.length === 1 && grids[0].rowYs.length === 2 && grids[0].colXs.length === 2 && grids[0].bbox.x2 - grids[0].bbox.x1 > pageWidth * 1.2 && grids[0].bbox.y2 - grids[0].bbox.y1 > pageHeight * 1.2) {
|
|
6498
|
-
return extractPageBlocksFallback(items, pageNum, true, detectTables, lex);
|
|
6655
|
+
return extractPageBlocksFallback(items, pageNum, true, detectTables, lex, figures());
|
|
6499
6656
|
}
|
|
6500
6657
|
const ruled = detectTables && clipGrids.length === 0 ? detectRuledBandTables(horizontals, verticals, items, pageNum) : [];
|
|
6501
6658
|
if (detectTables && clipGrids.length === 0 && ruled.length === 0 && lineGrids.length === 0) ruled.push(...detectTextBoxTables(extracted.hiddenBoxes, items, pageNum));
|
|
@@ -6504,7 +6661,7 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
|
|
|
6504
6661
|
return extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, horizontals, verticals, imageRegions, lex, ruled, rawRules);
|
|
6505
6662
|
}
|
|
6506
6663
|
if (detectTables && stackedTableBands(items)) {
|
|
6507
|
-
return extractPageBlocksFallback(items, pageNum, true, detectTables, lex);
|
|
6664
|
+
return extractPageBlocksFallback(items, pageNum, true, detectTables, lex, figures());
|
|
6508
6665
|
}
|
|
6509
6666
|
const sidebar = splitSidebarTitleRegion(items);
|
|
6510
6667
|
if (sidebar && grids.every((grid) => grid.rowYs.length === 2 && grid.colXs.length === 2 && !items.some((item) => item.x + item.w / 2 >= grid.bbox.x1 && item.x + item.w / 2 <= grid.bbox.x2 && item.y + item.h / 2 >= grid.bbox.y1 && item.y + item.h / 2 <= grid.bbox.y2))) {
|
|
@@ -6514,8 +6671,7 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
|
|
|
6514
6671
|
const imageRegions = extractImageRegions(opList.fnArray, opList.argsArray).filter((r) => r.x2 - r.x1 >= 8 && r.y2 - r.y1 >= 8);
|
|
6515
6672
|
return extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, horizontals, verticals, imageRegions, lex, [], rawRules);
|
|
6516
6673
|
}
|
|
6517
|
-
|
|
6518
|
-
return extractPageBlocksFallback(items, pageNum, true, detectTables, lex, figures);
|
|
6674
|
+
return extractPageBlocksFallback(items, pageNum, true, detectTables, lex, figures());
|
|
6519
6675
|
}
|
|
6520
6676
|
var STRIKE_MAX_THICKNESS = 2;
|
|
6521
6677
|
var STRIKE_MAX_THICKNESS_RATIO = 0.25;
|
|
@@ -6618,10 +6774,6 @@ function isSparseProseGrid(table) {
|
|
|
6618
6774
|
const prose = filled.filter((t) => t.length >= 60 && /[.!?。]/.test(t)).reduce((n, t) => n + t.length, 0);
|
|
6619
6775
|
return prose >= chars * 0.6;
|
|
6620
6776
|
}
|
|
6621
|
-
function cleanCellText(text) {
|
|
6622
|
-
const stripped = text.replace(/^[\s]*[-–—]\s*\d+\s*[-–—][\s]*$/gm, "").trim();
|
|
6623
|
-
return stripped.split("\n").map((line) => collapseEvenSpacing(line)).join("\n");
|
|
6624
|
-
}
|
|
6625
6777
|
var FRAME_RECT_TOL = 1.5;
|
|
6626
6778
|
function takePendingNested(pending, cellBox, clipCell) {
|
|
6627
6779
|
const out = [];
|
|
@@ -6734,25 +6886,13 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
6734
6886
|
markImageCell(irGrid[cell.row][cell.col]);
|
|
6735
6887
|
}
|
|
6736
6888
|
if (cell.filler && !cellItems.length) FILLER_CELLS.add(irGrid[cell.row][cell.col]);
|
|
6737
|
-
if (
|
|
6889
|
+
if (cellItems.length) recordCellLines(irGrid[cell.row][cell.col], cellItems);
|
|
6738
6890
|
takeClipCellEdges(cell, irGrid[cell.row][cell.col]);
|
|
6739
6891
|
}
|
|
6740
6892
|
let finalGrid = irGrid;
|
|
6741
6893
|
let finalRows = numRows;
|
|
6742
6894
|
let rebuiltUsed = false;
|
|
6743
|
-
|
|
6744
|
-
let unitText = "";
|
|
6745
|
-
if (!grid.cells && numRows >= 3 && numRows <= 5 && numCols >= 3) {
|
|
6746
|
-
const nearby = items.filter((item) => item.y >= grid.bbox.y2 && item.y - grid.bbox.y2 <= 18 && item.x >= grid.bbox.x1 - 3 && item.x + item.w <= grid.bbox.x2 + 3);
|
|
6747
|
-
for (const y of [...new Set(nearby.map((item) => Math.round(item.y)))].sort((a, b) => a - b)) {
|
|
6748
|
-
const line = nearby.filter((item) => Math.abs(item.y - y) <= 1).sort((a, b) => a.x - b.x);
|
|
6749
|
-
const text = line.map((item) => item.text).join("");
|
|
6750
|
-
if (!/^\s*\(\s*단위\s*[::]/.test(text)) continue;
|
|
6751
|
-
unitLine = line;
|
|
6752
|
-
unitText = text;
|
|
6753
|
-
break;
|
|
6754
|
-
}
|
|
6755
|
-
}
|
|
6895
|
+
const unitLine = !grid.cells && numRows >= 3 && numRows <= 5 && numCols >= 3 ? rebuildUnitLine(items, grid) : [];
|
|
6756
6896
|
if (!grid.cells && numRows <= 5 && numCols >= 3 && !nestedAttached && (numRows <= 2 || unitLine.length > 0)) {
|
|
6757
6897
|
const rebuilt = normalizeUndersegmentedTable(irGrid, grid.colXs, textItems, grid.rowYs);
|
|
6758
6898
|
if (rebuilt) {
|
|
@@ -6767,23 +6907,10 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
6767
6907
|
}
|
|
6768
6908
|
}
|
|
6769
6909
|
if (unitLine.length > 0 && rebuiltUsed && !/^\s*\(\s*단위\s*[::]/.test(finalGrid[0]?.[0]?.text ?? "")) {
|
|
6770
|
-
finalGrid
|
|
6910
|
+
prependUnitRow(finalGrid, numCols, unitLine, usedItems);
|
|
6771
6911
|
finalRows++;
|
|
6772
|
-
for (const item of unitLine) usedItems.add(item);
|
|
6773
|
-
}
|
|
6774
|
-
const filledCells = finalGrid.flat().filter((c) => c.text.trim()).length;
|
|
6775
|
-
if (!rebuiltUsed && filledCells * 2 >= finalGrid.flat().length && !/^\s*\(\s*단위\s*[::]/.test(finalGrid[0]?.[0]?.text ?? "")) {
|
|
6776
|
-
const above = items.filter((it) => !usedItems.has(it) && it.y >= grid.bbox.y2 && it.y - grid.bbox.y2 <= 8 && it.x >= grid.bbox.x1 - 3 && it.x + it.w <= grid.bbox.x2 + 3);
|
|
6777
|
-
const line = above.filter((it) => Math.abs(it.y - Math.min(...above.map((a) => a.y))) <= 1).sort((a, b) => a.x - b.x);
|
|
6778
|
-
const text = line.map((it) => it.text).join("");
|
|
6779
|
-
const inset = line.length ? grid.bbox.x2 - (line[line.length - 1].x + line[line.length - 1].w) : 0;
|
|
6780
|
-
if (line.length && /^\s*\(\s*단위\s*[::]/.test(text) && inset >= 4.6 && inset <= 5.6) {
|
|
6781
|
-
finalGrid.unshift(Array.from({ length: numCols }, (_, c) => ({ text: c === 0 ? cleanCellText(text) : "", colSpan: c === 0 ? numCols : 1, rowSpan: 1 })));
|
|
6782
|
-
if (grid.cells) for (const u of finalGrid[0]) CELL_EDGES.set(u, NO_EDGES);
|
|
6783
|
-
finalRows++;
|
|
6784
|
-
for (const item of line) usedItems.add(item);
|
|
6785
|
-
}
|
|
6786
6912
|
}
|
|
6913
|
+
if (!rebuiltUsed && attachUnitRow(items, grid, finalGrid, numCols, usedItems)) finalRows++;
|
|
6787
6914
|
let semanticOneColumn = false;
|
|
6788
6915
|
if (!grid.cells && numCols === 1 && numGridRows >= 2) {
|
|
6789
6916
|
const populatedRows = finalGrid.filter((row) => row[0]?.text.trim());
|
|
@@ -7232,6 +7359,8 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
|
|
|
7232
7359
|
syntheticSpace: i.syntheticSpace
|
|
7233
7360
|
}));
|
|
7234
7361
|
const textRects = items.map((i) => ({ x: i.x, y: i.y, w: i.w, h: i.h > 0 ? i.h : i.fontSize }));
|
|
7362
|
+
const imagePanels = fullPage ? splitImagePanels(items, figures) : null;
|
|
7363
|
+
if (imagePanels) return imagePanels.flatMap((group) => extractPageBlocksFallback(group, pageNum, false, detectTables, lex));
|
|
7235
7364
|
const earlyProseCut = fullPage && detectTables ? findTwoColumnProseCutX(clusterItems) ?? persistentGutter(textRects) ?? (figures.length > 0 ? detectColumnGutter([...textRects, ...figures]) : null) : null;
|
|
7236
7365
|
if (earlyProseCut !== null) {
|
|
7237
7366
|
const band = topTableBand(items);
|
|
@@ -7355,4 +7484,4 @@ export {
|
|
|
7355
7484
|
joinCellEdges,
|
|
7356
7485
|
extractPageBlocksWithLines
|
|
7357
7486
|
};
|
|
7358
|
-
//# sourceMappingURL=chunk-
|
|
7487
|
+
//# sourceMappingURL=chunk-3N272C5L.js.map
|