kordoc 4.0.7 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +837 -806
  3. package/dist/{-6HWEFXVV.js → -AS4IABL2.js} +24 -11
  4. package/dist/{chunk-BKWHX3RC.js → chunk-37HJHCPA.js} +24 -15
  5. package/dist/chunk-37HJHCPA.js.map +1 -0
  6. package/dist/{chunk-U25XGCNH.cjs → chunk-37VKMUST.cjs} +174 -25
  7. package/dist/chunk-37VKMUST.cjs.map +1 -0
  8. package/dist/{chunk-5OKHAJ62.js → chunk-4KI23VHA.js} +162 -13
  9. package/dist/chunk-4KI23VHA.js.map +1 -0
  10. package/dist/{chunk-6GBLFQMA.js → chunk-5RPYBC2Q.js} +1 -1
  11. package/dist/chunk-5RPYBC2Q.js.map +1 -0
  12. package/dist/{chunk-NGSHDBQR.js → chunk-AX2R5Q2N.js} +7 -4
  13. package/dist/chunk-AX2R5Q2N.js.map +1 -0
  14. package/dist/{chunk-X34YWRL5.cjs → chunk-DCZVOIEO.cjs} +1 -1
  15. package/dist/chunk-DCZVOIEO.cjs.map +1 -0
  16. package/dist/chunk-DZIXKL7E.js +145 -0
  17. package/dist/chunk-DZIXKL7E.js.map +1 -0
  18. package/dist/chunk-F2ZU3IZG.js +82 -0
  19. package/dist/chunk-F2ZU3IZG.js.map +1 -0
  20. package/dist/{chunk-AIQ3ISQU.js → chunk-GE43BE46.js} +1 -1
  21. package/dist/chunk-GE43BE46.js.map +1 -0
  22. package/dist/{chunk-Q7EN4EUJ.js → chunk-GQVSHGG4.js} +12 -4
  23. package/dist/chunk-GQVSHGG4.js.map +1 -0
  24. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  25. package/dist/{chunk-TJJTLM76.js → chunk-L2XQQTOY.js} +1422 -1121
  26. package/dist/chunk-L2XQQTOY.js.map +1 -0
  27. package/dist/{chunk-3TBUDJDE.js → chunk-MOL7MDBG.js} +1 -1
  28. package/dist/chunk-MOL7MDBG.js.map +1 -0
  29. package/dist/{chunk-CNM75ZSX.js → chunk-O5VS7RIR.js} +2 -2
  30. package/dist/chunk-O5VS7RIR.js.map +1 -0
  31. package/dist/{chunk-2SN3CKME.js → chunk-SSTK6IKK.js} +18 -21
  32. package/dist/chunk-SSTK6IKK.js.map +1 -0
  33. package/dist/chunk-UOO7LSDG.js +152 -0
  34. package/dist/chunk-UOO7LSDG.js.map +1 -0
  35. package/dist/{chunk-ONXVBURQ.js → chunk-WO52HVQJ.js} +2 -2
  36. package/dist/chunk-WO52HVQJ.js.map +1 -0
  37. package/dist/{chunk-CFQLK3LM.js → chunk-YOO6ET6M.js} +7 -3
  38. package/dist/chunk-YOO6ET6M.js.map +1 -0
  39. package/dist/chunks-WVMGF7JL.js +10 -0
  40. package/dist/cli.js +173 -38
  41. package/dist/cli.js.map +1 -1
  42. package/dist/{detect-NTR2FUEG.js → detect-YEZX2XCF.js} +2 -2
  43. package/dist/{formula-ZYUDQHD3.cjs → formula-5NKVS2LR.cjs} +1 -1
  44. package/dist/formula-5NKVS2LR.cjs.map +1 -0
  45. package/dist/{formula-KOQV353G.js → formula-JCNF43NE.js} +1 -1
  46. package/dist/formula-JCNF43NE.js.map +1 -0
  47. package/dist/{formula-MEDGYQXS.js → formula-RXVSQPXI.js} +1 -1
  48. package/dist/formula-RXVSQPXI.js.map +1 -0
  49. package/dist/index.cjs +1932 -1397
  50. package/dist/index.cjs.map +1 -1
  51. package/dist/index.d.cts +106 -2
  52. package/dist/index.d.ts +106 -2
  53. package/dist/index.js +1626 -1091
  54. package/dist/index.js.map +1 -1
  55. package/dist/mcp.js +275 -67
  56. package/dist/mcp.js.map +1 -1
  57. package/dist/page-range-737B4EZW.js +8 -0
  58. package/dist/page-range-LNMXJU6W.js +7 -0
  59. package/dist/page-range-P7SDW6LR.cjs +8 -0
  60. package/dist/page-range-P7SDW6LR.cjs.map +1 -0
  61. package/dist/{parser-E6U5TNAU.cjs → parser-N4A7UGDK.cjs} +314 -56
  62. package/dist/parser-N4A7UGDK.cjs.map +1 -0
  63. package/dist/{parser-5EHWYJMC.js → parser-PEOYBXBO.js} +287 -27
  64. package/dist/parser-PEOYBXBO.js.map +1 -0
  65. package/dist/{parser-UGB3NIVH.js → parser-XX4QTDFQ.js} +283 -25
  66. package/dist/parser-XX4QTDFQ.js.map +1 -0
  67. package/dist/{profile-io-CAKRPQRD.js → profile-io-PLDQFPJA.js} +3 -3
  68. package/dist/{provider-5K7O3Z2O.cjs → provider-4FAYHJ6N.cjs} +3 -3
  69. package/dist/provider-4FAYHJ6N.cjs.map +1 -0
  70. package/dist/{provider-H4WWSPOV.js → provider-C6IOGIS5.js} +3 -3
  71. package/dist/provider-C6IOGIS5.js.map +1 -0
  72. package/dist/{provider-7H4CPZYS.js → provider-UIBW2MIH.js} +3 -3
  73. package/dist/provider-UIBW2MIH.js.map +1 -0
  74. package/dist/rasterize-WWNQLKYW.js +40 -0
  75. package/dist/rasterize-WWNQLKYW.js.map +1 -0
  76. package/dist/redact-7ILEAUTS.js +12 -0
  77. package/dist/render-T7S6H6AN.js +10 -0
  78. package/dist/render-T7S6H6AN.js.map +1 -0
  79. package/dist/seal-7PTL6MXH.js +10 -0
  80. package/dist/seal-7PTL6MXH.js.map +1 -0
  81. package/dist/{setup-QSJ2INNS.js → setup-Q2PRE7UA.js} +5 -3
  82. package/dist/setup-Q2PRE7UA.js.map +1 -0
  83. package/dist/{watch-RMX427YR.js → watch-SFHXZALC.js} +78 -24
  84. package/dist/watch-SFHXZALC.js.map +1 -0
  85. package/package.json +97 -97
  86. package/dist/chunk-2SN3CKME.js.map +0 -1
  87. package/dist/chunk-3TBUDJDE.js.map +0 -1
  88. package/dist/chunk-5OKHAJ62.js.map +0 -1
  89. package/dist/chunk-6GBLFQMA.js.map +0 -1
  90. package/dist/chunk-AIQ3ISQU.js.map +0 -1
  91. package/dist/chunk-BKWHX3RC.js.map +0 -1
  92. package/dist/chunk-CFQLK3LM.js.map +0 -1
  93. package/dist/chunk-CNM75ZSX.js.map +0 -1
  94. package/dist/chunk-NGSHDBQR.js.map +0 -1
  95. package/dist/chunk-ONXVBURQ.js.map +0 -1
  96. package/dist/chunk-Q7EN4EUJ.js.map +0 -1
  97. package/dist/chunk-TJJTLM76.js.map +0 -1
  98. package/dist/chunk-U25XGCNH.cjs.map +0 -1
  99. package/dist/chunk-X34YWRL5.cjs.map +0 -1
  100. package/dist/formula-KOQV353G.js.map +0 -1
  101. package/dist/formula-MEDGYQXS.js.map +0 -1
  102. package/dist/formula-ZYUDQHD3.cjs.map +0 -1
  103. package/dist/page-range-CIRRJPXJ.js +0 -7
  104. package/dist/page-range-OF5I4PQY.js +0 -8
  105. package/dist/page-range-TPIRSA3J.cjs +0 -8
  106. package/dist/page-range-TPIRSA3J.cjs.map +0 -1
  107. package/dist/parser-5EHWYJMC.js.map +0 -1
  108. package/dist/parser-E6U5TNAU.cjs.map +0 -1
  109. package/dist/parser-UGB3NIVH.js.map +0 -1
  110. package/dist/provider-5K7O3Z2O.cjs.map +0 -1
  111. package/dist/provider-7H4CPZYS.js.map +0 -1
  112. package/dist/provider-H4WWSPOV.js.map +0 -1
  113. package/dist/render-P6663O4I.js +0 -10
  114. package/dist/seal-7PPTXKKV.js +0 -10
  115. package/dist/setup-QSJ2INNS.js.map +0 -1
  116. package/dist/watch-RMX427YR.js.map +0 -1
  117. /package/dist/{-6HWEFXVV.js.map → -AS4IABL2.js.map} +0 -0
  118. /package/dist/{detect-NTR2FUEG.js.map → chunks-WVMGF7JL.js.map} +0 -0
  119. /package/dist/{page-range-CIRRJPXJ.js.map → detect-YEZX2XCF.js.map} +0 -0
  120. /package/dist/{page-range-OF5I4PQY.js.map → page-range-737B4EZW.js.map} +0 -0
  121. /package/dist/{profile-io-CAKRPQRD.js.map → page-range-LNMXJU6W.js.map} +0 -0
  122. /package/dist/{render-P6663O4I.js.map → profile-io-PLDQFPJA.js.map} +0 -0
  123. /package/dist/{seal-7PPTXKKV.js.map → redact-7ILEAUTS.js.map} +0 -0
