kordoc 4.17.4 → 4.17.6
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/{-SQRLFE4N.js → -Y6U3UTVZ.js} +11 -11
- package/dist/{chunk-RCS7WXOM.js → chunk-226C4AJR.js} +2 -2
- package/dist/{chunk-ODVIUG6Q.js → chunk-2WUE6JIT.js} +2 -2
- package/dist/{chunk-AOONZC4S.cjs → chunk-4LU6NGTL.cjs} +3 -3
- package/dist/{chunk-AOONZC4S.cjs.map → chunk-4LU6NGTL.cjs.map} +1 -1
- package/dist/{chunk-HY33WBAH.js → chunk-5VHV6W7W.js} +2 -2
- package/dist/{chunk-W3OY3SLY.js → chunk-6A4Z6VYA.js} +2 -2
- package/dist/{chunk-IERSVUW6.js → chunk-7F7CUU22.js} +2 -2
- package/dist/{chunk-TMHMJUYU.js → chunk-7R7NFGHY.js} +6 -6
- package/dist/{chunk-VJP7O6BL.js → chunk-AYMTRCLC.js} +2 -2
- package/dist/{chunk-P2ZPPRM7.js → chunk-B3RQHQCC.js} +2 -2
- package/dist/{chunk-PTMYCK7R.js → chunk-BPLEMV4B.js} +2 -2
- package/dist/{chunk-WNF3TSV3.cjs → chunk-CZOPNDTO.cjs} +426 -324
- package/dist/chunk-CZOPNDTO.cjs.map +1 -0
- package/dist/{chunk-EXBZHI25.cjs → chunk-FVESLY6V.cjs} +2 -2
- package/dist/{chunk-EXBZHI25.cjs.map → chunk-FVESLY6V.cjs.map} +1 -1
- package/dist/{chunk-7TE6TK52.js → chunk-HRJAAWEP.js} +2 -2
- package/dist/{chunk-AFXX3YSP.cjs → chunk-L5JX2GAM.cjs} +6 -6
- package/dist/{chunk-AFXX3YSP.cjs.map → chunk-L5JX2GAM.cjs.map} +1 -1
- package/dist/{chunk-GNORDND5.cjs → chunk-LLFXHX7K.cjs} +12 -12
- package/dist/{chunk-GNORDND5.cjs.map → chunk-LLFXHX7K.cjs.map} +1 -1
- package/dist/{chunk-O5T5OIJM.js → chunk-MOM67IND.js} +2 -2
- package/dist/{chunk-AAQR4RIX.js → chunk-MOVFO74W.js} +2 -2
- package/dist/{chunk-4D52VUGA.js → chunk-PGHIQ6E5.js} +3 -3
- package/dist/{chunk-PVJFCDND.js → chunk-QKEPDJ2D.js} +341 -239
- package/dist/chunk-QKEPDJ2D.js.map +1 -0
- package/dist/{chunk-KIYHQQVO.cjs → chunk-S26THA3Q.cjs} +3 -3
- package/dist/{chunk-KIYHQQVO.cjs.map → chunk-S26THA3Q.cjs.map} +1 -1
- package/dist/{chunk-DD6AY6EI.js → chunk-T5O6HEHG.js} +2 -2
- package/dist/{chunk-PNXJYEOR.js → chunk-TOCNK4VO.js} +2 -2
- package/dist/{chunk-FSCVZR4A.js → chunk-U6NLEEIN.js} +4 -4
- package/dist/{chunk-HQ6TM2JE.js → chunk-VHIGYTRO.js} +3 -3
- package/dist/{chunk-YBIWPCUX.js → chunk-YCMPQRHV.js} +342 -240
- package/dist/chunk-YCMPQRHV.js.map +1 -0
- package/dist/{chunk-NNNRN6BY.js → chunk-ZQA7Q3GV.js} +2 -2
- package/dist/{chunk-6DXSRQ65.js → chunk-ZQBBMUFA.js} +2 -2
- package/dist/{chunk-SSY6FQLS.js → chunk-ZS5KKM4L.js} +10 -10
- package/dist/chunks-S72SPTCL.js +10 -0
- package/dist/cli.js +26 -26
- package/dist/{formula-U37MTMBD.cjs → formula-3IQFGZXS.cjs} +9 -9
- package/dist/{formula-U37MTMBD.cjs.map → formula-3IQFGZXS.cjs.map} +1 -1
- package/dist/{formula-WZH5CMA3.js → formula-B72X7SFX.js} +3 -3
- package/dist/{formula-U3MJXXIL.js → formula-U7K3K4AE.js} +4 -4
- package/dist/{image-ocr-OXU55EW3.cjs → image-ocr-GYYVTTDG.cjs} +15 -15
- package/dist/{image-ocr-OXU55EW3.cjs.map → image-ocr-GYYVTTDG.cjs.map} +1 -1
- package/dist/{image-ocr-HYWDBN72.js → image-ocr-UGL5PWJ3.js} +6 -6
- package/dist/{image-ocr-V6MICC6R.js → image-ocr-YCBQ7HUD.js} +9 -9
- package/dist/index.cjs +259 -259
- package/dist/index.js +5 -5
- package/dist/mcp.js +22 -22
- package/dist/{model-bundle-AHBUQ6SD.js → model-bundle-Z4KSW4P5.js} +5 -5
- package/dist/{models-UF7B5LLG.js → models-HCI2GHBA.js} +5 -5
- package/dist/{parser-IXRGUYZW.cjs → parser-MZKMFBI3.cjs} +175 -157
- package/dist/parser-MZKMFBI3.cjs.map +1 -0
- package/dist/{parser-T4FBG2FR.js → parser-NFOHA5VI.js} +28 -10
- package/dist/{parser-F6N6ID25.js.map → parser-NFOHA5VI.js.map} +1 -1
- package/dist/{parser-F6N6ID25.js → parser-XCHUEHOX.js} +31 -13
- package/dist/{parser-T4FBG2FR.js.map → parser-XCHUEHOX.js.map} +1 -1
- package/dist/pdf-ocr-PXU6MBUZ.cjs +16 -0
- package/dist/{pdf-ocr-2CITOAIG.cjs.map → pdf-ocr-PXU6MBUZ.cjs.map} +1 -1
- package/dist/pdf-ocr-QQ6MJCXT.js +19 -0
- package/dist/pdf-ocr-WADZZ2YQ.js +15 -0
- package/dist/{profile-io-GM3NVLV3.js → profile-io-3BZXXOIW.js} +3 -3
- package/dist/{rasterize-4A3LJXTG.js → rasterize-SLLX5CQN.js} +3 -3
- package/dist/{redact-doc-SQ7C3LIG.js → redact-doc-CCOUCCQA.js} +11 -11
- package/dist/{render-6LTQZG4W.js → render-7OLLRV4U.js} +7 -7
- package/dist/seal-WGSATSQC.js +10 -0
- package/dist/{setup-DGBJOROA.js → setup-GONHHIMX.js} +3 -3
- package/dist/visual-C5D42ZAJ.js +20 -0
- package/dist/{watch-DJVJRSLE.js → watch-EWWEQI33.js} +12 -12
- package/package.json +1 -1
- package/dist/chunk-PVJFCDND.js.map +0 -1
- package/dist/chunk-WNF3TSV3.cjs.map +0 -1
- package/dist/chunk-YBIWPCUX.js.map +0 -1
- package/dist/chunks-VNSLMJQD.js +0 -10
- package/dist/parser-IXRGUYZW.cjs.map +0 -1
- package/dist/pdf-ocr-2CITOAIG.cjs +0 -16
- package/dist/pdf-ocr-RG2MFWBX.js +0 -15
- package/dist/pdf-ocr-U7Z4IUMA.js +0 -19
- package/dist/seal-ROSVLTRQ.js +0 -10
- package/dist/visual-6W34SFIW.js +0 -20
- /package/dist/{-SQRLFE4N.js.map → -Y6U3UTVZ.js.map} +0 -0
- /package/dist/{chunk-RCS7WXOM.js.map → chunk-226C4AJR.js.map} +0 -0
- /package/dist/{chunk-ODVIUG6Q.js.map → chunk-2WUE6JIT.js.map} +0 -0
- /package/dist/{chunk-HY33WBAH.js.map → chunk-5VHV6W7W.js.map} +0 -0
- /package/dist/{chunk-W3OY3SLY.js.map → chunk-6A4Z6VYA.js.map} +0 -0
- /package/dist/{chunk-IERSVUW6.js.map → chunk-7F7CUU22.js.map} +0 -0
- /package/dist/{chunk-TMHMJUYU.js.map → chunk-7R7NFGHY.js.map} +0 -0
- /package/dist/{chunk-VJP7O6BL.js.map → chunk-AYMTRCLC.js.map} +0 -0
- /package/dist/{chunk-P2ZPPRM7.js.map → chunk-B3RQHQCC.js.map} +0 -0
- /package/dist/{chunk-PTMYCK7R.js.map → chunk-BPLEMV4B.js.map} +0 -0
- /package/dist/{chunk-7TE6TK52.js.map → chunk-HRJAAWEP.js.map} +0 -0
- /package/dist/{chunk-O5T5OIJM.js.map → chunk-MOM67IND.js.map} +0 -0
- /package/dist/{chunk-AAQR4RIX.js.map → chunk-MOVFO74W.js.map} +0 -0
- /package/dist/{chunk-4D52VUGA.js.map → chunk-PGHIQ6E5.js.map} +0 -0
- /package/dist/{chunk-DD6AY6EI.js.map → chunk-T5O6HEHG.js.map} +0 -0
- /package/dist/{chunk-PNXJYEOR.js.map → chunk-TOCNK4VO.js.map} +0 -0
- /package/dist/{chunk-FSCVZR4A.js.map → chunk-U6NLEEIN.js.map} +0 -0
- /package/dist/{chunk-HQ6TM2JE.js.map → chunk-VHIGYTRO.js.map} +0 -0
- /package/dist/{chunk-NNNRN6BY.js.map → chunk-ZQA7Q3GV.js.map} +0 -0
- /package/dist/{chunk-6DXSRQ65.js.map → chunk-ZQBBMUFA.js.map} +0 -0
- /package/dist/{chunk-SSY6FQLS.js.map → chunk-ZS5KKM4L.js.map} +0 -0
- /package/dist/{chunks-VNSLMJQD.js.map → chunks-S72SPTCL.js.map} +0 -0
- /package/dist/{formula-WZH5CMA3.js.map → formula-B72X7SFX.js.map} +0 -0
- /package/dist/{formula-U3MJXXIL.js.map → formula-U7K3K4AE.js.map} +0 -0
- /package/dist/{image-ocr-HYWDBN72.js.map → image-ocr-UGL5PWJ3.js.map} +0 -0
- /package/dist/{image-ocr-V6MICC6R.js.map → image-ocr-YCBQ7HUD.js.map} +0 -0
- /package/dist/{model-bundle-AHBUQ6SD.js.map → model-bundle-Z4KSW4P5.js.map} +0 -0
- /package/dist/{models-UF7B5LLG.js.map → models-HCI2GHBA.js.map} +0 -0
- /package/dist/{pdf-ocr-RG2MFWBX.js.map → pdf-ocr-QQ6MJCXT.js.map} +0 -0
- /package/dist/{pdf-ocr-U7Z4IUMA.js.map → pdf-ocr-WADZZ2YQ.js.map} +0 -0
- /package/dist/{profile-io-GM3NVLV3.js.map → profile-io-3BZXXOIW.js.map} +0 -0
- /package/dist/{rasterize-4A3LJXTG.js.map → rasterize-SLLX5CQN.js.map} +0 -0
- /package/dist/{redact-doc-SQ7C3LIG.js.map → redact-doc-CCOUCCQA.js.map} +0 -0
- /package/dist/{render-6LTQZG4W.js.map → render-7OLLRV4U.js.map} +0 -0
- /package/dist/{seal-ROSVLTRQ.js.map → seal-WGSATSQC.js.map} +0 -0
- /package/dist/{setup-DGBJOROA.js.map → setup-GONHHIMX.js.map} +0 -0
- /package/dist/{visual-6W34SFIW.js.map → visual-C5D42ZAJ.js.map} +0 -0
- /package/dist/{watch-DJVJRSLE.js.map → watch-EWWEQI33.js.map} +0 -0
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
var
|
|
7
|
+
var _chunkL5JX2GAMcjs = require('./chunk-L5JX2GAM.cjs');
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
var
|
|
11
|
+
var _chunk4LU6NGTLcjs = require('./chunk-4LU6NGTL.cjs');
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
var
|
|
15
|
+
var _chunkFVESLY6Vcjs = require('./chunk-FVESLY6V.cjs');
|
|
16
16
|
|
|
17
17
|
// src/ocr/models.ts
|
|
18
18
|
var _path = require('path');
|
|
@@ -40,10 +40,10 @@ var OCR_REC_DICT = {
|
|
|
40
40
|
};
|
|
41
41
|
var ALL_OCR_MODELS = [OCR_DET_MODEL, OCR_REC_MODEL, OCR_REC_DICT];
|
|
42
42
|
function getOcrModelsDir() {
|
|
43
|
-
return
|
|
43
|
+
return _chunk4LU6NGTLcjs.getModelsDir.call(void 0, "ppocr");
|
|
44
44
|
}
|
|
45
45
|
async function ensureOcrModels(onProgress) {
|
|
46
|
-
return
|
|
46
|
+
return _chunk4LU6NGTLcjs.ensureModelsIn.call(void 0, getOcrModelsDir(), ALL_OCR_MODELS, onProgress);
|
|
47
47
|
}
|
|
48
48
|
async function ocrModelsCached() {
|
|
49
49
|
const dir = getOcrModelsDir();
|
|
@@ -2090,7 +2090,7 @@ function tagScripts(text, lines) {
|
|
|
2090
2090
|
const [s, e, kind] = marks[m];
|
|
2091
2091
|
out = out.slice(0, s) + `<${kind}>` + out.slice(s, e) + `</${kind}>` + out.slice(e);
|
|
2092
2092
|
}
|
|
2093
|
-
return
|
|
2093
|
+
return _chunkL5JX2GAMcjs.tidyScriptTags.call(void 0, out);
|
|
2094
2094
|
}
|
|
2095
2095
|
|
|
2096
2096
|
// src/pdf/line-wrap.ts
|
|
@@ -3236,6 +3236,324 @@ function panelBlocks(items, panel, pageNum) {
|
|
|
3236
3236
|
});
|
|
3237
3237
|
}
|
|
3238
3238
|
|
|
3239
|
+
// src/pdf/xy-cut.ts
|
|
3240
|
+
var MAX_XYCUT_DEPTH = 50;
|
|
3241
|
+
var XYCUT_MIN_GAP = 5;
|
|
3242
|
+
var CROSS_LAYOUT_BETA = 2;
|
|
3243
|
+
var CROSS_OVERLAP_RATIO = 0.1;
|
|
3244
|
+
var CROSS_MIN_OVERLAPS = 2;
|
|
3245
|
+
var CROSS_MAX_MASK_RATIO = 0.2;
|
|
3246
|
+
var NARROW_ELEMENT_WIDTH_RATIO = 0.1;
|
|
3247
|
+
var PROSE_GUTTER_MIN_GAP = 6;
|
|
3248
|
+
var XY_WRAP_BANDS = /* @__PURE__ */ new WeakMap();
|
|
3249
|
+
var XY_WRAP_ITEMS = /* @__PURE__ */ new WeakMap();
|
|
3250
|
+
var leaf = (items, wrapped) => {
|
|
3251
|
+
wrapped = validWrapBands(items, wrapped);
|
|
3252
|
+
const source = wrapped.length ? [...items] : [];
|
|
3253
|
+
for (const item of items) {
|
|
3254
|
+
if (wrapped.length) {
|
|
3255
|
+
XY_WRAP_BANDS.set(item, wrapped);
|
|
3256
|
+
XY_WRAP_ITEMS.set(item, source);
|
|
3257
|
+
} else {
|
|
3258
|
+
XY_WRAP_BANDS.delete(item);
|
|
3259
|
+
XY_WRAP_ITEMS.delete(item);
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
return [items];
|
|
3263
|
+
};
|
|
3264
|
+
function xyCutOrder(items, gapThreshold, depth = 0, wrapped) {
|
|
3265
|
+
if (items.length === 0) return [];
|
|
3266
|
+
const newRegion = wrapped === void 0;
|
|
3267
|
+
wrapped ??= inheritedWrapBands(items);
|
|
3268
|
+
if (items.length <= 2 || depth >= MAX_XYCUT_DEPTH) return leaf(items, wrapped);
|
|
3269
|
+
if (depth === 0 && items.length >= 3) {
|
|
3270
|
+
const cross = identifyCrossLayoutItems(items);
|
|
3271
|
+
if (cross.size > 0 && cross.size <= items.length * CROSS_MAX_MASK_RATIO) {
|
|
3272
|
+
const rest = items.filter((i) => !cross.has(i));
|
|
3273
|
+
if (rest.length > 0) {
|
|
3274
|
+
const groups = xyCutOrder(rest, gapThreshold, 1);
|
|
3275
|
+
return mergeCrossLayoutGroups(groups, [...cross]);
|
|
3276
|
+
}
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
const minGap = Math.max(XYCUT_MIN_GAP, gapThreshold);
|
|
3280
|
+
const sortedY = [...items].sort((a, b) => b.y - a.y);
|
|
3281
|
+
let hCut = findHorizontalCut(sortedY, wrapped);
|
|
3282
|
+
if (newRegion && hCut.gap >= minGap) {
|
|
3283
|
+
wrapped = wrappedLineBands(items, wrapped);
|
|
3284
|
+
hCut = findHorizontalCut(sortedY, wrapped);
|
|
3285
|
+
}
|
|
3286
|
+
const vCut = findVerticalCutWithOutlierFilter(items, minGap);
|
|
3287
|
+
const hValid = hCut.gap >= minGap;
|
|
3288
|
+
const vValid = (vCut.gap >= minGap || vCut.gap >= PROSE_GUTTER_MIN_GAP && isProseGutter(items, vCut.position)) && !splitsSpacedLabel(items, vCut.position);
|
|
3289
|
+
let useHorizontal;
|
|
3290
|
+
if (hValid && vValid) useHorizontal = vCut.gap <= hCut.gap * 1.5 || staggeredSides(items, vCut.position);
|
|
3291
|
+
else if (hValid) useHorizontal = true;
|
|
3292
|
+
else if (vValid) useHorizontal = false;
|
|
3293
|
+
else return _nullishCoalesce(splitEdgeSpannedColumns(items, gapThreshold, depth), () => ( leaf(items, wrapped)));
|
|
3294
|
+
if (useHorizontal) {
|
|
3295
|
+
const upper = items.filter((i) => i.y > hCut.position);
|
|
3296
|
+
const lower = items.filter((i) => i.y <= hCut.position);
|
|
3297
|
+
if (upper.length > 0 && lower.length > 0 && upper.length < items.length) {
|
|
3298
|
+
return [...xyCutOrder(upper, gapThreshold, depth + 1, wrapped), ...xyCutOrder(lower, gapThreshold, depth + 1, wrapped)];
|
|
3299
|
+
}
|
|
3300
|
+
} else {
|
|
3301
|
+
const left = items.filter((i) => i.x + i.w / 2 < vCut.position);
|
|
3302
|
+
const right = items.filter((i) => i.x + i.w / 2 >= vCut.position);
|
|
3303
|
+
if (left.length > 0 && right.length > 0 && left.length < items.length) {
|
|
3304
|
+
return [...xyCutOrder(left, gapThreshold, depth + 1), ...xyCutOrder(right, gapThreshold, depth + 1)];
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
return leaf(items, wrapped);
|
|
3308
|
+
}
|
|
3309
|
+
function splitsSpacedLabel(items, cutX) {
|
|
3310
|
+
const lone = (i) => /^[가-힣]$/.test(i.text.trim());
|
|
3311
|
+
const sameRow = (a, b) => Math.min(a.y, b.y) > Math.max(a.y - a.h, b.y - b.h);
|
|
3312
|
+
const left = items.filter((i) => i.x + i.w / 2 < cutX);
|
|
3313
|
+
const right = items.filter((i) => i.x + i.w / 2 >= cutX);
|
|
3314
|
+
let spaced = 0;
|
|
3315
|
+
for (const r of right) {
|
|
3316
|
+
if (right.some((o) => o !== r && o.x < r.x && sameRow(o, r))) continue;
|
|
3317
|
+
const row = left.filter((l2) => sameRow(l2, r));
|
|
3318
|
+
if (row.length === 0) continue;
|
|
3319
|
+
const l = row.reduce((a, b) => b.x + b.w > a.x + a.w ? b : a);
|
|
3320
|
+
if (!lone(l) || !lone(r)) return false;
|
|
3321
|
+
spaced++;
|
|
3322
|
+
}
|
|
3323
|
+
return spaced > 0;
|
|
3324
|
+
}
|
|
3325
|
+
function staggeredSides(items, cutX) {
|
|
3326
|
+
const left = items.filter((i) => i.x + i.w / 2 < cutX);
|
|
3327
|
+
const right = items.filter((i) => i.x + i.w / 2 >= cutX);
|
|
3328
|
+
if (left.length * right.length > 2e5) return false;
|
|
3329
|
+
const shareRow = (a, b) => Math.min(a.y, b.y) > Math.max(a.y - a.h, b.y - b.h);
|
|
3330
|
+
if (left.some((a) => right.some((b) => shareRow(a, b)))) return false;
|
|
3331
|
+
const sides = [...items].sort((a, b) => b.y - a.y).map((i) => i.x + i.w / 2 < cutX);
|
|
3332
|
+
let switches = 0;
|
|
3333
|
+
for (let k = 1; k < sides.length; k++) if (sides[k] !== sides[k - 1]) switches++;
|
|
3334
|
+
return switches >= 3;
|
|
3335
|
+
}
|
|
3336
|
+
function identifyCrossLayoutItems(items) {
|
|
3337
|
+
const cross = /* @__PURE__ */ new Set();
|
|
3338
|
+
if (items.length < 3) return cross;
|
|
3339
|
+
let maxWidth = 0;
|
|
3340
|
+
for (const i of items) {
|
|
3341
|
+
if (i.w > maxWidth) maxWidth = i.w;
|
|
3342
|
+
}
|
|
3343
|
+
const threshold = CROSS_LAYOUT_BETA * maxWidth;
|
|
3344
|
+
for (const item of items) {
|
|
3345
|
+
if (item.w < threshold) continue;
|
|
3346
|
+
let overlaps = 0;
|
|
3347
|
+
for (const other of items) {
|
|
3348
|
+
if (other === item) continue;
|
|
3349
|
+
const left = Math.max(item.x, other.x);
|
|
3350
|
+
const right = Math.min(item.x + item.w, other.x + other.w);
|
|
3351
|
+
const overlapW = right - left;
|
|
3352
|
+
if (overlapW <= 0) continue;
|
|
3353
|
+
const smaller = Math.min(item.w, other.w);
|
|
3354
|
+
if (smaller > 0 && overlapW / smaller >= CROSS_OVERLAP_RATIO) {
|
|
3355
|
+
overlaps++;
|
|
3356
|
+
if (overlaps >= CROSS_MIN_OVERLAPS) break;
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
if (overlaps >= CROSS_MIN_OVERLAPS) cross.add(item);
|
|
3360
|
+
}
|
|
3361
|
+
return cross;
|
|
3362
|
+
}
|
|
3363
|
+
function mergeCrossLayoutGroups(groups, cross) {
|
|
3364
|
+
if (cross.length === 0) return groups;
|
|
3365
|
+
const sortedCross = [...cross].sort((a, b) => b.y + b.h - (a.y + a.h) || a.x - b.x);
|
|
3366
|
+
const groupTop = (g) => {
|
|
3367
|
+
let top = -Infinity;
|
|
3368
|
+
for (const i of g) {
|
|
3369
|
+
const t = i.y + i.h;
|
|
3370
|
+
if (t > top) top = t;
|
|
3371
|
+
}
|
|
3372
|
+
return top;
|
|
3373
|
+
};
|
|
3374
|
+
const result = [];
|
|
3375
|
+
let gi = 0, ci = 0;
|
|
3376
|
+
while (gi < groups.length || ci < sortedCross.length) {
|
|
3377
|
+
if (ci >= sortedCross.length) {
|
|
3378
|
+
result.push(groups[gi++]);
|
|
3379
|
+
continue;
|
|
3380
|
+
}
|
|
3381
|
+
if (gi >= groups.length) {
|
|
3382
|
+
result.push([sortedCross[ci++]]);
|
|
3383
|
+
continue;
|
|
3384
|
+
}
|
|
3385
|
+
const crossTop = sortedCross[ci].y + sortedCross[ci].h;
|
|
3386
|
+
if (crossTop >= groupTop(groups[gi])) result.push([sortedCross[ci++]]);
|
|
3387
|
+
else result.push(groups[gi++]);
|
|
3388
|
+
}
|
|
3389
|
+
return result;
|
|
3390
|
+
}
|
|
3391
|
+
function validWrapBands(items, bands) {
|
|
3392
|
+
if (!bands.length) return [];
|
|
3393
|
+
const present = new Set(items);
|
|
3394
|
+
return bands.filter((b) => b.sources.every(({ item: a, state: s }) => present.has(a) && a.text === s.text && a.x === s.x && a.y === s.y && a.w === s.w && a.h === s.h && a.fontSize === s.fontSize && a.fontName === s.fontName && a.isHidden === s.isHidden && a.hasSpaceBefore === s.hasSpaceBefore && a.syntheticSpace === s.syntheticSpace && a.strike === s.strike && a.underline === s.underline && a.seq === s.seq && a.rotated === s.rotated));
|
|
3395
|
+
}
|
|
3396
|
+
function inheritedWrapBands(items) {
|
|
3397
|
+
const source = XY_WRAP_ITEMS.get(items[0]);
|
|
3398
|
+
const present = _optionalChain([source, 'optionalAccess', _82 => _82.length]) === items.length ? new Set(items) : null;
|
|
3399
|
+
const sameLeaf = present && source.every((item) => present.has(item));
|
|
3400
|
+
return sameLeaf ? validWrapBands(items, _nullishCoalesce(XY_WRAP_BANDS.get(items[0]), () => ( []))) : [];
|
|
3401
|
+
}
|
|
3402
|
+
function tocRecordBoundaries(rows) {
|
|
3403
|
+
const out = /* @__PURE__ */ new Set();
|
|
3404
|
+
if (rows.length < 2) return out;
|
|
3405
|
+
const records = rows.map((row, index) => {
|
|
3406
|
+
const visible = row.filter((i) => i.text.trim()).sort((a, b) => a.x - b.x);
|
|
3407
|
+
let start = visible.length - 1;
|
|
3408
|
+
if (start < 1 || !/^\d+$/.test(visible[start].text.trim())) return null;
|
|
3409
|
+
for (; start > 0; start--) {
|
|
3410
|
+
const a = visible[start - 1], b = visible[start];
|
|
3411
|
+
if (!/^\d+$/.test(a.text.trim()) || b.x - (a.x + a.w) > 0.5 * b.fontSize) break;
|
|
3412
|
+
}
|
|
3413
|
+
const nums = visible.slice(start), label = visible.slice(0, start).filter((i) => !/^[·.⋯…]{4,}$/.test(i.text.trim()));
|
|
3414
|
+
const fs = nums[0].fontSize;
|
|
3415
|
+
if (!/^\d{1,4}$/.test(nums.map((i) => i.text.trim()).join("")) || fs <= 0 || !label.some((i) => /[\p{L}]/u.test(i.text)) || nums[0].x - Math.max(...label.map((i) => i.x + i.w)) < Math.max(2 * fs, 30)) return null;
|
|
3416
|
+
return { right: Math.max(...nums.map((i) => i.x + i.w)), fs, index };
|
|
3417
|
+
}).filter((record) => record !== null).sort((a, b) => a.right - b.right);
|
|
3418
|
+
for (let i = 0; i + 1 < records.length; i++) {
|
|
3419
|
+
const a = records[i], b = records[i + 1];
|
|
3420
|
+
if (Math.abs(a.right - b.right) <= 0.5 * Math.min(a.fs, b.fs) && Math.abs(a.fs - b.fs) <= 0.15 * Math.min(a.fs, b.fs)) {
|
|
3421
|
+
if (a.index + 1 < rows.length) out.add(a.index);
|
|
3422
|
+
if (b.index + 1 < rows.length) out.add(b.index);
|
|
3423
|
+
}
|
|
3424
|
+
}
|
|
3425
|
+
return out;
|
|
3426
|
+
}
|
|
3427
|
+
function wrappedLineBands(items, inherited) {
|
|
3428
|
+
const rows = groupByY(items);
|
|
3429
|
+
const records = tocRecordBoundaries(rows);
|
|
3430
|
+
const lines = rows.map((row) => {
|
|
3431
|
+
const box = computeBBox(row, 0);
|
|
3432
|
+
return {
|
|
3433
|
+
text: mergeLineSimple(row).replace(/<\/?u>|~~/g, ""),
|
|
3434
|
+
left: box.x,
|
|
3435
|
+
right: box.x + box.width,
|
|
3436
|
+
y: row.reduce((n, i) => n + i.y, 0) / row.length,
|
|
3437
|
+
fontSize: _nullishCoalesce(_optionalChain([dominantStyle, 'call', _83 => _83(row), 'optionalAccess', _84 => _84.fontSize]), () => ( 0)),
|
|
3438
|
+
sources: row.map((item) => ({ item, state: { ...item } }))
|
|
3439
|
+
};
|
|
3440
|
+
});
|
|
3441
|
+
const joins = bodyLineJoins(lines);
|
|
3442
|
+
const fresh = lines.slice(0, -1).flatMap((line, i) => joins[i] === "\n" || records.has(i) || line.text.trim() === lines[i + 1].text.trim() ? [] : [{ top: line.y, bottom: lines[i + 1].y, sources: [...line.sources, ...lines[i + 1].sources] }]);
|
|
3443
|
+
const freshKeys = new Set(fresh.map((b) => `${b.top}:${b.bottom}`));
|
|
3444
|
+
return [...inherited.filter((b) => !freshKeys.has(`${b.top}:${b.bottom}`)), ...fresh].sort((a, b) => b.top - a.top);
|
|
3445
|
+
}
|
|
3446
|
+
function findHorizontalCut(sorted, wrapped) {
|
|
3447
|
+
if (sorted.length < 2) return { position: 0, gap: 0 };
|
|
3448
|
+
let largestGap = 0;
|
|
3449
|
+
let position = 0;
|
|
3450
|
+
let wrapIndex = 0;
|
|
3451
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
3452
|
+
const prevBottom = sorted[i - 1].y - sorted[i - 1].h;
|
|
3453
|
+
const currTop = sorted[i].y;
|
|
3454
|
+
const gap = prevBottom - currTop;
|
|
3455
|
+
if (gap <= 0) continue;
|
|
3456
|
+
const at = (prevBottom + currTop) / 2;
|
|
3457
|
+
while (wrapIndex < wrapped.length && at <= wrapped[wrapIndex].bottom) wrapIndex++;
|
|
3458
|
+
const band = wrapped[wrapIndex];
|
|
3459
|
+
if (gap > largestGap && !(band && at < band.top && at > band.bottom)) {
|
|
3460
|
+
largestGap = gap;
|
|
3461
|
+
position = at;
|
|
3462
|
+
}
|
|
3463
|
+
}
|
|
3464
|
+
return { position, gap: largestGap };
|
|
3465
|
+
}
|
|
3466
|
+
function findVerticalCutWithOutlierFilter(items, minGap) {
|
|
3467
|
+
const edgeCut = findVerticalCut(items);
|
|
3468
|
+
if (edgeCut.gap >= minGap) return edgeCut;
|
|
3469
|
+
if (items.length >= 3) {
|
|
3470
|
+
let minX = Infinity, maxX = -Infinity;
|
|
3471
|
+
for (const i of items) {
|
|
3472
|
+
if (i.x < minX) minX = i.x;
|
|
3473
|
+
const r = i.x + i.w;
|
|
3474
|
+
if (r > maxX) maxX = r;
|
|
3475
|
+
}
|
|
3476
|
+
const narrowThreshold = (maxX - minX) * NARROW_ELEMENT_WIDTH_RATIO;
|
|
3477
|
+
const filtered = items.filter((i) => i.w >= narrowThreshold);
|
|
3478
|
+
if (filtered.length >= 2 && filtered.length < items.length && filtered.length >= items.length * 0.7) {
|
|
3479
|
+
const filteredCut = findVerticalCut(filtered);
|
|
3480
|
+
if (filteredCut.gap > edgeCut.gap && filteredCut.gap >= minGap) {
|
|
3481
|
+
return filteredCut;
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3485
|
+
return edgeCut;
|
|
3486
|
+
}
|
|
3487
|
+
function findVerticalCut(items) {
|
|
3488
|
+
if (items.length < 2) return { position: 0, gap: 0 };
|
|
3489
|
+
const sorted = [...items].sort((a, b) => a.x - b.x || a.x + a.w - (b.x + b.w));
|
|
3490
|
+
let largestGap = 0;
|
|
3491
|
+
let position = 0;
|
|
3492
|
+
let prevRight = null;
|
|
3493
|
+
for (const it of sorted) {
|
|
3494
|
+
const left = it.x;
|
|
3495
|
+
const right = it.x + it.w;
|
|
3496
|
+
if (prevRight !== null && left > prevRight) {
|
|
3497
|
+
const gap = left - prevRight;
|
|
3498
|
+
if (gap > largestGap) {
|
|
3499
|
+
largestGap = gap;
|
|
3500
|
+
position = (prevRight + left) / 2;
|
|
3501
|
+
}
|
|
3502
|
+
}
|
|
3503
|
+
prevRight = prevRight === null ? right : Math.max(prevRight, right);
|
|
3504
|
+
}
|
|
3505
|
+
return { position, gap: largestGap };
|
|
3506
|
+
}
|
|
3507
|
+
function isProseGutter(items, x) {
|
|
3508
|
+
const sideLines = (side) => {
|
|
3509
|
+
const lines = [];
|
|
3510
|
+
for (const item of [...side].sort((a, b) => b.y - a.y)) {
|
|
3511
|
+
const line = lines.find((l) => Math.abs(l.y - item.y) <= 2);
|
|
3512
|
+
if (line) {
|
|
3513
|
+
line.chars += item.text.length;
|
|
3514
|
+
line.left = Math.min(line.left, item.x);
|
|
3515
|
+
line.right = Math.max(line.right, item.x + item.w);
|
|
3516
|
+
} else lines.push({ y: item.y, chars: item.text.length, left: item.x, right: item.x + item.w });
|
|
3517
|
+
}
|
|
3518
|
+
return lines;
|
|
3519
|
+
};
|
|
3520
|
+
const left = sideLines(items.filter((i) => i.x + i.w / 2 < x));
|
|
3521
|
+
const right = sideLines(items.filter((i) => i.x + i.w / 2 >= x));
|
|
3522
|
+
if (left.length < 4 || right.length < 4) return false;
|
|
3523
|
+
const prose = (lines) => {
|
|
3524
|
+
const width = Math.max(...lines.map((l) => l.right)) - Math.min(...lines.map((l) => l.left));
|
|
3525
|
+
const full = lines.filter((l) => l.chars >= 25 && l.right - l.left >= width * 0.6).length;
|
|
3526
|
+
return full >= lines.length * 0.6;
|
|
3527
|
+
};
|
|
3528
|
+
if (!prose(left) || !prose(right)) return false;
|
|
3529
|
+
const span = (lines) => [Math.min(...lines.map((l) => l.y)), Math.max(...lines.map((l) => l.y))];
|
|
3530
|
+
const [l0, l1] = span(left), [r0, r1] = span(right);
|
|
3531
|
+
return Math.min(l1, r1) - Math.max(l0, r0) >= Math.min(l1 - l0, r1 - r0) * 0.5;
|
|
3532
|
+
}
|
|
3533
|
+
function splitEdgeSpannedColumns(items, gapThreshold, depth) {
|
|
3534
|
+
let minX = Infinity, maxX = -Infinity;
|
|
3535
|
+
for (const i of items) {
|
|
3536
|
+
minX = Math.min(minX, i.x);
|
|
3537
|
+
maxX = Math.max(maxX, i.x + i.w);
|
|
3538
|
+
}
|
|
3539
|
+
const narrow = items.filter((i) => i.w < (maxX - minX) * 0.5);
|
|
3540
|
+
if (narrow.length === items.length || narrow.length < 8) return null;
|
|
3541
|
+
const cut = findVerticalCut(narrow);
|
|
3542
|
+
if (cut.gap < PROSE_GUTTER_MIN_GAP || !isProseGutter(narrow, cut.position)) return null;
|
|
3543
|
+
const crossing = items.filter((i) => i.x < cut.position && i.x + i.w > cut.position);
|
|
3544
|
+
const rest = items.filter((i) => !crossing.includes(i));
|
|
3545
|
+
const restTop = Math.max(...rest.map((i) => i.y)), restBottom = Math.min(...rest.map((i) => i.y));
|
|
3546
|
+
const above = crossing.filter((i) => i.y > restTop), below = crossing.filter((i) => i.y < restBottom);
|
|
3547
|
+
if (above.length + below.length !== crossing.length) return null;
|
|
3548
|
+
const left = rest.filter((i) => i.x + i.w / 2 < cut.position), right = rest.filter((i) => i.x + i.w / 2 >= cut.position);
|
|
3549
|
+
return [
|
|
3550
|
+
...above.length ? [above] : [],
|
|
3551
|
+
...xyCutOrder(left, gapThreshold, depth + 1),
|
|
3552
|
+
...xyCutOrder(right, gapThreshold, depth + 1),
|
|
3553
|
+
...below.length ? [below] : []
|
|
3554
|
+
];
|
|
3555
|
+
}
|
|
3556
|
+
|
|
3239
3557
|
// src/pdf/paragraph-lines.ts
|
|
3240
3558
|
var FACE_CHARS = /* @__PURE__ */ new WeakMap();
|
|
3241
3559
|
function hasNumberedStyledTitle(lines) {
|
|
@@ -3250,9 +3568,29 @@ function pushLineParagraphs(out, yLines, pageNum, lex) {
|
|
|
3250
3568
|
const lines = attachDropCaps(yLines).map((items) => ({ items, text: mergeLineSimple(items) })).filter((l) => l.text.trim());
|
|
3251
3569
|
const geo = lines.map((l) => {
|
|
3252
3570
|
const b = computeBBox(l.items, pageNum);
|
|
3253
|
-
return { text: l.text, left: b.x, right: b.x + b.width, y: l.items.reduce((s, i) => s + i.y, 0) / l.items.length, fontSize: _nullishCoalesce(_optionalChain([dominantStyle, 'call',
|
|
3571
|
+
return { text: l.text, left: b.x, right: b.x + b.width, y: l.items.reduce((s, i) => s + i.y, 0) / l.items.length, fontSize: _nullishCoalesce(_optionalChain([dominantStyle, 'call', _85 => _85(l.items), 'optionalAccess', _86 => _86.fontSize]), () => ( 0)) };
|
|
3254
3572
|
});
|
|
3255
3573
|
const joins = bodyLineJoins(geo, lex);
|
|
3574
|
+
const first = _optionalChain([lines, 'access', _87 => _87[0], 'optionalAccess', _88 => _88.items, 'access', _89 => _89[0]]);
|
|
3575
|
+
const bands = first ? _nullishCoalesce(XY_WRAP_BANDS.get(first), () => ( [])) : [];
|
|
3576
|
+
const hasBand = (top, bottom) => {
|
|
3577
|
+
let lo = 0, hi = bands.length;
|
|
3578
|
+
while (lo < hi) {
|
|
3579
|
+
const mid = lo + hi >>> 1;
|
|
3580
|
+
if (bands[mid].top > top + 3) lo = mid + 1;
|
|
3581
|
+
else hi = mid;
|
|
3582
|
+
}
|
|
3583
|
+
for (; lo < bands.length && bands[lo].top >= top - 3; lo++) {
|
|
3584
|
+
if (Math.abs(bands[lo].bottom - bottom) <= 3) return true;
|
|
3585
|
+
}
|
|
3586
|
+
return false;
|
|
3587
|
+
};
|
|
3588
|
+
for (let i = 0; i + 1 < geo.length; i++) {
|
|
3589
|
+
if (joins[i] === "\n" && Math.abs(geo[i + 1].fontSize - geo[i].fontSize) <= 0.15 * geo[i].fontSize && !startsNewItem(geo[i].text, geo[i + 1].text) && hasBand(geo[i].y, geo[i + 1].y)) {
|
|
3590
|
+
joins[i] = wrapJoiner(geo[i].text, geo[i + 1].text, lex);
|
|
3591
|
+
}
|
|
3592
|
+
}
|
|
3593
|
+
for (const i of tocRecordBoundaries(lines.map((line) => line.items))) joins[i] = "\n";
|
|
3256
3594
|
for (let i = 0; i + 1 < geo.length; i++) {
|
|
3257
3595
|
if (/^\d{1,2}$/.test(geo[i].text.trim()) && geo[i].fontSize >= geo[i + 1].fontSize * 1.2) joins[i] = "\n";
|
|
3258
3596
|
}
|
|
@@ -3297,15 +3635,15 @@ function computeMedianFontSizeFromFreq(freq) {
|
|
|
3297
3635
|
function detectHeadings(blocks, medianFontSize) {
|
|
3298
3636
|
for (let bi = 0; bi < blocks.length; bi++) {
|
|
3299
3637
|
const block = blocks[bi];
|
|
3300
|
-
if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access',
|
|
3638
|
+
if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _90 => _90.style, 'optionalAccess', _91 => _91.fontSize])) continue;
|
|
3301
3639
|
const text = block.text.trim();
|
|
3302
3640
|
if (text.length === 0 || text.length > 200) continue;
|
|
3303
3641
|
if (/^\d+$/.test(text) && !isChapterNumber(block, blocks[bi + 1], medianFontSize)) continue;
|
|
3304
3642
|
const ratio = block.style.fontSize / medianFontSize;
|
|
3305
3643
|
let level = 0;
|
|
3306
|
-
if (ratio >=
|
|
3307
|
-
else if (ratio >=
|
|
3308
|
-
else if (ratio >=
|
|
3644
|
+
if (ratio >= _chunkL5JX2GAMcjs.HEADING_RATIO_H1) level = 1;
|
|
3645
|
+
else if (ratio >= _chunkL5JX2GAMcjs.HEADING_RATIO_H2) level = 2;
|
|
3646
|
+
else if (ratio >= _chunkL5JX2GAMcjs.HEADING_RATIO_H3) level = 3;
|
|
3309
3647
|
if (level > 0) {
|
|
3310
3648
|
block.type = "heading";
|
|
3311
3649
|
block.level = level;
|
|
@@ -3314,21 +3652,21 @@ function detectHeadings(blocks, medianFontSize) {
|
|
|
3314
3652
|
}
|
|
3315
3653
|
}
|
|
3316
3654
|
function isChapterNumber(block, next, medianFontSize) {
|
|
3317
|
-
const size = _nullishCoalesce(_optionalChain([block, 'access',
|
|
3318
|
-
const nextSize = _nullishCoalesce(_optionalChain([next, 'optionalAccess',
|
|
3319
|
-
const text = _nullishCoalesce(_optionalChain([next, 'optionalAccess',
|
|
3320
|
-
const a = block.bbox, b = _optionalChain([next, 'optionalAccess',
|
|
3321
|
-
return /^\d{1,2}$/.test(_nullishCoalesce(_optionalChain([block, 'access',
|
|
3655
|
+
const size = _nullishCoalesce(_optionalChain([block, 'access', _92 => _92.style, 'optionalAccess', _93 => _93.fontSize]), () => ( 0));
|
|
3656
|
+
const nextSize = _nullishCoalesce(_optionalChain([next, 'optionalAccess', _94 => _94.style, 'optionalAccess', _95 => _95.fontSize]), () => ( 0));
|
|
3657
|
+
const text = _nullishCoalesce(_optionalChain([next, 'optionalAccess', _96 => _96.text, 'optionalAccess', _97 => _97.trim, 'call', _98 => _98()]), () => ( ""));
|
|
3658
|
+
const a = block.bbox, b = _optionalChain([next, 'optionalAccess', _99 => _99.bbox]);
|
|
3659
|
+
return /^\d{1,2}$/.test(_nullishCoalesce(_optionalChain([block, 'access', _100 => _100.text, 'optionalAccess', _101 => _101.trim, 'call', _102 => _102()]), () => ( ""))) && size >= medianFontSize * 2.5 && !!next && (next.type === "paragraph" || next.type === "heading") && next.pageNumber === block.pageNumber && nextSize >= medianFontSize * _chunkL5JX2GAMcjs.HEADING_RATIO_H1 && text.length > 0 && text.length <= 80 && !/^[\d\s.]+$/.test(text) && !!a && !!b && a.y > b.y && a.y - (b.y + b.height) <= size * 2;
|
|
3322
3660
|
}
|
|
3323
3661
|
function mergeStackedHeadingLines(blocks, medianFontSize) {
|
|
3324
3662
|
for (let i = 0; i < blocks.length - 1; ) {
|
|
3325
3663
|
const a = blocks[i], b = blocks[i + 1];
|
|
3326
3664
|
const ab = a.bbox, bb = b.bbox;
|
|
3327
|
-
const af = _nullishCoalesce(_optionalChain([a, 'access',
|
|
3665
|
+
const af = _nullishCoalesce(_optionalChain([a, 'access', _103 => _103.style, 'optionalAccess', _104 => _104.fontSize]), () => ( 0)), bf = _nullishCoalesce(_optionalChain([b, 'access', _105 => _105.style, 'optionalAccess', _106 => _106.fontSize]), () => ( 0));
|
|
3328
3666
|
const gap = ab && bb ? ab.y - (bb.y + bb.height) : Infinity;
|
|
3329
|
-
const centered = ab && bb && _optionalChain([a, 'access',
|
|
3667
|
+
const centered = ab && bb && _optionalChain([a, 'access', _107 => _107.style, 'optionalAccess', _108 => _108.fontName]) === _optionalChain([b, 'access', _109 => _109.style, 'optionalAccess', _110 => _110.fontName]) && Math.abs(ab.x + ab.width / 2 - (bb.x + bb.width / 2)) <= Math.max(5, af * 0.5);
|
|
3330
3668
|
const sameAnchor = ab && bb && Math.abs(ab.x - bb.x) <= 5;
|
|
3331
|
-
const wrapped = sameAnchor && _optionalChain([a, 'access',
|
|
3669
|
+
const wrapped = sameAnchor && _optionalChain([a, 'access', _111 => _111.style, 'optionalAccess', _112 => _112.fontName]) === _optionalChain([b, 'access', _113 => _113.style, 'optionalAccess', _114 => _114.fontName]) && af === bf && ab.width >= bb.width * 0.95 && (_nullishCoalesce(_optionalChain([a, 'access', _115 => _115.text, 'optionalAccess', _116 => _116.trim, 'call', _117 => _117(), 'access', _118 => _118.split, 'call', _119 => _119(/\s+/), 'access', _120 => _120.length]), () => ( 0))) >= 3;
|
|
3332
3670
|
const displayStack = centered && gap <= Math.min(af, bf) * 0.3 && Math.max(af, bf) <= Math.min(af, bf) * 1.45;
|
|
3333
3671
|
if (a.type !== "heading" || b.type !== "heading" || !a.text || !b.text || /^\d+$/.test(a.text.trim()) || !ab || !bb || ab.page !== bb.page || !(sameAnchor && af >= medianFontSize * 2 && bf >= medianFontSize * 2) && !wrapped && !(centered && af >= medianFontSize * 1.25 && bf >= medianFontSize * 1.25) || Math.abs(af - bf) > Math.max(af, bf) * 0.15 && !displayStack || gap < -2 || gap > Math.max(af, bf) * 0.45 || a.text.length > (centered ? 120 : 50) || b.text.length > (centered ? 120 : 50)) {
|
|
3334
3672
|
i++;
|
|
@@ -3357,25 +3695,25 @@ function detectTypographyHeadings(blocks) {
|
|
|
3357
3695
|
if (page.some((block) => block.type === "heading")) continue;
|
|
3358
3696
|
const faceWeight = /* @__PURE__ */ new Map();
|
|
3359
3697
|
for (const block of page) {
|
|
3360
|
-
if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access',
|
|
3698
|
+
if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _121 => _121.style, 'optionalAccess', _122 => _122.fontName])) continue;
|
|
3361
3699
|
const faces = FACE_CHARS.get(block);
|
|
3362
3700
|
if (faces) for (const [face, n] of faces) faceWeight.set(face, (_nullishCoalesce(faceWeight.get(face), () => ( 0))) + n);
|
|
3363
3701
|
else faceWeight.set(block.style.fontName, (_nullishCoalesce(faceWeight.get(block.style.fontName), () => ( 0))) + block.text.length);
|
|
3364
3702
|
}
|
|
3365
|
-
const bodyFace = _optionalChain([[...faceWeight], 'access',
|
|
3703
|
+
const bodyFace = _optionalChain([[...faceWeight], 'access', _123 => _123.sort, 'call', _124 => _124((a, b) => b[1] - a[1]), 'access', _125 => _125[0], 'optionalAccess', _126 => _126[0]]);
|
|
3366
3704
|
if (!bodyFace || (_nullishCoalesce(faceWeight.get(bodyFace), () => ( 0))) < 250) continue;
|
|
3367
3705
|
const sizeWeight = /* @__PURE__ */ new Map();
|
|
3368
3706
|
for (const block of page) {
|
|
3369
|
-
if (block.type !== "paragraph" || !_optionalChain([block, 'access',
|
|
3707
|
+
if (block.type !== "paragraph" || !_optionalChain([block, 'access', _127 => _127.style, 'optionalAccess', _128 => _128.fontSize])) continue;
|
|
3370
3708
|
const faces = FACE_CHARS.get(block);
|
|
3371
|
-
const chars = faces ? _nullishCoalesce(faces.get(bodyFace), () => ( 0)) : block.style.fontName === bodyFace ? _nullishCoalesce(_optionalChain([block, 'access',
|
|
3709
|
+
const chars = faces ? _nullishCoalesce(faces.get(bodyFace), () => ( 0)) : block.style.fontName === bodyFace ? _nullishCoalesce(_optionalChain([block, 'access', _129 => _129.text, 'optionalAccess', _130 => _130.length]), () => ( 0)) : 0;
|
|
3372
3710
|
if (chars) sizeWeight.set(block.style.fontSize, (_nullishCoalesce(sizeWeight.get(block.style.fontSize), () => ( 0))) + chars);
|
|
3373
3711
|
}
|
|
3374
|
-
const bodySize = _nullishCoalesce(_optionalChain([[...sizeWeight], 'access',
|
|
3712
|
+
const bodySize = _nullishCoalesce(_optionalChain([[...sizeWeight], 'access', _131 => _131.sort, 'call', _132 => _132((a, b) => b[1] - a[1]), 'access', _133 => _133[0], 'optionalAccess', _134 => _134[0]]), () => ( 0));
|
|
3375
3713
|
for (let i = 0; i < page.length; i++) {
|
|
3376
3714
|
const block = page[i];
|
|
3377
3715
|
const { text, bbox, style } = block;
|
|
3378
|
-
if (block.type !== "paragraph" || !text || !bbox || !_optionalChain([style, 'optionalAccess',
|
|
3716
|
+
if (block.type !== "paragraph" || !text || !bbox || !_optionalChain([style, 'optionalAccess', _135 => _135.fontName]) || !style.fontSize) continue;
|
|
3379
3717
|
const title = text.trim();
|
|
3380
3718
|
const numbered = /^\d+(?:\.\d+)*\.?\s+[A-Z가-힣]/.test(title);
|
|
3381
3719
|
const faces = FACE_CHARS.get(block);
|
|
@@ -3405,16 +3743,16 @@ function detectDocumentStyleHeadings(blocks) {
|
|
|
3405
3743
|
for (const page of byPage.values()) {
|
|
3406
3744
|
const faceChars = /* @__PURE__ */ new Map();
|
|
3407
3745
|
for (const block of page) {
|
|
3408
|
-
if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access',
|
|
3746
|
+
if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _136 => _136.style, 'optionalAccess', _137 => _137.fontName])) continue;
|
|
3409
3747
|
faceChars.set(block.style.fontName, (_nullishCoalesce(faceChars.get(block.style.fontName), () => ( 0))) + block.text.length);
|
|
3410
3748
|
}
|
|
3411
|
-
const bodyFace = _optionalChain([[...faceChars], 'access',
|
|
3749
|
+
const bodyFace = _optionalChain([[...faceChars], 'access', _138 => _138.sort, 'call', _139 => _139((a, b) => b[1] - a[1]), 'access', _140 => _140[0], 'optionalAccess', _141 => _141[0]]);
|
|
3412
3750
|
if (!bodyFace || (_nullishCoalesce(faceChars.get(bodyFace), () => ( 0))) < 100) continue;
|
|
3413
|
-
const labels = page.filter((b) => b.type === "paragraph" && b.text && b.bbox && _optionalChain([b, 'access',
|
|
3751
|
+
const labels = page.filter((b) => b.type === "paragraph" && b.text && b.bbox && _optionalChain([b, 'access', _142 => _142.style, 'optionalAccess', _143 => _143.fontName]) && b.style.fontName !== bodyFace && b.text.trim().length >= 3 && b.text.trim().length <= 40);
|
|
3414
3752
|
for (const label of labels) {
|
|
3415
|
-
const peers = labels.filter((b) => _optionalChain([b, 'access',
|
|
3753
|
+
const peers = labels.filter((b) => _optionalChain([b, 'access', _144 => _144.style, 'optionalAccess', _145 => _145.fontName]) === _optionalChain([label, 'access', _146 => _146.style, 'optionalAccess', _147 => _147.fontName]) && Math.abs(b.bbox.y - label.bbox.y) <= 3 && Math.abs(b.bbox.x - label.bbox.x) >= 60);
|
|
3416
3754
|
if (peers.length < 2) continue;
|
|
3417
|
-
const value = page.find((b) => b.type === "paragraph" && b.bbox && _optionalChain([b, 'access',
|
|
3755
|
+
const value = page.find((b) => b.type === "paragraph" && b.bbox && _optionalChain([b, 'access', _148 => _148.style, 'optionalAccess', _149 => _149.fontName]) !== _optionalChain([label, 'access', _150 => _150.style, 'optionalAccess', _151 => _151.fontName]) && b.bbox.x >= label.bbox.x - 5 && b.bbox.x <= label.bbox.x + 20 && b.bbox.y < label.bbox.y && label.bbox.y - (b.bbox.y + b.bbox.height) <= 60);
|
|
3418
3756
|
if (value) {
|
|
3419
3757
|
label.type = "heading";
|
|
3420
3758
|
label.level = 2;
|
|
@@ -3423,7 +3761,7 @@ function detectDocumentStyleHeadings(blocks) {
|
|
|
3423
3761
|
const first = page.find((b) => b.type !== "image" && b.type !== "separator");
|
|
3424
3762
|
const second = page[page.indexOf(first) + 1];
|
|
3425
3763
|
const third = page[page.indexOf(first) + 2];
|
|
3426
|
-
if (!first || !second || !third || first.type !== "list" && first.type !== "paragraph" || second.type !== "paragraph" || !first.text || !second.text || !first.bbox || !second.bbox || !_optionalChain([first, 'access',
|
|
3764
|
+
if (!first || !second || !third || first.type !== "list" && first.type !== "paragraph" || second.type !== "paragraph" || !first.text || !second.text || !first.bbox || !second.bbox || !_optionalChain([first, 'access', _152 => _152.style, 'optionalAccess', _153 => _153.fontName]) || !_optionalChain([second, 'access', _154 => _154.style, 'optionalAccess', _155 => _155.fontName]) || !/^\d+(?:\.\d+)*\.\s+/.test(first.text.trim()) || first.style.fontName === bodyFace || second.style.fontName === bodyFace || first.text.length + second.text.length > 140 || Math.abs(first.bbox.x - second.bbox.x) > 30 || first.bbox.y - (second.bbox.y + second.bbox.height) > (_nullishCoalesce(first.style.fontSize, () => ( 0))) * 1.5 || _optionalChain([third, 'access', _156 => _156.style, 'optionalAccess', _157 => _157.fontName]) !== bodyFace) continue;
|
|
3427
3765
|
first.type = "heading";
|
|
3428
3766
|
first.level = 1;
|
|
3429
3767
|
first.text = `${first.text.trim()} ${second.text.trim()}`;
|
|
@@ -3447,18 +3785,18 @@ function detectSiblingStyleHeadings(blocks) {
|
|
|
3447
3785
|
for (const page of byPage.values()) {
|
|
3448
3786
|
const bodyChars = /* @__PURE__ */ new Map();
|
|
3449
3787
|
for (const block of page) {
|
|
3450
|
-
if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access',
|
|
3788
|
+
if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _158 => _158.style, 'optionalAccess', _159 => _159.fontName])) continue;
|
|
3451
3789
|
const face = block.style.fontName;
|
|
3452
3790
|
bodyChars.set(face, (_nullishCoalesce(bodyChars.get(face), () => ( 0))) + block.text.length);
|
|
3453
3791
|
}
|
|
3454
|
-
const bodyFace = _optionalChain([[...bodyChars], 'access',
|
|
3455
|
-
const anchors = page.filter((b) => b.type === "heading" && b.text && _optionalChain([b, 'access',
|
|
3792
|
+
const bodyFace = _optionalChain([[...bodyChars], 'access', _160 => _160.sort, 'call', _161 => _161((a, b) => b[1] - a[1]), 'access', _162 => _162[0], 'optionalAccess', _163 => _163[0]]);
|
|
3793
|
+
const anchors = page.filter((b) => b.type === "heading" && b.text && _optionalChain([b, 'access', _164 => _164.style, 'optionalAccess', _165 => _165.fontName]) && b.style.fontName !== bodyFace);
|
|
3456
3794
|
for (const anchor of anchors) {
|
|
3457
3795
|
const numbered = /^([A-Z])\.\d+\s+/.exec(anchor.text.trim());
|
|
3458
3796
|
const lettered = /^([A-Z])\s+/.exec(anchor.text.trim());
|
|
3459
|
-
const peers = anchors.filter((b) => _optionalChain([b, 'access',
|
|
3797
|
+
const peers = anchors.filter((b) => _optionalChain([b, 'access', _166 => _166.style, 'optionalAccess', _167 => _167.fontName]) === _optionalChain([anchor, 'access', _168 => _168.style, 'optionalAccess', _169 => _169.fontName]) && Math.abs((_nullishCoalesce(_optionalChain([b, 'access', _170 => _170.style, 'optionalAccess', _171 => _171.fontSize]), () => ( 0))) - (_nullishCoalesce(_optionalChain([anchor, 'access', _172 => _172.style, 'optionalAccess', _173 => _173.fontSize]), () => ( 0)))) < 0.5);
|
|
3460
3798
|
if (peers.length < 2 && !numbered && !lettered) continue;
|
|
3461
|
-
const candidates = page.filter((b) => b.type === "paragraph" && b.text && b.bbox && _optionalChain([b, 'access',
|
|
3799
|
+
const candidates = page.filter((b) => b.type === "paragraph" && b.text && b.bbox && _optionalChain([b, 'access', _174 => _174.style, 'optionalAccess', _175 => _175.fontName]) === _optionalChain([anchor, 'access', _176 => _176.style, 'optionalAccess', _177 => _177.fontName]) && Math.abs((_nullishCoalesce(_optionalChain([b, 'access', _178 => _178.style, 'optionalAccess', _179 => _179.fontSize]), () => ( 0))) - (_nullishCoalesce(_optionalChain([anchor, 'access', _180 => _180.style, 'optionalAccess', _181 => _181.fontSize]), () => ( 0)))) < 0.5 && b.text.trim().length >= 3 && b.text.trim().length <= 80 && b.bbox.height <= (_nullishCoalesce(_optionalChain([b, 'access', _182 => _182.style, 'optionalAccess', _183 => _183.fontSize]), () => ( 0))) * 1.6 && /^[A-Z]/.test(b.text.trim()) && !/[.!?:;,]$/.test(b.text.trim()) && !/^(?:Table|Figure|Fig\.?|Appendix)\s+\d/i.test(b.text.trim()));
|
|
3462
3800
|
const siblings = candidates.filter((b) => numbered ? new RegExp(`^${numbered[1]}\\.\\d+\\s+`).test(b.text.trim()) : lettered ? /^[A-Z]\s+/.test(b.text.trim()) && Math.abs(anchor.bbox.x - b.bbox.x) < 8 : peers.some((h) => h.bbox && Math.abs(h.bbox.x - b.bbox.x) < 8));
|
|
3463
3801
|
if (siblings.length < (numbered || lettered ? 1 : 2)) continue;
|
|
3464
3802
|
for (const sibling of siblings) {
|
|
@@ -3477,13 +3815,13 @@ function detectRepeatedPageLabels(blocks) {
|
|
|
3477
3815
|
}
|
|
3478
3816
|
for (const page of byPage.values()) {
|
|
3479
3817
|
const bodyChars = /* @__PURE__ */ new Map();
|
|
3480
|
-
for (const b of page) if (b.type === "paragraph" && b.text && _optionalChain([b, 'access',
|
|
3818
|
+
for (const b of page) if (b.type === "paragraph" && b.text && _optionalChain([b, 'access', _184 => _184.style, 'optionalAccess', _185 => _185.fontName])) {
|
|
3481
3819
|
const faces = FACE_CHARS.get(b);
|
|
3482
3820
|
if (faces) for (const [face, n] of faces) bodyChars.set(face, (_nullishCoalesce(bodyChars.get(face), () => ( 0))) + n);
|
|
3483
3821
|
else bodyChars.set(b.style.fontName, (_nullishCoalesce(bodyChars.get(b.style.fontName), () => ( 0))) + b.text.length);
|
|
3484
3822
|
}
|
|
3485
|
-
const bodyFace = _optionalChain([[...bodyChars], 'access',
|
|
3486
|
-
const candidates = page.filter((b) => b.type === "paragraph" && b.text && b.bbox && _optionalChain([b, 'access',
|
|
3823
|
+
const bodyFace = _optionalChain([[...bodyChars], 'access', _186 => _186.sort, 'call', _187 => _187((a, b) => b[1] - a[1]), 'access', _188 => _188[0], 'optionalAccess', _189 => _189[0]]);
|
|
3824
|
+
const candidates = page.filter((b) => b.type === "paragraph" && b.text && b.bbox && _optionalChain([b, 'access', _190 => _190.style, 'optionalAccess', _191 => _191.fontName]) && b.style.fontName !== bodyFace && b.bbox.height <= (_nullishCoalesce(b.style.fontSize, () => ( 0))) * 1.6 && b.text.trim().length >= 5 && b.text.trim().length <= 80);
|
|
3487
3825
|
const groups = /* @__PURE__ */ new Map();
|
|
3488
3826
|
for (const b of candidates) {
|
|
3489
3827
|
const key = `${b.style.fontName}:${b.style.fontSize}`;
|
|
@@ -3519,19 +3857,19 @@ function detectPageLeadHeadings(blocks) {
|
|
|
3519
3857
|
for (const page of byPage.values()) {
|
|
3520
3858
|
const content = page.filter((b) => b.type !== "image" && b.type !== "separator" && !(b.type === "paragraph" && !b.style));
|
|
3521
3859
|
const [first, second, third] = content;
|
|
3522
|
-
if (!_optionalChain([first, 'optionalAccess',
|
|
3860
|
+
if (!_optionalChain([first, 'optionalAccess', _192 => _192.bbox]) || !first.text || !_optionalChain([first, 'access', _193 => _193.style, 'optionalAccess', _194 => _194.fontSize]) || !second) continue;
|
|
3523
3861
|
const firstText = first.text.trim();
|
|
3524
3862
|
const captionLike = /^(?:Figure|Fig\.?|Table|표|그림)\s*\d/i;
|
|
3525
3863
|
const hasImage = page.some((b) => b.type === "image");
|
|
3526
|
-
const firstIsTitle = first.type === "paragraph" && firstText.length >= 5 && firstText.length <= 80 && first.bbox.height <= first.style.fontSize * 1.6 && (/^(?:CONTENTS|Table of Contents)$/i.test(firstText) || hasImage && /^[A-Z]/.test(firstText) && !captionLike.test(firstText) && second.type === "paragraph" && /^[A-Z]/.test(_nullishCoalesce(_optionalChain([second, 'access',
|
|
3864
|
+
const firstIsTitle = first.type === "paragraph" && firstText.length >= 5 && firstText.length <= 80 && first.bbox.height <= first.style.fontSize * 1.6 && (/^(?:CONTENTS|Table of Contents)$/i.test(firstText) || hasImage && /^[A-Z]/.test(firstText) && !captionLike.test(firstText) && second.type === "paragraph" && /^[A-Z]/.test(_nullishCoalesce(_optionalChain([second, 'access', _195 => _195.text, 'optionalAccess', _196 => _196.trim, 'call', _197 => _197()]), () => ( ""))) && (_nullishCoalesce(_optionalChain([second, 'access', _198 => _198.text, 'optionalAccess', _199 => _199.length]), () => ( 0))) >= 100 && second.bbox && first.bbox.y - (second.bbox.y + second.bbox.height) >= first.style.fontSize);
|
|
3527
3865
|
const firstAboveProse = first.type === "paragraph" && firstText.length >= 5 && firstText.length <= 80 && first.bbox.height <= first.style.fontSize * 2 && second.type === "paragraph" && second.bbox && second.bbox.height >= first.style.fontSize * 4 && Math.abs(first.bbox.x - second.bbox.x) <= first.style.fontSize * 2 && first.bbox.y - (second.bbox.y + second.bbox.height) >= first.style.fontSize * 2 && !captionLike.test(firstText) && !/^(?:doi:|https?:|www\.)/i.test(firstText);
|
|
3528
|
-
const firstIsSection = first.type === "list" && /^\d+\.\s+[A-Z][A-Z\s]{12,}$/.test(firstText) && second.type === "paragraph" && (_nullishCoalesce(_optionalChain([second, 'access',
|
|
3866
|
+
const firstIsSection = first.type === "list" && /^\d+\.\s+[A-Z][A-Z\s]{12,}$/.test(firstText) && second.type === "paragraph" && (_nullishCoalesce(_optionalChain([second, 'access', _200 => _200.text, 'optionalAccess', _201 => _201.length]), () => ( 0))) >= 100;
|
|
3529
3867
|
if (firstIsTitle || firstAboveProse || firstIsSection) {
|
|
3530
3868
|
first.type = "heading";
|
|
3531
3869
|
first.level = 1;
|
|
3532
3870
|
}
|
|
3533
|
-
if (first.type !== "heading" || captionLike.test(firstText) || second.type !== "paragraph" || !second.text || !second.bbox || !_optionalChain([second, 'access',
|
|
3534
|
-
const distinctFace = _optionalChain([third, 'access',
|
|
3871
|
+
if (first.type !== "heading" || captionLike.test(firstText) || second.type !== "paragraph" || !second.text || !second.bbox || !_optionalChain([second, 'access', _202 => _202.style, 'optionalAccess', _203 => _203.fontName]) || !second.style.fontSize || !_optionalChain([third, 'optionalAccess', _204 => _204.text]) || !third.bbox || second.text.trim().length < 5 || second.text.trim().length > 80 || captionLike.test(second.text.trim()) || /^(?:doi:|https?:)/i.test(second.text.trim()) || second.bbox.height > second.style.fontSize * 1.6 || Math.abs(second.bbox.x - third.bbox.x) > 30) continue;
|
|
3872
|
+
const distinctFace = _optionalChain([third, 'access', _205 => _205.style, 'optionalAccess', _206 => _206.fontName]) !== second.style.fontName;
|
|
3535
3873
|
const namedContents = /^Table of Contents$/i.test(second.text.trim());
|
|
3536
3874
|
if (distinctFace && third.text.length >= 60 || namedContents) {
|
|
3537
3875
|
second.type = "heading";
|
|
@@ -3542,24 +3880,24 @@ function detectPageLeadHeadings(blocks) {
|
|
|
3542
3880
|
function refineDocumentStyleHeadings(blocks) {
|
|
3543
3881
|
const faceChars = /* @__PURE__ */ new Map();
|
|
3544
3882
|
for (const block of blocks) {
|
|
3545
|
-
if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access',
|
|
3883
|
+
if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _207 => _207.style, 'optionalAccess', _208 => _208.fontName])) continue;
|
|
3546
3884
|
faceChars.set(block.style.fontName, (_nullishCoalesce(faceChars.get(block.style.fontName), () => ( 0))) + block.text.length);
|
|
3547
3885
|
}
|
|
3548
3886
|
const [bodyFace, bodyChars] = _nullishCoalesce([...faceChars].sort((a, b) => b[1] - a[1])[0], () => ( []));
|
|
3549
3887
|
if (!bodyFace || !bodyChars || bodyChars < 300) return;
|
|
3550
3888
|
for (let i = 0; i < blocks.length; i++) {
|
|
3551
3889
|
const block = blocks[i];
|
|
3552
|
-
const text = _nullishCoalesce(_optionalChain([block, 'access',
|
|
3890
|
+
const text = _nullishCoalesce(_optionalChain([block, 'access', _209 => _209.text, 'optionalAccess', _210 => _210.trim, 'call', _211 => _211()]), () => ( ""));
|
|
3553
3891
|
if (block.type === "heading" && /(?:https?:\/\/|www\.|^arxiv:|^doi:)/i.test(text)) {
|
|
3554
3892
|
block.type = "paragraph";
|
|
3555
3893
|
block.level = void 0;
|
|
3556
3894
|
continue;
|
|
3557
3895
|
}
|
|
3558
3896
|
const box = block.bbox, style = block.style;
|
|
3559
|
-
if (block.type !== "paragraph" || !box || !_optionalChain([style, 'optionalAccess',
|
|
3897
|
+
if (block.type !== "paragraph" || !box || !_optionalChain([style, 'optionalAccess', _212 => _212.fontName]) || !style.fontSize || style.fontName === bodyFace || (_nullishCoalesce(faceChars.get(style.fontName), () => ( 0))) > bodyChars * 0.25 || text.length < 3 || text.length > 70 || text.includes("\n") || box.height > style.fontSize * 1.6 || /^(?:table|figure|fig\.?|source|doi:|arxiv:|https?:|www\.|[•●○▪▫⮚*∗†])/i.test(text) || /(?:https?:\/\/|www\.|@|[=¼≪þ])/i.test(text) || /^definition\s+\d+[.:]?\s+.*\b(?:is|are|means)\b/i.test(text) || /^[\d\s.,:%+\-–]+$/.test(text)) continue;
|
|
3560
3898
|
const previous = blocks[i - 1], next = blocks[i + 1];
|
|
3561
|
-
const pb = _optionalChain([previous, 'optionalAccess',
|
|
3562
|
-
if (!pb || !nb || previous.pageNumber !== block.pageNumber || next.pageNumber !== block.pageNumber || previous.type !== "paragraph" && previous.type !== "heading" || next.type !== "paragraph" || _optionalChain([next, 'access',
|
|
3899
|
+
const pb = _optionalChain([previous, 'optionalAccess', _213 => _213.bbox]), nb = _optionalChain([next, 'optionalAccess', _214 => _214.bbox]);
|
|
3900
|
+
if (!pb || !nb || previous.pageNumber !== block.pageNumber || next.pageNumber !== block.pageNumber || previous.type !== "paragraph" && previous.type !== "heading" || next.type !== "paragraph" || _optionalChain([next, 'access', _215 => _215.style, 'optionalAccess', _216 => _216.fontName]) !== bodyFace || !next.text || next.text.length < 40 || style.fontSize < (_nullishCoalesce(next.style.fontSize, () => ( 0))) * 0.95 || pb.y - (box.y + box.height) < style.fontSize * 0.5 || box.y - (nb.y + nb.height) < 0 || box.y - (nb.y + nb.height) > style.fontSize * 2 || box.x + box.width / 2 < nb.x - 10 || box.x + box.width / 2 > nb.x + nb.width + 10) continue;
|
|
3563
3901
|
block.type = "heading";
|
|
3564
3902
|
block.level = 2;
|
|
3565
3903
|
}
|
|
@@ -3609,7 +3947,7 @@ function detectMarkerHeadings(blocks) {
|
|
|
3609
3947
|
block.level = 4;
|
|
3610
3948
|
continue;
|
|
3611
3949
|
}
|
|
3612
|
-
if (/^[가-힣]{2,6}$/.test(text) && _optionalChain([block, 'access',
|
|
3950
|
+
if (/^[가-힣]{2,6}$/.test(text) && _optionalChain([block, 'access', _217 => _217.style, 'optionalAccess', _218 => _218.fontSize])) {
|
|
3613
3951
|
const prev = blocks[i - 1];
|
|
3614
3952
|
const next = blocks[i + 1];
|
|
3615
3953
|
const prevIsStructural = !prev || prev.type === "table" || prev.type === "heading" || prev.type === "separator";
|
|
@@ -3650,7 +3988,7 @@ function detectTableCaptions(blocks) {
|
|
|
3650
3988
|
block.table.caption = blocks[i - 1].text.trim();
|
|
3651
3989
|
blocks.splice(i - 1, 1);
|
|
3652
3990
|
i--;
|
|
3653
|
-
} else if (isCaptionCandidate(blocks[i + 1], block) && _optionalChain([blocks, 'access',
|
|
3991
|
+
} else if (isCaptionCandidate(blocks[i + 1], block) && _optionalChain([blocks, 'access', _219 => _219[i + 2], 'optionalAccess', _220 => _220.type]) !== "table") {
|
|
3654
3992
|
block.table.caption = blocks[i + 1].text.trim();
|
|
3655
3993
|
blocks.splice(i + 1, 1);
|
|
3656
3994
|
}
|
|
@@ -3864,7 +4202,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables =
|
|
|
3864
4202
|
const bottomEntries = [];
|
|
3865
4203
|
for (let bi = 0; bi < blocks.length; bi++) {
|
|
3866
4204
|
const b = blocks[bi];
|
|
3867
|
-
const text = !tables ? _optionalChain([b, 'access',
|
|
4205
|
+
const text = !tables ? _optionalChain([b, 'access', _221 => _221.text, 'optionalAccess', _222 => _222.trim, 'call', _223 => _223()]) : b.type === "table" && b.table ? b.table.cells.flat().map((c) => c.text.trim()).filter(Boolean).join(" | ") : void 0;
|
|
3868
4206
|
if (!b.bbox || !b.pageNumber || !text) continue;
|
|
3869
4207
|
const ph = pageHeights.get(b.bbox.page) || pageHeights.get(b.pageNumber);
|
|
3870
4208
|
if (!ph) continue;
|
|
@@ -3895,7 +4233,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables =
|
|
|
3895
4233
|
for (const [p, count] of patternCount) {
|
|
3896
4234
|
const pages = [..._nullishCoalesce(patternPages.get(p), () => ( []))];
|
|
3897
4235
|
const span = pages.length ? Math.max(...pages) - Math.min(...pages) + 1 : 0;
|
|
3898
|
-
const pageNumbered = !tables && (_nullishCoalesce(_optionalChain([patternNumbers, 'access',
|
|
4236
|
+
const pageNumbered = !tables && (_nullishCoalesce(_optionalChain([patternNumbers, 'access', _224 => _224.get, 'call', _225 => _225(p), 'optionalAccess', _226 => _226.size]), () => ( 0))) > 1;
|
|
3899
4237
|
if (count >= MIN_REPEAT && pages.length >= MIN_REPEAT && (pages.length >= span * 0.4 || pageNumbered)) {
|
|
3900
4238
|
repeatedPatterns.add(p);
|
|
3901
4239
|
}
|
|
@@ -3903,8 +4241,8 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables =
|
|
|
3903
4241
|
for (const e of entries) {
|
|
3904
4242
|
const norm = e.text.replace(/\d+/g, "#");
|
|
3905
4243
|
if (!repeatedPatterns.has(norm)) continue;
|
|
3906
|
-
const noteMark = _optionalChain([e, 'access',
|
|
3907
|
-
if (noteMark && _optionalChain([notes, 'optionalAccess',
|
|
4244
|
+
const noteMark = _optionalChain([e, 'access', _227 => _227.text, 'access', _228 => _228.match, 'call', _229 => _229(/^\d{1,3}\)/), 'optionalAccess', _230 => _230[0]]);
|
|
4245
|
+
if (noteMark && _optionalChain([notes, 'optionalAccess', _231 => _231.get, 'call', _232 => _232(e.page), 'optionalAccess', _233 => _233.marks, 'access', _234 => _234.some, 'call', _235 => _235((m) => m.mark === noteMark)])) continue;
|
|
3908
4246
|
const cand = blocks[e.blockIdx];
|
|
3909
4247
|
const cb = cand.bbox;
|
|
3910
4248
|
const tableNote = /^(?:주\s*(?:\d+\s*[).:]|[::])|(?:자료|출처)\s*[::])/.test(e.text.replace(/ \| /g, " ")) && blocks.some((o) => {
|
|
@@ -3918,7 +4256,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables =
|
|
|
3918
4256
|
if (bi === e.blockIdx) continue;
|
|
3919
4257
|
const o = blocks[bi];
|
|
3920
4258
|
if (!o.bbox || o.bbox.page !== cb.page) continue;
|
|
3921
|
-
const oNorm = _optionalChain([o, 'access',
|
|
4259
|
+
const oNorm = _optionalChain([o, 'access', _236 => _236.text, 'optionalAccess', _237 => _237.trim, 'call', _238 => _238(), 'access', _239 => _239.replace, 'call', _240 => _240(/\d+/g, "#")]);
|
|
3922
4260
|
if (oNorm && repeatedPatterns.has(oNorm)) continue;
|
|
3923
4261
|
const overlap2 = Math.min(cb.y + cb.height, o.bbox.y + o.bbox.height) - Math.max(cb.y, o.bbox.y);
|
|
3924
4262
|
if (overlap2 >= cb.height * 0.5) {
|
|
@@ -3992,7 +4330,7 @@ function recordRowRules(table, cells, bbox, hs) {
|
|
|
3992
4330
|
function markImageCell(cell) {
|
|
3993
4331
|
IMAGE_CELLS.add(cell);
|
|
3994
4332
|
}
|
|
3995
|
-
var emptyCell = (cell) => !cell || !_optionalChain([cell, 'access',
|
|
4333
|
+
var emptyCell = (cell) => !cell || !_optionalChain([cell, 'access', _241 => _241.text, 'optionalAccess', _242 => _242.trim, 'call', _243 => _243()]) && !_optionalChain([cell, 'access', _244 => _244.blocks, 'optionalAccess', _245 => _245.length]) && !IMAGE_CELLS.has(cell);
|
|
3996
4334
|
function trimTable(table) {
|
|
3997
4335
|
let cols = table.cols;
|
|
3998
4336
|
while (cols > 0 && table.cells.every((row) => emptyCell(row[cols - 1]))) cols--;
|
|
@@ -4008,7 +4346,7 @@ function trimTable(table) {
|
|
|
4008
4346
|
function trimTrailingEmptyTableCols(blocks) {
|
|
4009
4347
|
for (const b of blocks) {
|
|
4010
4348
|
if (b.type !== "table" || !b.table) continue;
|
|
4011
|
-
for (const row of b.table.cells) for (const cell of row) if (_optionalChain([cell, 'access',
|
|
4349
|
+
for (const row of b.table.cells) for (const cell of row) if (_optionalChain([cell, 'access', _246 => _246.blocks, 'optionalAccess', _247 => _247.length])) trimTrailingEmptyTableCols(cell.blocks);
|
|
4012
4350
|
trimTable(b.table);
|
|
4013
4351
|
}
|
|
4014
4352
|
}
|
|
@@ -4028,7 +4366,7 @@ function mergeSliverColumns(grid, colXs, maxWidth) {
|
|
|
4028
4366
|
}
|
|
4029
4367
|
const ok = owner.every((row) => {
|
|
4030
4368
|
const o = row[c];
|
|
4031
|
-
return !!o && (o.colSpan > 1 || !o.text.trim() && !_optionalChain([o, 'access',
|
|
4369
|
+
return !!o && (o.colSpan > 1 || !o.text.trim() && !_optionalChain([o, 'access', _248 => _248.blocks, 'optionalAccess', _249 => _249.length]));
|
|
4032
4370
|
});
|
|
4033
4371
|
if (!ok) continue;
|
|
4034
4372
|
const spanning = /* @__PURE__ */ new Set();
|
|
@@ -4094,7 +4432,7 @@ function isProseTable(table) {
|
|
|
4094
4432
|
if (!(long > 0 && long >= total * 0.5 && longRows >= rows * 0.4)) return false;
|
|
4095
4433
|
for (let c = 0; c < table.cols; c++) {
|
|
4096
4434
|
const filled = table.cells.map((row) => row[c]).filter((cell) => cell && cell.colSpan < table.cols && cell.text.trim()).map((cell) => cell.text.trim());
|
|
4097
|
-
if (filled.length >= 3 && filled.length >= rows * 0.6 && filled.every((text) => text.length <= 30 && (_nullishCoalesce(_optionalChain([text, 'access',
|
|
4435
|
+
if (filled.length >= 3 && filled.length >= rows * 0.6 && filled.every((text) => text.length <= 30 && (_nullishCoalesce(_optionalChain([text, 'access', _250 => _250.match, 'call', _251 => _251(/\p{L}/gu), 'optionalAccess', _252 => _252.length]), () => ( 0))) >= 2)) return false;
|
|
4098
4436
|
}
|
|
4099
4437
|
return true;
|
|
4100
4438
|
}
|
|
@@ -4121,7 +4459,7 @@ function isChartTable(table) {
|
|
|
4121
4459
|
const numeric = texts.filter((text) => NUMERIC_CELL.test(text)).length;
|
|
4122
4460
|
if (numeric < texts.length * 0.5) return false;
|
|
4123
4461
|
for (let c = 0; c < table.cols; c++) {
|
|
4124
|
-
const ticks = table.cells.flatMap((row) => (_nullishCoalesce(_optionalChain([row, 'access',
|
|
4462
|
+
const ticks = table.cells.flatMap((row) => (_nullishCoalesce(_optionalChain([row, 'access', _253 => _253[c], 'optionalAccess', _254 => _254.text]), () => ( ""))).split(/\s+/)).filter((token) => /^-?[\d,]+(?:\.\d+)?%?$/.test(token)).map((token) => Number(token.replace(/[,%]/g, "")));
|
|
4125
4463
|
if (hasValueAxis(ticks)) return true;
|
|
4126
4464
|
}
|
|
4127
4465
|
const values = texts.filter((text) => text.split(/\s+/).every((token) => /^[-−–]?[\d,]*\.?\d+%?$/.test(token))).length;
|
|
@@ -4275,7 +4613,7 @@ function detectAlignedTwoColumnTables(rows, pageNum) {
|
|
|
4275
4613
|
continue;
|
|
4276
4614
|
}
|
|
4277
4615
|
const top = rows[i - 1];
|
|
4278
|
-
const title = _optionalChain([top, 'optionalAccess',
|
|
4616
|
+
const title = _optionalChain([top, 'optionalAccess', _255 => _255.items, 'access', _256 => _256.length]) === 1 && Math.abs(top.items[0].x - first[0].x) <= 5 && top.items[0].text.length <= 65 && top.y - first[0].y <= Math.max(24, first[0].fontSize * 2.8) ? top : void 0;
|
|
4279
4617
|
const tableRows = title ? [title, ...body] : body;
|
|
4280
4618
|
const cells = tableRows.map((row, idx) => {
|
|
4281
4619
|
if (title && idx === 0) return [{ text: row.items[0].text, colSpan: 2, rowSpan: 1 }, { text: "", colSpan: 1, rowSpan: 1 }];
|
|
@@ -4331,12 +4669,12 @@ function isTwoColumnProse(r) {
|
|
|
4331
4669
|
if (t.rows < 8) return false;
|
|
4332
4670
|
const dense = [];
|
|
4333
4671
|
for (let c = 0; c < t.cols; c++) {
|
|
4334
|
-
const filled = t.cells.filter((row) => _optionalChain([row, 'access',
|
|
4672
|
+
const filled = t.cells.filter((row) => _optionalChain([row, 'access', _257 => _257[c], 'optionalAccess', _258 => _258.text, 'access', _259 => _259.trim, 'call', _260 => _260()])).length;
|
|
4335
4673
|
if (filled / t.rows >= 0.3) dense.push(c);
|
|
4336
4674
|
}
|
|
4337
4675
|
if (dense.length !== 2) return false;
|
|
4338
4676
|
for (const c of dense) {
|
|
4339
|
-
const lens = t.cells.map((row) => _nullishCoalesce(_optionalChain([row, 'access',
|
|
4677
|
+
const lens = t.cells.map((row) => _nullishCoalesce(_optionalChain([row, 'access', _261 => _261[c], 'optionalAccess', _262 => _262.text, 'access', _263 => _263.replace, 'call', _264 => _264(/\s+/g, ""), 'access', _265 => _265.length]), () => ( 0))).filter((n) => n > 0);
|
|
4340
4678
|
const avg = lens.reduce((s, v) => s + v, 0) / (lens.length || 1);
|
|
4341
4679
|
if (avg < 12) return false;
|
|
4342
4680
|
}
|
|
@@ -4732,7 +5070,7 @@ function assignRowItems(items, columns, numCols, headerFace) {
|
|
|
4732
5070
|
const runs = [];
|
|
4733
5071
|
for (const it of sorted) {
|
|
4734
5072
|
const last = runs[runs.length - 1];
|
|
4735
|
-
const prev = _optionalChain([last, 'optionalAccess',
|
|
5073
|
+
const prev = _optionalChain([last, 'optionalAccess', _266 => _266[last.length - 1]]);
|
|
4736
5074
|
if (prev && it.x - (prev.x + prev.w) <= Math.max(0.5, it.fontSize * 0.05) && !it.hasSpaceBefore) last.push(it);
|
|
4737
5075
|
else runs.push([it]);
|
|
4738
5076
|
}
|
|
@@ -4806,7 +5144,7 @@ function buildClusterTable(rows, columns, pageNum) {
|
|
|
4806
5144
|
() => Array.from({ length: numCols }, () => ({ text: "", colSpan: 1, rowSpan: 1 }))
|
|
4807
5145
|
);
|
|
4808
5146
|
const usedItems = /* @__PURE__ */ new Set();
|
|
4809
|
-
const headFaces = new Set(_optionalChain([rows, 'access',
|
|
5147
|
+
const headFaces = new Set(_optionalChain([rows, 'access', _267 => _267[0], 'optionalAccess', _268 => _268.items, 'access', _269 => _269.map, 'call', _270 => _270((i) => i.fontName)]));
|
|
4810
5148
|
const headerFace = headFaces.size === 1 && rows.slice(1).every((row) => row.items.every((i) => !headFaces.has(i.fontName))) ? [...headFaces][0] : void 0;
|
|
4811
5149
|
for (let r = 0; r < numRows; r++) {
|
|
4812
5150
|
const row = rows[r];
|
|
@@ -4836,7 +5174,7 @@ function buildClusterTable(rows, columns, pageNum) {
|
|
|
4836
5174
|
const nonEmptyCols = cells[r].filter((c) => c.text.trim()).length;
|
|
4837
5175
|
if (nonEmptyCols !== 1) continue;
|
|
4838
5176
|
if (cells[r][0].text.trim() !== "") continue;
|
|
4839
|
-
const contentText = _optionalChain([cells, 'access',
|
|
5177
|
+
const contentText = _optionalChain([cells, 'access', _271 => _271[r], 'access', _272 => _272.find, 'call', _273 => _273((c) => c.text.trim()), 'optionalAccess', _274 => _274.text, 'access', _275 => _275.trim, 'call', _276 => _276()]) || "";
|
|
4840
5178
|
if (/^[○●▶\-·]/.test(contentText)) continue;
|
|
4841
5179
|
for (let pr = r - 1; pr >= 0; pr--) {
|
|
4842
5180
|
if (cells[pr].some((c) => c.text.trim())) {
|
|
@@ -4936,242 +5274,6 @@ function findRuledColumnDivider(regions, horizontals, verticals, pageWidth, page
|
|
|
4936
5274
|
return candidates.length === 1 ? candidates[0] : null;
|
|
4937
5275
|
}
|
|
4938
5276
|
|
|
4939
|
-
// src/pdf/xy-cut.ts
|
|
4940
|
-
var MAX_XYCUT_DEPTH = 50;
|
|
4941
|
-
var XYCUT_MIN_GAP = 5;
|
|
4942
|
-
var CROSS_LAYOUT_BETA = 2;
|
|
4943
|
-
var CROSS_OVERLAP_RATIO = 0.1;
|
|
4944
|
-
var CROSS_MIN_OVERLAPS = 2;
|
|
4945
|
-
var CROSS_MAX_MASK_RATIO = 0.2;
|
|
4946
|
-
var NARROW_ELEMENT_WIDTH_RATIO = 0.1;
|
|
4947
|
-
var PROSE_GUTTER_MIN_GAP = 6;
|
|
4948
|
-
function xyCutOrder(items, gapThreshold, depth = 0) {
|
|
4949
|
-
if (items.length === 0) return [];
|
|
4950
|
-
if (items.length <= 2 || depth >= MAX_XYCUT_DEPTH) return [items];
|
|
4951
|
-
if (depth === 0 && items.length >= 3) {
|
|
4952
|
-
const cross = identifyCrossLayoutItems(items);
|
|
4953
|
-
if (cross.size > 0 && cross.size <= items.length * CROSS_MAX_MASK_RATIO) {
|
|
4954
|
-
const rest = items.filter((i) => !cross.has(i));
|
|
4955
|
-
if (rest.length > 0) {
|
|
4956
|
-
const groups = xyCutOrder(rest, gapThreshold, 1);
|
|
4957
|
-
return mergeCrossLayoutGroups(groups, [...cross]);
|
|
4958
|
-
}
|
|
4959
|
-
}
|
|
4960
|
-
}
|
|
4961
|
-
const minGap = Math.max(XYCUT_MIN_GAP, gapThreshold);
|
|
4962
|
-
const hCut = findHorizontalCut(items);
|
|
4963
|
-
const vCut = findVerticalCutWithOutlierFilter(items, minGap);
|
|
4964
|
-
const hValid = hCut.gap >= minGap;
|
|
4965
|
-
const vValid = (vCut.gap >= minGap || vCut.gap >= PROSE_GUTTER_MIN_GAP && isProseGutter(items, vCut.position)) && !splitsSpacedLabel(items, vCut.position);
|
|
4966
|
-
let useHorizontal;
|
|
4967
|
-
if (hValid && vValid) useHorizontal = vCut.gap <= hCut.gap * 1.5 || staggeredSides(items, vCut.position);
|
|
4968
|
-
else if (hValid) useHorizontal = true;
|
|
4969
|
-
else if (vValid) useHorizontal = false;
|
|
4970
|
-
else return _nullishCoalesce(splitEdgeSpannedColumns(items, gapThreshold, depth), () => ( [items]));
|
|
4971
|
-
if (useHorizontal) {
|
|
4972
|
-
const upper = items.filter((i) => i.y > hCut.position);
|
|
4973
|
-
const lower = items.filter((i) => i.y <= hCut.position);
|
|
4974
|
-
if (upper.length > 0 && lower.length > 0 && upper.length < items.length) {
|
|
4975
|
-
return [...xyCutOrder(upper, gapThreshold, depth + 1), ...xyCutOrder(lower, gapThreshold, depth + 1)];
|
|
4976
|
-
}
|
|
4977
|
-
} else {
|
|
4978
|
-
const left = items.filter((i) => i.x + i.w / 2 < vCut.position);
|
|
4979
|
-
const right = items.filter((i) => i.x + i.w / 2 >= vCut.position);
|
|
4980
|
-
if (left.length > 0 && right.length > 0 && left.length < items.length) {
|
|
4981
|
-
return [...xyCutOrder(left, gapThreshold, depth + 1), ...xyCutOrder(right, gapThreshold, depth + 1)];
|
|
4982
|
-
}
|
|
4983
|
-
}
|
|
4984
|
-
return [items];
|
|
4985
|
-
}
|
|
4986
|
-
function splitsSpacedLabel(items, cutX) {
|
|
4987
|
-
const lone = (i) => /^[가-힣]$/.test(i.text.trim());
|
|
4988
|
-
const sameRow = (a, b) => Math.min(a.y, b.y) > Math.max(a.y - a.h, b.y - b.h);
|
|
4989
|
-
const left = items.filter((i) => i.x + i.w / 2 < cutX);
|
|
4990
|
-
const right = items.filter((i) => i.x + i.w / 2 >= cutX);
|
|
4991
|
-
let spaced = 0;
|
|
4992
|
-
for (const r of right) {
|
|
4993
|
-
if (right.some((o) => o !== r && o.x < r.x && sameRow(o, r))) continue;
|
|
4994
|
-
const row = left.filter((l2) => sameRow(l2, r));
|
|
4995
|
-
if (row.length === 0) continue;
|
|
4996
|
-
const l = row.reduce((a, b) => b.x + b.w > a.x + a.w ? b : a);
|
|
4997
|
-
if (!lone(l) || !lone(r)) return false;
|
|
4998
|
-
spaced++;
|
|
4999
|
-
}
|
|
5000
|
-
return spaced > 0;
|
|
5001
|
-
}
|
|
5002
|
-
function staggeredSides(items, cutX) {
|
|
5003
|
-
const left = items.filter((i) => i.x + i.w / 2 < cutX);
|
|
5004
|
-
const right = items.filter((i) => i.x + i.w / 2 >= cutX);
|
|
5005
|
-
if (left.length * right.length > 2e5) return false;
|
|
5006
|
-
const shareRow = (a, b) => Math.min(a.y, b.y) > Math.max(a.y - a.h, b.y - b.h);
|
|
5007
|
-
if (left.some((a) => right.some((b) => shareRow(a, b)))) return false;
|
|
5008
|
-
const sides = [...items].sort((a, b) => b.y - a.y).map((i) => i.x + i.w / 2 < cutX);
|
|
5009
|
-
let switches = 0;
|
|
5010
|
-
for (let k = 1; k < sides.length; k++) if (sides[k] !== sides[k - 1]) switches++;
|
|
5011
|
-
return switches >= 3;
|
|
5012
|
-
}
|
|
5013
|
-
function identifyCrossLayoutItems(items) {
|
|
5014
|
-
const cross = /* @__PURE__ */ new Set();
|
|
5015
|
-
if (items.length < 3) return cross;
|
|
5016
|
-
let maxWidth = 0;
|
|
5017
|
-
for (const i of items) {
|
|
5018
|
-
if (i.w > maxWidth) maxWidth = i.w;
|
|
5019
|
-
}
|
|
5020
|
-
const threshold = CROSS_LAYOUT_BETA * maxWidth;
|
|
5021
|
-
for (const item of items) {
|
|
5022
|
-
if (item.w < threshold) continue;
|
|
5023
|
-
let overlaps = 0;
|
|
5024
|
-
for (const other of items) {
|
|
5025
|
-
if (other === item) continue;
|
|
5026
|
-
const left = Math.max(item.x, other.x);
|
|
5027
|
-
const right = Math.min(item.x + item.w, other.x + other.w);
|
|
5028
|
-
const overlapW = right - left;
|
|
5029
|
-
if (overlapW <= 0) continue;
|
|
5030
|
-
const smaller = Math.min(item.w, other.w);
|
|
5031
|
-
if (smaller > 0 && overlapW / smaller >= CROSS_OVERLAP_RATIO) {
|
|
5032
|
-
overlaps++;
|
|
5033
|
-
if (overlaps >= CROSS_MIN_OVERLAPS) break;
|
|
5034
|
-
}
|
|
5035
|
-
}
|
|
5036
|
-
if (overlaps >= CROSS_MIN_OVERLAPS) cross.add(item);
|
|
5037
|
-
}
|
|
5038
|
-
return cross;
|
|
5039
|
-
}
|
|
5040
|
-
function mergeCrossLayoutGroups(groups, cross) {
|
|
5041
|
-
if (cross.length === 0) return groups;
|
|
5042
|
-
const sortedCross = [...cross].sort((a, b) => b.y + b.h - (a.y + a.h) || a.x - b.x);
|
|
5043
|
-
const groupTop = (g) => {
|
|
5044
|
-
let top = -Infinity;
|
|
5045
|
-
for (const i of g) {
|
|
5046
|
-
const t = i.y + i.h;
|
|
5047
|
-
if (t > top) top = t;
|
|
5048
|
-
}
|
|
5049
|
-
return top;
|
|
5050
|
-
};
|
|
5051
|
-
const result = [];
|
|
5052
|
-
let gi = 0, ci = 0;
|
|
5053
|
-
while (gi < groups.length || ci < sortedCross.length) {
|
|
5054
|
-
if (ci >= sortedCross.length) {
|
|
5055
|
-
result.push(groups[gi++]);
|
|
5056
|
-
continue;
|
|
5057
|
-
}
|
|
5058
|
-
if (gi >= groups.length) {
|
|
5059
|
-
result.push([sortedCross[ci++]]);
|
|
5060
|
-
continue;
|
|
5061
|
-
}
|
|
5062
|
-
const crossTop = sortedCross[ci].y + sortedCross[ci].h;
|
|
5063
|
-
if (crossTop >= groupTop(groups[gi])) result.push([sortedCross[ci++]]);
|
|
5064
|
-
else result.push(groups[gi++]);
|
|
5065
|
-
}
|
|
5066
|
-
return result;
|
|
5067
|
-
}
|
|
5068
|
-
function findHorizontalCut(items) {
|
|
5069
|
-
if (items.length < 2) return { position: 0, gap: 0 };
|
|
5070
|
-
const sorted = [...items].sort((a, b) => b.y - a.y);
|
|
5071
|
-
let largestGap = 0;
|
|
5072
|
-
let position = 0;
|
|
5073
|
-
for (let i = 1; i < sorted.length; i++) {
|
|
5074
|
-
const prevBottom = sorted[i - 1].y - sorted[i - 1].h;
|
|
5075
|
-
const currTop = sorted[i].y;
|
|
5076
|
-
const gap = prevBottom - currTop;
|
|
5077
|
-
if (gap > largestGap) {
|
|
5078
|
-
largestGap = gap;
|
|
5079
|
-
position = (prevBottom + currTop) / 2;
|
|
5080
|
-
}
|
|
5081
|
-
}
|
|
5082
|
-
return { position, gap: largestGap };
|
|
5083
|
-
}
|
|
5084
|
-
function findVerticalCutWithOutlierFilter(items, minGap) {
|
|
5085
|
-
const edgeCut = findVerticalCut(items);
|
|
5086
|
-
if (edgeCut.gap >= minGap) return edgeCut;
|
|
5087
|
-
if (items.length >= 3) {
|
|
5088
|
-
let minX = Infinity, maxX = -Infinity;
|
|
5089
|
-
for (const i of items) {
|
|
5090
|
-
if (i.x < minX) minX = i.x;
|
|
5091
|
-
const r = i.x + i.w;
|
|
5092
|
-
if (r > maxX) maxX = r;
|
|
5093
|
-
}
|
|
5094
|
-
const narrowThreshold = (maxX - minX) * NARROW_ELEMENT_WIDTH_RATIO;
|
|
5095
|
-
const filtered = items.filter((i) => i.w >= narrowThreshold);
|
|
5096
|
-
if (filtered.length >= 2 && filtered.length < items.length && filtered.length >= items.length * 0.7) {
|
|
5097
|
-
const filteredCut = findVerticalCut(filtered);
|
|
5098
|
-
if (filteredCut.gap > edgeCut.gap && filteredCut.gap >= minGap) {
|
|
5099
|
-
return filteredCut;
|
|
5100
|
-
}
|
|
5101
|
-
}
|
|
5102
|
-
}
|
|
5103
|
-
return edgeCut;
|
|
5104
|
-
}
|
|
5105
|
-
function findVerticalCut(items) {
|
|
5106
|
-
if (items.length < 2) return { position: 0, gap: 0 };
|
|
5107
|
-
const sorted = [...items].sort((a, b) => a.x - b.x || a.x + a.w - (b.x + b.w));
|
|
5108
|
-
let largestGap = 0;
|
|
5109
|
-
let position = 0;
|
|
5110
|
-
let prevRight = null;
|
|
5111
|
-
for (const it of sorted) {
|
|
5112
|
-
const left = it.x;
|
|
5113
|
-
const right = it.x + it.w;
|
|
5114
|
-
if (prevRight !== null && left > prevRight) {
|
|
5115
|
-
const gap = left - prevRight;
|
|
5116
|
-
if (gap > largestGap) {
|
|
5117
|
-
largestGap = gap;
|
|
5118
|
-
position = (prevRight + left) / 2;
|
|
5119
|
-
}
|
|
5120
|
-
}
|
|
5121
|
-
prevRight = prevRight === null ? right : Math.max(prevRight, right);
|
|
5122
|
-
}
|
|
5123
|
-
return { position, gap: largestGap };
|
|
5124
|
-
}
|
|
5125
|
-
function isProseGutter(items, x) {
|
|
5126
|
-
const sideLines = (side) => {
|
|
5127
|
-
const lines = [];
|
|
5128
|
-
for (const item of [...side].sort((a, b) => b.y - a.y)) {
|
|
5129
|
-
const line = lines.find((l) => Math.abs(l.y - item.y) <= 2);
|
|
5130
|
-
if (line) {
|
|
5131
|
-
line.chars += item.text.length;
|
|
5132
|
-
line.left = Math.min(line.left, item.x);
|
|
5133
|
-
line.right = Math.max(line.right, item.x + item.w);
|
|
5134
|
-
} else lines.push({ y: item.y, chars: item.text.length, left: item.x, right: item.x + item.w });
|
|
5135
|
-
}
|
|
5136
|
-
return lines;
|
|
5137
|
-
};
|
|
5138
|
-
const left = sideLines(items.filter((i) => i.x + i.w / 2 < x));
|
|
5139
|
-
const right = sideLines(items.filter((i) => i.x + i.w / 2 >= x));
|
|
5140
|
-
if (left.length < 4 || right.length < 4) return false;
|
|
5141
|
-
const prose = (lines) => {
|
|
5142
|
-
const width = Math.max(...lines.map((l) => l.right)) - Math.min(...lines.map((l) => l.left));
|
|
5143
|
-
const full = lines.filter((l) => l.chars >= 25 && l.right - l.left >= width * 0.6).length;
|
|
5144
|
-
return full >= lines.length * 0.6;
|
|
5145
|
-
};
|
|
5146
|
-
if (!prose(left) || !prose(right)) return false;
|
|
5147
|
-
const span = (lines) => [Math.min(...lines.map((l) => l.y)), Math.max(...lines.map((l) => l.y))];
|
|
5148
|
-
const [l0, l1] = span(left), [r0, r1] = span(right);
|
|
5149
|
-
return Math.min(l1, r1) - Math.max(l0, r0) >= Math.min(l1 - l0, r1 - r0) * 0.5;
|
|
5150
|
-
}
|
|
5151
|
-
function splitEdgeSpannedColumns(items, gapThreshold, depth) {
|
|
5152
|
-
let minX = Infinity, maxX = -Infinity;
|
|
5153
|
-
for (const i of items) {
|
|
5154
|
-
minX = Math.min(minX, i.x);
|
|
5155
|
-
maxX = Math.max(maxX, i.x + i.w);
|
|
5156
|
-
}
|
|
5157
|
-
const narrow = items.filter((i) => i.w < (maxX - minX) * 0.5);
|
|
5158
|
-
if (narrow.length === items.length || narrow.length < 8) return null;
|
|
5159
|
-
const cut = findVerticalCut(narrow);
|
|
5160
|
-
if (cut.gap < PROSE_GUTTER_MIN_GAP || !isProseGutter(narrow, cut.position)) return null;
|
|
5161
|
-
const crossing = items.filter((i) => i.x < cut.position && i.x + i.w > cut.position);
|
|
5162
|
-
const rest = items.filter((i) => !crossing.includes(i));
|
|
5163
|
-
const restTop = Math.max(...rest.map((i) => i.y)), restBottom = Math.min(...rest.map((i) => i.y));
|
|
5164
|
-
const above = crossing.filter((i) => i.y > restTop), below = crossing.filter((i) => i.y < restBottom);
|
|
5165
|
-
if (above.length + below.length !== crossing.length) return null;
|
|
5166
|
-
const left = rest.filter((i) => i.x + i.w / 2 < cut.position), right = rest.filter((i) => i.x + i.w / 2 >= cut.position);
|
|
5167
|
-
return [
|
|
5168
|
-
...above.length ? [above] : [],
|
|
5169
|
-
...xyCutOrder(left, gapThreshold, depth + 1),
|
|
5170
|
-
...xyCutOrder(right, gapThreshold, depth + 1),
|
|
5171
|
-
...below.length ? [below] : []
|
|
5172
|
-
];
|
|
5173
|
-
}
|
|
5174
|
-
|
|
5175
5277
|
// src/pdf/two-column.ts
|
|
5176
5278
|
var GUTTER_SCAN_LO = 0.3;
|
|
5177
5279
|
var GUTTER_SCAN_HI = 0.7;
|
|
@@ -5463,16 +5565,16 @@ function isProseSpread(items) {
|
|
|
5463
5565
|
for (let i = 1; i < sorted.length; i++) {
|
|
5464
5566
|
gaps.push(sorted[i].x - (sorted[i - 1].x + sorted[i - 1].w));
|
|
5465
5567
|
}
|
|
5466
|
-
const maxGap =
|
|
5568
|
+
const maxGap = _chunkFVESLY6Vcjs.safeMax.call(void 0, gaps);
|
|
5467
5569
|
const avgLen = items.reduce((s, i) => s + i.text.length, 0) / items.length;
|
|
5468
5570
|
if (items.length >= 4 && maxGap < 40 && avgLen < 5) return true;
|
|
5469
|
-
const minGap =
|
|
5571
|
+
const minGap = _chunkFVESLY6Vcjs.safeMin.call(void 0, gaps);
|
|
5470
5572
|
return minGap > 0 && maxGap - minGap <= Math.max(2, maxGap * 0.15) && items.filter((i) => /^\P{L}*\p{Ll}/u.test(i.text)).length * 2 >= items.length;
|
|
5471
5573
|
}
|
|
5472
5574
|
function detectColumns(yLines) {
|
|
5473
5575
|
const allItems = yLines.flat();
|
|
5474
5576
|
if (allItems.length === 0) return null;
|
|
5475
|
-
const pageWidth =
|
|
5577
|
+
const pageWidth = _chunkFVESLY6Vcjs.safeMax.call(void 0, allItems.map((i) => i.x + i.w)) - _chunkFVESLY6Vcjs.safeMin.call(void 0, allItems.map((i) => i.x));
|
|
5476
5578
|
if (pageWidth < 100) return null;
|
|
5477
5579
|
let bigoLineIdx = -1;
|
|
5478
5580
|
for (let i = 0; i < yLines.length; i++) {
|
|
@@ -5771,7 +5873,7 @@ function hasBoxTopPair(line, maxH, horizontals, cellItems) {
|
|
|
5771
5873
|
if (ow <= 0) continue;
|
|
5772
5874
|
const overlap2 = Math.min(line.x2, o.x2) - Math.max(line.x1, o.x1);
|
|
5773
5875
|
if (overlap2 / Math.max(w, ow) < UNDER_BOX_PAIR_OVERLAP) continue;
|
|
5774
|
-
const covered = _nullishCoalesce(_optionalChain([cellItems, 'optionalAccess',
|
|
5876
|
+
const covered = _nullishCoalesce(_optionalChain([cellItems, 'optionalAccess', _277 => _277.reduce, 'call', _278 => _278((sum, item) => {
|
|
5775
5877
|
const below = item.y - o.y1;
|
|
5776
5878
|
if (below < 0.5 || below > 3 || !item.text.trim()) return sum;
|
|
5777
5879
|
return sum + Math.max(0, Math.min(o.x2, item.x + item.w) - Math.max(o.x1, item.x));
|
|
@@ -5901,8 +6003,8 @@ function edgesOf(box, h, v, hNear = EDGE_NEAR2) {
|
|
|
5901
6003
|
}
|
|
5902
6004
|
function recordClipCellEdges(grids, horizontals, verticals, nonRules) {
|
|
5903
6005
|
if (!grids.some((g) => g.cells)) return;
|
|
5904
|
-
const h = rules(_optionalChain([nonRules, 'optionalAccess',
|
|
5905
|
-
const v = rules(_optionalChain([nonRules, 'optionalAccess',
|
|
6006
|
+
const h = rules(_optionalChain([nonRules, 'optionalAccess', _279 => _279.size]) ? horizontals.filter((l) => !nonRules.has(l)) : horizontals, "h");
|
|
6007
|
+
const v = rules(_optionalChain([nonRules, 'optionalAccess', _280 => _280.size]) ? verticals.filter((l) => !nonRules.has(l)) : verticals, "v");
|
|
5906
6008
|
for (const g of grids) for (const c of _nullishCoalesce(g.cells, () => ( []))) {
|
|
5907
6009
|
const near = c.filler ? Math.min(EDGE_NEAR2, (c.bbox.y2 - c.bbox.y1) / 3) : EDGE_NEAR2;
|
|
5908
6010
|
CLIP_CELL_EDGES.set(c, edgesOf(c.bbox, h, v, near));
|
|
@@ -5910,12 +6012,12 @@ function recordClipCellEdges(grids, horizontals, verticals, nonRules) {
|
|
|
5910
6012
|
}
|
|
5911
6013
|
function takeClipCellEdges(from, to) {
|
|
5912
6014
|
const e = CLIP_CELL_EDGES.get(from);
|
|
5913
|
-
if (e)
|
|
6015
|
+
if (e) _chunkL5JX2GAMcjs.CELL_EDGES.set(to, e);
|
|
5914
6016
|
}
|
|
5915
6017
|
function joinCellEdges(a, b) {
|
|
5916
|
-
const u =
|
|
6018
|
+
const u = _chunkL5JX2GAMcjs.CELL_EDGES.get(a), d = _chunkL5JX2GAMcjs.CELL_EDGES.get(b);
|
|
5917
6019
|
if (!u || !d) return;
|
|
5918
|
-
|
|
6020
|
+
_chunkL5JX2GAMcjs.CELL_EDGES.set(a, { t: u.t, b: d.b, l: u.l || d.l, r: u.r || d.r });
|
|
5919
6021
|
}
|
|
5920
6022
|
|
|
5921
6023
|
// src/pdf/table-unit-row.ts
|
|
@@ -5931,12 +6033,12 @@ function rebuildUnitLine(items, grid) {
|
|
|
5931
6033
|
function prependUnitRow(cells, cols, line, usedItems) {
|
|
5932
6034
|
const text = cleanCellText(line.map((item) => item.text).join(""));
|
|
5933
6035
|
cells.unshift(Array.from({ length: cols }, (_, c) => ({ text: c === 0 ? text : "", colSpan: c === 0 ? cols : 1, rowSpan: 1 })));
|
|
5934
|
-
for (const cell of cells[0])
|
|
6036
|
+
for (const cell of cells[0]) _chunkL5JX2GAMcjs.CELL_EDGES.set(cell, NO_EDGES);
|
|
5935
6037
|
for (const item of line) usedItems.add(item);
|
|
5936
6038
|
}
|
|
5937
6039
|
function attachUnitRow(items, grid, cells, cols, usedItems) {
|
|
5938
6040
|
const all = cells.flat();
|
|
5939
|
-
if (all.filter((c) => c.text.trim()).length * 2 < all.length || UNIT.test(_nullishCoalesce(_optionalChain([cells, 'access',
|
|
6041
|
+
if (all.filter((c) => c.text.trim()).length * 2 < all.length || UNIT.test(_nullishCoalesce(_optionalChain([cells, 'access', _281 => _281[0], 'optionalAccess', _282 => _282[0], 'optionalAccess', _283 => _283.text]), () => ( "")))) return false;
|
|
5940
6042
|
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);
|
|
5941
6043
|
let nearest = Infinity;
|
|
5942
6044
|
for (const it of above) nearest = Math.min(nearest, it.y);
|
|
@@ -6476,7 +6578,7 @@ function stackedTableBands(items) {
|
|
|
6476
6578
|
const caption = (start, end) => lines.slice(start, end).some((line) => /^Table\s+\d+\s*[:.]/i.test(mergeLineSimple(line).trim()));
|
|
6477
6579
|
while (runs.length > 0 && !caption(runs[runs.length - 1].end, lines.length)) runs.pop();
|
|
6478
6580
|
if (runs.length < 2) return null;
|
|
6479
|
-
if (runs.some((run, i) => !caption(run.end, _nullishCoalesce(_optionalChain([runs, 'access',
|
|
6581
|
+
if (runs.some((run, i) => !caption(run.end, _nullishCoalesce(_optionalChain([runs, 'access', _284 => _284[i + 1], 'optionalAccess', _285 => _285.start]), () => ( lines.length))))) return null;
|
|
6480
6582
|
const tables = runs.map((run) => lines.slice(run.start, run.end).flat());
|
|
6481
6583
|
const between = runs.slice(0, -1).map((run, i) => lines.slice(run.end, runs[i + 1].start).flat());
|
|
6482
6584
|
const tail = lines.slice(runs[runs.length - 1].end);
|
|
@@ -6640,7 +6742,7 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
|
|
|
6640
6742
|
const filled = fillBlanks(items, horizontals, verticals);
|
|
6641
6743
|
items = filled.items;
|
|
6642
6744
|
horizontals = filled.horizontals;
|
|
6643
|
-
const prevPage = _optionalChain([carry, 'optionalAccess',
|
|
6745
|
+
const prevPage = _optionalChain([carry, 'optionalAccess', _286 => _286.page]) === pageNum - 1 ? carry.clip : void 0;
|
|
6644
6746
|
const clipResult = detectTables ? buildClipCellGrids(extracted.clipRects, horizontals, verticals, pageWidth, pageHeight, items.map((it) => ({ x: it.x + it.w / 2, y: it.y + it.h / 2 })), extracted.fillRects, prevPage) : { grids: [], containers: [], page: void 0 };
|
|
6645
6747
|
if (carry) {
|
|
6646
6748
|
carry.page = pageNum;
|
|
@@ -6928,14 +7030,14 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
6928
7030
|
if (!assignedItems.has(textItems[ti])) usedItems.delete(tableItems[ti]);
|
|
6929
7031
|
}
|
|
6930
7032
|
}
|
|
6931
|
-
if (unitLine.length > 0 && rebuiltUsed && !/^\s*\(\s*단위\s*[::]/.test(_nullishCoalesce(_optionalChain([finalGrid, 'access',
|
|
7033
|
+
if (unitLine.length > 0 && rebuiltUsed && !/^\s*\(\s*단위\s*[::]/.test(_nullishCoalesce(_optionalChain([finalGrid, 'access', _287 => _287[0], 'optionalAccess', _288 => _288[0], 'optionalAccess', _289 => _289.text]), () => ( "")))) {
|
|
6932
7034
|
prependUnitRow(finalGrid, numCols, unitLine, usedItems);
|
|
6933
7035
|
finalRows++;
|
|
6934
7036
|
}
|
|
6935
7037
|
if (!rebuiltUsed && attachUnitRow(items, grid, finalGrid, numCols, usedItems)) finalRows++;
|
|
6936
7038
|
let semanticOneColumn = false;
|
|
6937
7039
|
if (!grid.cells && numCols === 1 && numGridRows >= 2) {
|
|
6938
|
-
const populatedRows = finalGrid.filter((row) => _optionalChain([row, 'access',
|
|
7040
|
+
const populatedRows = finalGrid.filter((row) => _optionalChain([row, 'access', _290 => _290[0], 'optionalAccess', _291 => _291.text, 'access', _292 => _292.trim, 'call', _293 => _293()]));
|
|
6939
7041
|
if (populatedRows.length >= 4) {
|
|
6940
7042
|
const fontSizes = tableItems.map((item) => item.fontSize).filter((size) => size > 0).sort((a, b) => a - b);
|
|
6941
7043
|
const medianFont = _nullishCoalesce(fontSizes[Math.floor(fontSizes.length / 2)], () => ( 0));
|
|
@@ -7014,7 +7116,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
7014
7116
|
height: grid.bbox.y2 - grid.bbox.y1
|
|
7015
7117
|
};
|
|
7016
7118
|
if (numRows === 1 && numCols === 1 && gridW < pageWidth * 0.35) {
|
|
7017
|
-
const prose = _nullishCoalesce(_optionalChain([finalGrid, 'access',
|
|
7119
|
+
const prose = _nullishCoalesce(_optionalChain([finalGrid, 'access', _294 => _294[0], 'optionalAccess', _295 => _295[0], 'optionalAccess', _296 => _296.text]), () => ( ""));
|
|
7018
7120
|
const besideLines = (side) => new Set(side.map((it) => Math.round(it.y / 3))).size;
|
|
7019
7121
|
const rightLines = items.filter((it) => it.x >= grid.bbox.x2 + 3 && it.y >= grid.bbox.y1 && it.y <= grid.bbox.y2);
|
|
7020
7122
|
const leftLines = items.filter((it) => it.x + it.w <= grid.bbox.x1 - 3 && it.y >= grid.bbox.y1 && it.y <= grid.bbox.y2);
|
|
@@ -7068,7 +7170,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
7068
7170
|
const proseColumns = findTwoColumnProseCutX(clusterItems) !== null || detectPersistentColumnGutter(remaining.map((i) => ({ x: i.x, y: i.y, w: i.w, h: i.h > 0 ? i.h : i.fontSize }))) !== null;
|
|
7069
7171
|
const clusterResults = (proseColumns ? [] : detectClusterTables(clusterItems, pageNum)).filter((cr) => {
|
|
7070
7172
|
const b = cr.bbox;
|
|
7071
|
-
return !blocks.some((x) => x.type === "paragraph" && x.bbox && (_nullishCoalesce(_optionalChain([x, 'access',
|
|
7173
|
+
return !blocks.some((x) => x.type === "paragraph" && x.bbox && (_nullishCoalesce(_optionalChain([x, 'access', _297 => _297.text, 'optionalAccess', _298 => _298.match, 'call', _299 => _299(/\p{L}/gu), 'optionalAccess', _300 => _300.length]), () => ( 0))) >= 10 && Math.min(x.bbox.x + x.bbox.width, b.x + b.width) - Math.max(x.bbox.x, b.x) >= 0.8 * b.width && x.bbox.y >= b.y - 2 && x.bbox.y + x.bbox.height <= b.y + b.height + 2);
|
|
7072
7174
|
});
|
|
7073
7175
|
if (clusterResults.length > 0) {
|
|
7074
7176
|
const ciToIdx = /* @__PURE__ */ new Map();
|
|
@@ -7102,7 +7204,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
7102
7204
|
if (gutterX !== null) {
|
|
7103
7205
|
const gx = gutterX;
|
|
7104
7206
|
const allY = remaining.map((i) => i.y);
|
|
7105
|
-
const pageH =
|
|
7207
|
+
const pageH = _chunkFVESLY6Vcjs.safeMax.call(void 0, allY) - _chunkFVESLY6Vcjs.safeMin.call(void 0, allY);
|
|
7106
7208
|
const gapThreshold = Math.max(15, pageH * 0.03);
|
|
7107
7209
|
const sides = [
|
|
7108
7210
|
remaining.filter((i) => i.x + i.w <= gx),
|
|
@@ -7122,7 +7224,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
|
|
|
7122
7224
|
finalTextBlocks = detectListBlocks(textBlocks);
|
|
7123
7225
|
} else {
|
|
7124
7226
|
const allY = remaining.map((i) => i.y);
|
|
7125
|
-
const pageH =
|
|
7227
|
+
const pageH = _chunkFVESLY6Vcjs.safeMax.call(void 0, allY) - _chunkFVESLY6Vcjs.safeMin.call(void 0, allY);
|
|
7126
7228
|
const groups = xyCutOrder(remaining, Math.max(15, pageH * 0.03));
|
|
7127
7229
|
const textBlocks = [];
|
|
7128
7230
|
for (const group of groups) {
|
|
@@ -7441,7 +7543,7 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
|
|
|
7441
7543
|
blocks.push(...columnTextToBlocks(tableText, pageNum, bbox, dominantStyle(items)));
|
|
7442
7544
|
} else {
|
|
7443
7545
|
const allY = items.map((i) => i.y);
|
|
7444
|
-
const pageHeight =
|
|
7546
|
+
const pageHeight = _chunkFVESLY6Vcjs.safeMax.call(void 0, allY) - _chunkFVESLY6Vcjs.safeMin.call(void 0, allY);
|
|
7445
7547
|
const gapThreshold = Math.max(15, pageHeight * 0.03);
|
|
7446
7548
|
const orderedGroups = proseCutX !== null ? splitTwoColumnProse(items, proseCutX) : xyCutOrder(items, gapThreshold);
|
|
7447
7549
|
for (const group of orderedGroups) {
|
|
@@ -7509,4 +7611,4 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
|
|
|
7509
7611
|
|
|
7510
7612
|
|
|
7511
7613
|
exports.OCR_DET_MODEL = OCR_DET_MODEL; exports.OCR_REC_MODEL = OCR_REC_MODEL; exports.OCR_REC_DICT = OCR_REC_DICT; exports.getOcrModelsDir = getOcrModelsDir; exports.ensureOcrModels = ensureOcrModels; exports.ocrModelsCached = ocrModelsCached; exports.parseCharacterDict = parseCharacterDict; exports.extractLines = extractLines; exports.extractImageRegions = extractImageRegions; exports.filterHiddenText = filterHiddenText; exports.collapseEvenSpacing = collapseEvenSpacing; exports.normalizeItems = normalizeItems; exports.WrapLexicon = WrapLexicon; exports.startsNewItem = startsNewItem; exports.wrapJoiner = wrapJoiner; exports.joinPageBreakWraps = joinPageBreakWraps; exports.latinSoftWrap = latinSoftWrap; exports.TOC_BLOCKS = TOC_BLOCKS; exports.computeMedianFontSizeFromFreq = computeMedianFontSizeFromFreq; exports.detectHeadings = detectHeadings; exports.mergeStackedHeadingLines = mergeStackedHeadingLines; exports.detectTypographyHeadings = detectTypographyHeadings; exports.detectDocumentStyleHeadings = detectDocumentStyleHeadings; exports.detectSiblingStyleHeadings = detectSiblingStyleHeadings; exports.detectRepeatedPageLabels = detectRepeatedPageLabels; exports.detectPageLeadHeadings = detectPageLeadHeadings; exports.refineDocumentStyleHeadings = refineDocumentStyleHeadings; exports.detectMarkerHeadings = detectMarkerHeadings; exports.detectTableCaptions = detectTableCaptions; exports.detectKoreanListBlocks = detectKoreanListBlocks; exports.removeHeaderFooterBlocks = removeHeaderFooterBlocks; exports.CLIP_TABLES = CLIP_TABLES; exports.TABLE_COLXS = TABLE_COLXS; exports.TABLE_ROWYS = TABLE_ROWYS; exports.TABLE_TAIL = TABLE_TAIL; exports.PART_COLXS = PART_COLXS; exports.EMPTY_PARTS = EMPTY_PARTS; exports.IMAGE_CELLS = IMAGE_CELLS; exports.FILLER_CELLS = FILLER_CELLS; exports.CONT_PARTS = CONT_PARTS; exports.CELL_LINES = CELL_LINES; exports.ROW_RULES = ROW_RULES; exports.trimTrailingEmptyTableCols = trimTrailingEmptyTableCols; exports.NO_EDGES = NO_EDGES; exports.joinCellEdges = joinCellEdges; exports.extractPageBlocksWithLines = extractPageBlocksWithLines;
|
|
7512
|
-
//# sourceMappingURL=chunk-
|
|
7614
|
+
//# sourceMappingURL=chunk-CZOPNDTO.cjs.map
|