kordoc 4.18.0 → 4.18.2

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 (144) hide show
  1. package/README.md +7 -6
  2. package/dist/{-DHSHP3AB.js → -I3CP33G4.js} +13 -11
  3. package/dist/{chunk-JUU2M5WI.js → chunk-4B2EXELH.js} +2 -2
  4. package/dist/{chunk-NYF7AGOX.js → chunk-6OKBTY72.js} +2 -2
  5. package/dist/{chunk-JU4DNVBP.js → chunk-B2E6C2LH.js} +27 -11
  6. package/dist/chunk-B2E6C2LH.js.map +1 -0
  7. package/dist/{chunk-UA7TQ37A.js → chunk-BL7KRE6X.js} +3 -3
  8. package/dist/{chunk-PGZX5JWZ.js → chunk-C2CVOC5K.js} +4 -4
  9. package/dist/{chunk-WSYTO525.js → chunk-CKUIFTXJ.js} +2 -2
  10. package/dist/{chunk-FPU7WPQM.js → chunk-F5HING4Y.js} +25 -9
  11. package/dist/chunk-F5HING4Y.js.map +1 -0
  12. package/dist/{chunk-VVJCQKXV.js → chunk-GM7XIZF2.js} +2 -2
  13. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  14. package/dist/{chunk-DSF64VZN.js → chunk-IA3UKDHA.js} +4 -4
  15. package/dist/chunk-IA3UKDHA.js.map +1 -0
  16. package/dist/chunk-J55UQC5H.cjs.map +1 -1
  17. package/dist/{chunk-ELTPM4HM.cjs → chunk-KDMAYOWH.cjs} +158 -43
  18. package/dist/chunk-KDMAYOWH.cjs.map +1 -0
  19. package/dist/{chunk-Q6SKAFWN.js → chunk-L5RLJPI3.js} +3 -3
  20. package/dist/{chunk-QBTYETIU.js → chunk-L64QRUMK.js} +202 -7
  21. package/dist/chunk-L64QRUMK.js.map +1 -0
  22. package/dist/{chunk-LLD4EY2F.js → chunk-LACO375L.js} +2 -2
  23. package/dist/{chunk-DT57TAEL.js → chunk-LSOD2A6N.js} +2 -2
  24. package/dist/{chunk-OLOMR452.js → chunk-M4P7YS2N.js} +395 -58
  25. package/dist/chunk-M4P7YS2N.js.map +1 -0
  26. package/dist/{chunk-5JFKSCTE.js → chunk-N5DQFA7L.js} +2 -2
  27. package/dist/{chunk-DTPALXTW.js → chunk-NZM2SSI4.js} +2 -2
  28. package/dist/{chunk-GNBQXQDK.js → chunk-O2DI4GHD.js} +2 -2
  29. package/dist/{chunk-32FQLCUJ.js → chunk-OBILAVWC.js} +2 -2
  30. package/dist/{chunk-PQZ4BDXT.js → chunk-OGAYGUJF.js} +122 -87
  31. package/dist/chunk-OGAYGUJF.js.map +1 -0
  32. package/dist/{chunk-2QBZMCRT.cjs → chunk-OI5ZSSIC.cjs} +12 -12
  33. package/dist/chunk-OI5ZSSIC.cjs.map +1 -0
  34. package/dist/{chunk-F4ESJBGU.cjs → chunk-QGFZU3JE.cjs} +31 -15
  35. package/dist/chunk-QGFZU3JE.cjs.map +1 -0
  36. package/dist/{chunk-WDJJ77HP.js → chunk-QP7IXF7R.js} +2 -2
  37. package/dist/{chunk-NKCKN4WW.js → chunk-T4MXCSBP.js} +137 -27
  38. package/dist/chunk-T4MXCSBP.js.map +1 -0
  39. package/dist/{chunk-CKMGVW6S.cjs → chunk-UZGZRGYM.cjs} +2 -2
  40. package/dist/chunk-UZGZRGYM.cjs.map +1 -0
  41. package/dist/{chunk-NIPT5FJO.js → chunk-VSY5PAJ5.js} +2 -2
  42. package/dist/{chunk-GP7BPJTU.cjs → chunk-W2YYBPW5.cjs} +3 -3
  43. package/dist/chunk-W2YYBPW5.cjs.map +1 -0
  44. package/dist/{chunk-RLVALQZI.cjs → chunk-YNLW6EGU.cjs} +3 -3
  45. package/dist/chunk-YNLW6EGU.cjs.map +1 -0
  46. package/dist/chunks-IFFRC5IQ.js +10 -0
  47. package/dist/cli.js +26 -26
  48. package/dist/{formula-6Q2SBBQ5.js → formula-AQZODKZF.js} +3 -3
  49. package/dist/{formula-M6JJBJ3O.js → formula-E3N7KDDG.js} +4 -4
  50. package/dist/{formula-43KHT3B3.cjs → formula-VY4ITOMN.cjs} +9 -9
  51. package/dist/formula-VY4ITOMN.cjs.map +1 -0
  52. package/dist/{image-ocr-22XQ4TMN.cjs → image-ocr-6LYEBMVR.cjs} +15 -15
  53. package/dist/image-ocr-6LYEBMVR.cjs.map +1 -0
  54. package/dist/{image-ocr-2FIFDA7I.js → image-ocr-IMYXOHHV.js} +6 -6
  55. package/dist/{image-ocr-TH2E6E3E.js → image-ocr-LN3GSQPW.js} +9 -9
  56. package/dist/index.cjs +1042 -603
  57. package/dist/index.cjs.map +1 -1
  58. package/dist/index.d.cts +8 -6
  59. package/dist/index.d.ts +8 -6
  60. package/dist/index.js +529 -90
  61. package/dist/index.js.map +1 -1
  62. package/dist/mcp.js +26 -27
  63. package/dist/mcp.js.map +1 -1
  64. package/dist/{model-bundle-MLEDO25V.js → model-bundle-IHKNDLOT.js} +5 -5
  65. package/dist/{models-MYB5M4XC.js → models-YXITRAMR.js} +5 -5
  66. package/dist/page-range-QHHFTL7X.cjs.map +1 -1
  67. package/dist/{parser-L77S4RZC.cjs → parser-7KECZTTP.cjs} +176 -228
  68. package/dist/parser-7KECZTTP.cjs.map +1 -0
  69. package/dist/{parser-BKTX4GVM.js → parser-KB4BYQBZ.js} +14 -66
  70. package/dist/parser-KB4BYQBZ.js.map +1 -0
  71. package/dist/{parser-WW7NWTUM.js → parser-M3T2EWUN.js} +11 -63
  72. package/dist/parser-M3T2EWUN.js.map +1 -0
  73. package/dist/pdf-ocr-4S2OAHUX.js +15 -0
  74. package/dist/pdf-ocr-IGYCZ7G2.cjs +16 -0
  75. package/dist/pdf-ocr-IGYCZ7G2.cjs.map +1 -0
  76. package/dist/pdf-ocr-YEBFWU2K.js +19 -0
  77. package/dist/{profile-io-XZPNRT4U.js → profile-io-GQWQR7YQ.js} +3 -3
  78. package/dist/{rasterize-4EWPBCOJ.js → rasterize-Y6TVFQ3M.js} +3 -3
  79. package/dist/{redact-doc-YYCWBWGL.js → redact-doc-TRPZ3HNW.js} +11 -11
  80. package/dist/{render-JNMBK4WF.js → render-GHT5HKBO.js} +7 -7
  81. package/dist/seal-3YTXSABW.js +10 -0
  82. package/dist/{setup-NM5ICZ4U.js → setup-AGSCEHDB.js} +3 -3
  83. package/dist/visual-R3E35Q2K.js +20 -0
  84. package/dist/{watch-PTTCHO32.js → watch-ALSEW4GB.js} +13 -13
  85. package/dist/watch-ALSEW4GB.js.map +1 -0
  86. package/package.json +1 -1
  87. package/dist/chunk-2QBZMCRT.cjs.map +0 -1
  88. package/dist/chunk-CKMGVW6S.cjs.map +0 -1
  89. package/dist/chunk-DSF64VZN.js.map +0 -1
  90. package/dist/chunk-ELTPM4HM.cjs.map +0 -1
  91. package/dist/chunk-F4ESJBGU.cjs.map +0 -1
  92. package/dist/chunk-FPU7WPQM.js.map +0 -1
  93. package/dist/chunk-GP7BPJTU.cjs.map +0 -1
  94. package/dist/chunk-JU4DNVBP.js.map +0 -1
  95. package/dist/chunk-NKCKN4WW.js.map +0 -1
  96. package/dist/chunk-OLOMR452.js.map +0 -1
  97. package/dist/chunk-PQZ4BDXT.js.map +0 -1
  98. package/dist/chunk-QBTYETIU.js.map +0 -1
  99. package/dist/chunk-RLVALQZI.cjs.map +0 -1
  100. package/dist/chunks-WTZTE3OL.js +0 -10
  101. package/dist/formula-43KHT3B3.cjs.map +0 -1
  102. package/dist/image-ocr-22XQ4TMN.cjs.map +0 -1
  103. package/dist/parser-BKTX4GVM.js.map +0 -1
  104. package/dist/parser-L77S4RZC.cjs.map +0 -1
  105. package/dist/parser-WW7NWTUM.js.map +0 -1
  106. package/dist/pdf-ocr-IUTBPKOM.js +0 -15
  107. package/dist/pdf-ocr-RQUU3JBR.js +0 -19
  108. package/dist/pdf-ocr-ZWF6ZXLP.cjs +0 -16
  109. package/dist/pdf-ocr-ZWF6ZXLP.cjs.map +0 -1
  110. package/dist/seal-ZIVUVBLM.js +0 -10
  111. package/dist/visual-4W4RBIOA.js +0 -20
  112. package/dist/watch-PTTCHO32.js.map +0 -1
  113. /package/dist/{-DHSHP3AB.js.map → -I3CP33G4.js.map} +0 -0
  114. /package/dist/{chunk-JUU2M5WI.js.map → chunk-4B2EXELH.js.map} +0 -0
  115. /package/dist/{chunk-NYF7AGOX.js.map → chunk-6OKBTY72.js.map} +0 -0
  116. /package/dist/{chunk-UA7TQ37A.js.map → chunk-BL7KRE6X.js.map} +0 -0
  117. /package/dist/{chunk-PGZX5JWZ.js.map → chunk-C2CVOC5K.js.map} +0 -0
  118. /package/dist/{chunk-WSYTO525.js.map → chunk-CKUIFTXJ.js.map} +0 -0
  119. /package/dist/{chunk-VVJCQKXV.js.map → chunk-GM7XIZF2.js.map} +0 -0
  120. /package/dist/{chunk-Q6SKAFWN.js.map → chunk-L5RLJPI3.js.map} +0 -0
  121. /package/dist/{chunk-LLD4EY2F.js.map → chunk-LACO375L.js.map} +0 -0
  122. /package/dist/{chunk-DT57TAEL.js.map → chunk-LSOD2A6N.js.map} +0 -0
  123. /package/dist/{chunk-5JFKSCTE.js.map → chunk-N5DQFA7L.js.map} +0 -0
  124. /package/dist/{chunk-DTPALXTW.js.map → chunk-NZM2SSI4.js.map} +0 -0
  125. /package/dist/{chunk-GNBQXQDK.js.map → chunk-O2DI4GHD.js.map} +0 -0
  126. /package/dist/{chunk-32FQLCUJ.js.map → chunk-OBILAVWC.js.map} +0 -0
  127. /package/dist/{chunk-WDJJ77HP.js.map → chunk-QP7IXF7R.js.map} +0 -0
  128. /package/dist/{chunk-NIPT5FJO.js.map → chunk-VSY5PAJ5.js.map} +0 -0
  129. /package/dist/{chunks-WTZTE3OL.js.map → chunks-IFFRC5IQ.js.map} +0 -0
  130. /package/dist/{formula-6Q2SBBQ5.js.map → formula-AQZODKZF.js.map} +0 -0
  131. /package/dist/{formula-M6JJBJ3O.js.map → formula-E3N7KDDG.js.map} +0 -0
  132. /package/dist/{image-ocr-2FIFDA7I.js.map → image-ocr-IMYXOHHV.js.map} +0 -0
  133. /package/dist/{image-ocr-TH2E6E3E.js.map → image-ocr-LN3GSQPW.js.map} +0 -0
  134. /package/dist/{model-bundle-MLEDO25V.js.map → model-bundle-IHKNDLOT.js.map} +0 -0
  135. /package/dist/{models-MYB5M4XC.js.map → models-YXITRAMR.js.map} +0 -0
  136. /package/dist/{pdf-ocr-IUTBPKOM.js.map → pdf-ocr-4S2OAHUX.js.map} +0 -0
  137. /package/dist/{pdf-ocr-RQUU3JBR.js.map → pdf-ocr-YEBFWU2K.js.map} +0 -0
  138. /package/dist/{profile-io-XZPNRT4U.js.map → profile-io-GQWQR7YQ.js.map} +0 -0
  139. /package/dist/{rasterize-4EWPBCOJ.js.map → rasterize-Y6TVFQ3M.js.map} +0 -0
  140. /package/dist/{redact-doc-YYCWBWGL.js.map → redact-doc-TRPZ3HNW.js.map} +0 -0
  141. /package/dist/{render-JNMBK4WF.js.map → render-GHT5HKBO.js.map} +0 -0
  142. /package/dist/{seal-ZIVUVBLM.js.map → seal-3YTXSABW.js.map} +0 -0
  143. /package/dist/{setup-NM5ICZ4U.js.map → setup-AGSCEHDB.js.map} +0 -0
  144. /package/dist/{visual-4W4RBIOA.js.map → visual-R3E35Q2K.js.map} +0 -0
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  parseRenderStyles
4
- } from "./chunk-LLD4EY2F.js";
4
+ } from "./chunk-LACO375L.js";
5
5
  import {
6
6
  KordocError,
7
7
  precheckZipSize
8
- } from "./chunk-32FQLCUJ.js";
8
+ } from "./chunk-OBILAVWC.js";
9
9
 