@@ -4,12 +4,13 @@ import {
4
4
  HEADING_RATIO_H3,
5
5
  KordocError,
6
6
  blocksToMarkdown,
7
+ encodePng,
7
8
  safeMax,
8
9
  safeMin
9
- } from "./chunk-5OKHAJ62.js";
10
+ } from "./chunk-4KI23VHA.js";
10
11
  import {
11
12
  parsePageRange
12
- } from "./chunk-AIQ3ISQU.js";
13
+ } from "./chunk-GE43BE46.js";
13
14
 
14
15
  // src/pdf/line-extract.ts
15
16
  import { OPS } from "pdfjs-dist/legacy/build/pdf.mjs";
@@ -577,6 +578,18 @@ function buildVertices(horizontals, verticals) {
577
578
  }
578
579
  function mergeVertices(vertices) {
579
580
  if (vertices.length <= 1) return vertices;
581
+ let maxRadiusAll = 1;
582
+ for (const v of vertices) {
583
+ if (v.radius > maxRadiusAll) maxRadiusAll = v.radius;
584
+ }
585
+ const cell = Math.max(VERTEX_MERGE_FACTOR * maxRadiusAll, 1);
586
+ const buckets = /* @__PURE__ */ new Map();
587
+ for (let i = 0; i < vertices.length; i++) {
588
+ const key = Math.floor(vertices[i].x / cell) + "," + Math.floor(vertices[i].y / cell);
589
+ const arr = buckets.get(key);
590
+ if (arr) arr.push(i);
591
+ else buckets.set(key, [i]);
592
+ }
580
593
  const merged = [];
581
594
  const used = new Array(vertices.length).fill(false);
582
595
  for (let i = 0; i < vertices.length; i++) {
@@ -584,7 +597,20 @@ function mergeVertices(vertices) {
584
597
  let sumX = vertices[i].x, sumY = vertices[i].y;
585
598
  let maxRadius = vertices[i].radius;
586
599
  let count = 1;
587
- for (let j = i + 1; j < vertices.length; j++) {
600
+ const cx = Math.floor(vertices[i].x / cell);
601
+ const cy = Math.floor(vertices[i].y / cell);
602
+ const candidates = [];
603
+ for (let dx = -1; dx <= 1; dx++) {
604
+ for (let dy = -1; dy <= 1; dy++) {
605
+ const arr = buckets.get(cx + dx + "," + (cy + dy));
606
+ if (!arr) continue;
607
+ for (const j of arr) {
608
+ if (j > i && !used[j]) candidates.push(j);
609
+ }
610
+ }
611
+ }
612
+ candidates.sort((a, b) => a - b);
613
+ for (const j of candidates) {
588
614
  if (used[j]) continue;
589
615
  const mergeTol = VERTEX_MERGE_FACTOR * Math.max(maxRadius, vertices[j].radius);
590
616
  if (Math.abs(vertices[i].x - vertices[j].x) <= mergeTol && Math.abs(vertices[i].y - vertices[j].y) <= mergeTol) {
@@ -811,6 +837,7 @@ function splitStackedGroup(group) {
811
837
  }
812
838
  return bands.filter((b) => b.length > 0);
813
839
  }
840
+ var GROUP_BUCKET_CELL = 100;
814
841
  function groupConnectedLines(lines) {
815
842
  const parent = lines.map((_, i) => i);
816
843
  function find(x) {
@@ -824,10 +851,34 @@ function groupConnectedLines(lines) {
824
851
  const ra = find(a), rb = find(b);
825
852
  if (ra !== rb) parent[ra] = rb;
826
853
  }
854
+ const cellMap = /* @__PURE__ */ new Map();
827
855
  for (let i = 0; i < lines.length; i++) {
828
- for (let j = i + 1; j < lines.length; j++) {
829
- if (linesIntersect(lines[i], lines[j])) {
830
- union(i, j);
856
+ const l = lines[i];
857
+ const cx1 = Math.floor((Math.min(l.x1, l.x2) - CONNECT_TOL) / GROUP_BUCKET_CELL);
858
+ const cx2 = Math.floor((Math.max(l.x1, l.x2) + CONNECT_TOL) / GROUP_BUCKET_CELL);
859
+ const cy1 = Math.floor((Math.min(l.y1, l.y2) - CONNECT_TOL) / GROUP_BUCKET_CELL);
860
+ const cy2 = Math.floor((Math.max(l.y1, l.y2) + CONNECT_TOL) / GROUP_BUCKET_CELL);
861
+ for (let cx = cx1; cx <= cx2; cx++) {
862
+ for (let cy = cy1; cy <= cy2; cy++) {
863
+ const key = cx + "," + cy;
864
+ const arr = cellMap.get(key);
865
+ if (arr) arr.push(i);
866
+ else cellMap.set(key, [i]);
867
+ }
868
+ }
869
+ }
870
+ const tested = /* @__PURE__ */ new Set();
871
+ for (const arr of cellMap.values()) {
872
+ for (let a = 0; a < arr.length; a++) {
873
+ for (let b = a + 1; b < arr.length; b++) {
874
+ const i = Math.min(arr[a], arr[b]);
875
+ const j = Math.max(arr[a], arr[b]);
876
+ const key = i * lines.length + j;
877
+ if (tested.has(key)) continue;
878
+ tested.add(key);
879
+ if (linesIntersect(lines[i], lines[j])) {
880
+ union(i, j);
881
+ }
831
882
  }
832
883
  }
833
884
  }
@@ -1220,6 +1271,172 @@ function normalizeUndersegmentedTable(originalCells, colXs, items) {
1220
1271
  return rebuilt;
1221
1272
  }
1222
1273
 
1274
+ // src/pdf/image-extract.ts
1275
+ import { OPS as OPS3, ImageKind } from "pdfjs-dist/legacy/build/pdf.mjs";
1276
+ var IMAGE_RESOLVE_TIMEOUT_MS = 5e3;
1277
+ function resolveImgData(page, objId) {
1278
+ const store = objId.startsWith("g_") ? page.commonObjs : page.objs;
1279
+ return new Promise((resolve) => {
1280
+ let done = false;
1281
+ const timer = setTimeout(() => {
1282
+ if (!done) {
1283
+ done = true;
1284
+ resolve(null);
1285
+ }
1286
+ }, IMAGE_RESOLVE_TIMEOUT_MS);
1287
+ try {
1288
+ store.get(objId, (data) => {
1289
+ if (!done) {
1290
+ done = true;
1291
+ clearTimeout(timer);
1292
+ resolve(data ?? null);
1293
+ }
1294
+ });
1295
+ } catch {
1296
+ if (!done) {
1297
+ done = true;
1298
+ clearTimeout(timer);
1299
+ resolve(null);
1300
+ }
1301
+ }
1302
+ });
1303
+ }
1304
+ var MIN_DIM = 8;
1305
+ var MAX_PIXELS = 36e6;
1306
+ var MAX_IMAGES_PER_DOC = 200;
1307
+ var MAX_TOTAL_IMAGE_BYTES = 128 * 1024 * 1024;
1308
+ function createPdfImageState() {
1309
+ return { imageIndex: 0, totalBytes: 0, seen: /* @__PURE__ */ new Map(), capWarned: false };
1310
+ }
1311
+ function fnv1a(data) {
1312
+ let h = 2166136261;
1313
+ for (let i = 0; i < data.length; i++) {
1314
+ h ^= data[i];
1315
+ h = Math.imul(h, 16777619);
1316
+ }
1317
+ return h >>> 0;
1318
+ }
1319
+ function toRgba(img) {
1320
+ const { width: w, height: h, kind, data } = img;
1321
+ if (!data || !w || !h) return null;
1322
+ const rgba = new Uint8Array(w * h * 4);
1323
+ if (kind === ImageKind.RGBA_32BPP) {
1324
+ if (data.length < w * h * 4) return null;
1325
+ rgba.set(data.subarray(0, w * h * 4));
1326
+ return rgba;
1327
+ }
1328
+ if (kind === ImageKind.RGB_24BPP) {
1329
+ if (data.length < w * h * 3) return null;
1330
+ for (let i = 0, s = 0, d = 0; i < w * h; i++, s += 3, d += 4) {
1331
+ rgba[d] = data[s];
1332
+ rgba[d + 1] = data[s + 1];
1333
+ rgba[d + 2] = data[s + 2];
1334
+ rgba[d + 3] = 255;
1335
+ }
1336
+ return rgba;
1337
+ }
1338
+ if (kind === ImageKind.GRAYSCALE_1BPP) {
1339
+ const stride = w + 7 >> 3;
1340
+ if (data.length < stride * h) return null;
1341
+ for (let y = 0; y < h; y++) {
1342
+ for (let x = 0; x < w; x++) {
1343
+ const bit = data[y * stride + (x >> 3)] >> 7 - (x & 7) & 1;
1344
+ const v = bit ? 255 : 0;
1345
+ const d = (y * w + x) * 4;
1346
+ rgba[d] = v;
1347
+ rgba[d + 1] = v;
1348
+ rgba[d + 2] = v;
1349
+ rgba[d + 3] = 255;
1350
+ }
1351
+ }
1352
+ return rgba;
1353
+ }
1354
+ return null;
1355
+ }
1356
+ async function extractPageImages(page, fnArray, argsArray, pageNumber, state, warnings) {
1357
+ const blocks = [];
1358
+ const images = [];
1359
+ const pageSeenIds = /* @__PURE__ */ new Set();
1360
+ for (let i = 0; i < fnArray.length; i++) {
1361
+ const op = fnArray[i];
1362
+ let imgData = null;
1363
+ let dedupeId = null;
1364
+ if (op === OPS3.paintImageXObject || op === OPS3.paintImageXObjectRepeat) {
1365
+ const objId = argsArray[i]?.[0];
1366
+ if (typeof objId !== "string" || pageSeenIds.has(objId)) continue;
1367
+ pageSeenIds.add(objId);
1368
+ dedupeId = objId;
1369
+ } else if (op !== OPS3.paintInlineImageXObject) {
1370
+ continue;
1371
+ }
1372
+ if (state.imageIndex >= MAX_IMAGES_PER_DOC || state.totalBytes >= MAX_TOTAL_IMAGE_BYTES) {
1373
+ if (!state.capWarned) {
1374
+ state.capWarned = true;
1375
+ warnings.push({ page: pageNumber, message: `\uC774\uBBF8\uC9C0 \uCD94\uCD9C \uC0C1\uD55C \uB3C4\uB2EC (${MAX_IMAGES_PER_DOC}\uAC1C/128MB) \u2014 \uC774\uD6C4 \uC774\uBBF8\uC9C0 \uC0DD\uB7B5`, code: "SKIPPED_IMAGE" });
1376
+ }
1377
+ continue;
1378
+ }
1379
+ if (dedupeId) {
1380
+ imgData = await resolveImgData(page, dedupeId);
1381
+ } else {
1382
+ imgData = argsArray[i]?.[0];
1383
+ }
1384
+ if (!imgData?.data || !imgData.width || !imgData.height) continue;
1385
+ const { width: w, height: h } = imgData;
1386
+ if (w < MIN_DIM || h < MIN_DIM) continue;
1387
+ if (w * h > MAX_PIXELS) {
1388
+ warnings.push({ page: pageNumber, message: `\uC774\uBBF8\uC9C0 \uD06C\uAE30 \uCD08\uACFC\uB85C \uCD94\uCD9C \uC0DD\uB7B5 (${w}\xD7${h})`, code: "SKIPPED_IMAGE" });
1389
+ continue;
1390
+ }
1391
+ const hash = `${w}x${h}k${imgData.kind ?? "?"}h${fnv1a(imgData.data)}${dedupeId ? "" : "inline"}`;
1392
+ if (state.seen.has(hash)) continue;
1393
+ const rgba = toRgba(imgData);
1394
+ if (!rgba) continue;
1395
+ const png = encodePng(w, h, rgba);
1396
+ state.imageIndex++;
1397
+ state.totalBytes += png.length;
1398
+ const filename = `image_${String(state.imageIndex).padStart(3, "0")}.png`;
1399
+ state.seen.set(hash, filename);
1400
+ images.push({ filename, data: png, mimeType: "image/png" });
1401
+ blocks.push({ type: "image", text: filename, pageNumber });
1402
+ }
1403
+ return { blocks, images };
1404
+ }
1405
+ function injectPageImageBlocks(blocks, pageImages) {
1406
+ if (pageImages.size === 0) return;
1407
+ const lastIndexForPage = /* @__PURE__ */ new Map();
1408
+ for (let i = 0; i < blocks.length; i++) {
1409
+ const p = blocks[i].pageNumber;
1410
+ if (p !== void 0) lastIndexForPage.set(p, i);
1411
+ }
1412
+ const pageAtIndex = /* @__PURE__ */ new Map();
1413
+ for (const [p, last] of lastIndexForPage) pageAtIndex.set(last, p);
1414
+ const result = [];
1415
+ const injected = /* @__PURE__ */ new Set();
1416
+ for (let i = 0; i < blocks.length; i++) {
1417
+ result.push(blocks[i]);
1418
+ const p = pageAtIndex.get(i);
1419
+ if (p !== void 0 && pageImages.has(p)) {
1420
+ result.push(...pageImages.get(p));
1421
+ injected.add(p);
1422
+ }
1423
+ }
1424
+ for (const p of [...pageImages.keys()].sort((a, b) => a - b)) {
1425
+ if (injected.has(p)) continue;
1426
+ let at = result.length;
1427
+ for (let i = 0; i < result.length; i++) {
1428
+ const bp = result[i].pageNumber;
1429
+ if (bp !== void 0 && bp > p) {
1430
+ at = i;
1431
+ break;
1432
+ }
1433
+ }
1434
+ result.splice(at, 0, ...pageImages.get(p));
1435
+ }
1436
+ blocks.length = 0;
1437
+ blocks.push(...result);
1438
+ }
1439
+
1223
1440
  // src/pdf/quality.ts
1224
1441
  var RARE_JONG = /* @__PURE__ */ new Set([3, 5, 6, 9, 10, 11, 12, 13, 14, 15, 18, 24, 25, 26]);
1225
1442
  var MOJIBAKE_MIN_HANGUL = 30;
@@ -2515,11 +2732,12 @@ function buildGridTable(lines, columns) {
2515
2732
  if (filledCells < totalCells * 0.35 || merged.length < 2 || merged.length <= 3 && numCols >= 7) {
2516
2733
  return merged.map((r) => r.filter((c) => c).join(" ")).join("\n");
2517
2734
  }
2735
+ const escCell = (c) => c.replace(/\t/g, " ").replace(/\|/g, "\\|");
2518
2736
  const md = [];
2519
- md.push("| " + merged[0].join(" | ") + " |");
2737
+ md.push("| " + merged[0].map(escCell).join(" | ") + " |");
2520
2738
  md.push("| " + merged[0].map(() => "---").join(" | ") + " |");
2521
2739
  for (let r = 1; r < merged.length; r++) {
2522
- md.push("| " + merged[r].join(" | ") + " |");
2740
+ md.push("| " + merged[r].map(escCell).join(" | ") + " |");
2523
2741
  }
2524
2742
  return md.join("\n");
2525
2743
  }
@@ -2699,6 +2917,7 @@ function detectKoreanListBlocks(blocks) {
2699
2917
  }
2700
2918
  let familyStack = [];
2701
2919
  let lastTopLevelList = null;
2920
+ let prevListIdx = -2;
2702
2921
  const toRemove = /* @__PURE__ */ new Set();
2703
2922
  for (let i = 0; i < blocks.length; i++) {
2704
2923
  const b = blocks[i];
@@ -2727,7 +2946,7 @@ function detectKoreanListBlocks(blocks) {
2727
2946
  if (depth === 0) {
2728
2947
  blocks[i] = listBlock;
2729
2948
  lastTopLevelList = listBlock;
2730
- } else if (lastTopLevelList) {
2949
+ } else if (lastTopLevelList && i === prevListIdx + 1) {
2731
2950
  if (!lastTopLevelList.children) lastTopLevelList.children = [];
2732
2951
  lastTopLevelList.children.push(listBlock);
2733
2952
  toRemove.add(i);
@@ -2735,6 +2954,7 @@ function detectKoreanListBlocks(blocks) {
2735
2954
  blocks[i] = listBlock;
2736
2955
  lastTopLevelList = listBlock;
2737
2956
  }
2957
+ prevListIdx = i;
2738
2958
  }
2739
2959
  if (toRemove.size > 0) {
2740
2960
  const sorted = [...toRemove].sort((a, b) => b - a);
@@ -2860,8 +3080,8 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings) {
2860
3080
  const blockTop = ph - (b.bbox.y + b.bbox.height);
2861
3081
  const blockBottom = ph - b.bbox.y;
2862
3082
  const entry = { blockIdx: bi, page: b.pageNumber, text: b.text.trim() };
2863
- if (blockBottom <= ph * ZONE_RATIO) bottomEntries.push(entry);
2864
- else if (blockTop >= ph * (1 - ZONE_RATIO)) topEntries.push(entry);
3083
+ if (blockBottom <= ph * ZONE_RATIO) topEntries.push(entry);
3084
+ else if (blockTop >= ph * (1 - ZONE_RATIO)) bottomEntries.push(entry);
2865
3085
  }
2866
3086
  const removeSet = /* @__PURE__ */ new Set();
2867
3087
  for (const entries of [topEntries, bottomEntries]) {
@@ -3034,6 +3254,8 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3034
3254
  hasSpaceBefore: i.hasSpaceBefore
3035
3255
  }));
3036
3256
  const cellTextMap = mapTextToCells(textItems, cells);
3257
+ const assignedItems = /* @__PURE__ */ new Set();
3258
+ for (const arr of cellTextMap.values()) for (const it of arr) assignedItems.add(it);
3037
3259
  const numRows = grid.rowYs.length - 1;
3038
3260
  const numCols = grid.colXs.length - 1;
3039
3261
  const irGrid = Array.from(
@@ -3053,9 +3275,11 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3053
3275
  }
3054
3276
  let finalGrid = irGrid;
3055
3277
  let finalRows = numRows;
3278
+ let rebuiltUsed = false;
3056
3279
  if (numRows <= 2 && numCols >= 3) {
3057
3280
  const rebuilt = normalizeUndersegmentedTable(irGrid, grid.colXs, textItems);
3058
3281
  if (rebuilt) {
3282
+ rebuiltUsed = true;
3059
3283
  finalGrid = rebuilt.map((row) => row.map((rawText) => {
3060
3284
  const cleaned = rawText.replace(/^[\s]*[-–—]\s*\d+\s*[-–—][\s]*$/gm, "").trim();
3061
3285
  return {
@@ -3067,6 +3291,11 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3067
3291
  finalRows = finalGrid.length;
3068
3292
  }
3069
3293
  }
3294
+ if (!rebuiltUsed) {
3295
+ for (let ti = 0; ti < textItems.length; ti++) {
3296
+ if (!assignedItems.has(textItems[ti])) usedItems.delete(tableItems[ti]);
3297
+ }
3298
+ }
3070
3299
  const irTable = {
3071
3300
  rows: finalRows,
3072
3301
  cols: numCols,
@@ -3123,6 +3352,8 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3123
3352
  }
3124
3353
  remaining = remaining.filter((_, idx) => !usedClusterIndices.has(idx));
3125
3354
  }
3355
+ const groupSizes = [];
3356
+ let finalTextBlocks = [];
3126
3357
  if (remaining.length > 0) {
3127
3358
  const allY = remaining.map((i) => i.y);
3128
3359
  const pageH = safeMax(allY) - safeMin(allY);
@@ -3132,16 +3363,28 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3132
3363
  if (group.length === 0) continue;
3133
3364
  const groupBlocks = extractPageBlocksFallback(group, pageNum);
3134
3365
  for (const b of groupBlocks) textBlocks.push(b);
3366
+ groupSizes.push(groupBlocks.length);
3135
3367
  }
3136
- const finalTextBlocks = detectListBlocks(textBlocks);
3137
- for (const b of finalTextBlocks) blocks.push(b);
3368
+ finalTextBlocks = detectListBlocks(textBlocks);
3138
3369
  }
3139
- blocks.sort((a, b) => {
3140
- const ay = a.bbox ? a.bbox.y + a.bbox.height : 0;
3141
- const by = b.bbox ? b.bbox.y + b.bbox.height : 0;
3142
- return by - ay;
3143
- });
3144
- return mergeAdjacentTableBlocks(blocks);
3370
+ const units = blocks.map((b) => [b]);
3371
+ let off = 0;
3372
+ for (const size of groupSizes) {
3373
+ const unit = finalTextBlocks.slice(off, off + size);
3374
+ off += size;
3375
+ if (unit.length > 0) units.push(unit);
3376
+ }
3377
+ const unitTopY = (u) => {
3378
+ let top = 0;
3379
+ for (const b of u) {
3380
+ if (b.bbox && b.bbox.y + b.bbox.height > top) top = b.bbox.y + b.bbox.height;
3381
+ }
3382
+ return top;
3383
+ };
3384
+ units.sort((a, b) => unitTopY(b) - unitTopY(a));
3385
+ const ordered = [];
3386
+ for (const u of units) for (const b of u) ordered.push(b);
3387
+ return mergeAdjacentTableBlocks(ordered);
3145
3388
  }
3146
3389
  return mergeAdjacentTableBlocks(blocks);
3147
3390
  }
@@ -3387,7 +3630,7 @@ function mergeKoreanLines(text) {
3387
3630
 
3388
3631
  // src/pdf/formula-ocr.ts
3389
3632
  async function applyFormulaOcr(buffer, blocks, pageFilter, effectivePageCount, warnings, _onProgress) {
3390
- const formulaMod = await import("./formula-MEDGYQXS.js");
3633
+ const formulaMod = await import("./formula-RXVSQPXI.js");
3391
3634
  const { FormulaPipeline, ensureFormulaModels } = formulaMod;
3392
3635
  await ensureFormulaModels((p) => {
3393
3636
  if (p.phase === "download" && p.total) {
@@ -3582,6 +3825,9 @@ async function parsePdfDocument(buffer, options) {
3582
3825
  const pageHeights = /* @__PURE__ */ new Map();
3583
3826
  const pagesWithLargeImage = /* @__PURE__ */ new Set();
3584
3827
  const skippedImagePages = /* @__PURE__ */ new Map();
3828
+ const imageState = createPdfImageState();
3829
+ const extractedImages = [];
3830
+ const pageImageBlocks = /* @__PURE__ */ new Map();
3585
3831
  let parsedPages = 0;
3586
3832
  for (let i = 1; i <= effectivePageCount; i++) {
3587
3833
  if (pageFilter && !pageFilter.has(i)) continue;
@@ -3619,9 +3865,19 @@ async function parsePdfDocument(buffer, options) {
3619
3865
  }
3620
3866
  const pageBlocks = extractPageBlocksWithLines(visible, i, opList, viewport.width, viewport.height);
3621
3867
  for (const b of pageBlocks) blocks.push(b);
3868
+ try {
3869
+ const { blocks: imgBlocks, images: pageImages } = await extractPageImages(page, opList.fnArray, opList.argsArray, i, imageState, warnings);
3870
+ if (imgBlocks.length > 0) pageImageBlocks.set(i, imgBlocks);
3871
+ extractedImages.push(...pageImages);
3872
+ } catch {
3873
+ }
3622
3874
  let pageText = "";
3623
3875
  for (const b of pageBlocks) {
3624
- const t = b.text || "";
3876
+ let t = b.text || "";
3877
+ if (b.type === "table" && b.table) {
3878
+ const cellText = b.table.cells.map((row) => row.map((c) => c.text).join(" ")).join("\n");
3879
+ t = t ? t + "\n" + cellText : cellText;
3880
+ }
3625
3881
  totalChars += t.replace(/\s/g, "").length;
3626
3882
  totalTextBytes += t.length * 2;
3627
3883
  pageText += pageText ? "\n" + t : t;
@@ -3640,11 +3896,11 @@ async function parsePdfDocument(buffer, options) {
3640
3896
  if (totalChars / Math.max(parsedPageCount, 1) < 10) {
3641
3897
  if (options?.ocr) {
3642
3898
  try {
3643
- const { ocrPages } = await import("./provider-H4WWSPOV.js");
3899
+ const { ocrPages } = await import("./provider-C6IOGIS5.js");
3644
3900
  const ocrBlocks = await ocrPages(doc, options.ocr, pageFilter, effectivePageCount);
3645
3901
  if (ocrBlocks.length > 0) {
3646
3902
  const ocrMarkdown = ocrBlocks.map((b) => b.text || "").filter(Boolean).join("\n\n");
3647
- return { markdown: ocrMarkdown, blocks: ocrBlocks, metadata, warnings, isImageBased: true, pageQuality, qualitySummary: summarizeDocumentQuality(pageQuality) };
3903
+ return { markdown: ocrMarkdown, blocks: ocrBlocks, metadata, warnings, isImageBased: true, pageQuality, qualitySummary: summarizeDocumentQuality(pageQuality), images: extractedImages.length > 0 ? extractedImages : void 0 };
3648
3904
  }
3649
3905
  } catch {
3650
3906
  }
@@ -3681,6 +3937,7 @@ async function parsePdfDocument(buffer, options) {
3681
3937
  }
3682
3938
  }
3683
3939
  mergeCrossPageTables(blocks);
3940
+ injectPageImageBlocks(blocks, pageImageBlocks);
3684
3941
  if (options?.formulaOcr && formulaBuffer) {
3685
3942
  try {
3686
3943
  await applyFormulaOcr(formulaBuffer, blocks, pageFilter, effectivePageCount, warnings, options.onProgress);
@@ -3709,7 +3966,8 @@ async function parsePdfDocument(buffer, options) {
3709
3966
  warnings: warnings.length > 0 ? warnings : void 0,
3710
3967
  isImageBased: isImageBased || void 0,
3711
3968
  pageQuality,
3712
- qualitySummary: summarizeDocumentQuality(pageQuality)
3969
+ qualitySummary: summarizeDocumentQuality(pageQuality),
3970
+ images: extractedImages.length > 0 ? extractedImages : void 0
3713
3971
  };
3714
3972
  } finally {
3715
3973
  await doc.destroy().catch(() => {
@@ -3759,4 +4017,4 @@ export {
3759
4017
  parsePdfDocument,
3760
4018
  removeHeaderFooterBlocks
3761
4019
  };
3762
- //# sourceMappingURL=parser-UGB3NIVH.js.map
4020
+ //# sourceMappingURL=parser-XX4QTDFQ.js.map