kordoc 4.14.2 → 4.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/README.md +51 -6
  2. package/dist/{-AQKXLFIM.js → -Z4TJ3QGK.js} +13 -11
  3. package/dist/{chunk-QOMNEWCQ.cjs → chunk-5LAZQCUJ.cjs} +305 -31
  4. package/dist/chunk-5LAZQCUJ.cjs.map +1 -0
  5. package/dist/{chunk-7IAQ4HOK.js → chunk-6BWU6SQX.js} +1 -1
  6. package/dist/chunk-6BWU6SQX.js.map +1 -0
  7. package/dist/{chunk-FOJZNMMK.js → chunk-6CUIXJOC.js} +1 -1
  8. package/dist/chunk-6CUIXJOC.js.map +1 -0
  9. package/dist/{chunk-ZWD734EY.js → chunk-7SE4EZ45.js} +2 -2
  10. package/dist/{chunk-TSFS5VKD.js → chunk-D4U2TXDC.js} +332 -141
  11. package/dist/chunk-D4U2TXDC.js.map +1 -0
  12. package/dist/chunk-DPWWXUOG.js +2222 -0
  13. package/dist/chunk-DPWWXUOG.js.map +1 -0
  14. package/dist/{chunk-GDW4YP7K.js → chunk-GLSBEEZJ.js} +2 -2
  15. package/dist/{chunk-JQEFP45L.js → chunk-GUJ4Q73I.js} +2 -2
  16. package/dist/{chunk-ZWOFQRIB.js → chunk-HIJUKZHM.js} +3 -3
  17. package/dist/chunk-IMAAFSAX.cjs +1352 -0
  18. package/dist/chunk-IMAAFSAX.cjs.map +1 -0
  19. package/dist/{chunk-TNCKOL2O.js → chunk-LCW7SEPG.js} +2 -2
  20. package/dist/chunk-LFSQAMSM.js +1352 -0
  21. package/dist/chunk-LFSQAMSM.js.map +1 -0
  22. package/dist/chunk-MG6DJEX4.js +1299 -0
  23. package/dist/chunk-MG6DJEX4.js.map +1 -0
  24. package/dist/{chunk-QC5T6D4J.js → chunk-NLU6LBLY.js} +299 -25
  25. package/dist/chunk-NLU6LBLY.js.map +1 -0
  26. package/dist/{chunk-EQZI77PP.cjs → chunk-QEJUY6SK.cjs} +3 -3
  27. package/dist/{chunk-EQZI77PP.cjs.map → chunk-QEJUY6SK.cjs.map} +1 -1
  28. package/dist/{chunk-VQ5W4MYO.js → chunk-QIF2VXBQ.js} +298 -24
  29. package/dist/chunk-QIF2VXBQ.js.map +1 -0
  30. package/dist/{chunk-UET462HB.js → chunk-TITDJWVZ.js} +2 -2
  31. package/dist/{chunk-247ANM72.cjs → chunk-USHQCF5T.cjs} +870 -147
  32. package/dist/chunk-USHQCF5T.cjs.map +1 -0
  33. package/dist/{chunk-C7FQBSON.js → chunk-V3DX4DUF.js} +2 -2
  34. package/dist/{chunk-DOGPOY4B.js → chunk-VDN7LMPL.js} +2 -2
  35. package/dist/{chunk-EDNJLUSE.js → chunk-VJIL6PIL.js} +2 -2
  36. package/dist/{chunk-L7DMSMAG.cjs → chunk-VWUYVEFN.cjs} +1 -1
  37. package/dist/chunk-VWUYVEFN.cjs.map +1 -0
  38. package/dist/{chunk-HR2XNERB.cjs → chunk-WJHAU73B.cjs} +2 -2
  39. package/dist/{chunk-HR2XNERB.cjs.map → chunk-WJHAU73B.cjs.map} +1 -1
  40. package/dist/{chunk-NS55SM7A.js → chunk-WJJGW5PL.js} +2 -2
  41. package/dist/{chunk-EISO3POT.js → chunk-XVXHXQIO.js} +788 -194
  42. package/dist/chunk-XVXHXQIO.js.map +1 -0
  43. package/dist/{chunk-ILU76UF3.js → chunk-YAKC46HZ.js} +2 -2
  44. package/dist/chunk-YAKC46HZ.js.map +1 -0
  45. package/dist/{chunk-3DUADAY2.js → chunk-YAVHVFRY.js} +851 -128
  46. package/dist/chunk-YAVHVFRY.js.map +1 -0
  47. package/dist/{chunk-A7QC2ZVP.js → chunk-YT3GC62E.js} +851 -128
  48. package/dist/chunk-YT3GC62E.js.map +1 -0
  49. package/dist/chunks-CCMRL4MJ.js +10 -0
  50. package/dist/cli.js +228 -97
  51. package/dist/cli.js.map +1 -1
  52. package/dist/{formula-PJJ6S3Z2.cjs → formula-5LOVHAKE.cjs} +9 -9
  53. package/dist/{formula-PJJ6S3Z2.cjs.map → formula-5LOVHAKE.cjs.map} +1 -1
  54. package/dist/{formula-JGFTXWYT.js → formula-7RANCW5L.js} +3 -3
  55. package/dist/{formula-5S7WWXGH.js → formula-7UYJOVTB.js} +4 -4
  56. package/dist/{image-ocr-WCAYXLOA.js → image-ocr-I6JOCATS.js} +34 -16
  57. package/dist/image-ocr-I6JOCATS.js.map +1 -0
  58. package/dist/{image-ocr-ZTYAGV3W.cjs → image-ocr-NYBJEOH2.cjs} +36 -18
  59. package/dist/image-ocr-NYBJEOH2.cjs.map +1 -0
  60. package/dist/{image-ocr-FLIL7MGN.js → image-ocr-ZV6PDBUQ.js} +32 -14
  61. package/dist/image-ocr-ZV6PDBUQ.js.map +1 -0
  62. package/dist/index.cjs +4048 -1216
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +66 -28
  65. package/dist/index.d.ts +66 -28
  66. package/dist/index.js +3487 -655
  67. package/dist/index.js.map +1 -1
  68. package/dist/mcp.js +74 -53
  69. package/dist/mcp.js.map +1 -1
  70. package/dist/{model-bundle-FSPZZ2EM.js → model-bundle-2C5IYDLE.js} +5 -5
  71. package/dist/{models-CJPAQK5R.js → models-SEQZHZFT.js} +5 -5
  72. package/dist/{parser-SCUTZAIJ.js → parser-3FNXEP6T.js} +708 -250
  73. package/dist/parser-3FNXEP6T.js.map +1 -0
  74. package/dist/{parser-A4TMPJAM.js → parser-FJBJXRJK.js} +708 -250
  75. package/dist/parser-FJBJXRJK.js.map +1 -0
  76. package/dist/{parser-VCXE4I5A.cjs → parser-HVEKF73B.cjs} +733 -275
  77. package/dist/parser-HVEKF73B.cjs.map +1 -0
  78. package/dist/pdf-ocr-JRDBJ6TA.cjs +14 -0
  79. package/dist/{pdf-ocr-MBZZ57LD.cjs.map → pdf-ocr-JRDBJ6TA.cjs.map} +1 -1
  80. package/dist/pdf-ocr-UUBWBEHL.js +16 -0
  81. package/dist/pdf-ocr-VJSF2SQC.js +13 -0
  82. package/dist/{profile-io-LBM263K7.js → profile-io-RUFZOZO6.js} +3 -3
  83. package/dist/{rasterize-46RG4ZF6.js → rasterize-IOYXR5SI.js} +3 -3
  84. package/dist/redact-NMIKVHMP.js +18 -0
  85. package/dist/redact-doc-QBHNJ2BU.js +1284 -0
  86. package/dist/redact-doc-QBHNJ2BU.js.map +1 -0
  87. package/dist/{render-NGP5T24S.js → render-YZ2TEC3N.js} +7 -7
  88. package/dist/seal-ECV44TUH.js +10 -0
  89. package/dist/{setup-AU4OCHNH.js → setup-MPIEP6XT.js} +3 -3
  90. package/dist/visual-ICMOWUCR.js +19 -0
  91. package/dist/{watch-MKPUCPXM.js → watch-RYO7MN5B.js} +12 -12
  92. package/package.json +2 -2
  93. package/dist/chunk-247ANM72.cjs.map +0 -1
  94. package/dist/chunk-3DUADAY2.js.map +0 -1
  95. package/dist/chunk-422427XJ.cjs +0 -571
  96. package/dist/chunk-422427XJ.cjs.map +0 -1
  97. package/dist/chunk-7IAQ4HOK.js.map +0 -1
  98. package/dist/chunk-A7QC2ZVP.js.map +0 -1
  99. package/dist/chunk-DZIXKL7E.js +0 -145
  100. package/dist/chunk-DZIXKL7E.js.map +0 -1
  101. package/dist/chunk-EISO3POT.js.map +0 -1
  102. package/dist/chunk-EP7KOI2V.js +0 -571
  103. package/dist/chunk-EP7KOI2V.js.map +0 -1
  104. package/dist/chunk-FOJZNMMK.js.map +0 -1
  105. package/dist/chunk-ILU76UF3.js.map +0 -1
  106. package/dist/chunk-KVWV4ULP.js +0 -516
  107. package/dist/chunk-KVWV4ULP.js.map +0 -1
  108. package/dist/chunk-L7DMSMAG.cjs.map +0 -1
  109. package/dist/chunk-QC5T6D4J.js.map +0 -1
  110. package/dist/chunk-QOMNEWCQ.cjs.map +0 -1
  111. package/dist/chunk-TSFS5VKD.js.map +0 -1
  112. package/dist/chunk-VQ5W4MYO.js.map +0 -1
  113. package/dist/chunks-SX77P5CV.js +0 -10
  114. package/dist/image-ocr-FLIL7MGN.js.map +0 -1
  115. package/dist/image-ocr-WCAYXLOA.js.map +0 -1
  116. package/dist/image-ocr-ZTYAGV3W.cjs.map +0 -1
  117. package/dist/parser-A4TMPJAM.js.map +0 -1
  118. package/dist/parser-SCUTZAIJ.js.map +0 -1
  119. package/dist/parser-VCXE4I5A.cjs.map +0 -1
  120. package/dist/pdf-ocr-76SAUXMZ.js +0 -13
  121. package/dist/pdf-ocr-CPU55CVF.js +0 -16
  122. package/dist/pdf-ocr-MBZZ57LD.cjs +0 -14
  123. package/dist/redact-7ILEAUTS.js +0 -12
  124. package/dist/seal-RGUPOLXD.js +0 -10
  125. package/dist/visual-NZLYIYEM.js +0 -19
  126. /package/dist/{-AQKXLFIM.js.map → -Z4TJ3QGK.js.map} +0 -0
  127. /package/dist/{chunk-ZWD734EY.js.map → chunk-7SE4EZ45.js.map} +0 -0
  128. /package/dist/{chunk-GDW4YP7K.js.map → chunk-GLSBEEZJ.js.map} +0 -0
  129. /package/dist/{chunk-JQEFP45L.js.map → chunk-GUJ4Q73I.js.map} +0 -0
  130. /package/dist/{chunk-ZWOFQRIB.js.map → chunk-HIJUKZHM.js.map} +0 -0
  131. /package/dist/{chunk-TNCKOL2O.js.map → chunk-LCW7SEPG.js.map} +0 -0
  132. /package/dist/{chunk-UET462HB.js.map → chunk-TITDJWVZ.js.map} +0 -0
  133. /package/dist/{chunk-C7FQBSON.js.map → chunk-V3DX4DUF.js.map} +0 -0
  134. /package/dist/{chunk-DOGPOY4B.js.map → chunk-VDN7LMPL.js.map} +0 -0
  135. /package/dist/{chunk-EDNJLUSE.js.map → chunk-VJIL6PIL.js.map} +0 -0
  136. /package/dist/{chunk-NS55SM7A.js.map → chunk-WJJGW5PL.js.map} +0 -0
  137. /package/dist/{chunks-SX77P5CV.js.map → chunks-CCMRL4MJ.js.map} +0 -0
  138. /package/dist/{formula-JGFTXWYT.js.map → formula-7RANCW5L.js.map} +0 -0
  139. /package/dist/{formula-5S7WWXGH.js.map → formula-7UYJOVTB.js.map} +0 -0
  140. /package/dist/{model-bundle-FSPZZ2EM.js.map → model-bundle-2C5IYDLE.js.map} +0 -0
  141. /package/dist/{models-CJPAQK5R.js.map → models-SEQZHZFT.js.map} +0 -0
  142. /package/dist/{pdf-ocr-76SAUXMZ.js.map → pdf-ocr-UUBWBEHL.js.map} +0 -0
  143. /package/dist/{pdf-ocr-CPU55CVF.js.map → pdf-ocr-VJSF2SQC.js.map} +0 -0
  144. /package/dist/{profile-io-LBM263K7.js.map → profile-io-RUFZOZO6.js.map} +0 -0
  145. /package/dist/{rasterize-46RG4ZF6.js.map → rasterize-IOYXR5SI.js.map} +0 -0
  146. /package/dist/{redact-7ILEAUTS.js.map → redact-NMIKVHMP.js.map} +0 -0
  147. /package/dist/{render-NGP5T24S.js.map → render-YZ2TEC3N.js.map} +0 -0
  148. /package/dist/{seal-RGUPOLXD.js.map → seal-ECV44TUH.js.map} +0 -0
  149. /package/dist/{setup-AU4OCHNH.js.map → setup-MPIEP6XT.js.map} +0 -0
  150. /package/dist/{visual-NZLYIYEM.js.map → visual-ICMOWUCR.js.map} +0 -0
  151. /package/dist/{watch-MKPUCPXM.js.map → watch-RYO7MN5B.js.map} +0 -0
