kordoc 4.14.2 → 4.14.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 (151) hide show
  1. package/README.md +38 -5
  2. package/dist/{-AQKXLFIM.js → -7XBPXCXN.js} +13 -11
  3. package/dist/{chunk-FOJZNMMK.js → chunk-2LQGSDZ6.js} +1 -1
  4. package/dist/chunk-2LQGSDZ6.js.map +1 -0
  5. package/dist/chunk-4R67INKT.js +1002 -0
  6. package/dist/chunk-4R67INKT.js.map +1 -0
  7. package/dist/{chunk-ILU76UF3.js → chunk-4RJ5D7MT.js} +2 -2
  8. package/dist/chunk-4RJ5D7MT.js.map +1 -0
  9. package/dist/{chunk-EQZI77PP.cjs → chunk-5VVS2QIJ.cjs} +3 -3
  10. package/dist/{chunk-EQZI77PP.cjs.map → chunk-5VVS2QIJ.cjs.map} +1 -1
  11. package/dist/{chunk-3DUADAY2.js → chunk-A275ZQLX.js} +209 -87
  12. package/dist/chunk-A275ZQLX.js.map +1 -0
  13. package/dist/{chunk-EISO3POT.js → chunk-CVEERPMP.js} +788 -194
  14. package/dist/chunk-CVEERPMP.js.map +1 -0
  15. package/dist/{chunk-ZWD734EY.js → chunk-D6KQKMU3.js} +2 -2
  16. package/dist/{chunk-QOMNEWCQ.cjs → chunk-EBZUZC6F.cjs} +305 -31
  17. package/dist/chunk-EBZUZC6F.cjs.map +1 -0
  18. package/dist/{chunk-HR2XNERB.cjs → chunk-EMGF6EEV.cjs} +2 -2
  19. package/dist/{chunk-HR2XNERB.cjs.map → chunk-EMGF6EEV.cjs.map} +1 -1
  20. package/dist/{chunk-GDW4YP7K.js → chunk-FAZR34CA.js} +2 -2
  21. package/dist/{chunk-TNCKOL2O.js → chunk-GTINVM5K.js} +2 -2
  22. package/dist/{chunk-L7DMSMAG.cjs → chunk-HX4UUF7Y.cjs} +1 -1
  23. package/dist/chunk-HX4UUF7Y.cjs.map +1 -0
  24. package/dist/{chunk-UET462HB.js → chunk-I4NNYWIR.js} +2 -2
  25. package/dist/chunk-IH56ZISC.js +620 -0
  26. package/dist/chunk-IH56ZISC.js.map +1 -0
  27. package/dist/{chunk-EDNJLUSE.js → chunk-IHZEFW4L.js} +2 -2
  28. package/dist/chunk-IW2CB755.cjs +1002 -0
  29. package/dist/chunk-IW2CB755.cjs.map +1 -0
  30. package/dist/{chunk-ZWOFQRIB.js → chunk-JCVIOLBF.js} +3 -3
  31. package/dist/{chunk-JQEFP45L.js → chunk-L5EH2NVO.js} +2 -2
  32. package/dist/{chunk-247ANM72.cjs → chunk-NOAQRCV6.cjs} +219 -97
  33. package/dist/chunk-NOAQRCV6.cjs.map +1 -0
  34. package/dist/{chunk-7IAQ4HOK.js → chunk-NQCUAGLR.js} +1 -1
  35. package/dist/chunk-NQCUAGLR.js.map +1 -0
  36. package/dist/{chunk-NS55SM7A.js → chunk-O2PGQNYE.js} +2 -2
  37. package/dist/{chunk-QC5T6D4J.js → chunk-QGW7NMTX.js} +299 -25
  38. package/dist/chunk-QGW7NMTX.js.map +1 -0
  39. package/dist/{chunk-A7QC2ZVP.js → chunk-UVVEBI22.js} +209 -87
  40. package/dist/chunk-UVVEBI22.js.map +1 -0
  41. package/dist/chunk-VJHAUMCF.js +949 -0
  42. package/dist/chunk-VJHAUMCF.js.map +1 -0
  43. package/dist/{chunk-C7FQBSON.js → chunk-VNFJPTU4.js} +2 -2
  44. package/dist/{chunk-VQ5W4MYO.js → chunk-VYOGXNQ3.js} +298 -24
  45. package/dist/chunk-VYOGXNQ3.js.map +1 -0
  46. package/dist/{chunk-DOGPOY4B.js → chunk-WB5LW52Z.js} +2 -2
  47. package/dist/{chunk-TSFS5VKD.js → chunk-YGBZABI4.js} +332 -141
  48. package/dist/chunk-YGBZABI4.js.map +1 -0
  49. package/dist/chunks-I7TEMJXH.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-CPO2TZGB.cjs} +9 -9
  53. package/dist/{formula-PJJ6S3Z2.cjs.map → formula-CPO2TZGB.cjs.map} +1 -1
  54. package/dist/{formula-5S7WWXGH.js → formula-NOIDZEBA.js} +4 -4
  55. package/dist/{formula-JGFTXWYT.js → formula-X44GV7TN.js} +3 -3
  56. package/dist/{image-ocr-WCAYXLOA.js → image-ocr-72RAR4WR.js} +34 -16
  57. package/dist/image-ocr-72RAR4WR.js.map +1 -0
  58. package/dist/{image-ocr-FLIL7MGN.js → image-ocr-R6W6A75P.js} +32 -14
  59. package/dist/image-ocr-R6W6A75P.js.map +1 -0
  60. package/dist/{image-ocr-ZTYAGV3W.cjs → image-ocr-SUGT64ZM.cjs} +36 -18
  61. package/dist/image-ocr-SUGT64ZM.cjs.map +1 -0
  62. package/dist/index.cjs +2416 -1184
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +62 -25
  65. package/dist/index.d.ts +62 -25
  66. package/dist/index.js +1853 -621
  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-57CLEBCO.js} +5 -5
  71. package/dist/{models-CJPAQK5R.js → models-7ELIFTD7.js} +5 -5
  72. package/dist/{parser-SCUTZAIJ.js → parser-4NKAYWAX.js} +261 -241
  73. package/dist/parser-4NKAYWAX.js.map +1 -0
  74. package/dist/{parser-A4TMPJAM.js → parser-HWFQRSUQ.js} +261 -241
  75. package/dist/parser-HWFQRSUQ.js.map +1 -0
  76. package/dist/{parser-VCXE4I5A.cjs → parser-RANGXGBD.cjs} +289 -269
  77. package/dist/parser-RANGXGBD.cjs.map +1 -0
  78. package/dist/pdf-ocr-BNC34MNU.js +13 -0
  79. package/dist/pdf-ocr-QX2GB33Q.js +16 -0
  80. package/dist/pdf-ocr-VHSFACH7.cjs +14 -0
  81. package/dist/{pdf-ocr-MBZZ57LD.cjs.map → pdf-ocr-VHSFACH7.cjs.map} +1 -1
  82. package/dist/{profile-io-LBM263K7.js → profile-io-V52PL5ZO.js} +3 -3
  83. package/dist/{rasterize-46RG4ZF6.js → rasterize-ZIGLJDOG.js} +3 -3
  84. package/dist/redact-TIQEQI3M.js +18 -0
  85. package/dist/redact-doc-KXZ3TZAG.js +1216 -0
  86. package/dist/redact-doc-KXZ3TZAG.js.map +1 -0
  87. package/dist/{render-NGP5T24S.js → render-U5PE6V2E.js} +7 -7
  88. package/dist/seal-DNXJBILR.js +10 -0
  89. package/dist/{setup-AU4OCHNH.js → setup-YRDM4ODP.js} +3 -3
  90. package/dist/visual-5XWMA4EV.js +19 -0
  91. package/dist/{watch-MKPUCPXM.js → watch-5IOLBATT.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 → -7XBPXCXN.js.map} +0 -0
  127. /package/dist/{chunk-ZWD734EY.js.map → chunk-D6KQKMU3.js.map} +0 -0
  128. /package/dist/{chunk-GDW4YP7K.js.map → chunk-FAZR34CA.js.map} +0 -0
  129. /package/dist/{chunk-TNCKOL2O.js.map → chunk-GTINVM5K.js.map} +0 -0
  130. /package/dist/{chunk-UET462HB.js.map → chunk-I4NNYWIR.js.map} +0 -0
  131. /package/dist/{chunk-EDNJLUSE.js.map → chunk-IHZEFW4L.js.map} +0 -0
  132. /package/dist/{chunk-ZWOFQRIB.js.map → chunk-JCVIOLBF.js.map} +0 -0
  133. /package/dist/{chunk-JQEFP45L.js.map → chunk-L5EH2NVO.js.map} +0 -0
  134. /package/dist/{chunk-NS55SM7A.js.map → chunk-O2PGQNYE.js.map} +0 -0
  135. /package/dist/{chunk-C7FQBSON.js.map → chunk-VNFJPTU4.js.map} +0 -0
  136. /package/dist/{chunk-DOGPOY4B.js.map → chunk-WB5LW52Z.js.map} +0 -0
  137. /package/dist/{chunks-SX77P5CV.js.map → chunks-I7TEMJXH.js.map} +0 -0
  138. /package/dist/{formula-5S7WWXGH.js.map → formula-NOIDZEBA.js.map} +0 -0
  139. /package/dist/{formula-JGFTXWYT.js.map → formula-X44GV7TN.js.map} +0 -0
  140. /package/dist/{model-bundle-FSPZZ2EM.js.map → model-bundle-57CLEBCO.js.map} +0 -0
  141. /package/dist/{models-CJPAQK5R.js.map → models-7ELIFTD7.js.map} +0 -0
  142. /package/dist/{pdf-ocr-76SAUXMZ.js.map → pdf-ocr-BNC34MNU.js.map} +0 -0
  143. /package/dist/{pdf-ocr-CPU55CVF.js.map → pdf-ocr-QX2GB33Q.js.map} +0 -0
  144. /package/dist/{profile-io-LBM263K7.js.map → profile-io-V52PL5ZO.js.map} +0 -0
  145. /package/dist/{rasterize-46RG4ZF6.js.map → rasterize-ZIGLJDOG.js.map} +0 -0
  146. /package/dist/{redact-7ILEAUTS.js.map → redact-TIQEQI3M.js.map} +0 -0
  147. /package/dist/{render-NGP5T24S.js.map → render-U5PE6V2E.js.map} +0 -0
  148. /package/dist/{seal-RGUPOLXD.js.map → seal-DNXJBILR.js.map} +0 -0
  149. /package/dist/{setup-AU4OCHNH.js.map → setup-YRDM4ODP.js.map} +0 -0
  150. /package/dist/{visual-NZLYIYEM.js.map → visual-5XWMA4EV.js.map} +0 -0
  151. /package/dist/{watch-MKPUCPXM.js.map → watch-5IOLBATT.js.map} +0 -0
