qr 0.4.2 → 0.5.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/README.md +18 -19
- package/decode.js +7 -11
- package/dom.js +16 -17
- package/index.js +17 -20
- package/package.json +18 -25
- package/src/decode.ts +897 -0
- package/src/dom.ts +352 -0
- package/src/index.ts +1261 -0
- package/esm/decode.d.ts +0 -62
- package/esm/decode.d.ts.map +0 -1
- package/esm/decode.js +0 -926
- package/esm/decode.js.map +0 -1
- package/esm/dom.d.ts +0 -102
- package/esm/dom.d.ts.map +0 -1
- package/esm/dom.js +0 -320
- package/esm/dom.js.map +0 -1
- package/esm/index.d.ts +0 -232
- package/esm/index.d.ts.map +0 -1
- package/esm/index.js +0 -1123
- package/esm/index.js.map +0 -1
- package/esm/package.json +0 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Minimal 0-dep QR code generator & reader.
|
|
|
6
6
|
- 🏞️ Encoding (generating) supports ASCII, term, gif and svg codes
|
|
7
7
|
- 📷 Decoding (reading) supports camera feed input, files and non-browser environments
|
|
8
8
|
- 🔍 Extensive tests ensure correctness: 100MB+ of vectors
|
|
9
|
-
- 🪶
|
|
9
|
+
- 🪶 14KB (gzipped) for encoding + decoding, 7KB for encoding
|
|
10
10
|
|
|
11
11
|
Check out:
|
|
12
12
|
|
|
@@ -43,7 +43,7 @@ A standalone file [qr.js](https://github.com/paulmillr/qr/releases) is also avai
|
|
|
43
43
|
```ts
|
|
44
44
|
import encodeQR from 'qr';
|
|
45
45
|
|
|
46
|
-
// import decodeQR from 'qr/decode';
|
|
46
|
+
// import decodeQR from 'qr/decode.js';
|
|
47
47
|
// See separate README section for decoding.
|
|
48
48
|
|
|
49
49
|
const txt = 'Hello world';
|
|
@@ -100,7 +100,7 @@ Decoding raw bitmap is still possible.
|
|
|
100
100
|
|
|
101
101
|
```js
|
|
102
102
|
import encodeQR from 'qr';
|
|
103
|
-
import decodeQR from 'qr/decode';
|
|
103
|
+
import decodeQR from 'qr/decode.js';
|
|
104
104
|
import { Bitmap } from 'qr';
|
|
105
105
|
|
|
106
106
|
// Scale so it would be 100x100 instead of 25x25
|
|
@@ -136,7 +136,7 @@ function decodeWithExternal() {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
// c) draw gif/svg to browser DOM canvas
|
|
139
|
-
import { svgToPng } from 'qr/dom';
|
|
139
|
+
import { svgToPng } from 'qr/dom.js';
|
|
140
140
|
const png = svgToPng(encodeQR('Hello world', 'svg'), 512, 512);
|
|
141
141
|
```
|
|
142
142
|
|
|
@@ -196,7 +196,7 @@ Check out `dom.ts` for browser-related camera code that would make your apps sim
|
|
|
196
196
|
## Using with Kotlin
|
|
197
197
|
|
|
198
198
|
```kotlin
|
|
199
|
-
@JsModule("
|
|
199
|
+
@JsModule("qr")
|
|
200
200
|
@JsNonModule
|
|
201
201
|
external object Qr {
|
|
202
202
|
@JsName("default")
|
|
@@ -238,23 +238,22 @@ Benchmarks measured with Apple M2 on MacOS 13 with node.js 19.
|
|
|
238
238
|
|
|
239
239
|
```
|
|
240
240
|
======== encode/ascii ========
|
|
241
|
-
encode/paulmillr
|
|
242
|
-
encode/qrcode-generator x
|
|
243
|
-
encode/nuintun x
|
|
241
|
+
encode/paulmillr x 2,995 ops/sec @ 333μs/op
|
|
242
|
+
encode/qrcode-generator x 6,029 ops/sec @ 165μs/op ± 1.39% (min: 142μs, max: 2ms)
|
|
243
|
+
encode/nuintun x 3,647 ops/sec @ 274μs/op
|
|
244
244
|
======== encode/gif ========
|
|
245
|
-
encode/paulmillr
|
|
246
|
-
encode/qrcode-generator x
|
|
247
|
-
encode/nuintun x
|
|
245
|
+
encode/paulmillr x 2,967 ops/sec @ 337μs/op
|
|
246
|
+
encode/qrcode-generator x 3,486 ops/sec @ 286μs/op
|
|
247
|
+
encode/nuintun x 3,643 ops/sec @ 274μs/op
|
|
248
248
|
======== encode: big ========
|
|
249
|
-
encode/paulmillr
|
|
250
|
-
encode/qrcode-generator x
|
|
251
|
-
encode/nuintun x
|
|
249
|
+
encode/paulmillr x 156 ops/sec @ 6ms/op
|
|
250
|
+
encode/qrcode-generator x 200 ops/sec @ 4ms/op
|
|
251
|
+
encode/nuintun x 223 ops/sec @ 4ms/op
|
|
252
252
|
======== decode ========
|
|
253
|
-
decode/paulmillr
|
|
254
|
-
decode/jsqr x
|
|
255
|
-
decode/nuintun x
|
|
256
|
-
decode/instascan x
|
|
257
|
-
======== Decoding quality ========
|
|
253
|
+
decode/paulmillr x 154 ops/sec @ 6ms/op ± 1.29% (min: 6ms, max: 18ms)
|
|
254
|
+
decode/jsqr x 52 ops/sec @ 18ms/op
|
|
255
|
+
decode/nuintun x 51 ops/sec @ 19ms/op
|
|
256
|
+
decode/instascan x 158 ops/sec @ 6ms/op ± 9.06% (min: 3ms, max: 144ms)======== Decoding quality ========
|
|
258
257
|
blurred(45): paulmillr-qr=12 (26.66%) jsqr=13 (28.88%) nuintun=13 (28.88%) instascan=11 (24.44%)
|
|
259
258
|
```
|
|
260
259
|
|
package/decode.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/*!
|
|
3
2
|
Copyright (c) 2023 Paul Miller (paulmillr.com)
|
|
4
3
|
The library paulmillr-qr is dual-licensed under the Apache 2.0 OR MIT license.
|
|
@@ -23,11 +22,8 @@ limitations under the License.
|
|
|
23
22
|
|
|
24
23
|
```
|
|
25
24
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
exports.decodeQR = decodeQR;
|
|
29
|
-
const index_ts_1 = require("./index.js");
|
|
30
|
-
const { best, bin, drawTemplate, fillArr, info, interleave, validateVersion, zigzag } = index_ts_1.utils;
|
|
25
|
+
import { Bitmap, utils } from "./index.js";
|
|
26
|
+
const { best, bin, drawTemplate, fillArr, info, interleave, validateVersion, zigzag } = utils;
|
|
31
27
|
// Constants
|
|
32
28
|
const MAX_BITS_ERROR = 3; // Up to 3 bit errors in version/format
|
|
33
29
|
const GRAYSCALE_BLOCK_SIZE = 8;
|
|
@@ -115,7 +111,7 @@ function toBitmap(img) {
|
|
|
115
111
|
blocks[bWidth * y + x] = int(average);
|
|
116
112
|
}
|
|
117
113
|
}
|
|
118
|
-
const matrix = new
|
|
114
|
+
const matrix = new Bitmap({ width: img.width, height: img.height });
|
|
119
115
|
for (let y = 0; y < bHeight; y++) {
|
|
120
116
|
const yPos = cap(y * block, 0, maxY);
|
|
121
117
|
const top = cap(y, 2, bHeight - 3);
|
|
@@ -660,7 +656,7 @@ function transform(b, size, from, to) {
|
|
|
660
656
|
];
|
|
661
657
|
const sToQ = squareToQuadrilateral(from);
|
|
662
658
|
const transform = sToQ.map((i) => i.map((_, qx) => i.reduce((acc, v, j) => acc + v * qToS[j][qx], 0)));
|
|
663
|
-
const res = new
|
|
659
|
+
const res = new Bitmap(size);
|
|
664
660
|
const points = fillArr(2 * size, 0);
|
|
665
661
|
const pointsLength = points.length;
|
|
666
662
|
for (let y = 0; y < size; y++) {
|
|
@@ -886,7 +882,7 @@ function cropToSquare(img) {
|
|
|
886
882
|
}
|
|
887
883
|
return { offset, img: { height: squareSize, width: squareSize, data: croppedData } };
|
|
888
884
|
}
|
|
889
|
-
function decodeQR(img, opts = {}) {
|
|
885
|
+
export function decodeQR(img, opts = {}) {
|
|
890
886
|
for (const field of ['height', 'width']) {
|
|
891
887
|
if (!Number.isSafeInteger(img[field]) || img[field] <= 0)
|
|
892
888
|
throw new Error(`invalid img.${field}=${img[field]} (${typeof img[field]})`);
|
|
@@ -919,9 +915,9 @@ function decodeQR(img, opts = {}) {
|
|
|
919
915
|
opts.imageOnResult(bits.toImage());
|
|
920
916
|
return res;
|
|
921
917
|
}
|
|
922
|
-
|
|
918
|
+
export default decodeQR;
|
|
923
919
|
// Unsafe API utils, exported only for tests
|
|
924
|
-
|
|
920
|
+
export const _tests = {
|
|
925
921
|
toBitmap,
|
|
926
922
|
decodeBitmap,
|
|
927
923
|
findFinder,
|
package/dom.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/*!
|
|
3
2
|
Copyright (c) 2023 Paul Miller (paulmillr.com)
|
|
4
3
|
The library paulmillr-qr is dual-licensed under the Apache 2.0 OR MIT license.
|
|
@@ -23,19 +22,13 @@ limitations under the License.
|
|
|
23
22
|
* The code is fragile: it is easy to make subtle errors, which will break decoding.
|
|
24
23
|
* @module
|
|
25
24
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
exports.frontalCamera = frontalCamera;
|
|
29
|
-
exports.frameLoop = frameLoop;
|
|
30
|
-
exports.svgToPng = svgToPng;
|
|
31
|
-
const decode_ts_1 = require("./decode.js");
|
|
32
|
-
const getSize = (elm) => {
|
|
25
|
+
import decodeQR, {} from "./decode.js";
|
|
26
|
+
export const getSize = (elm) => {
|
|
33
27
|
const css = getComputedStyle(elm);
|
|
34
28
|
const width = Math.floor(+css.width.split('px')[0]);
|
|
35
29
|
const height = Math.floor(+css.height.split('px')[0]);
|
|
36
30
|
return { width, height };
|
|
37
31
|
};
|
|
38
|
-
exports.getSize = getSize;
|
|
39
32
|
const setCanvasSize = (canvas, height, width) => {
|
|
40
33
|
// NOTE: setting canvas.width even to same size will clear & redraw it (flickering)
|
|
41
34
|
if (canvas.height !== height)
|
|
@@ -55,9 +48,14 @@ const clearCanvas = ({ canvas, context }) => {
|
|
|
55
48
|
/**
|
|
56
49
|
* Handles canvases for QR code decoding
|
|
57
50
|
*/
|
|
58
|
-
class QRCanvas {
|
|
51
|
+
export class QRCanvas {
|
|
52
|
+
opts;
|
|
53
|
+
lastDetect = 0;
|
|
54
|
+
main;
|
|
55
|
+
overlay;
|
|
56
|
+
bitmap;
|
|
57
|
+
resultQR;
|
|
59
58
|
constructor({ overlay, bitmap, resultQR } = {}, opts = {}) {
|
|
60
|
-
this.lastDetect = 0;
|
|
61
59
|
this.opts = {
|
|
62
60
|
resultBlockSize: 8,
|
|
63
61
|
overlayMainColor: 'green',
|
|
@@ -171,7 +169,7 @@ class QRCanvas {
|
|
|
171
169
|
if (this.resultQR)
|
|
172
170
|
options.imageOnResult = (img) => this.drawResultQr(img);
|
|
173
171
|
try {
|
|
174
|
-
const res = (
|
|
172
|
+
const res = decodeQR(data, options);
|
|
175
173
|
this.lastDetect = Date.now();
|
|
176
174
|
return res;
|
|
177
175
|
}
|
|
@@ -191,8 +189,9 @@ class QRCanvas {
|
|
|
191
189
|
clearCanvas(this.resultQR);
|
|
192
190
|
}
|
|
193
191
|
}
|
|
194
|
-
exports.QRCanvas = QRCanvas;
|
|
195
192
|
class QRCamera {
|
|
193
|
+
stream;
|
|
194
|
+
player;
|
|
196
195
|
constructor(stream, player) {
|
|
197
196
|
this.stream = stream;
|
|
198
197
|
this.player = player;
|
|
@@ -236,7 +235,7 @@ class QRCamera {
|
|
|
236
235
|
const { player } = this;
|
|
237
236
|
if (fullSize)
|
|
238
237
|
return canvas.drawImage(player, player.videoHeight, player.videoWidth);
|
|
239
|
-
const size =
|
|
238
|
+
const size = getSize(player);
|
|
240
239
|
return canvas.drawImage(player, size.height, size.width);
|
|
241
240
|
}
|
|
242
241
|
stop() {
|
|
@@ -254,7 +253,7 @@ class QRCamera {
|
|
|
254
253
|
* await camera.setDevice(devices[0].deviceId); // Change camera
|
|
255
254
|
* const res = camera.readFrame(canvas);
|
|
256
255
|
*/
|
|
257
|
-
async function frontalCamera(player) {
|
|
256
|
+
export async function frontalCamera(player) {
|
|
258
257
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
259
258
|
video: {
|
|
260
259
|
// Ask for screen resolution
|
|
@@ -274,7 +273,7 @@ async function frontalCamera(player) {
|
|
|
274
273
|
* const cancel = frameLoop((ns) => console.log(ns));
|
|
275
274
|
* cancel();
|
|
276
275
|
*/
|
|
277
|
-
function frameLoop(cb) {
|
|
276
|
+
export function frameLoop(cb) {
|
|
278
277
|
let handle = undefined;
|
|
279
278
|
function loop(ts) {
|
|
280
279
|
cb(ts);
|
|
@@ -288,7 +287,7 @@ function frameLoop(cb) {
|
|
|
288
287
|
handle = undefined;
|
|
289
288
|
};
|
|
290
289
|
}
|
|
291
|
-
function svgToPng(svgData, width, height) {
|
|
290
|
+
export function svgToPng(svgData, width, height) {
|
|
292
291
|
return new Promise((resolve, reject) => {
|
|
293
292
|
if (!(Number.isSafeInteger(width) &&
|
|
294
293
|
Number.isSafeInteger(height) &&
|
package/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/*!
|
|
3
2
|
Copyright (c) 2023 Paul Miller (paulmillr.com)
|
|
4
3
|
The library paulmillr-qr is dual-licensed under the Apache 2.0 OR MIT license.
|
|
@@ -15,24 +14,20 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
15
14
|
See the License for the specific language governing permissions and
|
|
16
15
|
limitations under the License.
|
|
17
16
|
*/
|
|
18
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports._tests = exports.utils = exports.Encoding = exports.ECMode = exports.Bitmap = void 0;
|
|
20
|
-
exports.utf8ToBytes = utf8ToBytes;
|
|
21
|
-
exports.encodeQR = encodeQR;
|
|
22
17
|
/**
|
|
23
18
|
* Methods for encoding (generating) QR code patterns.
|
|
24
19
|
* Check out decode.ts for decoding (reading).
|
|
25
20
|
* @module
|
|
26
21
|
* @example
|
|
27
22
|
```js
|
|
28
|
-
import encodeQR from '
|
|
23
|
+
import encodeQR from 'qr';
|
|
29
24
|
const txt = 'Hello world';
|
|
30
25
|
const ascii = encodeQR(txt, 'ascii'); // Not all fonts are supported
|
|
31
26
|
const terminalFriendly = encodeQR(txt, 'term'); // 2x larger, all fonts are OK
|
|
32
27
|
const gifBytes = encodeQR(txt, 'gif'); // Uncompressed GIF
|
|
33
28
|
const svgElement = encodeQR(txt, 'svg'); // SVG vector image element
|
|
34
29
|
const array = encodeQR(txt, 'raw'); // 2d array for canvas or other libs
|
|
35
|
-
// import decodeQR from '
|
|
30
|
+
// import decodeQR from 'qr/decode.js';
|
|
36
31
|
```
|
|
37
32
|
*/
|
|
38
33
|
// We do not use newline escape code directly in strings because it's not parser-friendly
|
|
@@ -125,7 +120,7 @@ function alphabet(alphabet) {
|
|
|
125
120
|
},
|
|
126
121
|
};
|
|
127
122
|
}
|
|
128
|
-
class Bitmap {
|
|
123
|
+
export class Bitmap {
|
|
129
124
|
static size(size, limit) {
|
|
130
125
|
if (typeof size === 'number')
|
|
131
126
|
size = { height: size, width: size };
|
|
@@ -168,6 +163,9 @@ class Bitmap {
|
|
|
168
163
|
width = 0;
|
|
169
164
|
return new Bitmap({ height, width }, data);
|
|
170
165
|
}
|
|
166
|
+
data;
|
|
167
|
+
height;
|
|
168
|
+
width;
|
|
171
169
|
constructor(size, data) {
|
|
172
170
|
const { height, width } = Bitmap.size(size);
|
|
173
171
|
this.data = data || Array.from({ length: height }, () => fillArr(width, undefined));
|
|
@@ -385,13 +383,12 @@ class Bitmap {
|
|
|
385
383
|
return { height, width, data };
|
|
386
384
|
}
|
|
387
385
|
}
|
|
388
|
-
exports.Bitmap = Bitmap;
|
|
389
386
|
// End of utils
|
|
390
387
|
// Runtime type-checking
|
|
391
388
|
/** Error correction mode. low: 7%, medium: 15%, quartile: 25%, high: 30% */
|
|
392
|
-
|
|
389
|
+
export const ECMode = ['low', 'medium', 'quartile', 'high'];
|
|
393
390
|
/** QR Code encoding */
|
|
394
|
-
|
|
391
|
+
export const Encoding = ['numeric', 'alphanumeric', 'byte', 'kanji', 'eci'];
|
|
395
392
|
// Various constants & tables
|
|
396
393
|
// prettier-ignore
|
|
397
394
|
const BYTES = [
|
|
@@ -886,7 +883,7 @@ function detectType(str) {
|
|
|
886
883
|
/**
|
|
887
884
|
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
|
|
888
885
|
*/
|
|
889
|
-
function utf8ToBytes(str) {
|
|
886
|
+
export function utf8ToBytes(str) {
|
|
890
887
|
if (typeof str !== 'string')
|
|
891
888
|
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
|
|
892
889
|
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
|
|
@@ -1036,12 +1033,12 @@ function drawQRBest(ver, ecc, data, maskIdx) {
|
|
|
1036
1033
|
return drawQR(ver, ecc, data, maskIdx);
|
|
1037
1034
|
}
|
|
1038
1035
|
function validateECC(ec) {
|
|
1039
|
-
if (!
|
|
1040
|
-
throw new Error(`Invalid error correction mode=${ec}. Expected: ${
|
|
1036
|
+
if (!ECMode.includes(ec))
|
|
1037
|
+
throw new Error(`Invalid error correction mode=${ec}. Expected: ${ECMode}`);
|
|
1041
1038
|
}
|
|
1042
1039
|
function validateEncoding(enc) {
|
|
1043
|
-
if (!
|
|
1044
|
-
throw new Error(`Encoding: invalid mode=${enc}. Expected: ${
|
|
1040
|
+
if (!Encoding.includes(enc))
|
|
1041
|
+
throw new Error(`Encoding: invalid mode=${enc}. Expected: ${Encoding}`);
|
|
1045
1042
|
if (enc === 'kanji' || enc === 'eci')
|
|
1046
1043
|
throw new Error(`Encoding: ${enc} is not supported (yet?).`);
|
|
1047
1044
|
}
|
|
@@ -1049,7 +1046,7 @@ function validateMask(mask) {
|
|
|
1049
1046
|
if (![0, 1, 2, 3, 4, 5, 6, 7].includes(mask) || !PATTERNS[mask])
|
|
1050
1047
|
throw new Error(`Invalid mask=${mask}. Expected number [0..7]`);
|
|
1051
1048
|
}
|
|
1052
|
-
function encodeQR(text, output = 'raw', opts = {}) {
|
|
1049
|
+
export function encodeQR(text, output = 'raw', opts = {}) {
|
|
1053
1050
|
const ecc = opts.ecc !== undefined ? opts.ecc : 'medium';
|
|
1054
1051
|
validateECC(ecc);
|
|
1055
1052
|
const encoding = opts.encoding !== undefined ? opts.encoding : detectType(text);
|
|
@@ -1099,8 +1096,8 @@ function encodeQR(text, output = 'raw', opts = {}) {
|
|
|
1099
1096
|
else
|
|
1100
1097
|
throw new Error(`Unknown output: ${output}`);
|
|
1101
1098
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1099
|
+
export default encodeQR;
|
|
1100
|
+
export const utils = {
|
|
1104
1101
|
best,
|
|
1105
1102
|
bin,
|
|
1106
1103
|
drawTemplate,
|
|
@@ -1111,7 +1108,7 @@ exports.utils = {
|
|
|
1111
1108
|
zigzag,
|
|
1112
1109
|
};
|
|
1113
1110
|
// Unsafe API utils, exported only for tests
|
|
1114
|
-
|
|
1111
|
+
export const _tests = {
|
|
1115
1112
|
Bitmap,
|
|
1116
1113
|
info,
|
|
1117
1114
|
detectType,
|
package/package.json
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Minimal 0-dep QR code generator & reader. Supports ascii, term, gif and svg formats",
|
|
5
5
|
"files": [
|
|
6
|
-
"esm",
|
|
7
6
|
"index.js",
|
|
8
7
|
"index.d.ts",
|
|
9
8
|
"index.d.ts.map",
|
|
@@ -16,17 +15,16 @@
|
|
|
16
15
|
"dom.d.ts",
|
|
17
16
|
"dom.d.ts.map",
|
|
18
17
|
"dom.ts",
|
|
18
|
+
"src",
|
|
19
19
|
"LICENSE",
|
|
20
20
|
"LICENSE-MIT"
|
|
21
21
|
],
|
|
22
|
-
"main": "index.js",
|
|
23
|
-
"module": "index.js",
|
|
24
|
-
"types": "index.d.ts",
|
|
25
22
|
"sideEffects": false,
|
|
26
23
|
"devDependencies": {
|
|
27
|
-
"@paulmillr/jsbt": "0.
|
|
24
|
+
"@paulmillr/jsbt": "0.4.1",
|
|
25
|
+
"@types/node": "22.15.23",
|
|
28
26
|
"micro-bmark": "0.4.1",
|
|
29
|
-
"micro-should": "0.5.
|
|
27
|
+
"micro-should": "0.5.3",
|
|
30
28
|
"prettier": "3.5.3",
|
|
31
29
|
"typescript": "5.8.3"
|
|
32
30
|
},
|
|
@@ -37,28 +35,23 @@
|
|
|
37
35
|
"type": "git",
|
|
38
36
|
"url": "git+https://github.com/paulmillr/qr.git"
|
|
39
37
|
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">= 20.19.0"
|
|
40
|
+
},
|
|
41
|
+
"type": "module",
|
|
42
|
+
"main": "index.js",
|
|
43
|
+
"module": "index.js",
|
|
44
|
+
"types": "index.d.ts",
|
|
40
45
|
"scripts": {
|
|
41
|
-
"build": "tsc
|
|
46
|
+
"build": "tsc",
|
|
42
47
|
"build:release": "npx jsbt esbuild test/build",
|
|
48
|
+
"bench": "cd test/benchmark && npm ci && node index.ts",
|
|
43
49
|
"lint": "prettier --check src",
|
|
44
50
|
"format": "prettier --write src",
|
|
45
|
-
"test": "cd test; npm ci; node index.
|
|
46
|
-
"test:bun": "cd test; bun install; bun index.
|
|
47
|
-
"test:deno": "cd test; npm install; deno --allow-env --allow-read index.
|
|
48
|
-
|
|
49
|
-
"exports": {
|
|
50
|
-
".": {
|
|
51
|
-
"import": "./esm/index.js",
|
|
52
|
-
"require": "./index.js"
|
|
53
|
-
},
|
|
54
|
-
"./decode.js": {
|
|
55
|
-
"import": "./esm/decode.js",
|
|
56
|
-
"require": "./decode.js"
|
|
57
|
-
},
|
|
58
|
-
"./dom.js": {
|
|
59
|
-
"import": "./esm/dom.js",
|
|
60
|
-
"require": "./dom.js"
|
|
61
|
-
}
|
|
51
|
+
"test": "cd test; npm ci; node --experimental-strip-types --no-warnings index.ts",
|
|
52
|
+
"test:bun": "cd test; bun install; bun index.ts",
|
|
53
|
+
"test:deno": "cd test; npm install; deno --allow-env --allow-read index.ts",
|
|
54
|
+
"test:node20": "cd test; npx tsc; cd compiled/test; npm install; node index.js"
|
|
62
55
|
},
|
|
63
56
|
"keywords": [
|
|
64
57
|
"qr",
|