kordoc 4.0.6 → 4.0.8

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 (86) hide show
  1. package/README.md +823 -806
  2. package/dist/{-NDU7YGSS.js → -LE4RLXVA.js} +8 -8
  3. package/dist/{chunk-5SOZXPQY.js → chunk-2DZQF6YJ.js} +3 -3
  4. package/dist/chunk-2DZQF6YJ.js.map +1 -0
  5. package/dist/{chunk-6GBLFQMA.js → chunk-5RPYBC2Q.js} +1 -1
  6. package/dist/chunk-5RPYBC2Q.js.map +1 -0
  7. package/dist/{chunk-DQJTNXVS.cjs → chunk-6XAAYAWL.cjs} +142 -3
  8. package/dist/chunk-6XAAYAWL.cjs.map +1 -0
  9. package/dist/{chunk-HC2SEH6I.js → chunk-7S3M4N4E.js} +939 -946
  10. package/dist/chunk-7S3M4N4E.js.map +1 -0
  11. package/dist/{chunk-4C7SBZNW.js → chunk-BNU5QGIZ.js} +2 -2
  12. package/dist/chunk-BNU5QGIZ.js.map +1 -0
  13. package/dist/{chunk-63ASYC4N.js → chunk-D35VBACN.js} +3 -3
  14. package/dist/chunk-D35VBACN.js.map +1 -0
  15. package/dist/chunk-DCZVOIEO.cjs.map +1 -1
  16. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  17. package/dist/{chunk-L3I4TIRP.js → chunk-HMUEU7D7.js} +2 -2
  18. package/dist/chunk-HMUEU7D7.js.map +1 -0
  19. package/dist/{chunk-5CJGKKMZ.js → chunk-MEPHGCPQ.js} +1 -1
  20. package/dist/chunk-MEPHGCPQ.js.map +1 -0
  21. package/dist/chunk-MOL7MDBG.js +0 -0
  22. package/dist/{chunk-HOGJ5ALY.js → chunk-OQPILS7B.js} +142 -3
  23. package/dist/chunk-OQPILS7B.js.map +1 -0
  24. package/dist/{chunk-KA4FEBS2.js → chunk-RROH5WHO.js} +2 -2
  25. package/dist/chunk-RROH5WHO.js.map +1 -0
  26. package/dist/{chunk-UVSOSFER.js → chunk-UEIYETCQ.js} +142 -3
  27. package/dist/chunk-UEIYETCQ.js.map +1 -0
  28. package/dist/cli.js +15 -15
  29. package/dist/cli.js.map +1 -1
  30. package/dist/{detect-PJZMUL2Z.js → detect-RI2MQ33K.js} +2 -2
  31. package/dist/formula-5NKVS2LR.cjs.map +1 -1
  32. package/dist/formula-JCNF43NE.js +0 -0
  33. package/dist/index.cjs +1248 -1255
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +1 -1
  36. package/dist/index.d.ts +1 -1
  37. package/dist/index.js +925 -932
  38. package/dist/index.js.map +1 -1
  39. package/dist/mcp.js +13 -13
  40. package/dist/mcp.js.map +1 -1
  41. package/dist/page-range-737B4EZW.js +0 -0
  42. package/dist/page-range-P7SDW6LR.cjs.map +1 -1
  43. package/dist/{parser-VEY4B5CJ.cjs → parser-ITMU2WN5.cjs} +231 -37
  44. package/dist/parser-ITMU2WN5.cjs.map +1 -0
  45. package/dist/{parser-DMKHIV4E.js → parser-KMMUS73Q.js} +200 -6
  46. package/dist/parser-KMMUS73Q.js.map +1 -0
  47. package/dist/{parser-C636QIOB.js → parser-TCTCSBYZ.js} +202 -8
  48. package/dist/parser-TCTCSBYZ.js.map +1 -0
  49. package/dist/{profile-io-JYGCC6XQ.js → profile-io-SLN4P76T.js} +3 -3
  50. package/dist/{provider-H4WWSPOV.js → provider-4ZJKV3DC.js} +1 -1
  51. package/dist/provider-4ZJKV3DC.js.map +1 -0
  52. package/dist/{provider-7H4CPZYS.js → provider-AKROB7WQ.js} +1 -1
  53. package/dist/provider-AKROB7WQ.js.map +1 -0
  54. package/dist/{provider-5K7O3Z2O.cjs → provider-G4C2V2PD.cjs} +1 -1
  55. package/dist/provider-G4C2V2PD.cjs.map +1 -0
  56. package/dist/render-25BT623I.js +10 -0
  57. package/dist/seal-R4TETA4C.js +10 -0
  58. package/dist/setup-57FB3LSP.js +0 -0
  59. package/dist/{watch-ZQUFJBFR.js → watch-OHQWSVPE.js} +8 -8
  60. package/dist/watch-OHQWSVPE.js.map +1 -0
  61. package/package.json +97 -97
  62. package/dist/chunk-4C7SBZNW.js.map +0 -1
  63. package/dist/chunk-5CJGKKMZ.js.map +0 -1
  64. package/dist/chunk-5SOZXPQY.js.map +0 -1
  65. package/dist/chunk-63ASYC4N.js.map +0 -1
  66. package/dist/chunk-6GBLFQMA.js.map +0 -1
  67. package/dist/chunk-DQJTNXVS.cjs.map +0 -1
  68. package/dist/chunk-HC2SEH6I.js.map +0 -1
  69. package/dist/chunk-HOGJ5ALY.js.map +0 -1
  70. package/dist/chunk-KA4FEBS2.js.map +0 -1
  71. package/dist/chunk-L3I4TIRP.js.map +0 -1
  72. package/dist/chunk-UVSOSFER.js.map +0 -1
  73. package/dist/parser-C636QIOB.js.map +0 -1
  74. package/dist/parser-DMKHIV4E.js.map +0 -1
  75. package/dist/parser-VEY4B5CJ.cjs.map +0 -1
  76. package/dist/provider-5K7O3Z2O.cjs.map +0 -1
  77. package/dist/provider-7H4CPZYS.js.map +0 -1
  78. package/dist/provider-H4WWSPOV.js.map +0 -1
  79. package/dist/render-ISOEOMTM.js +0 -10
  80. package/dist/seal-676ZIAZZ.js +0 -10
  81. package/dist/watch-ZQUFJBFR.js.map +0 -1
  82. /package/dist/{-NDU7YGSS.js.map → -LE4RLXVA.js.map} +0 -0
  83. /package/dist/{detect-PJZMUL2Z.js.map → detect-RI2MQ33K.js.map} +0 -0
  84. /package/dist/{profile-io-JYGCC6XQ.js.map → profile-io-SLN4P76T.js.map} +0 -0
  85. /package/dist/{render-ISOEOMTM.js.map → render-25BT623I.js.map} +0 -0
  86. /package/dist/{seal-676ZIAZZ.js.map → seal-R4TETA4C.js.map} +0 -0
