kordoc 4.18.1 → 4.18.3

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 (148) hide show
  1. package/README.md +7 -6
  2. package/dist/{-X4KTLQC6.js → -WOKB25R2.js} +13 -11
  3. package/dist/{chunk-UTVMLJZE.js → chunk-2I2RTJJ5.js} +433 -71
  4. package/dist/chunk-2I2RTJJ5.js.map +1 -0
  5. package/dist/{chunk-Q5N4YS3T.cjs → chunk-2ZBLQVAS.cjs} +20 -13
  6. package/dist/chunk-2ZBLQVAS.cjs.map +1 -0
  7. package/dist/{chunk-KXR4CTFT.js → chunk-3FZGL3IL.js} +2 -2
  8. package/dist/{chunk-R2IFWAHI.js → chunk-5X7XWYR2.js} +2 -2
  9. package/dist/{chunk-PWRY4W6Q.js → chunk-6GLTGOP6.js} +2 -2
  10. package/dist/{chunk-SQQ4ITJ5.js → chunk-AZQWESRH.js} +2 -2
  11. package/dist/{chunk-KBZ3MQJX.js → chunk-BGOR5GCF.js} +2 -2
  12. package/dist/{chunk-WWOTHS2E.js → chunk-BJ6RYYXV.js} +205 -7
  13. package/dist/chunk-BJ6RYYXV.js.map +1 -0
  14. package/dist/{chunk-VDIXNEWV.js → chunk-CAN5P6N6.js} +10 -5
  15. package/dist/chunk-CAN5P6N6.js.map +1 -0
  16. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  17. package/dist/{chunk-SIZ63E5G.cjs → chunk-HZV52V2X.cjs} +3 -3
  18. package/dist/chunk-HZV52V2X.cjs.map +1 -0
  19. package/dist/{chunk-X625PCZM.js → chunk-IXX3WHIE.js} +3 -3
  20. package/dist/{chunk-6V7QRQY3.js → chunk-J2A46VCA.js} +125 -87
  21. package/dist/chunk-J2A46VCA.js.map +1 -0
  22. package/dist/chunk-J55UQC5H.cjs.map +1 -1
  23. package/dist/{chunk-AQUNBGXH.js → chunk-KSJ7GKNQ.js} +2 -2
  24. package/dist/{chunk-Z4KCEERM.js → chunk-NES5U4JK.js} +3 -3
  25. package/dist/{chunk-MTTYJEKA.js → chunk-OOX2GZZ4.js} +2 -2
  26. package/dist/{chunk-HUGBJVAA.js → chunk-PSJLB3SZ.js} +16 -9
  27. package/dist/chunk-PSJLB3SZ.js.map +1 -0
  28. package/dist/{chunk-NQR3VKWN.js → chunk-RDBTOE5X.js} +2 -2
  29. package/dist/{chunk-2VFZQ634.js → chunk-RRURZDEK.js} +2 -2
  30. package/dist/{chunk-6N5BOPJI.js → chunk-RSDUH4XF.js} +4 -3
  31. package/dist/chunk-RSDUH4XF.js.map +1 -0
  32. package/dist/{chunk-PCSOJ523.cjs → chunk-SHRRD2TD.cjs} +10 -5
  33. package/dist/chunk-SHRRD2TD.cjs.map +1 -0
  34. package/dist/{chunk-TMC4A3FM.js → chunk-UVUKT3IQ.js} +13 -7
  35. package/dist/chunk-UVUKT3IQ.js.map +1 -0
  36. package/dist/{chunk-IXAXI2S3.cjs → chunk-V4BKT65D.cjs} +3 -3
  37. package/dist/chunk-V4BKT65D.cjs.map +1 -0
  38. package/dist/{chunk-I7YWXECO.js → chunk-VGDTONTB.js} +10 -5
  39. package/dist/chunk-VGDTONTB.js.map +1 -0
  40. package/dist/{chunk-K35WIYBD.js → chunk-W3RADOLO.js} +5 -4
  41. package/dist/chunk-W3RADOLO.js.map +1 -0
  42. package/dist/{chunk-5PNQIF3V.js → chunk-W7P4GPOV.js} +4 -4
  43. package/dist/{chunk-7DC2KL3V.cjs → chunk-WN5YLP7H.cjs} +161 -43
  44. package/dist/chunk-WN5YLP7H.cjs.map +1 -0
  45. package/dist/{chunk-IUMV45TX.cjs → chunk-ZD5WNQNC.cjs} +12 -12
  46. package/dist/chunk-ZD5WNQNC.cjs.map +1 -0
  47. package/dist/{chunk-CWJ5KY2F.js → chunk-ZN3LHNJG.js} +176 -43
  48. package/dist/chunk-ZN3LHNJG.js.map +1 -0
  49. package/dist/chunks-OQDRDICD.js +10 -0
  50. package/dist/cli.js +55 -34
  51. package/dist/cli.js.map +1 -1
  52. package/dist/{formula-W3GQC6L6.cjs → formula-BQ5RW5XD.cjs} +9 -9
  53. package/dist/formula-BQ5RW5XD.cjs.map +1 -0
  54. package/dist/{formula-LICM6K27.js → formula-GPCOJJXN.js} +3 -3
  55. package/dist/{formula-T4Q2UHWO.js → formula-QZAOKPBX.js} +4 -4
  56. package/dist/{image-ocr-WZJURDX6.js → image-ocr-POCME5I4.js} +6 -6
  57. package/dist/{image-ocr-XB2NFKGZ.js → image-ocr-TWNNVTZS.js} +9 -9
  58. package/dist/{image-ocr-7PNHBD2G.cjs → image-ocr-VKIUBLBX.cjs} +15 -15
  59. package/dist/image-ocr-VKIUBLBX.cjs.map +1 -0
  60. package/dist/index.cjs +1264 -778
  61. package/dist/index.cjs.map +1 -1
  62. package/dist/index.d.cts +7 -5
  63. package/dist/index.d.ts +7 -5
  64. package/dist/index.js +606 -120
  65. package/dist/index.js.map +1 -1
  66. package/dist/mcp.js +30 -31
  67. package/dist/mcp.js.map +1 -1
  68. package/dist/{model-bundle-O2XYR54X.js → model-bundle-THYUL7GG.js} +5 -5
  69. package/dist/{models-SKK3NH3V.js → models-U22N4RXX.js} +5 -5
  70. package/dist/page-range-QHHFTL7X.cjs.map +1 -1
  71. package/dist/{parser-PJUZSMFR.cjs → parser-JOMFOZLH.cjs} +213 -252
  72. package/dist/parser-JOMFOZLH.cjs.map +1 -0
  73. package/dist/{parser-4D2M5BKY.js → parser-NKP2NCSV.js} +27 -66
  74. package/dist/parser-NKP2NCSV.js.map +1 -0
  75. package/dist/{parser-5G5G7HHG.js → parser-SCXRLOW7.js} +24 -63
  76. package/dist/parser-SCXRLOW7.js.map +1 -0
  77. package/dist/pdf-ocr-NF4AY5MI.cjs +16 -0
  78. package/dist/pdf-ocr-NF4AY5MI.cjs.map +1 -0
  79. package/dist/pdf-ocr-OLII3WAG.js +15 -0
  80. package/dist/pdf-ocr-VJL7ON2Q.js +19 -0
  81. package/dist/{profile-io-BAQTYPK7.js → profile-io-UI3TZBYH.js} +3 -3
  82. package/dist/{rasterize-A2ZEACKV.js → rasterize-XMBV5H2I.js} +3 -3
  83. package/dist/{redact-doc-26KN2LSZ.js → redact-doc-7ZZMHDBO.js} +11 -11
  84. package/dist/{render-62ZUDMHB.js → render-SWRTUDAV.js} +7 -7
  85. package/dist/seal-UKKJZHKE.js +10 -0
  86. package/dist/{setup-2A3E6WRE.js → setup-43JJEEU7.js} +3 -3
  87. package/dist/visual-D2563HCJ.js +20 -0
  88. package/dist/{watch-D2T5FEKT.js → watch-NRATQ472.js} +14 -14
  89. package/dist/watch-NRATQ472.js.map +1 -0
  90. package/package.json +1 -1
  91. package/dist/chunk-6N5BOPJI.js.map +0 -1
  92. package/dist/chunk-6V7QRQY3.js.map +0 -1
  93. package/dist/chunk-7DC2KL3V.cjs.map +0 -1
  94. package/dist/chunk-CWJ5KY2F.js.map +0 -1
  95. package/dist/chunk-HUGBJVAA.js.map +0 -1
  96. package/dist/chunk-I7YWXECO.js.map +0 -1
  97. package/dist/chunk-IUMV45TX.cjs.map +0 -1
  98. package/dist/chunk-IXAXI2S3.cjs.map +0 -1
  99. package/dist/chunk-K35WIYBD.js.map +0 -1
  100. package/dist/chunk-PCSOJ523.cjs.map +0 -1
  101. package/dist/chunk-Q5N4YS3T.cjs.map +0 -1
  102. package/dist/chunk-SIZ63E5G.cjs.map +0 -1
  103. package/dist/chunk-TMC4A3FM.js.map +0 -1
  104. package/dist/chunk-UTVMLJZE.js.map +0 -1
  105. package/dist/chunk-VDIXNEWV.js.map +0 -1
  106. package/dist/chunk-WWOTHS2E.js.map +0 -1
  107. package/dist/chunks-ACUC63N3.js +0 -10
  108. package/dist/formula-W3GQC6L6.cjs.map +0 -1
  109. package/dist/image-ocr-7PNHBD2G.cjs.map +0 -1
  110. package/dist/parser-4D2M5BKY.js.map +0 -1
  111. package/dist/parser-5G5G7HHG.js.map +0 -1
  112. package/dist/parser-PJUZSMFR.cjs.map +0 -1
  113. package/dist/pdf-ocr-EGWOIB6O.cjs +0 -16
  114. package/dist/pdf-ocr-EGWOIB6O.cjs.map +0 -1
  115. package/dist/pdf-ocr-NJTFXBRC.js +0 -19
  116. package/dist/pdf-ocr-ZXR6Q6BK.js +0 -15
  117. package/dist/seal-3GXC2API.js +0 -10
  118. package/dist/visual-4ZBZRMCM.js +0 -20
  119. package/dist/watch-D2T5FEKT.js.map +0 -1
  120. /package/dist/{-X4KTLQC6.js.map → -WOKB25R2.js.map} +0 -0
  121. /package/dist/{chunk-KXR4CTFT.js.map → chunk-3FZGL3IL.js.map} +0 -0
  122. /package/dist/{chunk-R2IFWAHI.js.map → chunk-5X7XWYR2.js.map} +0 -0
  123. /package/dist/{chunk-PWRY4W6Q.js.map → chunk-6GLTGOP6.js.map} +0 -0
  124. /package/dist/{chunk-SQQ4ITJ5.js.map → chunk-AZQWESRH.js.map} +0 -0
  125. /package/dist/{chunk-KBZ3MQJX.js.map → chunk-BGOR5GCF.js.map} +0 -0
  126. /package/dist/{chunk-X625PCZM.js.map → chunk-IXX3WHIE.js.map} +0 -0
  127. /package/dist/{chunk-AQUNBGXH.js.map → chunk-KSJ7GKNQ.js.map} +0 -0
  128. /package/dist/{chunk-Z4KCEERM.js.map → chunk-NES5U4JK.js.map} +0 -0
  129. /package/dist/{chunk-MTTYJEKA.js.map → chunk-OOX2GZZ4.js.map} +0 -0
  130. /package/dist/{chunk-NQR3VKWN.js.map → chunk-RDBTOE5X.js.map} +0 -0
  131. /package/dist/{chunk-2VFZQ634.js.map → chunk-RRURZDEK.js.map} +0 -0
  132. /package/dist/{chunk-5PNQIF3V.js.map → chunk-W7P4GPOV.js.map} +0 -0
  133. /package/dist/{chunks-ACUC63N3.js.map → chunks-OQDRDICD.js.map} +0 -0
  134. /package/dist/{formula-LICM6K27.js.map → formula-GPCOJJXN.js.map} +0 -0
  135. /package/dist/{formula-T4Q2UHWO.js.map → formula-QZAOKPBX.js.map} +0 -0
  136. /package/dist/{image-ocr-WZJURDX6.js.map → image-ocr-POCME5I4.js.map} +0 -0
  137. /package/dist/{image-ocr-XB2NFKGZ.js.map → image-ocr-TWNNVTZS.js.map} +0 -0
  138. /package/dist/{model-bundle-O2XYR54X.js.map → model-bundle-THYUL7GG.js.map} +0 -0
  139. /package/dist/{models-SKK3NH3V.js.map → models-U22N4RXX.js.map} +0 -0
  140. /package/dist/{pdf-ocr-NJTFXBRC.js.map → pdf-ocr-OLII3WAG.js.map} +0 -0
  141. /package/dist/{pdf-ocr-ZXR6Q6BK.js.map → pdf-ocr-VJL7ON2Q.js.map} +0 -0
  142. /package/dist/{profile-io-BAQTYPK7.js.map → profile-io-UI3TZBYH.js.map} +0 -0
  143. /package/dist/{rasterize-A2ZEACKV.js.map → rasterize-XMBV5H2I.js.map} +0 -0
  144. /package/dist/{redact-doc-26KN2LSZ.js.map → redact-doc-7ZZMHDBO.js.map} +0 -0
  145. /package/dist/{render-62ZUDMHB.js.map → render-SWRTUDAV.js.map} +0 -0
  146. /package/dist/{seal-3GXC2API.js.map → seal-UKKJZHKE.js.map} +0 -0
  147. /package/dist/{setup-2A3E6WRE.js.map → setup-43JJEEU7.js.map} +0 -0
  148. /package/dist/{visual-4ZBZRMCM.js.map → visual-D2563HCJ.js.map} +0 -0
