meticulous-ui 3.12.0 → 3.12.1
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.
- package/index.d.ts +17 -13
- package/package.json +1 -1
- package/utils/getImageContentAsJson.js +78 -17
package/index.d.ts
CHANGED
|
@@ -1488,28 +1488,32 @@ export declare function getQrAsJsonContent(source: QrSource): Promise<QrJsonResu
|
|
|
1488
1488
|
|
|
1489
1489
|
export interface RecognizeImageResult {
|
|
1490
1490
|
success: boolean;
|
|
1491
|
-
/** Whether the TextDetector API is available in this browser. */
|
|
1492
|
-
supported?: boolean;
|
|
1493
1491
|
/** BCP-47 code of the primary language used for recognition. */
|
|
1494
1492
|
detectedLanguage?: string;
|
|
1495
|
-
/** Full extracted text, newline-separated by detected region. */
|
|
1493
|
+
/** Full extracted text from OCR, newline-separated by detected region. */
|
|
1496
1494
|
text?: string;
|
|
1497
|
-
/** OCR confidence score 0–100
|
|
1495
|
+
/** OCR confidence score 0–100. */
|
|
1498
1496
|
confidence?: number | null;
|
|
1499
|
-
/**
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1497
|
+
/**
|
|
1498
|
+
* All readable lines from the OCR output as a key-value object.
|
|
1499
|
+
* Lines matching `ALL-CAPS KEY : value` use the label as the key.
|
|
1500
|
+
* Lines without a recognisable label are assigned generic keys (`param_1`, `param_2`, …).
|
|
1501
|
+
* Continuation lines (e.g. a wrapped address) are appended to the previous key.
|
|
1502
|
+
*/
|
|
1503
|
+
fields?: Record<string, string>;
|
|
1504
|
+
/** Raw Tesseract output including per-word bounding boxes and metadata. */
|
|
1505
|
+
rawJson?: object;
|
|
1505
1506
|
/** Human-readable error when success is false. */
|
|
1506
1507
|
error?: string;
|
|
1507
1508
|
}
|
|
1508
1509
|
|
|
1509
1510
|
/**
|
|
1510
|
-
*
|
|
1511
|
-
*
|
|
1512
|
-
*
|
|
1511
|
+
* Runs OCR on a base64 image in all browsers with no npm dependency.
|
|
1512
|
+
* Powered by Tesseract.js loaded on demand from a CDN (fetched once, then
|
|
1513
|
+
* browser-cached). Preprocesses the image (grayscale + 2× upscale + contrast
|
|
1514
|
+
* boost) before recognition for higher accuracy. Returns structured `fields`
|
|
1515
|
+
* with extracted key-value pairs alongside the raw `text`, `confidence` score,
|
|
1516
|
+
* and `rawJson` with full word-level bounding-box metadata.
|
|
1513
1517
|
*/
|
|
1514
1518
|
export declare function recognizeImageContent(
|
|
1515
1519
|
base64Image: string,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "meticulous-ui",
|
|
3
|
-
"version": "3.12.
|
|
3
|
+
"version": "3.12.1",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"description": "A comprehensive React UI component library with a wide range of customizable components, icons, colors, and utilities for building modern web applications.",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -1,4 +1,62 @@
|
|
|
1
|
-
const
|
|
1
|
+
const b = (l) => new Promise((n, s) => {
|
|
2
|
+
const o = new Image();
|
|
3
|
+
o.onload = () => {
|
|
4
|
+
const r = document.createElement("canvas");
|
|
5
|
+
r.width = o.width * 2, r.height = o.height * 2;
|
|
6
|
+
const e = r.getContext("2d");
|
|
7
|
+
e.filter = "grayscale(1) contrast(1.8)", e.drawImage(o, 0, 0, r.width, r.height), n(r.toDataURL("image/png"));
|
|
8
|
+
}, o.onerror = s, o.src = l;
|
|
9
|
+
}), u = (l) => {
|
|
10
|
+
var r;
|
|
11
|
+
const n = ((r = l.words) != null ? r : []).map((e) => {
|
|
12
|
+
var t;
|
|
13
|
+
return { text: (t = e.text) == null ? void 0 : t.trim(), bbox: e.bbox };
|
|
14
|
+
}).filter((e) => e.text && e.bbox);
|
|
15
|
+
if (!n.length) return [];
|
|
16
|
+
const s = [];
|
|
17
|
+
for (const e of n) {
|
|
18
|
+
const t = (e.bbox.y0 + e.bbox.y1) / 2, c = (e.bbox.y1 - e.bbox.y0) / 2;
|
|
19
|
+
let a = s.find((m) => Math.abs(m.cy - t) < c);
|
|
20
|
+
a || (a = { cy: t, words: [] }, s.push(a)), a.words.push(e);
|
|
21
|
+
}
|
|
22
|
+
const o = [];
|
|
23
|
+
for (const e of s) {
|
|
24
|
+
const t = e.words.slice().sort((i, x) => i.bbox.x0 - x.bbox.x0), c = t.slice(1).map((i, x) => i.bbox.x0 - t[x].bbox.x1), a = c.length ? c.reduce((i, x) => i + x, 0) / c.length : 0, m = Math.max(a * 3, (t[0].bbox.y1 - t[0].bbox.y0) * 1.5);
|
|
25
|
+
let d = [t[0]];
|
|
26
|
+
for (let i = 1; i < t.length; i++)
|
|
27
|
+
t[i].bbox.x0 - t[i - 1].bbox.x1 > m && (o.push({
|
|
28
|
+
text: d.map((x) => x.text).join(" "),
|
|
29
|
+
y: e.cy,
|
|
30
|
+
x: d[0].bbox.x0
|
|
31
|
+
}), d = []), d.push(t[i]);
|
|
32
|
+
o.push({
|
|
33
|
+
text: d.map((i) => i.text).join(" "),
|
|
34
|
+
y: e.cy,
|
|
35
|
+
x: d[0].bbox.x0
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return o.sort((e, t) => e.y - t.y || e.x - t.x), o.map((e) => e.text);
|
|
39
|
+
}, h = (l) => {
|
|
40
|
+
const n = {};
|
|
41
|
+
let s = null, o = 0;
|
|
42
|
+
const r = (e) => {
|
|
43
|
+
let t = e.replace(/^[^A-Za-z0-9"'(]+/, "").trim();
|
|
44
|
+
return t = t.replace(/[^A-Za-z0-9"')]+$/, "").trim(), t = t.replace(/^[A-Za-z]{1,3}\s+(?=\d)/, ""), t;
|
|
45
|
+
};
|
|
46
|
+
for (const e of l) {
|
|
47
|
+
const t = r(e.trim());
|
|
48
|
+
if (!t) {
|
|
49
|
+
s = null;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const c = t.match(/\b([A-Z][A-Z.]{0,}(?:\s+[A-Z.]+){0,2})\s*[:©]\s*(.+)/);
|
|
53
|
+
if (c) {
|
|
54
|
+
const a = c[1].trim();
|
|
55
|
+
n[a] = c[2].trim(), s = a;
|
|
56
|
+
} else s && /^[A-Z0-9][A-Z0-9\s.,'\-]+$/.test(t) ? (n[s] += " " + t, s = null) : (/\w{3,}/.test(t) && (n[`param_${++o}`] = t), s = null);
|
|
57
|
+
}
|
|
58
|
+
return n;
|
|
59
|
+
}, g = {
|
|
2
60
|
en: "eng",
|
|
3
61
|
hi: "hin",
|
|
4
62
|
fr: "fra",
|
|
@@ -17,37 +75,40 @@ const l = {
|
|
|
17
75
|
vi: "vie",
|
|
18
76
|
th: "tha",
|
|
19
77
|
id: "ind"
|
|
20
|
-
},
|
|
21
|
-
var
|
|
22
|
-
return (
|
|
78
|
+
}, f = (l) => l.map((n) => {
|
|
79
|
+
var s;
|
|
80
|
+
return (s = g[n]) != null ? s : n;
|
|
23
81
|
}).join("+");
|
|
24
|
-
let
|
|
25
|
-
const
|
|
82
|
+
let p = null;
|
|
83
|
+
const y = () => (p || (p = import(
|
|
26
84
|
/* webpackIgnore: true */
|
|
27
85
|
/* @vite-ignore */
|
|
28
86
|
"https://esm.sh/tesseract.js@5"
|
|
29
|
-
)),
|
|
30
|
-
var
|
|
87
|
+
)), p), w = async (l, n = "en") => {
|
|
88
|
+
var s;
|
|
31
89
|
try {
|
|
32
|
-
const
|
|
90
|
+
const o = l.startsWith("data:") ? l : `data:image/png;base64,${l}`, r = n.split("+").filter(Boolean), e = await b(o), { createWorker: t } = await y(), c = await t(f(r));
|
|
33
91
|
try {
|
|
34
|
-
|
|
92
|
+
await c.setParameters({ tessedit_pageseg_mode: "3" });
|
|
93
|
+
const { data: a } = await c.recognize(e), m = a.text.trim();
|
|
35
94
|
return {
|
|
36
95
|
success: !0,
|
|
37
|
-
detectedLanguage: (
|
|
38
|
-
text:
|
|
39
|
-
confidence:
|
|
96
|
+
detectedLanguage: (s = r[0]) != null ? s : "en",
|
|
97
|
+
text: m,
|
|
98
|
+
confidence: a.confidence,
|
|
40
99
|
// 0–100
|
|
41
|
-
|
|
100
|
+
fields: h(u(a)),
|
|
101
|
+
// structured key-value extraction, split on bbox gaps
|
|
102
|
+
rawJson: a
|
|
42
103
|
// full metadata: words, blocks, bounding boxes
|
|
43
104
|
};
|
|
44
105
|
} finally {
|
|
45
106
|
await c.terminate();
|
|
46
107
|
}
|
|
47
|
-
} catch (
|
|
48
|
-
return { success: !1, error:
|
|
108
|
+
} catch (o) {
|
|
109
|
+
return { success: !1, error: o.message };
|
|
49
110
|
}
|
|
50
111
|
};
|
|
51
112
|
export {
|
|
52
|
-
|
|
113
|
+
w as default
|
|
53
114
|
};
|