@@ -1,5 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ CELL_LINES,
4
+ CLIP_TABLES,
5
+ CONT_PARTS,
6
+ EMPTY_PARTS,
7
+ FILLER_CELLS,
8
+ IMAGE_CELLS,
9
+ TABLE_COLXS,
10
+ WrapLexicon,
3
11
  collapseEvenSpacing,
4
12
  computeMedianFontSizeFromFreq,
5
13
  detectHeadings,
@@ -9,24 +17,27 @@ import {
9
17
  extractImageRegions,
10
18
  extractPageBlocksWithLines,
11
19
  filterHiddenText,
12
- mergeCrossPageTables,
20
+ joinPageBreakWraps,
13
21
  normalizeItems,
14
- removeHeaderFooterBlocks
15
- } from "./chunk-3DUADAY2.js";
22
+ removeHeaderFooterBlocks,
23
+ trimTrailingEmptyTableCols
24
+ } from "./chunk-YAVHVFRY.js";
16
25
  import {
17
26
  encodePng
18
27
  } from "./chunk-7FCNOKOR.js";
19
- import "./chunk-7IAQ4HOK.js";
28
+ import "./chunk-6BWU6SQX.js";
20
29
  import {
21
30
  parsePageRange
22
31
  } from "./chunk-MOL7MDBG.js";
23
32
  import {
24
- blocksToMarkdown
25
- } from "./chunk-QC5T6D4J.js";
33
+ WINGDINGS,
34
+ blocksToMarkdown,
35
+ escapeLiteralDollar
36
+ } from "./chunk-NLU6LBLY.js";
26
37
  import {
27
38
  KordocError,
28
39
  sanitizeHref
29
- } from "./chunk-UET462HB.js";
40
+ } from "./chunk-TITDJWVZ.js";
30
41
 
31
42
  // src/pdf/image-extract.ts
32
43
  import { OPS, ImageKind } from "pdfjs-dist/legacy/build/pdf.mjs";
@@ -110,7 +121,7 @@ function toRgba(img) {
110
121
  }
111
122
  return null;
112
123
  }