@@ -1,15 +1,88 @@
1
- #!/usr/bin/env node
2
1
  import {
3
2
  CELL_EDGES,
4
3
  HEADING_RATIO_H1,
5
4
  HEADING_RATIO_H2,
6
5
  HEADING_RATIO_H3,
7
6
  tidyScriptTags
8
- } from "./chunk-TMC4A3FM.js";
7
+ } from "./chunk-PSJLB3SZ.js";
8
+ import {
9
+ ensureModelsIn,
10
+ getModelsDir
11
+ } from "./chunk-3FZGL3IL.js";
9
12
  import {
10
13
  safeMax,
11
14
  safeMin
12
- } from "./chunk-I7YWXECO.js";
15
+ } from "./chunk-CAN5P6N6.js";
16
+
17
+ // src/ocr/models.ts
18
+ import { join } from "path";
19
+ import { stat } from "fs/promises";
20
+ var OCR_DET_MODEL = {
21
+ name: "PP-OCRv5 mobile det",
22
+ filename: "det.onnx",
23
+ url: "https://huggingface.co/PaddlePaddle/PP-OCRv5_mobile_det_onnx/resolve/main/inference.onnx",
24
+ sha256: "a431985659dc921974177a95adcfbb90fd9e51989a5e04d70d0b75f597b6e61d",
25
+ sizeMb: 5
26
+ };
27
+ var OCR_REC_MODEL = {
28
+ name: "PP-OCRv5 korean rec",
29
+ filename: "rec_korean.onnx",
30
+ url: "https://huggingface.co/PaddlePaddle/korean_PP-OCRv5_mobile_rec_onnx/resolve/main/inference.onnx",
31
+ sha256: "92f0b7785e64fc9090106a241cf4c1eb97472824558272751b88a2a4476d3a08",
32
+ sizeMb: 13
33
+ };
34
+ var OCR_REC_DICT = {
35
+ name: "PP-OCRv5 korean dict",
36
+ filename: "rec_korean.yml",
37
+ url: "https://huggingface.co/PaddlePaddle/korean_PP-OCRv5_mobile_rec_onnx/resolve/main/inference.yml",
38
+ sha256: "f757fa1c40e99edcf27e9cce879b93eb2a51fa46f5ef39095689b8c37dd75998",
39
+ sizeMb: 1
40
+ };
41
+ var ALL_OCR_MODELS = [OCR_DET_MODEL, OCR_REC_MODEL, OCR_REC_DICT];
42
+ function getOcrModelsDir() {
43
+ return getModelsDir("ppocr");
44
+ }
45
+ async function ensureOcrModels(onProgress) {
46
+ return ensureModelsIn(getOcrModelsDir(), ALL_OCR_MODELS, onProgress);
47
+ }
48
+ async function ocrModelsCached() {
49
+ const dir = getOcrModelsDir();
50
+ for (const spec of ALL_OCR_MODELS) {
51
+ try {
52
+ if (!(await stat(join(dir, spec.filename))).size) return false;
53
+ } catch {
54
+ return false;
55
+ }
56
+ }
57
+ return true;
58
+ }
59
+ function parseCharacterDict(yml) {
60
+ const lines = yml.split("\n");
61
+ const chars = [];
62
+ let inDict = false;
63
+ let dictIndent = -1;
64
+ for (const line of lines) {
65
+ if (!inDict) {
66
+ const m2 = /^(\s*)character_dict:\s*$/.exec(line);
67
+ if (m2) {
68
+ inDict = true;
69
+ dictIndent = m2[1].length;
70
+ }
71
+ continue;
72
+ }
73
+ const m = /^(\s*)- (.*)$/.exec(line);
74
+ if (m && m[1].length >= dictIndent) {
75
+ let v = m[2];
76
+ if (v.length >= 2 && (v.startsWith("'") && v.endsWith("'") || v.startsWith('"') && v.endsWith('"'))) {
77
+ v = v.slice(1, -1).replace(/''/g, "'");
78
+ }
79
+ chars.push(v);
80
+ continue;
81
+ }
82
+ if (line.trim() !== "") break;
83
+ }
84
+ return chars;
85
+ }
13
86
 