@@ -6,7 +6,8 @@
6
6
 
7
7
 
8
8
 
9
- var _chunkDQJTNXVScjs = require('./chunk-DQJTNXVS.cjs');
9
+
10
+ var _chunk6XAAYAWLcjs = require('./chunk-6XAAYAWL.cjs');
10
11
 
11
12
 
12
13
  var _chunkDCZVOIEOcjs = require('./chunk-DCZVOIEO.cjs');
@@ -1223,10 +1224,180 @@ function normalizeUndersegmentedTable(originalCells, colXs, items) {
1223
1224
  return rebuilt;
1224
1225
  }
1225
1226
 
1227
+ // src/pdf/image-extract.ts
1228
+
1229
+ var IMAGE_RESOLVE_TIMEOUT_MS = 5e3;
1230
+ function resolveImgData(page, objId) {
1231
+ const store = objId.startsWith("g_") ? page.commonObjs : page.objs;
1232
+ return new Promise((resolve) => {
1233
+ let done = false;
1234
+ const timer = setTimeout(() => {
1235
+ if (!done) {
1236
+ done = true;
1237
+ resolve(null);
1238
+ }
1239
+ }, IMAGE_RESOLVE_TIMEOUT_MS);
1240
+ try {
1241
+ store.get(objId, (data) => {
1242
+ if (!done) {
1243
+ done = true;
1244
+ clearTimeout(timer);
1245
+ resolve(_nullishCoalesce(data, () => ( null)));
1246
+ }
1247
+ });
1248
+ } catch (e2) {
1249
+ if (!done) {
1250
+ done = true;
1251
+ clearTimeout(timer);
1252
+ resolve(null);
1253
+ }
1254
+ }
1255
+ });
1256
+ }
1257
+ var MIN_DIM = 8;
1258
+ var MAX_PIXELS = 36e6;
1259
+ var MAX_IMAGES_PER_DOC = 200;
1260
+ var MAX_TOTAL_IMAGE_BYTES = 128 * 1024 * 1024;
1261
+ function createPdfImageState() {
1262
+ return { imageIndex: 0, totalBytes: 0, seen: /* @__PURE__ */ new Map(), capWarned: false };
1263
+ }
1264
+ function fnv1a(data) {
1265
+ let h = 2166136261;
1266
+ for (let i = 0; i < data.length; i++) {
1267
+ h ^= data[i];
1268
+ h = Math.imul(h, 16777619);
1269
+ }
1270
+ return h >>> 0;
1271
+ }
1272
+ function toRgba(img) {
1273
+ const { width: w, height: h, kind, data } = img;
1274
+ if (!data || !w || !h) return null;
1275
+ const rgba = new Uint8Array(w * h * 4);
1276
+ if (kind === _pdfmjs.ImageKind.RGBA_32BPP) {
1277
+ if (data.length < w * h * 4) return null;
1278
+ rgba.set(data.subarray(0, w * h * 4));
1279
+ return rgba;
1280
+ }
1281
+ if (kind === _pdfmjs.ImageKind.RGB_24BPP) {
1282
+ if (data.length < w * h * 3) return null;
1283
+ for (let i = 0, s = 0, d = 0; i < w * h; i++, s += 3, d += 4) {
1284
+ rgba[d] = data[s];
1285
+ rgba[d + 1] = data[s + 1];
1286
+ rgba[d + 2] = data[s + 2];
1287
+ rgba[d + 3] = 255;
1288
+ }
1289
+ return rgba;
1290
+ }
1291
+ if (kind === _pdfmjs.ImageKind.GRAYSCALE_1BPP) {
1292
+ const stride = w + 7 >> 3;
1293
+ if (data.length < stride * h) return null;
1294
+ for (let y = 0; y < h; y++) {
1295
+ for (let x = 0; x < w; x++) {
1296
+ const bit = data[y * stride + (x >> 3)] >> 7 - (x & 7) & 1;
1297
+ const v = bit ? 255 : 0;
1298
+ const d = (y * w + x) * 4;
1299
+ rgba[d] = v;
1300
+ rgba[d + 1] = v;
1301
+ rgba[d + 2] = v;
1302
+ rgba[d + 3] = 255;
1303
+ }
1304
+ }
1305
+ return rgba;
1306
+ }
1307
+ return null;
1308
+ }
1309
+ async function extractPageImages(page, fnArray, argsArray, pageNumber, state, warnings) {
1310
+ const blocks = [];
1311
+ const images = [];
1312
+ const pageSeenIds = /* @__PURE__ */ new Set();
1313
+ for (let i = 0; i < fnArray.length; i++) {
1314
+ const op = fnArray[i];
1315
+ let imgData = null;
1316
+ let dedupeId = null;
1317
+ if (op === _pdfmjs.OPS.paintImageXObject || op === _pdfmjs.OPS.paintImageXObjectRepeat) {
1318
+ const objId = _optionalChain([argsArray, 'access', _4 => _4[i], 'optionalAccess', _5 => _5[0]]);
1319
+ if (typeof objId !== "string" || pageSeenIds.has(objId)) continue;
1320
+ pageSeenIds.add(objId);
1321
+ dedupeId = objId;
1322
+ imgData = await resolveImgData(page, objId);
1323
+ } else if (op === _pdfmjs.OPS.paintInlineImageXObject) {
1324
+ imgData = _optionalChain([argsArray, 'access', _6 => _6[i], 'optionalAccess', _7 => _7[0]]);
1325
+ } else {
1326
+ continue;
1327
+ }
1328
+ if (!_optionalChain([imgData, 'optionalAccess', _8 => _8.data]) || !imgData.width || !imgData.height) continue;
1329
+ const { width: w, height: h } = imgData;
1330
+ if (w < MIN_DIM || h < MIN_DIM) continue;
1331
+ if (w * h > MAX_PIXELS) {
1332
+ warnings.push({ page: pageNumber, message: `\uC774\uBBF8\uC9C0 \uD06C\uAE30 \uCD08\uACFC\uB85C \uCD94\uCD9C \uC0DD\uB7B5 (${w}\xD7${h})`, code: "SKIPPED_IMAGE" });
1333
+ continue;
1334
+ }
1335
+ const hash = `${w}x${h}k${_nullishCoalesce(imgData.kind, () => ( "?"))}h${fnv1a(imgData.data)}${dedupeId ? "" : "inline"}`;
1336
+ if (state.seen.has(hash)) continue;
1337
+ if (state.imageIndex >= MAX_IMAGES_PER_DOC || state.totalBytes >= MAX_TOTAL_IMAGE_BYTES) {
1338
+ if (!state.capWarned) {
1339
+ state.capWarned = true;
1340
+ 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" });
1341
+ }
1342
+ continue;
1343
+ }
1344
+ const rgba = toRgba(imgData);
1345
+ if (!rgba) continue;
1346
+ const png = _chunk6XAAYAWLcjs.encodePng.call(void 0, w, h, rgba);
1347
+ state.imageIndex++;
1348
+ state.totalBytes += png.length;
1349
+ const filename = `image_${String(state.imageIndex).padStart(3, "0")}.png`;
1350
+ state.seen.set(hash, filename);
1351
+ images.push({ filename, data: png, mimeType: "image/png" });
1352
+ blocks.push({ type: "image", text: filename, pageNumber });
1353
+ }
1354
+ return { blocks, images };
1355
+ }
1356
+ function injectPageImageBlocks(blocks, pageImages) {
1357
+ if (pageImages.size === 0) return;
1358
+ const lastIndexForPage = /* @__PURE__ */ new Map();
1359
+ for (let i = 0; i < blocks.length; i++) {
1360
+ const p = blocks[i].pageNumber;
1361
+ if (p !== void 0) lastIndexForPage.set(p, i);
1362
+ }
1363
+ const pageAtIndex = /* @__PURE__ */ new Map();
1364
+ for (const [p, last] of lastIndexForPage) pageAtIndex.set(last, p);
1365
+ const result = [];
1366
+ const injected = /* @__PURE__ */ new Set();
1367
+ for (let i = 0; i < blocks.length; i++) {
1368
+ result.push(blocks[i]);
1369
+ const p = pageAtIndex.get(i);
1370
+ if (p !== void 0 && pageImages.has(p)) {
1371
+ result.push(...pageImages.get(p));
1372
+ injected.add(p);
1373
+ }
1374
+ }
1375
+ for (const p of [...pageImages.keys()].sort((a, b) => a - b)) {
1376
+ if (injected.has(p)) continue;
1377
+ let at = result.length;
1378
+ for (let i = 0; i < result.length; i++) {
1379
+ const bp = result[i].pageNumber;
1380
+ if (bp !== void 0 && bp > p) {
1381
+ at = i;
1382
+ break;
1383
+ }
1384
+ }
1385
+ result.splice(at, 0, ...pageImages.get(p));
1386
+ }
1387
+ blocks.length = 0;
1388
+ blocks.push(...result);
1389
+ }
1390
+
1226
1391
  // src/pdf/quality.ts
