@kreuzberg/wasm 4.0.0-rc.21 → 4.0.0-rc.24

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 (42) hide show
  1. package/README.md +520 -837
  2. package/dist/adapters/wasm-adapter.d.ts +7 -10
  3. package/dist/adapters/wasm-adapter.d.ts.map +1 -0
  4. package/dist/adapters/wasm-adapter.js +41 -19
  5. package/dist/adapters/wasm-adapter.js.map +1 -1
  6. package/dist/index.d.ts +23 -24
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +240 -67
  9. package/dist/index.js.map +1 -1
  10. package/dist/ocr/registry.d.ts +7 -10
  11. package/dist/ocr/registry.d.ts.map +1 -0
  12. package/dist/ocr/registry.js.map +1 -1
  13. package/dist/ocr/tesseract-wasm-backend.d.ts +3 -6
  14. package/dist/ocr/tesseract-wasm-backend.d.ts.map +1 -0
  15. package/dist/ocr/tesseract-wasm-backend.js +0 -46
  16. package/dist/ocr/tesseract-wasm-backend.js.map +1 -1
  17. package/dist/pdfium.js +0 -5
  18. package/dist/plugin-registry.d.ts +246 -0
  19. package/dist/plugin-registry.d.ts.map +1 -0
  20. package/dist/runtime.d.ts +21 -22
  21. package/dist/runtime.d.ts.map +1 -0
  22. package/dist/runtime.js +0 -1
  23. package/dist/runtime.js.map +1 -1
  24. package/dist/{types-CKjcIYcX.d.ts → types.d.ts} +91 -22
  25. package/dist/types.d.ts.map +1 -0
  26. package/package.json +119 -162
  27. package/dist/adapters/wasm-adapter.cjs +0 -245
  28. package/dist/adapters/wasm-adapter.cjs.map +0 -1
  29. package/dist/adapters/wasm-adapter.d.cts +0 -121
  30. package/dist/index.cjs +0 -1245
  31. package/dist/index.cjs.map +0 -1
  32. package/dist/index.d.cts +0 -423
  33. package/dist/ocr/registry.cjs +0 -92
  34. package/dist/ocr/registry.cjs.map +0 -1
  35. package/dist/ocr/registry.d.cts +0 -102
  36. package/dist/ocr/tesseract-wasm-backend.cjs +0 -456
  37. package/dist/ocr/tesseract-wasm-backend.cjs.map +0 -1
  38. package/dist/ocr/tesseract-wasm-backend.d.cts +0 -257
  39. package/dist/runtime.cjs +0 -174
  40. package/dist/runtime.cjs.map +0 -1
  41. package/dist/runtime.d.cts +0 -256
  42. package/dist/types-CKjcIYcX.d.cts +0 -294
