@tapple.io/qr-code-generator 0.9.0
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/LICENSE +21 -0
- package/README.md +578 -0
- package/dist/browser.mjs +29 -0
- package/dist/index.d.ts +230 -0
- package/dist/node.cjs +29 -0
- package/dist/node.mjs +29 -0
- package/package.json +104 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tapple Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
# Tapple QR
|
|
2
|
+
|
|
3
|
+
A lightweight QR code generator with full TypeScript support. Generate QR codes as SVG, PNG, or ASCII with extensive customization options.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/qr-code-generator)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://www.npmjs.com/package/qr-code-generator)
|
|
8
|
+
[](https://bundlephobia.com/package/qr-code-generator)
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- 🚀 **Platform-optimized architecture** - Zero browser dependencies (native Canvas API) + one Node.js dependency (`@resvg/resvg-js`)
|
|
13
|
+
- 🌐 **Universal API** - Identical API across Node.js, browsers, and bundlers (ESM & CommonJS)
|
|
14
|
+
- 🎯 **Multiple outputs** - Generate SVG, PNG (Buffer/DataURL), or ASCII art in any environment
|
|
15
|
+
- 🎨 **Highly customizable** - Control colors, shapes, borders, logos, and more
|
|
16
|
+
- 📱 **Smart formatting** - Built-in support for WiFi, vCards, URLs, SMS, and calendar events
|
|
17
|
+
- 🔒 **Type-safe** - Full TypeScript support with comprehensive type definitions
|
|
18
|
+
- ⚡ **Auto-optimized** - Automatic version selection, error correction, and mask patterns
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install qr-code-generator
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
That's it! The package automatically provides platform-optimized bundles:
|
|
27
|
+
|
|
28
|
+
- **Browser**: Zero dependencies - uses native Canvas API
|
|
29
|
+
- **Node.js**: One dependency (`@resvg/resvg-js`) - installed automatically
|
|
30
|
+
|
|
31
|
+
**Why this matters:** Most QR libraries bundle heavy dependencies (~2.5MB) that work everywhere but bloat browser bundles. We use environment-specific implementations - Canvas API in browsers (built-in) and `@resvg/resvg-js` in Node.js (acceptable for server environments) - automatically delivering the optimal bundle for your platform.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
The following examples work universally in both Node.js and browsers:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { genQrImage, genQrText } from 'qr-code-generator';
|
|
39
|
+
|
|
40
|
+
// Generate PNG buffer (default)
|
|
41
|
+
const pngBuffer = await genQrImage('https://tapple.io');
|
|
42
|
+
|
|
43
|
+
// Generate PNG data URL
|
|
44
|
+
const pngDataUrl = await genQrImage('https://tapple.io', {
|
|
45
|
+
output: { format: 'png', type: 'dataURL' }
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Generate SVG string
|
|
49
|
+
const svg = await genQrImage('Hello World', {
|
|
50
|
+
output: { format: 'svg', type: 'string' }
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Generate SVG data URL
|
|
54
|
+
const svgDataUrl = await genQrImage('Hello World', {
|
|
55
|
+
output: { format: 'svg', type: 'dataURL' }
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Generate ASCII art (synchronous)
|
|
59
|
+
const ascii = genQrText('Terminal QR');
|
|
60
|
+
console.log(ascii);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Platform-Specific Examples
|
|
64
|
+
|
|
65
|
+
#### Saving to File (Node.js)
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { genQrImage } from 'qr-code-generator';
|
|
69
|
+
import fs from 'fs';
|
|
70
|
+
|
|
71
|
+
// Save PNG to file
|
|
72
|
+
const buffer = await genQrImage('https://tapple.io', {
|
|
73
|
+
output: { format: 'png', type: 'buffer' }
|
|
74
|
+
});
|
|
75
|
+
fs.writeFileSync('qrcode.png', buffer);
|
|
76
|
+
|
|
77
|
+
// Save SVG to file
|
|
78
|
+
const svg = await genQrImage('https://tapple.io', {
|
|
79
|
+
output: { format: 'svg', type: 'string' }
|
|
80
|
+
});
|
|
81
|
+
fs.writeFileSync('qrcode.svg', svg);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
#### Using in HTML (Browser)
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { genQrImage } from 'qr-code-generator';
|
|
88
|
+
|
|
89
|
+
// Display PNG as image (returns dataURL string)
|
|
90
|
+
const img = document.getElementById('qr-image');
|
|
91
|
+
img.src = await genQrImage('https://tapple.io', {
|
|
92
|
+
output: { format: 'png', type: 'dataURL' }
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Or use SVG data URL
|
|
96
|
+
img.src = await genQrImage('https://tapple.io', {
|
|
97
|
+
output: { format: 'svg', type: 'dataURL' }
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## API Reference
|
|
102
|
+
|
|
103
|
+
### Render Functions
|
|
104
|
+
|
|
105
|
+
#### `genQrImage(input, options?)`
|
|
106
|
+
|
|
107
|
+
Generates a QR code image. Returns a Promise that resolves to the output format specified.
|
|
108
|
+
|
|
109
|
+
**Return types:**
|
|
110
|
+
- PNG buffer: `Buffer` (Node.js) or `Uint8Array` (browser)
|
|
111
|
+
- PNG dataURL: `string`
|
|
112
|
+
- SVG string: `string`
|
|
113
|
+
- SVG dataURL: `string`
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// Default: PNG buffer
|
|
117
|
+
const buffer = await genQrImage('https://tapple.io');
|
|
118
|
+
|
|
119
|
+
// PNG data URL
|
|
120
|
+
const dataURL = await genQrImage('https://tapple.io', {
|
|
121
|
+
size: 400,
|
|
122
|
+
output: { format: 'png', type: 'dataURL' }
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// SVG string
|
|
126
|
+
const svg = await genQrImage('https://tapple.io', {
|
|
127
|
+
output: { format: 'svg', type: 'string' }
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// SVG data URL
|
|
131
|
+
const svgDataURL = await genQrImage('https://tapple.io', {
|
|
132
|
+
output: { format: 'svg', type: 'dataURL' }
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### `genQrText(input, options?)`
|
|
137
|
+
|
|
138
|
+
Generates ASCII art representation. This function is synchronous.
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
const ascii = genQrText('Hello', {
|
|
142
|
+
margin: 2,
|
|
143
|
+
darkChar: '██',
|
|
144
|
+
lightChar: ' '
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Customization Options
|
|
149
|
+
|
|
150
|
+
### Image Options (PNG & SVG)
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { genQrImage, EyeFrameShape, DotShape, BorderShape } from 'qr-code-generator';
|
|
154
|
+
|
|
155
|
+
const options = {
|
|
156
|
+
size: 300, // QR matrix size in pixels
|
|
157
|
+
margin: 24, // Margin in pixels
|
|
158
|
+
backgroundColor: '#ffffff', // Background color
|
|
159
|
+
|
|
160
|
+
// Eye (position marker) styling
|
|
161
|
+
eyes: {
|
|
162
|
+
shape: EyeFrameShape.SQUIRCLE, // 'square' | 'squircle'
|
|
163
|
+
color: '#0066ff'
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
// Pupil (center of eyes) styling
|
|
167
|
+
pupils: {
|
|
168
|
+
color: '#000000'
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
// Data dot styling
|
|
172
|
+
dots: {
|
|
173
|
+
shape: DotShape.DOTS, // 'classic' | 'dots' | 'square'
|
|
174
|
+
color: '#000000',
|
|
175
|
+
scale: 1.0 // 0.75 to 1.25
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
// Add a logo in the center
|
|
179
|
+
logo: {
|
|
180
|
+
src: 'data:image/png;base64,...', // Data URL or SVG string
|
|
181
|
+
scale: 0.2 // 0.1 to 0.3
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
// Border styling
|
|
185
|
+
border: {
|
|
186
|
+
shape: BorderShape.SQUIRCLE, // 'none' | 'square' | 'squircle' | 'circle'
|
|
187
|
+
width: 10, // Border width in pixels
|
|
188
|
+
color: '#000000',
|
|
189
|
+
style: 'solid' // 'solid' | 'dashed'
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
// Output configuration
|
|
193
|
+
output: {
|
|
194
|
+
format: 'png', // 'png' | 'svg'
|
|
195
|
+
type: 'buffer' // 'buffer' | 'dataURL' for PNG; 'string' | 'dataURL' for SVG
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const qr = await genQrImage('https://tapple.io', options);
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### ImageOptions Reference
|
|
203
|
+
|
|
204
|
+
Complete reference for PNG and SVG rendering options:
|
|
205
|
+
|
|
206
|
+
| Option | Type | Default | Valid Range | Description |
|
|
207
|
+
|--------|------|---------|-------------|-------------|
|
|
208
|
+
| `size` | number | `300` | >= 21 | QR matrix size in pixels |
|
|
209
|
+
| `margin` | number | `24` | >= 0 | Spacing around QR code in pixels |
|
|
210
|
+
| `backgroundColor` | string | `'#ffffff'` | Hex color | Background color |
|
|
211
|
+
| **Eyes (Position Markers)** |
|
|
212
|
+
| `eyes.shape` | enum | `'square'` | `'square'` \| `'squircle'` | Outer frame shape of position markers |
|
|
213
|
+
| `eyes.color` | string | `'#000000'` | Hex color | Color of eye frames |
|
|
214
|
+
| **Pupils (Eye Centers)** |
|
|
215
|
+
| `pupils.color` | string | `'#000000'` | Hex color | Color of pupil (inner square of eyes) |
|
|
216
|
+
| **Dots (Data Modules)** |
|
|
217
|
+
| `dots.shape` | enum | `'classic'` | `'classic'` \| `'dots'` \| `'square'` | Shape of data modules |
|
|
218
|
+
| `dots.color` | string | `'#000000'` | Hex color | Color of data modules |
|
|
219
|
+
| `dots.scale` | number | `1.0` | 0.75 - 1.25 | Visual size multiplier |
|
|
220
|
+
| **Logo** |
|
|
221
|
+
| `logo.src` | string | - | Data URL or SVG string | Image source |
|
|
222
|
+
| `logo.scale` | number | `0.2` | 0.1 - 0.3 | Logo size as percentage of QR width |
|
|
223
|
+
| **Border** |
|
|
224
|
+
| `border.shape` | enum | `'none'` | `'none'` \| `'square'` \| `'squircle'` \| `'circle'` | Border shape wrapping the QR code |
|
|
225
|
+
| `border.width` | number | `10` | >=0 | Border thickness in pixels |
|
|
226
|
+
| `border.color` | string | `'#000000'` | Hex color | Border color |
|
|
227
|
+
| `border.style` | enum | `'solid'` | `'solid'` \| `'dashed'` | Border line style |
|
|
228
|
+
| **Output** |
|
|
229
|
+
| `output.format` | enum | `'png'` | `'png'` \| `'svg'` | Output image format |
|
|
230
|
+
| `output.type` | enum | `'buffer'` | `'buffer'` \| `'dataURL'` (png), `'string'` \| `'dataURL'` (svg) | Output type |
|
|
231
|
+
|
|
232
|
+
> **Note:** Error correction level is automatically selected based on input length and logo presence (not user-configurable).
|
|
233
|
+
|
|
234
|
+
### TextOptions Reference
|
|
235
|
+
|
|
236
|
+
Options for ASCII text rendering:
|
|
237
|
+
|
|
238
|
+
| Option | Type | Default | Valid Range | Description |
|
|
239
|
+
|--------|------|---------|-------------|-------------|
|
|
240
|
+
| `margin` | number | `2` | >= 0 | Margin in modules (not pixels) |
|
|
241
|
+
| `darkChar` | string | `'██'` | Any string | Character(s) representing dark modules |
|
|
242
|
+
| `lightChar` | string | `' '` | Any string | Character(s) representing light modules |
|
|
243
|
+
|
|
244
|
+
## Structured Content Types
|
|
245
|
+
|
|
246
|
+
### WiFi Network
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
const qr = await genQrImage({
|
|
250
|
+
type: 'wifi',
|
|
251
|
+
data: {
|
|
252
|
+
ssid: 'MyNetwork',
|
|
253
|
+
password: 'SecurePassword123',
|
|
254
|
+
encryption: 'WPA', // 'WPA' | 'WPA2' | 'WEP' | 'nopass'
|
|
255
|
+
hidden: false
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Contact Card (vCard)
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
const qr = await genQrImage({
|
|
264
|
+
type: 'vcard',
|
|
265
|
+
data: {
|
|
266
|
+
name: 'John Doe',
|
|
267
|
+
phone: '+1-555-123-4567',
|
|
268
|
+
email: 'john@tapple.io',
|
|
269
|
+
organization: 'Acme Corp',
|
|
270
|
+
title: 'Software Engineer',
|
|
271
|
+
url: 'https://johndoe.com',
|
|
272
|
+
address: {
|
|
273
|
+
street: '123 Main St',
|
|
274
|
+
city: 'San Francisco',
|
|
275
|
+
state: 'CA',
|
|
276
|
+
zip: '94105',
|
|
277
|
+
country: 'USA'
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Calendar Event
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
const qr = await genQrImage({
|
|
287
|
+
type: 'calendar',
|
|
288
|
+
data: {
|
|
289
|
+
title: 'Team Meeting',
|
|
290
|
+
startDate: new Date('2024-12-30T14:00:00'),
|
|
291
|
+
endDate: new Date('2024-12-30T15:00:00'),
|
|
292
|
+
location: 'Conference Room A',
|
|
293
|
+
description: 'Quarterly planning session'
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Email, SMS, Phone
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
// Email with subject and body
|
|
302
|
+
const emailQR = await genQrImage({
|
|
303
|
+
type: 'email',
|
|
304
|
+
email: 'support@tapple.io',
|
|
305
|
+
subject: 'Support Request',
|
|
306
|
+
body: 'I need help with...'
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// SMS message
|
|
310
|
+
const smsQR = await genQrImage({
|
|
311
|
+
type: 'sms',
|
|
312
|
+
phone: '+1-555-123-4567',
|
|
313
|
+
message: 'Hello from QR code!'
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// Phone number
|
|
317
|
+
const phoneQR = await genQrImage({
|
|
318
|
+
type: 'phone',
|
|
319
|
+
phone: '+1-555-123-4567'
|
|
320
|
+
});
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### URL (explicit)
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
const qr = await genQrImage({
|
|
327
|
+
type: 'url',
|
|
328
|
+
url: 'https://tapple.io'
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
// Or just pass the URL directly:
|
|
332
|
+
const qr = await genQrImage('https://tapple.io');
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Shape Enums
|
|
336
|
+
|
|
337
|
+
Import shape enums for type-safe customization:
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
import { EyeFrameShape, DotShape, BorderShape, BorderStyle } from 'qr-code-generator';
|
|
341
|
+
|
|
342
|
+
// Eye shapes
|
|
343
|
+
EyeFrameShape.SQUARE
|
|
344
|
+
EyeFrameShape.SQUIRCLE
|
|
345
|
+
|
|
346
|
+
// Dot shapes
|
|
347
|
+
DotShape.CLASSIC
|
|
348
|
+
DotShape.DOTS
|
|
349
|
+
DotShape.SQUARE
|
|
350
|
+
|
|
351
|
+
// Border shapes
|
|
352
|
+
BorderShape.NONE
|
|
353
|
+
BorderShape.SQUARE
|
|
354
|
+
BorderShape.SQUIRCLE
|
|
355
|
+
BorderShape.CIRCLE
|
|
356
|
+
|
|
357
|
+
// Border styles
|
|
358
|
+
BorderStyle.SOLID
|
|
359
|
+
BorderStyle.DASHED
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## Advanced Examples
|
|
363
|
+
|
|
364
|
+
### Custom Styled QR Code
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import { genQrImage, EyeFrameShape, DotShape, BorderShape } from 'qr-code-generator';
|
|
368
|
+
|
|
369
|
+
const styledQR = await genQrImage('https://tapple.io', {
|
|
370
|
+
size: 500,
|
|
371
|
+
margin: 30,
|
|
372
|
+
backgroundColor: '#f8f9fa',
|
|
373
|
+
eyes: {
|
|
374
|
+
shape: EyeFrameShape.SQUIRCLE,
|
|
375
|
+
color: '#0066ff'
|
|
376
|
+
},
|
|
377
|
+
pupils: {
|
|
378
|
+
color: '#ff6600'
|
|
379
|
+
},
|
|
380
|
+
dots: {
|
|
381
|
+
shape: DotShape.DOTS,
|
|
382
|
+
color: '#333333',
|
|
383
|
+
scale: 0.9
|
|
384
|
+
},
|
|
385
|
+
border: {
|
|
386
|
+
shape: BorderShape.SQUIRCLE,
|
|
387
|
+
width: 15,
|
|
388
|
+
color: '#0066ff',
|
|
389
|
+
style: 'solid'
|
|
390
|
+
},
|
|
391
|
+
output: { format: 'png', type: 'dataURL' }
|
|
392
|
+
});
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### QR Code with Logo
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
import { genQrImage } from 'qr-code-generator';
|
|
399
|
+
import fs from 'fs';
|
|
400
|
+
|
|
401
|
+
// Load logo as data URL
|
|
402
|
+
const logoBuffer = fs.readFileSync('logo.png');
|
|
403
|
+
const logoDataURL = `data:image/png;base64,${logoBuffer.toString('base64')}`;
|
|
404
|
+
|
|
405
|
+
const qr = await genQrImage('https://tapple.io', {
|
|
406
|
+
size: 400,
|
|
407
|
+
logo: {
|
|
408
|
+
src: logoDataURL,
|
|
409
|
+
scale: 0.25 // Logo takes up 25% of QR width
|
|
410
|
+
},
|
|
411
|
+
output: { format: 'png', type: 'dataURL' }
|
|
412
|
+
});
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
## Browser Usage
|
|
416
|
+
|
|
417
|
+
### Via Module Bundler (Recommended)
|
|
418
|
+
|
|
419
|
+
```typescript
|
|
420
|
+
import { genQrImage } from 'qr-code-generator';
|
|
421
|
+
|
|
422
|
+
const qr = await genQrImage('https://tapple.io', {
|
|
423
|
+
output: { format: 'png', type: 'dataURL' }
|
|
424
|
+
});
|
|
425
|
+
document.querySelector('#qr-image').src = qr;
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Via CDN (ESM)
|
|
429
|
+
|
|
430
|
+
```html
|
|
431
|
+
<script type="module">
|
|
432
|
+
import { genQrImage } from 'https://cdn.jsdelivr.net/npm/qr-code-generator/+esm';
|
|
433
|
+
|
|
434
|
+
const qr = await genQrImage('https://tapple.io', {
|
|
435
|
+
output: { format: 'png', type: 'dataURL' }
|
|
436
|
+
});
|
|
437
|
+
document.querySelector('#qr-image').src = qr;
|
|
438
|
+
</script>
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Technical Details
|
|
442
|
+
|
|
443
|
+
- **QR Versions**: Supports QR versions 1-10 (automatically selected based on input length)
|
|
444
|
+
- **Error Correction**: Levels L, M, Q, H (automatically optimized)
|
|
445
|
+
- **Encoding Modes**: Numeric, Alphanumeric, Byte (automatically detected)
|
|
446
|
+
- **Mask Patterns**: All 8 patterns with automatic penalty score optimization
|
|
447
|
+
- **Architecture**: SVG-first rendering with environment-specific raster conversion
|
|
448
|
+
- **Browser**: Uses native Canvas API for SVG→PNG conversion
|
|
449
|
+
- **Node.js**: Uses `@resvg/resvg-js` for high-quality SVG→PNG conversion
|
|
450
|
+
|
|
451
|
+
## TypeScript Support
|
|
452
|
+
|
|
453
|
+
Full TypeScript support with comprehensive type definitions:
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
import type { ImageOptions, QRInput, VCardData, OutputConfig } from 'qr-code-generator';
|
|
457
|
+
|
|
458
|
+
const options: ImageOptions = {
|
|
459
|
+
size: 400,
|
|
460
|
+
backgroundColor: '#ffffff',
|
|
461
|
+
output: { format: 'svg', type: 'string' }
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
const input: QRInput = {
|
|
465
|
+
type: 'vcard',
|
|
466
|
+
data: { name: 'John Doe' }
|
|
467
|
+
};
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
## Performance
|
|
471
|
+
|
|
472
|
+
- **Small bundle size** - Zero browser dependencies means minimal footprint
|
|
473
|
+
- **Tree-shakeable** - Only import what you need with full ESM support
|
|
474
|
+
- **Efficient architecture** - SVG-first rendering with environment-specific raster conversion
|
|
475
|
+
- **No DOM dependency** - Works in Node.js, browsers, and Web Workers
|
|
476
|
+
- **Fast execution** - Optimized algorithms for matrix generation and mask selection
|
|
477
|
+
|
|
478
|
+
## Contributing
|
|
479
|
+
|
|
480
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
481
|
+
|
|
482
|
+
1. Fork the repository
|
|
483
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
484
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
485
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
486
|
+
5. Open a Pull Request
|
|
487
|
+
|
|
488
|
+
## Development
|
|
489
|
+
|
|
490
|
+
### Available Scripts
|
|
491
|
+
|
|
492
|
+
```bash
|
|
493
|
+
# Building
|
|
494
|
+
npm run build # Full build (types + bundles)
|
|
495
|
+
npm run clean # Remove build artifacts
|
|
496
|
+
|
|
497
|
+
# Testing
|
|
498
|
+
npm test # Run all tests
|
|
499
|
+
npm run test:unit # Unit tests only
|
|
500
|
+
npm run test:integration # Integration tests only
|
|
501
|
+
npm run test:e2e # End-to-end scannability tests
|
|
502
|
+
npm run test:dist # Test built packages (requires build)
|
|
503
|
+
npm run test:fast # Skip slow e2e tests
|
|
504
|
+
npm run test:watch # Watch mode
|
|
505
|
+
npm run test:ui # Interactive test UI
|
|
506
|
+
|
|
507
|
+
# Demo
|
|
508
|
+
npm run demo # Build and serve interactive demo at localhost:8080
|
|
509
|
+
|
|
510
|
+
# Code Quality
|
|
511
|
+
npm run lint # Check code for issues
|
|
512
|
+
npm run lint:fix # Auto-fix linting issues
|
|
513
|
+
npm run format # Format code with Prettier
|
|
514
|
+
npm run format:check # Check formatting without changes
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Project Structure
|
|
518
|
+
|
|
519
|
+
```
|
|
520
|
+
src/
|
|
521
|
+
├── index.ts - Public API exports
|
|
522
|
+
├── qrcode.ts - Render function implementations
|
|
523
|
+
├── types.ts - Public type definitions
|
|
524
|
+
└── internal/ - Private implementation
|
|
525
|
+
├── core/ - Constants, defaults, validation
|
|
526
|
+
├── encoding/ - Data encoding & error correction
|
|
527
|
+
├── matrix/ - QR matrix generation & masking
|
|
528
|
+
└── rendering/ - Output format renderers
|
|
529
|
+
├── svg-renderer.ts - SVG generation
|
|
530
|
+
├── ascii-renderer.ts - ASCII text output
|
|
531
|
+
├── output-handler.ts - Output routing (SVG/PNG)
|
|
532
|
+
├── svg-to-raster-browser.ts - Browser PNG converter (Canvas API)
|
|
533
|
+
└── svg-to-raster-node.ts - Node.js PNG converter (resvg)
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
## Testing
|
|
537
|
+
|
|
538
|
+
The library includes comprehensive test coverage:
|
|
539
|
+
- **Unit tests**: Core encoding, error correction, matrix generation
|
|
540
|
+
- **Integration tests**: Full pipeline rendering across all formats
|
|
541
|
+
- **E2E tests**: QR code scannability validation with dual decoders (jsQR + @nuintun/qrcode)
|
|
542
|
+
- **Distribution tests**: Validates built packages work in Node.js and browser environments
|
|
543
|
+
|
|
544
|
+
## Interactive Demo
|
|
545
|
+
|
|
546
|
+
The demo showcases real-time QR code generation with all available options including colors, shapes, borders, logos, and more.
|
|
547
|
+
|
|
548
|
+
**Try it locally:**
|
|
549
|
+
|
|
550
|
+
```bash
|
|
551
|
+
# Clone the repository
|
|
552
|
+
git clone https://github.com/tappleinc/qr-code-generator.git
|
|
553
|
+
cd qr-code-generator
|
|
554
|
+
|
|
555
|
+
# Install dependencies and run demo
|
|
556
|
+
npm install
|
|
557
|
+
npm run demo
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
Then open [http://localhost:8080/demo/](http://localhost:8080/demo/) in your browser.
|
|
561
|
+
|
|
562
|
+
**Quick try without cloning:**
|
|
563
|
+
|
|
564
|
+
You can also experiment using online playgrounds like [CodeSandbox](https://codesandbox.io) or [StackBlitz](https://stackblitz.com) by creating a new project and installing `qr-code-generator`.
|
|
565
|
+
|
|
566
|
+
## License
|
|
567
|
+
|
|
568
|
+
MIT © [Tapple Inc.](https://github.com/tappleinc)
|
|
569
|
+
|
|
570
|
+
## Support
|
|
571
|
+
|
|
572
|
+
- 🐛 [Report Issues](https://github.com/tappleinc/qr-code-generator/issues)
|
|
573
|
+
- 📖 [View Documentation](https://github.com/tappleinc/qr-code-generator)
|
|
574
|
+
- 💬 Questions? Open an issue for discussion
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
Made with ❤️ by [Tapple Inc.](https://tappleinc.com)
|
package/dist/browser.mjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
var j={L:[7,10,15,20,26,18,20,24,30,18],M:[10,16,26,18,24,16,18,22,22,26],Q:[13,22,18,26,18,24,18,22,20,24],H:[17,28,22,16,22,28,26,26,24,28]},M={L:[19,34,55,80,108,136,156,194,232,274],M:[16,28,44,64,86,108,124,154,182,216],Q:[13,22,34,48,62,76,88,110,132,154],H:[9,16,26,36,46,60,66,86,100,122]},Y={L:[[1,19,0,0],[1,34,0,0],[1,55,0,0],[1,80,0,0],[1,108,0,0],[2,68,0,0],[2,78,0,0],[2,97,0,0],[2,116,0,0],[2,68,2,69]],M:[[1,16,0,0],[1,28,0,0],[1,44,0,0],[2,32,0,0],[2,43,0,0],[4,27,0,0],[4,31,0,0],[2,38,2,39],[3,36,2,37],[4,43,1,44]],Q:[[1,13,0,0],[1,22,0,0],[2,17,0,0],[2,24,0,0],[2,15,2,16],[4,19,0,0],[2,14,4,15],[4,18,2,19],[4,16,4,17],[6,19,2,20]],H:[[1,9,0,0],[1,16,0,0],[2,13,0,0],[4,9,0,0],[2,11,2,12],[4,15,0,0],[4,13,1,14],[4,14,2,15],[4,12,4,13],[6,15,2,16]]},S="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:",ve={1:[10,12,14],2:[9,11,13],4:[8,16,16]},B={L:1,M:0,Q:3,H:2},P=[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50]],X=[31892,34236,39577,42195],Z=[0,7,7,7,7,7,0,0,0,0];function R(e){return e*4+17}function L(e,r){let t=r<10?0:r<27?1:2;return ve[e][t]}var K=(t=>(t.SQUARE="square",t.SQUIRCLE="squircle",t))(K||{}),J=(o=>(o.CLASSIC="classic",o.DOTS="dots",o.SQUARE="square",o))(J||{}),ee=(n=>(n.NONE="none",n.SQUARE="square",n.SQUIRCLE="squircle",n.CIRCLE="circle",n))(ee||{}),te=(t=>(t.SOLID="solid",t.DASHED="dashed",t))(te||{});function y(e,r){let t=r/2;return e<=-t?0:e>=t?255:Math.round((e+t)/r*255)}function F(e,r,t=.01){return y(r-e,t)}function ke(e,r,t,o){let n=Math.abs(e)-t+o,s=Math.abs(r)-t+o,a=Math.sqrt(Math.max(n,0)**2+Math.max(s,0)**2),i=Math.min(Math.max(n,s),0);return a+i-o}function Te(e,r){let n=r*3,s=r*2,a=n+s,i=Math.max(1,Math.round(e/a)),c=e/i,u=c*(3/5),l=c*(2/5),d=l/2;return{dashArray:`${u} ${l}`,offset:d}}function V(e,r){let t=r*3,o=r*2,n=t+o,s=Math.round(e/n);s=Math.round(s/4)*4,s=Math.max(4,s);let a=e/s,i=a*.6,c=a*.4,u=i/2;return{dashArray:`${i} ${c}`,offset:u}}function N(e,r,t,o,n){return n==="circle"?De(e,r,t,o):n==="squircle"?Be(e,r,t,o):Fe(e,r,t,o)}function De(e,r,t,o){let s=(Math.atan2(r,e)+Math.PI)/(2*Math.PI),a=t/2-o/2,i=2*Math.PI*a,c=o*3,u=o*2,l=Math.floor(i/(c+u)),d=l%2===0?l:l-1,f=Math.max(4,d);return s*f%1<.6}function Be(e,r,t,o){let s=t/2-o/2,a=t*z,i=Math.max(0,a-o/2),c=s-i,u=2*c,l=.5*Math.PI*i,d=4*u+4*l,f=Ne(e,r,c,i,u,l,d),{dashArray:m}=V(d,o),[h,g]=m.split(" ").map(Number),b=h+g;return(f+h/2)%b<h}function Ne(e,r,t,o,n,s,a){if(r<-t)if(e>t){let i=Math.atan2(r- -t,e-t)+Math.PI/2;return t+i*o}else if(e<-t){let i=Math.atan2(r- -t,e- -t)+Math.PI;return t+3*s+3*n+i*o}else return e>=0?e:a+e;else if(r>t)if(e>t){let i=Math.atan2(r-t,e-t);return t+s+n+i*o}else if(e<-t){let i=Math.atan2(r-t,e- -t)-Math.PI/2;return t+2*s+2*n+i*o}else return t+2*s+n+(t-e);else return e>t?t+s+(r- -t):e<-t?t+3*s+2*n+(t-r):e>=0?e:a+e}function Fe(e,r,t,o){let n=t/2,s=Math.abs(e),i=Math.abs(r)>=s?n+e:n+r,c=t-o,u=3,l=2,d=o*(u+l),f=Math.max(1,Math.round(c/d)),m=c/f,h=m*(u/(u+l)),b=(m-h)/2;return(i+b)%m<h}var z=.12,Ve={EYE_FRAME:.90909},E={square:{renderSVG(e,r,t,o){return`<rect x="${e}" y="${r}" width="${t}" height="${t}" fill="${o}"/>`},renderPixel(e,r,t,o){let n=t/2,s=o?.pixelSize??.01,a=Math.min(n-Math.abs(e),n-Math.abs(r));return y(a,s)}},squircle:{renderSVG(e,r,t,o){let n=t/2,s=n*Ve.EYE_FRAME,a=e+n,i=r+n;return`<path d="${`M${a},${i-n}
|
|
2
|
+
C${a+s},${i-n} ${a+n},${i-s} ${a+n},${i}
|
|
3
|
+
S${a+s},${i+n} ${a},${i+n}
|
|
4
|
+
S${a-n},${i+s} ${a-n},${i}
|
|
5
|
+
S${a-s},${i-n} ${a},${i-n}Z`}" fill="${o}"/>`},renderPixel(e,r,t,o){let n=t/2,s=o?.pixelSize??.01,a=4,i=Math.abs(e),c=Math.abs(r),u=i/n,l=c/n;if(i<.001&&c<.001)return 255;let d=Math.pow(u,a)+Math.pow(l,a),f=a/n*Math.sqrt(Math.pow(u,2*a-2)+Math.pow(l,2*a-2)),m=(1-d)/f;return y(m,s)}}},I={classic:{renderSVG(){return""},renderPixel(e,r,t,o){let n=t/2,s=o?.pixelSize??.01;if(t>=.99&&o&&o.qrcode&&o.row!==void 0&&o.col!==void 0){let{qrcode:i,row:c,col:u}=o,l=o.qrSize||i.length,d=u>0&&i[c][u-1],f=u<l-1&&i[c][u+1],m=c>0&&i[c-1][u],h=c<l-1&&i[c+1][u],g=d?1/0:n+e,b=f?1/0:n-e,$=m?1/0:n+r,C=h?1/0:n-r,D=Math.min(Math.min(g,b),Math.min($,C));return y(D,s)}let a=Math.min(n-Math.abs(e),n-Math.abs(r));return y(a,s)}},dots:{renderSVG(e,r,t,o){let n=e+t/2,s=r+t/2,a=t*.35;return`<circle cx="${n}" cy="${s}" r="${a}" fill="${o}"/>`},renderPixel(e,r,t,o){let n=t*.35,s=o?.pixelSize??.01,a=Math.sqrt(e*e+r*r);return F(a,n,s)}},square:{renderSVG(e,r,t,o){let n=t*.7,s=(t-n)/2,a=e+s,i=r+s;return`<rect x="${a}" y="${i}" width="${n}" height="${n}" fill="${o}"/>`},renderPixel(e,r,t,o){let s=t*.7/2,a=o?.pixelSize??.01,i=Math.min(s-Math.abs(e),s-Math.abs(r));return y(i,a)}}},v={square:{getDiagonalFactor(){return Math.sqrt(2)},renderSVG(e,r,t,o,n){let s=n?.borderWidth??1;if((n?.borderStyle??"solid")==="dashed"){let f=s/2,m=t-s,{dashArray:h,offset:g}=Te(m,s);return`<rect x="${e+f}" y="${r+f}" width="${m}" height="${m}" fill="none" stroke="${o}" stroke-width="${s}" stroke-dasharray="${h}" stroke-dashoffset="${-g}"/>`}let i=`M${e},${r}h${t}v${t}h${-t}z`,c=e+s,u=r+s,l=t-s*2,d=`M${c},${u}h${l}v${l}h${-l}z`;return`<path d="${i} ${d}" fill="${o}" fill-rule="evenodd"/>`},renderPixel(e,r,t,o){let n=o?.borderWidth??1,s=o?.borderStyle??"solid",a=o?.pixelSize??.01,i=t/2,c=i-n,u=i-Math.abs(e),l=i-Math.abs(r),d=c-Math.abs(e),f=c-Math.abs(r),m=Math.min(u,l),h=Math.min(d,f);if(m>=0&&h<=0){if(s==="dashed"&&!N(e,r,t,n,"square"))return 0;let g=y(m,a),b=255-y(h,a);return Math.min(g,b)}return 0}},squircle:{getDiagonalFactor(){return Math.pow(2,.25)},renderSVG(e,r,t,o,n){let s=n?.borderWidth??1,a=n?.borderStyle??"solid",i=t/2,c=e+i,u=r+i,l=i-s/2,d=t*z,f=Math.max(0,d-s/2),m=l-f,h=`M${c},${u-l}
|
|
6
|
+
H${c+m}
|
|
7
|
+
A${f},${f} 0 0 1 ${c+l},${u-m}
|
|
8
|
+
V${u+m}
|
|
9
|
+
A${f},${f} 0 0 1 ${c+m},${u+l}
|
|
10
|
+
H${c-m}
|
|
11
|
+
A${f},${f} 0 0 1 ${c-l},${u+m}
|
|
12
|
+
V${u-m}
|
|
13
|
+
A${f},${f} 0 0 1 ${c-m},${u-l}
|
|
14
|
+
Z`;if(a==="dashed"){let g=2*m,b=.5*Math.PI*f,$=4*g+4*b,{dashArray:C,offset:D}=V($,s);return`<path d="${h}" fill="none" stroke="${o}" stroke-width="${s}" stroke-dasharray="${C}" stroke-dashoffset="${D}"/>`}return`<path d="${h}" fill="none" stroke="${o}" stroke-width="${s}"/>`},renderPixel(e,r,t,o){let n=o?.borderWidth??1,s=o?.borderStyle??"solid",a=o?.pixelSize??.01,c=t/2-n/2,u=t*z,l=Math.max(0,u-n/2),d=Math.abs(ke(e,r,c,l)),f=n/2-d;return f>-a?s==="dashed"&&!N(e,r,t,n,"squircle")?0:y(f,a):0}},circle:{getDiagonalFactor(){return 1},renderSVG(e,r,t,o,n){let s=n?.borderWidth??1,a=n?.borderStyle??"solid",i=e+t/2,c=r+t/2,u=t/2;if(a==="dashed"){let m=u-s/2,h=2*Math.PI*m,{dashArray:g,offset:b}=V(h,s);return`<circle cx="${i}" cy="${c}" r="${m}" fill="none" stroke="${o}" stroke-width="${s}" stroke-dasharray="${g}" stroke-dashoffset="${b}"/>`}let l=u-s,d=`M${i},${c-u}
|
|
15
|
+
A${u},${u} 0 1,1 ${i},${c+u}
|
|
16
|
+
A${u},${u} 0 1,1 ${i},${c-u}Z`,f=`M${i},${c-l}
|
|
17
|
+
A${l},${l} 0 1,0 ${i},${c+l}
|
|
18
|
+
A${l},${l} 0 1,0 ${i},${c-l}Z`;return`<path d="${d} ${f}" fill="${o}" fill-rule="evenodd"/>`},renderPixel(e,r,t,o){let n=o?.borderWidth??1,s=o?.borderStyle??"solid",a=o?.pixelSize??.01,i=t/2,c=i-n,u=Math.sqrt(e*e+r*r);if(u<=i&&u>=c){if(s==="dashed"&&!N(e,r,t,n,"circle"))return 0;let l=F(u,i,a),d=255-F(u,c,a);return Math.min(l,d)}return 0}}};var w=class extends Error{constructor(r){let t=r.map(o=>` - ${o.field}: ${o.message}`).join(`
|
|
19
|
+
`);super(`QR Code validation failed:
|
|
20
|
+
${t}`),this.name="QRValidationError",this.errors=r}};function x(e,r,t,o,n=!1){return typeof e!="number"||!isFinite(e)?{field:r,value:e,message:"must be a finite number"}:n&&!Number.isInteger(e)?{field:r,value:e,message:"must be an integer"}:e<t?{field:r,value:e,message:`must be at least ${t}`}:o!==null&&e>o?{field:r,value:e,message:`must be at most ${o}`}:null}function O(e,r){return typeof e!="string"?{field:r,value:e,message:"must be a string"}:/^#[0-9A-Fa-f]{6}$/.test(e)?null:{field:r,value:e,message:"must be a valid hex color (e.g., #000000)"}}function _(e,r,t){if(typeof e!="string")return{field:r,value:e,message:"must be a string"};if(!(e in t)){let o=Object.keys(t).join(", ");return{field:r,value:e,message:`must be one of: ${o}`}}return null}function re(e){let r=[];if(e.size!==void 0){let t=x(e.size,"size",21,null,!0);t&&r.push(t)}if(e.margin!==void 0){let t=x(e.margin,"margin",0,null,!0);t&&r.push(t)}if(e.backgroundColor!==void 0){let t=O(e.backgroundColor,"backgroundColor");t&&r.push(t)}if(e.eyes?.shape!==void 0){let t=_(e.eyes.shape,"eyes.shape",E);t&&r.push(t)}if(e.eyes?.color!==void 0){let t=O(e.eyes.color,"eyes.color");t&&r.push(t)}if(e.pupils?.color!==void 0){let t=O(e.pupils.color,"pupils.color");t&&r.push(t)}if(e.dots?.shape!==void 0){let t=_(e.dots.shape,"dots.shape",I);t&&r.push(t)}if(e.dots?.color!==void 0){let t=O(e.dots.color,"dots.color");t&&r.push(t)}if(e.dots?.scale!==void 0){let t=x(e.dots.scale,"dots.scale",.75,1.25,!1);t&&r.push(t)}if(e.border?.shape!==void 0&&e.border.shape!=="none"){let t=_(e.border.shape,"border.shape",v);t&&r.push(t)}if(e.border?.width!==void 0){let t=x(e.border.width,"border.width",0,null,!0);t&&r.push(t)}if(e.border?.color!==void 0){let t=O(e.border.color,"border.color");t&&r.push(t)}if(e.border?.style!==void 0&&(typeof e.border.style!="string"||e.border.style!=="solid"&&e.border.style!=="dashed")&&r.push({field:"border.style",value:e.border.style,message:'must be either "solid" or "dashed"'}),e.logo&&((!e.logo.src||typeof e.logo.src!="string")&&r.push({field:"logo.src",value:e.logo.src,message:"must be a non-empty string"}),e.logo.scale!==void 0)){let t=x(e.logo.scale,"logo.scale",.1,.3,!1);t&&r.push(t)}if(r.length>0)throw new w(r)}function ne(e){let r=[];if(e.margin!==void 0){let t=x(e.margin,"margin",0,null,!0);t&&r.push(t)}if(e.darkChar!==void 0&&typeof e.darkChar!="string"&&r.push({field:"darkChar",value:e.darkChar,message:"must be a string"}),e.lightChar!==void 0&&typeof e.lightChar!="string"&&r.push({field:"lightChar",value:e.lightChar,message:"must be a string"}),r.length>0)throw new w(r)}var p={size:300,margin:24,backgroundColor:"#ffffff",eyes:{shape:"square",color:"#000000"},pupils:{color:"#000000"},dots:{shape:"classic",color:"#000000",scale:1},logo:{scale:.2},border:{shape:"none",width:10,color:"#000000",style:"solid"},output:{format:"png",type:"buffer"}},k={margin:2,darkChar:"\u2588\u2588",lightChar:" "};function oe(e){if(!e){let{logo:t,...o}=p;return o}return re(e),{size:e.size??p.size,margin:e.margin??p.margin,backgroundColor:e.backgroundColor??p.backgroundColor,eyes:{shape:e.eyes?.shape??p.eyes.shape,color:e.eyes?.color??p.eyes.color},pupils:{color:e.pupils?.color??p.pupils.color},dots:{shape:e.dots?.shape??p.dots.shape,color:e.dots?.color??p.dots.color,scale:e.dots?.scale??p.dots.scale},logo:e.logo?{src:e.logo.src,scale:e.logo.scale??p.logo.scale}:void 0,border:{shape:e.border?.shape??p.border.shape,width:e.border?.width??p.border.width,color:e.border?.color??p.border.color,style:e.border?.style??p.border.style},output:e.output??p.output}}function se(e){return e?(ne(e),{margin:e.margin??k.margin,darkChar:e.darkChar??k.darkChar,lightChar:e.lightChar??k.lightChar}):{...k}}function ae(e){return/^\d+$/.test(e)?1:[...e].every(r=>S.includes(r))?2:4}function ze(e){let r=[];for(let t=0;t<e.length;t+=3){let o=e.substring(t,Math.min(t+3,e.length)),n=parseInt(o,10),s=o.length===3?10:o.length===2?7:4;for(let a=s-1;a>=0;a--)r.push(n>>a&1)}return r}function _e(e){let r=[];for(let t=0;t<e.length;t+=2)if(t+1<e.length){let o=S.indexOf(e[t])*45+S.indexOf(e[t+1]);for(let n=10;n>=0;n--)r.push(o>>n&1)}else{let o=S.indexOf(e[t]);for(let n=5;n>=0;n--)r.push(o>>n&1)}return r}function qe(e){let r=[],t=new TextEncoder().encode(e);for(let o of t)for(let n=7;n>=0;n--)r.push(o>>n&1);return r}function Qe(e,r,t,o){let n=[];for(let a=3;a>=0;a--)n.push(r>>a&1);let s=L(r,o);for(let a=s-1;a>=0;a--)n.push(t>>a&1);return[...n,...e]}function Ue(e){let r=[];for(let t=0;t<e.length;t+=8){let o=0;for(let n=0;n<8&&t+n<e.length;n++)o=o<<1|e[t+n];t+8>e.length&&(o<<=8-e.length%8),r.push(o)}return r}function Ge(e,r){let t=[...e],o=[236,17],n=0;for(;t.length<r;)t.push(o[n]),n=1-n;return t}function ie(e,r,t){let o=ae(e),n,s;o===1?(n=ze(e),s=e.length):o===2?(n=_e(e),s=e.length):(n=qe(e),s=new TextEncoder().encode(e).length);let a=Qe(n,o,s,r),i=Math.min(4,t*8-a.length);for(let u=0;u<i;u++)a.push(0);for(;a.length%8!==0;)a.push(0);let c=Ue(a);return Ge(c,t)}function T(e,r){let t=ae(e),o=t===4?new TextEncoder().encode(e).length:e.length;for(let c=1;c<=10;c++){let u=L(t,c),l=t===1?Math.ceil(o/3)*10-(o%3===1?6:o%3===2?3:0):t===2?Math.floor(o/2)*11+o%2*6:o*8,d=4+u+l;if(Math.ceil(d/8)<=r[c-1])return c}let n=L(t,10),s=t===1?Math.ceil(o/3)*10-(o%3===1?6:o%3===2?3:0):t===2?Math.floor(o/2)*11+o%2*6:o*8,a=4+n+s,i=Math.ceil(a/8);throw new Error(`Input too long for QR code version 10. Required capacity: ${i} bytes, Maximum available: ${r[9]} bytes. Current data length: ${e.length} characters (${o} bytes encoded).`)}function ce(e,r){if(r)try{if(T(e,M.H)<=10)return"H"}catch{throw new Error(`Data too large for QR code with logo. Data length: ${e.length} characters. Maximum capacity with logo (EC level H): ~122 bytes (version 10). Logos require high error correction (H) which reduces data capacity. Consider: reducing data length, removing logo, or using multiple QR codes.`)}let t=["H","Q","M","L"];for(let o of t)try{if(T(e,M[o])<=10)return o}catch{continue}throw new Error(`Data too large for QR code version 10 at any error correction level. Data length: ${e.length} characters. Maximum capacity: ~274 bytes (version 10, EC level L). Please reduce input length or split into multiple QR codes.`)}var A=new Array(256),q=new Array(256);function We(){let e=1;for(let r=0;r<255;r++)A[r]=e,q[e]=r,e<<=1,e&256&&(e^=285);for(let r=255;r<512;r++)A[r]=A[r-255]}We();function le(e,r){return e===0||r===0?0:A[q[e]+q[r]]}function He(e){let r=[1];for(let t=0;t<e;t++){let o=r.length+1,n=new Array(o).fill(0);for(let s=0;s<r.length;s++)n[s]^=r[s],n[s+1]^=le(r[s],A[t]);r=n}return r}function ue(e,r){let t=He(r),o=[...e,...new Array(r).fill(0)];for(let n=0;n<e.length;n++){let s=o[n];if(s!==0)for(let a=0;a<t.length;a++)o[n+a]^=le(t[a],s)}return o.slice(e.length)}function fe(e,r,t){let o=[],n=[],[s,a,i,c]=t,u=0;for(let l=0;l<s;l++){let d=e.slice(u,u+a);o.push(d);let f=ue(d,r);n.push(f),u+=a}for(let l=0;l<i;l++){let d=e.slice(u,u+c);o.push(d);let f=ue(d,r);n.push(f),u+=c}return{dataBlocks:o,ecBlocks:n}}function de(e,r){let t=[],o=Math.max(...e.map(s=>s.length));for(let s=0;s<o;s++)for(let a of e)s<a.length&&t.push(a[s]);let n=Math.max(...r.map(s=>s.length));for(let s=0;s<n;s++)for(let a of r)s<a.length&&t.push(a[s]);return t}function me(e){let r=R(e);return Array.from({length:r},()=>Array(r).fill(!1))}function he(e){let r=R(e),t=Array.from({length:r},()=>Array(r).fill(!1));for(let n=0;n<=7;n++)for(let s=0;s<=7;s++)t[n][s]=!0;for(let n=0;n<=7;n++)for(let s=0;s<=7;s++)t[n][r-8+s]=!0;for(let n=0;n<=7;n++)for(let s=0;s<=7;s++)t[r-8+n][s]=!0;for(let n=8;n<r-8;n++)t[6][n]=!0,t[n][6]=!0;t[4*e+9][8]=!0;for(let n=0;n<6;n++)t[n][8]=!0;t[7][8]=!0,t[8][8]=!0;for(let n=r-8;n<r;n++)t[n][8]=!0;for(let n=0;n<9;n++)t[8][n]=!0;for(let n=r-8;n<r;n++)t[8][n]=!0;let o=P[e-1]||[];for(let n of o)for(let s of o)if(!(n<9&&s<9||n<9&&s>r-9||n>r-9&&s<9))for(let i=-2;i<=2;i++)for(let c=-2;c<=2;c++)t[n+i][s+c]=!0;if(e>=7){for(let n=0;n<6;n++)for(let s=r-11;s<r-8;s++)t[n][s]=!0;for(let n=r-11;n<r-8;n++)for(let s=0;s<6;s++)t[n][s]=!0}return t}function Q(e,r,t){for(let o=-1;o<=7;o++)for(let n=-1;n<=7;n++){let s=r+o,a=t+n;if(s<0||s>=e.length||a<0||a>=e.length)continue;let i=o>=0&&o<=6&&n>=0&&n<=6&&(o===0||o===6||n===0||n===6),c=o>=2&&o<=4&&n>=2&&n<=4;e[s][a]=i||c}}function je(e,r,t){for(let o=-2;o<=2;o++)for(let n=-2;n<=2;n++){let s=o===-2||o===2||n===-2||n===2,a=o===0&&n===0;e[r+o][t+n]=s||a}}function ge(e){let r=e.length;for(let t=8;t<r-8;t++)e[6][t]=t%2===0,e[t][6]=t%2===0}function be(e){Q(e,0,0),Q(e,0,e.length-7),Q(e,e.length-7,0)}function pe(e,r){let t=e.length,o=P[r-1]||[];for(let n of o)for(let s of o)n<9&&s<9||n<9&&s>t-9||n>t-9&&s<9||je(e,n,s)}function $e(e,r){e[4*r+9][8]=!0}function Ce(e,r,t){let o=e.length,n=0,s=-1,a=o-1;for(let i=o-1;i>0;i-=2)for(i===6&&i--;;){for(let c=0;c<2;c++)if(!r[a][i-c]){let u=n<t.length?t[n]:!1;e[a][i-c]=u,n++}if(a+=s,a<0||o<=a){a-=s,s=-s;break}}}function U(e,r,t){let o=e.length;for(let n=0;n<o;n++)for(let s=0;s<o;s++){if(r[n][s])continue;let a=!1;switch(t){case 0:a=(n+s)%2===0;break;case 1:a=n%2===0;break;case 2:a=s%3===0;break;case 3:a=(n+s)%3===0;break;case 4:a=(Math.floor(n/2)+Math.floor(s/3))%2===0;break;case 5:a=n*s%2+n*s%3===0;break;case 6:a=(n*s%2+n*s%3)%2===0;break;case 7:a=((n+s)%2+n*s%3)%2===0;break}a&&(e[n][s]=!e[n][s])}}function Ye(e){let r=e.length,t=0;for(let a=0;a<r;a++){let i=e[a][0],c=e[0][a],u=1,l=1;for(let d=1;d<r;d++)e[a][d]===i?u++:(u>=5&&(t+=3+(u-5)),i=e[a][d],u=1),e[d][a]===c?l++:(l>=5&&(t+=3+(l-5)),c=e[d][a],l=1);u>=5&&(t+=3+(u-5)),l>=5&&(t+=3+(l-5))}for(let a=0;a<r-1;a++)for(let i=0;i<r-1;i++){let c=e[a][i];e[a][i+1]===c&&e[a+1][i]===c&&e[a+1][i+1]===c&&(t+=3)}for(let a=0;a<r;a++){let i=0,c=0;for(let u=0;u<r;u++)i=i<<1&2047|(e[a][u]?1:0),u>=10&&(i===1488||i===93)&&(t+=40),c=c<<1&2047|(e[u][a]?1:0),u>=10&&(c===1488||c===93)&&(t+=40)}let o=0,n=r*r;for(let a=0;a<r;a++)for(let i=0;i<r;i++)e[a][i]&&o++;let s=Math.abs(Math.ceil(o*100/n/5)-10);return t+=s*10,t}function ye(e,r,t,o){let n=0,s=1/0;for(let a=0;a<8;a++){let i=e.map(u=>[...u]);U(i,r,a),o(i,t,a);let c=Ye(i);c<s&&(s=c,n=a)}return n}function G(e,r,t){let o=e.length,n=B[r]<<3|t,s=n<<10;for(let i=0;i<5;i++)s&1<<14-i&&(s^=1335<<4-i);let a=(n<<10|s)^21522;for(let i=0;i<15;i++){let c=(a>>14-i&1)===1;i<=5?e[8][i]=c:i===6?e[8][7]=c:i===7?e[8][8]=c:i===8?e[7][8]=c:e[5-(i-9)][8]=c,i<=6?e[o-1-i][8]=c:e[8][o-8+(i-7)]=c}}function Me(e,r){if(r<7)return;let t=e.length,o=X[r-7];for(let n=0;n<18;n++){let s=(o>>n&1)===1,a=Math.floor(n/3),i=t-11+n%3;e[a][i]=s;let c=t-11+n%3,u=Math.floor(n/3);e[c][u]=s}}function xe(e,r){return B[e]<<3|r}function Se(e,r,t,o,n){let s=me(e),a=he(e);be(s),ge(s),pe(s,e),$e(s,e),Ce(s,a,t);let i=n?s.map(u=>[...u]):void 0,c=o??ye(s,a,r,G);return U(s,a,c),G(s,r,c),Me(s,e),{matrix:s,mask:c,formatInfo:n?xe(r,c):void 0,unmaskedMatrix:i}}function W(e,r,t){return e<7&&r<7||e<7&&r>=t-7||e>=t-7&&r<7}function Re(e){return[{x:0,y:0},{x:e-7,y:0},{x:0,y:e-7}]}function Ee(e,r){let o=Math.max(.1,Math.min(.3,r));return e*o}function Xe(e,r,t,o,n,s,a){let i=E[t]||E.square,c=i.renderSVG(e,r,7*a,o),u=i.renderSVG(e+a,r+a,5*a,s),l=i.renderSVG(e+2*a,r+2*a,3*a,n);return c+u+l}function Ze(e,r,t,o){let n=o/2;if(e.includes("data:image/svg")||e.trim().startsWith("<svg")){let s=e;if(e.includes("data:image/svg")){let u=e.match(/data:image\/svg\+xml[^,]*,(.+)/);if(u)try{s=decodeURIComponent(u[1])}catch{return""}}let a=s.match(/viewBox=["']([^"']+)["']/),i=a?a[1]:"0 0 100 100",c=s.replace(/<\?xml[^>]*>|<svg[^>]*>|<\/svg>/gi,"");return`<g transform="translate(${r-n}, ${t-n})">
|
|
21
|
+
<svg width="${o}" height="${o}" viewBox="${i}">
|
|
22
|
+
${c}
|
|
23
|
+
</svg>
|
|
24
|
+
</g>`}else return`<image x="${r-n}" y="${t-n}" width="${o}" height="${o}" href="${e}" preserveAspectRatio="xMidYMid meet"/>`}function Ke(e,r,t,o,n){let s=e.matrixSize,a="",i=I[t]||I.classic;if(t==="classic"){a=`<path fill="${o}" d="`;for(let c=0;c<s;c++)for(let u=0;u<s;u++)if(e.modules[c][u]&&!W(c,u,s)){let l=u*r,d=c*r,f=n*r,m=(1-n)*r/2,h=l+m,g=d+m;a+=`M${h},${g}h${f}v${f}h${-f}z`}return a+='"/>',a}for(let c=0;c<s;c++)for(let u=0;u<s;u++)if(e.modules[c][u]&&!W(c,u,s)){let l=u*r,d=c*r,f=n*r,m=(1-n)*r/2,h=l+m,g=d+m,b={qrcode:e.modules,qrSize:s,row:c,col:u};a+=i.renderSVG(h,g,f,o,b)}return a}function Ie(e,r){let{size:t,margin:o,backgroundColor:n,eyes:s,pupils:a,dots:i}=r,c=t/e.matrixSize,u=r.border.shape==="none"?0:r.border.width,l=t+2*o+2*u,d=o+u,f=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${l} ${l}" width="${l}" height="${l}">`;if(f+=`<rect width="${l}" height="${l}" fill="${n}"/>`,r.border.shape!=="none"&&u>0){let $=v[r.border.shape];if($){let C={borderWidth:u,borderStyle:r.border.style};f+=$.renderSVG(0,0,l,r.border.color,C)}}r.border.shape!=="none"&&u>0&&(f+=`<rect x="${d}" y="${d}" width="${t}" height="${t}" fill="${n}"/>`),f+=`<g transform="translate(${d}, ${d})">`;let m=Re(e.matrixSize),h="";for(let $ of m)h+=Xe($.x*c,$.y*c,s.shape,s.color,a.color,n,c);let g=Ke(e,c,i.shape,i.color,i.scale);f+=h+g+"</g>";let b="";if(r.logo){let $=Ee(e.matrixSize,r.logo.scale)*c,C=l/2;b=Ze(r.logo.src,C,C,$)}return f+=b+"</svg>",f}function Oe(e,r){let{margin:t,lightChar:o,darkChar:n}=r,s="",a=e.matrixSize+t*2;for(let i=0;i<t;i++)s+=o.repeat(a)+`
|
|
25
|
+
`;for(let i=0;i<e.matrixSize;i++){s+=o.repeat(t);for(let c=0;c<e.matrixSize;c++)s+=e.modules[i][c]?n:o;s+=o.repeat(t)+`
|
|
26
|
+
`}for(let i=0;i<t;i++)s+=o.repeat(a)+`
|
|
27
|
+
`;return s}async function we(e,r){let{output:t,size:o,margin:n,border:s}=r,a=s.shape==="none"?0:s.width,i=o+2*n+2*a;return new Promise((c,u)=>{let l=document.createElement("canvas");l.width=i,l.height=i;let d=l.getContext("2d");if(!d){u(new Error("Failed to get canvas context"));return}let f=new Image,m=null;try{let h=new Blob([e],{type:"image/svg+xml;charset=utf-8"});m=URL.createObjectURL(h)}catch{u(new Error("Failed to create SVG blob for rasterization"));return}f.onload=()=>{if(m&&URL.revokeObjectURL(m),d.drawImage(f,0,0,i,i),t.type==="dataURL"){let h=l.toDataURL("image/png");c(h)}else l.toBlob(h=>{if(!h){u(new Error("Failed to convert PNG to blob"));return}h.arrayBuffer().then(g=>{c(new Uint8Array(g))})},"image/png")},f.onerror=()=>{m&&URL.revokeObjectURL(m),u(new Error("Failed to load SVG for rasterization"))},f.src=m})}async function Ae(e,r){let{format:t,type:o}=r.output;return t==="svg"?o==="string"?e:`data:image/svg+xml;charset=utf-8,${encodeURIComponent(e)}`:await we(e,r)}function H(e){if(typeof e=="string")return e;switch(e.type){case"url":return Je(e.url);case"vcard":return et(e.data);case"wifi":return tt(e.data);case"calendar":return rt(e.data);case"email":return nt(e.email,e.subject,e.body);case"sms":return ot(e.phone,e.message);case"phone":return st(e.phone)}}function Je(e){return!e.startsWith("http://")&&!e.startsWith("https://")?`https://${e}`:e}function et(e){let r=["BEGIN:VCARD","VERSION:3.0",`FN:${e.name}`];if(e.phone&&r.push(`TEL:${e.phone}`),e.email&&r.push(`EMAIL:${e.email}`),e.organization&&r.push(`ORG:${e.organization}`),e.url&&r.push(`URL:${e.url}`),e.title&&r.push(`TITLE:${e.title}`),e.note&&r.push(`NOTE:${e.note}`),e.address){let{street:t,city:o,state:n,zip:s,country:a}=e.address,i=["","",t||"",o||"",n||"",s||"",a||""];r.push(`ADR:${i.join(";")}`)}return r.push("END:VCARD"),r.join(`
|
|
28
|
+
`)}function tt(e){let r=e.encryption||"WPA",t=e.hidden?"H:true;":"",o=Pe(e.ssid),n=Pe(e.password);return`WIFI:T:${r};S:${o};P:${n};${t};`}function Pe(e){return e.replace(/([\\;,":])/g,"\\$1")}function rt(e){let r=o=>(typeof o=="string"?new Date(o):o).toISOString().replace(/[-:]/g,"").split(".")[0]+"Z",t=["BEGIN:VCALENDAR","VERSION:2.0","BEGIN:VEVENT",`SUMMARY:${e.title}`,`DTSTART:${r(e.startDate)}`,`DTEND:${r(e.endDate)}`];return e.location&&t.push(`LOCATION:${e.location}`),e.description&&t.push(`DESCRIPTION:${e.description}`),t.push("END:VEVENT","END:VCALENDAR"),t.join(`
|
|
29
|
+
`)}function nt(e,r,t){let o=`mailto:${e}`,n=[];return r&&n.push(`subject=${encodeURIComponent(r)}`),t&&n.push(`body=${encodeURIComponent(t)}`),n.length>0&&(o+=`?${n.join("&")}`),o}function ot(e,r){return r?`sms:${e}:${r}`:`sms:${e}`}function st(e){return`tel:${e}`}function at(e,r){let t=[];for(let n of e)for(let s=7;s>=0;s--)t.push((n>>s&1)===1);let o=Z[r-1];for(let n=0;n<o;n++)t.push(!1);return t}function Le(e,r){if(!e)throw new Error("QR Code input cannot be empty. Please provide text or structured content to encode.");let t=ce(e,r),o=M[t],n=T(e,o);if(n<1||n>10)throw new Error(`Input data is too large for QR code version 10. Data length: ${e.length} characters. Maximum capacity at EC level ${t}: ~${M[t][9]} bytes. Try reducing input length or removing logo for higher capacity.`);let s=ie(e,n,o[n-1]),a=j[t][n-1],i=Y[t][n-1],{dataBlocks:c,ecBlocks:u}=fe(s,a,i),l=de(c,u),d=at(l,n),{matrix:f,mask:m}=Se(n,t,d);return{version:n,matrixSize:R(n),modules:f,mask:m,errorCorrectionLevel:t}}async function it(e,r){let t=H(e),o=oe(r),n=Le(t,!!o.logo),s=Ie(n,o);return await Ae(s,o)}function ct(e,r){let t=H(e),o=se(r),n=Le(t,!1);return Oe(n,o)}export{ee as BorderShape,te as BorderStyle,J as DotShape,K as EyeFrameShape,w as QRValidationError,it as genQrImage,ct as genQrText};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v9.5.1
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Public API Type Definitions
|
|
5
|
+
*
|
|
6
|
+
* This file contains all types, interfaces, and enums that are part of the public API.
|
|
7
|
+
* Internal types used only within the library are in internal/core/types.ts
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Eye frame (outer 7x7 position marker) shape options
|
|
11
|
+
*/
|
|
12
|
+
export declare enum EyeFrameShape {
|
|
13
|
+
SQUARE = "square",
|
|
14
|
+
SQUIRCLE = "squircle"
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Data dot (module) shape options
|
|
18
|
+
*/
|
|
19
|
+
export declare enum DotShape {
|
|
20
|
+
CLASSIC = "classic",
|
|
21
|
+
DOTS = "dots",
|
|
22
|
+
SQUARE = "square"
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Border shape options
|
|
26
|
+
*/
|
|
27
|
+
export declare enum BorderShape {
|
|
28
|
+
NONE = "none",
|
|
29
|
+
SQUARE = "square",
|
|
30
|
+
SQUIRCLE = "squircle",
|
|
31
|
+
CIRCLE = "circle"
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Border style options
|
|
35
|
+
*/
|
|
36
|
+
export declare enum BorderStyle {
|
|
37
|
+
SOLID = "solid",
|
|
38
|
+
DASHED = "dashed"
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* vCard contact information
|
|
42
|
+
*/
|
|
43
|
+
export interface VCardData {
|
|
44
|
+
/** Full name (required) */
|
|
45
|
+
name: string;
|
|
46
|
+
/** Phone number */
|
|
47
|
+
phone?: string;
|
|
48
|
+
/** Email address */
|
|
49
|
+
email?: string;
|
|
50
|
+
/** Organization/company name */
|
|
51
|
+
organization?: string;
|
|
52
|
+
/** Website URL */
|
|
53
|
+
url?: string;
|
|
54
|
+
/** Postal address */
|
|
55
|
+
address?: {
|
|
56
|
+
street?: string;
|
|
57
|
+
city?: string;
|
|
58
|
+
state?: string;
|
|
59
|
+
zip?: string;
|
|
60
|
+
country?: string;
|
|
61
|
+
};
|
|
62
|
+
/** Job title */
|
|
63
|
+
title?: string;
|
|
64
|
+
/** Notes/additional info */
|
|
65
|
+
note?: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* WiFi network credentials
|
|
69
|
+
*/
|
|
70
|
+
export interface WiFiData {
|
|
71
|
+
/** Network SSID (name) */
|
|
72
|
+
ssid: string;
|
|
73
|
+
/** Network password */
|
|
74
|
+
password: string;
|
|
75
|
+
/** Encryption type (default: 'WPA') */
|
|
76
|
+
encryption?: "WPA" | "WPA2" | "WEP" | "nopass";
|
|
77
|
+
/** Whether network is hidden (default: false) */
|
|
78
|
+
hidden?: boolean;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Calendar event data
|
|
82
|
+
*/
|
|
83
|
+
export interface CalendarData {
|
|
84
|
+
/** Event title (required) */
|
|
85
|
+
title: string;
|
|
86
|
+
/** Event start date/time */
|
|
87
|
+
startDate: Date | string;
|
|
88
|
+
/** Event end date/time */
|
|
89
|
+
endDate: Date | string;
|
|
90
|
+
/** Event location */
|
|
91
|
+
location?: string;
|
|
92
|
+
/** Event description */
|
|
93
|
+
description?: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* QR Code input - accepts either raw string or structured content types
|
|
97
|
+
*/
|
|
98
|
+
export type QRInput = string | {
|
|
99
|
+
type: "url";
|
|
100
|
+
url: string;
|
|
101
|
+
} | {
|
|
102
|
+
type: "vcard";
|
|
103
|
+
data: VCardData;
|
|
104
|
+
} | {
|
|
105
|
+
type: "wifi";
|
|
106
|
+
data: WiFiData;
|
|
107
|
+
} | {
|
|
108
|
+
type: "calendar";
|
|
109
|
+
data: CalendarData;
|
|
110
|
+
} | {
|
|
111
|
+
type: "email";
|
|
112
|
+
email: string;
|
|
113
|
+
subject?: string;
|
|
114
|
+
body?: string;
|
|
115
|
+
} | {
|
|
116
|
+
type: "sms";
|
|
117
|
+
phone: string;
|
|
118
|
+
message?: string;
|
|
119
|
+
} | {
|
|
120
|
+
type: "phone";
|
|
121
|
+
phone: string;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Output format and type configuration
|
|
125
|
+
* Uses union type to prevent invalid combinations
|
|
126
|
+
*/
|
|
127
|
+
export type OutputConfig = {
|
|
128
|
+
format: "png";
|
|
129
|
+
type: "dataURL" | "buffer";
|
|
130
|
+
} | {
|
|
131
|
+
format: "svg";
|
|
132
|
+
type: "dataURL" | "string";
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Image-based rendering options for PNG and SVG (public API)
|
|
136
|
+
* All fields are optional - unspecified values use defaults from internal/core/defaults.ts
|
|
137
|
+
*/
|
|
138
|
+
export interface ImageOptions {
|
|
139
|
+
/** QR code matrix size in pixels (default: 300) - margin and border are added to this */
|
|
140
|
+
size?: number;
|
|
141
|
+
/** Margin around QR code in pixels (default: 24) */
|
|
142
|
+
margin?: number;
|
|
143
|
+
/** Background color in hex format (default: '#ffffff') */
|
|
144
|
+
backgroundColor?: string;
|
|
145
|
+
/** Eye (outer frame) styling */
|
|
146
|
+
eyes?: {
|
|
147
|
+
/** Eye frame shape (default: 'square') */
|
|
148
|
+
shape?: EyeFrameShape;
|
|
149
|
+
/** Eye frame color in hex format (default: '#000000') */
|
|
150
|
+
color?: string;
|
|
151
|
+
};
|
|
152
|
+
/** Pupil (inner core) styling */
|
|
153
|
+
pupils?: {
|
|
154
|
+
/** Pupil color in hex format (default: '#000000') */
|
|
155
|
+
color?: string;
|
|
156
|
+
};
|
|
157
|
+
/** Data dot (module) styling */
|
|
158
|
+
dots?: {
|
|
159
|
+
/** Data dot shape (default: 'classic') */
|
|
160
|
+
shape?: DotShape;
|
|
161
|
+
/** Data dot color in hex format (default: '#000000') */
|
|
162
|
+
color?: string;
|
|
163
|
+
/** Data dot scale (0.75 to 1.25, default: 1.0) - adjusts visual size of dots while keeping overall dimensions fixed */
|
|
164
|
+
scale?: number;
|
|
165
|
+
};
|
|
166
|
+
/** Logo image to place in center of QR code (jpg, png, svg, or webp) */
|
|
167
|
+
logo?: {
|
|
168
|
+
/** Image source - data URL (recommended) or raw SVG string */
|
|
169
|
+
src: string;
|
|
170
|
+
/** Logo scale as percentage of QR code width (0-1, default: 0.2 = 20%, max: 0.3 = 30%) */
|
|
171
|
+
scale?: number;
|
|
172
|
+
};
|
|
173
|
+
/** Border styling (surrounds margin area) */
|
|
174
|
+
border?: {
|
|
175
|
+
/** Border shape (default: 'none') */
|
|
176
|
+
shape?: BorderShape;
|
|
177
|
+
/**
|
|
178
|
+
* Border width in pixels (default: 10)
|
|
179
|
+
* Total output size = size + 2×margin + 2×width
|
|
180
|
+
*/
|
|
181
|
+
width?: number;
|
|
182
|
+
/** Border color in hex format (default: '#000000') */
|
|
183
|
+
color?: string;
|
|
184
|
+
/** Border style - solid or dashed pattern (default: 'solid') */
|
|
185
|
+
style?: BorderStyle;
|
|
186
|
+
};
|
|
187
|
+
/** Output format and type (default: { format: 'png', type: 'buffer' }) */
|
|
188
|
+
output?: OutputConfig;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Text-based rendering options for ASCII (public API)
|
|
192
|
+
* All fields are optional - unspecified values use defaults from internal/core/defaults.ts
|
|
193
|
+
*/
|
|
194
|
+
export interface TextOptions {
|
|
195
|
+
/** Margin in modules (default: 2) */
|
|
196
|
+
margin?: number;
|
|
197
|
+
/** Dark character(s) for modules (default: '██') */
|
|
198
|
+
darkChar?: string;
|
|
199
|
+
/** Light/background character(s) (default: ' ') */
|
|
200
|
+
lightChar?: string;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Generate QR code image with configurable output format
|
|
204
|
+
* @param input - Content to encode (string or structured content type)
|
|
205
|
+
* @param options - Styling and output options
|
|
206
|
+
* @returns Promise resolving to Buffer, Uint8Array, or string based on output config
|
|
207
|
+
*/
|
|
208
|
+
export declare function genQrImage(input: QRInput, options?: ImageOptions): Promise<string | Buffer | Uint8Array>;
|
|
209
|
+
/**
|
|
210
|
+
* Generate ASCII QR code
|
|
211
|
+
* @param input - Content to encode (string or structured content type)
|
|
212
|
+
* @param options - Text styling options
|
|
213
|
+
* @returns ASCII string representation
|
|
214
|
+
*/
|
|
215
|
+
export declare function genQrText(input: QRInput, options?: TextOptions): string;
|
|
216
|
+
export interface ValidationError {
|
|
217
|
+
field: string;
|
|
218
|
+
value: unknown;
|
|
219
|
+
message: string;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Custom error for validation failures
|
|
223
|
+
* Contains array of all validation errors found
|
|
224
|
+
*/
|
|
225
|
+
export declare class QRValidationError extends Error {
|
|
226
|
+
errors: ValidationError[];
|
|
227
|
+
constructor(errors: ValidationError[]);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export {};
|
package/dist/node.cjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";var Ve=Object.create;var P=Object.defineProperty;var ze=Object.getOwnPropertyDescriptor;var Fe=Object.getOwnPropertyNames;var qe=Object.getPrototypeOf,_e=Object.prototype.hasOwnProperty;var Qe=(e,r)=>{for(var t in r)P(e,t,{get:r[t],enumerable:!0})},ee=(e,r,t,o)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of Fe(r))!_e.call(e,n)&&n!==t&&P(e,n,{get:()=>r[n],enumerable:!(o=ze(r,n))||o.enumerable});return e};var Ge=(e,r,t)=>(t=e!=null?Ve(qe(e)):{},ee(r||!e||!e.__esModule?P(t,"default",{value:e,enumerable:!0}):t,e)),Ue=e=>ee(P({},"__esModule",{value:!0}),e);var xt={};Qe(xt,{BorderShape:()=>q,BorderStyle:()=>_,DotShape:()=>F,EyeFrameShape:()=>z,QRValidationError:()=>S,genQrImage:()=>Be,genQrText:()=>Ne});module.exports=Ue(xt);var te={L:[7,10,15,20,26,18,20,24,30,18],M:[10,16,26,18,24,16,18,22,22,26],Q:[13,22,18,26,18,24,18,22,20,24],H:[17,28,22,16,22,28,26,26,24,28]},y={L:[19,34,55,80,108,136,156,194,232,274],M:[16,28,44,64,86,108,124,154,182,216],Q:[13,22,34,48,62,76,88,110,132,154],H:[9,16,26,36,46,60,66,86,100,122]},re={L:[[1,19,0,0],[1,34,0,0],[1,55,0,0],[1,80,0,0],[1,108,0,0],[2,68,0,0],[2,78,0,0],[2,97,0,0],[2,116,0,0],[2,68,2,69]],M:[[1,16,0,0],[1,28,0,0],[1,44,0,0],[2,32,0,0],[2,43,0,0],[4,27,0,0],[4,31,0,0],[2,38,2,39],[3,36,2,37],[4,43,1,44]],Q:[[1,13,0,0],[1,22,0,0],[2,17,0,0],[2,24,0,0],[2,15,2,16],[4,19,0,0],[2,14,4,15],[4,18,2,19],[4,16,4,17],[6,19,2,20]],H:[[1,9,0,0],[1,16,0,0],[2,13,0,0],[4,9,0,0],[2,11,2,12],[4,15,0,0],[4,13,1,14],[4,14,2,15],[4,12,4,13],[6,15,2,16]]},R="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:",We={1:[10,12,14],2:[9,11,13],4:[8,16,16]},V={L:1,M:0,Q:3,H:2},A=[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50]],ne=[31892,34236,39577,42195],oe=[0,7,7,7,7,7,0,0,0,0];function I(e){return e*4+17}function L(e,r){let t=r<10?0:r<27?1:2;return We[e][t]}var z=(t=>(t.SQUARE="square",t.SQUIRCLE="squircle",t))(z||{}),F=(o=>(o.CLASSIC="classic",o.DOTS="dots",o.SQUARE="square",o))(F||{}),q=(n=>(n.NONE="none",n.SQUARE="square",n.SQUIRCLE="squircle",n.CIRCLE="circle",n))(q||{}),_=(t=>(t.SOLID="solid",t.DASHED="dashed",t))(_||{});function M(e,r){let t=r/2;return e<=-t?0:e>=t?255:Math.round((e+t)/r*255)}function G(e,r,t=.01){return M(r-e,t)}function je(e,r,t,o){let n=Math.abs(e)-t+o,s=Math.abs(r)-t+o,a=Math.sqrt(Math.max(n,0)**2+Math.max(s,0)**2),i=Math.min(Math.max(n,s),0);return a+i-o}function He(e,r){let n=r*3,s=r*2,a=n+s,i=Math.max(1,Math.round(e/a)),c=e/i,u=c*(3/5),l=c*(2/5),d=l/2;return{dashArray:`${u} ${l}`,offset:d}}function U(e,r){let t=r*3,o=r*2,n=t+o,s=Math.round(e/n);s=Math.round(s/4)*4,s=Math.max(4,s);let a=e/s,i=a*.6,c=a*.4,u=i/2;return{dashArray:`${i} ${c}`,offset:u}}function Q(e,r,t,o,n){return n==="circle"?Ye(e,r,t,o):n==="squircle"?Xe(e,r,t,o):Ke(e,r,t,o)}function Ye(e,r,t,o){let s=(Math.atan2(r,e)+Math.PI)/(2*Math.PI),a=t/2-o/2,i=2*Math.PI*a,c=o*3,u=o*2,l=Math.floor(i/(c+u)),d=l%2===0?l:l-1,f=Math.max(4,d);return s*f%1<.6}function Xe(e,r,t,o){let s=t/2-o/2,a=t*W,i=Math.max(0,a-o/2),c=s-i,u=2*c,l=.5*Math.PI*i,d=4*u+4*l,f=Ze(e,r,c,i,u,l,d),{dashArray:m}=U(d,o),[h,g]=m.split(" ").map(Number),b=h+g;return(f+h/2)%b<h}function Ze(e,r,t,o,n,s,a){if(r<-t)if(e>t){let i=Math.atan2(r- -t,e-t)+Math.PI/2;return t+i*o}else if(e<-t){let i=Math.atan2(r- -t,e- -t)+Math.PI;return t+3*s+3*n+i*o}else return e>=0?e:a+e;else if(r>t)if(e>t){let i=Math.atan2(r-t,e-t);return t+s+n+i*o}else if(e<-t){let i=Math.atan2(r-t,e- -t)-Math.PI/2;return t+2*s+2*n+i*o}else return t+2*s+n+(t-e);else return e>t?t+s+(r- -t):e<-t?t+3*s+2*n+(t-r):e>=0?e:a+e}function Ke(e,r,t,o){let n=t/2,s=Math.abs(e),i=Math.abs(r)>=s?n+e:n+r,c=t-o,u=3,l=2,d=o*(u+l),f=Math.max(1,Math.round(c/d)),m=c/f,h=m*(u/(u+l)),b=(m-h)/2;return(i+b)%m<h}var W=.12,Je={EYE_FRAME:.90909},E={square:{renderSVG(e,r,t,o){return`<rect x="${e}" y="${r}" width="${t}" height="${t}" fill="${o}"/>`},renderPixel(e,r,t,o){let n=t/2,s=o?.pixelSize??.01,a=Math.min(n-Math.abs(e),n-Math.abs(r));return M(a,s)}},squircle:{renderSVG(e,r,t,o){let n=t/2,s=n*Je.EYE_FRAME,a=e+n,i=r+n;return`<path d="${`M${a},${i-n}
|
|
2
|
+
C${a+s},${i-n} ${a+n},${i-s} ${a+n},${i}
|
|
3
|
+
S${a+s},${i+n} ${a},${i+n}
|
|
4
|
+
S${a-n},${i+s} ${a-n},${i}
|
|
5
|
+
S${a-s},${i-n} ${a},${i-n}Z`}" fill="${o}"/>`},renderPixel(e,r,t,o){let n=t/2,s=o?.pixelSize??.01,a=4,i=Math.abs(e),c=Math.abs(r),u=i/n,l=c/n;if(i<.001&&c<.001)return 255;let d=Math.pow(u,a)+Math.pow(l,a),f=a/n*Math.sqrt(Math.pow(u,2*a-2)+Math.pow(l,2*a-2)),m=(1-d)/f;return M(m,s)}}},O={classic:{renderSVG(){return""},renderPixel(e,r,t,o){let n=t/2,s=o?.pixelSize??.01;if(t>=.99&&o&&o.qrcode&&o.row!==void 0&&o.col!==void 0){let{qrcode:i,row:c,col:u}=o,l=o.qrSize||i.length,d=u>0&&i[c][u-1],f=u<l-1&&i[c][u+1],m=c>0&&i[c-1][u],h=c<l-1&&i[c+1][u],g=d?1/0:n+e,b=f?1/0:n-e,$=m?1/0:n+r,C=h?1/0:n-r,N=Math.min(Math.min(g,b),Math.min($,C));return M(N,s)}let a=Math.min(n-Math.abs(e),n-Math.abs(r));return M(a,s)}},dots:{renderSVG(e,r,t,o){let n=e+t/2,s=r+t/2,a=t*.35;return`<circle cx="${n}" cy="${s}" r="${a}" fill="${o}"/>`},renderPixel(e,r,t,o){let n=t*.35,s=o?.pixelSize??.01,a=Math.sqrt(e*e+r*r);return G(a,n,s)}},square:{renderSVG(e,r,t,o){let n=t*.7,s=(t-n)/2,a=e+s,i=r+s;return`<rect x="${a}" y="${i}" width="${n}" height="${n}" fill="${o}"/>`},renderPixel(e,r,t,o){let s=t*.7/2,a=o?.pixelSize??.01,i=Math.min(s-Math.abs(e),s-Math.abs(r));return M(i,a)}}},T={square:{getDiagonalFactor(){return Math.sqrt(2)},renderSVG(e,r,t,o,n){let s=n?.borderWidth??1;if((n?.borderStyle??"solid")==="dashed"){let f=s/2,m=t-s,{dashArray:h,offset:g}=He(m,s);return`<rect x="${e+f}" y="${r+f}" width="${m}" height="${m}" fill="none" stroke="${o}" stroke-width="${s}" stroke-dasharray="${h}" stroke-dashoffset="${-g}"/>`}let i=`M${e},${r}h${t}v${t}h${-t}z`,c=e+s,u=r+s,l=t-s*2,d=`M${c},${u}h${l}v${l}h${-l}z`;return`<path d="${i} ${d}" fill="${o}" fill-rule="evenodd"/>`},renderPixel(e,r,t,o){let n=o?.borderWidth??1,s=o?.borderStyle??"solid",a=o?.pixelSize??.01,i=t/2,c=i-n,u=i-Math.abs(e),l=i-Math.abs(r),d=c-Math.abs(e),f=c-Math.abs(r),m=Math.min(u,l),h=Math.min(d,f);if(m>=0&&h<=0){if(s==="dashed"&&!Q(e,r,t,n,"square"))return 0;let g=M(m,a),b=255-M(h,a);return Math.min(g,b)}return 0}},squircle:{getDiagonalFactor(){return Math.pow(2,.25)},renderSVG(e,r,t,o,n){let s=n?.borderWidth??1,a=n?.borderStyle??"solid",i=t/2,c=e+i,u=r+i,l=i-s/2,d=t*W,f=Math.max(0,d-s/2),m=l-f,h=`M${c},${u-l}
|
|
6
|
+
H${c+m}
|
|
7
|
+
A${f},${f} 0 0 1 ${c+l},${u-m}
|
|
8
|
+
V${u+m}
|
|
9
|
+
A${f},${f} 0 0 1 ${c+m},${u+l}
|
|
10
|
+
H${c-m}
|
|
11
|
+
A${f},${f} 0 0 1 ${c-l},${u+m}
|
|
12
|
+
V${u-m}
|
|
13
|
+
A${f},${f} 0 0 1 ${c-m},${u-l}
|
|
14
|
+
Z`;if(a==="dashed"){let g=2*m,b=.5*Math.PI*f,$=4*g+4*b,{dashArray:C,offset:N}=U($,s);return`<path d="${h}" fill="none" stroke="${o}" stroke-width="${s}" stroke-dasharray="${C}" stroke-dashoffset="${N}"/>`}return`<path d="${h}" fill="none" stroke="${o}" stroke-width="${s}"/>`},renderPixel(e,r,t,o){let n=o?.borderWidth??1,s=o?.borderStyle??"solid",a=o?.pixelSize??.01,c=t/2-n/2,u=t*W,l=Math.max(0,u-n/2),d=Math.abs(je(e,r,c,l)),f=n/2-d;return f>-a?s==="dashed"&&!Q(e,r,t,n,"squircle")?0:M(f,a):0}},circle:{getDiagonalFactor(){return 1},renderSVG(e,r,t,o,n){let s=n?.borderWidth??1,a=n?.borderStyle??"solid",i=e+t/2,c=r+t/2,u=t/2;if(a==="dashed"){let m=u-s/2,h=2*Math.PI*m,{dashArray:g,offset:b}=U(h,s);return`<circle cx="${i}" cy="${c}" r="${m}" fill="none" stroke="${o}" stroke-width="${s}" stroke-dasharray="${g}" stroke-dashoffset="${b}"/>`}let l=u-s,d=`M${i},${c-u}
|
|
15
|
+
A${u},${u} 0 1,1 ${i},${c+u}
|
|
16
|
+
A${u},${u} 0 1,1 ${i},${c-u}Z`,f=`M${i},${c-l}
|
|
17
|
+
A${l},${l} 0 1,0 ${i},${c+l}
|
|
18
|
+
A${l},${l} 0 1,0 ${i},${c-l}Z`;return`<path d="${d} ${f}" fill="${o}" fill-rule="evenodd"/>`},renderPixel(e,r,t,o){let n=o?.borderWidth??1,s=o?.borderStyle??"solid",a=o?.pixelSize??.01,i=t/2,c=i-n,u=Math.sqrt(e*e+r*r);if(u<=i&&u>=c){if(s==="dashed"&&!Q(e,r,t,n,"circle"))return 0;let l=G(u,i,a),d=255-G(u,c,a);return Math.min(l,d)}return 0}}};var S=class extends Error{constructor(r){let t=r.map(o=>` - ${o.field}: ${o.message}`).join(`
|
|
19
|
+
`);super(`QR Code validation failed:
|
|
20
|
+
${t}`),this.name="QRValidationError",this.errors=r}};function x(e,r,t,o,n=!1){return typeof e!="number"||!isFinite(e)?{field:r,value:e,message:"must be a finite number"}:n&&!Number.isInteger(e)?{field:r,value:e,message:"must be an integer"}:e<t?{field:r,value:e,message:`must be at least ${t}`}:o!==null&&e>o?{field:r,value:e,message:`must be at most ${o}`}:null}function v(e,r){return typeof e!="string"?{field:r,value:e,message:"must be a string"}:/^#[0-9A-Fa-f]{6}$/.test(e)?null:{field:r,value:e,message:"must be a valid hex color (e.g., #000000)"}}function j(e,r,t){if(typeof e!="string")return{field:r,value:e,message:"must be a string"};if(!(e in t)){let o=Object.keys(t).join(", ");return{field:r,value:e,message:`must be one of: ${o}`}}return null}function se(e){let r=[];if(e.size!==void 0){let t=x(e.size,"size",21,null,!0);t&&r.push(t)}if(e.margin!==void 0){let t=x(e.margin,"margin",0,null,!0);t&&r.push(t)}if(e.backgroundColor!==void 0){let t=v(e.backgroundColor,"backgroundColor");t&&r.push(t)}if(e.eyes?.shape!==void 0){let t=j(e.eyes.shape,"eyes.shape",E);t&&r.push(t)}if(e.eyes?.color!==void 0){let t=v(e.eyes.color,"eyes.color");t&&r.push(t)}if(e.pupils?.color!==void 0){let t=v(e.pupils.color,"pupils.color");t&&r.push(t)}if(e.dots?.shape!==void 0){let t=j(e.dots.shape,"dots.shape",O);t&&r.push(t)}if(e.dots?.color!==void 0){let t=v(e.dots.color,"dots.color");t&&r.push(t)}if(e.dots?.scale!==void 0){let t=x(e.dots.scale,"dots.scale",.75,1.25,!1);t&&r.push(t)}if(e.border?.shape!==void 0&&e.border.shape!=="none"){let t=j(e.border.shape,"border.shape",T);t&&r.push(t)}if(e.border?.width!==void 0){let t=x(e.border.width,"border.width",0,null,!0);t&&r.push(t)}if(e.border?.color!==void 0){let t=v(e.border.color,"border.color");t&&r.push(t)}if(e.border?.style!==void 0&&(typeof e.border.style!="string"||e.border.style!=="solid"&&e.border.style!=="dashed")&&r.push({field:"border.style",value:e.border.style,message:'must be either "solid" or "dashed"'}),e.logo&&((!e.logo.src||typeof e.logo.src!="string")&&r.push({field:"logo.src",value:e.logo.src,message:"must be a non-empty string"}),e.logo.scale!==void 0)){let t=x(e.logo.scale,"logo.scale",.1,.3,!1);t&&r.push(t)}if(r.length>0)throw new S(r)}function ae(e){let r=[];if(e.margin!==void 0){let t=x(e.margin,"margin",0,null,!0);t&&r.push(t)}if(e.darkChar!==void 0&&typeof e.darkChar!="string"&&r.push({field:"darkChar",value:e.darkChar,message:"must be a string"}),e.lightChar!==void 0&&typeof e.lightChar!="string"&&r.push({field:"lightChar",value:e.lightChar,message:"must be a string"}),r.length>0)throw new S(r)}var p={size:300,margin:24,backgroundColor:"#ffffff",eyes:{shape:"square",color:"#000000"},pupils:{color:"#000000"},dots:{shape:"classic",color:"#000000",scale:1},logo:{scale:.2},border:{shape:"none",width:10,color:"#000000",style:"solid"},output:{format:"png",type:"buffer"}},k={margin:2,darkChar:"\u2588\u2588",lightChar:" "};function ie(e){if(!e){let{logo:t,...o}=p;return o}return se(e),{size:e.size??p.size,margin:e.margin??p.margin,backgroundColor:e.backgroundColor??p.backgroundColor,eyes:{shape:e.eyes?.shape??p.eyes.shape,color:e.eyes?.color??p.eyes.color},pupils:{color:e.pupils?.color??p.pupils.color},dots:{shape:e.dots?.shape??p.dots.shape,color:e.dots?.color??p.dots.color,scale:e.dots?.scale??p.dots.scale},logo:e.logo?{src:e.logo.src,scale:e.logo.scale??p.logo.scale}:void 0,border:{shape:e.border?.shape??p.border.shape,width:e.border?.width??p.border.width,color:e.border?.color??p.border.color,style:e.border?.style??p.border.style},output:e.output??p.output}}function ce(e){return e?(ae(e),{margin:e.margin??k.margin,darkChar:e.darkChar??k.darkChar,lightChar:e.lightChar??k.lightChar}):{...k}}function ue(e){return/^\d+$/.test(e)?1:[...e].every(r=>R.includes(r))?2:4}function et(e){let r=[];for(let t=0;t<e.length;t+=3){let o=e.substring(t,Math.min(t+3,e.length)),n=parseInt(o,10),s=o.length===3?10:o.length===2?7:4;for(let a=s-1;a>=0;a--)r.push(n>>a&1)}return r}function tt(e){let r=[];for(let t=0;t<e.length;t+=2)if(t+1<e.length){let o=R.indexOf(e[t])*45+R.indexOf(e[t+1]);for(let n=10;n>=0;n--)r.push(o>>n&1)}else{let o=R.indexOf(e[t]);for(let n=5;n>=0;n--)r.push(o>>n&1)}return r}function rt(e){let r=[],t=new TextEncoder().encode(e);for(let o of t)for(let n=7;n>=0;n--)r.push(o>>n&1);return r}function nt(e,r,t,o){let n=[];for(let a=3;a>=0;a--)n.push(r>>a&1);let s=L(r,o);for(let a=s-1;a>=0;a--)n.push(t>>a&1);return[...n,...e]}function ot(e){let r=[];for(let t=0;t<e.length;t+=8){let o=0;for(let n=0;n<8&&t+n<e.length;n++)o=o<<1|e[t+n];t+8>e.length&&(o<<=8-e.length%8),r.push(o)}return r}function st(e,r){let t=[...e],o=[236,17],n=0;for(;t.length<r;)t.push(o[n]),n=1-n;return t}function le(e,r,t){let o=ue(e),n,s;o===1?(n=et(e),s=e.length):o===2?(n=tt(e),s=e.length):(n=rt(e),s=new TextEncoder().encode(e).length);let a=nt(n,o,s,r),i=Math.min(4,t*8-a.length);for(let u=0;u<i;u++)a.push(0);for(;a.length%8!==0;)a.push(0);let c=ot(a);return st(c,t)}function D(e,r){let t=ue(e),o=t===4?new TextEncoder().encode(e).length:e.length;for(let c=1;c<=10;c++){let u=L(t,c),l=t===1?Math.ceil(o/3)*10-(o%3===1?6:o%3===2?3:0):t===2?Math.floor(o/2)*11+o%2*6:o*8,d=4+u+l;if(Math.ceil(d/8)<=r[c-1])return c}let n=L(t,10),s=t===1?Math.ceil(o/3)*10-(o%3===1?6:o%3===2?3:0):t===2?Math.floor(o/2)*11+o%2*6:o*8,a=4+n+s,i=Math.ceil(a/8);throw new Error(`Input too long for QR code version 10. Required capacity: ${i} bytes, Maximum available: ${r[9]} bytes. Current data length: ${e.length} characters (${o} bytes encoded).`)}function fe(e,r){if(r)try{if(D(e,y.H)<=10)return"H"}catch{throw new Error(`Data too large for QR code with logo. Data length: ${e.length} characters. Maximum capacity with logo (EC level H): ~122 bytes (version 10). Logos require high error correction (H) which reduces data capacity. Consider: reducing data length, removing logo, or using multiple QR codes.`)}let t=["H","Q","M","L"];for(let o of t)try{if(D(e,y[o])<=10)return o}catch{continue}throw new Error(`Data too large for QR code version 10 at any error correction level. Data length: ${e.length} characters. Maximum capacity: ~274 bytes (version 10, EC level L). Please reduce input length or split into multiple QR codes.`)}var w=new Array(256),H=new Array(256);function at(){let e=1;for(let r=0;r<255;r++)w[r]=e,H[e]=r,e<<=1,e&256&&(e^=285);for(let r=255;r<512;r++)w[r]=w[r-255]}at();function me(e,r){return e===0||r===0?0:w[H[e]+H[r]]}function it(e){let r=[1];for(let t=0;t<e;t++){let o=r.length+1,n=new Array(o).fill(0);for(let s=0;s<r.length;s++)n[s]^=r[s],n[s+1]^=me(r[s],w[t]);r=n}return r}function de(e,r){let t=it(r),o=[...e,...new Array(r).fill(0)];for(let n=0;n<e.length;n++){let s=o[n];if(s!==0)for(let a=0;a<t.length;a++)o[n+a]^=me(t[a],s)}return o.slice(e.length)}function he(e,r,t){let o=[],n=[],[s,a,i,c]=t,u=0;for(let l=0;l<s;l++){let d=e.slice(u,u+a);o.push(d);let f=de(d,r);n.push(f),u+=a}for(let l=0;l<i;l++){let d=e.slice(u,u+c);o.push(d);let f=de(d,r);n.push(f),u+=c}return{dataBlocks:o,ecBlocks:n}}function ge(e,r){let t=[],o=Math.max(...e.map(s=>s.length));for(let s=0;s<o;s++)for(let a of e)s<a.length&&t.push(a[s]);let n=Math.max(...r.map(s=>s.length));for(let s=0;s<n;s++)for(let a of r)s<a.length&&t.push(a[s]);return t}function be(e){let r=I(e);return Array.from({length:r},()=>Array(r).fill(!1))}function pe(e){let r=I(e),t=Array.from({length:r},()=>Array(r).fill(!1));for(let n=0;n<=7;n++)for(let s=0;s<=7;s++)t[n][s]=!0;for(let n=0;n<=7;n++)for(let s=0;s<=7;s++)t[n][r-8+s]=!0;for(let n=0;n<=7;n++)for(let s=0;s<=7;s++)t[r-8+n][s]=!0;for(let n=8;n<r-8;n++)t[6][n]=!0,t[n][6]=!0;t[4*e+9][8]=!0;for(let n=0;n<6;n++)t[n][8]=!0;t[7][8]=!0,t[8][8]=!0;for(let n=r-8;n<r;n++)t[n][8]=!0;for(let n=0;n<9;n++)t[8][n]=!0;for(let n=r-8;n<r;n++)t[8][n]=!0;let o=A[e-1]||[];for(let n of o)for(let s of o)if(!(n<9&&s<9||n<9&&s>r-9||n>r-9&&s<9))for(let i=-2;i<=2;i++)for(let c=-2;c<=2;c++)t[n+i][s+c]=!0;if(e>=7){for(let n=0;n<6;n++)for(let s=r-11;s<r-8;s++)t[n][s]=!0;for(let n=r-11;n<r-8;n++)for(let s=0;s<6;s++)t[n][s]=!0}return t}function Y(e,r,t){for(let o=-1;o<=7;o++)for(let n=-1;n<=7;n++){let s=r+o,a=t+n;if(s<0||s>=e.length||a<0||a>=e.length)continue;let i=o>=0&&o<=6&&n>=0&&n<=6&&(o===0||o===6||n===0||n===6),c=o>=2&&o<=4&&n>=2&&n<=4;e[s][a]=i||c}}function ct(e,r,t){for(let o=-2;o<=2;o++)for(let n=-2;n<=2;n++){let s=o===-2||o===2||n===-2||n===2,a=o===0&&n===0;e[r+o][t+n]=s||a}}function $e(e){let r=e.length;for(let t=8;t<r-8;t++)e[6][t]=t%2===0,e[t][6]=t%2===0}function Ce(e){Y(e,0,0),Y(e,0,e.length-7),Y(e,e.length-7,0)}function Me(e,r){let t=e.length,o=A[r-1]||[];for(let n of o)for(let s of o)n<9&&s<9||n<9&&s>t-9||n>t-9&&s<9||ct(e,n,s)}function ye(e,r){e[4*r+9][8]=!0}function xe(e,r,t){let o=e.length,n=0,s=-1,a=o-1;for(let i=o-1;i>0;i-=2)for(i===6&&i--;;){for(let c=0;c<2;c++)if(!r[a][i-c]){let u=n<t.length?t[n]:!1;e[a][i-c]=u,n++}if(a+=s,a<0||o<=a){a-=s,s=-s;break}}}function X(e,r,t){let o=e.length;for(let n=0;n<o;n++)for(let s=0;s<o;s++){if(r[n][s])continue;let a=!1;switch(t){case 0:a=(n+s)%2===0;break;case 1:a=n%2===0;break;case 2:a=s%3===0;break;case 3:a=(n+s)%3===0;break;case 4:a=(Math.floor(n/2)+Math.floor(s/3))%2===0;break;case 5:a=n*s%2+n*s%3===0;break;case 6:a=(n*s%2+n*s%3)%2===0;break;case 7:a=((n+s)%2+n*s%3)%2===0;break}a&&(e[n][s]=!e[n][s])}}function ut(e){let r=e.length,t=0;for(let a=0;a<r;a++){let i=e[a][0],c=e[0][a],u=1,l=1;for(let d=1;d<r;d++)e[a][d]===i?u++:(u>=5&&(t+=3+(u-5)),i=e[a][d],u=1),e[d][a]===c?l++:(l>=5&&(t+=3+(l-5)),c=e[d][a],l=1);u>=5&&(t+=3+(u-5)),l>=5&&(t+=3+(l-5))}for(let a=0;a<r-1;a++)for(let i=0;i<r-1;i++){let c=e[a][i];e[a][i+1]===c&&e[a+1][i]===c&&e[a+1][i+1]===c&&(t+=3)}for(let a=0;a<r;a++){let i=0,c=0;for(let u=0;u<r;u++)i=i<<1&2047|(e[a][u]?1:0),u>=10&&(i===1488||i===93)&&(t+=40),c=c<<1&2047|(e[u][a]?1:0),u>=10&&(c===1488||c===93)&&(t+=40)}let o=0,n=r*r;for(let a=0;a<r;a++)for(let i=0;i<r;i++)e[a][i]&&o++;let s=Math.abs(Math.ceil(o*100/n/5)-10);return t+=s*10,t}function Se(e,r,t,o){let n=0,s=1/0;for(let a=0;a<8;a++){let i=e.map(u=>[...u]);X(i,r,a),o(i,t,a);let c=ut(i);c<s&&(s=c,n=a)}return n}function Z(e,r,t){let o=e.length,n=V[r]<<3|t,s=n<<10;for(let i=0;i<5;i++)s&1<<14-i&&(s^=1335<<4-i);let a=(n<<10|s)^21522;for(let i=0;i<15;i++){let c=(a>>14-i&1)===1;i<=5?e[8][i]=c:i===6?e[8][7]=c:i===7?e[8][8]=c:i===8?e[7][8]=c:e[5-(i-9)][8]=c,i<=6?e[o-1-i][8]=c:e[8][o-8+(i-7)]=c}}function Re(e,r){if(r<7)return;let t=e.length,o=ne[r-7];for(let n=0;n<18;n++){let s=(o>>n&1)===1,a=Math.floor(n/3),i=t-11+n%3;e[a][i]=s;let c=t-11+n%3,u=Math.floor(n/3);e[c][u]=s}}function Ie(e,r){return V[e]<<3|r}function Ee(e,r,t,o,n){let s=be(e),a=pe(e);Ce(s),$e(s),Me(s,e),ye(s,e),xe(s,a,t);let i=n?s.map(u=>[...u]):void 0,c=o??Se(s,a,r,Z);return X(s,a,c),Z(s,r,c),Re(s,e),{matrix:s,mask:c,formatInfo:n?Ie(r,c):void 0,unmaskedMatrix:i}}function K(e,r,t){return e<7&&r<7||e<7&&r>=t-7||e>=t-7&&r<7}function Oe(e){return[{x:0,y:0},{x:e-7,y:0},{x:0,y:e-7}]}function ve(e,r){let o=Math.max(.1,Math.min(.3,r));return e*o}function lt(e,r,t,o,n,s,a){let i=E[t]||E.square,c=i.renderSVG(e,r,7*a,o),u=i.renderSVG(e+a,r+a,5*a,s),l=i.renderSVG(e+2*a,r+2*a,3*a,n);return c+u+l}function ft(e,r,t,o){let n=o/2;if(e.includes("data:image/svg")||e.trim().startsWith("<svg")){let s=e;if(e.includes("data:image/svg")){let u=e.match(/data:image\/svg\+xml[^,]*,(.+)/);if(u)try{s=decodeURIComponent(u[1])}catch{return""}}let a=s.match(/viewBox=["']([^"']+)["']/),i=a?a[1]:"0 0 100 100",c=s.replace(/<\?xml[^>]*>|<svg[^>]*>|<\/svg>/gi,"");return`<g transform="translate(${r-n}, ${t-n})">
|
|
21
|
+
<svg width="${o}" height="${o}" viewBox="${i}">
|
|
22
|
+
${c}
|
|
23
|
+
</svg>
|
|
24
|
+
</g>`}else return`<image x="${r-n}" y="${t-n}" width="${o}" height="${o}" href="${e}" preserveAspectRatio="xMidYMid meet"/>`}function dt(e,r,t,o,n){let s=e.matrixSize,a="",i=O[t]||O.classic;if(t==="classic"){a=`<path fill="${o}" d="`;for(let c=0;c<s;c++)for(let u=0;u<s;u++)if(e.modules[c][u]&&!K(c,u,s)){let l=u*r,d=c*r,f=n*r,m=(1-n)*r/2,h=l+m,g=d+m;a+=`M${h},${g}h${f}v${f}h${-f}z`}return a+='"/>',a}for(let c=0;c<s;c++)for(let u=0;u<s;u++)if(e.modules[c][u]&&!K(c,u,s)){let l=u*r,d=c*r,f=n*r,m=(1-n)*r/2,h=l+m,g=d+m,b={qrcode:e.modules,qrSize:s,row:c,col:u};a+=i.renderSVG(h,g,f,o,b)}return a}function we(e,r){let{size:t,margin:o,backgroundColor:n,eyes:s,pupils:a,dots:i}=r,c=t/e.matrixSize,u=r.border.shape==="none"?0:r.border.width,l=t+2*o+2*u,d=o+u,f=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${l} ${l}" width="${l}" height="${l}">`;if(f+=`<rect width="${l}" height="${l}" fill="${n}"/>`,r.border.shape!=="none"&&u>0){let $=T[r.border.shape];if($){let C={borderWidth:u,borderStyle:r.border.style};f+=$.renderSVG(0,0,l,r.border.color,C)}}r.border.shape!=="none"&&u>0&&(f+=`<rect x="${d}" y="${d}" width="${t}" height="${t}" fill="${n}"/>`),f+=`<g transform="translate(${d}, ${d})">`;let m=Oe(e.matrixSize),h="";for(let $ of m)h+=lt($.x*c,$.y*c,s.shape,s.color,a.color,n,c);let g=dt(e,c,i.shape,i.color,i.scale);f+=h+g+"</g>";let b="";if(r.logo){let $=ve(e.matrixSize,r.logo.scale)*c,C=l/2;b=ft(r.logo.src,C,C,$)}return f+=b+"</svg>",f}function Pe(e,r){let{margin:t,lightChar:o,darkChar:n}=r,s="",a=e.matrixSize+t*2;for(let i=0;i<t;i++)s+=o.repeat(a)+`
|
|
25
|
+
`;for(let i=0;i<e.matrixSize;i++){s+=o.repeat(t);for(let c=0;c<e.matrixSize;c++)s+=e.modules[i][c]?n:o;s+=o.repeat(t)+`
|
|
26
|
+
`}for(let i=0;i<t;i++)s+=o.repeat(a)+`
|
|
27
|
+
`;return s}var B=null,Ae=!1;async function mt(){if(B)return B;if(Ae)throw new Error("PNG generation in Node.js requires @resvg/resvg-js. Install with: npm install @resvg/resvg-js");Ae=!0;try{return B=(await import("@resvg/resvg-js")).Resvg,B}catch{throw new Error("PNG generation in Node.js requires @resvg/resvg-js. Install with: npm install @resvg/resvg-js")}}async function Le(e,r){let{output:t,size:o,margin:n,border:s}=r,a=s.shape==="none"?0:s.width,i=o+2*n+2*a,c=await mt(),d=new c(e,{fitTo:{mode:"width",value:i}}).render().asPng(),f=Buffer.from(d);return t.type==="dataURL"?`data:image/png;base64,${f.toString("base64")}`:f}async function Te(e,r){let{format:t,type:o}=r.output;return t==="svg"?o==="string"?e:`data:image/svg+xml;charset=utf-8,${encodeURIComponent(e)}`:await Le(e,r)}function J(e){if(typeof e=="string")return e;switch(e.type){case"url":return ht(e.url);case"vcard":return gt(e.data);case"wifi":return bt(e.data);case"calendar":return pt(e.data);case"email":return $t(e.email,e.subject,e.body);case"sms":return Ct(e.phone,e.message);case"phone":return Mt(e.phone)}}function ht(e){return!e.startsWith("http://")&&!e.startsWith("https://")?`https://${e}`:e}function gt(e){let r=["BEGIN:VCARD","VERSION:3.0",`FN:${e.name}`];if(e.phone&&r.push(`TEL:${e.phone}`),e.email&&r.push(`EMAIL:${e.email}`),e.organization&&r.push(`ORG:${e.organization}`),e.url&&r.push(`URL:${e.url}`),e.title&&r.push(`TITLE:${e.title}`),e.note&&r.push(`NOTE:${e.note}`),e.address){let{street:t,city:o,state:n,zip:s,country:a}=e.address,i=["","",t||"",o||"",n||"",s||"",a||""];r.push(`ADR:${i.join(";")}`)}return r.push("END:VCARD"),r.join(`
|
|
28
|
+
`)}function bt(e){let r=e.encryption||"WPA",t=e.hidden?"H:true;":"",o=ke(e.ssid),n=ke(e.password);return`WIFI:T:${r};S:${o};P:${n};${t};`}function ke(e){return e.replace(/([\\;,":])/g,"\\$1")}function pt(e){let r=o=>(typeof o=="string"?new Date(o):o).toISOString().replace(/[-:]/g,"").split(".")[0]+"Z",t=["BEGIN:VCALENDAR","VERSION:2.0","BEGIN:VEVENT",`SUMMARY:${e.title}`,`DTSTART:${r(e.startDate)}`,`DTEND:${r(e.endDate)}`];return e.location&&t.push(`LOCATION:${e.location}`),e.description&&t.push(`DESCRIPTION:${e.description}`),t.push("END:VEVENT","END:VCALENDAR"),t.join(`
|
|
29
|
+
`)}function $t(e,r,t){let o=`mailto:${e}`,n=[];return r&&n.push(`subject=${encodeURIComponent(r)}`),t&&n.push(`body=${encodeURIComponent(t)}`),n.length>0&&(o+=`?${n.join("&")}`),o}function Ct(e,r){return r?`sms:${e}:${r}`:`sms:${e}`}function Mt(e){return`tel:${e}`}function yt(e,r){let t=[];for(let n of e)for(let s=7;s>=0;s--)t.push((n>>s&1)===1);let o=oe[r-1];for(let n=0;n<o;n++)t.push(!1);return t}function De(e,r){if(!e)throw new Error("QR Code input cannot be empty. Please provide text or structured content to encode.");let t=fe(e,r),o=y[t],n=D(e,o);if(n<1||n>10)throw new Error(`Input data is too large for QR code version 10. Data length: ${e.length} characters. Maximum capacity at EC level ${t}: ~${y[t][9]} bytes. Try reducing input length or removing logo for higher capacity.`);let s=le(e,n,o[n-1]),a=te[t][n-1],i=re[t][n-1],{dataBlocks:c,ecBlocks:u}=he(s,a,i),l=ge(c,u),d=yt(l,n),{matrix:f,mask:m}=Ee(n,t,d);return{version:n,matrixSize:I(n),modules:f,mask:m,errorCorrectionLevel:t}}async function Be(e,r){let t=J(e),o=ie(r),n=De(t,!!o.logo),s=we(n,o);return await Te(s,o)}function Ne(e,r){let t=J(e),o=ce(r),n=De(t,!1);return Pe(n,o)}0&&(module.exports={BorderShape,BorderStyle,DotShape,EyeFrameShape,QRValidationError,genQrImage,genQrText});
|
package/dist/node.mjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
var Y={L:[7,10,15,20,26,18,20,24,30,18],M:[10,16,26,18,24,16,18,22,22,26],Q:[13,22,18,26,18,24,18,22,20,24],H:[17,28,22,16,22,28,26,26,24,28]},y={L:[19,34,55,80,108,136,156,194,232,274],M:[16,28,44,64,86,108,124,154,182,216],Q:[13,22,34,48,62,76,88,110,132,154],H:[9,16,26,36,46,60,66,86,100,122]},X={L:[[1,19,0,0],[1,34,0,0],[1,55,0,0],[1,80,0,0],[1,108,0,0],[2,68,0,0],[2,78,0,0],[2,97,0,0],[2,116,0,0],[2,68,2,69]],M:[[1,16,0,0],[1,28,0,0],[1,44,0,0],[2,32,0,0],[2,43,0,0],[4,27,0,0],[4,31,0,0],[2,38,2,39],[3,36,2,37],[4,43,1,44]],Q:[[1,13,0,0],[1,22,0,0],[2,17,0,0],[2,24,0,0],[2,15,2,16],[4,19,0,0],[2,14,4,15],[4,18,2,19],[4,16,4,17],[6,19,2,20]],H:[[1,9,0,0],[1,16,0,0],[2,13,0,0],[4,9,0,0],[2,11,2,12],[4,15,0,0],[4,13,1,14],[4,14,2,15],[4,12,4,13],[6,15,2,16]]},S="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:",ke={1:[10,12,14],2:[9,11,13],4:[8,16,16]},N={L:1,M:0,Q:3,H:2},P=[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50]],Z=[31892,34236,39577,42195],K=[0,7,7,7,7,7,0,0,0,0];function R(e){return e*4+17}function A(e,r){let t=r<10?0:r<27?1:2;return ke[e][t]}var J=(t=>(t.SQUARE="square",t.SQUIRCLE="squircle",t))(J||{}),ee=(o=>(o.CLASSIC="classic",o.DOTS="dots",o.SQUARE="square",o))(ee||{}),te=(n=>(n.NONE="none",n.SQUARE="square",n.SQUIRCLE="squircle",n.CIRCLE="circle",n))(te||{}),re=(t=>(t.SOLID="solid",t.DASHED="dashed",t))(re||{});function M(e,r){let t=r/2;return e<=-t?0:e>=t?255:Math.round((e+t)/r*255)}function z(e,r,t=.01){return M(r-e,t)}function De(e,r,t,o){let n=Math.abs(e)-t+o,s=Math.abs(r)-t+o,a=Math.sqrt(Math.max(n,0)**2+Math.max(s,0)**2),i=Math.min(Math.max(n,s),0);return a+i-o}function Be(e,r){let n=r*3,s=r*2,a=n+s,i=Math.max(1,Math.round(e/a)),c=e/i,u=c*(3/5),l=c*(2/5),d=l/2;return{dashArray:`${u} ${l}`,offset:d}}function F(e,r){let t=r*3,o=r*2,n=t+o,s=Math.round(e/n);s=Math.round(s/4)*4,s=Math.max(4,s);let a=e/s,i=a*.6,c=a*.4,u=i/2;return{dashArray:`${i} ${c}`,offset:u}}function V(e,r,t,o,n){return n==="circle"?Ne(e,r,t,o):n==="squircle"?Ve(e,r,t,o):Fe(e,r,t,o)}function Ne(e,r,t,o){let s=(Math.atan2(r,e)+Math.PI)/(2*Math.PI),a=t/2-o/2,i=2*Math.PI*a,c=o*3,u=o*2,l=Math.floor(i/(c+u)),d=l%2===0?l:l-1,f=Math.max(4,d);return s*f%1<.6}function Ve(e,r,t,o){let s=t/2-o/2,a=t*q,i=Math.max(0,a-o/2),c=s-i,u=2*c,l=.5*Math.PI*i,d=4*u+4*l,f=ze(e,r,c,i,u,l,d),{dashArray:m}=F(d,o),[h,g]=m.split(" ").map(Number),b=h+g;return(f+h/2)%b<h}function ze(e,r,t,o,n,s,a){if(r<-t)if(e>t){let i=Math.atan2(r- -t,e-t)+Math.PI/2;return t+i*o}else if(e<-t){let i=Math.atan2(r- -t,e- -t)+Math.PI;return t+3*s+3*n+i*o}else return e>=0?e:a+e;else if(r>t)if(e>t){let i=Math.atan2(r-t,e-t);return t+s+n+i*o}else if(e<-t){let i=Math.atan2(r-t,e- -t)-Math.PI/2;return t+2*s+2*n+i*o}else return t+2*s+n+(t-e);else return e>t?t+s+(r- -t):e<-t?t+3*s+2*n+(t-r):e>=0?e:a+e}function Fe(e,r,t,o){let n=t/2,s=Math.abs(e),i=Math.abs(r)>=s?n+e:n+r,c=t-o,u=3,l=2,d=o*(u+l),f=Math.max(1,Math.round(c/d)),m=c/f,h=m*(u/(u+l)),b=(m-h)/2;return(i+b)%m<h}var q=.12,qe={EYE_FRAME:.90909},I={square:{renderSVG(e,r,t,o){return`<rect x="${e}" y="${r}" width="${t}" height="${t}" fill="${o}"/>`},renderPixel(e,r,t,o){let n=t/2,s=o?.pixelSize??.01,a=Math.min(n-Math.abs(e),n-Math.abs(r));return M(a,s)}},squircle:{renderSVG(e,r,t,o){let n=t/2,s=n*qe.EYE_FRAME,a=e+n,i=r+n;return`<path d="${`M${a},${i-n}
|
|
2
|
+
C${a+s},${i-n} ${a+n},${i-s} ${a+n},${i}
|
|
3
|
+
S${a+s},${i+n} ${a},${i+n}
|
|
4
|
+
S${a-n},${i+s} ${a-n},${i}
|
|
5
|
+
S${a-s},${i-n} ${a},${i-n}Z`}" fill="${o}"/>`},renderPixel(e,r,t,o){let n=t/2,s=o?.pixelSize??.01,a=4,i=Math.abs(e),c=Math.abs(r),u=i/n,l=c/n;if(i<.001&&c<.001)return 255;let d=Math.pow(u,a)+Math.pow(l,a),f=a/n*Math.sqrt(Math.pow(u,2*a-2)+Math.pow(l,2*a-2)),m=(1-d)/f;return M(m,s)}}},E={classic:{renderSVG(){return""},renderPixel(e,r,t,o){let n=t/2,s=o?.pixelSize??.01;if(t>=.99&&o&&o.qrcode&&o.row!==void 0&&o.col!==void 0){let{qrcode:i,row:c,col:u}=o,l=o.qrSize||i.length,d=u>0&&i[c][u-1],f=u<l-1&&i[c][u+1],m=c>0&&i[c-1][u],h=c<l-1&&i[c+1][u],g=d?1/0:n+e,b=f?1/0:n-e,$=m?1/0:n+r,C=h?1/0:n-r,B=Math.min(Math.min(g,b),Math.min($,C));return M(B,s)}let a=Math.min(n-Math.abs(e),n-Math.abs(r));return M(a,s)}},dots:{renderSVG(e,r,t,o){let n=e+t/2,s=r+t/2,a=t*.35;return`<circle cx="${n}" cy="${s}" r="${a}" fill="${o}"/>`},renderPixel(e,r,t,o){let n=t*.35,s=o?.pixelSize??.01,a=Math.sqrt(e*e+r*r);return z(a,n,s)}},square:{renderSVG(e,r,t,o){let n=t*.7,s=(t-n)/2,a=e+s,i=r+s;return`<rect x="${a}" y="${i}" width="${n}" height="${n}" fill="${o}"/>`},renderPixel(e,r,t,o){let s=t*.7/2,a=o?.pixelSize??.01,i=Math.min(s-Math.abs(e),s-Math.abs(r));return M(i,a)}}},L={square:{getDiagonalFactor(){return Math.sqrt(2)},renderSVG(e,r,t,o,n){let s=n?.borderWidth??1;if((n?.borderStyle??"solid")==="dashed"){let f=s/2,m=t-s,{dashArray:h,offset:g}=Be(m,s);return`<rect x="${e+f}" y="${r+f}" width="${m}" height="${m}" fill="none" stroke="${o}" stroke-width="${s}" stroke-dasharray="${h}" stroke-dashoffset="${-g}"/>`}let i=`M${e},${r}h${t}v${t}h${-t}z`,c=e+s,u=r+s,l=t-s*2,d=`M${c},${u}h${l}v${l}h${-l}z`;return`<path d="${i} ${d}" fill="${o}" fill-rule="evenodd"/>`},renderPixel(e,r,t,o){let n=o?.borderWidth??1,s=o?.borderStyle??"solid",a=o?.pixelSize??.01,i=t/2,c=i-n,u=i-Math.abs(e),l=i-Math.abs(r),d=c-Math.abs(e),f=c-Math.abs(r),m=Math.min(u,l),h=Math.min(d,f);if(m>=0&&h<=0){if(s==="dashed"&&!V(e,r,t,n,"square"))return 0;let g=M(m,a),b=255-M(h,a);return Math.min(g,b)}return 0}},squircle:{getDiagonalFactor(){return Math.pow(2,.25)},renderSVG(e,r,t,o,n){let s=n?.borderWidth??1,a=n?.borderStyle??"solid",i=t/2,c=e+i,u=r+i,l=i-s/2,d=t*q,f=Math.max(0,d-s/2),m=l-f,h=`M${c},${u-l}
|
|
6
|
+
H${c+m}
|
|
7
|
+
A${f},${f} 0 0 1 ${c+l},${u-m}
|
|
8
|
+
V${u+m}
|
|
9
|
+
A${f},${f} 0 0 1 ${c+m},${u+l}
|
|
10
|
+
H${c-m}
|
|
11
|
+
A${f},${f} 0 0 1 ${c-l},${u+m}
|
|
12
|
+
V${u-m}
|
|
13
|
+
A${f},${f} 0 0 1 ${c-m},${u-l}
|
|
14
|
+
Z`;if(a==="dashed"){let g=2*m,b=.5*Math.PI*f,$=4*g+4*b,{dashArray:C,offset:B}=F($,s);return`<path d="${h}" fill="none" stroke="${o}" stroke-width="${s}" stroke-dasharray="${C}" stroke-dashoffset="${B}"/>`}return`<path d="${h}" fill="none" stroke="${o}" stroke-width="${s}"/>`},renderPixel(e,r,t,o){let n=o?.borderWidth??1,s=o?.borderStyle??"solid",a=o?.pixelSize??.01,c=t/2-n/2,u=t*q,l=Math.max(0,u-n/2),d=Math.abs(De(e,r,c,l)),f=n/2-d;return f>-a?s==="dashed"&&!V(e,r,t,n,"squircle")?0:M(f,a):0}},circle:{getDiagonalFactor(){return 1},renderSVG(e,r,t,o,n){let s=n?.borderWidth??1,a=n?.borderStyle??"solid",i=e+t/2,c=r+t/2,u=t/2;if(a==="dashed"){let m=u-s/2,h=2*Math.PI*m,{dashArray:g,offset:b}=F(h,s);return`<circle cx="${i}" cy="${c}" r="${m}" fill="none" stroke="${o}" stroke-width="${s}" stroke-dasharray="${g}" stroke-dashoffset="${b}"/>`}let l=u-s,d=`M${i},${c-u}
|
|
15
|
+
A${u},${u} 0 1,1 ${i},${c+u}
|
|
16
|
+
A${u},${u} 0 1,1 ${i},${c-u}Z`,f=`M${i},${c-l}
|
|
17
|
+
A${l},${l} 0 1,0 ${i},${c+l}
|
|
18
|
+
A${l},${l} 0 1,0 ${i},${c-l}Z`;return`<path d="${d} ${f}" fill="${o}" fill-rule="evenodd"/>`},renderPixel(e,r,t,o){let n=o?.borderWidth??1,s=o?.borderStyle??"solid",a=o?.pixelSize??.01,i=t/2,c=i-n,u=Math.sqrt(e*e+r*r);if(u<=i&&u>=c){if(s==="dashed"&&!V(e,r,t,n,"circle"))return 0;let l=z(u,i,a),d=255-z(u,c,a);return Math.min(l,d)}return 0}}};var v=class extends Error{constructor(r){let t=r.map(o=>` - ${o.field}: ${o.message}`).join(`
|
|
19
|
+
`);super(`QR Code validation failed:
|
|
20
|
+
${t}`),this.name="QRValidationError",this.errors=r}};function x(e,r,t,o,n=!1){return typeof e!="number"||!isFinite(e)?{field:r,value:e,message:"must be a finite number"}:n&&!Number.isInteger(e)?{field:r,value:e,message:"must be an integer"}:e<t?{field:r,value:e,message:`must be at least ${t}`}:o!==null&&e>o?{field:r,value:e,message:`must be at most ${o}`}:null}function O(e,r){return typeof e!="string"?{field:r,value:e,message:"must be a string"}:/^#[0-9A-Fa-f]{6}$/.test(e)?null:{field:r,value:e,message:"must be a valid hex color (e.g., #000000)"}}function _(e,r,t){if(typeof e!="string")return{field:r,value:e,message:"must be a string"};if(!(e in t)){let o=Object.keys(t).join(", ");return{field:r,value:e,message:`must be one of: ${o}`}}return null}function ne(e){let r=[];if(e.size!==void 0){let t=x(e.size,"size",21,null,!0);t&&r.push(t)}if(e.margin!==void 0){let t=x(e.margin,"margin",0,null,!0);t&&r.push(t)}if(e.backgroundColor!==void 0){let t=O(e.backgroundColor,"backgroundColor");t&&r.push(t)}if(e.eyes?.shape!==void 0){let t=_(e.eyes.shape,"eyes.shape",I);t&&r.push(t)}if(e.eyes?.color!==void 0){let t=O(e.eyes.color,"eyes.color");t&&r.push(t)}if(e.pupils?.color!==void 0){let t=O(e.pupils.color,"pupils.color");t&&r.push(t)}if(e.dots?.shape!==void 0){let t=_(e.dots.shape,"dots.shape",E);t&&r.push(t)}if(e.dots?.color!==void 0){let t=O(e.dots.color,"dots.color");t&&r.push(t)}if(e.dots?.scale!==void 0){let t=x(e.dots.scale,"dots.scale",.75,1.25,!1);t&&r.push(t)}if(e.border?.shape!==void 0&&e.border.shape!=="none"){let t=_(e.border.shape,"border.shape",L);t&&r.push(t)}if(e.border?.width!==void 0){let t=x(e.border.width,"border.width",0,null,!0);t&&r.push(t)}if(e.border?.color!==void 0){let t=O(e.border.color,"border.color");t&&r.push(t)}if(e.border?.style!==void 0&&(typeof e.border.style!="string"||e.border.style!=="solid"&&e.border.style!=="dashed")&&r.push({field:"border.style",value:e.border.style,message:'must be either "solid" or "dashed"'}),e.logo&&((!e.logo.src||typeof e.logo.src!="string")&&r.push({field:"logo.src",value:e.logo.src,message:"must be a non-empty string"}),e.logo.scale!==void 0)){let t=x(e.logo.scale,"logo.scale",.1,.3,!1);t&&r.push(t)}if(r.length>0)throw new v(r)}function oe(e){let r=[];if(e.margin!==void 0){let t=x(e.margin,"margin",0,null,!0);t&&r.push(t)}if(e.darkChar!==void 0&&typeof e.darkChar!="string"&&r.push({field:"darkChar",value:e.darkChar,message:"must be a string"}),e.lightChar!==void 0&&typeof e.lightChar!="string"&&r.push({field:"lightChar",value:e.lightChar,message:"must be a string"}),r.length>0)throw new v(r)}var p={size:300,margin:24,backgroundColor:"#ffffff",eyes:{shape:"square",color:"#000000"},pupils:{color:"#000000"},dots:{shape:"classic",color:"#000000",scale:1},logo:{scale:.2},border:{shape:"none",width:10,color:"#000000",style:"solid"},output:{format:"png",type:"buffer"}},T={margin:2,darkChar:"\u2588\u2588",lightChar:" "};function se(e){if(!e){let{logo:t,...o}=p;return o}return ne(e),{size:e.size??p.size,margin:e.margin??p.margin,backgroundColor:e.backgroundColor??p.backgroundColor,eyes:{shape:e.eyes?.shape??p.eyes.shape,color:e.eyes?.color??p.eyes.color},pupils:{color:e.pupils?.color??p.pupils.color},dots:{shape:e.dots?.shape??p.dots.shape,color:e.dots?.color??p.dots.color,scale:e.dots?.scale??p.dots.scale},logo:e.logo?{src:e.logo.src,scale:e.logo.scale??p.logo.scale}:void 0,border:{shape:e.border?.shape??p.border.shape,width:e.border?.width??p.border.width,color:e.border?.color??p.border.color,style:e.border?.style??p.border.style},output:e.output??p.output}}function ae(e){return e?(oe(e),{margin:e.margin??T.margin,darkChar:e.darkChar??T.darkChar,lightChar:e.lightChar??T.lightChar}):{...T}}function ie(e){return/^\d+$/.test(e)?1:[...e].every(r=>S.includes(r))?2:4}function _e(e){let r=[];for(let t=0;t<e.length;t+=3){let o=e.substring(t,Math.min(t+3,e.length)),n=parseInt(o,10),s=o.length===3?10:o.length===2?7:4;for(let a=s-1;a>=0;a--)r.push(n>>a&1)}return r}function Qe(e){let r=[];for(let t=0;t<e.length;t+=2)if(t+1<e.length){let o=S.indexOf(e[t])*45+S.indexOf(e[t+1]);for(let n=10;n>=0;n--)r.push(o>>n&1)}else{let o=S.indexOf(e[t]);for(let n=5;n>=0;n--)r.push(o>>n&1)}return r}function Ge(e){let r=[],t=new TextEncoder().encode(e);for(let o of t)for(let n=7;n>=0;n--)r.push(o>>n&1);return r}function Ue(e,r,t,o){let n=[];for(let a=3;a>=0;a--)n.push(r>>a&1);let s=A(r,o);for(let a=s-1;a>=0;a--)n.push(t>>a&1);return[...n,...e]}function We(e){let r=[];for(let t=0;t<e.length;t+=8){let o=0;for(let n=0;n<8&&t+n<e.length;n++)o=o<<1|e[t+n];t+8>e.length&&(o<<=8-e.length%8),r.push(o)}return r}function je(e,r){let t=[...e],o=[236,17],n=0;for(;t.length<r;)t.push(o[n]),n=1-n;return t}function ce(e,r,t){let o=ie(e),n,s;o===1?(n=_e(e),s=e.length):o===2?(n=Qe(e),s=e.length):(n=Ge(e),s=new TextEncoder().encode(e).length);let a=Ue(n,o,s,r),i=Math.min(4,t*8-a.length);for(let u=0;u<i;u++)a.push(0);for(;a.length%8!==0;)a.push(0);let c=We(a);return je(c,t)}function k(e,r){let t=ie(e),o=t===4?new TextEncoder().encode(e).length:e.length;for(let c=1;c<=10;c++){let u=A(t,c),l=t===1?Math.ceil(o/3)*10-(o%3===1?6:o%3===2?3:0):t===2?Math.floor(o/2)*11+o%2*6:o*8,d=4+u+l;if(Math.ceil(d/8)<=r[c-1])return c}let n=A(t,10),s=t===1?Math.ceil(o/3)*10-(o%3===1?6:o%3===2?3:0):t===2?Math.floor(o/2)*11+o%2*6:o*8,a=4+n+s,i=Math.ceil(a/8);throw new Error(`Input too long for QR code version 10. Required capacity: ${i} bytes, Maximum available: ${r[9]} bytes. Current data length: ${e.length} characters (${o} bytes encoded).`)}function ue(e,r){if(r)try{if(k(e,y.H)<=10)return"H"}catch{throw new Error(`Data too large for QR code with logo. Data length: ${e.length} characters. Maximum capacity with logo (EC level H): ~122 bytes (version 10). Logos require high error correction (H) which reduces data capacity. Consider: reducing data length, removing logo, or using multiple QR codes.`)}let t=["H","Q","M","L"];for(let o of t)try{if(k(e,y[o])<=10)return o}catch{continue}throw new Error(`Data too large for QR code version 10 at any error correction level. Data length: ${e.length} characters. Maximum capacity: ~274 bytes (version 10, EC level L). Please reduce input length or split into multiple QR codes.`)}var w=new Array(256),Q=new Array(256);function He(){let e=1;for(let r=0;r<255;r++)w[r]=e,Q[e]=r,e<<=1,e&256&&(e^=285);for(let r=255;r<512;r++)w[r]=w[r-255]}He();function fe(e,r){return e===0||r===0?0:w[Q[e]+Q[r]]}function Ye(e){let r=[1];for(let t=0;t<e;t++){let o=r.length+1,n=new Array(o).fill(0);for(let s=0;s<r.length;s++)n[s]^=r[s],n[s+1]^=fe(r[s],w[t]);r=n}return r}function le(e,r){let t=Ye(r),o=[...e,...new Array(r).fill(0)];for(let n=0;n<e.length;n++){let s=o[n];if(s!==0)for(let a=0;a<t.length;a++)o[n+a]^=fe(t[a],s)}return o.slice(e.length)}function de(e,r,t){let o=[],n=[],[s,a,i,c]=t,u=0;for(let l=0;l<s;l++){let d=e.slice(u,u+a);o.push(d);let f=le(d,r);n.push(f),u+=a}for(let l=0;l<i;l++){let d=e.slice(u,u+c);o.push(d);let f=le(d,r);n.push(f),u+=c}return{dataBlocks:o,ecBlocks:n}}function me(e,r){let t=[],o=Math.max(...e.map(s=>s.length));for(let s=0;s<o;s++)for(let a of e)s<a.length&&t.push(a[s]);let n=Math.max(...r.map(s=>s.length));for(let s=0;s<n;s++)for(let a of r)s<a.length&&t.push(a[s]);return t}function he(e){let r=R(e);return Array.from({length:r},()=>Array(r).fill(!1))}function ge(e){let r=R(e),t=Array.from({length:r},()=>Array(r).fill(!1));for(let n=0;n<=7;n++)for(let s=0;s<=7;s++)t[n][s]=!0;for(let n=0;n<=7;n++)for(let s=0;s<=7;s++)t[n][r-8+s]=!0;for(let n=0;n<=7;n++)for(let s=0;s<=7;s++)t[r-8+n][s]=!0;for(let n=8;n<r-8;n++)t[6][n]=!0,t[n][6]=!0;t[4*e+9][8]=!0;for(let n=0;n<6;n++)t[n][8]=!0;t[7][8]=!0,t[8][8]=!0;for(let n=r-8;n<r;n++)t[n][8]=!0;for(let n=0;n<9;n++)t[8][n]=!0;for(let n=r-8;n<r;n++)t[8][n]=!0;let o=P[e-1]||[];for(let n of o)for(let s of o)if(!(n<9&&s<9||n<9&&s>r-9||n>r-9&&s<9))for(let i=-2;i<=2;i++)for(let c=-2;c<=2;c++)t[n+i][s+c]=!0;if(e>=7){for(let n=0;n<6;n++)for(let s=r-11;s<r-8;s++)t[n][s]=!0;for(let n=r-11;n<r-8;n++)for(let s=0;s<6;s++)t[n][s]=!0}return t}function G(e,r,t){for(let o=-1;o<=7;o++)for(let n=-1;n<=7;n++){let s=r+o,a=t+n;if(s<0||s>=e.length||a<0||a>=e.length)continue;let i=o>=0&&o<=6&&n>=0&&n<=6&&(o===0||o===6||n===0||n===6),c=o>=2&&o<=4&&n>=2&&n<=4;e[s][a]=i||c}}function Xe(e,r,t){for(let o=-2;o<=2;o++)for(let n=-2;n<=2;n++){let s=o===-2||o===2||n===-2||n===2,a=o===0&&n===0;e[r+o][t+n]=s||a}}function be(e){let r=e.length;for(let t=8;t<r-8;t++)e[6][t]=t%2===0,e[t][6]=t%2===0}function pe(e){G(e,0,0),G(e,0,e.length-7),G(e,e.length-7,0)}function $e(e,r){let t=e.length,o=P[r-1]||[];for(let n of o)for(let s of o)n<9&&s<9||n<9&&s>t-9||n>t-9&&s<9||Xe(e,n,s)}function Ce(e,r){e[4*r+9][8]=!0}function Me(e,r,t){let o=e.length,n=0,s=-1,a=o-1;for(let i=o-1;i>0;i-=2)for(i===6&&i--;;){for(let c=0;c<2;c++)if(!r[a][i-c]){let u=n<t.length?t[n]:!1;e[a][i-c]=u,n++}if(a+=s,a<0||o<=a){a-=s,s=-s;break}}}function U(e,r,t){let o=e.length;for(let n=0;n<o;n++)for(let s=0;s<o;s++){if(r[n][s])continue;let a=!1;switch(t){case 0:a=(n+s)%2===0;break;case 1:a=n%2===0;break;case 2:a=s%3===0;break;case 3:a=(n+s)%3===0;break;case 4:a=(Math.floor(n/2)+Math.floor(s/3))%2===0;break;case 5:a=n*s%2+n*s%3===0;break;case 6:a=(n*s%2+n*s%3)%2===0;break;case 7:a=((n+s)%2+n*s%3)%2===0;break}a&&(e[n][s]=!e[n][s])}}function Ze(e){let r=e.length,t=0;for(let a=0;a<r;a++){let i=e[a][0],c=e[0][a],u=1,l=1;for(let d=1;d<r;d++)e[a][d]===i?u++:(u>=5&&(t+=3+(u-5)),i=e[a][d],u=1),e[d][a]===c?l++:(l>=5&&(t+=3+(l-5)),c=e[d][a],l=1);u>=5&&(t+=3+(u-5)),l>=5&&(t+=3+(l-5))}for(let a=0;a<r-1;a++)for(let i=0;i<r-1;i++){let c=e[a][i];e[a][i+1]===c&&e[a+1][i]===c&&e[a+1][i+1]===c&&(t+=3)}for(let a=0;a<r;a++){let i=0,c=0;for(let u=0;u<r;u++)i=i<<1&2047|(e[a][u]?1:0),u>=10&&(i===1488||i===93)&&(t+=40),c=c<<1&2047|(e[u][a]?1:0),u>=10&&(c===1488||c===93)&&(t+=40)}let o=0,n=r*r;for(let a=0;a<r;a++)for(let i=0;i<r;i++)e[a][i]&&o++;let s=Math.abs(Math.ceil(o*100/n/5)-10);return t+=s*10,t}function ye(e,r,t,o){let n=0,s=1/0;for(let a=0;a<8;a++){let i=e.map(u=>[...u]);U(i,r,a),o(i,t,a);let c=Ze(i);c<s&&(s=c,n=a)}return n}function W(e,r,t){let o=e.length,n=N[r]<<3|t,s=n<<10;for(let i=0;i<5;i++)s&1<<14-i&&(s^=1335<<4-i);let a=(n<<10|s)^21522;for(let i=0;i<15;i++){let c=(a>>14-i&1)===1;i<=5?e[8][i]=c:i===6?e[8][7]=c:i===7?e[8][8]=c:i===8?e[7][8]=c:e[5-(i-9)][8]=c,i<=6?e[o-1-i][8]=c:e[8][o-8+(i-7)]=c}}function xe(e,r){if(r<7)return;let t=e.length,o=Z[r-7];for(let n=0;n<18;n++){let s=(o>>n&1)===1,a=Math.floor(n/3),i=t-11+n%3;e[a][i]=s;let c=t-11+n%3,u=Math.floor(n/3);e[c][u]=s}}function Se(e,r){return N[e]<<3|r}function Re(e,r,t,o,n){let s=he(e),a=ge(e);pe(s),be(s),$e(s,e),Ce(s,e),Me(s,a,t);let i=n?s.map(u=>[...u]):void 0,c=o??ye(s,a,r,W);return U(s,a,c),W(s,r,c),xe(s,e),{matrix:s,mask:c,formatInfo:n?Se(r,c):void 0,unmaskedMatrix:i}}function j(e,r,t){return e<7&&r<7||e<7&&r>=t-7||e>=t-7&&r<7}function Ie(e){return[{x:0,y:0},{x:e-7,y:0},{x:0,y:e-7}]}function Ee(e,r){let o=Math.max(.1,Math.min(.3,r));return e*o}function Ke(e,r,t,o,n,s,a){let i=I[t]||I.square,c=i.renderSVG(e,r,7*a,o),u=i.renderSVG(e+a,r+a,5*a,s),l=i.renderSVG(e+2*a,r+2*a,3*a,n);return c+u+l}function Je(e,r,t,o){let n=o/2;if(e.includes("data:image/svg")||e.trim().startsWith("<svg")){let s=e;if(e.includes("data:image/svg")){let u=e.match(/data:image\/svg\+xml[^,]*,(.+)/);if(u)try{s=decodeURIComponent(u[1])}catch{return""}}let a=s.match(/viewBox=["']([^"']+)["']/),i=a?a[1]:"0 0 100 100",c=s.replace(/<\?xml[^>]*>|<svg[^>]*>|<\/svg>/gi,"");return`<g transform="translate(${r-n}, ${t-n})">
|
|
21
|
+
<svg width="${o}" height="${o}" viewBox="${i}">
|
|
22
|
+
${c}
|
|
23
|
+
</svg>
|
|
24
|
+
</g>`}else return`<image x="${r-n}" y="${t-n}" width="${o}" height="${o}" href="${e}" preserveAspectRatio="xMidYMid meet"/>`}function et(e,r,t,o,n){let s=e.matrixSize,a="",i=E[t]||E.classic;if(t==="classic"){a=`<path fill="${o}" d="`;for(let c=0;c<s;c++)for(let u=0;u<s;u++)if(e.modules[c][u]&&!j(c,u,s)){let l=u*r,d=c*r,f=n*r,m=(1-n)*r/2,h=l+m,g=d+m;a+=`M${h},${g}h${f}v${f}h${-f}z`}return a+='"/>',a}for(let c=0;c<s;c++)for(let u=0;u<s;u++)if(e.modules[c][u]&&!j(c,u,s)){let l=u*r,d=c*r,f=n*r,m=(1-n)*r/2,h=l+m,g=d+m,b={qrcode:e.modules,qrSize:s,row:c,col:u};a+=i.renderSVG(h,g,f,o,b)}return a}function Oe(e,r){let{size:t,margin:o,backgroundColor:n,eyes:s,pupils:a,dots:i}=r,c=t/e.matrixSize,u=r.border.shape==="none"?0:r.border.width,l=t+2*o+2*u,d=o+u,f=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${l} ${l}" width="${l}" height="${l}">`;if(f+=`<rect width="${l}" height="${l}" fill="${n}"/>`,r.border.shape!=="none"&&u>0){let $=L[r.border.shape];if($){let C={borderWidth:u,borderStyle:r.border.style};f+=$.renderSVG(0,0,l,r.border.color,C)}}r.border.shape!=="none"&&u>0&&(f+=`<rect x="${d}" y="${d}" width="${t}" height="${t}" fill="${n}"/>`),f+=`<g transform="translate(${d}, ${d})">`;let m=Ie(e.matrixSize),h="";for(let $ of m)h+=Ke($.x*c,$.y*c,s.shape,s.color,a.color,n,c);let g=et(e,c,i.shape,i.color,i.scale);f+=h+g+"</g>";let b="";if(r.logo){let $=Ee(e.matrixSize,r.logo.scale)*c,C=l/2;b=Je(r.logo.src,C,C,$)}return f+=b+"</svg>",f}function ve(e,r){let{margin:t,lightChar:o,darkChar:n}=r,s="",a=e.matrixSize+t*2;for(let i=0;i<t;i++)s+=o.repeat(a)+`
|
|
25
|
+
`;for(let i=0;i<e.matrixSize;i++){s+=o.repeat(t);for(let c=0;c<e.matrixSize;c++)s+=e.modules[i][c]?n:o;s+=o.repeat(t)+`
|
|
26
|
+
`}for(let i=0;i<t;i++)s+=o.repeat(a)+`
|
|
27
|
+
`;return s}var D=null,we=!1;async function tt(){if(D)return D;if(we)throw new Error("PNG generation in Node.js requires @resvg/resvg-js. Install with: npm install @resvg/resvg-js");we=!0;try{return D=(await import("@resvg/resvg-js")).Resvg,D}catch{throw new Error("PNG generation in Node.js requires @resvg/resvg-js. Install with: npm install @resvg/resvg-js")}}async function Pe(e,r){let{output:t,size:o,margin:n,border:s}=r,a=s.shape==="none"?0:s.width,i=o+2*n+2*a,c=await tt(),d=new c(e,{fitTo:{mode:"width",value:i}}).render().asPng(),f=Buffer.from(d);return t.type==="dataURL"?`data:image/png;base64,${f.toString("base64")}`:f}async function Ae(e,r){let{format:t,type:o}=r.output;return t==="svg"?o==="string"?e:`data:image/svg+xml;charset=utf-8,${encodeURIComponent(e)}`:await Pe(e,r)}function H(e){if(typeof e=="string")return e;switch(e.type){case"url":return rt(e.url);case"vcard":return nt(e.data);case"wifi":return ot(e.data);case"calendar":return st(e.data);case"email":return at(e.email,e.subject,e.body);case"sms":return it(e.phone,e.message);case"phone":return ct(e.phone)}}function rt(e){return!e.startsWith("http://")&&!e.startsWith("https://")?`https://${e}`:e}function nt(e){let r=["BEGIN:VCARD","VERSION:3.0",`FN:${e.name}`];if(e.phone&&r.push(`TEL:${e.phone}`),e.email&&r.push(`EMAIL:${e.email}`),e.organization&&r.push(`ORG:${e.organization}`),e.url&&r.push(`URL:${e.url}`),e.title&&r.push(`TITLE:${e.title}`),e.note&&r.push(`NOTE:${e.note}`),e.address){let{street:t,city:o,state:n,zip:s,country:a}=e.address,i=["","",t||"",o||"",n||"",s||"",a||""];r.push(`ADR:${i.join(";")}`)}return r.push("END:VCARD"),r.join(`
|
|
28
|
+
`)}function ot(e){let r=e.encryption||"WPA",t=e.hidden?"H:true;":"",o=Le(e.ssid),n=Le(e.password);return`WIFI:T:${r};S:${o};P:${n};${t};`}function Le(e){return e.replace(/([\\;,":])/g,"\\$1")}function st(e){let r=o=>(typeof o=="string"?new Date(o):o).toISOString().replace(/[-:]/g,"").split(".")[0]+"Z",t=["BEGIN:VCALENDAR","VERSION:2.0","BEGIN:VEVENT",`SUMMARY:${e.title}`,`DTSTART:${r(e.startDate)}`,`DTEND:${r(e.endDate)}`];return e.location&&t.push(`LOCATION:${e.location}`),e.description&&t.push(`DESCRIPTION:${e.description}`),t.push("END:VEVENT","END:VCALENDAR"),t.join(`
|
|
29
|
+
`)}function at(e,r,t){let o=`mailto:${e}`,n=[];return r&&n.push(`subject=${encodeURIComponent(r)}`),t&&n.push(`body=${encodeURIComponent(t)}`),n.length>0&&(o+=`?${n.join("&")}`),o}function it(e,r){return r?`sms:${e}:${r}`:`sms:${e}`}function ct(e){return`tel:${e}`}function ut(e,r){let t=[];for(let n of e)for(let s=7;s>=0;s--)t.push((n>>s&1)===1);let o=K[r-1];for(let n=0;n<o;n++)t.push(!1);return t}function Te(e,r){if(!e)throw new Error("QR Code input cannot be empty. Please provide text or structured content to encode.");let t=ue(e,r),o=y[t],n=k(e,o);if(n<1||n>10)throw new Error(`Input data is too large for QR code version 10. Data length: ${e.length} characters. Maximum capacity at EC level ${t}: ~${y[t][9]} bytes. Try reducing input length or removing logo for higher capacity.`);let s=ce(e,n,o[n-1]),a=Y[t][n-1],i=X[t][n-1],{dataBlocks:c,ecBlocks:u}=de(s,a,i),l=me(c,u),d=ut(l,n),{matrix:f,mask:m}=Re(n,t,d);return{version:n,matrixSize:R(n),modules:f,mask:m,errorCorrectionLevel:t}}async function lt(e,r){let t=H(e),o=se(r),n=Te(t,!!o.logo),s=Oe(n,o);return await Ae(s,o)}function ft(e,r){let t=H(e),o=ae(r),n=Te(t,!1);return ve(n,o)}export{te as BorderShape,re as BorderStyle,ee as DotShape,J as EyeFrameShape,v as QRValidationError,lt as genQrImage,ft as genQrText};
|
package/package.json
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tapple.io/qr-code-generator",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Lightweight QR code generator with ESM and CommonJS support",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist",
|
|
7
|
+
"README.md",
|
|
8
|
+
"LICENSE"
|
|
9
|
+
],
|
|
10
|
+
"main": "./dist/node.cjs",
|
|
11
|
+
"module": "./dist/node.mjs",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"browser": "./dist/browser.mjs",
|
|
17
|
+
"node": {
|
|
18
|
+
"import": "./dist/node.mjs",
|
|
19
|
+
"require": "./dist/node.cjs"
|
|
20
|
+
},
|
|
21
|
+
"default": "./dist/node.mjs"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"clean": "rm -rf dist",
|
|
26
|
+
"build": "npm run clean && npm run build:types && npm run build:bundle-types && npm run build:browser && npm run build:node-esm && npm run build:node-cjs",
|
|
27
|
+
"build:types": "node scripts/build-types.mjs",
|
|
28
|
+
"build:bundle-types": "node scripts/bundle-types.mjs",
|
|
29
|
+
"build:browser": "node scripts/build-browser.mjs",
|
|
30
|
+
"build:node-esm": "node scripts/build-node-esm.mjs",
|
|
31
|
+
"build:node-cjs": "node scripts/build-node-cjs.mjs",
|
|
32
|
+
"demo": "npm run build && npx serve . -l 8080",
|
|
33
|
+
"visual-preview": "npm run build && node scripts/visual-preview.mjs",
|
|
34
|
+
"test": "vitest run && npm run test:dist",
|
|
35
|
+
"test:fast": "vitest run",
|
|
36
|
+
"test:unit": "vitest run test/unit",
|
|
37
|
+
"test:integration": "vitest run test/integration",
|
|
38
|
+
"test:e2e": "vitest run test/e2e",
|
|
39
|
+
"test:dist": "npm run test:dist:node && npm run test:dist:browser",
|
|
40
|
+
"test:dist:node": "npm run build && vitest run test/dist/node-*.test.ts",
|
|
41
|
+
"test:dist:browser": "npm run build && playwright test test/dist/browser-e2e.test.ts",
|
|
42
|
+
"test:watch": "vitest",
|
|
43
|
+
"test:ui": "vitest --ui",
|
|
44
|
+
"lint": "eslint src/ test/",
|
|
45
|
+
"lint:fix": "eslint src/ --fix",
|
|
46
|
+
"format": "prettier --write src/",
|
|
47
|
+
"format:check": "prettier --check src/",
|
|
48
|
+
"preversion": "npm run format && npm test && npm run lint",
|
|
49
|
+
"version": "npm run build && git add -A dist",
|
|
50
|
+
"postversion": "git push --follow-tags",
|
|
51
|
+
"prepublishOnly": "npm run build"
|
|
52
|
+
},
|
|
53
|
+
"sideEffects": false,
|
|
54
|
+
"author": {
|
|
55
|
+
"name": "Tapple Inc.",
|
|
56
|
+
"url": "https://tapple.io"
|
|
57
|
+
},
|
|
58
|
+
"license": "MIT",
|
|
59
|
+
"keywords": [
|
|
60
|
+
"qr",
|
|
61
|
+
"qrcode",
|
|
62
|
+
"qr-code",
|
|
63
|
+
"generator",
|
|
64
|
+
"svg",
|
|
65
|
+
"png",
|
|
66
|
+
"ascii",
|
|
67
|
+
"browser",
|
|
68
|
+
"universal"
|
|
69
|
+
],
|
|
70
|
+
"repository": {
|
|
71
|
+
"type": "git",
|
|
72
|
+
"url": "https://github.com/tappleinc/qr-code-generator.git"
|
|
73
|
+
},
|
|
74
|
+
"bugs": {
|
|
75
|
+
"url": "https://github.com/tappleinc/qr-code-generator/issues"
|
|
76
|
+
},
|
|
77
|
+
"homepage": "https://github.com/tappleinc/qr-code-generator#readme",
|
|
78
|
+
"optionalDependencies": {
|
|
79
|
+
"@resvg/resvg-js": "^2.6.0"
|
|
80
|
+
},
|
|
81
|
+
"devDependencies": {
|
|
82
|
+
"@eslint/js": "^9.39.2",
|
|
83
|
+
"@nuintun/qrcode": "^5.0.2",
|
|
84
|
+
"@playwright/test": "^1.49.0",
|
|
85
|
+
"@types/node": "^25.0.3",
|
|
86
|
+
"@types/pngjs": "^6.0.5",
|
|
87
|
+
"@vitest/ui": "^4.0.16",
|
|
88
|
+
"dts-bundle-generator": "^9.5.1",
|
|
89
|
+
"esbuild": "^0.27.2",
|
|
90
|
+
"eslint": "^9.39.2",
|
|
91
|
+
"eslint-config-prettier": "^10.1.8",
|
|
92
|
+
"globals": "^16.5.0",
|
|
93
|
+
"jsqr": "^1.4.0",
|
|
94
|
+
"pngjs": "^7.0.0",
|
|
95
|
+
"prettier": "^3.7.4",
|
|
96
|
+
"tsx": "^4.19.0",
|
|
97
|
+
"typescript": "^5.3.0",
|
|
98
|
+
"typescript-eslint": "^8.51.0",
|
|
99
|
+
"vitest": "^4.0.16"
|
|
100
|
+
},
|
|
101
|
+
"engines": {
|
|
102
|
+
"node": ">=18.0.0"
|
|
103
|
+
}
|
|
104
|
+
}
|