1392
+ var RARE_JONG = /* @__PURE__ */ new Set([3, 5, 6, 9, 10, 11, 12, 13, 14, 15, 18, 24, 25, 26]);
1393
+ var MOJIBAKE_MIN_HANGUL = 30;
1394
+ var MOJIBAKE_MAX_NOBATCHIM = 0.15;
1395
+ var MOJIBAKE_MIN_RAREBATCHIM = 0.25;
1227
1396
  function computePageQuality(page, text) {
1228
1397
  let total = 0;
1229
1398
  let hangul = 0;
1399
+ let hangulNoBatchim = 0;
1400
+ let hangulRareBatchim = 0;
1230
1401
  let control = 0;
1231
1402
  let replacement = 0;
1232
1403
  let pua = 0;
@@ -1244,6 +1415,9 @@ function computePageQuality(page, text) {
1244
1415
  }
1245
1416
  if (code >= 44032 && code <= 55203) {
1246
1417
  hangul++;
1418
+ const jong = (code - 44032) % 28;
1419
+ if (jong === 0) hangulNoBatchim++;
1420
+ else if (RARE_JONG.has(jong)) hangulRareBatchim++;
1247
1421
  continue;
1248
1422
  }
1249
1423
  if (code >= 57344 && code <= 63743 || code >= 56192 && code <= 56319) {
@@ -1255,6 +1429,9 @@ function computePageQuality(page, text) {
1255
1429
  const puaRatio = pua / denom;
1256
1430
  const controlCharRatio = control / denom;
1257
1431
  const replacementCharRatio = replacement / denom;
1432
+ const hangulNoBatchimRatio = hangul > 0 ? hangulNoBatchim / hangul : 0;
1433
+ const hangulRareBatchimRatio = hangul > 0 ? hangulRareBatchim / hangul : 0;
1434
+ const garbledHangul = hangul >= MOJIBAKE_MIN_HANGUL && hangulNoBatchimRatio < MOJIBAKE_MAX_NOBATCHIM && hangulRareBatchimRatio >= MOJIBAKE_MIN_RAREBATCHIM;
1258
1435
  let needsOcr = false;
1259
1436
  let ocrReason;
1260
1437
  if (total < LOW_TEXT_THRESHOLD) {
@@ -1269,6 +1446,9 @@ function computePageQuality(page, text) {
1269
1446
  } else if (replacementCharRatio >= HIGH_REPLACEMENT_THRESHOLD) {
1270
1447
  needsOcr = true;
1271
1448
  ocrReason = "high_replacement";
1449
+ } else if (garbledHangul) {
1450
+ needsOcr = true;
1451
+ ocrReason = "garbled_hangul";
1272
1452
  }
1273
1453
  return {
1274
1454
  page,
@@ -1277,6 +1457,8 @@ function computePageQuality(page, text) {
1277
1457
  controlCharRatio,
1278
1458
  replacementCharRatio,
1279
1459
  puaRatio,
1460
+ hangulNoBatchimRatio,
1461
+ hangulRareBatchimRatio,
1280
1462
  needsOcr,
1281
1463
  ocrReason
1282
1464
  };
@@ -1391,7 +1573,7 @@ function dominantStyle(items) {
1391
1573
  }
1392
1574
  }
1393
1575
  if (dominantSize === 0) return void 0;
1394
- const fontName = _optionalChain([items, 'access', _4 => _4.find, 'call', _5 => _5((i) => i.fontSize === dominantSize), 'optionalAccess', _6 => _6.fontName]) || void 0;
1576
+ const fontName = _optionalChain([items, 'access', _9 => _9.find, 'call', _10 => _10((i) => i.fontSize === dominantSize), 'optionalAccess', _11 => _11.fontName]) || void 0;
1395
1577
  return fontName ? { fontSize: dominantSize, fontName } : { fontSize: dominantSize };
1396
1578
  }
1397
1579
  function normalizeItems(rawItems) {
@@ -1512,7 +1694,7 @@ function mergeSuperscriptLines(lines) {
1512
1694
  return result;
1513
1695
  }
1514
1696
  function mergeLineSimple(items) {
1515
- if (items.length <= 1) return _optionalChain([items, 'access', _7 => _7[0], 'optionalAccess', _8 => _8.text]) || "";
1697
+ if (items.length <= 1) return _optionalChain([items, 'access', _12 => _12[0], 'optionalAccess', _13 => _13.text]) || "";
1516
1698
  const sorted = [...items].sort((a, b) => a.x - b.x);
1517
1699
  const isEvenSpaced = detectEvenSpacedItems(sorted);
1518
1700
  let result = sorted[0].text;
@@ -1599,12 +1781,12 @@ function isTwoColumnProse(r) {
1599
1781
  if (t.rows < 8) return false;
1600
1782
  const dense = [];
1601
1783
  for (let c = 0; c < t.cols; c++) {
1602
- const filled = t.cells.filter((row) => _optionalChain([row, 'access', _9 => _9[c], 'optionalAccess', _10 => _10.text, 'access', _11 => _11.trim, 'call', _12 => _12()])).length;
1784
+ const filled = t.cells.filter((row) => _optionalChain([row, 'access', _14 => _14[c], 'optionalAccess', _15 => _15.text, 'access', _16 => _16.trim, 'call', _17 => _17()])).length;
1603
1785
  if (filled / t.rows >= 0.3) dense.push(c);
1604
1786
  }
1605
1787
  if (dense.length !== 2) return false;
1606
1788
  for (const c of dense) {
1607
- const lens = t.cells.map((row) => _nullishCoalesce(_optionalChain([row, 'access', _13 => _13[c], 'optionalAccess', _14 => _14.text, 'access', _15 => _15.replace, 'call', _16 => _16(/\s+/g, ""), 'access', _17 => _17.length]), () => ( 0))).filter((n) => n > 0);
1789
+ const lens = t.cells.map((row) => _nullishCoalesce(_optionalChain([row, 'access', _18 => _18[c], 'optionalAccess', _19 => _19.text, 'access', _20 => _20.replace, 'call', _21 => _21(/\s+/g, ""), 'access', _22 => _22.length]), () => ( 0))).filter((n) => n > 0);
1608
1790
  const avg = lens.reduce((s, v) => s + v, 0) / (lens.length || 1);
1609
1791
  if (avg < 12) return false;
1610
1792
  }
@@ -2081,7 +2263,7 @@ function buildClusterTable(rows, columns, pageNum) {
2081
2263
  const nonEmptyCols = cells[r].filter((c) => c.text.trim()).length;
2082
2264
  if (nonEmptyCols !== 1) continue;
2083
2265
  if (cells[r][0].text.trim() !== "") continue;
2084
- const contentText = _optionalChain([cells, 'access', _18 => _18[r], 'access', _19 => _19.find, 'call', _20 => _20((c) => c.text.trim()), 'optionalAccess', _21 => _21.text, 'access', _22 => _22.trim, 'call', _23 => _23()]) || "";
2266
+ const contentText = _optionalChain([cells, 'access', _23 => _23[r], 'access', _24 => _24.find, 'call', _25 => _25((c) => c.text.trim()), 'optionalAccess', _26 => _26.text, 'access', _27 => _27.trim, 'call', _28 => _28()]) || "";
2085
2267
  if (/^[○●▶\-·]/.test(contentText)) continue;
2086
2268
  for (let pr = r - 1; pr >= 0; pr--) {
2087
2269
  if (cells[pr].some((c) => c.text.trim())) {
@@ -2303,14 +2485,14 @@ function isProseSpread(items) {
2303
2485
  for (let i = 1; i < sorted.length; i++) {
2304
2486
  gaps.push(sorted[i].x - (sorted[i - 1].x + sorted[i - 1].w));
2305
2487
  }
2306
- const maxGap = _chunkDQJTNXVScjs.safeMax.call(void 0, gaps);
2488
+ const maxGap = _chunk6XAAYAWLcjs.safeMax.call(void 0, gaps);
2307
2489
  const avgLen = items.reduce((s, i) => s + i.text.length, 0) / items.length;
2308
2490
  return maxGap < 40 && avgLen < 5;
2309
2491
  }
2310
2492
  function detectColumns(yLines) {
2311
2493
  const allItems = yLines.flat();
2312
2494
  if (allItems.length === 0) return null;
2313
- const pageWidth = _chunkDQJTNXVScjs.safeMax.call(void 0, allItems.map((i) => i.x + i.w)) - _chunkDQJTNXVScjs.safeMin.call(void 0, allItems.map((i) => i.x));
2495
+ const pageWidth = _chunk6XAAYAWLcjs.safeMax.call(void 0, allItems.map((i) => i.x + i.w)) - _chunk6XAAYAWLcjs.safeMin.call(void 0, allItems.map((i) => i.x));
2314
2496
  if (pageWidth < 100) return null;
2315
2497
  let bigoLineIdx = -1;
2316
2498
  for (let i = 0; i < yLines.length; i++) {
@@ -2526,15 +2708,15 @@ function computeMedianFontSizeFromFreq(freq) {
2526
2708
  }
2527
2709
  function detectHeadings(blocks, medianFontSize) {
2528
2710
  for (const block of blocks) {
2529
- if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _24 => _24.style, 'optionalAccess', _25 => _25.fontSize])) continue;
2711
+ if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _29 => _29.style, 'optionalAccess', _30 => _30.fontSize])) continue;
2530
2712
  const text = block.text.trim();
2531
2713
  if (text.length === 0 || text.length > 200) continue;
2532
2714
  if (/^\d+$/.test(text)) continue;
2533
2715
  const ratio = block.style.fontSize / medianFontSize;
2534
2716
  let level = 0;
2535
- if (ratio >= _chunkDQJTNXVScjs.HEADING_RATIO_H1) level = 1;
2536
- else if (ratio >= _chunkDQJTNXVScjs.HEADING_RATIO_H2) level = 2;
2537
- else if (ratio >= _chunkDQJTNXVScjs.HEADING_RATIO_H3) level = 3;
2717
+ if (ratio >= _chunk6XAAYAWLcjs.HEADING_RATIO_H1) level = 1;
2718
+ else if (ratio >= _chunk6XAAYAWLcjs.HEADING_RATIO_H2) level = 2;
2719
+ else if (ratio >= _chunk6XAAYAWLcjs.HEADING_RATIO_H3) level = 3;
2538
2720
  if (level > 0) {
2539
2721
  block.type = "heading";
2540
2722
  block.level = level;
@@ -2587,7 +2769,7 @@ function detectMarkerHeadings(blocks) {
2587
2769
  block.level = 4;
2588
2770
  continue;
2589
2771
  }
2590
- if (/^[가-힣]{2,6}$/.test(text) && _optionalChain([block, 'access', _26 => _26.style, 'optionalAccess', _27 => _27.fontSize])) {
2772
+ if (/^[가-힣]{2,6}$/.test(text) && _optionalChain([block, 'access', _31 => _31.style, 'optionalAccess', _32 => _32.fontSize])) {
2591
2773
  const prev = blocks[i - 1];
2592
2774
  const next = blocks[i + 1];
2593
2775
  const prevIsStructural = !prev || prev.type === "table" || prev.type === "heading" || prev.type === "separator";
@@ -2840,7 +3022,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings) {
2840
3022
  const bottomEntries = [];
2841
3023
  for (let bi = 0; bi < blocks.length; bi++) {
2842
3024
  const b = blocks[bi];
2843
- if (!b.bbox || !b.pageNumber || !_optionalChain([b, 'access', _28 => _28.text, 'optionalAccess', _29 => _29.trim, 'call', _30 => _30()])) continue;
3025
+ if (!b.bbox || !b.pageNumber || !_optionalChain([b, 'access', _33 => _33.text, 'optionalAccess', _34 => _34.trim, 'call', _35 => _35()])) continue;
2844
3026
  const ph = pageHeights.get(b.bbox.page) || pageHeights.get(b.pageNumber);
2845
3027
  if (!ph) continue;
2846
3028
  const blockTop = ph - (b.bbox.y + b.bbox.height);
@@ -2863,7 +3045,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings) {
2863
3045
  }
2864
3046
  const repeatedPatterns = /* @__PURE__ */ new Set();
2865
3047
  for (const [p, count] of patternCount) {
2866
- if (count >= MIN_REPEAT && (_nullishCoalesce(_optionalChain([patternPages, 'access', _31 => _31.get, 'call', _32 => _32(p), 'optionalAccess', _33 => _33.size]), () => ( 0))) >= MIN_REPEAT) {
3048
+ if (count >= MIN_REPEAT && (_nullishCoalesce(_optionalChain([patternPages, 'access', _36 => _36.get, 'call', _37 => _37(p), 'optionalAccess', _38 => _38.size]), () => ( 0))) >= MIN_REPEAT) {
2867
3049
  repeatedPatterns.add(p);
2868
3050
  }
2869
3051
  }
@@ -3111,7 +3293,7 @@ function extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals) {
3111
3293
  }
3112
3294
  if (remaining.length > 0) {
3113
3295
  const allY = remaining.map((i) => i.y);
3114
- const pageH = _chunkDQJTNXVScjs.safeMax.call(void 0, allY) - _chunkDQJTNXVScjs.safeMin.call(void 0, allY);
3296
+ const pageH = _chunk6XAAYAWLcjs.safeMax.call(void 0, allY) - _chunk6XAAYAWLcjs.safeMin.call(void 0, allY);
3115
3297
  const groups = xyCutOrder(remaining, Math.max(15, pageH * 0.03));
3116
3298
  const textBlocks = [];
3117
3299
  for (const group of groups) {
@@ -3287,7 +3469,7 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false) {
3287
3469
  blocks.push({ type: "paragraph", text: tableText, pageNumber: pageNum, bbox, style: dominantStyle(items) });
3288
3470
  } else {
3289
3471
  const allY = items.map((i) => i.y);
3290
- const pageHeight = _chunkDQJTNXVScjs.safeMax.call(void 0, allY) - _chunkDQJTNXVScjs.safeMin.call(void 0, allY);
3472
+ const pageHeight = _chunk6XAAYAWLcjs.safeMax.call(void 0, allY) - _chunk6XAAYAWLcjs.safeMin.call(void 0, allY);
3291
3473
  const gapThreshold = Math.max(15, pageHeight * 0.03);
3292
3474
  const orderedGroups = proseCutX !== null ? splitTwoColumnProse(items, proseCutX) : xyCutOrder(items, gapThreshold);
3293
3475
  for (const group of orderedGroups) {
@@ -3523,7 +3705,7 @@ try {
3523
3705
  pdfjsAssets.cMapUrl = _path.join.call(void 0, pkgDir, "cmaps") + "/";
3524
3706
  pdfjsAssets.cMapPacked = true;
3525
3707
  pdfjsAssets.standardFontDataUrl = _path.join.call(void 0, pkgDir, "standard_fonts") + "/";
3526
- } catch (e2) {
3708
+ } catch (e3) {
3527
3709
  }
3528
3710
  async function loadPdfWithTimeout(buffer) {
3529
3711
  const loadingTask = _pdfmjs.getDocument.call(void 0, {
@@ -3540,7 +3722,7 @@ async function loadPdfWithTimeout(buffer) {
3540
3722
  new Promise((_, reject) => {
3541
3723
  timer = setTimeout(() => {
3542
3724
  loadingTask.destroy();
3543
- reject(new (0, _chunkDQJTNXVScjs.KordocError)("PDF \uB85C\uB529 \uD0C0\uC784\uC544\uC6C3 (30\uCD08 \uCD08\uACFC)"));
3725
+ reject(new (0, _chunk6XAAYAWLcjs.KordocError)("PDF \uB85C\uB529 \uD0C0\uC784\uC544\uC6C3 (30\uCD08 \uCD08\uACFC)"));
3544
3726
  }, PDF_LOAD_TIMEOUT_MS);
3545
3727
  })
3546
3728
  ]);
@@ -3549,11 +3731,11 @@ async function loadPdfWithTimeout(buffer) {
3549
3731
  }
3550
3732
  }
3551
3733
  async function parsePdfDocument(buffer, options) {
3552
- const formulaBuffer = _optionalChain([options, 'optionalAccess', _34 => _34.formulaOcr]) ? buffer.slice(0) : null;
3734
+ const formulaBuffer = _optionalChain([options, 'optionalAccess', _39 => _39.formulaOcr]) ? buffer.slice(0) : null;
3553
3735
  const doc = await loadPdfWithTimeout(buffer);
3554
3736
  try {
3555
3737
  const pageCount = doc.numPages;
3556
- if (pageCount === 0) throw new (0, _chunkDQJTNXVScjs.KordocError)("PDF\uC5D0 \uD398\uC774\uC9C0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.");
3738
+ if (pageCount === 0) throw new (0, _chunk6XAAYAWLcjs.KordocError)("PDF\uC5D0 \uD398\uC774\uC9C0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.");
3557
3739
  const metadata = { pageCount };
3558
3740
  await extractPdfMetadata(doc, metadata);
3559
3741
  const blocks = [];
@@ -3562,12 +3744,15 @@ async function parsePdfDocument(buffer, options) {
3562
3744
  let totalChars = 0;
3563
3745
  let totalTextBytes = 0;
3564
3746
  const effectivePageCount = Math.min(pageCount, MAX_PAGES);
3565
- const pageFilter = _optionalChain([options, 'optionalAccess', _35 => _35.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, effectivePageCount) : null;
3747
+ const pageFilter = _optionalChain([options, 'optionalAccess', _40 => _40.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, effectivePageCount) : null;
3566
3748
  const totalTarget = pageFilter ? pageFilter.size : effectivePageCount;
3567
3749
  const fontSizeFreq = /* @__PURE__ */ new Map();
3568
3750
  const pageHeights = /* @__PURE__ */ new Map();
3569
3751
  const pagesWithLargeImage = /* @__PURE__ */ new Set();
3570
3752
  const skippedImagePages = /* @__PURE__ */ new Map();
3753
+ const imageState = createPdfImageState();
3754
+ const extractedImages = [];
3755
+ const pageImageBlocks = /* @__PURE__ */ new Map();
3571
3756
  let parsedPages = 0;
3572
3757
  for (let i = 1; i <= effectivePageCount; i++) {
3573
3758
  if (pageFilter && !pageFilter.has(i)) continue;
@@ -3605,6 +3790,12 @@ async function parsePdfDocument(buffer, options) {
3605
3790
  }
3606
3791
  const pageBlocks = extractPageBlocksWithLines(visible, i, opList, viewport.width, viewport.height);
3607
3792
  for (const b of pageBlocks) blocks.push(b);
3793
+ try {
3794
+ const { blocks: imgBlocks, images: pageImages } = await extractPageImages(page, opList.fnArray, opList.argsArray, i, imageState, warnings);
3795
+ if (imgBlocks.length > 0) pageImageBlocks.set(i, imgBlocks);
3796
+ extractedImages.push(...pageImages);
3797
+ } catch (e4) {
3798
+ }
3608
3799
  let pageText = "";
3609
3800
  for (const b of pageBlocks) {
3610
3801
  const t = b.text || "";
@@ -3613,26 +3804,26 @@ async function parsePdfDocument(buffer, options) {
3613
3804
  pageText += pageText ? "\n" + t : t;
3614
3805
  }
3615
3806
  pageQuality.push(computePageQuality(i, pageText));
3616
- if (totalTextBytes > MAX_TOTAL_TEXT) throw new (0, _chunkDQJTNXVScjs.KordocError)("\uD14D\uC2A4\uD2B8 \uCD94\uCD9C \uD06C\uAE30 \uCD08\uACFC");
3807
+ if (totalTextBytes > MAX_TOTAL_TEXT) throw new (0, _chunk6XAAYAWLcjs.KordocError)("\uD14D\uC2A4\uD2B8 \uCD94\uCD9C \uD06C\uAE30 \uCD08\uACFC");
3617
3808
  parsedPages++;
3618
- _optionalChain([options, 'optionalAccess', _36 => _36.onProgress, 'optionalCall', _37 => _37(parsedPages, totalTarget)]);
3809
+ _optionalChain([options, 'optionalAccess', _41 => _41.onProgress, 'optionalCall', _42 => _42(parsedPages, totalTarget)]);
3619
3810
  } catch (pageErr) {
3620
- if (pageErr instanceof _chunkDQJTNXVScjs.KordocError) throw pageErr;
3811
+ if (pageErr instanceof _chunk6XAAYAWLcjs.KordocError) throw pageErr;
3621
3812
  warnings.push({ page: i, message: `\uD398\uC774\uC9C0 ${i} \uD30C\uC2F1 \uC2E4\uD328: ${pageErr instanceof Error ? pageErr.message : "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958"}`, code: "PARTIAL_PARSE" });
3622
3813
  }
3623
3814
  }
3624
3815
  const parsedPageCount = parsedPages || (pageFilter ? pageFilter.size : effectivePageCount);
3625
3816
  let isImageBased = false;
3626
3817
  if (totalChars / Math.max(parsedPageCount, 1) < 10) {
3627
- if (_optionalChain([options, 'optionalAccess', _38 => _38.ocr])) {
3818
+ if (_optionalChain([options, 'optionalAccess', _43 => _43.ocr])) {
3628
3819
  try {
3629
- const { ocrPages } = await Promise.resolve().then(() => _interopRequireWildcard(require("./provider-5K7O3Z2O.cjs")));
3820
+ const { ocrPages } = await Promise.resolve().then(() => _interopRequireWildcard(require("./provider-G4C2V2PD.cjs")));
3630
3821
  const ocrBlocks = await ocrPages(doc, options.ocr, pageFilter, effectivePageCount);
3631
3822
  if (ocrBlocks.length > 0) {
3632
3823
  const ocrMarkdown = ocrBlocks.map((b) => b.text || "").filter(Boolean).join("\n\n");
3633
- return { markdown: ocrMarkdown, blocks: ocrBlocks, metadata, warnings, isImageBased: true, pageQuality, qualitySummary: summarizeDocumentQuality(pageQuality) };
3824
+ return { markdown: ocrMarkdown, blocks: ocrBlocks, metadata, warnings, isImageBased: true, pageQuality, qualitySummary: summarizeDocumentQuality(pageQuality), images: extractedImages.length > 0 ? extractedImages : void 0 };
3634
3825
  }
3635
- } catch (e3) {
3826
+ } catch (e5) {
3636
3827
  }
3637
3828
  }
3638
3829
  isImageBased = true;
@@ -3646,7 +3837,8 @@ async function parsePdfDocument(buffer, options) {
3646
3837
  low_text: "\uD14D\uC2A4\uD2B8\uAC00 \uAC70\uC758 \uC5C6\uB294 \uD398\uC774\uC9C0 (\uC2A4\uCE94/\uC774\uBBF8\uC9C0 \uCD94\uC815)",
3647
3838
  high_pua: "\uAE00\uAF34 \uB9E4\uD551 \uC2E4\uD328 (PUA \uBE44\uC728 \uB192\uC74C) \u2014 \uCD94\uCD9C \uD14D\uC2A4\uD2B8 \uC2E0\uB8B0 \uBD88\uAC00",
3648
3839
  high_control: "\uC81C\uC5B4\uBB38\uC790 \uBE44\uC728 \uB192\uC74C \u2014 \uCD94\uCD9C \uD14D\uC2A4\uD2B8 \uC2E0\uB8B0 \uBD88\uAC00",
3649
- high_replacement: "\uB300\uCCB4\uBB38\uC790(U+FFFD) \uBE44\uC728 \uB192\uC74C \u2014 \uCD94\uCD9C \uD14D\uC2A4\uD2B8 \uC2E0\uB8B0 \uBD88\uAC00"
3840
+ high_replacement: "\uB300\uCCB4\uBB38\uC790(U+FFFD) \uBE44\uC728 \uB192\uC74C \u2014 \uCD94\uCD9C \uD14D\uC2A4\uD2B8 \uC2E0\uB8B0 \uBD88\uAC00",
3841
+ garbled_hangul: "\uAE00\uAF34 \uB9E4\uD551 \uC2E4\uD328 (\uD55C\uAE00 \uC790\uC18C \uBD84\uD3EC \uC774\uC0C1) \u2014 \uCD94\uCD9C \uD14D\uC2A4\uD2B8\uAC00 \uAE68\uC84C\uC744 \uC218 \uC788\uC74C"
3650
3842
  };
3651
3843
  for (const pq of pageQuality) {
3652
3844
  if (!pq.needsOcr || !pq.ocrReason) continue;
@@ -3659,14 +3851,15 @@ async function parsePdfDocument(buffer, options) {
3659
3851
  warnings.push({ page, message: `${count}\uAC1C \uC774\uBBF8\uC9C0 \uC601\uC5ED\uC5D0 \uCD94\uCD9C \uAC00\uB2A5\uD55C \uD14D\uC2A4\uD2B8 \uC5C6\uC74C (\uADF8\uB9BC/\uCC28\uD2B8/\uB3C4\uC7A5 \uB0B4\uC6A9 \uB204\uB77D \uAC00\uB2A5)`, code: "SKIPPED_IMAGE" });
3660
3852
  }
3661
3853
  }
3662
- if (_optionalChain([options, 'optionalAccess', _39 => _39.removeHeaderFooter]) !== false && parsedPageCount >= 3) {
3854
+ if (_optionalChain([options, 'optionalAccess', _44 => _44.removeHeaderFooter]) !== false && parsedPageCount >= 3) {
3663
3855
  const removed = removeHeaderFooterBlocks(blocks, pageHeights, warnings);
3664
3856
  for (let ri = removed.length - 1; ri >= 0; ri--) {
3665
3857
  blocks.splice(removed[ri], 1);
3666
3858
  }
3667
3859
  }
3668
3860
  mergeCrossPageTables(blocks);
3669
- if (_optionalChain([options, 'optionalAccess', _40 => _40.formulaOcr]) && formulaBuffer) {
3861
+ injectPageImageBlocks(blocks, pageImageBlocks);
3862
+ if (_optionalChain([options, 'optionalAccess', _45 => _45.formulaOcr]) && formulaBuffer) {
3670
3863
  try {
3671
3864
  await applyFormulaOcr(formulaBuffer, blocks, pageFilter, effectivePageCount, warnings, options.onProgress);
3672
3865
  } catch (e) {
@@ -3685,7 +3878,7 @@ async function parsePdfDocument(buffer, options) {
3685
3878
  detectKoreanListBlocks(blocks);
3686
3879
  const outline = blocks.filter((b) => b.type === "heading" && b.level && b.text).map((b) => ({ level: b.level, text: b.text, pageNumber: b.pageNumber }));
3687
3880
  sanitizeBlockControlChars(blocks);
3688
- let markdown = cleanPdfText(_chunkDQJTNXVScjs.blocksToMarkdown.call(void 0, blocks));
3881
+ let markdown = cleanPdfText(_chunk6XAAYAWLcjs.blocksToMarkdown.call(void 0, blocks));
3689
3882
  return {
3690
3883
  markdown,
3691
3884
  blocks,
@@ -3694,7 +3887,8 @@ async function parsePdfDocument(buffer, options) {
3694
3887
  warnings: warnings.length > 0 ? warnings : void 0,
3695
3888
  isImageBased: isImageBased || void 0,
3696
3889
  pageQuality,
3697
- qualitySummary: summarizeDocumentQuality(pageQuality)
3890
+ qualitySummary: summarizeDocumentQuality(pageQuality),
3891
+ images: extractedImages.length > 0 ? extractedImages : void 0
3698
3892
  };
3699
3893
  } finally {
3700
3894
  await doc.destroy().catch(() => {
@@ -3704,7 +3898,7 @@ async function parsePdfDocument(buffer, options) {
3704
3898
  async function extractPdfMetadata(doc, metadata) {
3705
3899
  try {
3706
3900
  const result = await doc.getMetadata();
3707
- if (!_optionalChain([result, 'optionalAccess', _41 => _41.info])) return;
3901
+ if (!_optionalChain([result, 'optionalAccess', _46 => _46.info])) return;
3708
3902
  const info = result.info;
3709
3903
  if (typeof info.Title === "string" && info.Title.trim()) metadata.title = info.Title.trim();
3710
3904
  if (typeof info.Author === "string" && info.Author.trim()) metadata.author = info.Author.trim();
@@ -3715,7 +3909,7 @@ async function extractPdfMetadata(doc, metadata) {
3715
3909
  }
3716
3910
  if (typeof info.CreationDate === "string") metadata.createdAt = parsePdfDate(info.CreationDate);
3717
3911
  if (typeof info.ModDate === "string") metadata.modifiedAt = parsePdfDate(info.ModDate);
3718
- } catch (e4) {
3912
+ } catch (e6) {
3719
3913
  }
3720
3914
  }
3721
3915
  function parsePdfDate(dateStr) {
@@ -3744,4 +3938,4 @@ async function extractPdfMetadataOnly(buffer) {
3744
3938
 
3745
3939
 
3746
3940
  exports.cleanPdfText = cleanPdfText; exports.detectKoreanListBlocks = detectKoreanListBlocks; exports.detectTableCaptions = detectTableCaptions; exports.extractPdfMetadataOnly = extractPdfMetadataOnly; exports.mergeCrossPageTables = mergeCrossPageTables; exports.parsePdfDocument = parsePdfDocument; exports.removeHeaderFooterBlocks = removeHeaderFooterBlocks;
3747
- //# sourceMappingURL=parser-VEY4B5CJ.cjs.map
3941
+ //# sourceMappingURL=parser-ITMU2WN5.cjs.map