kordoc 4.18.3 → 4.18.4
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/dist/{-WOKB25R2.js → -DDAVBMHD.js} +11 -11
- package/dist/{chunk-BGOR5GCF.js → chunk-274ZPMHK.js} +2 -2
- package/dist/{chunk-2ZBLQVAS.cjs → chunk-3WLZOJIE.cjs} +6 -6
- package/dist/chunk-3WLZOJIE.cjs.map +1 -0
- package/dist/{chunk-SHRRD2TD.cjs → chunk-3XSP7V5P.cjs} +2 -2
- package/dist/chunk-3XSP7V5P.cjs.map +1 -0
- package/dist/{chunk-6GLTGOP6.js → chunk-4IBY5LTJ.js} +2 -2
- package/dist/chunk-6H25SXDI.js +11 -0
- package/dist/chunk-6H25SXDI.js.map +1 -0
- package/dist/{chunk-CAN5P6N6.js → chunk-7GR2GCJF.js} +2 -2
- package/dist/{chunk-HZV52V2X.cjs → chunk-AVIZ55NQ.cjs} +3 -3
- package/dist/chunk-AVIZ55NQ.cjs.map +1 -0
- package/dist/chunk-DC6CTQTK.js +9 -0
- package/dist/chunk-DC6CTQTK.js.map +1 -0
- package/dist/{chunk-NES5U4JK.js → chunk-DUV7Y6IQ.js} +3 -3
- package/dist/{chunk-WN5YLP7H.cjs → chunk-E2644XCO.cjs} +693 -187
- package/dist/chunk-E2644XCO.cjs.map +1 -0
- package/dist/{chunk-3FZGL3IL.js → chunk-ELOPDQES.js} +2 -2
- package/dist/{chunk-2I2RTJJ5.js → chunk-F2GDLA45.js} +25 -35
- package/dist/chunk-F2GDLA45.js.map +1 -0
- package/dist/{chunk-VGDTONTB.js → chunk-F5YVCJVF.js} +2 -2
- package/dist/chunk-GS7T56RP.cjs.map +1 -1
- package/dist/{chunk-RDBTOE5X.js → chunk-HRJJDNRD.js} +2 -2
- package/dist/{chunk-KSJ7GKNQ.js → chunk-IAXGGQGD.js} +2 -2
- package/dist/{chunk-IXX3WHIE.js → chunk-IBQCK4F3.js} +7 -3
- package/dist/chunk-IBQCK4F3.js.map +1 -0
- package/dist/chunk-J55UQC5H.cjs.map +1 -1
- package/dist/{chunk-J2A46VCA.js → chunk-KUUSP6OS.js} +576 -70
- package/dist/chunk-KUUSP6OS.js.map +1 -0
- package/dist/{chunk-RSDUH4XF.js → chunk-LGF2IO66.js} +2 -2
- package/dist/{chunk-BJ6RYYXV.js → chunk-MXA6YW2W.js} +577 -71
- package/dist/chunk-MXA6YW2W.js.map +1 -0
- package/dist/{chunk-ZD5WNQNC.cjs → chunk-OIUSF2VA.cjs} +16 -12
- package/dist/chunk-OIUSF2VA.cjs.map +1 -0
- package/dist/{chunk-AZQWESRH.js → chunk-QVCHFCT2.js} +2 -2
- package/dist/{chunk-W7P4GPOV.js → chunk-RCI7LY4N.js} +8 -4
- package/dist/chunk-RCI7LY4N.js.map +1 -0
- package/dist/{chunk-V4BKT65D.cjs → chunk-SVNBZEL6.cjs} +3 -3
- package/dist/chunk-SVNBZEL6.cjs.map +1 -0
- package/dist/{chunk-OOX2GZZ4.js → chunk-T2BJPT6D.js} +3 -3
- package/dist/{chunk-OOX2GZZ4.js.map → chunk-T2BJPT6D.js.map} +1 -1
- package/dist/chunk-TK3FDAEE.cjs +9 -0
- package/dist/chunk-TK3FDAEE.cjs.map +1 -0
- package/dist/{chunk-UVUKT3IQ.js → chunk-TMJVD6FW.js} +2 -2
- package/dist/{chunk-ZN3LHNJG.js → chunk-V5X4LLVM.js} +28 -27
- package/dist/chunk-V5X4LLVM.js.map +1 -0
- package/dist/{chunk-W3RADOLO.js → chunk-VTVK2JMI.js} +2 -2
- package/dist/{chunk-PSJLB3SZ.js → chunk-XG4SYOZL.js} +2 -2
- package/dist/{chunk-RRURZDEK.js → chunk-YCY2R4FM.js} +2 -2
- package/dist/{chunk-5X7XWYR2.js → chunk-Z2PPDQK2.js} +2 -2
- package/dist/chunks-5QTTAT5T.js +10 -0
- package/dist/cli.js +154 -115
- package/dist/cli.js.map +1 -1
- package/dist/{formula-QZAOKPBX.js → formula-7ZOZ5QJ6.js} +8 -4
- package/dist/{formula-QZAOKPBX.js.map → formula-7ZOZ5QJ6.js.map} +1 -1
- package/dist/{formula-GPCOJJXN.js → formula-HQFZEXFF.js} +7 -3
- package/dist/{formula-GPCOJJXN.js.map → formula-HQFZEXFF.js.map} +1 -1
- package/dist/{formula-BQ5RW5XD.cjs → formula-YYJQBKEN.cjs} +13 -9
- package/dist/formula-YYJQBKEN.cjs.map +1 -0
- package/dist/{image-ocr-POCME5I4.js → image-ocr-4BGX2EJJ.js} +7 -6
- package/dist/{image-ocr-POCME5I4.js.map → image-ocr-4BGX2EJJ.js.map} +1 -1
- package/dist/{image-ocr-VKIUBLBX.cjs → image-ocr-CC26Q5KG.cjs} +16 -15
- package/dist/image-ocr-CC26Q5KG.cjs.map +1 -0
- package/dist/{image-ocr-TWNNVTZS.js → image-ocr-RK3HJVCI.js} +10 -9
- package/dist/{image-ocr-TWNNVTZS.js.map → image-ocr-RK3HJVCI.js.map} +1 -1
- package/dist/index.cjs +338 -347
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +42 -51
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +22 -22
- package/dist/{model-bundle-THYUL7GG.js → model-bundle-VHRXG63R.js} +5 -5
- package/dist/{models-U22N4RXX.js → models-G3WA24SY.js} +5 -5
- package/dist/page-range-QHHFTL7X.cjs.map +1 -1
- package/dist/{parser-JOMFOZLH.cjs → parser-BGORCLIU.cjs} +449 -244
- package/dist/parser-BGORCLIU.cjs.map +1 -0
- package/dist/{parser-SCXRLOW7.js → parser-GFDGAVLV.js} +242 -37
- package/dist/parser-GFDGAVLV.js.map +1 -0
- package/dist/{parser-NKP2NCSV.js → parser-SOWTUOMK.js} +245 -40
- package/dist/parser-SOWTUOMK.js.map +1 -0
- package/dist/pdf-ocr-7IOOVR2I.js +20 -0
- package/dist/pdf-ocr-EJ2HNZN6.cjs +17 -0
- package/dist/pdf-ocr-EJ2HNZN6.cjs.map +1 -0
- package/dist/pdf-ocr-RACAZU3N.js +16 -0
- package/dist/{profile-io-UI3TZBYH.js → profile-io-Q2T47RVH.js} +3 -3
- package/dist/{rasterize-XMBV5H2I.js → rasterize-OAVMUTE6.js} +3 -3
- package/dist/{redact-doc-7ZZMHDBO.js → redact-doc-ECFOVR4X.js} +11 -11
- package/dist/{render-SWRTUDAV.js → render-NSKWZVTD.js} +7 -7
- package/dist/seal-A4MG7MPQ.js +10 -0
- package/dist/{setup-43JJEEU7.js → setup-REH2KZP2.js} +3 -3
- package/dist/visual-B56WQAGW.js +20 -0
- package/dist/{watch-NRATQ472.js → watch-JXDUZYBY.js} +12 -12
- package/package.json +1 -1
- package/dist/chunk-2I2RTJJ5.js.map +0 -1
- package/dist/chunk-2ZBLQVAS.cjs.map +0 -1
- package/dist/chunk-BJ6RYYXV.js.map +0 -1
- package/dist/chunk-HZV52V2X.cjs.map +0 -1
- package/dist/chunk-IXX3WHIE.js.map +0 -1
- package/dist/chunk-J2A46VCA.js.map +0 -1
- package/dist/chunk-SHRRD2TD.cjs.map +0 -1
- package/dist/chunk-V4BKT65D.cjs.map +0 -1
- package/dist/chunk-W7P4GPOV.js.map +0 -1
- package/dist/chunk-WN5YLP7H.cjs.map +0 -1
- package/dist/chunk-ZD5WNQNC.cjs.map +0 -1
- package/dist/chunk-ZN3LHNJG.js.map +0 -1
- package/dist/chunks-OQDRDICD.js +0 -10
- package/dist/formula-BQ5RW5XD.cjs.map +0 -1
- package/dist/image-ocr-VKIUBLBX.cjs.map +0 -1
- package/dist/parser-JOMFOZLH.cjs.map +0 -1
- package/dist/parser-NKP2NCSV.js.map +0 -1
- package/dist/parser-SCXRLOW7.js.map +0 -1
- package/dist/pdf-ocr-NF4AY5MI.cjs +0 -16
- package/dist/pdf-ocr-NF4AY5MI.cjs.map +0 -1
- package/dist/pdf-ocr-OLII3WAG.js +0 -15
- package/dist/pdf-ocr-VJL7ON2Q.js +0 -19
- package/dist/seal-UKKJZHKE.js +0 -10
- package/dist/visual-D2563HCJ.js +0 -20
- /package/dist/{-WOKB25R2.js.map → -DDAVBMHD.js.map} +0 -0
- /package/dist/{chunk-BGOR5GCF.js.map → chunk-274ZPMHK.js.map} +0 -0
- /package/dist/{chunk-6GLTGOP6.js.map → chunk-4IBY5LTJ.js.map} +0 -0
- /package/dist/{chunk-CAN5P6N6.js.map → chunk-7GR2GCJF.js.map} +0 -0
- /package/dist/{chunk-NES5U4JK.js.map → chunk-DUV7Y6IQ.js.map} +0 -0
- /package/dist/{chunk-3FZGL3IL.js.map → chunk-ELOPDQES.js.map} +0 -0
- /package/dist/{chunk-VGDTONTB.js.map → chunk-F5YVCJVF.js.map} +0 -0
- /package/dist/{chunk-RDBTOE5X.js.map → chunk-HRJJDNRD.js.map} +0 -0
- /package/dist/{chunk-KSJ7GKNQ.js.map → chunk-IAXGGQGD.js.map} +0 -0
- /package/dist/{chunk-RSDUH4XF.js.map → chunk-LGF2IO66.js.map} +0 -0
- /package/dist/{chunk-AZQWESRH.js.map → chunk-QVCHFCT2.js.map} +0 -0
- /package/dist/{chunk-UVUKT3IQ.js.map → chunk-TMJVD6FW.js.map} +0 -0
- /package/dist/{chunk-W3RADOLO.js.map → chunk-VTVK2JMI.js.map} +0 -0
- /package/dist/{chunk-PSJLB3SZ.js.map → chunk-XG4SYOZL.js.map} +0 -0
- /package/dist/{chunk-RRURZDEK.js.map → chunk-YCY2R4FM.js.map} +0 -0
- /package/dist/{chunk-5X7XWYR2.js.map → chunk-Z2PPDQK2.js.map} +0 -0
- /package/dist/{chunks-OQDRDICD.js.map → chunks-5QTTAT5T.js.map} +0 -0
- /package/dist/{model-bundle-THYUL7GG.js.map → model-bundle-VHRXG63R.js.map} +0 -0
- /package/dist/{models-U22N4RXX.js.map → models-G3WA24SY.js.map} +0 -0
- /package/dist/{pdf-ocr-OLII3WAG.js.map → pdf-ocr-7IOOVR2I.js.map} +0 -0
- /package/dist/{pdf-ocr-VJL7ON2Q.js.map → pdf-ocr-RACAZU3N.js.map} +0 -0
- /package/dist/{profile-io-UI3TZBYH.js.map → profile-io-Q2T47RVH.js.map} +0 -0
- /package/dist/{rasterize-XMBV5H2I.js.map → rasterize-OAVMUTE6.js.map} +0 -0
- /package/dist/{redact-doc-7ZZMHDBO.js.map → redact-doc-ECFOVR4X.js.map} +0 -0
- /package/dist/{render-SWRTUDAV.js.map → render-NSKWZVTD.js.map} +0 -0
- /package/dist/{seal-UKKJZHKE.js.map → seal-A4MG7MPQ.js.map} +0 -0
- /package/dist/{setup-43JJEEU7.js.map → setup-REH2KZP2.js.map} +0 -0
- /package/dist/{visual-D2563HCJ.js.map → visual-B56WQAGW.js.map} +0 -0
- /package/dist/{watch-NRATQ472.js.map → watch-JXDUZYBY.js.map} +0 -0
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
HEADING_RATIO_H2,
|
|
6
6
|
HEADING_RATIO_H3,
|
|
7
7
|
tidyScriptTags
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-TMJVD6FW.js";
|
|
9
9
|
import {
|
|
10
10
|
safeMax,
|
|
11
11
|
safeMin
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-F5YVCJVF.js";
|
|
13
13
|
|
|
14
14
|
// src/pdf/line-extract.ts
|
|
15
15
|
import { OPS } from "pdfjs-dist/legacy/build/pdf.mjs";
|
|
@@ -415,13 +415,13 @@ function classifyAndAdd(seg, lineWidth, horizontals, verticals, fromFill = false
|
|
|
415
415
|
verticals.push({ x1: x, y1, x2: x, y2, lineWidth, fromFill });
|
|
416
416
|
}
|
|
417
417
|
}
|
|
418
|
-
function preprocessLines(horizontals, verticals) {
|
|
418
|
+
function preprocessLines(horizontals, verticals, nonRules) {
|
|
419
419
|
let h = horizontals.filter((l) => l.lineWidth <= MAX_LINE_WIDTH);
|
|
420
420
|
let v = verticals.filter((l) => l.lineWidth <= MAX_LINE_WIDTH);
|
|
421
421
|
h = dropShadingStacks(h, "h");
|
|
422
422
|
v = dropShadingStacks(v, "v");
|
|
423
|
-
h = mergeParallelLines(h, "h");
|
|
424
|
-
v = mergeParallelLines(v, "v");
|
|
423
|
+
h = mergeParallelLines(h, "h", nonRules);
|
|
424
|
+
v = mergeParallelLines(v, "v", nonRules);
|
|
425
425
|
return { horizontals: h, verticals: v };
|
|
426
426
|
}
|
|
427
427
|
var STACK_GAP = 2;
|
|
@@ -581,15 +581,15 @@ function closeOpenTableEdges(horizontals, verticals) {
|
|
|
581
581
|
const hasInterior = verticals.some((v) => v.x1 > x1 + EDGE_INSET && v.x1 < x2 - EDGE_INSET && crossCount(v) >= 2);
|
|
582
582
|
if (!hasInterior) continue;
|
|
583
583
|
for (const edgeX of [x1, x2]) {
|
|
584
|
-
const
|
|
585
|
-
if (!
|
|
584
|
+
const closed2 = verticals.some((v) => Math.abs(v.x1 - edgeX) <= EDGE_NEAR && v.y1 <= yMax + EDGE_CONNECT_TOL && v.y2 >= yMin - EDGE_CONNECT_TOL);
|
|
585
|
+
if (!closed2) {
|
|
586
586
|
synthesized.push({ x1: edgeX, y1: yMin, x2: edgeX, y2: yMax, lineWidth: 0.5 });
|
|
587
587
|
}
|
|
588
588
|
}
|
|
589
589
|
}
|
|
590
590
|
return synthesized.length ? [...verticals, ...synthesized] : verticals;
|
|
591
591
|
}
|
|
592
|
-
function mergeParallelLines(lines, dir) {
|
|
592
|
+
function mergeParallelLines(lines, dir, nonRules) {
|
|
593
593
|
if (lines.length <= 1) return lines;
|
|
594
594
|
const sorted = [...lines].sort((a, b) => {
|
|
595
595
|
const posA = dir === "h" ? a.y1 : a.x1;
|
|
@@ -612,6 +612,7 @@ function mergeParallelLines(lines, dir) {
|
|
|
612
612
|
const overlap2 = Math.min(prevEnd, currEnd) - Math.max(prevStart, currStart);
|
|
613
613
|
const minLen = Math.min(prevEnd - prevStart, currEnd - currStart);
|
|
614
614
|
if (overlap2 > minLen * 0.3) {
|
|
615
|
+
if (nonRules?.has(prev) && !nonRules.has(curr)) nonRules.delete(prev);
|
|
615
616
|
if (dir === "h") {
|
|
616
617
|
prev.x1 = Math.min(prev.x1, curr.x1);
|
|
617
618
|
prev.x2 = Math.max(prev.x2, curr.x2);
|
|
@@ -4124,7 +4125,12 @@ function detectSpecialKoreanTables(blocks) {
|
|
|
4124
4125
|
flushKvTable();
|
|
4125
4126
|
return result;
|
|
4126
4127
|
}
|
|
4127
|
-
function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables = false) {
|
|
4128
|
+
function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables = false, context = []) {
|
|
4129
|
+
if (context.length && !tables) {
|
|
4130
|
+
const removed = removeHeaderFooterBlocks([...blocks, ...context], pageHeights, [], notes).filter((index) => index < blocks.length);
|
|
4131
|
+
if (removed.length) warnings.push({ message: `${removed.length}\uAC1C \uBA38\uB9AC\uAE00/\uBC14\uB2E5\uAE00 \uC694\uC18C \uC81C\uAC70\uB428`, code: "HIDDEN_TEXT_FILTERED" });
|
|
4132
|
+
return removed;
|
|
4133
|
+
}
|
|
4128
4134
|
const ZONE_RATIO = 0.12;
|
|
4129
4135
|
const MIN_REPEAT2 = 3;
|
|
4130
4136
|
const topEntries = [];
|
|
@@ -4204,6 +4210,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables =
|
|
|
4204
4210
|
|
|
4205
4211
|
// src/pdf/table-meta.ts
|
|
4206
4212
|
var CLIP_TABLES = /* @__PURE__ */ new WeakSet();
|
|
4213
|
+
var FRAME_TITLE_BLOCKS = /* @__PURE__ */ new WeakMap();
|
|
4207
4214
|
var TABLE_COLXS = /* @__PURE__ */ new WeakMap();
|
|
4208
4215
|
var TABLE_ROWYS = /* @__PURE__ */ new WeakMap();
|
|
4209
4216
|
var TABLE_TAIL = /* @__PURE__ */ new WeakMap();
|
|
@@ -4311,6 +4318,262 @@ function mergeSliverColumns(grid, colXs, maxWidth) {
|
|
|
4311
4318
|
return merged;
|
|
4312
4319
|
}
|
|
4313
4320
|
|
|
4321
|
+
// src/pdf/image-bullets.ts
|
|
4322
|
+
import { OPS as OPS3, ImageKind } from "pdfjs-dist/legacy/build/pdf.mjs";
|
|
4323
|
+
var multiply = (m, t) => [
|
|
4324
|
+
m[0] * t[0] + m[2] * t[1],
|
|
4325
|
+
m[1] * t[0] + m[3] * t[1],
|
|
4326
|
+
m[0] * t[2] + m[2] * t[3],
|
|
4327
|
+
m[1] * t[2] + m[3] * t[3],
|
|
4328
|
+
m[0] * t[4] + m[2] * t[5] + m[4],
|
|
4329
|
+
m[1] * t[4] + m[3] * t[5] + m[5]
|
|
4330
|
+
];
|
|
4331
|
+
function hollowCircle(image) {
|
|
4332
|
+
if (!image?.data || image.width < 16 || image.width > 128 || image.height < 16 || image.height > 128 || Math.abs(image.width - image.height) > Math.min(image.width, image.height) * 0.1) return false;
|
|
4333
|
+
const stride = image.kind === ImageKind.RGB_24BPP ? 3 : image.kind === ImageKind.RGBA_32BPP ? 4 : 0;
|
|
4334
|
+
const { width, height, data } = image;
|
|
4335
|
+
if (!stride || data.length < width * height * stride) return false;
|
|
4336
|
+
const dark = [];
|
|
4337
|
+
let white = 0;
|
|
4338
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
4339
|
+
const i = (y * width + x) * stride;
|
|
4340
|
+
if (stride === 4 && data[i + 3] < 240) return false;
|
|
4341
|
+
const min = Math.min(data[i], data[i + 1], data[i + 2]), max = Math.max(data[i], data[i + 1], data[i + 2]);
|
|
4342
|
+
if (max - min > 15) return false;
|
|
4343
|
+
if (min >= 235) white++;
|
|
4344
|
+
if (max < 180) dark.push({ x, y });
|
|
4345
|
+
}
|
|
4346
|
+
if (white < width * height * 0.65 || dark.length < width * height * 0.025 || dark.length > width * height * 0.3) return false;
|
|
4347
|
+
const x0 = Math.min(...dark.map((p) => p.x)), x1 = Math.max(...dark.map((p) => p.x));
|
|
4348
|
+
const y0 = Math.min(...dark.map((p) => p.y)), y1 = Math.max(...dark.map((p) => p.y));
|
|
4349
|
+
const w = x1 - x0 + 1, h = y1 - y0 + 1, radius = (w + h) / 4;
|
|
4350
|
+
const cx = (x0 + x1) / 2, cy = (y0 + y1) / 2;
|
|
4351
|
+
if (Math.abs(w - h) > Math.min(w, h) * 0.15 || w < width * 0.4 || w > width * 0.85 || h < height * 0.4 || h > height * 0.85 || x0 < width * 0.04 || y0 < height * 0.04 || x1 >= width * 0.96 || y1 >= height * 0.96 || Math.abs(cx - width / 2) > width * 0.15 || Math.abs(cy - height / 2) > height * 0.15) return false;
|
|
4352
|
+
const sectors = /* @__PURE__ */ new Set();
|
|
4353
|
+
for (const point of dark) {
|
|
4354
|
+
const r = Math.hypot(point.x - cx, point.y - cy) / radius;
|
|
4355
|
+
if (r < 0.65 || r > 1.15) return false;
|
|
4356
|
+
sectors.add(Math.floor((Math.atan2(point.y - cy, point.x - cx) + Math.PI) / (Math.PI * 2) * 8) % 8);
|
|
4357
|
+
}
|
|
4358
|
+
return sectors.size === 8;
|
|
4359
|
+
}
|
|
4360
|
+
async function resolveImagePixels(page, id) {
|
|
4361
|
+
const objects = id.startsWith("g_") ? page.commonObjs : page.objs;
|
|
4362
|
+
return new Promise((resolve) => {
|
|
4363
|
+
const timer = setTimeout(() => resolve(null), 5e3);
|
|
4364
|
+
try {
|
|
4365
|
+
objects.get(id, (value) => {
|
|
4366
|
+
clearTimeout(timer);
|
|
4367
|
+
resolve(value ?? null);
|
|
4368
|
+
});
|
|
4369
|
+
} catch {
|
|
4370
|
+
clearTimeout(timer);
|
|
4371
|
+
resolve(null);
|
|
4372
|
+
}
|
|
4373
|
+
});
|
|
4374
|
+
}
|
|
4375
|
+
function smallVisibleImagePaints(fnArray, argsArray) {
|
|
4376
|
+
const paints = [];
|
|
4377
|
+
let ctm = [1, 0, 0, 1, 0, 0];
|
|
4378
|
+
let alpha = 1, clip = null, unknownClip = false;
|
|
4379
|
+
const stack = [];
|
|
4380
|
+
let pathRect, pendingClip = false;
|
|
4381
|
+
const intersectClip = (box) => {
|
|
4382
|
+
clip = clip ? {
|
|
4383
|
+
x1: Math.max(clip.x1, box.x1),
|
|
4384
|
+
y1: Math.max(clip.y1, box.y1),
|
|
4385
|
+
x2: Math.min(clip.x2, box.x2),
|
|
4386
|
+
y2: Math.min(clip.y2, box.y2)
|
|
4387
|
+
} : box;
|
|
4388
|
+
};
|
|
4389
|
+
const rectangle = (x, y, w, h) => extractImageRegions(
|
|
4390
|
+
[OPS3.transform, OPS3.transform, OPS3.paintImageXObject],
|
|
4391
|
+
[ctm, [w, 0, 0, h, x, y], ["bounds"]]
|
|
4392
|
+
)[0];
|
|
4393
|
+
for (let i = 0; i < fnArray.length; i++) {
|
|
4394
|
+
const op = fnArray[i], args = argsArray[i];
|
|
4395
|
+
if (op === OPS3.save || op === OPS3.paintFormXObjectBegin) {
|
|
4396
|
+
stack.push({ ctm, alpha, clip, unknownClip });
|
|
4397
|
+
const matrix = op === OPS3.paintFormXObjectBegin ? args?.[0] : void 0;
|
|
4398
|
+
if (Array.isArray(matrix) && matrix.length >= 6) ctm = multiply(ctm, matrix);
|
|
4399
|
+
const bounds = op === OPS3.paintFormXObjectBegin ? args?.[1] : void 0;
|
|
4400
|
+
if (Array.isArray(bounds) && bounds.length === 4) {
|
|
4401
|
+
const box = rectangle(bounds[0], bounds[1], bounds[2] - bounds[0], bounds[3] - bounds[1]);
|
|
4402
|
+
if (box && ctm[1] === 0 && ctm[2] === 0) intersectClip(box);
|
|
4403
|
+
else unknownClip = true;
|
|
4404
|
+
}
|
|
4405
|
+
} else if (op === OPS3.restore || op === OPS3.paintFormXObjectEnd) {
|
|
4406
|
+
const state = stack.pop();
|
|
4407
|
+
ctm = state?.ctm ?? [1, 0, 0, 1, 0, 0];
|
|
4408
|
+
alpha = state?.alpha ?? 1;
|
|
4409
|
+
clip = state?.clip ?? null;
|
|
4410
|
+
unknownClip = state?.unknownClip ?? false;
|
|
4411
|
+
} else if (op === OPS3.setGState) {
|
|
4412
|
+
for (const [key, value] of args?.[0] ?? []) {
|
|
4413
|
+
if (key === "ca") alpha = typeof value === "number" ? value : 0;
|
|
4414
|
+
}
|
|
4415
|
+
} else if (op === OPS3.constructPath) {
|
|
4416
|
+
const [operations, coordinates] = args;
|
|
4417
|
+
pathRect = pathRect === void 0 && operations?.length === 1 && operations[0] === OPS3.rectangle && coordinates?.length >= 4 && ctm[1] === 0 && ctm[2] === 0 ? rectangle(coordinates[0], coordinates[1], coordinates[2], coordinates[3]) : null;
|
|
4418
|
+
} else if (op === OPS3.clip || op === OPS3.eoClip) pendingClip = true;
|
|
4419
|
+
else if ([
|
|
4420
|
+
OPS3.endPath,
|
|
4421
|
+
OPS3.stroke,
|
|
4422
|
+
OPS3.closeStroke,
|
|
4423
|
+
OPS3.fill,
|
|
4424
|
+
OPS3.eoFill,
|
|
4425
|
+
OPS3.fillStroke,
|
|
4426
|
+
OPS3.eoFillStroke,
|
|
4427
|
+
OPS3.closeFillStroke,
|
|
4428
|
+
OPS3.closeEOFillStroke
|
|
4429
|
+
].includes(op)) {
|
|
4430
|
+
if (pendingClip) {
|
|
4431
|
+
if (pathRect) intersectClip(pathRect);
|
|
4432
|
+
else unknownClip = true;
|
|
4433
|
+
}
|
|
4434
|
+
pendingClip = false;
|
|
4435
|
+
pathRect = void 0;
|
|
4436
|
+
} else if (op === OPS3.transform && Array.isArray(args) && args.length >= 6) ctm = multiply(ctm, args);
|
|
4437
|
+
else if (op === OPS3.paintImageXObject && typeof args?.[0] === "string") {
|
|
4438
|
+
if (typeof args[1] !== "number" || typeof args[2] !== "number" || args[1] < 16 || args[1] > 128 || args[2] < 16 || args[2] > 128) continue;
|
|
4439
|
+
const box = extractImageRegions([OPS3.transform, OPS3.paintImageXObject], [ctm, args])[0];
|
|
4440
|
+
if (!box || ctm[1] !== 0 || ctm[2] !== 0 || alpha < 0.99 || unknownClip || clip && (box.x1 + (box.x2 - box.x1) * 0.03 < clip.x1 || box.y1 + (box.y2 - box.y1) * 0.03 < clip.y1 || box.x2 - (box.x2 - box.x1) * 0.03 > clip.x2 || box.y2 - (box.y2 - box.y1) * 0.03 > clip.y2)) continue;
|
|
4441
|
+
const width = box.x2 - box.x1, height = box.y2 - box.y1;
|
|
4442
|
+
if (width < 3 || width > 24 || height < 3 || height > 24 || width / height < 0.5 || width / height > 2) continue;
|
|
4443
|
+
paints.push({ id: args[0], box, mirrored: ctm[0] < 0 });
|
|
4444
|
+
}
|
|
4445
|
+
}
|
|
4446
|
+
return paints;
|
|
4447
|
+
}
|
|
4448
|
+
async function restoreImageBullets(items, page, fnArray, argsArray, shapes = /* @__PURE__ */ new Map()) {
|
|
4449
|
+
const candidates = [];
|
|
4450
|
+
for (const { id, box } of smallVisibleImagePaints(fnArray, argsArray)) {
|
|
4451
|
+
const width = box.x2 - box.x1, height = box.y2 - box.y1;
|
|
4452
|
+
if (Math.abs(width - height) > Math.min(width, height) * 0.1) continue;
|
|
4453
|
+
const line = items.filter((item) => !item.isHidden && item.fontSize > 0 && item.x >= box.x2 && item.x - box.x2 <= item.fontSize * 0.7 && Math.abs(item.y + item.h / 2 - (box.y1 + box.y2) / 2) <= item.fontSize * 0.4 && height >= item.fontSize * 0.5 && height <= item.fontSize * 1.2).sort((a, b) => a.x - b.x)[0];
|
|
4454
|
+
if (!line || /^[○●•◦□■∙]/.test(line.text.trim()) || !/\p{L}/u.test(line.text)) continue;
|
|
4455
|
+
const row = items.filter((item) => Math.abs(item.y - line.y) <= 2 && item.x >= line.x);
|
|
4456
|
+
if (row.reduce((n, item) => n + (item.text.match(/\p{L}/gu)?.length ?? 0), 0) < 12 || items.some((item) => item !== line && Math.abs(item.y - line.y) <= 2 && item.x < line.x)) continue;
|
|
4457
|
+
candidates.push({ id, x: box.x1, width, line });
|
|
4458
|
+
}
|
|
4459
|
+
let restored = 0;
|
|
4460
|
+
const used = /* @__PURE__ */ new Set();
|
|
4461
|
+
for (const candidate of candidates) {
|
|
4462
|
+
const same = candidates.filter((other) => other.id === candidate.id && other.line !== candidate.line && Math.abs(other.line.x - candidate.line.x) <= 1 && Math.abs(other.x - candidate.x) <= 1 && Math.abs(other.width - candidate.width) <= 1 && other.line.fontSize === candidate.line.fontSize && Math.abs(other.line.y - candidate.line.y) >= candidate.line.fontSize * 2);
|
|
4463
|
+
const numbered = items.filter((item) => !item.isHidden && /^[①-⑮]\s*/.test(item.text.trim()) && item.fontName === candidate.line.fontName && item.fontSize === candidate.line.fontSize && Math.abs(item.x - candidate.x) <= 1 && (item.text.match(/\p{L}/gu)?.length ?? 0) >= 12).sort((a, b) => b.y - a.y);
|
|
4464
|
+
const numberedList = numbered.some((item, index) => index > 0 && item.text.trim().charCodeAt(0) === numbered[index - 1].text.trim().charCodeAt(0) + 1);
|
|
4465
|
+
if (!same.length && !numberedList || used.has(candidate.line)) continue;
|
|
4466
|
+
if (!shapes.has(candidate.id)) shapes.set(candidate.id, hollowCircle(await resolveImagePixels(page, candidate.id)));
|
|
4467
|
+
if (!shapes.get(candidate.id)) continue;
|
|
4468
|
+
used.add(candidate.line);
|
|
4469
|
+
items.push({ ...candidate.line, text: "\u25CB", x: candidate.x, w: candidate.width, strike: false, underline: false, hasSpaceBefore: false, syntheticSpace: false });
|
|
4470
|
+
restored++;
|
|
4471
|
+
}
|
|
4472
|
+
return restored;
|
|
4473
|
+
}
|
|
4474
|
+
|
|
4475
|
+
// src/pdf/flow-boxes.ts
|
|
4476
|
+
import { ImageKind as ImageKind2 } from "pdfjs-dist/legacy/build/pdf.mjs";
|
|
4477
|
+
var contains2 = (outer, inner, tolerance = 1) => inner.x1 >= outer.x1 - tolerance && inner.x2 <= outer.x2 + tolerance && inner.y1 >= outer.y1 - tolerance && inner.y2 <= outer.y2 + tolerance;
|
|
4478
|
+
function closed(grid, hs, vs) {
|
|
4479
|
+
const b = grid.bbox;
|
|
4480
|
+
return [b.y1, b.y2].every((y) => hs.some((h) => Math.abs(h.y1 - y) <= 1 && h.x1 <= b.x1 + 1 && h.x2 >= b.x2 - 1)) && [b.x1, b.x2].every((x) => vs.some((v) => Math.abs(v.x1 - x) <= 1 && v.y1 <= b.y1 + 1 && v.y2 >= b.y2 - 1));
|
|
4481
|
+
}
|
|
4482
|
+
function groupFlowBoxUnits(blocks, grids, hs, vs, images) {
|
|
4483
|
+
const candidates = grids.filter((g) => g.bbox.y2 - g.bbox.y1 >= 30 && closed(g, hs, vs) && !grids.some((other) => other !== g && contains2(other.bbox, g.bbox, 0) && (other.bbox.x2 - other.bbox.x1) * (other.bbox.y2 - other.bbox.y1) > (g.bbox.x2 - g.bbox.x1) * (g.bbox.y2 - g.bbox.y1) + 1));
|
|
4484
|
+
const bands = [], visited = /* @__PURE__ */ new Set();
|
|
4485
|
+
for (const first of candidates) {
|
|
4486
|
+
if (visited.has(first)) continue;
|
|
4487
|
+
const row = candidates.filter((g) => Math.abs(g.bbox.y1 - first.bbox.y1) <= 1 && Math.abs(g.bbox.y2 - first.bbox.y2) <= 1).sort((a, b) => a.bbox.x1 - b.bbox.x1);
|
|
4488
|
+
row.forEach((g) => visited.add(g));
|
|
4489
|
+
if (row.length < 4 || row.filter((g) => g.rowYs.length === 2 && g.colXs.length === 2).length < 3) continue;
|
|
4490
|
+
const connectors = [];
|
|
4491
|
+
for (let i = 1; i < row.length; i++) {
|
|
4492
|
+
const left = row[i - 1].bbox, right = row[i].bbox, gap = right.x1 - left.x2;
|
|
4493
|
+
if (gap < 4 || gap > Math.min(left.x2 - left.x1, right.x2 - right.x1) * 0.6) break;
|
|
4494
|
+
const centerX = (left.x2 + right.x1) / 2, centerY = (left.y1 + left.y2) / 2;
|
|
4495
|
+
const connector = images.find((p) => {
|
|
4496
|
+
const w = p.x2 - p.x1, h = p.y2 - p.y1;
|
|
4497
|
+
return p.x1 >= left.x2 && p.x2 <= right.x1 && w >= gap * 0.4 && w <= gap * 0.9 && h >= 3 && h <= (left.y2 - left.y1) * 0.2 && w / h >= 0.8 && w / h <= 1.6 && Math.abs((p.x1 + p.x2) / 2 - centerX) <= gap * 0.15 && Math.abs((p.y1 + p.y2) / 2 - centerY) <= (left.y2 - left.y1) * 0.1;
|
|
4498
|
+
});
|
|
4499
|
+
if (!connector) break;
|
|
4500
|
+
connectors.push(connector);
|
|
4501
|
+
}
|
|
4502
|
+
if (connectors.length !== row.length - 1 || connectors.some((p) => Math.abs(p.x2 - p.x1 - (connectors[0].x2 - connectors[0].x1)) > (connectors[0].x2 - connectors[0].x1) * 0.2 || Math.abs(p.y2 - p.y1 - (connectors[0].y2 - connectors[0].y1)) > (connectors[0].y2 - connectors[0].y1) * 0.2)) continue;
|
|
4503
|
+
bands.push(row);
|
|
4504
|
+
}
|
|
4505
|
+
const members = /* @__PURE__ */ new Map();
|
|
4506
|
+
for (const band of bands) {
|
|
4507
|
+
const columns = band.map((g) => blocks.filter((b) => b.bbox && contains2(g.bbox, {
|
|
4508
|
+
x1: b.bbox.x,
|
|
4509
|
+
y1: b.bbox.y,
|
|
4510
|
+
x2: b.bbox.x + b.bbox.width,
|
|
4511
|
+
y2: b.bbox.y + b.bbox.height
|
|
4512
|
+
})).sort((a, b) => b.bbox.y + b.bbox.height - a.bbox.y - a.bbox.height || a.bbox.x - b.bbox.x));
|
|
4513
|
+
if (columns.some((column) => !column.length)) continue;
|
|
4514
|
+
const unit = columns.flat();
|
|
4515
|
+
for (const block of unit) members.set(block, unit);
|
|
4516
|
+
}
|
|
4517
|
+
const units = [], emitted = /* @__PURE__ */ new Set();
|
|
4518
|
+
for (const block of blocks) {
|
|
4519
|
+
const unit = members.get(block);
|
|
4520
|
+
if (!unit) units.push([block]);
|
|
4521
|
+
else if (!emitted.has(unit)) {
|
|
4522
|
+
units.push(unit);
|
|
4523
|
+
emitted.add(unit);
|
|
4524
|
+
}
|
|
4525
|
+
}
|
|
4526
|
+
return units;
|
|
4527
|
+
}
|
|
4528
|
+
function arrowDirection(image) {
|
|
4529
|
+
if (!image?.data || image.width < 16 || image.width > 128 || image.height < 16 || image.height > 128) return 0;
|
|
4530
|
+
const { width, height, data } = image;
|
|
4531
|
+
const stride = image.kind === ImageKind2.RGB_24BPP ? 3 : image.kind === ImageKind2.RGBA_32BPP ? 4 : 0;
|
|
4532
|
+
if (!stride || data.length < width * height * stride) return 0;
|
|
4533
|
+
const ink = [];
|
|
4534
|
+
let white = 0;
|
|
4535
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
4536
|
+
const offset = (y * width + x) * stride;
|
|
4537
|
+
if (stride === 4 && data[offset + 3] < 240) return 0;
|
|
4538
|
+
const min = Math.min(data[offset], data[offset + 1], data[offset + 2]);
|
|
4539
|
+
if (min >= 235) white++;
|
|
4540
|
+
if (min < 230) ink.push({ x, y });
|
|
4541
|
+
}
|
|
4542
|
+
if (white < width * height * 0.55 || !ink.length) return 0;
|
|
4543
|
+
const x0 = Math.min(...ink.map((p) => p.x)), x1 = Math.max(...ink.map((p) => p.x));
|
|
4544
|
+
const y0 = Math.min(...ink.map((p) => p.y)), y1 = Math.max(...ink.map((p) => p.y));
|
|
4545
|
+
const w = x1 - x0 + 1, h = y1 - y0 + 1, centerY = (y0 + y1) / 2;
|
|
4546
|
+
if (w < width * 0.5 || h < height * 0.5 || x0 < width * 0.04 || y0 < height * 0.04 || x1 >= width * 0.96 || y1 >= height * 0.96) return 0;
|
|
4547
|
+
const pointsRight = (mirror) => {
|
|
4548
|
+
const points = ink.map((p) => ({ x: mirror ? x0 + x1 - p.x : p.x, y: p.y }));
|
|
4549
|
+
const tail = points.filter((p) => p.x <= x0 + w * 0.25), tip = points.filter((p) => p.x >= x1 - w * 0.1);
|
|
4550
|
+
if (!tail.length || !tip.length) return false;
|
|
4551
|
+
const span = (points2) => Math.max(...points2.map((p) => p.y)) - Math.min(...points2.map((p) => p.y)) + 1;
|
|
4552
|
+
if (span(tail) > h * 0.4 || span(tip) > h * 0.45 || Math.abs((Math.max(...tail.map((p) => p.y)) + Math.min(...tail.map((p) => p.y))) / 2 - centerY) > h * 0.1 || Math.abs((Math.max(...tip.map((p) => p.y)) + Math.min(...tip.map((p) => p.y))) / 2 - centerY) > h * 0.1) return false;
|
|
4553
|
+
let head = 0;
|
|
4554
|
+
for (let x = Math.ceil(x0 + w * 0.45); x <= x0 + w * 0.75; x++) {
|
|
4555
|
+
const column = points.filter((p) => p.x === x);
|
|
4556
|
+
if (column.length) head = Math.max(head, span(column));
|
|
4557
|
+
}
|
|
4558
|
+
const middle = new Set(points.filter((p) => Math.abs(p.y - centerY) <= 1).map((p) => p.x));
|
|
4559
|
+
return head >= h * 0.8 && middle.size >= w * 0.9;
|
|
4560
|
+
};
|
|
4561
|
+
return pointsRight(false) ? 1 : pointsRight(true) ? -1 : 0;
|
|
4562
|
+
}
|
|
4563
|
+
async function detectRightArrowRegions(page, fnArray, argsArray, directions = /* @__PURE__ */ new Map()) {
|
|
4564
|
+
const regions = [];
|
|
4565
|
+
const paints = smallVisibleImagePaints(fnArray, argsArray);
|
|
4566
|
+
for (const paint of paints) {
|
|
4567
|
+
const row = paints.filter((other) => other.id === paint.id && Math.abs(other.box.y1 - paint.box.y1) <= 1 && Math.abs(other.box.y2 - paint.box.y2) <= 1 && Math.abs(other.box.x2 - other.box.x1 - (paint.box.x2 - paint.box.x1)) <= 1);
|
|
4568
|
+
const positions = new Set(row.map((other) => Math.round(other.box.x1)));
|
|
4569
|
+
if (positions.size < 3) continue;
|
|
4570
|
+
if (!directions.has(paint.id)) directions.set(paint.id, arrowDirection(await resolveImagePixels(page, paint.id)));
|
|
4571
|
+
const direction = directions.get(paint.id) ?? 0;
|
|
4572
|
+
if (direction && (paint.mirrored ? -direction : direction) === 1) regions.push(paint.box);
|
|
4573
|
+
}
|
|
4574
|
+
return regions;
|
|
4575
|
+
}
|
|
4576
|
+
|
|
4314
4577
|
// src/pdf/side-tabs.ts
|
|
4315
4578
|
var BAND = 0.12;
|
|
4316
4579
|
var MAX_CHARS = 10;
|
|
@@ -4325,7 +4588,8 @@ function isSideTabTable(box, table, others, pageWidth, pageHeight) {
|
|
|
4325
4588
|
if (!side) return false;
|
|
4326
4589
|
const texts = table.cells.flat().map((c) => c.text.replace(/\s+/g, ""));
|
|
4327
4590
|
if (!texts.some(Boolean) || texts.some((t) => [...t].length > TAB_CELL_CHARS)) return false;
|
|
4328
|
-
|
|
4591
|
+
const overlap2 = others.filter((it) => it.y >= box.y1 && it.y <= box.y2);
|
|
4592
|
+
return overlap2.length > 0 && overlap2.every((it) => side === "R" ? it.x + it.w <= box.x1 + 1 : it.x >= box.x2 - 1);
|
|
4329
4593
|
}
|
|
4330
4594
|
function removeSideTabs(blocks, pageWidths) {
|
|
4331
4595
|
const edges = /* @__PURE__ */ new Map();
|
|
@@ -4354,7 +4618,7 @@ function removeSideTabs(blocks, pageWidths) {
|
|
|
4354
4618
|
}
|
|
4355
4619
|
if (!w || !area || !b.bbox || !text || [...text].length > MAX_CHARS) return null;
|
|
4356
4620
|
const side = b.bbox.x + b.bbox.width <= Math.min(w * BAND, area.left - 1) ? "L" : b.bbox.x >= Math.max(w * (1 - BAND), area.right + 1) ? "R" : null;
|
|
4357
|
-
return side && text.replace(/\s+/g, "")
|
|
4621
|
+
return side && `${side}\0${text.replace(/\s+/g, "")}`;
|
|
4358
4622
|
};
|
|
4359
4623
|
const pages = /* @__PURE__ */ new Map();
|
|
4360
4624
|
for (const b of blocks) {
|
|
@@ -4561,15 +4825,39 @@ function sideTabGlyphs(items) {
|
|
|
4561
4825
|
if (c) c.push(it);
|
|
4562
4826
|
else cols.push([it]);
|
|
4563
4827
|
}
|
|
4828
|
+
const cands = [];
|
|
4564
4829
|
for (const col of cols) {
|
|
4565
|
-
if (col.length <
|
|
4830
|
+
if (col.length < 2) continue;
|
|
4566
4831
|
if (col.filter((g) => /[\p{L}\p{N}]/u.test(g.text)).length < col.length * 0.8) continue;
|
|
4567
4832
|
col.sort((a, b) => b.y - a.y);
|
|
4568
4833
|
const fs = [...col.map((i) => i.fontSize)].sort((a, b) => a - b)[col.length >> 1];
|
|
4569
4834
|
if (col.slice(1).some((it, k) => col[k].y - it.y > fs * 3)) continue;
|
|
4835
|
+
cands.push({ col, fs });
|
|
4836
|
+
}
|
|
4837
|
+
const bands = [];
|
|
4838
|
+
for (const c of cands.sort((a, b) => a.col[0].x - b.col[0].x)) {
|
|
4839
|
+
const last = bands[bands.length - 1];
|
|
4840
|
+
if (last) {
|
|
4841
|
+
const lastRight = Math.max(...last.col.map((i) => i.x + i.w));
|
|
4842
|
+
const gap = Math.min(...c.col.map((i) => i.x)) - lastRight;
|
|
4843
|
+
const lTop = Math.max(...last.col.map((i) => i.y)), lBot = Math.min(...last.col.map((i) => i.y));
|
|
4844
|
+
const cTop = c.col[0].y, cBot = c.col[c.col.length - 1].y;
|
|
4845
|
+
if (gap <= Math.max(last.fs, c.fs) * 1.5 && Math.min(lTop, cTop) >= Math.max(lBot, cBot)) {
|
|
4846
|
+
last.col.push(...c.col);
|
|
4847
|
+
last.fs = Math.max(last.fs, c.fs);
|
|
4848
|
+
last.anchored ||= c.col.length >= SIDE_TAB_MIN;
|
|
4849
|
+
continue;
|
|
4850
|
+
}
|
|
4851
|
+
}
|
|
4852
|
+
bands.push({ col: [...c.col], fs: c.fs, anchored: c.col.length >= SIDE_TAB_MIN });
|
|
4853
|
+
}
|
|
4854
|
+
for (const { col, fs, anchored } of bands) {
|
|
4855
|
+
if (!anchored) continue;
|
|
4856
|
+
col.sort((a, b) => b.y - a.y);
|
|
4570
4857
|
const members = new Set(col);
|
|
4571
4858
|
const top = col[0].y + fs, bottom = col[col.length - 1].y - fs;
|
|
4572
|
-
const others = items.filter((i) => !members.has(i) && i.y <= top && i.y >= bottom);
|
|
4859
|
+
const others = items.filter((i) => !members.has(i) && i.text.trim() && i.y <= top && i.y >= bottom);
|
|
4860
|
+
if (!others.length) continue;
|
|
4573
4861
|
const left = Math.min(...col.map((i) => i.x)), right = Math.max(...col.map((i) => i.x + i.w));
|
|
4574
4862
|
const rest = items.filter((i) => !members.has(i) && i.text.trim());
|
|
4575
4863
|
const outside = rest.every((i) => i.x >= right + fs) || rest.every((i) => i.x + i.w <= left - fs);
|
|
@@ -5830,13 +6118,44 @@ var UNDER_SPAN_OVERLAP_RATIO = 0.8;
|
|
|
5830
6118
|
var UNDER_BOX_PAIR_MIN_EM = 0.5;
|
|
5831
6119
|
var UNDER_BOX_PAIR_MAX_EM = 2.2;
|
|
5832
6120
|
var UNDER_BOX_PAIR_OVERLAP = 0.8;
|
|
5833
|
-
function markUnderlineItems(items, horizontals, verticals) {
|
|
6121
|
+
function markUnderlineItems(items, horizontals, verticals, nonRules) {
|
|
5834
6122
|
const underlines = [];
|
|
6123
|
+
if (nonRules?.size) horizontals = horizontals.filter((line) => !nonRules.has(line));
|
|
5835
6124
|
if (items.length === 0 || horizontals.length === 0) return underlines;
|
|
6125
|
+
const tightOwners = /* @__PURE__ */ new Map();
|
|
6126
|
+
const tightlyOwned = (line) => {
|
|
6127
|
+
const cached = tightOwners.get(line);
|
|
6128
|
+
if (cached !== void 0) return cached;
|
|
6129
|
+
const owners = items.filter((item) => {
|
|
6130
|
+
const below = item.y - line.y1;
|
|
6131
|
+
return item.w > 0 && item.text.trim() && below >= 0.5 && below <= 3 && Math.min(line.x2, item.x + item.w) > Math.max(line.x1, item.x);
|
|
6132
|
+
}).sort((a, b) => a.x - b.x);
|
|
6133
|
+
let owned = owners.length > 0 && (Math.abs(owners[0].x - line.x1) <= UNDER_GRID_EPS || owners.length === 1 && line.x1 > owners[0].x && line.x1 - owners[0].x <= Math.max(owners[0].h, owners[0].fontSize, 1) * 3) && Math.abs(owners[owners.length - 1].x + owners[owners.length - 1].w - line.x2) <= UNDER_GRID_EPS;
|
|
6134
|
+
for (let i = 1; owned && i < owners.length; i++) {
|
|
6135
|
+
const em = Math.max(owners[i].h, owners[i].fontSize, 1);
|
|
6136
|
+
if (owners[i].x - (owners[i - 1].x + owners[i - 1].w) > em * UNDER_COLUMN_GAP_EM) owned = false;
|
|
6137
|
+
}
|
|
6138
|
+
tightOwners.set(line, owned);
|
|
6139
|
+
return owned;
|
|
6140
|
+
};
|
|
6141
|
+
const paragraphUnderline = (line) => {
|
|
6142
|
+
if (!tightlyOwned(line)) return false;
|
|
6143
|
+
const width = line.x2 - line.x1;
|
|
6144
|
+
const ys = [];
|
|
6145
|
+
for (const other of horizontals) {
|
|
6146
|
+
const overlap2 = Math.min(line.x2, other.x2) - Math.max(line.x1, other.x1);
|
|
6147
|
+
if (other.lineWidth > UNDER_MAX_THICKNESS || overlap2 / Math.max(width, other.x2 - other.x1) < UNDER_SPAN_OVERLAP_RATIO || !tightlyOwned(other)) continue;
|
|
6148
|
+
if (!ys.some((y) => Math.abs(y - other.y1) < UNDER_GRID_EPS)) ys.push(other.y1);
|
|
6149
|
+
if (ys.length >= UNDER_REPEATED_SPAN_LEVELS) return true;
|
|
6150
|
+
}
|
|
6151
|
+
return false;
|
|
6152
|
+
};
|
|
5836
6153
|
for (const line of horizontals) {
|
|
5837
6154
|
if (line.lineWidth > UNDER_MAX_THICKNESS) continue;
|
|
5838
6155
|
const enclosed = insideTallCell(line, verticals, 0);
|
|
5839
|
-
|
|
6156
|
+
const repeated = isRepeatedSpanRule(line, horizontals);
|
|
6157
|
+
const textSeries = repeated && paragraphUnderline(line);
|
|
6158
|
+
if (!enclosed && (touchesVertical(line, verticals) || repeated && !textSeries)) continue;
|
|
5840
6159
|
const matches = [];
|
|
5841
6160
|
for (const item of items) {
|
|
5842
6161
|
const h = item.h > 0 ? item.h : item.fontSize;
|
|
@@ -5856,11 +6175,11 @@ function markUnderlineItems(items, horizontals, verticals) {
|
|
|
5856
6175
|
covered += m.w;
|
|
5857
6176
|
}
|
|
5858
6177
|
const inset = enclosed && insideTallCell(line, verticals, maxH);
|
|
5859
|
-
if (enclosed && !inset && (touchesVertical(line, verticals) ||
|
|
6178
|
+
if (enclosed && !inset && (touchesVertical(line, verticals) || repeated && !textSeries)) continue;
|
|
5860
6179
|
const pad = Math.max(maxH * UNDER_OWNER_PAD_EM, UNDER_OWNER_PAD_MIN_PT);
|
|
5861
6180
|
if (line.x1 < x1 - pad || line.x2 > x2 + pad) continue;
|
|
5862
6181
|
if (covered < (line.x2 - line.x1) * UNDER_MIN_COVERAGE) continue;
|
|
5863
|
-
if (hasBoxTopPair(line, maxH, horizontals, inset ? items : void 0)) continue;
|
|
6182
|
+
if (hasBoxTopPair(line, maxH, horizontals, inset || textSeries || tightlyOwned(line) ? items : void 0)) continue;
|
|
5864
6183
|
matches.sort((a, b) => a.x - b.x);
|
|
5865
6184
|
let hole = false;
|
|
5866
6185
|
for (let i = 1; i < matches.length; i++) {
|
|
@@ -5891,6 +6210,7 @@ function touchesVertical(line, verticals) {
|
|
|
5891
6210
|
for (const v of verticals) {
|
|
5892
6211
|
if (v.x1 < line.x1 - UNDER_GRID_EPS || v.x1 > line.x2 + UNDER_GRID_EPS) continue;
|
|
5893
6212
|
const lo = Math.min(v.y1, v.y2), hi = Math.max(v.y1, v.y2);
|
|
6213
|
+
if (hi - lo <= UNDER_GRID_EPS) continue;
|
|
5894
6214
|
if (lo <= line.y1 + UNDER_GRID_EPS && hi >= line.y1 - UNDER_GRID_EPS) return true;
|
|
5895
6215
|
}
|
|
5896
6216
|
return false;
|
|
@@ -6100,6 +6420,57 @@ function isPageFrameGrid(grid, cells, pageWidth, pageHeight, items = []) {
|
|
|
6100
6420
|
return inner.length === 0 || crossing >= 1 && crossing >= inBig.length * 0.01;
|
|
6101
6421
|
}
|
|
6102
6422
|
|
|
6423
|
+
// src/pdf/shaded-open-table.ts
|
|
6424
|
+
function closeShadedTableEdges(clipGrids, horizontals, verticals, fillRects) {
|
|
6425
|
+
const near = (a, b) => Math.abs(a - b) <= 1.5;
|
|
6426
|
+
let hs = horizontals, vs = verticals;
|
|
6427
|
+
const restored = [];
|
|
6428
|
+
for (const grid of clipGrids) {
|
|
6429
|
+
if (grid.clipParent || grid.rowYs.length !== 2 || grid.colXs.length < 3 || !grid.cells?.length || grid.cells.some((c) => c.filler || c.rowSpan !== 1 || c.colSpan !== 1)) continue;
|
|
6430
|
+
const { x1, x2, y1: mid, y2: top } = grid.bbox;
|
|
6431
|
+
if (!grid.cells.every((c) => fillRects.some((f) => near(f.x1, c.bbox.x1) && near(f.x2, c.bbox.x2) && near(f.y1, c.bbox.y1) && near(f.y2, c.bbox.y2)))) continue;
|
|
6432
|
+
const topRule = hs.find((h) => near(h.y1, top) && near(h.x1, x1) && near(h.x2, x2));
|
|
6433
|
+
if (!topRule) continue;
|
|
6434
|
+
const dividers = grid.colXs.slice(1, -1).map((x) => vs.find((v) => near(v.x1, x) && near(v.y2, top) && v.y1 <= mid - 6));
|
|
6435
|
+
if (dividers.some((v) => !v)) continue;
|
|
6436
|
+
const bottom = dividers[0].y1;
|
|
6437
|
+
if (!dividers.every((v) => near(v.y1, bottom))) continue;
|
|
6438
|
+
const bottomRule = hs.find((h) => near(h.y1, bottom) && near(h.x1, x1) && near(h.x2, x2));
|
|
6439
|
+
if (!bottomRule) continue;
|
|
6440
|
+
const missing = [x1, x2].filter((x) => !vs.some((v) => near(v.x1, x) && v.y1 <= bottom + 1.5 && v.y2 >= top - 1.5));
|
|
6441
|
+
if (!missing.length) continue;
|
|
6442
|
+
restored.push({ x1, x2, y1: bottom, y2: top });
|
|
6443
|
+
vs = vs.concat(missing.map((x) => ({ x1: x, x2: x, y1: bottom, y2: top, lineWidth: topRule.lineWidth })));
|
|
6444
|
+
if (!hs.some((h) => near(h.y1, mid) && near(h.x1, x1) && near(h.x2, x2))) {
|
|
6445
|
+
hs = hs.concat({ x1, x2, y1: mid, y2: mid, lineWidth: topRule.lineWidth });
|
|
6446
|
+
}
|
|
6447
|
+
}
|
|
6448
|
+
return { horizontals: hs, verticals: vs, restored };
|
|
6449
|
+
}
|
|
6450
|
+
function nestRestoredShadedGrids(grids, restored, horizontals, verticals) {
|
|
6451
|
+
const near = (a, b) => Math.abs(a - b) <= 1.5;
|
|
6452
|
+
if (restored.length === 0) return;
|
|
6453
|
+
const nested = /* @__PURE__ */ new Set();
|
|
6454
|
+
for (const grid of grids) {
|
|
6455
|
+
const b = grid.bbox;
|
|
6456
|
+
if (!restored.some((r) => near(r.x1, b.x1) && near(r.x2, b.x2) && near(r.y1, b.y1) && near(r.y2, b.y2))) continue;
|
|
6457
|
+
if (grids.some((g) => g !== grid && b.x1 - g.bbox.x1 >= 0.8 && g.bbox.x2 - b.x2 >= 0.8 && b.y1 - g.bbox.y1 >= 0.8 && g.bbox.y2 - b.y2 >= 0.8)) {
|
|
6458
|
+
grid.lineNested = true;
|
|
6459
|
+
nested.add(grid);
|
|
6460
|
+
}
|
|
6461
|
+
}
|
|
6462
|
+
for (const frame of grids) {
|
|
6463
|
+
const b = frame.bbox;
|
|
6464
|
+
if (frame.lineNested || ![...nested].some((g) => g.bbox.x1 > b.x1 && g.bbox.x2 < b.x2 && g.bbox.y1 > b.y1 && g.bbox.y2 < b.y2)) continue;
|
|
6465
|
+
const fullH = horizontals.filter((h) => near(h.x1, b.x1) && near(h.x2, b.x2) && h.y1 >= b.y1 - 1.5 && h.y1 <= b.y2 + 1.5);
|
|
6466
|
+
if (!fullH.some((h) => near(h.y1, b.y1)) || !fullH.some((h) => near(h.y1, b.y2)) || fullH.some((h) => h.y1 > b.y1 + 1.5 && h.y1 < b.y2 - 1.5)) continue;
|
|
6467
|
+
const fullV = verticals.filter((v) => v.y1 <= b.y1 + 1.5 && v.y2 >= b.y2 - 1.5 && v.x1 >= b.x1 - 1.5 && v.x1 <= b.x2 + 1.5);
|
|
6468
|
+
if (!fullV.some((v) => near(v.x1, b.x1)) || !fullV.some((v) => near(v.x1, b.x2)) || fullV.some((v) => v.x1 > b.x1 + 1.5 && v.x1 < b.x2 - 1.5)) continue;
|
|
6469
|
+
frame.colXs = [b.x1, b.x2];
|
|
6470
|
+
frame.rowYs = [b.y2, b.y1];
|
|
6471
|
+
}
|
|
6472
|
+
}
|
|
6473
|
+
|
|
6103
6474
|
// src/pdf/open-table-ends.ts
|
|
6104
6475
|
var ALIGN_TOL = 3;
|
|
6105
6476
|
var MIN_RULES = 3;
|
|
@@ -6435,6 +6806,140 @@ function detectTextBoxTables(boxes, items, pageNum) {
|
|
|
6435
6806
|
}];
|
|
6436
6807
|
}
|
|
6437
6808
|
|
|
6809
|
+
// src/pdf/frame-cell-blocks.ts
|
|
6810
|
+
var FRAME_READING_UNITS = /* @__PURE__ */ new WeakMap();
|
|
6811
|
+
var FRAME_SOURCE_BOUNDS = /* @__PURE__ */ new WeakMap();
|
|
6812
|
+
function recordFrameReadingUnit(blocks, bbox) {
|
|
6813
|
+
for (const block of blocks) FRAME_SOURCE_BOUNDS.set(block, bbox);
|
|
6814
|
+
if (blocks.length < 2) return;
|
|
6815
|
+
const unit = { blocks, bbox };
|
|
6816
|
+
for (const block of blocks) FRAME_READING_UNITS.set(block, unit);
|
|
6817
|
+
}
|
|
6818
|
+
function frameLayoutBoxes(blocks) {
|
|
6819
|
+
const boxes = [], seen2 = /* @__PURE__ */ new Set();
|
|
6820
|
+
for (const block of blocks) {
|
|
6821
|
+
const frame = FRAME_SOURCE_BOUNDS.get(block);
|
|
6822
|
+
if (frame) {
|
|
6823
|
+
if (!seen2.has(frame)) {
|
|
6824
|
+
boxes.push(frame);
|
|
6825
|
+
seen2.add(frame);
|
|
6826
|
+
}
|
|
6827
|
+
} else if (block.bbox) boxes.push(block.bbox);
|
|
6828
|
+
}
|
|
6829
|
+
return boxes;
|
|
6830
|
+
}
|
|
6831
|
+
function groupFrameParagraphUnits(units, frames) {
|
|
6832
|
+
const source = /* @__PURE__ */ new Map();
|
|
6833
|
+
for (const unit of units) for (const block of unit) source.set(block, unit);
|
|
6834
|
+
const members = /* @__PURE__ */ new Map(), emitted = /* @__PURE__ */ new Set();
|
|
6835
|
+
for (const frame of frames) {
|
|
6836
|
+
if (frame.length < 2 || frame.some((block) => block.type !== "paragraph" || source.get(block)?.length !== 1)) continue;
|
|
6837
|
+
for (const block of frame) members.set(block, frame);
|
|
6838
|
+
}
|
|
6839
|
+
const out = [];
|
|
6840
|
+
for (const unit of units) {
|
|
6841
|
+
const frame = unit.length === 1 ? members.get(unit[0]) : void 0;
|
|
6842
|
+
if (!frame) out.push(unit);
|
|
6843
|
+
else if (!emitted.has(frame)) {
|
|
6844
|
+
out.push(frame);
|
|
6845
|
+
emitted.add(frame);
|
|
6846
|
+
}
|
|
6847
|
+
}
|
|
6848
|
+
for (const unit of out) {
|
|
6849
|
+
if (unit.length < 2 || FRAME_READING_UNITS.get(unit[0])?.blocks === unit) continue;
|
|
6850
|
+
const bs = unit.map((b) => b.bbox).filter((b) => !!b);
|
|
6851
|
+
if (bs.length !== unit.length) continue;
|
|
6852
|
+
const x = Math.min(...bs.map((b) => b.x)), y = Math.min(...bs.map((b) => b.y));
|
|
6853
|
+
recordFrameReadingUnit(unit, {
|
|
6854
|
+
page: bs[0].page,
|
|
6855
|
+
x,
|
|
6856
|
+
y,
|
|
6857
|
+
width: Math.max(...bs.map((b) => b.x + b.width)) - x,
|
|
6858
|
+
height: Math.max(...bs.map((b) => b.y + b.height)) - y
|
|
6859
|
+
});
|
|
6860
|
+
}
|
|
6861
|
+
return out;
|
|
6862
|
+
}
|
|
6863
|
+
function recordFrameTitle(table, source, pageNum) {
|
|
6864
|
+
if (!CLIP_TABLES.has(table) || table.rows !== 1 || table.cols !== 3 || source.length < 2) return;
|
|
6865
|
+
const cells = table.cells[0];
|
|
6866
|
+
if (cells.length !== 3 || cells.some((c) => c.colSpan !== 1 || c.rowSpan !== 1 || c.blocks?.length || c.text.includes("\n"))) return;
|
|
6867
|
+
const [label, spacer, title] = cells;
|
|
6868
|
+
if (!/^(?:붙임|별첨|첨부|부록)\s*\d{1,3}$/.test(label.text.trim()) || spacer.text.trim() || !title.text.trim()) return;
|
|
6869
|
+
if (cells.some((c) => {
|
|
6870
|
+
const e = CELL_EDGES.get(c);
|
|
6871
|
+
return !e || e.t || e.b || e.l || e.r;
|
|
6872
|
+
})) return;
|
|
6873
|
+
const xs = TABLE_COLXS.get(table), style = dominantStyle(source), fs = style?.fontSize ?? 0;
|
|
6874
|
+
if (!xs || xs.length !== 4 || fs <= 0) return;
|
|
6875
|
+
const width = xs[3] - xs[0], gap = xs[2] - xs[1];
|
|
6876
|
+
if (width < fs * 12 || gap <= 0 || gap > fs * 1.5 || xs[1] - xs[0] > width * 0.25 || xs[3] - xs[2] < width * 0.6) return;
|
|
6877
|
+
if (source.some((i) => i.fontName !== source[0].fontName || Math.abs(i.fontSize - fs) > fs * 0.15)) return;
|
|
6878
|
+
if (groupByY([...source].sort((a, b) => b.y - a.y)).length !== 1) return;
|
|
6879
|
+
FRAME_TITLE_BLOCKS.set(table, {
|
|
6880
|
+
type: "paragraph",
|
|
6881
|
+
text: `${label.text.trim()} ${title.text.trim()}`,
|
|
6882
|
+
pageNumber: pageNum,
|
|
6883
|
+
bbox: computeBBox(source, pageNum),
|
|
6884
|
+
style
|
|
6885
|
+
});
|
|
6886
|
+
}
|
|
6887
|
+
var FRAME_RECT_TOL = 1.5;
|
|
6888
|
+
function takePendingNested(pending, cellBox, clipCell) {
|
|
6889
|
+
const out = [];
|
|
6890
|
+
for (let i = pending.length - 1; i >= 0; i--) {
|
|
6891
|
+
const p = pending[i].parent;
|
|
6892
|
+
if (pending[i].contained ? p.x1 >= cellBox.x1 - FRAME_RECT_TOL && p.x2 <= cellBox.x2 + FRAME_RECT_TOL && p.y1 >= cellBox.y1 - FRAME_RECT_TOL && p.y2 <= cellBox.y2 + FRAME_RECT_TOL : clipCell && Math.abs(p.x1 - cellBox.x1) <= FRAME_RECT_TOL && Math.abs(p.x2 - cellBox.x2) <= FRAME_RECT_TOL && Math.abs(p.y1 - cellBox.y1) <= FRAME_RECT_TOL && Math.abs(p.y2 - cellBox.y2) <= FRAME_RECT_TOL) {
|
|
6893
|
+
out.push(pending[i].block);
|
|
6894
|
+
pending.splice(i, 1);
|
|
6895
|
+
}
|
|
6896
|
+
}
|
|
6897
|
+
return out;
|
|
6898
|
+
}
|
|
6899
|
+
function buildFrameCellBlocks(cellItems, nested, pageNum, lex) {
|
|
6900
|
+
const tables = [...nested].sort((a, b) => b.bbox.y + b.bbox.height - (a.bbox.y + a.bbox.height));
|
|
6901
|
+
const blocks = [];
|
|
6902
|
+
let rest = [...cellItems];
|
|
6903
|
+
const pushParagraphs = (items) => {
|
|
6904
|
+
if (items.length === 0) return;
|
|
6905
|
+
const source = items.map((it) => ({ ...it, isHidden: false })).sort((a, b) => b.y - a.y || a.x - b.x);
|
|
6906
|
+
const paragraphs = [];
|
|
6907
|
+
pushLineParagraphs(paragraphs, mergeSuperscriptLines(groupByY(source)), pageNum, lex);
|
|
6908
|
+
for (const block of paragraphs) {
|
|
6909
|
+
block.text = cleanCellText(block.text ?? "");
|
|
6910
|
+
if (block.text) blocks.push(block);
|
|
6911
|
+
}
|
|
6912
|
+
};
|
|
6913
|
+
for (const tb of tables) {
|
|
6914
|
+
const bottom = tb.bbox.y;
|
|
6915
|
+
pushParagraphs(rest.filter((it) => it.y >= bottom));
|
|
6916
|
+
rest = rest.filter((it) => it.y < bottom);
|
|
6917
|
+
blocks.push(tb);
|
|
6918
|
+
}
|
|
6919
|
+
pushParagraphs(rest);
|
|
6920
|
+
const text = blocks.map((b) => b.type === "table" && b.table ? b.table.cells.flat().map((c) => c.text).filter(Boolean).join("\n") : b.text ?? "").filter(Boolean).join("\n");
|
|
6921
|
+
return { blocks, text };
|
|
6922
|
+
}
|
|
6923
|
+
|
|
6924
|
+
// src/pdf/nested-shaded-headers.ts
|
|
6925
|
+
function extendNestedShadedHeaders(clipGrids, lineGrids, horizontals, verticals, fills) {
|
|
6926
|
+
const near = (a, b) => Math.abs(a - b) <= 1.5;
|
|
6927
|
+
const contains3 = (a, b) => b.x1 >= a.x1 - 1.5 && b.x2 <= a.x2 + 1.5 && b.y1 >= a.y1 - 1.5 && b.y2 <= a.y2 + 1.5;
|
|
6928
|
+
const extended = [];
|
|
6929
|
+
for (let i = 0; i < clipGrids.length; i++) {
|
|
6930
|
+
const c = clipGrids[i], parent = c.clipParent;
|
|
6931
|
+
if (!parent || c.rowYs.length !== 2 || c.colXs.length < 3 || !c.cells?.length || c.cells.some((cell) => cell.filler || cell.rowSpan !== 1 || cell.colSpan !== 1)) continue;
|
|
6932
|
+
if (!clipGrids.some((g) => g.rowYs.length === 2 && g.colXs.length === 2 && near(g.bbox.x1, parent.x1) && near(g.bbox.x2, parent.x2) && near(g.bbox.y1, parent.y1) && near(g.bbox.y2, parent.y2))) continue;
|
|
6933
|
+
if (!c.cells.every((cell) => fills.some((f) => near(f.x1, cell.bbox.x1) && near(f.x2, cell.bbox.x2) && near(f.y1, cell.bbox.y1) && near(f.y2, cell.bbox.y2)))) continue;
|
|
6934
|
+
const host = lineGrids.find((l) => l.rowYs.length > 2 && l.colXs.length === c.colXs.length && c.colXs.every((x, k) => near(x, l.colXs[k])) && c.rowYs.every((y, k) => near(y, l.rowYs[k])) && contains3(parent, l.bbox) && l.rowYs.every((y) => horizontals.some((h) => near(h.y1, y) && near(h.x1, l.bbox.x1) && near(h.x2, l.bbox.x2))) && l.colXs.every((x) => verticals.some((v) => near(v.x1, x) && v.y1 <= l.bbox.y1 + 1.5 && v.y2 >= l.bbox.y2 - 1.5)) && !clipGrids.some((o) => o !== c && !contains3(o.bbox, l.bbox) && Math.min(o.bbox.x2, l.bbox.x2) > Math.max(o.bbox.x1, l.bbox.x1) && Math.min(o.bbox.y2, l.bbox.y2) > Math.max(o.bbox.y1, l.bbox.y1)));
|
|
6935
|
+
if (!host) continue;
|
|
6936
|
+
const grid = { ...host, clipParent: parent, cells: extractCells(host, horizontals, verticals) };
|
|
6937
|
+
clipGrids[i] = grid;
|
|
6938
|
+
extended.push(grid);
|
|
6939
|
+
}
|
|
6940
|
+
return extended;
|
|
6941
|
+
}
|
|
6942
|
+
|
|
6438
6943
|
// src/pdf/page-regions.ts
|
|
6439
6944
|
function splitTwoColumnProse(items, cutX) {
|
|
6440
6945
|
const left = [];
|
|
@@ -6762,7 +7267,7 @@ function figureColumnBands(items, figures) {
|
|
|
6762
7267
|
}
|
|
6763
7268
|
|
|
6764
7269
|
// src/pdf/page-blocks.ts
|
|
6765
|
-
function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeight, extraLines, detectTables = true, carry, lexicon) {
|
|
7270
|
+
function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeight, extraLines, detectTables = true, carry, lexicon, verifiedRightArrows = []) {
|
|
6766
7271
|
if (items.length === 0) {
|
|
6767
7272
|
if (carry) carry.clip = void 0;
|
|
6768
7273
|
return [];
|
|
@@ -6770,7 +7275,7 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
|
|
|
6770
7275
|
const tab = sideTabGlyphs(items);
|
|
6771
7276
|
if (tab.size) {
|
|
6772
7277
|
const glyphs = [...tab].sort((a, b) => b.y - a.y).map((g) => ({ type: "paragraph", text: g.text.trim(), pageNumber: pageNum, bbox: computeBBox([g], pageNum), style: dominantStyle([g]) }));
|
|
6773
|
-
return [...glyphs, ...extractPageBlocksWithLines(items.filter((i) => !tab.has(i)), pageNum, opList, pageWidth, pageHeight, extraLines, detectTables, carry, lexicon)];
|
|
7278
|
+
return [...glyphs, ...extractPageBlocksWithLines(items.filter((i) => !tab.has(i)), pageNum, opList, pageWidth, pageHeight, extraLines, detectTables, carry, lexicon, verifiedRightArrows)];
|
|
6774
7279
|
}
|
|
6775
7280
|
const lex = lexicon ?? new WrapLexicon();
|
|
6776
7281
|
for (const line of streamLines(items)) lex.addLine(mergeLineSimple(line));
|
|
@@ -6798,19 +7303,28 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
|
|
|
6798
7303
|
}
|
|
6799
7304
|
;
|
|
6800
7305
|
({ horizontals, verticals } = filterPageBorderLines(horizontals, verticals, pageWidth, pageHeight));
|
|
6801
|
-
({ horizontals, verticals } = preprocessLines(horizontals, verticals));
|
|
7306
|
+
({ horizontals, verticals } = preprocessLines(horizontals, verticals, extracted.nonRules));
|
|
7307
|
+
markStrikethroughItems(items, horizontals);
|
|
7308
|
+
wrapStrikethroughRuns(items);
|
|
7309
|
+
const underlines = new Set(markUnderlineItems(items, horizontals, verticals, extracted.nonRules));
|
|
7310
|
+
if (underlines.size) horizontals = horizontals.filter((l) => !underlines.has(l));
|
|
7311
|
+
wrapUnderlineRuns(items);
|
|
6802
7312
|
horizontals = closeOpenTableEnds(horizontals, verticals, items.every((it) => it.seq !== void 0));
|
|
6803
7313
|
verticals = closeOpenTableEdges(horizontals, verticals);
|
|
6804
7314
|
verticals = bridgeSplitColumnVerticals(horizontals, verticals);
|
|
6805
7315
|
if (detectTables && clipGrids.length === 0) verticals = bridgeSkippedRowVerticals(horizontals, verticals, items);
|
|
6806
7316
|
if (detectTables && clipGrids.length === 0) ({ horizontals, verticals } = extendHeaderBoxRows(horizontals, verticals, items));
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
const underlines = new Set(markUnderlineItems(items, horizontals, verticals));
|
|
6810
|
-
if (underlines.size) horizontals = horizontals.filter((l) => !underlines.has(l));
|
|
6811
|
-
wrapUnderlineRuns(items);
|
|
7317
|
+
const shadedEdges = detectTables ? closeShadedTableEdges(clipGrids, horizontals, verticals, extracted.fillRects) : void 0;
|
|
7318
|
+
if (shadedEdges) ({ horizontals, verticals } = shadedEdges);
|
|
6812
7319
|
const lineGrids = detectTables ? buildTableGrids(horizontals, verticals) : [];
|
|
7320
|
+
if (shadedEdges) nestRestoredShadedGrids(lineGrids, shadedEdges.restored, horizontals, verticals);
|
|
6813
7321
|
const tableClipGrids = dropHeadBandClipGrids(dropInsetClipGrids(dropShadingClipGrids(clipGrids, lineGrids, extracted.fillRects, verticals), lineGrids), lineGrids);
|
|
7322
|
+
recordClipCellEdges(
|
|
7323
|
+
extendNestedShadedHeaders(tableClipGrids, lineGrids, horizontals, verticals, extracted.fillRects),
|
|
7324
|
+
extracted.horizontals.concat(extracted.shortH),
|
|
7325
|
+
extracted.verticals.concat(extracted.shortV),
|
|
7326
|
+
extracted.nonRules
|
|
7327
|
+
);
|
|
6814
7328
|
const grids = [...tableClipGrids, ...dropGridsInside(lineGrids, tableClipGrids, clipResult.containers)];
|
|
6815
7329
|
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 }));
|
|
6816
7330
|
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) {
|
|
@@ -6820,7 +7334,7 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
|
|
|
6820
7334
|
if (detectTables && clipGrids.length === 0 && ruled.length === 0 && lineGrids.length === 0) ruled.push(...detectTextBoxTables(extracted.hiddenBoxes, items, pageNum));
|
|
6821
7335
|
if (ruled.length > 0) {
|
|
6822
7336
|
const imageRegions = extractImageRegions(opList.fnArray, opList.argsArray).filter((r) => r.x2 - r.x1 >= 8 && r.y2 - r.y1 >= 8);
|
|
6823
|
-
return extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, horizontals, verticals, imageRegions, lex, ruled, rawRules);
|
|
7337
|
+
return extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, horizontals, verticals, imageRegions, lex, ruled, rawRules, verifiedRightArrows);
|
|
6824
7338
|
}
|
|
6825
7339
|
if (detectTables && stackedTableBands(items)) {
|
|
6826
7340
|
return extractPageBlocksFallback(items, pageNum, true, detectTables, lex, figures());
|
|
@@ -6831,7 +7345,7 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
|
|
|
6831
7345
|
}
|
|
6832
7346
|
if (grids.length > 0) {
|
|
6833
7347
|
const imageRegions = extractImageRegions(opList.fnArray, opList.argsArray).filter((r) => r.x2 - r.x1 >= 8 && r.y2 - r.y1 >= 8);
|
|
6834
|
-
return extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, horizontals, verticals, imageRegions, lex, [], rawRules);
|
|
7348
|
+
return extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, horizontals, verticals, imageRegions, lex, [], rawRules, verifiedRightArrows);
|
|
6835
7349
|
}
|
|
6836
7350
|
return extractPageBlocksFallback(items, pageNum, true, detectTables, lex, figures());
|
|
6837
7351
|
}
|
|
@@ -6936,42 +7450,10 @@ function isSparseProseGrid(table) {
|
|
|
6936
7450
|
const prose = filled.filter((t) => t.length >= 60 && /[.!?。]/.test(t)).reduce((n, t) => n + t.length, 0);
|
|
6937
7451
|
return prose >= chars * 0.6;
|
|
6938
7452
|
}
|
|
6939
|
-
|
|
6940
|
-
function takePendingNested(pending, cellBox, clipCell) {
|
|
6941
|
-
const out = [];
|
|
6942
|
-
for (let i = pending.length - 1; i >= 0; i--) {
|
|
6943
|
-
const p = pending[i].parent;
|
|
6944
|
-
if (pending[i].contained ? p.x1 >= cellBox.x1 - FRAME_RECT_TOL && p.x2 <= cellBox.x2 + FRAME_RECT_TOL && p.y1 >= cellBox.y1 - FRAME_RECT_TOL && p.y2 <= cellBox.y2 + FRAME_RECT_TOL : clipCell && Math.abs(p.x1 - cellBox.x1) <= FRAME_RECT_TOL && Math.abs(p.x2 - cellBox.x2) <= FRAME_RECT_TOL && Math.abs(p.y1 - cellBox.y1) <= FRAME_RECT_TOL && Math.abs(p.y2 - cellBox.y2) <= FRAME_RECT_TOL) {
|
|
6945
|
-
out.push(pending[i].block);
|
|
6946
|
-
pending.splice(i, 1);
|
|
6947
|
-
}
|
|
6948
|
-
}
|
|
6949
|
-
return out;
|
|
6950
|
-
}
|
|
6951
|
-
function buildFrameCellBlocks(cellItems, nested, pageNum, wrap) {
|
|
6952
|
-
const tables = [...nested].sort((a, b) => b.bbox.y + b.bbox.height - (a.bbox.y + a.bbox.height));
|
|
6953
|
-
const blocks = [];
|
|
6954
|
-
let rest = [...cellItems];
|
|
6955
|
-
const pushParagraphs = (items) => {
|
|
6956
|
-
if (items.length === 0) return;
|
|
6957
|
-
for (const line of cleanCellText(cellTextToString(items, wrap)).split("\n")) {
|
|
6958
|
-
const t = line.trim();
|
|
6959
|
-
if (t) blocks.push({ type: "paragraph", text: t, pageNumber: pageNum });
|
|
6960
|
-
}
|
|
6961
|
-
};
|
|
6962
|
-
for (const tb of tables) {
|
|
6963
|
-
const bottom = tb.bbox.y;
|
|
6964
|
-
pushParagraphs(rest.filter((it) => it.y >= bottom));
|
|
6965
|
-
rest = rest.filter((it) => it.y < bottom);
|
|
6966
|
-
blocks.push(tb);
|
|
6967
|
-
}
|
|
6968
|
-
pushParagraphs(rest);
|
|
6969
|
-
const text = blocks.map((b) => b.type === "table" && b.table ? b.table.cells.flat().map((c) => c.text).filter(Boolean).join("\n") : b.text ?? "").filter(Boolean).join("\n");
|
|
6970
|
-
return { blocks, text };
|
|
6971
|
-
}
|
|
6972
|
-
function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, horizontals, verticals, imageRegions = [], lex, ruled = [], rawRules = horizontals) {
|
|
7453
|
+
function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, horizontals, verticals, imageRegions = [], lex, ruled = [], rawRules = horizontals, verifiedRightArrows = []) {
|
|
6973
7454
|
const ocrPage = items.length > 0 && items.every((i) => i.fontName === "ocr");
|
|
6974
7455
|
const blocks = [];
|
|
7456
|
+
const frameParagraphUnits = [];
|
|
6975
7457
|
const usedItems = /* @__PURE__ */ new Set();
|
|
6976
7458
|
for (const r of ruled) {
|
|
6977
7459
|
for (const it of r.items) usedItems.add(it);
|
|
@@ -7028,7 +7510,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
7028
7510
|
const nested = pendingNested.length ? takePendingNested(pendingNested, cell.bbox, !!grid.cells) : [];
|
|
7029
7511
|
if (nested.length > 0) {
|
|
7030
7512
|
nestedAttached = true;
|
|
7031
|
-
const built = buildFrameCellBlocks(cellItems, nested, pageNum,
|
|
7513
|
+
const built = buildFrameCellBlocks(cellItems, nested, pageNum, lex);
|
|
7032
7514
|
irGrid[cell.row][cell.col] = { text: built.text, colSpan: cell.colSpan, rowSpan: cell.rowSpan, blocks: built.blocks };
|
|
7033
7515
|
if (cellItems.length) recordCellLines(irGrid[cell.row][cell.col], cellItems);
|
|
7034
7516
|
takeClipCellEdges(cell, irGrid[cell.row][cell.col]);
|
|
@@ -7039,6 +7521,9 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
7039
7521
|
colSpan: cell.colSpan,
|
|
7040
7522
|
rowSpan: cell.rowSpan
|
|
7041
7523
|
};
|
|
7524
|
+
if (numRows === 1 && numCols === 1 && cellItems.length) {
|
|
7525
|
+
irGrid[cell.row][cell.col].blocks = buildFrameCellBlocks(cellItems, [], pageNum, lex).blocks;
|
|
7526
|
+
}
|
|
7042
7527
|
const b = cell.bbox;
|
|
7043
7528
|
const isBackdrop = (r) => r.x1 <= b.x1 + 1 && r.x2 >= b.x2 - 1 && r.y1 <= b.y1 + 1 && r.y2 >= b.y2 - 1;
|
|
7044
7529
|
if (imageRegions.some((r) => {
|
|
@@ -7074,7 +7559,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
7074
7559
|
}
|
|
7075
7560
|
if (!rebuiltUsed && attachUnitRow(items, grid, finalGrid, numCols, usedItems)) finalRows++;
|
|
7076
7561
|
let semanticOneColumn = false;
|
|
7077
|
-
if (!grid.cells && numCols === 1 && numGridRows >= 2) {
|
|
7562
|
+
if (!grid.cells && !nestedAttached && numCols === 1 && numGridRows >= 2) {
|
|
7078
7563
|
const populatedRows = finalGrid.filter((row) => row[0]?.text.trim());
|
|
7079
7564
|
if (populatedRows.length >= 4) {
|
|
7080
7565
|
const fontSizes = tableItems.map((item) => item.fontSize).filter((size) => size > 0).sort((a, b) => a - b);
|
|
@@ -7127,6 +7612,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
7127
7612
|
recordRowRules(irTable, grid.cells, grid.bbox, rawRules);
|
|
7128
7613
|
}
|
|
7129
7614
|
TABLE_COLXS.set(irTable, grid.colXs);
|
|
7615
|
+
if (grid.cells) recordFrameTitle(irTable, tableItems, pageNum);
|
|
7130
7616
|
if (grid.cells && finalRows === numRows) TABLE_ROWYS.set(irTable, grid.rowYs);
|
|
7131
7617
|
if (grid.continues) CONT_PARTS.set(irTable, grid.continues);
|
|
7132
7618
|
const hasContent = finalGrid.some((row) => row.some((cell) => cell.text.trim() !== ""));
|
|
@@ -7178,7 +7664,14 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
7178
7664
|
continue;
|
|
7179
7665
|
}
|
|
7180
7666
|
}
|
|
7181
|
-
if (!grid.cells && shouldDemoteTable(irTable)) {
|
|
7667
|
+
if (!grid.cells && !nestedAttached && shouldDemoteTable(irTable)) {
|
|
7668
|
+
const paragraphs = numRows === 1 && numCols === 1 ? irTable.cells[0]?.[0]?.blocks : void 0;
|
|
7669
|
+
if (paragraphs?.length) {
|
|
7670
|
+
blocks.push(...paragraphs);
|
|
7671
|
+
frameParagraphUnits.push(paragraphs);
|
|
7672
|
+
recordFrameReadingUnit(paragraphs, tableBbox);
|
|
7673
|
+
continue;
|
|
7674
|
+
}
|
|
7182
7675
|
const demoted = demoteTableToText(irTable);
|
|
7183
7676
|
if (demoted) {
|
|
7184
7677
|
const text = numGridRows === 1 ? "\n" + demoted + "\n" : demoted;
|
|
@@ -7232,9 +7725,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
7232
7725
|
}
|
|
7233
7726
|
{
|
|
7234
7727
|
const rects = remaining.map((i) => ({ x: i.x, y: i.y, w: i.w, h: i.h > 0 ? i.h : i.fontSize }));
|
|
7235
|
-
for (const b of blocks) {
|
|
7236
|
-
if (b.bbox && !(b.table && EMPTY_PARTS.has(b.table))) rects.push({ x: b.bbox.x, y: b.bbox.y, w: b.bbox.width, h: b.bbox.height });
|
|
7237
|
-
}
|
|
7728
|
+
for (const b of frameLayoutBoxes(blocks.filter((b2) => !(b2.table && EMPTY_PARTS.has(b2.table))))) rects.push({ x: b.x, y: b.y, w: b.width, h: b.height });
|
|
7238
7729
|
gutterX = detectColumnGutter(rects) ?? findRuledColumnDivider(
|
|
7239
7730
|
blocks.filter((b) => b.type === "table" && b.bbox && b.table && !EMPTY_PARTS.has(b.table)).map((b) => ({ x: b.bbox.x, y: b.bbox.y, w: b.bbox.width, h: b.bbox.height })),
|
|
7240
7731
|
horizontals,
|
|
@@ -7281,7 +7772,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
7281
7772
|
finalTextBlocks = detectListBlocks(textBlocks);
|
|
7282
7773
|
}
|
|
7283
7774
|
}
|
|
7284
|
-
const units =
|
|
7775
|
+
const units = groupFrameParagraphUnits(groupFlowBoxUnits(blocks, grids, horizontals, verticals, verifiedRightArrows), frameParagraphUnits);
|
|
7285
7776
|
let off = 0;
|
|
7286
7777
|
for (const size of groupSizes) {
|
|
7287
7778
|
const unit = finalTextBlocks.slice(off, off + size);
|
|
@@ -7420,7 +7911,7 @@ function mergeAdjacentTableBlocks(blocks) {
|
|
|
7420
7911
|
table: merged,
|
|
7421
7912
|
bbox: { ...pb, y: cb.y, height: pb.y + pb.height - cb.y }
|
|
7422
7913
|
};
|
|
7423
|
-
} else if (prev.type === "table" && curr.type === "table" && prev.table && curr.table && prev.table.cols === curr.table.cols && prev.table.renderAsTable === curr.table.renderAsTable && !CLIP_TABLES.has(prev.table) && !CLIP_TABLES.has(curr.table)) {
|
|
7914
|
+
} else if (prev.type === "table" && curr.type === "table" && prev.table && curr.table && prev.table.cols === curr.table.cols && prev.table.renderAsTable === curr.table.renderAsTable && !CLIP_TABLES.has(prev.table) && !CLIP_TABLES.has(curr.table) && !separateRepeatedHeadings(prev, curr)) {
|
|
7424
7915
|
const merged = {
|
|
7425
7916
|
rows: prev.table.rows + curr.table.rows,
|
|
7426
7917
|
cols: prev.table.cols,
|
|
@@ -7435,6 +7926,12 @@ function mergeAdjacentTableBlocks(blocks) {
|
|
|
7435
7926
|
}
|
|
7436
7927
|
return result;
|
|
7437
7928
|
}
|
|
7929
|
+
function separateRepeatedHeadings(upper, lower) {
|
|
7930
|
+
const u = upper.table, d = lower.table, ub = upper.bbox, db = lower.bbox;
|
|
7931
|
+
if (!ub || !db || ub.page !== db.page || u.rows < 2 || d.rows < 2 || !u.hasHeader || !d.hasHeader || ub.y - (db.y + db.height) <= 1 || Math.abs(ub.x - db.x) > 1 || Math.abs(ub.width - db.width) > 1) return false;
|
|
7932
|
+
const a = u.cells[0], b = d.cells[0], norm = (text) => text.replace(/<\/?u>|~~|\s+/g, "");
|
|
7933
|
+
return a.filter((cell) => norm(cell.text)).length >= 2 && a.length === b.length && a.every((cell, c) => cell.colSpan === b[c].colSpan && cell.rowSpan === b[c].rowSpan && norm(cell.text) === norm(b[c].text));
|
|
7934
|
+
}
|
|
7438
7935
|
function streamLines(items) {
|
|
7439
7936
|
if (items.some((i) => i.seq === void 0)) return groupByY([...items].sort((a, b) => b.y - a.y || a.x - b.x));
|
|
7440
7937
|
const lines = [];
|
|
@@ -7612,7 +8109,11 @@ export {
|
|
|
7612
8109
|
extractImageRegions,
|
|
7613
8110
|
filterHiddenText,
|
|
7614
8111
|
collapseEvenSpacing,
|
|
8112
|
+
computeBBox,
|
|
8113
|
+
dominantStyle,
|
|
7615
8114
|
normalizeItems,
|
|
8115
|
+
groupByY,
|
|
8116
|
+
mergeLineSimple,
|
|
7616
8117
|
WrapLexicon,
|
|
7617
8118
|
startsNewItem,
|
|
7618
8119
|
wrapJoiner,
|
|
@@ -7633,6 +8134,7 @@ export {
|
|
|
7633
8134
|
detectKoreanListBlocks,
|
|
7634
8135
|
removeHeaderFooterBlocks,
|
|
7635
8136
|
CLIP_TABLES,
|
|
8137
|
+
FRAME_TITLE_BLOCKS,
|
|
7636
8138
|
TABLE_COLXS,
|
|
7637
8139
|
TABLE_ROWYS,
|
|
7638
8140
|
TABLE_TAIL,
|
|
@@ -7646,7 +8148,11 @@ export {
|
|
|
7646
8148
|
trimTrailingEmptyTableCols,
|
|
7647
8149
|
NO_EDGES,
|
|
7648
8150
|
joinCellEdges,
|
|
8151
|
+
FRAME_READING_UNITS,
|
|
8152
|
+
recordFrameReadingUnit,
|
|
8153
|
+
restoreImageBullets,
|
|
8154
|
+
detectRightArrowRegions,
|
|
7649
8155
|
removeSideTabs,
|
|
7650
8156
|
extractPageBlocksWithLines
|
|
7651
8157
|
};
|
|
7652
|
-
//# sourceMappingURL=chunk-
|
|
8158
|
+
//# sourceMappingURL=chunk-KUUSP6OS.js.map
|