113
- async function extractPageImages(page, fnArray, argsArray, pageNumber, state, warnings) {
124
+ async function extractPageImages(page, fnArray, argsArray, pageNumber, state, warnings, withBytes = true) {
114
125
  const blocks = [];
115
126
  const images = [];
116
127
  const pageSeenIds = /* @__PURE__ */ new Set();
@@ -149,12 +160,14 @@ async function extractPageImages(page, fnArray, argsArray, pageNumber, state, wa
149
160
  if (state.seen.has(hash)) continue;
150
161
  const rgba = toRgba(imgData);
151
162
  if (!rgba) continue;
152
- const png = encodePng(w, h, rgba);
153
163
  state.imageIndex++;
154
- state.totalBytes += png.length;
155
164
  const filename = `image_${String(state.imageIndex).padStart(3, "0")}.png`;
156
165
  state.seen.set(hash, filename);
157
- images.push({ filename, data: png, mimeType: "image/png" });
166
+ if (withBytes) {
167
+ const png = encodePng(w, h, rgba);
168
+ state.totalBytes += png.length;
169
+ images.push({ filename, data: png, mimeType: "image/png" });
170
+ }
158
171
  blocks.push({ type: "image", text: filename, pageNumber });
159
172
  }
160
173
  return { blocks, images };
@@ -199,7 +212,9 @@ var RARE_JONG = /* @__PURE__ */ new Set([3, 5, 6, 9, 10, 11, 12, 13, 14, 15, 18,
199
212
  var MOJIBAKE_MIN_HANGUL = 30;
200
213
  var MOJIBAKE_MAX_NOBATCHIM = 0.15;
201
214
  var MOJIBAKE_MIN_RAREBATCHIM = 0.25;
202
- function computePageQuality(page, text) {
215
+ var VECTOR_TEXT_MIN_GLYPHS = 40;
216
+ var VECTOR_TEXT_MIN_SHARE = 0.25;
217
+ function computePageQuality(page, text, vectorGlyphs = 0) {
203
218
  let total = 0;
204
219
  let hangul = 0;
205
220
  let hangulNoBatchim = 0;
@@ -240,7 +255,10 @@ function computePageQuality(page, text) {
240
255
  const garbledHangul = hangul >= MOJIBAKE_MIN_HANGUL && hangulNoBatchimRatio < MOJIBAKE_MAX_NOBATCHIM && hangulRareBatchimRatio >= MOJIBAKE_MIN_RAREBATCHIM;
241
256
  let needsOcr = false;
242
257
  let ocrReason;
243
- if (total < LOW_TEXT_THRESHOLD) {
258
+ if (vectorGlyphs >= VECTOR_TEXT_MIN_GLYPHS && vectorGlyphs >= (vectorGlyphs + total) * VECTOR_TEXT_MIN_SHARE) {
259
+ needsOcr = true;
260
+ ocrReason = "vector_text";
261
+ } else if (total < LOW_TEXT_THRESHOLD) {
244
262
  needsOcr = true;
245
263
  ocrReason = "low_text";
246
264
  } else if (puaRatio >= HIGH_PUA_THRESHOLD) {
@@ -325,232 +343,657 @@ function summarizeDocumentQuality(pages) {
325
343
  };
326
344
  }
327
345
 
328
- // src/pdf/symbol-fonts.ts
329
- var WINGDINGS = [
330
- "\u{1F589}",
331
- "\u2702",
332
- "\u2701",
333
- "\u{1F453}",
334
- "\u{1F56D}",
335
- "\u{1F56E}",
336
- "\u{1F56F}",
337
- "\u{1F57F}",
338
- "\u2706",
339
- "\u{1F582}",
340
- "\u{1F583}",
341
- "\u{1F4EA}",
342
- "\u{1F4EB}",
343
- "\u{1F4EC}",
344
- "\u{1F4ED}",
345
- "\u{1F4C1}",
346
- "\u{1F4C2}",
347
- "\u{1F4C4}",
348
- "\u{1F5CF}",
349
- "\u{1F5D0}",
350
- "\u{1F5C4}",
351
- "\u231B",
352
- "\u{1F5AE}",
353
- "\u{1F5B0}",
354
- "\u{1F5B2}",
355
- "\u{1F5B3}",
356
- "\u{1F5B4}",
357
- "\u{1F5AB}",
358
- "\u{1F5AC}",
359
- "\u2707",
360
- "\u270D",
361
- "\u{1F58E}",
362
- "\u270C",
363
- "\u{1F44C}",
364
- "\u{1F44D}",
365
- "\u{1F44E}",
366
- "\u261C",
367
- "\u261E",
368
- "\u261D",
369
- "\u261F",
370
- "\u{1F590}",
371
- "\u263A",
372
- "\u{1F610}",
373
- "\u2639",
374
- "\u{1F4A3}",
375
- "\u2620",
376
- "\u{1F3F3}",
377
- "\u{1F3F1}",
378
- "\u2708",
379
- "\u263C",
380
- "\u{1F4A7}",
381
- "\u2744",
382
- "\u{1F546}",
383
- "\u271E",
384
- "\u{1F548}",
385
- "\u2720",
386
- "\u2721",
387
- "\u262A",
388
- "\u262F",
389
- "\u0950",
390
- "\u2638",
391
- "\u2648",
392
- "\u2649",
393
- "\u264A",
394
- "\u264B",
395
- "\u264C",
396
- "\u264D",
397
- "\u264E",
398
- "\u264F",
399
- "\u2650",
400
- "\u2651",
401
- "\u2652",
402
- "\u2653",
403
- "\u{1F670}",
404
- "\u{1F675}",
405
- "\u25CF",
406
- "\u25CB",
407
- "\u25A0",
408
- "\u25A1",
409
- "\u25A1",
410
- "\u2751",
411
- "\u2752",
412
- "\u2B27",
413
- "\u29EB",
414
- "\u25C6",
415
- "\u2756",
416
- "\u2B25",
417
- "\u2327",
418
- "\u2BB9",
419
- "\u2318",
420
- "\u{1F3F5}",
421
- "\u{1F3F6}",
422
- "\u{1F676}",
423
- "\u{1F677}",
424
- "",
425
- "\u24EA",
426
- "\u2460",
427
- "\u2461",
428
- "\u2462",
429
- "\u2463",
430
- "\u2464",
431
- "\u2465",
432
- "\u2466",
433
- "\u2467",
434
- "\u2468",
435
- "\u2469",
436
- "\u24FF",
437
- "\u2776",
438
- "\u2777",
439
- "\u2778",
440
- "\u2779",
441
- "\u277A",
442
- "\u277B",
443
- "\u277C",
444
- "\u277D",
445
- "\u277E",
446
- "\u277F",
447
- "\u{1F662}",
448
- "\u{1F660}",
449
- "\u{1F661}",
450
- "\u{1F663}",
451
- "\u{1F65E}",
452
- "\u{1F65C}",
453
- "\u{1F65D}",
454
- "\u{1F65F}",
455
- "\xB7",
456
- "\u2022",
457
- "\u25AA",
458
- "\u26AA",
459
- "\u25CB",
460
- "\u25EF",
461
- "\u25C9",
462
- "\u25CE",
463
- "\u{1F53F}",
464
- "\u25AA",
465
- "\u25FB",
466
- "\u{1F7C2}",
467
- "\u2726",
468
- "\u2605",
469
- "\u2736",
470
- "\u2734",
471
- "\u2739",
472
- "\u2735",
473
- "\u2BD0",
474
- "\u2316",
475
- "\u27E1",
476
- "\u2311",
477
- "\u2BD1",
478
- "\u272A",
479
- "\u2730",
480
- "\u{1F550}",
481
- "\u{1F551}",
482
- "\u{1F552}",
483
- "\u{1F553}",
484
- "\u{1F554}",
485
- "\u{1F555}",
486
- "\u{1F556}",
487
- "\u{1F557}",
488
- "\u{1F558}",
489
- "\u{1F559}",
490
- "\u{1F55A}",
491
- "\u{1F55B}",
492
- "\u2BB0",
493
- "\u2BB1",
494
- "\u2BB2",
495
- "\u2BB3",
496
- "\u2BB4",
497
- "\u2BB5",
498
- "\u2BB6",
499
- "\u2BB7",
500
- "\u{1F66A}",
501
- "\u{1F66B}",
502
- "\u{1F655}",
503
- "\u{1F654}",
504
- "\u{1F657}",
505
- "\u{1F656}",
506
- "\u{1F650}",
507
- "\u{1F651}",
508
- "\u{1F652}",
509
- "\u{1F653}",
510
- "\u232B",
511
- "\u2326",
512
- "\u2B98",
513
- "\u2B9A",
514
- "\u2B99",
515
- "\u2B9B",
516
- "\u2B88",
517
- "\u2B8A",
518
- "\u2B89",
519
- "\u2B8B",
520
- "\u2190",
521
- "\u2192",
522
- "\u2191",
523
- "\u2193",
524
- "\u2196",
525
- "\u2197",
526
- "\u2199",
527
- "\u2198",
528
- "\u2B05",
529
- "\u2794",
530
- "\u2B06",
531
- "\u2B07",
532
- "\u2B09",
533
- "\u2B08",
534
- "\u2B0B",
535
- "\u2B0A",
536
- "\u21E6",
537
- "\u21E8",
538
- "\u21E7",
539
- "\u21E9",
540
- "\u2B04",
541
- "\u21F3",
542
- "\u2B00",
543
- "\u2B01",
544
- "\u2B03",
545
- "\u2B02",
546
- "\u{1F8AC}",
547
- "\u{1F8AD}",
548
- "\u2717",
549
- "\u2714",
550
- "\u2612",
551
- "\u2611",
552
- ""
346
+ // src/pdf/vector-glyphs.ts
347
+ import { OPS as OPS2 } from "pdfjs-dist/legacy/build/pdf.mjs";
348
+ var GLYPH_MIN_H = 3;
349
+ var GLYPH_MAX_H = 40;
350
+ var GLYPH_MAX_ASPECT = 2;
351
+ var GLYPH_MIN_SEGS = 8;
352
+ var GLYPH_MIN_SUBS = 2;
353
+ var RUN_GAP_EM = 1.5;
354
+ var RUN_MIN = 3;
355
+ var RUN_ALIGN_EM = 0.05;
356
+ var RUN_MAX_OVERLAP = 0.2;
357
+ var RUN_MIN_COLOR = 0.9;
358
+ var RUN_MIN_SHAPES = 0.5;
359
+ var mul = (m, t) => [
360
+ m[0] * t[0] + m[2] * t[1],
361
+ m[1] * t[0] + m[3] * t[1],
362
+ m[0] * t[2] + m[2] * t[3],
363
+ m[1] * t[2] + m[3] * t[3],
364
+ m[0] * t[4] + m[2] * t[5] + m[4],
365
+ m[1] * t[4] + m[3] * t[5] + m[5]
553
366
  ];
367
+ function collectGlyphPaths(fnArray, argsArray) {
368
+ const out = [];
369
+ let ctm = [1, 0, 0, 1, 0, 0];
370
+ let color = 0;
371
+ const stack = [];
372
+ let x1 = Infinity, y1 = Infinity, x2 = -Infinity, y2 = -Infinity;
373
+ let segs = 0, subs = 0, rects = 0;
374
+ let ops = [];
375
+ const add = (x, y) => {
376
+ const tx = ctm[0] * x + ctm[2] * y + ctm[4], ty = ctm[1] * x + ctm[3] * y + ctm[5];
377
+ if (tx < x1) x1 = tx;
378
+ if (tx > x2) x2 = tx;
379
+ if (ty < y1) y1 = ty;
380
+ if (ty > y2) y2 = ty;
381
+ };
382
+ const reset = () => {
383
+ x1 = Infinity;
384
+ y1 = Infinity;
385
+ x2 = -Infinity;
386
+ y2 = -Infinity;
387
+ segs = 0;
388
+ subs = 0;
389
+ rects = 0;
390
+ ops = [];
391
+ };
392
+ for (let i = 0; i < fnArray.length; i++) {
393
+ const op = fnArray[i];
394
+ const args = argsArray[i];
395
+ switch (op) {
396
+ case OPS2.save:
397
+ stack.push([ctm, color]);
398
+ break;
399
+ case OPS2.restore:
400
+ [ctm, color] = stack.pop() ?? [[1, 0, 0, 1, 0, 0], 0];
401
+ break;
402
+ case OPS2.transform:
403
+ ctm = mul(ctm, args);
404
+ break;
405
+ case OPS2.paintFormXObjectBegin: {
406
+ stack.push([ctm, color]);
407
+ const m = args[0];
408
+ if (Array.isArray(m) && m.length >= 6) ctm = mul(ctm, m);
409
+ break;
410
+ }
411
+ case OPS2.paintFormXObjectEnd:
412
+ [ctm, color] = stack.pop() ?? [[1, 0, 0, 1, 0, 0], 0];
413
+ break;
414
+ case OPS2.setFillRGBColor: {
415
+ const c = args;
416
+ color = c[0] << 16 | c[1] << 8 | c[2];
417
+ break;
418
+ }
419
+ case OPS2.constructPath: {
420
+ const [subOps, coords] = args;
421
+ if (!Array.isArray(subOps) || !Array.isArray(coords)) break;
422
+ ops.push(i);
423
+ let ci = 0;
424
+ for (const s of subOps) {
425
+ if (s === OPS2.moveTo) {
426
+ add(coords[ci], coords[ci + 1]);
427
+ ci += 2;
428
+ subs++;
429
+ } else if (s === OPS2.lineTo) {
430
+ add(coords[ci], coords[ci + 1]);
431
+ ci += 2;
432
+ segs++;
433
+ } else if (s === OPS2.curveTo) {
434
+ add(coords[ci], coords[ci + 1]);
435
+ add(coords[ci + 2], coords[ci + 3]);
436
+ add(coords[ci + 4], coords[ci + 5]);
437
+ ci += 6;
438
+ segs++;
439
+ } else if (s === OPS2.curveTo2 || s === OPS2.curveTo3) {
440
+ add(coords[ci], coords[ci + 1]);
441
+ add(coords[ci + 2], coords[ci + 3]);
442
+ ci += 4;
443
+ segs++;
444
+ } else if (s === OPS2.rectangle) {
445
+ const rx = coords[ci], ry = coords[ci + 1], rw = coords[ci + 2], rh = coords[ci + 3];
446
+ add(rx, ry);
447
+ add(rx + rw, ry + rh);
448
+ add(rx, ry + rh);
449
+ add(rx + rw, ry);
450
+ ci += 4;
451
+ rects++;
452
+ subs++;
453
+ segs += 4;
454
+ }
455
+ }
456
+ break;
457
+ }
458
+ case OPS2.fill:
459
+ case OPS2.eoFill:
460
+ case OPS2.fillStroke:
461
+ case OPS2.eoFillStroke:
462
+ case OPS2.closeFillStroke:
463
+ case OPS2.closeEOFillStroke: {
464
+ const w = x2 - x1, h = y2 - y1;
465
+ if (segs > rects * 4 && h >= GLYPH_MIN_H && h <= GLYPH_MAX_H && w <= h * GLYPH_MAX_ASPECT && segs >= GLYPH_MIN_SEGS && subs >= GLYPH_MIN_SUBS) {
466
+ out.push({ x1, y1, x2, y2, segs, subs, color, ops: [...ops, i] });
467
+ }
468
+ reset();
469
+ break;
470
+ }
471
+ case OPS2.stroke:
472
+ case OPS2.closeStroke:
473
+ case OPS2.endPath:
474
+ reset();
475
+ break;
476
+ }
477
+ }
478
+ return out;
479
+ }
480
+ function coveredByText(b, texts) {
481
+ const cx = (b.x1 + b.x2) / 2, cy = (b.y1 + b.y2) / 2;
482
+ for (const t of texts) {
483
+ if (cx >= t.x - 1 && cx <= t.x + t.w + 1 && cy >= t.y - t.h * 0.3 - 1 && cy <= t.y + t.h + 1 && t.text.trim()) return true;
484
+ }
485
+ return false;
486
+ }
487
+ var median = (a) => {
488
+ const s = a.slice().sort((x, y) => x - y);
489
+ return s[s.length >> 1];
490
+ };
491
+ var spread = (a) => {
492
+ const c = median(a);
493
+ return median(a.map((v) => Math.abs(v - c)));
494
+ };
495
+ function isTextRun(m, em) {
496
+ if (m.length < RUN_MIN) return false;
497
+ if (Math.min(spread(m.map((b) => b.y2)), spread(m.map((b) => b.y1))) > em * RUN_ALIGN_EM) return false;
498
+ let overlaps = 0;
499
+ for (let i = 1; i < m.length; i++) if (m[i].x1 < m[i - 1].x2 - em * 0.1) overlaps++;
500
+ if (overlaps > (m.length - 1) * RUN_MAX_OVERLAP) return false;
501
+ const colors = /* @__PURE__ */ new Map();
502
+ for (const b of m) colors.set(b.color, (colors.get(b.color) ?? 0) + 1);
503
+ if (Math.max(...colors.values()) < m.length * RUN_MIN_COLOR) return false;
504
+ const shapes = new Set(m.map((b) => `${Math.round((b.x2 - b.x1) * 2)}:${Math.round((b.y2 - b.y1) * 2)}:${b.segs}`));
505
+ return shapes.size >= m.length * RUN_MIN_SHAPES;
506
+ }
507
+ function scanVectorGlyphs(fnArray, argsArray, texts) {
508
+ const paths = collectGlyphPaths(fnArray, argsArray);
509
+ if (paths.length < RUN_MIN) return { glyphs: 0, paths };
510
+ const free = paths.filter((b) => !coveredByText(b, texts));
511
+ const sorted = free.slice().sort((a, b) => a.y1 + a.y2 - (b.y1 + b.y2));
512
+ let glyphs = 0;
513
+ let row = [];
514
+ let rowCy = 0, rowH = 0;
515
+ const flushRow = () => {
516
+ if (row.length < RUN_MIN) return;
517
+ row.sort((a, b) => a.x1 - b.x1);
518
+ const em = median(row.map((b) => b.y2 - b.y1));
519
+ let start = 0, maxX = row[0].x2;
520
+ for (let i = 1; i <= row.length; i++) {
521
+ if (i < row.length && row[i].x1 - maxX <= em * RUN_GAP_EM) {
522
+ if (row[i].x2 > maxX) maxX = row[i].x2;
523
+ continue;
524
+ }
525
+ const run = row.slice(start, i);
526
+ if (isTextRun(run, em)) glyphs += run.length;
527
+ if (i < row.length) {
528
+ start = i;
529
+ maxX = row[i].x2;
530
+ }
531
+ }
532
+ };
533
+ for (const b of sorted) {
534
+ const cy = (b.y1 + b.y2) / 2, h = b.y2 - b.y1;
535
+ if (row.length && Math.abs(cy - rowCy) <= Math.max(h, rowH) * 0.5) {
536
+ row.push(b);
537
+ continue;
538
+ }
539
+ flushRow();
540
+ row = [b];
541
+ rowCy = cy;
542
+ rowH = h;
543
+ }
544
+ flushRow();
545
+ return { glyphs, paths };
546
+ }
547
+ function ocrVectorOps(opList, paths) {
548
+ const drop = /* @__PURE__ */ new Set();
549
+ for (const p of paths) for (const i of p.ops) drop.add(i);
550
+ const fnArray = [];
551
+ const argsArray = [];
552
+ for (let i = 0; i < opList.fnArray.length; i++) {
553
+ const op = opList.fnArray[i];
554
+ if (drop.has(i) || op === OPS2.clip || op === OPS2.eoClip) continue;
555
+ fnArray.push(op);
556
+ argsArray.push(opList.argsArray[i]);
557
+ }
558
+ return { fnArray, argsArray };
559
+ }
560
+
561
+ // src/pdf/table-parts.ts
562
+ var PART_COL_TOL = 1;
563
+ function anchorsOf(table) {
564
+ const out = [];
565
+ const covered = /* @__PURE__ */ new Set();
566
+ for (let r = 0; r < table.rows; r++) {
567
+ for (let c = 0; c < table.cols; c++) {
568
+ if (covered.has(r * 1e5 + c)) continue;
569
+ const cell = table.cells[r]?.[c];
570
+ if (!cell) continue;
571
+ out.push({ r, c, rs: cell.rowSpan, cs: cell.colSpan, cell });
572
+ for (let dr = 0; dr < cell.rowSpan; dr++) {
573
+ for (let dc = 0; dc < cell.colSpan; dc++) if (dr || dc) covered.add((r + dr) * 1e5 + (c + dc));
574
+ }
575
+ }
576
+ }
577
+ return out;
578
+ }
579
+ function unionCoords(a, b) {
580
+ const out = [...a];
581
+ for (const v of b) if (!a.some((x) => Math.abs(x - v) <= PART_COL_TOL)) out.push(v);
582
+ return out.sort((x, y) => x - y);
583
+ }
584
+ var indexOf = (coords, x) => {
585
+ let best = -1, bestD = Infinity;
586
+ for (let i = 0; i < coords.length; i++) {
587
+ const d = Math.abs(coords[i] - x);
588
+ if (d < bestD) {
589
+ bestD = d;
590
+ best = i;
591
+ }
592
+ }
593
+ return bestD <= PART_COL_TOL ? best : -1;
594
+ };
595
+ var rowText = (anchors, r) => anchors.filter((a) => a.r === r).map((a) => a.cell.text.replace(/\s+/g, "")).join("|");
596
+ var hasText = (t) => t.replace(/\|/g, "") !== "";
597
+ function joinSplitParts(prev, pcx, curr, ccx, dx = 0, prevBottom) {
598
+ if (pcx.length !== prev.cols + 1 || ccx.length !== curr.cols + 1) return null;
599
+ const U = unionCoords(pcx, ccx);
600
+ const cols = U.length - 1;
601
+ if (cols < 1) return null;
602
+ const pa = anchorsOf(prev), ca = anchorsOf(curr);
603
+ let skip = 0;
604
+ while (skip < Math.min(3, curr.rows - 1, prev.rows) && rowText(ca, skip) !== "" && rowText(ca, skip) === rowText(pa, skip)) skip++;
605
+ for (let h = 1; h <= 2 && !skip; h++) {
606
+ while (skip < Math.min(3, curr.rows - 1, prev.rows - h) && hasText(rowText(ca, skip)) && rowText(ca, skip) === rowText(pa, h + skip)) skip++;
607
+ }
608
+ const rows = prev.rows + curr.rows - skip;
609
+ const grid = Array.from({ length: rows }, () => Array.from({ length: cols }, () => ({ text: "", colSpan: 1, rowSpan: 1 })));
610
+ const owner = Array.from({ length: rows }, () => new Array(cols).fill(null));
611
+ const place = (a, x, rowOff, shift = 0) => {
612
+ const c1 = indexOf(U, x[a.c]), c2 = indexOf(U, x[a.c + a.cs]);
613
+ if (c1 < 0 || c2 <= c1) return false;
614
+ const r = a.r + rowOff;
615
+ const placed = { r, c: c1, rs: a.rs, cs: c2 - c1, cell: a.cell };
616
+ for (let dr = 0; dr < a.rs; dr++) for (let dc = c1; dc < c2; dc++) {
617
+ if (r + dr < rows) owner[r + dr][dc] = placed;
618
+ }
619
+ grid[r][c1] = { ...a.cell, colSpan: c2 - c1, rowSpan: a.rs };
620
+ const lines = CELL_LINES.get(a.cell);
621
+ if (lines) CELL_LINES.set(grid[r][c1], shift ? lines.map((l) => ({ ...l, l: l.l + shift, r: l.r + shift })) : lines);
622
+ if (IMAGE_CELLS.has(a.cell)) IMAGE_CELLS.add(grid[r][c1]);
623
+ return true;
624
+ };
625
+ for (const a of pa) if (!FILLER_CELLS.has(a.cell) && !place(a, pcx, 0)) return null;
626
+ for (const a of ca) {
627
+ if (a.r < skip || FILLER_CELLS.has(a.cell)) continue;
628
+ if (!place(a, ccx, prev.rows - skip, dx)) return null;
629
+ }
630
+ const first = prev.rows;
631
+ for (let c = 0; c < cols; c++) {
632
+ const above = owner[first - 1]?.[c];
633
+ if (!above) continue;
634
+ let r = first;
635
+ while (r < rows && owner[r][c] === null) r++;
636
+ if (r === first) continue;
637
+ const span = r - first;
638
+ let ok = true;
639
+ for (let dc = above.c; dc < above.c + above.cs && ok; dc++) {
640
+ for (let rr = first; rr < first + span; rr++) if (owner[rr][dc] !== null) {
641
+ ok = false;
642
+ break;
643
+ }
644
+ }
645
+ if (!ok) continue;
646
+ const newRs = above.rs + span;
647
+ grid[above.r][above.c].rowSpan = newRs;
648
+ const grown = { ...above, rs: newRs };
649
+ for (let rr = above.r; rr < above.r + newRs; rr++) for (let dc = above.c; dc < above.c + above.cs; dc++) owner[rr][dc] = grown;
650
+ }
651
+ for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) if (owner[r][c] === null) FILLER_CELLS.add(grid[r][c]);
652
+ const table = { rows, cols, cells: grid, hasHeader: prev.hasHeader, ...prev.caption ? { caption: prev.caption } : {} };
653
+ const split = rows > prev.rows && mergeSplitRow(table, owner, prev.rows, U);
654
+ if (rows > prev.rows && !split && prevBottom !== void 0) mergeStraddlingCells(table, owner, prev.rows, prevBottom);
655
+ return { table, colXs: U, split, header: ca.filter((a) => a.r < skip && a.cell.text.trim()).length >= 2 };
656
+ }
657
+ function mergeStraddlingCells(table, owner, first, prevBottom) {
658
+ const last = first - 1;
659
+ if (!owner[first].some((o, c) => o !== null && o === owner[last][c])) return;
660
+ for (let c = 0; c < table.cols; ) {
661
+ const u = owner[last][c], d = owner[first][c];
662
+ if (!u) {
663
+ c++;
664
+ continue;
665
+ }
666
+ c = u.c + u.cs;
667
+ if (!d || d === u || u.r >= last || u.r + u.rs - 1 !== last || d.r !== first || d.c !== u.c || d.cs !== u.cs) continue;
668
+ const a = table.cells[u.r][u.c], b = table.cells[first][d.c];
669
+ const U = CELL_LINES.get(a);
670
+ if (!U?.length || U.length > STRADDLE_MAX_LINES || !hasContent(b)) continue;
671
+ const lu = U[U.length - 1];
672
+ if (lu.y - prevBottom > STRADDLE_BOTTOM * (lu.h || 10)) continue;
673
+ appendCell(a, b);
674
+ a.rowSpan = first + d.rs - u.r;
675
+ table.cells[first][d.c] = { text: "", colSpan: 1, rowSpan: 1 };
676
+ const grown = { ...u, rs: a.rowSpan };
677
+ for (let rr = u.r; rr < u.r + grown.rs; rr++) for (let dc = u.c; dc < u.c + u.cs; dc++) owner[rr][dc] = grown;
678
+ }
679
+ }
680
+ var FULL_LINE_TOL = 1;
681
+ var FULL_LINE_MIN_FRAC = 0.5;
682
+ var FULL_LINE_EDGE_MIN = 12;
683
+ var SINGLE_LINE_WORD_GAP = 3.5;
684
+ var SHORT_LINE_GAP = 1.5;
685
+ var STRADDLE_MAX_LINES = 3;
686
+ var STRADDLE_BOTTOM = 1.2;
687
+ var CARRIED_MIN_COL_W = 4;
688
+ var LABEL_ROOM = 1.5;
689
+ var HANGING_MIN = 0.5;
690
+ var HANGING_TOL = 1;
691
+ function continuesAcross(u, d, x1, x2) {
692
+ const U = CELL_LINES.get(u), D = CELL_LINES.get(d);
693
+ if (!U?.length || !D?.length) return false;
694
+ const last = U[U.length - 1];
695
+ const fs = last.h || 10;
696
+ let minL = Infinity, maxR = -Infinity;
697
+ for (const l of U) {
698
+ minL = Math.min(minL, l.l);
699
+ maxR = Math.max(maxR, l.r);
700
+ }
701
+ for (const l of D) {
702
+ minL = Math.min(minL, l.l);
703
+ maxR = Math.max(maxR, l.r);
704
+ }
705
+ maxR = Math.max(maxR, x2 - (minL - x1));
706
+ if (maxR - last.r > FULL_LINE_TOL * fs) return false;
707
+ if (U.length === 1 && x2 - last.r > Math.max(FULL_LINE_EDGE_MIN, SINGLE_LINE_WORD_GAP * fs)) return false;
708
+ if (last.r - last.l < FULL_LINE_MIN_FRAC * (x2 - x1)) return false;
709
+ const leftAligned = (l) => l.l - minL <= fs && maxR - l.r > SHORT_LINE_GAP * fs;
710
+ const hanging = U.length >= 2 && U.every((l) => maxR - l.r <= FULL_LINE_TOL * fs) && last.l - minL >= HANGING_MIN * fs && Math.abs(D[0].l - last.l) <= HANGING_TOL;
711
+ return U.some(leftAligned) || D.some(leftAligned) || hanging;
712
+ }
713
+ function lineEnded(c, x1, x2) {
714
+ const L = CELL_LINES.get(c);
715
+ if (!L || L.length !== 1) return false;
716
+ const l = L[0];
717
+ return x2 - l.r - (l.l - x1) >= LABEL_ROOM * (l.h || 10);
718
+ }
719
+ function appendCell(a, b) {
720
+ if (a.blocks?.length || b.blocks?.length) {
721
+ const asBlocks = (c) => c.blocks?.length ? c.blocks : c.text.split("\n").map((l) => l.trim()).filter(Boolean).map((text) => ({ type: "paragraph", text }));
722
+ a.blocks = [...asBlocks(a), ...asBlocks(b)];
723
+ }
724
+ if (b.text.trim()) a.text = a.text.trim() ? a.text + "\n" + b.text : b.text;
725
+ }
726
+ var hasContent = (cell) => !!cell.text.trim() || !!cell.blocks?.length || IMAGE_CELLS.has(cell);
727
+ function mergeSplitRow(table, owner, first, colXs) {
728
+ const last = first - 1;
729
+ const pairs = [];
730
+ let carried = false;
731
+ for (let c = 0; c < table.cols; ) {
732
+ const a = owner[last][c], b = owner[first][c];
733
+ if (!a && !b) {
734
+ if (colXs[c + 1] - colXs[c] >= CARRIED_MIN_COL_W) carried = true;
735
+ c++;
736
+ continue;
737
+ }
738
+ if (!a || !b) return false;
739
+ if (a !== b) {
740
+ if (a.c !== b.c || a.cs !== b.cs || a.r + a.rs - 1 !== last || b.r !== first || b.rs !== 1) return false;
741
+ pairs.push([a, b]);
742
+ } else if (a.r === last && a.rs === 2) carried = true;
743
+ c = a.c + a.cs;
744
+ }
745
+ const carriedSplit = carried && pairs.filter(([u, d]) => hasContent(u.cell) && hasContent(d.cell)).length <= 1 && !pairs.some(([u, d]) => !hasContent(u.cell) && hasContent(d.cell));
746
+ const cell = (a) => table.cells[a.r][a.c];
747
+ if (!carriedSplit) {
748
+ const norm = (c) => c.text.replace(/\s+/g, "");
749
+ if (pairs.some(([u, d]) => hasContent(d.cell) && norm(cell(d)) !== norm(cell(u)) && lineEnded(cell(u), colXs[u.c], colXs[u.c + u.cs]))) return false;
750
+ if (!pairs.some(([u, d]) => continuesAcross(cell(u), cell(d), colXs[u.c], colXs[u.c + u.cs]))) return false;
751
+ }
752
+ for (const [u, d] of pairs) appendCell(table.cells[u.r][u.c], table.cells[d.r][d.c]);
753
+ for (let r = 0; r < first; r++) for (let c = 0; c < table.cols; c++) {
754
+ const o = owner[r][c];
755
+ if (o && o.r === r && o.c === c && r + table.cells[r][c].rowSpan > first) table.cells[r][c].rowSpan--;
756
+ }
757
+ table.cells.splice(first, 1);
758
+ table.rows--;
759
+ return true;
760
+ }
761
+ var NEIGHBOR_TABLE_EPSILON = 0.2;
762
+ function besideOwn(b, p, c) {
763
+ if (!b.bbox) return false;
764
+ if (b.type === "table") return leftColumnOf(b, p);
765
+ const t = (b.pageNumber === p.pageNumber ? p : c).bbox;
766
+ const bx1 = b.bbox.x, bx2 = b.bbox.x + b.bbox.width;
767
+ return bx2 <= t.x + 1 || bx1 >= t.x + t.width - 1;
768
+ }
769
+ function leftColumnOf(b, t) {
770
+ return !!b.bbox && b.pageNumber === t.pageNumber && b.bbox.x + b.bbox.width <= t.bbox.x + 1;
771
+ }
772
+ function placeJoined(blocks, i, j, table) {
773
+ const prev = blocks[i];
774
+ blocks[i] = { ...prev, table };
775
+ blocks.splice(j, 1);
776
+ let k = j - 1;
777
+ while (k > i && !leftColumnOf(blocks[k], prev)) k--;
778
+ if (k > i) blocks.splice(k, 0, blocks.splice(i, 1)[0]);
779
+ }
780
+ function insideTable(b, t) {
781
+ if (!b.bbox || b.pageNumber !== t.pageNumber) return false;
782
+ const o = t.bbox;
783
+ return b.bbox.x >= o.x - 1 && b.bbox.x + b.bbox.width <= o.x + o.width + 1 && b.bbox.y >= o.y - 1 && b.bbox.y + b.bbox.height <= o.y + o.height + 1;
784
+ }
785
+ function mergeCrossPageTables(blocks, pageHeights) {
786
+ mergeColumnFlow(blocks, pageHeights);
787
+ for (let i = blocks.length - 2; i >= 0; i--) {
788
+ const prev = blocks[i];
789
+ if (prev.type !== "table" || !prev.table || !prev.bbox || !prev.pageNumber) continue;
790
+ let j = i + 1;
791
+ while (j < blocks.length && (blocks[j].type !== "table" || insideTable(blocks[j], prev) || leftColumnOf(blocks[j], prev)) && (blocks[j].pageNumber ?? 0) <= prev.pageNumber + 1) j++;
792
+ const curr = blocks[j];
793
+ if (!curr || curr.type !== "table" || !curr.table || !curr.bbox || curr.pageNumber !== prev.pageNumber + 1) continue;
794
+ const joined = j === i + 1 || blocks.slice(i + 1, j).every((b) => besideOwn(b, prev, curr) || insideTable(b, prev)) ? looksContinued(prev, curr, pageHeights) && !restartsTable(blocks, i, curr.table, pageHeights) ? joinClipParts(prev, curr, pageHeights) ?? false : null : null;
795
+ if (joined) {
796
+ placeJoined(blocks, i, j, joined);
797
+ continue;
798
+ }
799
+ if (EMPTY_PARTS.has(curr.table)) {
800
+ blocks.splice(j, 1);
801
+ i++;
802
+ continue;
803
+ }
804
+ if (joined === null) continue;
805
+ if (prev.table.cols !== curr.table.cols || EMPTY_PARTS.has(prev.table)) continue;
806
+ const width = Math.max(prev.bbox.width, curr.bbox.width, 1);
807
+ const leftDiff = Math.abs(prev.bbox.x - curr.bbox.x);
808
+ const rightDiff = Math.abs(prev.bbox.x + prev.bbox.width - (curr.bbox.x + curr.bbox.width));
809
+ if (leftDiff > width * NEIGHBOR_TABLE_EPSILON || rightDiff > width * NEIGHBOR_TABLE_EPSILON) continue;
810
+ const px = TABLE_COLXS.get(prev.table), cx = TABLE_COLXS.get(curr.table);
811
+ if (px && cx && !shiftedSame(px, cx, !CLIP_TABLES.has(prev.table) && !CLIP_TABLES.has(curr.table))) continue;
812
+ let currCells = curr.table.cells;
813
+ if (currCells.length > 1 && prev.table.cells.length > 0 && rowTextsEqual(prev.table.cells[0], currCells[0])) {
814
+ currCells = currCells.slice(1);
815
+ }
816
+ if (currCells.length === 0) {
817
+ blocks.splice(j, 1);
818
+ continue;
819
+ }
820
+ const merged = {
821
+ rows: prev.table.rows + currCells.length,
822
+ cols: prev.table.cols,
823
+ cells: [...prev.table.cells, ...currCells],
824
+ hasHeader: prev.table.hasHeader,
825
+ caption: prev.table.caption
826
+ };
827
+ if (px ?? cx) TABLE_COLXS.set(merged, px ?? cx);
828
+ if (CLIP_TABLES.has(prev.table) || CLIP_TABLES.has(curr.table)) CLIP_TABLES.add(merged);
829
+ placeJoined(blocks, i, j, merged);
830
+ }
831
+ for (let i = blocks.length - 1; i >= 0; i--) {
832
+ const t = blocks[i].table;
833
+ if (blocks[i].type === "table" && t && EMPTY_PARTS.has(t)) blocks.splice(i, 1);
834
+ }
835
+ }
836
+ function mergeColumnFlow(blocks, pageHeights) {
837
+ if (!pageHeights) return;
838
+ for (let i = 0; i < blocks.length; i++) {
839
+ const L = blocks[i];
840
+ if (L.type !== "table" || !L.table || !L.bbox || !L.pageNumber || !CLIP_TABLES.has(L.table) || EMPTY_PARTS.has(L.table)) continue;
841
+ const ph = pageHeights.get(L.pageNumber);
842
+ if (!ph || L.bbox.y > ph * PAGE_EDGE_BAND) continue;
843
+ let s0 = i, s1 = i;
844
+ while (s0 > 0 && blocks[s0 - 1].pageNumber === L.pageNumber) s0--;
845
+ while (s1 + 1 < blocks.length && blocks[s1 + 1].pageNumber === L.pageNumber) s1++;
846
+ let k = -1;
847
+ for (let q = s0; q <= s1; q++) {
848
+ const R2 = blocks[q];
849
+ if (q === i || R2.type !== "table" || !R2.table || !R2.bbox || !leftColumnOf(L, R2)) continue;
850
+ const top2 = R2.bbox.y + R2.bbox.height;
851
+ if (top2 < ph * (1 - PAGE_EDGE_BAND)) continue;
852
+ if (k < 0 || top2 > blocks[k].bbox.y + blocks[k].bbox.height) k = q;
853
+ }
854
+ if (k < 0) continue;
855
+ const R = blocks[k];
856
+ if (Math.abs(R.bbox.width - L.bbox.width) > Math.max(R.bbox.width, L.bbox.width) * NEIGHBOR_TABLE_EPSILON) continue;
857
+ if (!looksContinued(L, R) || restartsTable(blocks, i, R.table, pageHeights)) continue;
858
+ const joined = joinClipParts(L, R, pageHeights);
859
+ if (!joined) continue;
860
+ const top = L.bbox.y + L.bbox.height;
861
+ const at = Math.min(i, k);
862
+ blocks[at] = { ...L, table: joined, bbox: { ...L.bbox, y: R.bbox.y, height: Math.max(0, top - R.bbox.y) } };
863
+ blocks.splice(Math.max(i, k), 1);
864
+ i = at - 1;
865
+ }
866
+ }
867
+ function joinClipParts(prev, curr, pageHeights) {
868
+ const pt = prev.table, ct = curr.table;
869
+ if (!CLIP_TABLES.has(pt) || !CLIP_TABLES.has(ct)) return null;
870
+ const px = TABLE_COLXS.get(pt), cx = TABLE_COLXS.get(ct);
871
+ if (!px || !cx) return null;
872
+ let xs = cx, shifted = false, dx = 0;
873
+ if (!shiftedSame(px, cx, false)) {
874
+ if (!pageHeights?.get(prev.pageNumber) || !pageHeights?.get(curr.pageNumber)) return null;
875
+ dx = px[px.length - 1] - cx[cx.length - 1];
876
+ if (Math.abs(dx) > CONTINUATION_COL_TOL) {
877
+ xs = cx.map((x) => x + dx);
878
+ shifted = true;
879
+ } else dx = 0;
880
+ if (!px.some((x) => Math.abs(x - xs[0]) <= CONTINUATION_COL_TOL)) return null;
881
+ }
882
+ const res = joinSplitParts(pt, px, ct, xs, dx, prev.bbox?.y);
883
+ if (!res || shifted && !res.split && !res.header) return null;
884
+ TABLE_COLXS.set(res.table, res.colXs);
885
+ CLIP_TABLES.add(res.table);
886
+ return res.table;
887
+ }
888
+ var ANNEX_HEAD_RE = /^\s*[<\[(【]?\s*(?:붙\s*임|참\s*고|별\s*첨|별\s*지|별\s*표|첨\s*부|부\s*록)(?:\s*\d|\s*$|\s*[>\])】])|^\s*■/;
889
+ function looksContinued(prev, curr, pageHeights) {
890
+ const ph = pageHeights?.get(prev.pageNumber), ch = pageHeights?.get(curr.pageNumber);
891
+ if (ph && ch && (prev.bbox.y > ph * PAGE_EDGE_BAND || curr.bbox.y + curr.bbox.height < ch * (1 - PAGE_EDGE_BAND))) return false;
892
+ const firstText = curr.table.cells[0]?.find((c) => c.text.trim())?.text ?? "";
893
+ return !ANNEX_HEAD_RE.test(firstText);
894
+ }
895
+ function firstRowSig(t) {
896
+ const x = TABLE_COLXS.get(t);
897
+ if (!x || x.length !== t.cols + 1) return null;
898
+ return anchorsOf(t).filter((a) => a.r === 0).map((a) => ({ x1: x[a.c], x2: x[a.c + a.cs], t: a.cell.text.replace(/\s+/g, "") }));
899
+ }
900
+ function restartsTable(blocks, i, curr, pageHeights) {
901
+ const cs = firstRowSig(curr);
902
+ if (!cs || cs.length < RESTART_MIN_ANCHORS) return false;
903
+ const hs = firstRowSig(blocks[chainHead(blocks, i, pageHeights)].table);
904
+ if (!hs || hs.length !== cs.length) return false;
905
+ const dx = hs[hs.length - 1].x2 - cs[cs.length - 1].x2;
906
+ if (!hs.every((h, n) => Math.abs(h.x1 - cs[n].x1 - dx) <= CONTINUATION_COL_TOL && Math.abs(h.x2 - cs[n].x2 - dx) <= CONTINUATION_COL_TOL)) return false;
907
+ let same = 0, diff = 0;
908
+ for (let n = 0; n < hs.length; n++) {
909
+ if (!hs[n].t && !cs[n].t) continue;
910
+ if (hs[n].t === cs[n].t) same++;
911
+ else diff++;
912
+ }
913
+ return same >= 2 && diff >= 1;
914
+ }
915
+ function chainHead(blocks, i, pageHeights) {
916
+ let k = i;
917
+ for (let steps = 0; steps < RESTART_LOOKBACK_PAGES; steps++) {
918
+ const cur = blocks[k];
919
+ let p = k - 1;
920
+ while (p >= 0 && blocks[p].type !== "table" && (blocks[p].pageNumber ?? 0) >= (cur.pageNumber ?? 0) - 1) p--;
921
+ if (p < 0 || blocks[p].type !== "table" || !blocks[p].table || !blocks[p].bbox) break;
922
+ for (let q = p - 1; q >= 0 && blocks[q].pageNumber === blocks[p].pageNumber; q--) {
923
+ if (blocks[q].type === "table" && blocks[q].bbox && insideTable(blocks[p], blocks[q])) {
924
+ p = q;
925
+ break;
926
+ }
927
+ }
928
+ const pb = blocks[p];
929
+ if (pb.pageNumber !== (cur.pageNumber ?? 0) - 1) break;
930
+ if (!blocks.slice(p + 1, k).every((b) => besideOwn(b, pb, cur) || insideTable(b, pb))) break;
931
+ if (!looksContinued(pb, cur, pageHeights)) break;
932
+ const px = TABLE_COLXS.get(pb.table), cx = TABLE_COLXS.get(cur.table);
933
+ if (!px || !cx) break;
934
+ const dx = px[px.length - 1] - cx[cx.length - 1];
935
+ if (!shiftedSame(px, cx) && !px.some((x) => Math.abs(x - (cx[0] + dx)) <= CONTINUATION_COL_TOL)) break;
936
+ k = p;
937
+ }
938
+ return k;
939
+ }
940
+ function rowTextsEqual(a, b) {
941
+ if (a.length !== b.length) return false;
942
+ const norm = (t) => t.replace(/\s+/g, "");
943
+ for (let i = 0; i < a.length; i++) {
944
+ if (norm(a[i].text) !== norm(b[i].text)) return false;
945
+ }
946
+ return a.some((c) => c.text.trim() !== "");
947
+ }
948
+ var CONTINUATION_COL_TOL = 2;
949
+ function shiftedSame(px, cx, allowShift = true) {
950
+ if (px.length !== cx.length) return false;
951
+ const dx = allowShift ? px[px.length - 1] - cx[cx.length - 1] : 0;
952
+ return px.every((x, k) => Math.abs(x - cx[k] - dx) <= CONTINUATION_COL_TOL);
953
+ }
954
+ var PAGE_EDGE_BAND = 0.16;
955
+ var RESTART_MIN_ANCHORS = 3;
956
+ var RESTART_LOOKBACK_PAGES = 5;
957
+
958
+ // src/pdf/cell-continuation.ts
959
+ var COL_MATCH_TOL = 0.5;
960
+ function lastRowCell(t, x1, x2) {
961
+ const xs = TABLE_COLXS.get(t);
962
+ const covered = /* @__PURE__ */ new Set();
963
+ for (let r = 0; r < t.rows; r++) {
964
+ for (let c = 0; c < t.cols; c++) {
965
+ if (covered.has(r * 1e5 + c)) continue;
966
+ const cell = t.cells[r]?.[c];
967
+ if (!cell) continue;
968
+ for (let dr = 0; dr < cell.rowSpan; dr++) for (let dc = 0; dc < cell.colSpan; dc++) covered.add((r + dr) * 1e5 + c + dc);
969
+ if (r + cell.rowSpan !== t.rows) continue;
970
+ if (xs ? Math.abs(xs[c] - x1) <= COL_MATCH_TOL && Math.abs(xs[c + cell.colSpan] - x2) <= COL_MATCH_TOL : t.cols === 1) return cell;
971
+ }
972
+ }
973
+ return void 0;
974
+ }
975
+ var cellBlocks = (cell, pageNumber) => cell.blocks ?? cell.text.split("\n").map((t) => t.trim()).filter(Boolean).map((text) => ({ type: "paragraph", text, pageNumber }));
976
+ function mergeContinuedCells(blocks, pageHeights) {
977
+ for (let j = blocks.length - 1; j > 0; j--) {
978
+ const part = blocks[j];
979
+ const from = part.table ? CONT_PARTS.get(part.table) : void 0;
980
+ if (!from || !part.table) continue;
981
+ let i = j - 1;
982
+ while (i >= 0 && blocks[i].type !== "table") i--;
983
+ const prev = blocks[i];
984
+ if (i < 0 || !prev.table || prev.pageNumber !== (part.pageNumber ?? 0) - 1) continue;
985
+ const cell = lastRowCell(prev.table, from.x1, from.x2);
986
+ const add = part.table.cells[0]?.[0];
987
+ if (!cell || !add) continue;
988
+ if (cell.blocks || add.blocks) cell.blocks = [...cellBlocks(cell, prev.pageNumber), ...cellBlocks(add, part.pageNumber)];
989
+ cell.text = [cell.text, add.text].filter((s) => s.trim()).join("\n");
990
+ if (cell.text.trim() || cell.blocks?.length) EMPTY_PARTS.delete(prev.table);
991
+ blocks.splice(j, 1);
992
+ if (cell.blocks) mergeCrossPageTables(cell.blocks, pageHeights);
993
+ }
994
+ }
995
+
996
+ // src/pdf/symbol-fonts.ts
554
997
  var WINANSI_REVERSE = {
555
998
  8364: 128,
556
999
  8218: 130,
@@ -623,7 +1066,8 @@ function remapSymbolFontItems(items, resolveFontName) {
623
1066
  function normalizeAraea(text) {
624
1067
  return text.replace(/(?<![\u1100-\u115F])\u119E/g, "\u318D");
625
1068
  }
626
- var cleanChars = (text) => normalizeAraea(stripControlChars(text));
1069
+ var stripNoUnicodeGlyph = (text) => text.includes("\uF000") ? text.replace(/\uF000/g, "") : text;
1070
+ var cleanChars = (text) => normalizeAraea(stripNoUnicodeGlyph(stripControlChars(text)));
627
1071
  function sanitizeBlockControlChars(blocks) {
628
1072
  for (const b of blocks) {
629
1073
  if (b.text) b.text = cleanChars(b.text);
@@ -658,7 +1102,8 @@ function cleanPdfText(text) {
658
1102
  normalizeAraea(stripControlChars(text)).replace(/^\d{1,4}\n/, "").replace(/^[\s]*[-–—]\s*[-–—]?\d+[-–—]?[\s]*[-–—]?[\s]*$/gm, "").replace(/^\s*\d+\s*\/\s*\d+\s*$/gm, "").replace(/\n\d{1,4}\n/g, "\n").replace(/\n\d{1,4}$/, "").replace(/^#{1,6}\s*\d{1,4}\s*$/gm, "")
659
1103
  ).replace(/^(?!\| ---).*$/gm, (line) => {
660
1104
  if (/^\s*\${1,2}.+\${1,2}\s*$/.test(line)) return line;
661
- return collapseEvenSpacing(line);
1105
+ const mark = /^(?:#{1,6}|-) /.exec(line)?.[0] ?? "";
1106
+ return mark + collapseEvenSpacing(line.slice(mark.length));
662
1107
  }).replace(/([□■◆○●▶ㅇ])\s+([가-힣])\s+([가-힣])/g, "$1 $2$3").replace(/\\~\\~/g, "~~").replace(/~~~~/g, "").replace(/<u>\s*<\/u>/g, "").replace(/\n{3,}/g, "\n\n").trim();
663
1108
  }
664
1109
  function startsWithMarker(line) {
@@ -737,7 +1182,7 @@ function applyLinkAnnotations(items, annots) {
737
1182
 
738
1183
  // src/pdf/formula-ocr.ts
739
1184
  async function applyFormulaOcr(buffer, blocks, pageFilter, effectivePageCount, warnings, _onProgress) {
740
- const formulaMod = await import("./formula-5S7WWXGH.js");
1185
+ const formulaMod = await import("./formula-7UYJOVTB.js");
741
1186
  const { FormulaPipeline, ensureFormulaModels } = formulaMod;
742
1187
  await ensureFormulaModels((p) => {
743
1188
  if (p.phase === "download" && p.total) {
@@ -937,6 +1382,9 @@ async function parsePdfDocument(buffer, options) {
937
1382
  const imageState = createPdfImageState();
938
1383
  const extractedImages = [];
939
1384
  const pageImageBlocks = /* @__PURE__ */ new Map();
1385
+ const carry = {};
1386
+ const vectorPageOps = /* @__PURE__ */ new Map();
1387
+ const wrapLexicon = new WrapLexicon();
940
1388
  let parsedPages = 0;
941
1389
  for (let i = 1; i <= effectivePageCount; i++) {
942
1390
  if (pageFilter && !pageFilter.has(i)) continue;
@@ -967,6 +1415,7 @@ async function parsePdfDocument(buffer, options) {
967
1415
  return void 0;
968
1416
  }
969
1417
  });
1418
+ for (const it of visible) if (it.text.includes("$")) it.text = escapeLiteralDollar(it.text);
970
1419
  const pageArea = viewport.width * viewport.height;
971
1420
  if (pageArea > 0) {
972
1421
  const imageRegions = extractImageRegions(opList.fnArray, opList.argsArray);
@@ -975,19 +1424,19 @@ async function parsePdfDocument(buffer, options) {
975
1424
  const area = (r.x2 - r.x1) * (r.y2 - r.y1);
976
1425
  if (area < pageArea * 0.05) continue;
977
1426
  pagesWithLargeImage.add(i);
978
- const hasText = visible.some((it) => {
1427
+ const hasText2 = visible.some((it) => {
979
1428
  const cx = it.x + it.w / 2;
980
1429
  const cy = it.y + (it.h || it.fontSize) / 2;
981
1430
  return cx >= r.x1 && cx <= r.x2 && cy >= r.y1 && cy <= r.y2;
982
1431
  });
983
- if (!hasText) uncovered++;
1432
+ if (!hasText2) uncovered++;
984
1433
  }
985
1434
  if (uncovered > 0) skippedImagePages.set(i, uncovered);
986
1435
  }
987
- const pageBlocks = extractPageBlocksWithLines(visible, i, opList, viewport.width, viewport.height, void 0, options?.tables !== false);
1436
+ const pageBlocks = extractPageBlocksWithLines(visible, i, opList, viewport.width, viewport.height, void 0, options?.tables !== false, carry, wrapLexicon);
988
1437
  for (const b of pageBlocks) blocks.push(b);
989
1438
  try {
990
- const { blocks: imgBlocks, images: pageImages } = await extractPageImages(page, opList.fnArray, opList.argsArray, i, imageState, warnings);
1439
+ const { blocks: imgBlocks, images: pageImages } = await extractPageImages(page, opList.fnArray, opList.argsArray, i, imageState, warnings, options?.images !== false);
991
1440
  if (imgBlocks.length > 0) pageImageBlocks.set(i, imgBlocks);
992
1441
  extractedImages.push(...pageImages);
993
1442
  } catch {
@@ -1003,7 +1452,12 @@ async function parsePdfDocument(buffer, options) {
1003
1452
  totalTextBytes += t.length * 2;
1004
1453
  pageText += pageText ? "\n" + t : t;
1005
1454
  }
1006
- pageQuality.push(computePageQuality(i, pageText));
1455
+ const vector = scanVectorGlyphs(opList.fnArray, opList.argsArray, visible);
1456
+ const quality = computePageQuality(i, pageText, vector.glyphs);
1457
+ pageQuality.push(quality);
1458
+ if (options?.ocr && quality.ocrReason === "vector_text" && page.rotate % 360 === 0 && page.view[0] === 0 && page.view[1] === 0) {
1459
+ vectorPageOps.set(i, ocrVectorOps(opList, vector.paths));
1460
+ }
1007
1461
  if (totalTextBytes > MAX_TOTAL_TEXT) throw new KordocError("\uD14D\uC2A4\uD2B8 \uCD94\uCD9C \uD06C\uAE30 \uCD08\uACFC");
1008
1462
  parsedPages++;
1009
1463
  options?.onProgress?.(parsedPages, totalTarget);
@@ -1029,9 +1483,9 @@ async function parsePdfDocument(buffer, options) {
1029
1483
  }
1030
1484
  if (targets.size > 0) {
1031
1485
  try {
1032
- const { runPdfOcr } = await import("./pdf-ocr-CPU55CVF.js");
1486
+ const { runPdfOcr } = await import("./pdf-ocr-UUBWBEHL.js");
1033
1487
  const mode = typeof options.ocr === "function" ? options.ocr : "builtin";
1034
- const ocrPageBlocks = await runPdfOcr(ocrBuffer, targets, mode, warnings, options.onProgress, options.tables !== false);
1488
+ const ocrPageBlocks = await runPdfOcr(ocrBuffer, targets, mode, warnings, options.onProgress, options.tables !== false, vectorPageOps);
1035
1489
  if (ocrPageBlocks.size > 0) {
1036
1490
  for (const p of ocrPageBlocks.keys()) ocrDone.add(p);
1037
1491
  const merged = blocks.filter((b) => !(b.pageNumber && ocrDone.has(b.pageNumber)));
@@ -1061,6 +1515,7 @@ async function parsePdfDocument(buffer, options) {
1061
1515
  }
1062
1516
  if (!isImageBased) {
1063
1517
  const OCR_REASON_MESSAGES = {
1518
+ vector_text: "\uAE00\uC790\uB97C \uACE1\uC120(\uBCA1\uD130 \uACBD\uB85C)\uC73C\uB85C \uADF8\uB9B0 \uD398\uC774\uC9C0 (\uD14D\uC2A4\uD2B8\uCE35\uC5D0 \uAE00\uC790 \uC5C6\uC74C)",
1064
1519
  low_text: "\uD14D\uC2A4\uD2B8\uAC00 \uAC70\uC758 \uC5C6\uB294 \uD398\uC774\uC9C0 (\uC2A4\uCE94/\uC774\uBBF8\uC9C0 \uCD94\uC815)",
1065
1520
  high_pua: "\uAE00\uAF34 \uB9E4\uD551 \uC2E4\uD328 (PUA \uBE44\uC728 \uB192\uC74C) \u2014 \uCD94\uCD9C \uD14D\uC2A4\uD2B8 \uC2E0\uB8B0 \uBD88\uAC00",
1066
1521
  high_control: "\uC81C\uC5B4\uBB38\uC790 \uBE44\uC728 \uB192\uC74C \u2014 \uCD94\uCD9C \uD14D\uC2A4\uD2B8 \uC2E0\uB8B0 \uBD88\uAC00",
@@ -1084,7 +1539,10 @@ async function parsePdfDocument(buffer, options) {
1084
1539
  blocks.splice(removed[ri], 1);
1085
1540
  }
1086
1541
  }
1087
- mergeCrossPageTables(blocks);
1542
+ mergeContinuedCells(blocks, pageHeights);
1543
+ mergeCrossPageTables(blocks, pageHeights);
1544
+ if (!options?.keepTrailingEmptyCols) trimTrailingEmptyTableCols(blocks);
1545
+ joinPageBreakWraps(blocks, wrapLexicon);
1088
1546
  injectPageImageBlocks(blocks, pageImageBlocks);
1089
1547
  if (options?.formulaOcr && formulaBuffer) {
1090
1548
  try {
@@ -1166,4 +1624,4 @@ export {
1166
1624
  parsePdfDocument,
1167
1625
  removeHeaderFooterBlocks
1168
1626
  };
1169
- //# sourceMappingURL=parser-SCUTZAIJ.js.map
1627
+ //# sourceMappingURL=parser-3FNXEP6T.js.map