@wirunrom/hqr-generate 0.3.11 → 0.4.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.
- package/README.md +365 -137
- package/index.d.ts +56 -17
- package/index.node.js +33 -0
- package/index.web.d.ts +2 -0
- package/index.web.js +23 -32
- package/package.json +35 -13
- package/pkg/nodejs/hqr_generate.d.ts +10 -0
- package/pkg/nodejs/hqr_generate.js +339 -0
- package/pkg/nodejs/hqr_generate_bg.wasm +0 -0
- package/pkg/{bundler → nodejs}/hqr_generate_bg.wasm.d.ts +8 -5
- package/pkg/web/hqr_generate.d.ts +13 -8
- package/pkg/web/hqr_generate.js +148 -9
- package/pkg/web/hqr_generate_bg.wasm +0 -0
- package/pkg/web/hqr_generate_bg.wasm.d.ts +8 -5
- package/react/index.d.ts +3 -12
- package/react/index.js +3 -4
- package/react/useDecode.d.ts +5 -0
- package/react/useDecode.js +33 -0
- package/react/useGenerate.d.ts +7 -0
- package/react/useGenerate.js +54 -0
- package/react/useGenerateSvg.d.ts +7 -0
- package/react/useGenerateSvg.js +48 -0
- package/index.bundler.js +0 -59
- package/pkg/bundler/LICENSE +0 -21
- package/pkg/bundler/README.md +0 -230
- package/pkg/bundler/hqr_generate.d.ts +0 -8
- package/pkg/bundler/hqr_generate.js +0 -9
- package/pkg/bundler/hqr_generate_bg.js +0 -192
- package/pkg/bundler/hqr_generate_bg.wasm +0 -0
- package/pkg/bundler/package.json +0 -23
- package/pkg/web/LICENSE +0 -21
- package/pkg/web/README.md +0 -230
- package/pkg/web/package.json +0 -21
- package/react/useQrDecodeFromImageData.d.ts +0 -5
- package/react/useQrDecodeFromImageData.js +0 -47
- package/react/useQrDecodeFromImageSrc.d.ts +0 -6
- package/react/useQrDecodeFromImageSrc.js +0 -59
- package/react/useQrPngBlobUrl.d.ts +0 -6
- package/react/useQrPngBlobUrl.js +0 -52
- package/react/useQrPngDataUrl.d.ts +0 -6
- package/react/useQrPngDataUrl.js +0 -41
package/README.md
CHANGED
|
@@ -1,29 +1,50 @@
|
|
|
1
1
|
# @wirunrom/hqr-generate
|
|
2
2
|
|
|
3
|
-
A high-performance **QR Code generator and decoder**
|
|
4
|
-
**
|
|
3
|
+
A high-performance **QR Code generator and decoder**
|
|
4
|
+
focused on **maximum scan reliability** and a **binary-first design**,
|
|
5
|
+
powered by **Rust + WebAssembly (WASM)**.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
This library intentionally keeps its core **simple, fast, and environment-agnostic**.
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Design Philosophy
|
|
12
|
+
|
|
13
|
+
This library follows a **byte-first architecture**:
|
|
14
|
+
|
|
15
|
+
- Core APIs always return **raw binary (`Uint8Array`)**
|
|
16
|
+
- No Base64 or Data URL generation in the core
|
|
17
|
+
- Rendering is handled at the **UI / presentation layer**
|
|
18
|
+
- Works consistently across:
|
|
19
|
+
- Browser
|
|
20
|
+
- React
|
|
21
|
+
- Next.js (Client & Server Components)
|
|
22
|
+
- Node.js (SSR / API routes)
|
|
23
|
+
|
|
24
|
+
This design ensures:
|
|
25
|
+
|
|
26
|
+
- Better performance
|
|
27
|
+
- Lower memory usage
|
|
28
|
+
- Clean separation between data and presentation
|
|
29
|
+
- Predictable behavior across environments
|
|
9
30
|
|
|
10
31
|
---
|
|
11
32
|
|
|
12
33
|
## Features
|
|
13
34
|
|
|
14
|
-
- High-contrast **black & white only**
|
|
15
|
-
|
|
16
|
-
- Deterministic and consistent
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- Plain HTML / JavaScript
|
|
35
|
+
- High-contrast **black & white only** QR codes
|
|
36
|
+
(scan reliability first)
|
|
37
|
+
- Deterministic and consistent output
|
|
38
|
+
- **Raw PNG bytes (`Uint8Array`)** generation
|
|
39
|
+
- **SVG output** for resolution-independent rendering
|
|
40
|
+
- QR decoding from:
|
|
41
|
+
- `Uint8Array`
|
|
42
|
+
- Browser `ImageData`
|
|
43
|
+
- Optimized for:
|
|
24
44
|
- React
|
|
25
|
-
- Next.js
|
|
26
|
-
-
|
|
45
|
+
- Next.js (App Router & SSR)
|
|
46
|
+
- Plain HTML / JavaScript
|
|
47
|
+
- Lightweight and fast (Rust + WASM)
|
|
27
48
|
|
|
28
49
|
---
|
|
29
50
|
|
|
@@ -33,198 +54,405 @@ This library is designed with a **scan-reliability-first** mindset and a **front
|
|
|
33
54
|
npm install @wirunrom/hqr-generate
|
|
34
55
|
```
|
|
35
56
|
|
|
36
|
-
## API Reference
|
|
57
|
+
## API Reference
|
|
37
58
|
|
|
38
|
-
|
|
59
|
+
| Function | Parameters | Returns |
|
|
60
|
+
| ------------------------------ | --------------------------------------------- | --------------------------------- |
|
|
61
|
+
| `generate(text, options?)` | `text: string`<br>`options?: GenerateOptions` | `Promise<Uint8Array>` (PNG bytes) |
|
|
62
|
+
| `generate_svg(text, options?)` | `text: string`<br>`options?: GenerateOptions` | `Promise<string>` (SVG markup) |
|
|
63
|
+
| `decode(input)` | `input: Uint8Array \| ImageData` | `Promise<string>` (decoded text) |
|
|
39
64
|
|
|
40
|
-
|
|
65
|
+
### GenerateOptions
|
|
41
66
|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
| ecc | `"L" \| "M" \| "Q" \| "H"` | `"Q"` | Error correction level |
|
|
67
|
+
| Option | Type | Default | Description |
|
|
68
|
+
| -------- | -------------------------- | ------- | ----------------------------- |
|
|
69
|
+
| `size` | `number` | `320` | Output image size (px) |
|
|
70
|
+
| `margin` | `number` | `4` | Quiet zone / margin (modules) |
|
|
71
|
+
| `ecc` | `'L' \| 'M' \| 'Q' \| 'H'` | `'Q'` | Error correction level |
|
|
48
72
|
|
|
49
|
-
|
|
73
|
+
### Notes
|
|
50
74
|
|
|
51
|
-
**
|
|
75
|
+
- All generate APIs return **raw data**, not Base64 or Data URLs.
|
|
76
|
+
- PNG output is returned as **binary bytes (`Uint8Array`)**.
|
|
77
|
+
- SVG output is returned as **plain string markup**.
|
|
52
78
|
|
|
53
|
-
|
|
79
|
+
---
|
|
54
80
|
|
|
55
|
-
|
|
56
|
-
import { qr_png_data_url } from "@wirunrom/hqr-generate";
|
|
81
|
+
## Client-side Usage (Recommended)
|
|
57
82
|
|
|
58
|
-
|
|
83
|
+
When rendering QR codes in the browser or a Client Component,
|
|
84
|
+
use the React hook provided by the `/react` entry.
|
|
59
85
|
|
|
60
|
-
|
|
61
|
-
```
|
|
86
|
+
The hook automatically:
|
|
62
87
|
|
|
63
|
-
|
|
88
|
+
- Calls the core API
|
|
89
|
+
- Converts binary data to a `Blob URL`
|
|
90
|
+
- Handles cleanup (`URL.revokeObjectURL`)
|
|
64
91
|
|
|
65
|
-
|
|
92
|
+
```tsx
|
|
93
|
+
"use client";
|
|
66
94
|
|
|
67
|
-
|
|
68
|
-
import { qr_png_bytes } from "@wirunrom/hqr-generate";
|
|
95
|
+
import { useGenerate } from "@wirunrom/hqr-generate/react";
|
|
69
96
|
|
|
70
|
-
|
|
97
|
+
export default function QR() {
|
|
98
|
+
const { src, loading } = useGenerate("hello world", {
|
|
99
|
+
size: 320,
|
|
100
|
+
ecc: "Q",
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (loading) return <p>Loading…</p>;
|
|
104
|
+
return <img src={src ?? ""} alt="QR Code" />;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
71
107
|
|
|
72
|
-
|
|
73
|
-
new Blob([bytes], { type: "image/png" })
|
|
74
|
-
);
|
|
108
|
+
Internally, the hook performs:
|
|
75
109
|
|
|
76
|
-
<img src={url} alt="QR Code" />
|
|
77
110
|
```
|
|
111
|
+
Uint8Array → Blob → blob: URL
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
78
115
|
|
|
79
|
-
|
|
116
|
+
## Next.js SSR / Route Handlers
|
|
80
117
|
|
|
81
|
-
|
|
118
|
+
When generating QR codes on the server,
|
|
119
|
+
the API returns raw PNG bytes.
|
|
82
120
|
|
|
83
121
|
```ts
|
|
84
|
-
import {
|
|
122
|
+
import { generate } from "@wirunrom/hqr-generate";
|
|
85
123
|
|
|
86
|
-
|
|
87
|
-
const
|
|
124
|
+
export async function GET() {
|
|
125
|
+
const bytes = await generate("hello ssr");
|
|
88
126
|
|
|
89
|
-
|
|
127
|
+
return new Response(bytes, {
|
|
128
|
+
headers: {
|
|
129
|
+
"Content-Type": "image/png",
|
|
130
|
+
"Cache-Control": "public, max-age=60",
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
}
|
|
90
134
|
```
|
|
91
135
|
|
|
92
|
-
|
|
136
|
+
No Base64 conversion is required.
|
|
137
|
+
|
|
138
|
+
---
|
|
93
139
|
|
|
94
|
-
##
|
|
140
|
+
## SSR → Client Rendering
|
|
95
141
|
|
|
96
|
-
|
|
142
|
+
If you generate QR codes on the server
|
|
143
|
+
but render them on the client:
|
|
97
144
|
|
|
98
|
-
|
|
145
|
+
1. Generate bytes on the server
|
|
146
|
+
2. Convert bytes to a `Blob` on the client
|
|
99
147
|
|
|
100
|
-
|
|
148
|
+
```tsx
|
|
149
|
+
// Server Component
|
|
150
|
+
import { generate } from "@wirunrom/hqr-generate";
|
|
151
|
+
import ClientQr from "./ClientQr";
|
|
101
152
|
|
|
102
|
-
|
|
103
|
-
|
|
153
|
+
export default async function Page() {
|
|
154
|
+
const bytes = await generate("hello ssr");
|
|
155
|
+
return <ClientQr bytes={bytes} />;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
104
158
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
159
|
+
```tsx
|
|
160
|
+
// Client Component
|
|
161
|
+
"use client";
|
|
162
|
+
|
|
163
|
+
import { useEffect, useState } from "react";
|
|
164
|
+
|
|
165
|
+
export default function ClientQr({ bytes }: { bytes: Uint8Array }) {
|
|
166
|
+
const [src, setSrc] = useState<string>("");
|
|
167
|
+
|
|
168
|
+
useEffect(() => {
|
|
169
|
+
const blob = new Blob([bytes], { type: "image/png" });
|
|
170
|
+
const url = URL.createObjectURL(blob);
|
|
171
|
+
setSrc(url);
|
|
172
|
+
return () => URL.revokeObjectURL(url);
|
|
173
|
+
}, [bytes]);
|
|
111
174
|
|
|
112
|
-
if (!src) return null;
|
|
113
175
|
return <img src={src} alt="QR Code" />;
|
|
114
176
|
}
|
|
115
177
|
```
|
|
116
178
|
|
|
117
|
-
|
|
179
|
+
---
|
|
118
180
|
|
|
119
|
-
|
|
120
|
-
Recommended for larger QR codes or frequent updates.
|
|
181
|
+
## Generate QR Code (SVG)
|
|
121
182
|
|
|
122
|
-
|
|
123
|
-
|
|
183
|
+
If you want to generate a QR code as **SVG** in React,
|
|
184
|
+
use the `useGenerateSvg` hook from the `/react` entry.
|
|
185
|
+
|
|
186
|
+
This hook:
|
|
124
187
|
|
|
125
|
-
|
|
126
|
-
|
|
188
|
+
- Calls the core `generate_svg()` API
|
|
189
|
+
- Converts SVG markup into a `Blob URL`
|
|
190
|
+
- Returns a `src` that can be used directly in `<img />`
|
|
191
|
+
- Automatically handles cleanup (`URL.revokeObjectURL`)
|
|
192
|
+
|
|
193
|
+
### Example
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
"use client";
|
|
197
|
+
|
|
198
|
+
import { useGenerateSvg } from "@wirunrom/hqr-generate/react";
|
|
199
|
+
|
|
200
|
+
export default function QrSvg() {
|
|
201
|
+
const { src, loading } = useGenerateSvg("hello svg", {
|
|
127
202
|
size: 320,
|
|
128
|
-
margin: 4,
|
|
129
203
|
ecc: "Q",
|
|
130
204
|
});
|
|
131
205
|
|
|
132
|
-
if (
|
|
133
|
-
|
|
206
|
+
if (loading) return <p>Loading…</p>;
|
|
207
|
+
|
|
208
|
+
return src && <img src={src} alt="QR Code (SVG)" />;
|
|
134
209
|
}
|
|
135
210
|
```
|
|
136
211
|
|
|
137
|
-
|
|
212
|
+
---
|
|
138
213
|
|
|
139
|
-
|
|
214
|
+
### Returned Values
|
|
140
215
|
|
|
141
216
|
```ts
|
|
142
|
-
|
|
217
|
+
const {
|
|
218
|
+
src, // string | null (Blob URL for <img>)
|
|
219
|
+
svg, // string | null (raw SVG markup)
|
|
220
|
+
loading,
|
|
221
|
+
error,
|
|
222
|
+
} = useGenerateSvg(text, options);
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Design Notes
|
|
226
|
+
|
|
227
|
+
- SVG generation is **data-first** at the core level
|
|
228
|
+
- Rendering decisions are handled in the React hook
|
|
229
|
+
- `src` is provided for convenience and safety
|
|
230
|
+
- Advanced users can use `svg` to render inline SVG manually if needed
|
|
231
|
+
|
|
232
|
+
---
|
|
143
233
|
|
|
144
|
-
|
|
145
|
-
const { text, loading, error } = useQrDecodeFromImageData(image);
|
|
234
|
+
## Decode QR Code (Client-side)
|
|
146
235
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (!text) return null;
|
|
236
|
+
To decode a QR code in the browser,
|
|
237
|
+
use the `useDecode` hook from the `/react` entry.
|
|
150
238
|
|
|
151
|
-
|
|
239
|
+
> ⚠️ `useDecode` accepts **ImageData only**
|
|
240
|
+
> If you have PNG bytes or an image URL, convert them to `ImageData` first using Canvas APIs.
|
|
241
|
+
|
|
242
|
+
### Example (decode from Canvas ImageData)
|
|
243
|
+
|
|
244
|
+
```tsx
|
|
245
|
+
"use client";
|
|
246
|
+
|
|
247
|
+
import { useDecode } from "@wirunrom/hqr-generate/react";
|
|
248
|
+
|
|
249
|
+
export default function DecodeQr({ imageData }: { imageData: ImageData }) {
|
|
250
|
+
const { text, loading, error } = useDecode(imageData);
|
|
251
|
+
|
|
252
|
+
if (loading) return <p>Decoding…</p>;
|
|
253
|
+
if (error) return <p>Failed to decode</p>;
|
|
254
|
+
|
|
255
|
+
return <p>Decoded text: {text}</p>;
|
|
152
256
|
}
|
|
153
257
|
```
|
|
154
258
|
|
|
155
|
-
|
|
259
|
+
---
|
|
156
260
|
|
|
157
|
-
|
|
158
|
-
| ----- | ----------- | ------------------------------------------- |
|
|
159
|
-
| image | `ImageData` | RGBA image data from Canvas or Camera frame |
|
|
261
|
+
## `useDecode` API Reference
|
|
160
262
|
|
|
161
|
-
|
|
263
|
+
### Signature
|
|
162
264
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
265
|
+
```ts
|
|
266
|
+
function useDecode(input?: ImageData): {
|
|
267
|
+
text: string | null;
|
|
268
|
+
loading: boolean;
|
|
269
|
+
error: unknown | null;
|
|
270
|
+
};
|
|
271
|
+
```
|
|
166
272
|
|
|
167
|
-
|
|
273
|
+
### Parameters
|
|
168
274
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
- Best results with:
|
|
173
|
-
- High-contrast QR codes
|
|
174
|
-
- Minimal blur
|
|
175
|
-
- Proper quiet zone
|
|
275
|
+
| Name | Type | Description |
|
|
276
|
+
| ------- | ---------------------- | -------------------------------------------------------------------- |
|
|
277
|
+
| `input` | `ImageData` (optional) | Image data containing a QR code. Decoding is skipped if `undefined`. |
|
|
176
278
|
|
|
177
|
-
|
|
279
|
+
### Returns
|
|
178
280
|
|
|
179
|
-
|
|
281
|
+
| Field | Type | Description |
|
|
282
|
+
| --------- | ----------------- | --------------------------------------------- |
|
|
283
|
+
| `text` | `string \| null` | Decoded QR text, or `null` if not decoded yet |
|
|
284
|
+
| `loading` | `boolean` | `true` while decoding is in progress |
|
|
285
|
+
| `error` | `unknown \| null` | Error object if decoding fails |
|
|
180
286
|
|
|
181
|
-
|
|
182
|
-
import { useQrDecodeFromImageSrc } from "@wirunrom/hqr-generate/react";
|
|
287
|
+
---
|
|
183
288
|
|
|
184
|
-
|
|
185
|
-
const { text } = useQrDecodeFromImageSrc(imagePath);
|
|
289
|
+
### Design Notes
|
|
186
290
|
|
|
187
|
-
|
|
291
|
+
- `useDecode` is **browser-only**
|
|
292
|
+
- It does **not** perform:
|
|
293
|
+
- image loading
|
|
294
|
+
- network requests
|
|
295
|
+
- Base64 conversion
|
|
188
296
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
297
|
+
- This keeps decoding:
|
|
298
|
+
- predictable
|
|
299
|
+
- side-effect free
|
|
300
|
+
- consistent with the binary-first core API
|
|
192
301
|
|
|
193
|
-
|
|
302
|
+
If you have an image URL or PNG bytes,
|
|
303
|
+
convert them to `ImageData` explicitly before calling `useDecode`.
|
|
194
304
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Plain HTML / Vanilla JavaScript Usage
|
|
308
|
+
|
|
309
|
+
The library can be used directly in **plain HTML** using ES Modules.
|
|
310
|
+
No framework or build tool is required.
|
|
311
|
+
|
|
312
|
+
> Note: The example assumes you are serving files over HTTP
|
|
313
|
+
> (do not open the file via `file://`), because WASM requires HTTP.
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
### Generate QR Code (PNG)
|
|
318
|
+
|
|
319
|
+
```html
|
|
320
|
+
<!doctype html>
|
|
321
|
+
<html lang="en">
|
|
322
|
+
<body>
|
|
323
|
+
<h3>Generate PNG QR</h3>
|
|
324
|
+
|
|
325
|
+
<input id="text" value="hello world" />
|
|
326
|
+
<button id="btn">Generate</button>
|
|
327
|
+
|
|
328
|
+
<br /><br />
|
|
329
|
+
<img id="img" />
|
|
330
|
+
|
|
331
|
+
<script type="module">
|
|
332
|
+
import { generate } from "https://esm.sh/@wirunrom/hqr-generate";
|
|
333
|
+
|
|
334
|
+
const btn = document.getElementById("btn");
|
|
335
|
+
const img = document.getElementById("img");
|
|
336
|
+
const input = document.getElementById("text");
|
|
337
|
+
|
|
338
|
+
btn.onclick = async () => {
|
|
339
|
+
const bytes = await generate(input.value, {
|
|
340
|
+
size: 256,
|
|
341
|
+
ecc: "Q",
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
const blob = new Blob([bytes], { type: "image/png" });
|
|
345
|
+
const url = URL.createObjectURL(blob);
|
|
346
|
+
img.src = url;
|
|
347
|
+
};
|
|
348
|
+
</script>
|
|
349
|
+
</body>
|
|
350
|
+
</html>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
---
|
|
198
354
|
|
|
199
|
-
|
|
355
|
+
### Generate QR Code (SVG)
|
|
200
356
|
|
|
201
|
-
|
|
202
|
-
|
|
357
|
+
```html
|
|
358
|
+
<!doctype html>
|
|
359
|
+
<html lang="en">
|
|
360
|
+
<body>
|
|
361
|
+
<h3>Generate SVG QR</h3>
|
|
362
|
+
|
|
363
|
+
<input id="text" value="hello world" />
|
|
364
|
+
<button id="btn">Generate</button>
|
|
365
|
+
|
|
366
|
+
<br /><br />
|
|
367
|
+
<div id="svg"></div>
|
|
368
|
+
|
|
369
|
+
<script type="module">
|
|
370
|
+
import { generate_svg } from "https://esm.sh/@wirunrom/hqr-generate";
|
|
371
|
+
|
|
372
|
+
const btn = document.getElementById("btn");
|
|
373
|
+
const input = document.getElementById("text");
|
|
374
|
+
const container = document.getElementById("svg");
|
|
375
|
+
|
|
376
|
+
btn.onclick = async () => {
|
|
377
|
+
const svg = await generate_svg(input.value, {
|
|
378
|
+
size: 256,
|
|
379
|
+
ecc: "Q",
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
container.innerHTML = svg;
|
|
383
|
+
};
|
|
384
|
+
</script>
|
|
385
|
+
</body>
|
|
386
|
+
</html>
|
|
387
|
+
```
|
|
203
388
|
|
|
204
|
-
|
|
389
|
+
---
|
|
205
390
|
|
|
206
|
-
|
|
391
|
+
### Decode QR Code
|
|
207
392
|
|
|
208
393
|
```html
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
394
|
+
<!doctype html>
|
|
395
|
+
<html lang="en">
|
|
396
|
+
<body>
|
|
397
|
+
<h3>Decode QR</h3>
|
|
398
|
+
|
|
399
|
+
<input type="file" id="file" accept="image/*" />
|
|
400
|
+
<p id="result"></p>
|
|
401
|
+
|
|
402
|
+
<script type="module">
|
|
403
|
+
import { decode } from "https://esm.sh/@wirunrom/hqr-generate";
|
|
404
|
+
|
|
405
|
+
const fileInput = document.getElementById("file");
|
|
406
|
+
const result = document.getElementById("result");
|
|
407
|
+
|
|
408
|
+
fileInput.onchange = async () => {
|
|
409
|
+
const file = fileInput.files?.[0];
|
|
410
|
+
if (!file) return;
|
|
411
|
+
|
|
412
|
+
const img = new Image();
|
|
413
|
+
img.src = URL.createObjectURL(file);
|
|
414
|
+
|
|
415
|
+
img.onload = async () => {
|
|
416
|
+
const canvas = document.createElement("canvas");
|
|
417
|
+
canvas.width = img.width;
|
|
418
|
+
canvas.height = img.height;
|
|
419
|
+
|
|
420
|
+
const ctx = canvas.getContext("2d");
|
|
421
|
+
ctx.drawImage(img, 0, 0);
|
|
422
|
+
|
|
423
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
424
|
+
const text = await decode(imageData);
|
|
425
|
+
|
|
426
|
+
result.textContent = `Decoded text: ${text}`;
|
|
427
|
+
};
|
|
428
|
+
};
|
|
429
|
+
</script>
|
|
430
|
+
</body>
|
|
431
|
+
</html>
|
|
230
432
|
```
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## What This Library Does NOT Do
|
|
437
|
+
|
|
438
|
+
- ❌ No Base64 or Data URL generation in the core
|
|
439
|
+
- ❌ No JPG / WebP / GIF rendering
|
|
440
|
+
- ❌ No DOM or framework-specific logic outside `/react`
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
## Summary
|
|
445
|
+
|
|
446
|
+
- Core → returns `Uint8Array`
|
|
447
|
+
- React hooks → handle `Blob` conversion
|
|
448
|
+
- SSR → returns raw bytes or `Response`
|
|
449
|
+
- Client → renders via `blob:` URL
|
|
450
|
+
|
|
451
|
+
> Keep data binary.
|
|
452
|
+
> Convert only at the UI boundary.
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## Changelog
|
|
457
|
+
|
|
458
|
+
See [CHANGELOG.md](./CHANGELOG.md)
|
package/index.d.ts
CHANGED
|
@@ -1,29 +1,68 @@
|
|
|
1
|
+
/* =========================================================
|
|
2
|
+
* Types
|
|
3
|
+
* ======================================================= */
|
|
4
|
+
|
|
1
5
|
export type QrEcc = "L" | "M" | "Q" | "H";
|
|
2
6
|
|
|
7
|
+
export interface GenerateOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Output image size (px)
|
|
10
|
+
* @default 320
|
|
11
|
+
*/
|
|
12
|
+
size?: number;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Quiet zone / margin (modules)
|
|
16
|
+
* @default 4
|
|
17
|
+
*/
|
|
18
|
+
margin?: number;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Error correction level
|
|
22
|
+
* @default "Q"
|
|
23
|
+
*/
|
|
24
|
+
ecc?: QrEcc;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* =========================================================
|
|
28
|
+
* Generate (Encode)
|
|
29
|
+
* ======================================================= */
|
|
30
|
+
|
|
3
31
|
/**
|
|
4
|
-
* Generate QR code PNG
|
|
32
|
+
* Generate QR code (PNG, fastest & default)
|
|
5
33
|
*/
|
|
6
|
-
export
|
|
34
|
+
export function generate(
|
|
7
35
|
text: string,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
ecc?: QrEcc
|
|
11
|
-
): Promise<string>;
|
|
36
|
+
opts?: GenerateOptions
|
|
37
|
+
): Promise<Uint8Array> | Uint8Array;
|
|
12
38
|
|
|
13
39
|
/**
|
|
14
|
-
* Generate QR code
|
|
15
|
-
* Recommended for best performance (Blob URL, upload, caching).
|
|
40
|
+
* Generate QR code as PNG
|
|
16
41
|
*/
|
|
17
|
-
export
|
|
42
|
+
export function generate_png(
|
|
18
43
|
text: string,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
44
|
+
opts?: GenerateOptions
|
|
45
|
+
): Promise<Uint8Array> | Uint8Array;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Generate QR code as SVG
|
|
49
|
+
*/
|
|
50
|
+
export function generate_svg(
|
|
51
|
+
text: string,
|
|
52
|
+
opts?: GenerateOptions
|
|
53
|
+
): Promise<string> | string;
|
|
54
|
+
|
|
55
|
+
/* =========================================================
|
|
56
|
+
* Decode
|
|
57
|
+
* ======================================================= */
|
|
23
58
|
|
|
24
59
|
/**
|
|
25
|
-
* Decode QR from
|
|
60
|
+
* Decode QR code from image source
|
|
61
|
+
*
|
|
62
|
+
* Supported inputs:
|
|
63
|
+
* - Uint8Array (PNG / JPG / WebP / etc.)
|
|
64
|
+
* - ImageData (Browser / Canvas)
|
|
26
65
|
*/
|
|
27
|
-
export function
|
|
28
|
-
|
|
29
|
-
): Promise<string
|
|
66
|
+
export function decode(
|
|
67
|
+
input: Uint8Array | ImageData
|
|
68
|
+
): Promise<string> | string;
|