14
87
  // src/pdf/line-extract.ts
15
88
  import { OPS } from "pdfjs-dist/legacy/build/pdf.mjs";
@@ -3404,7 +3477,9 @@ function findVerticalCutWithOutlierFilter(items, minGap) {
3404
3477
  const filtered = items.filter((i) => i.w >= narrowThreshold);
3405
3478
  if (filtered.length >= 2 && filtered.length < items.length && filtered.length >= items.length * 0.7) {
3406
3479
  const filteredCut = findVerticalCut(filtered);
3407
- if (filteredCut.gap > edgeCut.gap && filteredCut.gap >= minGap) {
3480
+ const sameRow = (a, b) => Math.abs(a.y - b.y) <= Math.max(a.fontSize, b.fontSize) * 0.5;
3481
+ const inLine = items.some((r) => r.w < narrowThreshold && r.x < filteredCut.position && r.x + r.w > filteredCut.position && filtered.some((o) => sameRow(o, r) && o.x + o.w <= r.x + 1) && filtered.some((o) => sameRow(o, r) && o.x >= r.x + r.w - 1));
3482
+ if (filteredCut.gap > edgeCut.gap && filteredCut.gap >= minGap && !inLine) {
3408
3483
  return filteredCut;
3409
3484
  }
3410
3485
  }
@@ -4124,7 +4199,7 @@ function detectSpecialKoreanTables(blocks) {
4124
4199
  }
4125
4200
  function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables = false) {
4126
4201
  const ZONE_RATIO = 0.12;
4127
- const MIN_REPEAT = 3;
4202
+ const MIN_REPEAT2 = 3;
4128
4203
  const topEntries = [];
4129
4204
  const bottomEntries = [];
4130
4205
  for (let bi = 0; bi < blocks.length; bi++) {
@@ -4161,7 +4236,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables =
4161
4236
  const pages = [...patternPages.get(p) ?? []];
4162
4237
  const span = pages.length ? Math.max(...pages) - Math.min(...pages) + 1 : 0;
4163
4238
  const pageNumbered = !tables && (patternNumbers.get(p)?.size ?? 0) > 1;
4164
- if (count >= MIN_REPEAT && pages.length >= MIN_REPEAT && (pages.length >= span * 0.4 || pageNumbered)) {
4239
+ if (count >= MIN_REPEAT2 && pages.length >= MIN_REPEAT2 && (pages.length >= span * 0.4 || pageNumbered)) {
4165
4240
  repeatedPatterns.add(p);
4166
4241
  }
4167
4242
  }
@@ -4309,6 +4384,78 @@ function mergeSliverColumns(grid, colXs, maxWidth) {
4309
4384
  return merged;
4310
4385
  }
4311
4386
 
4387
+ // src/pdf/side-tabs.ts
4388
+ var BAND = 0.12;
4389
+ var MAX_CHARS = 10;
4390
+ var MIN_REPEAT = 3;
4391
+ var RUN_GAP = 5;
4392
+ var TAB_CELL_CHARS = 24;
4393
+ var TAB_MIN_HEIGHT = 0.3;
4394
+ var SIDE_TAB_TABLES = /* @__PURE__ */ new WeakSet();
4395
+ function isSideTabTable(box, table, others, pageWidth, pageHeight) {
4396
+ if (table.cols !== 1 || box.x2 - box.x1 > pageWidth * BAND || box.y2 - box.y1 < pageHeight * TAB_MIN_HEIGHT) return false;
4397
+ const side = box.x1 >= pageWidth * (1 - BAND) ? "R" : box.x2 <= pageWidth * BAND ? "L" : null;
4398
+ if (!side) return false;
4399
+ const texts = table.cells.flat().map((c) => c.text.replace(/\s+/g, ""));
4400
+ if (!texts.some(Boolean) || texts.some((t) => [...t].length > TAB_CELL_CHARS)) return false;
4401
+ return others.every((it) => it.y < box.y1 || it.y > box.y2 || (side === "R" ? it.x + it.w <= box.x1 + 1 : it.x >= box.x2 - 1));
4402
+ }
4403
+ function removeSideTabs(blocks, pageWidths) {
4404
+ const edges = /* @__PURE__ */ new Map();
4405
+ for (const b of blocks) {
4406
+ if (!b.bbox || b.pageNumber === void 0 || [...b.text?.trim() ?? ""].length <= MAX_CHARS) continue;
4407
+ const e = edges.get(b.pageNumber) ?? { lefts: [], rights: [] };
4408
+ e.lefts.push(b.bbox.x);
4409
+ e.rights.push(b.bbox.x + b.bbox.width);
4410
+ edges.set(b.pageNumber, e);
4411
+ }
4412
+ const q = (xs, p) => {
4413
+ const v = [...xs].sort((a, b) => a - b);
4414
+ return v[Math.min(v.length - 1, Math.floor(p * v.length))];
4415
+ };
4416
+ const body = /* @__PURE__ */ new Map();
4417
+ for (const [page, e] of edges) body.set(page, { left: q(e.lefts, 0.2), right: q(e.rights, 0.8) });
4418
+ const all = [...body.values()];
4419
+ const fallback = all.length ? { left: q(all.map((e) => e.left), 0.5), right: q(all.map((e) => e.right), 0.5) } : void 0;
4420
+ const key = (b) => {
4421
+ const w = b.pageNumber !== void 0 ? pageWidths.get(b.pageNumber) : void 0;
4422
+ const text = b.text?.trim();
4423
+ const area = (b.pageNumber !== void 0 ? body.get(b.pageNumber) : void 0) ?? fallback;
4424
+ if (b.type === "table") {
4425
+ if (!w || !b.bbox || !b.table || !SIDE_TAB_TABLES.has(b.table)) return null;
4426
+ return `${b.bbox.x >= w * (1 - BAND) ? "R" : "L"}${Math.round(b.bbox.x / 8)}`;
4427
+ }
4428
+ if (!w || !area || !b.bbox || !text || [...text].length > MAX_CHARS) return null;
4429
+ const side = b.bbox.x + b.bbox.width <= Math.min(w * BAND, area.left - 1) ? "L" : b.bbox.x >= Math.max(w * (1 - BAND), area.right + 1) ? "R" : null;
4430
+ return side && text.replace(/\s+/g, "");
4431
+ };
4432
+ const pages = /* @__PURE__ */ new Map();
4433
+ for (const b of blocks) {
4434
+ const k = key(b);
4435
+ if (k) pages.set(k, (pages.get(k) ?? /* @__PURE__ */ new Set()).add(b.pageNumber));
4436
+ }
4437
+ const running = /* @__PURE__ */ new Set();
4438
+ for (const [k, ps] of pages) {
4439
+ const list = [...ps].sort((a, b) => a - b);
4440
+ const steps = list.slice(1).map((p, i) => p - list[i]).sort((a, b) => a - b);
4441
+ const gap = Math.max(RUN_GAP, (steps[steps.length >> 1] ?? 1) * 3);
4442
+ let run = [];
4443
+ const flush = () => {
4444
+ if (run.length >= MIN_REPEAT && run.length >= (run[run.length - 1] - run[0] + 1) * 0.4) for (const p of run) running.add(`${p}\0${k}`);
4445
+ run = [];
4446
+ };
4447
+ for (const p of list) {
4448
+ if (run.length && p - run[run.length - 1] > gap) flush();
4449
+ run.push(p);
4450
+ }
4451
+ flush();
4452
+ }
4453
+ return running.size ? blocks.filter((b) => {
4454
+ const k = key(b);
4455
+ return !k || !running.has(`${b.pageNumber}\0${k}`);
4456
+ }) : blocks;
4457
+ }
4458
+
4312
4459
  // src/pdf/table-roles.ts
4313
4460
  var TOC_BLOCKS = /* @__PURE__ */ new WeakSet();
4314
4461
  var PAGE_LABEL = /^(?:\d{1,4}|[ivxlc]{1,7})$/i;
@@ -4415,6 +4562,8 @@ var MIN_GAP_FACTOR = 2;
4415
4562
  var MIN_GAP_ABSOLUTE = 20;
4416
4563
  var MIN_COL_FILL_RATIO = 0.4;
4417
4564
  function detectClusterTables(items, pageNum, rejected) {
4565
+ const tab = sideTabGlyphs(items);
4566
+ if (tab.size) items = items.filter((i) => !tab.has(i));
4418
4567
  if (items.length < MIN_ROWS * MIN_COLS) return [];
4419
4568
  const { merged, originMap } = mergeEvenSpacedClusters(items);
4420
4569
  const rows = mergeOverlappingRows(groupByBaseline(merged));
@@ -4474,6 +4623,36 @@ function detectClusterTables(items, pageNum, rejected) {
4474
4623
  return !prose;
4475
4624
  });
4476
4625
  }
4626
+ var SIDE_TAB_MIN = 6;
4627
+ function sideTabGlyphs(items) {
4628
+ const found = /* @__PURE__ */ new Set();
4629
+ const singles = items.filter((i) => i.fontSize > 0 && [...i.text.trim()].length === 1);
4630
+ if (singles.length < SIDE_TAB_MIN) return found;
4631
+ const cols = [];
4632
+ for (const it of [...singles].sort((a, b) => a.x - b.x)) {
4633
+ const c = cols.find((col) => Math.abs(col[0].x - it.x) <= Math.max(1.5, it.fontSize * 0.25));
4634
+ if (c) c.push(it);
4635
+ else cols.push([it]);
4636
+ }
4637
+ for (const col of cols) {
4638
+ if (col.length < SIDE_TAB_MIN) continue;
4639
+ if (col.filter((g) => /[\p{L}\p{N}]/u.test(g.text)).length < col.length * 0.8) continue;
4640
+ col.sort((a, b) => b.y - a.y);
4641
+ const fs = [...col.map((i) => i.fontSize)].sort((a, b) => a - b)[col.length >> 1];
4642
+ if (col.slice(1).some((it, k) => col[k].y - it.y > fs * 3)) continue;
4643
+ const members = new Set(col);
4644
+ const top = col[0].y + fs, bottom = col[col.length - 1].y - fs;
4645
+ const others = items.filter((i) => !members.has(i) && i.y <= top && i.y >= bottom);
4646
+ const left = Math.min(...col.map((i) => i.x)), right = Math.max(...col.map((i) => i.x + i.w));
4647
+ const rest = items.filter((i) => !members.has(i) && i.text.trim());
4648
+ const outside = rest.every((i) => i.x >= right + fs) || rest.every((i) => i.x + i.w <= left - fs);
4649
+ if (!outside) continue;
4650
+ const alone = col.filter((g) => !others.some((i) => Math.abs(i.y - g.y) <= Y_TOL)).length;
4651
+ if (alone < col.length * 0.4) continue;
4652
+ for (const g of col) found.add(g);
4653
+ }
4654
+ return found;
4655
+ }
4477
4656
  function detectCompactStatisticalTables(rows, pageNum) {
4478
4657
  const found = [];
4479
4658
  const parts = /* @__PURE__ */ new Map();
@@ -6661,6 +6840,11 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
6661
6840
  if (carry) carry.clip = void 0;
6662
6841
  return [];
6663
6842
  }
6843
+ const tab = sideTabGlyphs(items);
6844
+ if (tab.size) {
6845
+ const glyphs = [...tab].sort((a, b) => b.y - a.y).map((g) => ({ type: "paragraph", text: g.text.trim(), pageNumber: pageNum, bbox: computeBBox([g], pageNum), style: dominantStyle([g]) }));
6846
+ return [...glyphs, ...extractPageBlocksWithLines(items.filter((i) => !tab.has(i)), pageNum, opList, pageWidth, pageHeight, extraLines, detectTables, carry, lexicon)];
6847
+ }
6664
6848
  const lex = lexicon ?? new WrapLexicon();
6665
6849
  for (const line of streamLines(items)) lex.addLine(mergeLineSimple(line));
6666
6850
  const extracted = extractLines(opList.fnArray, opList.argsArray);
@@ -7022,6 +7206,12 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
7022
7206
  const emptyPart = !hasContent && !!grid.cells && !grid.clipParent && !nestedAttached;
7023
7207
  if (!hasContent && !emptyPart) continue;
7024
7208
  if (emptyPart) EMPTY_PARTS.add(irTable);
7209
+ const ownItems = numCols === 1 ? new Set(tableItems) : null;
7210
+ if (ownItems && isSideTabTable(grid.bbox, irTable, items.filter((it) => !ownItems.has(it)), pageWidth, pageHeight)) {
7211
+ SIDE_TAB_TABLES.add(irTable);
7212
+ blocks.push({ type: "table", table: irTable, pageNumber: pageNum, bbox: { page: pageNum, x: grid.bbox.x1, y: grid.bbox.y1, width: gridW, height: grid.bbox.y2 - grid.bbox.y1 } });
7213
+ continue;
7214
+ }
7025
7215
  if (grid.clipParent) {
7026
7216
  const nb = { page: pageNum, x: grid.bbox.x1, y: grid.bbox.y1, width: grid.bbox.x2 - grid.bbox.x1, height: grid.bbox.y2 - grid.bbox.y1 };
7027
7217
  pendingNested.push({ parent: grid.clipParent, block: { type: "table", table: irTable, pageNumber: pageNum, bbox: nb } });
@@ -7491,6 +7681,13 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
7491
7681
  }
7492
7682
 
7493
7683
  export {
7684
+ OCR_DET_MODEL,
7685
+ OCR_REC_MODEL,
7686
+ OCR_REC_DICT,
7687
+ getOcrModelsDir,
7688
+ ensureOcrModels,
7689
+ ocrModelsCached,
7690
+ parseCharacterDict,
7494
7691
  extractLines,
7495
7692
  extractImageRegions,
7496
7693
  filterHiddenText,
@@ -7529,6 +7726,7 @@ export {
7529
7726
  trimTrailingEmptyTableCols,
7530
7727
  NO_EDGES,
7531
7728
  joinCellEdges,
7729
+ removeSideTabs,
7532
7730
  extractPageBlocksWithLines
7533
7731
  };
7534
- //# sourceMappingURL=chunk-WWOTHS2E.js.map
7732
+ //# sourceMappingURL=chunk-BJ6RYYXV.js.map