@@ -1,571 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
-
3
-
4
- var _chunkEQZI77PPcjs = require('./chunk-EQZI77PP.cjs');
5
-
6
-
7
- var _chunk247ANM72cjs = require('./chunk-247ANM72.cjs');
8
-
9
- // src/ocr/ruling-lines.ts
10
- var INK_LUMA_MAX = 190;
11
- var MIN_LINE_LENGTH_PT = 20;
12
- var MAX_LINE_WIDTH_PT = 2.5;
13
- var GAP_TOL_PX = 2;
14
- var BAND_OVERLAP_RATIO = 0.5;
15
- var SURROUND_INK_RATIO = 0.35;
16
- function detectRulingLines(rgba, width, height, scale) {
17
- const minLenPx = Math.round(MIN_LINE_LENGTH_PT * scale);
18
- const maxThickPx = Math.max(1, Math.floor(MAX_LINE_WIDTH_PT * scale));
19
- const ink = new Uint8Array(width * height);
20
- for (let p = 0, i = 0; p < ink.length; p++, i += 4) {
21
- const luma = rgba[i] * 77 + rgba[i + 1] * 150 + rgba[i + 2] * 29 >> 8;
22
- if (luma <= INK_LUMA_MAX && rgba[i + 3] >= 128) ink[p] = 1;
23
- }
24
- const horizontals = detectBands(ink, width, height, minLenPx, maxThickPx, false);
25
- const verticals = detectBands(ink, width, height, minLenPx, maxThickPx, true);
26
- return { horizontals, verticals };
27
- }
28
- function detectBands(ink, width, height, minLenPx, maxThickPx, transpose) {
29
- const lines = transpose ? width : height;
30
- const span = transpose ? height : width;
31
- const at = transpose ? (line, pos) => ink[pos * width + line] : (line, pos) => ink[line * width + pos];
32
- const out = [];
33
- let open = [];
34
- const surroundInkRatio = (b, side) => {
35
- if (side < 0 || side >= lines) return 0;
36
- let dark = 0, total = 0;
37
- for (let pos = b.lo; pos <= b.hi; pos += 3) {
38
- total++;
39
- if (at(side, pos) === 1) dark++;
40
- }
41
- return total > 0 ? dark / total : 0;
42
- };
43
- const emit = (b) => {
44
- const thick = b.last - b.first + 1;
45
- if (thick > maxThickPx) return;
46
- if (surroundInkRatio(b, b.first - 2) >= SURROUND_INK_RATIO && surroundInkRatio(b, b.last + 2) >= SURROUND_INK_RATIO) return;
47
- const center = (b.first + b.last) / 2;
48
- out.push(
49
- transpose ? { x1: center, y1: b.lo, x2: center, y2: b.hi, thicknessPx: thick } : { x1: b.lo, y1: center, x2: b.hi, y2: center, thicknessPx: thick }
50
- );
51
- };
52
- for (let line = 0; line < lines; line++) {
53
- const runs = [];
54
- let runStart = -1;
55
- let gap = 0;
56
- for (let pos = 0; pos <= span; pos++) {
57
- const on = pos < span && at(line, pos) === 1;
58
- if (on) {
59
- if (runStart < 0) runStart = pos;
60
- gap = 0;
61
- } else if (runStart >= 0) {
62
- if (++gap > GAP_TOL_PX || pos >= span) {
63
- const hi = pos - gap;
64
- if (hi - runStart + 1 >= minLenPx) runs.push({ lo: runStart, hi });
65
- runStart = -1;
66
- gap = 0;
67
- }
68
- }
69
- }
70
- const next = [];
71
- const used = /* @__PURE__ */ new Set();
72
- for (const band of open) {
73
- if (band.last !== line - 1) {
74
- emit(band);
75
- continue;
76
- }
77
- let merged = false;
78
- for (let r = 0; r < runs.length; r++) {
79
- if (used.has(r)) continue;
80
- const run = runs[r];
81
- const overlap = Math.min(band.hi, run.hi) - Math.max(band.lo, run.lo) + 1;
82
- const shorter = Math.min(band.hi - band.lo, run.hi - run.lo) + 1;
83
- if (overlap >= shorter * BAND_OVERLAP_RATIO) {
84
- band.lo = Math.min(band.lo, run.lo);
85
- band.hi = Math.max(band.hi, run.hi);
86
- band.last = line;
87
- next.push(band);
88
- used.add(r);
89
- merged = true;
90
- break;
91
- }
92
- }
93
- if (!merged) emit(band);
94
- }
95
- for (let r = 0; r < runs.length; r++) {
96
- if (!used.has(r)) next.push({ lo: runs[r].lo, hi: runs[r].hi, first: line, last: line });
97
- }
98
- open = next;
99
- }
100
- for (const band of open) emit(band);
101
- return out;
102
- }
103
- function rulingToPdfLines(ruling, scale, pdfHeight) {
104
- const horizontals = ruling.horizontals.map((s) => {
105
- const y = pdfHeight - (s.y1 + s.y2) / 2 / scale;
106
- return {
107
- x1: Math.min(s.x1, s.x2) / scale,
108
- y1: y,
109
- x2: Math.max(s.x1, s.x2) / scale,
110
- y2: y,
111
- lineWidth: s.thicknessPx / scale
112
- };
113
- });
114
- const verticals = ruling.verticals.map((s) => {
115
- const x = (s.x1 + s.x2) / 2 / scale;
116
- const yA = pdfHeight - Math.max(s.y1, s.y2) / scale;
117
- const yB = pdfHeight - Math.min(s.y1, s.y2) / scale;
118
- return { x1: x, y1: yA, x2: x, y2: yB, lineWidth: s.thicknessPx / scale };
119
- });
120
- return { horizontals, verticals };
121
- }
122
-
123
- // src/ocr/engine.ts
124
- var _promises = require('fs/promises');
125
- var _path = require('path');
126
-
127
- // src/ocr/models.ts
128
- var OCR_DET_MODEL = {
129
- name: "PP-OCRv5 mobile det",
130
- filename: "det.onnx",
131
- url: "https://huggingface.co/PaddlePaddle/PP-OCRv5_mobile_det_onnx/resolve/main/inference.onnx",
132
- sha256: "a431985659dc921974177a95adcfbb90fd9e51989a5e04d70d0b75f597b6e61d",
133
- sizeMb: 5
134
- };
135
- var OCR_REC_MODEL = {
136
- name: "PP-OCRv5 korean rec",
137
- filename: "rec_korean.onnx",
138
- url: "https://huggingface.co/PaddlePaddle/korean_PP-OCRv5_mobile_rec_onnx/resolve/main/inference.onnx",
139
- sha256: "92f0b7785e64fc9090106a241cf4c1eb97472824558272751b88a2a4476d3a08",
140
- sizeMb: 13
141
- };
142
- var OCR_REC_DICT = {
143
- name: "PP-OCRv5 korean dict",
144
- filename: "rec_korean.yml",
145
- url: "https://huggingface.co/PaddlePaddle/korean_PP-OCRv5_mobile_rec_onnx/resolve/main/inference.yml",
146
- sha256: "f757fa1c40e99edcf27e9cce879b93eb2a51fa46f5ef39095689b8c37dd75998",
147
- sizeMb: 1
148
- };
149
- var ALL_OCR_MODELS = [OCR_DET_MODEL, OCR_REC_MODEL, OCR_REC_DICT];
150
- function getOcrModelsDir() {
151
- return _chunkEQZI77PPcjs.getModelsDir.call(void 0, "ppocr");
152
- }
153
- async function ensureOcrModels(onProgress) {
154
- return _chunkEQZI77PPcjs.ensureModelsIn.call(void 0, getOcrModelsDir(), ALL_OCR_MODELS, onProgress);
155
- }
156
- function parseCharacterDict(yml) {
157
- const lines = yml.split("\n");
158
- const chars = [];
159
- let inDict = false;
160
- let dictIndent = -1;
161
- for (const line of lines) {
162
- if (!inDict) {
163
- const m2 = /^(\s*)character_dict:\s*$/.exec(line);
164
- if (m2) {
165
- inDict = true;
166
- dictIndent = m2[1].length;
167
- }
168
- continue;
169
- }
170
- const m = /^(\s*)- (.*)$/.exec(line);
171
- if (m && m[1].length >= dictIndent) {
172
- let v = m[2];
173
- if (v.length >= 2 && (v.startsWith("'") && v.endsWith("'") || v.startsWith('"') && v.endsWith('"'))) {
174
- v = v.slice(1, -1).replace(/''/g, "'");
175
- }
176
- chars.push(v);
177
- continue;
178
- }
179
- if (line.trim() !== "") break;
180
- }
181
- return chars;
182
- }
183
-
184
- // src/ocr/engine.ts
185
- var DET_LONG_SIDE = 960;
186
- var DET_THRESH = 0.3;
187
- var DET_BOX_THRESH = 0.6;
188
- var DET_UNCLIP_RATIO = 1.5;
189
- var DET_MIN_SIZE = 3;
190
- var DET_MAX_BOXES = 1e3;
191
- var REC_HEIGHT = 48;
192
- var REC_MIN_WIDTH = 320;
193
- var REC_MAX_WIDTH = 3200;
194
- var TEXT_SCORE = 0.5;
195
- var DET_MEAN = [0.485, 0.456, 0.406];
196
- var DET_STD = [0.229, 0.224, 0.225];
197
- var OcrEngine = class _OcrEngine {
198
-
199
-
200
-
201
-
202
-
203
- constructor(parts) {
204
- this.det = parts.det;
205
- this.rec = parts.rec;
206
- this.dict = parts.dict;
207
- this.ort = parts.ort;
208
- this.sharp = parts.sharp;
209
- }
210
- static async create() {
211
- const [ortMod, sharpModRaw] = await Promise.all([
212
- tryImport("onnxruntime-node", () => Promise.resolve().then(() => _interopRequireWildcard(require("onnxruntime-node")))),
213
- tryImport(
214
- "sharp",
215
- () => Promise.resolve().then(() => _interopRequireWildcard(require("sharp")))
216
- )
217
- ]);
218
- const sharpAny = sharpModRaw;
219
- const sharpMod = typeof sharpAny === "function" ? sharpAny : _nullishCoalesce(sharpAny.default, () => ( sharpAny));
220
- const dir = getOcrModelsDir();
221
- const sessionOpts = {
222
- graphOptimizationLevel: "all",
223
- executionProviders: ["cpu"],
224
- logSeverityLevel: 3
225
- // paddle2onnx 변환 잔여물 W 로그 폭주 억제
226
- };
227
- const [det, rec, dictYml] = await Promise.all([
228
- ortMod.InferenceSession.create(_path.join.call(void 0, dir, OCR_DET_MODEL.filename), sessionOpts),
229
- ortMod.InferenceSession.create(_path.join.call(void 0, dir, OCR_REC_MODEL.filename), sessionOpts),
230
- _promises.readFile.call(void 0, _path.join.call(void 0, dir, OCR_REC_DICT.filename), "utf-8")
231
- ]);
232
- const dict = parseCharacterDict(dictYml);
233
- if (dict.length === 0) throw new Error("OCR \uC0AC\uC804 \uD30C\uC2F1 \uC2E4\uD328 \u2014 \uBAA8\uB378 \uCE90\uC2DC\uB97C \uC0AD\uC81C \uD6C4 \uC7AC\uB2E4\uC6B4\uB85C\uB4DC\uD558\uC138\uC694");
234
- return new _OcrEngine({ det, rec, dict, ort: ortMod, sharp: sharpMod });
235
- }
236
- /** onnxruntime-node 1.14+ InferenceSession.release() — 구버전은 무시 */
237
- async destroy() {
238
- for (const s of [this.det, this.rec]) {
239
- const rel = s.release;
240
- if (typeof rel === "function") {
241
- try {
242
- await rel.call(s);
243
- } catch (e2) {
244
- }
245
- }
246
- }
247
- }
248
- /**
249
- * 페이지 RGBA 픽셀 → 텍스트 라인 인식.
250
- * 반환 좌표는 입력 픽셀 기준. 라인은 위→아래, 좌→우 정렬.
251
- * @param stats 저신뢰(conf<0.5) 폐기 라인 카운트 출력 — 종전엔 무음 폐기라 관측 불가
252
- */
253
- async recognizePage(rgba, width, height, stats) {
254
- if (width < DET_MIN_SIZE || height < DET_MIN_SIZE) return [];
255
- const boxes = await this.detect(rgba, width, height);
256
- const items = [];
257
- for (const b of boxes) {
258
- const r = await this.recognizeLine(rgba, width, height, b);
259
- if (!r || !r.text.trim()) continue;
260
- if (r.confidence >= TEXT_SCORE) items.push(r);
261
- else if (stats) stats.droppedLowConf++;
262
- }
263
- items.sort((a, b) => a.y - b.y || a.x - b.x);
264
- return items;
265
- }
266
- // ─── det ─────────────────────────────────────────────
267
- async detect(rgba, width, height) {
268
- const ratio = DET_LONG_SIDE / Math.max(width, height);
269
- const dw = Math.max(32, Math.round(width * ratio / 32) * 32);
270
- const dh = Math.max(32, Math.round(height * ratio / 32) * 32);
271
- const rgb = await this.sharp(rgba, { raw: { width, height, channels: 4 } }).resize(dw, dh, { fit: "fill" }).removeAlpha().raw().toBuffer();
272
- const plane = dw * dh;
273
- const input = new Float32Array(3 * plane);
274
- for (let i = 0; i < plane; i++) {
275
- const r = rgb[i * 3] / 255;
276
- const g = rgb[i * 3 + 1] / 255;
277
- const b = rgb[i * 3 + 2] / 255;
278
- input[i] = (b - DET_MEAN[0]) / DET_STD[0];
279
- input[plane + i] = (g - DET_MEAN[1]) / DET_STD[1];
280
- input[2 * plane + i] = (r - DET_MEAN[2]) / DET_STD[2];
281
- }
282
- const tensor = new this.ort.Tensor("float32", input, [1, 3, dh, dw]);
283
- const out = await this.det.run({ [this.det.inputNames[0]]: tensor });
284
- const probMap = out[this.det.outputNames[0]].data;
285
- const rawBoxes = componentBoxes(probMap, dw, dh);
286
- const sx = width / dw;
287
- const sy = height / dh;
288
- const boxes = [];
289
- for (const rb of rawBoxes.slice(0, DET_MAX_BOXES)) {
290
- const bw = rb.x2 - rb.x1 + 1;
291
- const bh = rb.y2 - rb.y1 + 1;
292
- const delta = bw * bh * DET_UNCLIP_RATIO / (2 * (bw + bh));
293
- const x1 = Math.max(0, Math.floor((rb.x1 - delta) * sx));
294
- const y1 = Math.max(0, Math.floor((rb.y1 - delta) * sy));
295
- const x2 = Math.min(width, Math.ceil((rb.x2 + 1 + delta) * sx));
296
- const y2 = Math.min(height, Math.ceil((rb.y2 + 1 + delta) * sy));
297
- if (x2 - x1 < DET_MIN_SIZE || y2 - y1 < DET_MIN_SIZE) continue;
298
- boxes.push({ x: x1, y: y1, w: x2 - x1, h: y2 - y1 });
299
- }
300
- return boxes;
301
- }
302
- // ─── rec ─────────────────────────────────────────────
303
- async recognizeLine(rgba, width, height, box) {
304
- const rw = Math.min(REC_MAX_WIDTH, Math.max(16, Math.round(box.w * REC_HEIGHT / box.h)));
305
- const padded = Math.max(REC_MIN_WIDTH, rw);
306
- const rgb = await this.sharp(rgba, { raw: { width, height, channels: 4 } }).extract({ left: box.x, top: box.y, width: box.w, height: box.h }).resize(rw, REC_HEIGHT, { fit: "fill" }).removeAlpha().raw().toBuffer();
307
- const plane = padded * REC_HEIGHT;
308
- const input = new Float32Array(3 * plane);
309
- for (let y = 0; y < REC_HEIGHT; y++) {
310
- for (let x = 0; x < rw; x++) {
311
- const src = (y * rw + x) * 3;
312
- const dst = y * padded + x;
313
- input[dst] = rgb[src + 2] / 255 / 0.5 - 1;
314
- input[plane + dst] = rgb[src + 1] / 255 / 0.5 - 1;
315
- input[2 * plane + dst] = rgb[src] / 255 / 0.5 - 1;
316
- }
317
- }
318
- const tensor = new this.ort.Tensor("float32", input, [1, 3, REC_HEIGHT, padded]);
319
- const out = await this.rec.run({ [this.rec.inputNames[0]]: tensor });
320
- const logits = out[this.rec.outputNames[0]];
321
- const [, T, C] = logits.dims;
322
- const data = logits.data;
323
- const decoded = ctcDecode(data, T, C, this.dict);
324
- if (!decoded) return null;
325
- return { text: decoded.text, x: box.x, y: box.y, w: box.w, h: box.h, confidence: decoded.confidence };
326
- }
327
- };
328
- function ctcDecode(data, T, C, dict) {
329
- let text = "";
330
- let confSum = 0;
331
- let confCount = 0;
332
- let prev = -1;
333
- for (let t = 0; t < T; t++) {
334
- const off = t * C;
335
- let best = 0;
336
- let bestV = data[off];
337
- for (let c = 1; c < C; c++) {
338
- const v = data[off + c];
339
- if (v > bestV) {
340
- bestV = v;
341
- best = c;
342
- }
343
- }
344
- const repeat = best === prev;
345
- prev = best;
346
- if (best === 0 || repeat) continue;
347
- let p = bestV;
348
- if (p > 1.0001 || p < 0) {
349
- let denom = 0;
350
- for (let c = 0; c < C; c++) denom += Math.exp(data[off + c] - bestV);
351
- p = 1 / denom;
352
- }
353
- confSum += p;
354
- confCount++;
355
- if (best >= 1 && best <= dict.length) text += dict[best - 1];
356
- else if (best === dict.length + 1) text += " ";
357
- }
358
- if (!text) return null;
359
- return { text, confidence: confCount > 0 ? confSum / confCount : 0 };
360
- }
361
- function componentBoxes(prob, w, h) {
362
- const visited = new Uint8Array(w * h);
363
- const boxes = [];
364
- const stack = [];
365
- for (let start = 0; start < w * h; start++) {
366
- if (visited[start] || prob[start] <= DET_THRESH) continue;
367
- let x1 = start % w, x2 = x1, y1 = start / w | 0, y2 = y1;
368
- let sum = 0;
369
- let count = 0;
370
- stack.length = 0;
371
- stack.push(start);
372
- visited[start] = 1;
373
- while (stack.length) {
374
- const p = stack.pop();
375
- const px = p % w;
376
- const py = p / w | 0;
377
- sum += prob[p];
378
- count++;
379
- if (px < x1) x1 = px;
380
- if (px > x2) x2 = px;
381
- if (py < y1) y1 = py;
382
- if (py > y2) y2 = py;
383
- if (px > 0 && !visited[p - 1] && prob[p - 1] > DET_THRESH) {
384
- visited[p - 1] = 1;
385
- stack.push(p - 1);
386
- }
387
- if (px < w - 1 && !visited[p + 1] && prob[p + 1] > DET_THRESH) {
388
- visited[p + 1] = 1;
389
- stack.push(p + 1);
390
- }
391
- if (py > 0 && !visited[p - w] && prob[p - w] > DET_THRESH) {
392
- visited[p - w] = 1;
393
- stack.push(p - w);
394
- }
395
- if (py < h - 1 && !visited[p + w] && prob[p + w] > DET_THRESH) {
396
- visited[p + w] = 1;
397
- stack.push(p + w);
398
- }
399
- }
400
- if (x2 - x1 + 1 < DET_MIN_SIZE && y2 - y1 + 1 < DET_MIN_SIZE) continue;
401
- boxes.push({ x1, y1, x2, y2, score: sum / count });
402
- }
403
- return boxes.filter((b) => b.score >= DET_BOX_THRESH).sort((a, b) => a.y1 - b.y1 || a.x1 - b.x1);
404
- }
405
- async function tryImport(name, loader) {
406
- try {
407
- return await loader();
408
- } catch (e) {
409
- throw new Error(
410
- `\uB0B4\uC7A5 OCR \uC744 \uC0AC\uC6A9\uD558\uB824\uBA74 optional dependency '${name}' \uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \`npm install ${name}\` \uD6C4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694. \uC6D0\uC778: ${e.message}`
411
- );
412
- }
413
- }
414
- var enginePromise = null;
415
- function getOcrEngine() {
416
- if (!enginePromise) {
417
- enginePromise = OcrEngine.create().catch((err) => {
418
- enginePromise = null;
419
- throw err;
420
- });
421
- }
422
- return enginePromise;
423
- }
424
-
425
- // src/ocr/pdf-ocr.ts
426
- var OCR_RENDER_SCALE = 3;
427
- var PAGE_TIMEOUT_MS = 12e4;
428
- async function runPdfOcr(buffer, targets, mode, warnings, onProgress, detectTables = true) {
429
- const result = /* @__PURE__ */ new Map();
430
- if (targets.size === 0) return result;
431
- const pdfiumMod = await tryImport2(
432
- "@hyzyla/pdfium",
433
- () => Promise.resolve().then(() => _interopRequireWildcard(require("@hyzyla/pdfium")))
434
- );
435
- if (mode === "builtin") {
436
- await ensureOcrModels((p) => {
437
- if (p.phase === "download" && p.downloaded === 0) {
438
- process.stderr.write(`[kordoc-ocr] ${p.spec.name} \uB2E4\uC6B4\uB85C\uB4DC \uC911 (~${p.spec.sizeMb}MB)...
439
- `);
440
- }
441
- });
442
- }
443
- const engine = mode === "builtin" ? await getOcrEngine() : null;
444
- const pdfium = await pdfiumMod.PDFiumLibrary.init();
445
- const doc = await pdfium.loadDocument(new Uint8Array(buffer));
446
- try {
447
- let done = 0;
448
- for (const page of doc.pages()) {
449
- const pageNo = page.number + 1;
450
- if (!targets.has(pageNo)) continue;
451
- _optionalChain([onProgress, 'optionalCall', _2 => _2(++done, targets.size)]);
452
- try {
453
- const blocks = await withTimeout(
454
- ocrOnePage(page, pageNo, mode, engine, warnings, detectTables),
455
- PAGE_TIMEOUT_MS,
456
- `OCR \uD398\uC774\uC9C0 ${pageNo} \uD0C0\uC784\uC544\uC6C3 (${PAGE_TIMEOUT_MS / 1e3}\uCD08)`
457
- );
458
- result.set(pageNo, blocks);
459
- } catch (e) {
460
- warnings.push({
461
- page: pageNo,
462
- message: `\uD398\uC774\uC9C0 ${pageNo} OCR \uC2E4\uD328: ${e instanceof Error ? e.message : String(e)}`,
463
- code: "OCR_FAILED"
464
- });
465
- }
466
- }
467
- } finally {
468
- doc.destroy();
469
- pdfium.destroy();
470
- }
471
- return result;
472
- }
473
- async function ocrOnePage(page, pageNo, mode, engine, warnings, detectTables) {
474
- const { originalWidth: pdfW, originalHeight: pdfH } = page.getOriginalSize();
475
- const rendered = await page.render({
476
- scale: OCR_RENDER_SCALE,
477
- render: async ({ data }) => data
478
- });
479
- const { data: bgra, width: rw, height: rh } = rendered;
480
- const rgba = bgraToRgba(bgra);
481
- if (mode === "builtin") {
482
- const stats = { droppedLowConf: 0 };
483
- const items = await engine.recognizePage(rgba, rw, rh, stats);
484
- if (stats.droppedLowConf > 0) {
485
- warnings.push({
486
- page: pageNo,
487
- message: `\uD398\uC774\uC9C0 ${pageNo}: \uC800\uC2E0\uB8B0 OCR \uB77C\uC778 ${stats.droppedLowConf}\uAC1C \uD3D0\uAE30 (\uC778\uC2DD \uACB0\uC190 \uAC00\uB2A5)`,
488
- code: "OCR_LOW_CONF"
489
- });
490
- }
491
- const scale = rh / pdfH;
492
- const ruling = detectRulingLines(rgba, rw, rh, scale);
493
- const extraLines = rulingToPdfLines(ruling, scale, pdfH);
494
- return ocrItemsToBlocks(items, pageNo, pdfW, pdfH, scale, extraLines, detectTables);
495
- }
496
- const sharpModRaw = await tryImport2(
497
- "sharp",
498
- () => Promise.resolve().then(() => _interopRequireWildcard(require("sharp")))
499
- );
500
- const sharpAny = sharpModRaw;
501
- const sharp = typeof sharpAny === "function" ? sharpAny : _nullishCoalesce(sharpAny.default, () => ( sharpAny));
502
- const png = await sharp(rgba, { raw: { width: rw, height: rh, channels: 4 } }).png().toBuffer();
503
- const text = await mode(new Uint8Array(png), pageNo, "image/png");
504
- if (!text.trim()) {
505
- warnings.push({ page: pageNo, message: `\uD398\uC774\uC9C0 ${pageNo} OCR \uACB0\uACFC \uC5C6\uC74C`, code: "OCR_FAILED" });
506
- return [];
507
- }
508
- return [{ type: "paragraph", text: text.trim(), pageNumber: pageNo }];
509
- }
510
- function ocrItemsToBlocks(items, pageNumber, pdfW, pdfH, scale, extraLines, detectTables = true) {
511
- const norm = items.map((it) => {
512
- const h = it.h / scale;
513
- return {
514
- text: it.text,
515
- x: Math.round(it.x / scale),
516
- // NormItem.y 는 pdfjs transform[5] = 베이스라인 (bottom-up) — 박스 하단으로 근사
517
- y: Math.round(pdfH - (it.y + it.h) / scale),
518
- w: Math.round(it.w / scale),
519
- h: Math.round(h),
520
- fontSize: Math.max(1, Math.round(h * 0.8)),
521
- // 박스높이는 어센더+디센더 포함 — 글자크기 근사
522
- fontName: "ocr",
523
- isHidden: false
524
- };
525
- });
526
- return _chunk247ANM72cjs.extractPageBlocksWithLines.call(void 0, norm, pageNumber, { fnArray: [], argsArray: [] }, pdfW, pdfH, extraLines, detectTables);
527
- }
528
- async function tryImport2(name, loader) {
529
- try {
530
- return await loader();
531
- } catch (e) {
532
- throw new Error(
533
- `OCR \uC744 \uC0AC\uC6A9\uD558\uB824\uBA74 optional dependency '${name}' \uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \`npm install ${name}\` \uD6C4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694. \uC6D0\uC778: ${e.message}`
534
- );
535
- }
536
- }
537
- async function withTimeout(promise, ms, msg) {
538
- promise.catch(() => {
539
- });
540
- let timer;
541
- try {
542
- return await Promise.race([
543
- promise,
544
- new Promise((_, reject) => {
545
- timer = setTimeout(() => reject(new Error(msg)), ms);
546
- })
547
- ]);
548
- } finally {
549
- if (timer) clearTimeout(timer);
550
- }
551
- }
552
- function bgraToRgba(bgra) {
553
- const out = new Uint8Array(bgra.length);
554
- for (let i = 0; i < bgra.length; i += 4) {
555
- out[i] = bgra[i + 2];
556
- out[i + 1] = bgra[i + 1];
557
- out[i + 2] = bgra[i];
558
- out[i + 3] = bgra[i + 3];
559
- }
560
- return out;
561
- }
562
-
563
-
564
-
565
-
566
-
567
-
568
-
569
-
570
- exports.ensureOcrModels = ensureOcrModels; exports.getOcrEngine = getOcrEngine; exports.detectRulingLines = detectRulingLines; exports.rulingToPdfLines = rulingToPdfLines; exports.runPdfOcr = runPdfOcr; exports.ocrItemsToBlocks = ocrItemsToBlocks;
571
- //# sourceMappingURL=chunk-422427XJ.cjs.map