10
10
  // src/form/seal.ts
11
11
  import JSZip from "jszip";
@@ -1057,4 +1057,4 @@ export {
1057
1057
  patchZipEntries,
1058
1058
  placeSealHwpx
1059
1059
  };
1060
- //# sourceMappingURL=chunk-Q6SKAFWN.js.map
1060
+ //# sourceMappingURL=chunk-L5RLJPI3.js.map
@@ -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-FPU7WPQM.js";
7
+ } from "./chunk-B2E6C2LH.js";
8
+ import {
9
+ ensureModelsIn,
10
+ getModelsDir
11
+ } from "./chunk-LSOD2A6N.js";
9
12
  import {
10
13
  safeMax,
11
14
  safeMin
12
- } from "./chunk-32FQLCUJ.js";
15
+ } from "./chunk-N5DQFA7L.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,34 @@ 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
+ col.sort((a, b) => b.y - a.y);
4640
+ const fs = [...col.map((i) => i.fontSize)].sort((a, b) => a - b)[col.length >> 1];
4641
+ if (col.slice(1).some((it, k) => col[k].y - it.y > fs * 3)) continue;
4642
+ const members = new Set(col);
4643
+ const top = col[0].y + fs, bottom = col[col.length - 1].y - fs;
4644
+ const others = items.filter((i) => !members.has(i) && i.y <= top && i.y >= bottom);
4645
+ const left = Math.min(...col.map((i) => i.x)), right = Math.max(...col.map((i) => i.x + i.w));
4646
+ const outside = others.every((i) => i.x >= right + fs) || others.every((i) => i.x + i.w <= left - fs);
4647
+ if (!outside) continue;
4648
+ const alone = col.filter((g) => !others.some((i) => Math.abs(i.y - g.y) <= Y_TOL)).length;
4649
+ if (alone < col.length * 0.4) continue;
4650
+ for (const g of col) found.add(g);
4651
+ }
4652
+ return found;
4653
+ }
4477
4654
  function detectCompactStatisticalTables(rows, pageNum) {
4478
4655
  const found = [];
4479
4656
  const parts = /* @__PURE__ */ new Map();
@@ -6661,6 +6838,11 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
6661
6838
  if (carry) carry.clip = void 0;
6662
6839
  return [];
6663
6840
  }