@@ -1,456 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // typescript/ocr/tesseract-wasm-backend.ts
31
- var tesseract_wasm_backend_exports = {};
32
- __export(tesseract_wasm_backend_exports, {
33
- TesseractWasmBackend: () => TesseractWasmBackend
34
- });
35
- module.exports = __toCommonJS(tesseract_wasm_backend_exports);
36
- var TesseractWasmBackend = class {
37
- /** Tesseract WASM client instance */
38
- client = null;
39
- /** Track which models are currently loaded to avoid redundant loads */
40
- loadedLanguages = /* @__PURE__ */ new Set();
41
- /** Cache for language availability validation */
42
- supportedLangsCache = null;
43
- /** Progress callback for UI updates */
44
- progressCallback = null;
45
- /** Base URL for training data CDN */
46
- CDN_BASE_URL = "https://cdn.jsdelivr.net/npm/tesseract-wasm@0.11.0/dist";
47
- /**
48
- * Return the unique name of this OCR backend
49
- *
50
- * @returns Backend identifier "tesseract-wasm"
51
- */
52
- name() {
53
- return "tesseract-wasm";
54
- }
55
- /**
56
- * Return list of supported language codes
57
- *
58
- * Returns a curated list of commonly available Tesseract language models.
59
- * Tesseract supports many more languages through custom models.
60
- *
61
- * @returns Array of ISO 639-1/2/3 language codes
62
- */
63
- supportedLanguages() {
64
- if (this.supportedLangsCache) {
65
- return this.supportedLangsCache;
66
- }
67
- this.supportedLangsCache = [
68
- // Major languages
69
- "eng",
70
- // English
71
- "deu",
72
- // German
73
- "fra",
74
- // French
75
- "spa",
76
- // Spanish
77
- "ita",
78
- // Italian
79
- "por",
80
- // Portuguese
81
- "nld",
82
- // Dutch
83
- "rus",
84
- // Russian
85
- "jpn",
86
- // Japanese
87
- "kor",
88
- // Korean
89
- "chi_sim",
90
- // Chinese (Simplified)
91
- "chi_tra",
92
- // Chinese (Traditional)
93
- // Additional European languages
94
- "pol",
95
- // Polish
96
- "tur",
97
- // Turkish
98
- "swe",
99
- // Swedish
100
- "dan",
101
- // Danish
102
- "fin",
103
- // Finnish
104
- "nor",
105
- // Norwegian
106
- "ces",
107
- // Czech
108
- "slk",
109
- // Slovak
110
- "ron",
111
- // Romanian
112
- "hun",
113
- // Hungarian
114
- "hrv",
115
- // Croatian
116
- "srp",
117
- // Serbian
118
- "bul",
119
- // Bulgarian
120
- "ukr",
121
- // Ukrainian
122
- "ell",
123
- // Greek
124
- // Asian languages
125
- "ara",
126
- // Arabic
127
- "heb",
128
- // Hebrew
129
- "hin",
130
- // Hindi
131
- "tha",
132
- // Thai
133
- "vie",
134
- // Vietnamese
135
- "mkd",
136
- // Macedonian
137
- "ben",
138
- // Bengali
139
- "tam",
140
- // Tamil
141
- "tel",
142
- // Telugu
143
- "kan",
144
- // Kannada
145
- "mal",
146
- // Malayalam
147
- "mya",
148
- // Burmese
149
- "khm",
150
- // Khmer
151
- "lao",
152
- // Lao
153
- "sin"
154
- // Sinhala
155
- ];
156
- return this.supportedLangsCache;
157
- }
158
- /**
159
- * Initialize the OCR backend
160
- *
161
- * Creates the Tesseract WASM client instance. This is called once when
162
- * the backend is registered with the extraction pipeline.
163
- *
164
- * The actual model loading happens in processImage() on-demand to avoid
165
- * loading all models upfront.
166
- *
167
- * @throws {Error} If tesseract-wasm is not available or initialization fails
168
- *
169
- * @example
170
- * ```typescript
171
- * const backend = new TesseractWasmBackend();
172
- * try {
173
- * await backend.initialize();
174
- * } catch (error) {
175
- * console.error('Failed to initialize OCR:', error);
176
- * }
177
- * ```
178
- */
179
- async initialize() {
180
- if (this.client) {
181
- return;
182
- }
183
- try {
184
- const tesseractModule = await this.loadTesseractWasm();
185
- if (!tesseractModule || typeof tesseractModule.OCRClient !== "function") {
186
- throw new Error("tesseract-wasm OCRClient not found. Ensure tesseract-wasm is installed and available.");
187
- }
188
- this.client = new tesseractModule.OCRClient();
189
- this.loadedLanguages.clear();
190
- } catch (error) {
191
- const message = error instanceof Error ? error.message : String(error);
192
- throw new Error(`Failed to initialize TesseractWasmBackend: ${message}`);
193
- }
194
- }
195
- /**
196
- * Process image bytes and extract text via OCR
197
- *
198
- * Handles image loading, model loading, OCR processing, and result formatting.
199
- * Automatically loads the language model on first use and caches it for subsequent calls.
200
- *
201
- * @param imageBytes - Raw image data (Uint8Array) or Base64-encoded string
202
- * @param language - ISO 639-2/3 language code (e.g., "eng", "deu")
203
- * @returns Promise resolving to OCR result with content and metadata
204
- * @throws {Error} If image processing fails, model loading fails, or language is unsupported
205
- *
206
- * @example
207
- * ```typescript
208
- * const backend = new TesseractWasmBackend();
209
- * await backend.initialize();
210
- *
211
- * const imageBuffer = fs.readFileSync('scanned.png');
212
- * const result = await backend.processImage(
213
- * new Uint8Array(imageBuffer),
214
- * 'eng'
215
- * );
216
- *
217
- * console.log(result.content); // Extracted text
218
- * console.log(result.metadata.confidence); // OCR confidence score
219
- * ```
220
- */
221
- async processImage(imageBytes, language) {
222
- if (!this.client) {
223
- throw new Error("TesseractWasmBackend not initialized. Call initialize() first.");
224
- }
225
- const supported = this.supportedLanguages();
226
- const normalizedLang = language.toLowerCase();
227
- const isSupported = supported.some((lang) => lang.toLowerCase() === normalizedLang);
228
- if (!isSupported) {
229
- throw new Error(`Language "${language}" is not supported. Supported languages: ${supported.join(", ")}`);
230
- }
231
- try {
232
- if (!this.loadedLanguages.has(normalizedLang)) {
233
- this.reportProgress(10);
234
- await this.loadLanguageModel(normalizedLang);
235
- this.loadedLanguages.add(normalizedLang);
236
- this.reportProgress(30);
237
- }
238
- this.reportProgress(40);
239
- const imageBitmap = await this.convertToImageBitmap(imageBytes);
240
- this.reportProgress(50);
241
- await this.client.loadImage(imageBitmap);
242
- this.reportProgress(70);
243
- const text = await this.client.getText();
244
- const confidence = await this.getConfidenceScore();
245
- const pageMetadata = await this.getPageMetadata();
246
- this.reportProgress(90);
247
- return {
248
- content: text,
249
- mime_type: "text/plain",
250
- metadata: {
251
- language: normalizedLang,
252
- confidence,
253
- ...pageMetadata
254
- },
255
- tables: []
256
- // Tesseract-wasm doesn't provide structured table detection
257
- };
258
- } catch (error) {
259
- const message = error instanceof Error ? error.message : String(error);
260
- throw new Error(`OCR processing failed for language "${language}": ${message}`);
261
- } finally {
262
- this.reportProgress(100);
263
- }
264
- }
265
- /**
266
- * Shutdown the OCR backend and release resources
267
- *
268
- * Properly cleans up the Tesseract WASM client, freeing memory and Web Workers.
269
- * Called when the backend is unregistered or the application shuts down.
270
- *
271
- * @throws {Error} If cleanup fails (errors are logged but not critical)
272
- *
273
- * @example
274
- * ```typescript
275
- * const backend = new TesseractWasmBackend();
276
- * await backend.initialize();
277
- * // ... use backend ...
278
- * await backend.shutdown(); // Clean up resources
279
- * ```
280
- */
281
- async shutdown() {
282
- try {
283
- if (this.client) {
284
- if (typeof this.client.destroy === "function") {
285
- this.client.destroy();
286
- }
287
- if (typeof this.client.terminate === "function") {
288
- this.client.terminate();
289
- }
290
- this.client = null;
291
- }
292
- this.loadedLanguages.clear();
293
- this.supportedLangsCache = null;
294
- this.progressCallback = null;
295
- } catch (error) {
296
- console.warn(
297
- `Warning during TesseractWasmBackend shutdown: ${error instanceof Error ? error.message : String(error)}`
298
- );
299
- }
300
- }
301
- /**
302
- * Set a progress callback for UI updates
303
- *
304
- * Allows the UI to display progress during OCR processing.
305
- * The callback will be called with values from 0 to 100.
306
- *
307
- * @param callback - Function to call with progress percentage
308
- *
309
- * @example
310
- * ```typescript
311
- * const backend = new TesseractWasmBackend();
312
- * backend.setProgressCallback((progress) => {
313
- * console.log(`OCR Progress: ${progress}%`);
314
- * document.getElementById('progress-bar').style.width = `${progress}%`;
315
- * });
316
- * ```
317
- */
318
- setProgressCallback(callback) {
319
- this.progressCallback = callback;
320
- }
321
- /**
322
- * Load language model from CDN
323
- *
324
- * Fetches the training data for a specific language from jsDelivr CDN.
325
- * This is an MVP approach - models are cached by the browser.
326
- *
327
- * @param language - ISO 639-2/3 language code
328
- * @throws {Error} If model download fails or language is not available
329
- *
330
- * @internal
331
- */
332
- async loadLanguageModel(language) {
333
- if (!this.client) {
334
- throw new Error("Client not initialized");
335
- }
336
- const modelFilename = `${language}.traineddata`;
337
- const modelUrl = `${this.CDN_BASE_URL}/${modelFilename}`;
338
- try {
339
- await this.client.loadModel(modelUrl);
340
- } catch (error) {
341
- const message = error instanceof Error ? error.message : String(error);
342
- throw new Error(`Failed to load model for language "${language}" from ${modelUrl}: ${message}`);
343
- }
344
- }
345
- /**
346
- * Convert image bytes or Base64 string to ImageBitmap
347
- *
348
- * Handles both Uint8Array and Base64-encoded image data, converting to
349
- * ImageBitmap format required by Tesseract WASM.
350
- *
351
- * @param imageBytes - Image data as Uint8Array or Base64 string
352
- * @returns Promise resolving to ImageBitmap
353
- * @throws {Error} If conversion fails (browser API not available or invalid image data)
354
- *
355
- * @internal
356
- */
357
- async convertToImageBitmap(imageBytes) {
358
- if (typeof createImageBitmap === "undefined") {
359
- throw new Error("createImageBitmap is not available. TesseractWasmBackend requires a browser environment.");
360
- }
361
- try {
362
- let bytes = imageBytes;
363
- if (typeof imageBytes === "string") {
364
- const binaryString = atob(imageBytes);
365
- bytes = new Uint8Array(binaryString.length);
366
- for (let i = 0; i < binaryString.length; i++) {
367
- bytes[i] = binaryString.charCodeAt(i);
368
- }
369
- }
370
- const blob = new Blob([bytes]);
371
- const imageBitmap = await createImageBitmap(blob);
372
- return imageBitmap;
373
- } catch (error) {
374
- const message = error instanceof Error ? error.message : String(error);
375
- throw new Error(`Failed to convert image bytes to ImageBitmap: ${message}`);
376
- }
377
- }
378
- /**
379
- * Get confidence score from OCR result
380
- *
381
- * Attempts to retrieve confidence score from Tesseract.
382
- * Returns a safe default if unavailable.
383
- *
384
- * @returns Confidence score between 0 and 1
385
- *
386
- * @internal
387
- */
388
- async getConfidenceScore() {
389
- try {
390
- if (this.client && typeof this.client.getConfidence === "function") {
391
- const confidence = await this.client.getConfidence();
392
- return confidence > 1 ? confidence / 100 : confidence;
393
- }
394
- } catch {
395
- }
396
- return 0.9;
397
- }
398
- /**
399
- * Get page metadata from OCR result
400
- *
401
- * Retrieves additional metadata like image dimensions and processing info.
402
- *
403
- * @returns Metadata object (may be empty if unavailable)
404
- *
405
- * @internal
406
- */
407
- async getPageMetadata() {
408
- try {
409
- if (this.client && typeof this.client.getPageMetadata === "function") {
410
- return await this.client.getPageMetadata();
411
- }
412
- } catch {
413
- }
414
- return {};
415
- }
416
- /**
417
- * Dynamically load tesseract-wasm module
418
- *
419
- * Uses dynamic import to load tesseract-wasm only when needed,
420
- * avoiding hard dependency in browser environments where it may not be bundled.
421
- *
422
- * @returns tesseract-wasm module object
423
- * @throws {Error} If module cannot be imported
424
- *
425
- * @internal
426
- */
427
- async loadTesseractWasm() {
428
- try {
429
- const module2 = await import("tesseract-wasm");
430
- return module2;
431
- } catch (error) {
432
- const message = error instanceof Error ? error.message : String(error);
433
- throw new Error(
434
- `Failed to import tesseract-wasm. Ensure it is installed via: npm install tesseract-wasm. Error: ${message}`
435
- );
436
- }
437
- }
438
- /**
439
- * Report progress to progress callback
440
- *
441
- * Internal helper for notifying progress updates during OCR processing.
442
- *
443
- * @param progress - Progress percentage (0-100)
444
- *
445
- * @internal
446
- */
447
- reportProgress(progress) {
448
- if (this.progressCallback) {
449
- try {
450
- this.progressCallback(Math.min(100, Math.max(0, progress)));
451
- } catch {
452
- }
453
- }
454
- }
455
- };
456
- //# sourceMappingURL=tesseract-wasm-backend.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../typescript/ocr/tesseract-wasm-backend.ts"],"sourcesContent":["/**\n * Tesseract WASM OCR Backend\n *\n * Provides OCR capabilities using tesseract-wasm library for browser environments.\n * Loads training data on-demand from jsDelivr CDN and implements the OcrBackendProtocol.\n *\n * ## Browser-Only Requirement\n *\n * This backend requires browser APIs like createImageBitmap and Web Workers.\n * It will NOT work in Node.js environments without additional canvas polyfills.\n *\n * ## Supported Languages\n *\n * Common ISO 639-1 and ISO 639-2 codes:\n * - English: \"eng\"\n * - German: \"deu\"\n * - French: \"fra\"\n * - Spanish: \"spa\"\n * - Italian: \"ita\"\n * - Portuguese: \"por\"\n * - Dutch: \"nld\"\n * - Russian: \"rus\"\n * - Chinese (Simplified): \"chi_sim\"\n * - Chinese (Traditional): \"chi_tra\"\n * - Japanese: \"jpn\"\n * - Korean: \"kor\"\n * - Arabic: \"ara\"\n * - Hindi: \"hin\"\n *\n * For complete language list, see: https://github.com/naptha/tesseract.js\n *\n * @example Basic Usage\n * ```typescript\n * import { TesseractWasmBackend } from '@kreuzberg/wasm/ocr/tesseract-wasm-backend';\n * import { registerOcrBackend, extractBytes, initWasm } from '@kreuzberg/wasm';\n *\n * // Initialize\n * await initWasm();\n * const backend = new TesseractWasmBackend();\n * await backend.initialize();\n * registerOcrBackend(backend);\n *\n * // Use in extraction\n * const imageBytes = new Uint8Array(buffer);\n * const result = await extractBytes(imageBytes, 'image/png', {\n * ocr: { backend: 'tesseract-wasm', language: 'eng' }\n * });\n * console.log(result.content); // Extracted text\n * ```\n *\n * @example With Language Auto-Detection\n * ```typescript\n * const backend = new TesseractWasmBackend();\n * await backend.initialize();\n * registerOcrBackend(backend);\n *\n * // Extract without specifying language - backend will auto-detect\n * const result = await extractBytes(imageBytes, 'image/png', {\n * ocr: { backend: 'tesseract-wasm' } // language will auto-detect\n * });\n * ```\n */\n\nimport type { OcrBackendProtocol } from \"../types.js\";\n\n/**\n * Tesseract WASM Client interface\n * Type definition for tesseract-wasm's OCRClient class\n */\ninterface TesseractClient {\n\tloadModel(modelPath: string): Promise<void>;\n\tloadImage(image: ImageBitmap | Blob): Promise<void>;\n\tgetText(): Promise<string>;\n\tgetConfidence(): Promise<number>;\n\tgetPageMetadata(): Promise<Record<string, unknown>>;\n\tdestroy(): void;\n\tterminate(): void;\n}\n\n/**\n * TesseractWasmBackend - OCR backend using tesseract-wasm library\n *\n * Implements the OcrBackendProtocol for Kreuzberg document extraction pipeline.\n * Provides comprehensive OCR support with model caching, error handling, and progress reporting.\n */\nexport class TesseractWasmBackend implements OcrBackendProtocol {\n\t/** Tesseract WASM client instance */\n\tprivate client: TesseractClient | null = null;\n\n\t/** Track which models are currently loaded to avoid redundant loads */\n\tprivate loadedLanguages: Set<string> = new Set();\n\n\t/** Cache for language availability validation */\n\tprivate supportedLangsCache: string[] | null = null;\n\n\t/** Progress callback for UI updates */\n\tprivate progressCallback: ((progress: number) => void) | null = null;\n\n\t/** Base URL for training data CDN */\n\tprivate readonly CDN_BASE_URL = \"https://cdn.jsdelivr.net/npm/tesseract-wasm@0.11.0/dist\";\n\n\t/**\n\t * Return the unique name of this OCR backend\n\t *\n\t * @returns Backend identifier \"tesseract-wasm\"\n\t */\n\tname(): string {\n\t\treturn \"tesseract-wasm\";\n\t}\n\n\t/**\n\t * Return list of supported language codes\n\t *\n\t * Returns a curated list of commonly available Tesseract language models.\n\t * Tesseract supports many more languages through custom models.\n\t *\n\t * @returns Array of ISO 639-1/2/3 language codes\n\t */\n\tsupportedLanguages(): string[] {\n\t\t// Return cached list if already computed\n\t\tif (this.supportedLangsCache) {\n\t\t\treturn this.supportedLangsCache;\n\t\t}\n\n\t\t// Comprehensive list of languages supported by tesseract-wasm\n\t\t// Includes both 3-letter (ISO 639-2) and 2-letter (ISO 639-1) codes where applicable\n\t\tthis.supportedLangsCache = [\n\t\t\t// Major languages\n\t\t\t\"eng\", // English\n\t\t\t\"deu\", // German\n\t\t\t\"fra\", // French\n\t\t\t\"spa\", // Spanish\n\t\t\t\"ita\", // Italian\n\t\t\t\"por\", // Portuguese\n\t\t\t\"nld\", // Dutch\n\t\t\t\"rus\", // Russian\n\t\t\t\"jpn\", // Japanese\n\t\t\t\"kor\", // Korean\n\t\t\t\"chi_sim\", // Chinese (Simplified)\n\t\t\t\"chi_tra\", // Chinese (Traditional)\n\n\t\t\t// Additional European languages\n\t\t\t\"pol\", // Polish\n\t\t\t\"tur\", // Turkish\n\t\t\t\"swe\", // Swedish\n\t\t\t\"dan\", // Danish\n\t\t\t\"fin\", // Finnish\n\t\t\t\"nor\", // Norwegian\n\t\t\t\"ces\", // Czech\n\t\t\t\"slk\", // Slovak\n\t\t\t\"ron\", // Romanian\n\t\t\t\"hun\", // Hungarian\n\t\t\t\"hrv\", // Croatian\n\t\t\t\"srp\", // Serbian\n\t\t\t\"bul\", // Bulgarian\n\t\t\t\"ukr\", // Ukrainian\n\t\t\t\"ell\", // Greek\n\n\t\t\t// Asian languages\n\t\t\t\"ara\", // Arabic\n\t\t\t\"heb\", // Hebrew\n\t\t\t\"hin\", // Hindi\n\t\t\t\"tha\", // Thai\n\t\t\t\"vie\", // Vietnamese\n\t\t\t\"mkd\", // Macedonian\n\t\t\t\"ben\", // Bengali\n\t\t\t\"tam\", // Tamil\n\t\t\t\"tel\", // Telugu\n\t\t\t\"kan\", // Kannada\n\t\t\t\"mal\", // Malayalam\n\t\t\t\"mya\", // Burmese\n\t\t\t\"khm\", // Khmer\n\t\t\t\"lao\", // Lao\n\t\t\t\"sin\", // Sinhala\n\t\t];\n\n\t\treturn this.supportedLangsCache;\n\t}\n\n\t/**\n\t * Initialize the OCR backend\n\t *\n\t * Creates the Tesseract WASM client instance. This is called once when\n\t * the backend is registered with the extraction pipeline.\n\t *\n\t * The actual model loading happens in processImage() on-demand to avoid\n\t * loading all models upfront.\n\t *\n\t * @throws {Error} If tesseract-wasm is not available or initialization fails\n\t *\n\t * @example\n\t * ```typescript\n\t * const backend = new TesseractWasmBackend();\n\t * try {\n\t * await backend.initialize();\n\t * } catch (error) {\n\t * console.error('Failed to initialize OCR:', error);\n\t * }\n\t * ```\n\t */\n\tasync initialize(): Promise<void> {\n\t\tif (this.client) {\n\t\t\treturn; // Already initialized\n\t\t}\n\n\t\ttry {\n\t\t\t// Dynamically import tesseract-wasm\n\t\t\tconst tesseractModule = await this.loadTesseractWasm();\n\n\t\t\t// @ts-expect-error - tesseract-wasm types are not fully typed\n\t\t\tif (!tesseractModule || typeof tesseractModule.OCRClient !== \"function\") {\n\t\t\t\tthrow new Error(\"tesseract-wasm OCRClient not found. Ensure tesseract-wasm is installed and available.\");\n\t\t\t}\n\n\t\t\t// Create client instance\n\t\t\t// @ts-expect-error - tesseract-wasm types are not fully typed\n\t\t\tthis.client = new tesseractModule.OCRClient();\n\n\t\t\t// Initialize tracking\n\t\t\tthis.loadedLanguages.clear();\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`Failed to initialize TesseractWasmBackend: ${message}`);\n\t\t}\n\t}\n\n\t/**\n\t * Process image bytes and extract text via OCR\n\t *\n\t * Handles image loading, model loading, OCR processing, and result formatting.\n\t * Automatically loads the language model on first use and caches it for subsequent calls.\n\t *\n\t * @param imageBytes - Raw image data (Uint8Array) or Base64-encoded string\n\t * @param language - ISO 639-2/3 language code (e.g., \"eng\", \"deu\")\n\t * @returns Promise resolving to OCR result with content and metadata\n\t * @throws {Error} If image processing fails, model loading fails, or language is unsupported\n\t *\n\t * @example\n\t * ```typescript\n\t * const backend = new TesseractWasmBackend();\n\t * await backend.initialize();\n\t *\n\t * const imageBuffer = fs.readFileSync('scanned.png');\n\t * const result = await backend.processImage(\n\t * new Uint8Array(imageBuffer),\n\t * 'eng'\n\t * );\n\t *\n\t * console.log(result.content); // Extracted text\n\t * console.log(result.metadata.confidence); // OCR confidence score\n\t * ```\n\t */\n\tasync processImage(\n\t\timageBytes: Uint8Array | string,\n\t\tlanguage: string,\n\t): Promise<{\n\t\tcontent: string;\n\t\tmime_type: string;\n\t\tmetadata: Record<string, unknown>;\n\t\ttables: unknown[];\n\t}> {\n\t\tif (!this.client) {\n\t\t\tthrow new Error(\"TesseractWasmBackend not initialized. Call initialize() first.\");\n\t\t}\n\n\t\t// Validate language support\n\t\tconst supported = this.supportedLanguages();\n\t\t// Normalize language code for comparison\n\t\tconst normalizedLang = language.toLowerCase();\n\t\tconst isSupported = supported.some((lang) => lang.toLowerCase() === normalizedLang);\n\n\t\tif (!isSupported) {\n\t\t\tthrow new Error(`Language \"${language}\" is not supported. Supported languages: ${supported.join(\", \")}`);\n\t\t}\n\n\t\ttry {\n\t\t\t// Load language model if not already loaded\n\t\t\tif (!this.loadedLanguages.has(normalizedLang)) {\n\t\t\t\tthis.reportProgress(10); // Progress: loading model\n\t\t\t\tawait this.loadLanguageModel(normalizedLang);\n\t\t\t\tthis.loadedLanguages.add(normalizedLang);\n\t\t\t\tthis.reportProgress(30); // Progress: model loaded\n\t\t\t}\n\n\t\t\t// Convert image bytes to ImageBitmap\n\t\t\tthis.reportProgress(40); // Progress: processing image\n\t\t\tconst imageBitmap = await this.convertToImageBitmap(imageBytes);\n\n\t\t\t// Load image into Tesseract\n\t\t\tthis.reportProgress(50); // Progress: loading image\n\t\t\tawait this.client.loadImage(imageBitmap);\n\n\t\t\t// Perform OCR\n\t\t\tthis.reportProgress(70); // Progress: performing OCR\n\t\t\tconst text = await this.client.getText();\n\n\t\t\t// Get confidence and metadata\n\t\t\tconst confidence = await this.getConfidenceScore();\n\t\t\tconst pageMetadata = await this.getPageMetadata();\n\n\t\t\tthis.reportProgress(90); // Progress: nearly complete\n\n\t\t\t// Return result in Kreuzberg format\n\t\t\treturn {\n\t\t\t\tcontent: text,\n\t\t\t\tmime_type: \"text/plain\",\n\t\t\t\tmetadata: {\n\t\t\t\t\tlanguage: normalizedLang,\n\t\t\t\t\tconfidence,\n\t\t\t\t\t...pageMetadata,\n\t\t\t\t},\n\t\t\t\ttables: [], // Tesseract-wasm doesn't provide structured table detection\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`OCR processing failed for language \"${language}\": ${message}`);\n\t\t} finally {\n\t\t\tthis.reportProgress(100); // Progress: complete\n\t\t}\n\t}\n\n\t/**\n\t * Shutdown the OCR backend and release resources\n\t *\n\t * Properly cleans up the Tesseract WASM client, freeing memory and Web Workers.\n\t * Called when the backend is unregistered or the application shuts down.\n\t *\n\t * @throws {Error} If cleanup fails (errors are logged but not critical)\n\t *\n\t * @example\n\t * ```typescript\n\t * const backend = new TesseractWasmBackend();\n\t * await backend.initialize();\n\t * // ... use backend ...\n\t * await backend.shutdown(); // Clean up resources\n\t * ```\n\t */\n\tasync shutdown(): Promise<void> {\n\t\ttry {\n\t\t\tif (this.client) {\n\t\t\t\t// Try both destroy and terminate for compatibility\n\t\t\t\tif (typeof this.client.destroy === \"function\") {\n\t\t\t\t\tthis.client.destroy();\n\t\t\t\t}\n\t\t\t\tif (typeof this.client.terminate === \"function\") {\n\t\t\t\t\tthis.client.terminate();\n\t\t\t\t}\n\t\t\t\tthis.client = null;\n\t\t\t}\n\n\t\t\t// Clear cached state\n\t\t\tthis.loadedLanguages.clear();\n\t\t\tthis.supportedLangsCache = null;\n\t\t\tthis.progressCallback = null;\n\t\t} catch (error) {\n\t\t\t// Log error but don't throw - shutdown is best-effort\n\t\t\tconsole.warn(\n\t\t\t\t`Warning during TesseractWasmBackend shutdown: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Set a progress callback for UI updates\n\t *\n\t * Allows the UI to display progress during OCR processing.\n\t * The callback will be called with values from 0 to 100.\n\t *\n\t * @param callback - Function to call with progress percentage\n\t *\n\t * @example\n\t * ```typescript\n\t * const backend = new TesseractWasmBackend();\n\t * backend.setProgressCallback((progress) => {\n\t * console.log(`OCR Progress: ${progress}%`);\n\t * document.getElementById('progress-bar').style.width = `${progress}%`;\n\t * });\n\t * ```\n\t */\n\tsetProgressCallback(callback: (progress: number) => void): void {\n\t\tthis.progressCallback = callback;\n\t}\n\n\t/**\n\t * Load language model from CDN\n\t *\n\t * Fetches the training data for a specific language from jsDelivr CDN.\n\t * This is an MVP approach - models are cached by the browser.\n\t *\n\t * @param language - ISO 639-2/3 language code\n\t * @throws {Error} If model download fails or language is not available\n\t *\n\t * @internal\n\t */\n\tprivate async loadLanguageModel(language: string): Promise<void> {\n\t\tif (!this.client) {\n\t\t\tthrow new Error(\"Client not initialized\");\n\t\t}\n\n\t\t// Construct model URL - models are named with their language code\n\t\tconst modelFilename = `${language}.traineddata`;\n\t\tconst modelUrl = `${this.CDN_BASE_URL}/${modelFilename}`;\n\n\t\ttry {\n\t\t\tawait this.client.loadModel(modelUrl);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`Failed to load model for language \"${language}\" from ${modelUrl}: ${message}`);\n\t\t}\n\t}\n\n\t/**\n\t * Convert image bytes or Base64 string to ImageBitmap\n\t *\n\t * Handles both Uint8Array and Base64-encoded image data, converting to\n\t * ImageBitmap format required by Tesseract WASM.\n\t *\n\t * @param imageBytes - Image data as Uint8Array or Base64 string\n\t * @returns Promise resolving to ImageBitmap\n\t * @throws {Error} If conversion fails (browser API not available or invalid image data)\n\t *\n\t * @internal\n\t */\n\tprivate async convertToImageBitmap(imageBytes: Uint8Array | string): Promise<ImageBitmap> {\n\t\t// Check if createImageBitmap is available (browser only)\n\t\tif (typeof createImageBitmap === \"undefined\") {\n\t\t\tthrow new Error(\"createImageBitmap is not available. TesseractWasmBackend requires a browser environment.\");\n\t\t}\n\n\t\ttry {\n\t\t\t// Convert to Uint8Array if string (Base64)\n\t\t\tlet bytes = imageBytes;\n\t\t\tif (typeof imageBytes === \"string\") {\n\t\t\t\t// Decode Base64 to binary\n\t\t\t\tconst binaryString = atob(imageBytes);\n\t\t\t\tbytes = new Uint8Array(binaryString.length);\n\t\t\t\tfor (let i = 0; i < binaryString.length; i++) {\n\t\t\t\t\t(bytes as Uint8Array)[i] = binaryString.charCodeAt(i);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Create Blob from bytes\n\t\t\tconst blob = new Blob([bytes as Uint8Array] as BlobPart[]);\n\n\t\t\t// Convert Blob to ImageBitmap\n\t\t\tconst imageBitmap = await createImageBitmap(blob);\n\t\t\treturn imageBitmap;\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`Failed to convert image bytes to ImageBitmap: ${message}`);\n\t\t}\n\t}\n\n\t/**\n\t * Get confidence score from OCR result\n\t *\n\t * Attempts to retrieve confidence score from Tesseract.\n\t * Returns a safe default if unavailable.\n\t *\n\t * @returns Confidence score between 0 and 1\n\t *\n\t * @internal\n\t */\n\tprivate async getConfidenceScore(): Promise<number> {\n\t\ttry {\n\t\t\tif (this.client && typeof this.client.getConfidence === \"function\") {\n\t\t\t\tconst confidence = await this.client.getConfidence();\n\t\t\t\t// Normalize to 0-1 range if needed (some versions return 0-100)\n\t\t\t\treturn confidence > 1 ? confidence / 100 : confidence;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Silently fail - confidence is optional\n\t\t}\n\t\treturn 0.9; // Default reasonable confidence\n\t}\n\n\t/**\n\t * Get page metadata from OCR result\n\t *\n\t * Retrieves additional metadata like image dimensions and processing info.\n\t *\n\t * @returns Metadata object (may be empty if unavailable)\n\t *\n\t * @internal\n\t */\n\tprivate async getPageMetadata(): Promise<Record<string, unknown>> {\n\t\ttry {\n\t\t\tif (this.client && typeof this.client.getPageMetadata === \"function\") {\n\t\t\t\treturn await this.client.getPageMetadata();\n\t\t\t}\n\t\t} catch {\n\t\t\t// Silently fail - metadata is optional\n\t\t}\n\t\treturn {};\n\t}\n\n\t/**\n\t * Dynamically load tesseract-wasm module\n\t *\n\t * Uses dynamic import to load tesseract-wasm only when needed,\n\t * avoiding hard dependency in browser environments where it may not be bundled.\n\t *\n\t * @returns tesseract-wasm module object\n\t * @throws {Error} If module cannot be imported\n\t *\n\t * @internal\n\t */\n\tprivate async loadTesseractWasm(): Promise<unknown> {\n\t\ttry {\n\t\t\t// Use dynamic import to handle both ESM and CJS\n\t\t\t// @ts-expect-error - tesseract-wasm has package.json exports issues with TypeScript\n\t\t\t// @vite-ignore - tesseract-wasm package resolution\n\t\t\tconst module = await import(\"tesseract-wasm\");\n\t\t\treturn module;\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to import tesseract-wasm. Ensure it is installed via: npm install tesseract-wasm. Error: ${message}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Report progress to progress callback\n\t *\n\t * Internal helper for notifying progress updates during OCR processing.\n\t *\n\t * @param progress - Progress percentage (0-100)\n\t *\n\t * @internal\n\t */\n\tprivate reportProgress(progress: number): void {\n\t\tif (this.progressCallback) {\n\t\t\ttry {\n\t\t\t\tthis.progressCallback(Math.min(100, Math.max(0, progress)));\n\t\t\t} catch {\n\t\t\t\t// Ignore callback errors to prevent blocking OCR processing\n\t\t\t}\n\t\t}\n\t}\n}\n"],"mappings":"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","names":["module"]}