6841
+ const tab = sideTabGlyphs(items);
6842
+ if (tab.size) {
6843
+ 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]) }));
6844
+ return [...glyphs, ...extractPageBlocksWithLines(items.filter((i) => !tab.has(i)), pageNum, opList, pageWidth, pageHeight, extraLines, detectTables, carry, lexicon)];
6845
+ }
6664
6846
  const lex = lexicon ?? new WrapLexicon();
6665
6847
  for (const line of streamLines(items)) lex.addLine(mergeLineSimple(line));
6666
6848
  const extracted = extractLines(opList.fnArray, opList.argsArray);
@@ -7022,6 +7204,11 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
7022
7204
  const emptyPart = !hasContent && !!grid.cells && !grid.clipParent && !nestedAttached;
7023
7205
  if (!hasContent && !emptyPart) continue;
7024
7206
  if (emptyPart) EMPTY_PARTS.add(irTable);
7207
+ if (numCols === 1 && isSideTabTable(grid.bbox, irTable, items.filter((it) => !tableItems.includes(it)), pageWidth, pageHeight)) {
7208
+ SIDE_TAB_TABLES.add(irTable);
7209
+ 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 } });
7210
+ continue;
7211
+ }
7025
7212
  if (grid.clipParent) {
7026
7213
  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
7214
  pendingNested.push({ parent: grid.clipParent, block: { type: "table", table: irTable, pageNumber: pageNum, bbox: nb } });
@@ -7491,6 +7678,13 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
7491
7678
  }
7492
7679
 
7493
7680
  export {
7681
+ OCR_DET_MODEL,
7682
+ OCR_REC_MODEL,
7683
+ OCR_REC_DICT,
7684
+ getOcrModelsDir,
7685
+ ensureOcrModels,
7686
+ ocrModelsCached,
7687
+ parseCharacterDict,
7494
7688
  extractLines,
7495
7689
  extractImageRegions,
7496
7690
  filterHiddenText,
@@ -7529,6 +7723,7 @@ export {
7529
7723
  trimTrailingEmptyTableCols,
7530
7724
  NO_EDGES,
7531
7725
  joinCellEdges,
7726
+ removeSideTabs,
7532
7727
  extractPageBlocksWithLines
7533
7728
  };
7534
- //# sourceMappingURL=chunk-QBTYETIU.js.map
7729
+ //# sourceMappingURL=chunk-L64QRUMK.js.map