uqr 0.1.1 → 0.1.3
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 +4 -2
- package/dist/index.cjs +31 -18
- package/dist/index.d.cts +161 -0
- package/dist/index.d.mts +161 -0
- package/dist/index.d.ts +35 -6
- package/dist/index.mjs +31 -18
- package/package.json +27 -30
package/README.md
CHANGED
|
@@ -111,6 +111,10 @@ import { renderSVG } from 'uqr'
|
|
|
111
111
|
const string = renderSVG(text, options)
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
+
## Alternatives
|
|
115
|
+
|
|
116
|
+
- [etiket](https://github.com/productdevbook/etiket) — Zero-dependency barcode & QR code SVG generator. 20+ formats (1D barcodes, QR, Data Matrix, PDF417, Aztec), styled QR codes with dot types/gradients/logos, tree-shakeable, CLI tool.
|
|
117
|
+
|
|
114
118
|
## Credits
|
|
115
119
|
|
|
116
120
|
QR Code generation algorithm is modified from [nayuki/QR-Code-generator](https://github.com/nayuki/QR-Code-generator/blob/master/typescript-javascript/qrcodegen.ts) by Project Nayuki.
|
|
@@ -128,8 +132,6 @@ CLI renders are inspired by [qrcode-terminal](https://github.com/gtanner/qrcode-
|
|
|
128
132
|
[npm-version-href]: https://npmjs.com/package/uqr
|
|
129
133
|
[npm-downloads-src]: https://img.shields.io/npm/dm/uqr?style=flat&colorA=18181B&colorB=F0DB4F
|
|
130
134
|
[npm-downloads-href]: https://npmjs.com/package/uqr
|
|
131
|
-
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/uqr/main?style=flat&colorA=18181B&colorB=F0DB4F
|
|
132
|
-
[codecov-href]: https://codecov.io/gh/unjs/uqr
|
|
133
135
|
[bundle-src]: https://img.shields.io/bundlephobia/minzip/uqr?style=flat&colorA=18181B&colorB=F0DB4F
|
|
134
136
|
[bundle-href]: https://bundlephobia.com/result?p=uqr
|
|
135
137
|
[license-src]: https://img.shields.io/github/license/unjs/uqr.svg?style=flat&colorA=18181B&colorB=F0DB4F
|
package/dist/index.cjs
CHANGED
|
@@ -20,8 +20,8 @@ const EccMap = {
|
|
|
20
20
|
Q: QUARTILE,
|
|
21
21
|
H: HIGH
|
|
22
22
|
};
|
|
23
|
-
const NUMERIC_REGEX =
|
|
24
|
-
const ALPHANUMERIC_REGEX = /^[A-Z0-9
|
|
23
|
+
const NUMERIC_REGEX = /^\d*$/;
|
|
24
|
+
const ALPHANUMERIC_REGEX = /^[A-Z0-9 $%*+./:-]*$/;
|
|
25
25
|
const ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
|
|
26
26
|
const MIN_VERSION = 1;
|
|
27
27
|
const MAX_VERSION = 40;
|
|
@@ -62,16 +62,12 @@ class QrCode {
|
|
|
62
62
|
constructor(version, ecc, dataCodewords, msk) {
|
|
63
63
|
this.version = version;
|
|
64
64
|
this.ecc = ecc;
|
|
65
|
-
// The modules of this QR Code (false = light, true = dark).
|
|
66
|
-
// Immutable after constructor finishes. Accessed through getModule().
|
|
67
|
-
this.modules = [];
|
|
68
|
-
this.types = [];
|
|
69
65
|
if (version < MIN_VERSION || version > MAX_VERSION)
|
|
70
66
|
throw new RangeError("Version value out of range");
|
|
71
67
|
if (msk < -1 || msk > 7)
|
|
72
68
|
throw new RangeError("Mask value out of range");
|
|
73
69
|
this.size = version * 4 + 17;
|
|
74
|
-
const row = Array.from({ length: this.size }
|
|
70
|
+
const row = Array.from({ length: this.size }).fill(false);
|
|
75
71
|
for (let i = 0; i < this.size; i++) {
|
|
76
72
|
this.modules.push(row.slice());
|
|
77
73
|
this.types.push(row.map(() => 0));
|
|
@@ -96,6 +92,18 @@ class QrCode {
|
|
|
96
92
|
this.applyMask(msk);
|
|
97
93
|
this.drawFormatBits(msk);
|
|
98
94
|
}
|
|
95
|
+
/* -- Fields -- */
|
|
96
|
+
// The width and height of this QR Code, measured in modules, between
|
|
97
|
+
// 21 and 177 (inclusive). This is equal to version * 4 + 17.
|
|
98
|
+
size;
|
|
99
|
+
// The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).
|
|
100
|
+
// Even if a QR Code is created with automatic masking requested (mask = -1),
|
|
101
|
+
// the resulting object still has a mask value between 0 and 7.
|
|
102
|
+
mask;
|
|
103
|
+
// The modules of this QR Code (false = light, true = dark).
|
|
104
|
+
// Immutable after constructor finishes. Accessed through getModule().
|
|
105
|
+
modules = [];
|
|
106
|
+
types = [];
|
|
99
107
|
/* -- Accessor methods -- */
|
|
100
108
|
// Returns the color of the module (pixel) at the given coordinates, which is false
|
|
101
109
|
// for light or true for dark. The top left corner has the coordinates (x=0, y=0).
|
|
@@ -342,8 +350,9 @@ class QrCode {
|
|
|
342
350
|
for (let y = 0; y < this.size - 1; y++) {
|
|
343
351
|
for (let x = 0; x < this.size - 1; x++) {
|
|
344
352
|
const color = this.modules[y][x];
|
|
345
|
-
if (color === this.modules[y][x + 1] && color === this.modules[y + 1][x] && color === this.modules[y + 1][x + 1])
|
|
353
|
+
if (color === this.modules[y][x + 1] && color === this.modules[y + 1][x] && color === this.modules[y + 1][x + 1]) {
|
|
346
354
|
result += PENALTY_N2;
|
|
355
|
+
}
|
|
347
356
|
}
|
|
348
357
|
}
|
|
349
358
|
let dark = 0;
|
|
@@ -551,8 +560,9 @@ function reedSolomonMultiply(x, y) {
|
|
|
551
560
|
return z;
|
|
552
561
|
}
|
|
553
562
|
function encodeSegments(segs, ecl, minVersion = 1, maxVersion = 40, mask = -1, boostEcl = true) {
|
|
554
|
-
if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7)
|
|
563
|
+
if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7) {
|
|
555
564
|
throw new RangeError("Invalid value");
|
|
565
|
+
}
|
|
556
566
|
let version;
|
|
557
567
|
let dataUsedBits;
|
|
558
568
|
for (version = minVersion; ; version++) {
|
|
@@ -671,7 +681,7 @@ function renderANSI(data, options = {}) {
|
|
|
671
681
|
});
|
|
672
682
|
}
|
|
673
683
|
function renderUnicodeCompact(data, options = {}) {
|
|
674
|
-
const
|
|
684
|
+
const palette = {
|
|
675
685
|
WHITE_ALL: "\u2588",
|
|
676
686
|
WHITE_BLACK: "\u2580",
|
|
677
687
|
BLACK_WHITE: "\u2584",
|
|
@@ -686,13 +696,13 @@ function renderUnicodeCompact(data, options = {}) {
|
|
|
686
696
|
for (let row = 0; row < result.size; row += 2) {
|
|
687
697
|
for (let col = 0; col < result.size; col++) {
|
|
688
698
|
if (at(col, row) === WHITE && at(col, row + 1) === WHITE)
|
|
689
|
-
line +=
|
|
699
|
+
line += palette.WHITE_ALL;
|
|
690
700
|
else if (at(col, row) === WHITE && at(col, row + 1) === BLACK)
|
|
691
|
-
line +=
|
|
701
|
+
line += palette.WHITE_BLACK;
|
|
692
702
|
else if (at(col, row) === BLACK && at(col, row + 1) === WHITE)
|
|
693
|
-
line +=
|
|
703
|
+
line += palette.BLACK_WHITE;
|
|
694
704
|
else
|
|
695
|
-
line +=
|
|
705
|
+
line += palette.BLACK_ALL;
|
|
696
706
|
}
|
|
697
707
|
lines.push(line);
|
|
698
708
|
line = "";
|
|
@@ -700,6 +710,9 @@ function renderUnicodeCompact(data, options = {}) {
|
|
|
700
710
|
return lines.join("\n");
|
|
701
711
|
}
|
|
702
712
|
|
|
713
|
+
function escapeAttr(value) {
|
|
714
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
715
|
+
}
|
|
703
716
|
function renderSVG(data, options = {}) {
|
|
704
717
|
const result = encode(data, options);
|
|
705
718
|
const {
|
|
@@ -710,17 +723,17 @@ function renderSVG(data, options = {}) {
|
|
|
710
723
|
const height = result.size * pixelSize;
|
|
711
724
|
const width = result.size * pixelSize;
|
|
712
725
|
let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}">`;
|
|
713
|
-
const
|
|
726
|
+
const paths = [];
|
|
714
727
|
for (let row = 0; row < result.size; row++) {
|
|
715
728
|
for (let col = 0; col < result.size; col++) {
|
|
716
729
|
const x = col * pixelSize;
|
|
717
730
|
const y = row * pixelSize;
|
|
718
731
|
if (result.data[row][col])
|
|
719
|
-
|
|
732
|
+
paths.push(`M${x},${y}h${pixelSize}v${pixelSize}h-${pixelSize}z`);
|
|
720
733
|
}
|
|
721
734
|
}
|
|
722
|
-
svg += `<rect fill="${whiteColor}" width="${width}" height="${height}"/>`;
|
|
723
|
-
svg += `<path fill="${blackColor}" d="${
|
|
735
|
+
svg += `<rect fill="${escapeAttr(whiteColor)}" width="${width}" height="${height}"/>`;
|
|
736
|
+
svg += `<path fill="${escapeAttr(blackColor)}" d="${paths.join("")}"/>`;
|
|
724
737
|
svg += "</svg>";
|
|
725
738
|
return svg;
|
|
726
739
|
}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* String or binary
|
|
3
|
+
*/
|
|
4
|
+
type QrCodeGenerateData = string | Readonly<Array<number>>;
|
|
5
|
+
interface QrCodeGenerateOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Error correction level
|
|
8
|
+
*
|
|
9
|
+
* L - Allows recovery of up to 7% data loss
|
|
10
|
+
* M - Allows recovery of up to 15% data loss
|
|
11
|
+
* Q - Allows recovery of up to 25% data loss
|
|
12
|
+
* H - Allows recovery of up to 30% data loss
|
|
13
|
+
*
|
|
14
|
+
* @default 'L'
|
|
15
|
+
*/
|
|
16
|
+
ecc?: 'L' | 'M' | 'Q' | 'H';
|
|
17
|
+
/**
|
|
18
|
+
* Mask pattern to use
|
|
19
|
+
*
|
|
20
|
+
* @default -1 (auto)
|
|
21
|
+
*/
|
|
22
|
+
maskPattern?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Boost the error correction level to the maximum allowed by the version and size
|
|
25
|
+
*/
|
|
26
|
+
boostEcc?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Minimum version of the QR code (1-40)
|
|
29
|
+
* @default 1
|
|
30
|
+
*/
|
|
31
|
+
minVersion?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Maximum version of the QR code (1-40)
|
|
34
|
+
* @default 40
|
|
35
|
+
*/
|
|
36
|
+
maxVersion?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Border around the QR code
|
|
39
|
+
*
|
|
40
|
+
* @default 1
|
|
41
|
+
*/
|
|
42
|
+
border?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Invert black and white
|
|
45
|
+
*/
|
|
46
|
+
invert?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Callback function to receive the generated QR Code
|
|
49
|
+
*/
|
|
50
|
+
onEncoded?: (qr: QrCodeGenerateResult) => void;
|
|
51
|
+
}
|
|
52
|
+
declare enum QrCodeDataType {
|
|
53
|
+
Border = -1,
|
|
54
|
+
Data = 0,
|
|
55
|
+
Function = 1,
|
|
56
|
+
Position = 2,
|
|
57
|
+
Timing = 3,
|
|
58
|
+
Alignment = 4
|
|
59
|
+
}
|
|
60
|
+
interface QrCodeGenerateResult {
|
|
61
|
+
/**
|
|
62
|
+
* QR Code version
|
|
63
|
+
*/
|
|
64
|
+
version: number;
|
|
65
|
+
/**
|
|
66
|
+
* Width and height of the QR Code array
|
|
67
|
+
*/
|
|
68
|
+
size: number;
|
|
69
|
+
/**
|
|
70
|
+
* Mask pattern used
|
|
71
|
+
*/
|
|
72
|
+
maskPattern: number;
|
|
73
|
+
/**
|
|
74
|
+
* Two dimensional array representing the QR Code
|
|
75
|
+
*
|
|
76
|
+
* `true` for black, `false` for white
|
|
77
|
+
*/
|
|
78
|
+
data: boolean[][];
|
|
79
|
+
/**
|
|
80
|
+
* Data type of each module
|
|
81
|
+
*/
|
|
82
|
+
types: QrCodeDataType[][];
|
|
83
|
+
}
|
|
84
|
+
interface QrCodeGenerateInvertableOptions extends QrCodeGenerateOptions {
|
|
85
|
+
/**
|
|
86
|
+
* Adds the option to invert the colour scheme of the QR code in addition to the standard options.
|
|
87
|
+
*/
|
|
88
|
+
invert?: boolean;
|
|
89
|
+
}
|
|
90
|
+
interface QrCodeGenerateUnicodeOptions extends QrCodeGenerateInvertableOptions {
|
|
91
|
+
/**
|
|
92
|
+
* Character used to represent white modules in the QR code.
|
|
93
|
+
*/
|
|
94
|
+
whiteChar?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Character used to represent black modules in the QR code.
|
|
97
|
+
*/
|
|
98
|
+
blackChar?: string;
|
|
99
|
+
}
|
|
100
|
+
interface QrCodeGenerateSvgOptions extends QrCodeGenerateOptions {
|
|
101
|
+
/**
|
|
102
|
+
* Size of each pixel
|
|
103
|
+
*
|
|
104
|
+
* @default 10
|
|
105
|
+
*/
|
|
106
|
+
pixelSize?: number;
|
|
107
|
+
/**
|
|
108
|
+
* Color of the white module
|
|
109
|
+
*
|
|
110
|
+
* @default 'white'
|
|
111
|
+
*/
|
|
112
|
+
whiteColor?: string;
|
|
113
|
+
/**
|
|
114
|
+
* Color of the black module
|
|
115
|
+
*
|
|
116
|
+
* @default 'black'
|
|
117
|
+
*/
|
|
118
|
+
blackColor?: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Encodes the given data into a QR code format according to the given options.
|
|
123
|
+
* @param {QrCodeGenerateData} data - The data to encode, either as a string or an array of bytes. See {@link QrCodeGenerateData}.
|
|
124
|
+
* @param {QrCodeGenerateOptions} [options] - QR Code generation configuration options. Optional. See {@link QrCodeGenerateOptions}.
|
|
125
|
+
* @returns {QrCodeGenerateResult} The result of the QR code generation, including the QR code matrix. See {@link QrCodeGenerateResult}.
|
|
126
|
+
*/
|
|
127
|
+
declare function encode(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): QrCodeGenerateResult;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Renders a QR code as a string using the specified Unicode characters for dark(`█`) and light(`░`) modules.
|
|
131
|
+
* @param {QrCodeGenerateData} data - The data to encode into the QR code. See {@link QrCodeGenerateData}.
|
|
132
|
+
* @param {QrCodeGenerateUnicodeOptions} [options] - Rendering options, including characters for white and black modules. optional. See {@link QrCodeGenerateUnicodeOptions}.
|
|
133
|
+
* Returns {string} A string representing the QR code, with each module replaced by the specified Unicode character.
|
|
134
|
+
*/
|
|
135
|
+
declare function renderUnicode(data: QrCodeGenerateData, options?: QrCodeGenerateUnicodeOptions): string;
|
|
136
|
+
/**
|
|
137
|
+
* Renders a QR code as a string suitable for display on terminals using ANSI background colours.
|
|
138
|
+
* @param {QrCodeGenerateData} data - The data to encode into the QR code. See {@link QrCodeGenerateData}.
|
|
139
|
+
* @param {QrCodeGenerateOptions} [options] - Options to render the QR code. optional. See {@link QrCodeGenerateOptions}.
|
|
140
|
+
* @returns {string} A string representing the QR code using ANSI colours, formatted for terminal display.
|
|
141
|
+
*/
|
|
142
|
+
declare function renderANSI(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): string;
|
|
143
|
+
/**
|
|
144
|
+
* Renders a QR code as a compact string using a combination of top half block(`▀`), bottom half block(`▄`), full block(`█`) and spaces to represent two lines in a single line.
|
|
145
|
+
* @param {QrCodeGenerateData} data - The data to encode into the QR code. See {@link QrCodeGenerateData}.
|
|
146
|
+
* @param {QrCodeGenerateOptions} [options] - Options to render the QR code in a compact form. optional. See {@link QrCodeGenerateOptions}.
|
|
147
|
+
* @returns {string} A string representing the QR code in a compact format, using Unicode block characters to combine two lines per line.
|
|
148
|
+
*/
|
|
149
|
+
declare function renderUnicodeCompact(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): string;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Renders a QR code as an SVG string.
|
|
153
|
+
* The function converts the input data into a QR code and then generates an SVG representation using the specified colours and pixel sizes.
|
|
154
|
+
* @param {QrCodeGenerateData} data - The data to encode into the QR code. See {@link QrCodeGenerateData}.
|
|
155
|
+
* @param {QrCodeGenerateSvgOptions} [options] - Options to render the QR code in SVG format, including pixel size and colours for modules. optional. See {@link QrCodeGenerateSvgOptions}.
|
|
156
|
+
* @returns {string} An SVG string representing the QR code.
|
|
157
|
+
*/
|
|
158
|
+
declare function renderSVG(data: QrCodeGenerateData, options?: QrCodeGenerateSvgOptions): string;
|
|
159
|
+
|
|
160
|
+
export { QrCodeDataType, encode, renderANSI, renderSVG, renderUnicode, renderUnicodeCompact };
|
|
161
|
+
export type { QrCodeGenerateData, QrCodeGenerateInvertableOptions, QrCodeGenerateOptions, QrCodeGenerateResult, QrCodeGenerateSvgOptions, QrCodeGenerateUnicodeOptions };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* String or binary
|
|
3
|
+
*/
|
|
4
|
+
type QrCodeGenerateData = string | Readonly<Array<number>>;
|
|
5
|
+
interface QrCodeGenerateOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Error correction level
|
|
8
|
+
*
|
|
9
|
+
* L - Allows recovery of up to 7% data loss
|
|
10
|
+
* M - Allows recovery of up to 15% data loss
|
|
11
|
+
* Q - Allows recovery of up to 25% data loss
|
|
12
|
+
* H - Allows recovery of up to 30% data loss
|
|
13
|
+
*
|
|
14
|
+
* @default 'L'
|
|
15
|
+
*/
|
|
16
|
+
ecc?: 'L' | 'M' | 'Q' | 'H';
|
|
17
|
+
/**
|
|
18
|
+
* Mask pattern to use
|
|
19
|
+
*
|
|
20
|
+
* @default -1 (auto)
|
|
21
|
+
*/
|
|
22
|
+
maskPattern?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Boost the error correction level to the maximum allowed by the version and size
|
|
25
|
+
*/
|
|
26
|
+
boostEcc?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Minimum version of the QR code (1-40)
|
|
29
|
+
* @default 1
|
|
30
|
+
*/
|
|
31
|
+
minVersion?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Maximum version of the QR code (1-40)
|
|
34
|
+
* @default 40
|
|
35
|
+
*/
|
|
36
|
+
maxVersion?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Border around the QR code
|
|
39
|
+
*
|
|
40
|
+
* @default 1
|
|
41
|
+
*/
|
|
42
|
+
border?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Invert black and white
|
|
45
|
+
*/
|
|
46
|
+
invert?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Callback function to receive the generated QR Code
|
|
49
|
+
*/
|
|
50
|
+
onEncoded?: (qr: QrCodeGenerateResult) => void;
|
|
51
|
+
}
|
|
52
|
+
declare enum QrCodeDataType {
|
|
53
|
+
Border = -1,
|
|
54
|
+
Data = 0,
|
|
55
|
+
Function = 1,
|
|
56
|
+
Position = 2,
|
|
57
|
+
Timing = 3,
|
|
58
|
+
Alignment = 4
|
|
59
|
+
}
|
|
60
|
+
interface QrCodeGenerateResult {
|
|
61
|
+
/**
|
|
62
|
+
* QR Code version
|
|
63
|
+
*/
|
|
64
|
+
version: number;
|
|
65
|
+
/**
|
|
66
|
+
* Width and height of the QR Code array
|
|
67
|
+
*/
|
|
68
|
+
size: number;
|
|
69
|
+
/**
|
|
70
|
+
* Mask pattern used
|
|
71
|
+
*/
|
|
72
|
+
maskPattern: number;
|
|
73
|
+
/**
|
|
74
|
+
* Two dimensional array representing the QR Code
|
|
75
|
+
*
|
|
76
|
+
* `true` for black, `false` for white
|
|
77
|
+
*/
|
|
78
|
+
data: boolean[][];
|
|
79
|
+
/**
|
|
80
|
+
* Data type of each module
|
|
81
|
+
*/
|
|
82
|
+
types: QrCodeDataType[][];
|
|
83
|
+
}
|
|
84
|
+
interface QrCodeGenerateInvertableOptions extends QrCodeGenerateOptions {
|
|
85
|
+
/**
|
|
86
|
+
* Adds the option to invert the colour scheme of the QR code in addition to the standard options.
|
|
87
|
+
*/
|
|
88
|
+
invert?: boolean;
|
|
89
|
+
}
|
|
90
|
+
interface QrCodeGenerateUnicodeOptions extends QrCodeGenerateInvertableOptions {
|
|
91
|
+
/**
|
|
92
|
+
* Character used to represent white modules in the QR code.
|
|
93
|
+
*/
|
|
94
|
+
whiteChar?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Character used to represent black modules in the QR code.
|
|
97
|
+
*/
|
|
98
|
+
blackChar?: string;
|
|
99
|
+
}
|
|
100
|
+
interface QrCodeGenerateSvgOptions extends QrCodeGenerateOptions {
|
|
101
|
+
/**
|
|
102
|
+
* Size of each pixel
|
|
103
|
+
*
|
|
104
|
+
* @default 10
|
|
105
|
+
*/
|
|
106
|
+
pixelSize?: number;
|
|
107
|
+
/**
|
|
108
|
+
* Color of the white module
|
|
109
|
+
*
|
|
110
|
+
* @default 'white'
|
|
111
|
+
*/
|
|
112
|
+
whiteColor?: string;
|
|
113
|
+
/**
|
|
114
|
+
* Color of the black module
|
|
115
|
+
*
|
|
116
|
+
* @default 'black'
|
|
117
|
+
*/
|
|
118
|
+
blackColor?: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Encodes the given data into a QR code format according to the given options.
|
|
123
|
+
* @param {QrCodeGenerateData} data - The data to encode, either as a string or an array of bytes. See {@link QrCodeGenerateData}.
|
|
124
|
+
* @param {QrCodeGenerateOptions} [options] - QR Code generation configuration options. Optional. See {@link QrCodeGenerateOptions}.
|
|
125
|
+
* @returns {QrCodeGenerateResult} The result of the QR code generation, including the QR code matrix. See {@link QrCodeGenerateResult}.
|
|
126
|
+
*/
|
|
127
|
+
declare function encode(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): QrCodeGenerateResult;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Renders a QR code as a string using the specified Unicode characters for dark(`█`) and light(`░`) modules.
|
|
131
|
+
* @param {QrCodeGenerateData} data - The data to encode into the QR code. See {@link QrCodeGenerateData}.
|
|
132
|
+
* @param {QrCodeGenerateUnicodeOptions} [options] - Rendering options, including characters for white and black modules. optional. See {@link QrCodeGenerateUnicodeOptions}.
|
|
133
|
+
* Returns {string} A string representing the QR code, with each module replaced by the specified Unicode character.
|
|
134
|
+
*/
|
|
135
|
+
declare function renderUnicode(data: QrCodeGenerateData, options?: QrCodeGenerateUnicodeOptions): string;
|
|
136
|
+
/**
|
|
137
|
+
* Renders a QR code as a string suitable for display on terminals using ANSI background colours.
|
|
138
|
+
* @param {QrCodeGenerateData} data - The data to encode into the QR code. See {@link QrCodeGenerateData}.
|
|
139
|
+
* @param {QrCodeGenerateOptions} [options] - Options to render the QR code. optional. See {@link QrCodeGenerateOptions}.
|
|
140
|
+
* @returns {string} A string representing the QR code using ANSI colours, formatted for terminal display.
|
|
141
|
+
*/
|
|
142
|
+
declare function renderANSI(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): string;
|
|
143
|
+
/**
|
|
144
|
+
* Renders a QR code as a compact string using a combination of top half block(`▀`), bottom half block(`▄`), full block(`█`) and spaces to represent two lines in a single line.
|
|
145
|
+
* @param {QrCodeGenerateData} data - The data to encode into the QR code. See {@link QrCodeGenerateData}.
|
|
146
|
+
* @param {QrCodeGenerateOptions} [options] - Options to render the QR code in a compact form. optional. See {@link QrCodeGenerateOptions}.
|
|
147
|
+
* @returns {string} A string representing the QR code in a compact format, using Unicode block characters to combine two lines per line.
|
|
148
|
+
*/
|
|
149
|
+
declare function renderUnicodeCompact(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): string;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Renders a QR code as an SVG string.
|
|
153
|
+
* The function converts the input data into a QR code and then generates an SVG representation using the specified colours and pixel sizes.
|
|
154
|
+
* @param {QrCodeGenerateData} data - The data to encode into the QR code. See {@link QrCodeGenerateData}.
|
|
155
|
+
* @param {QrCodeGenerateSvgOptions} [options] - Options to render the QR code in SVG format, including pixel size and colours for modules. optional. See {@link QrCodeGenerateSvgOptions}.
|
|
156
|
+
* @returns {string} An SVG string representing the QR code.
|
|
157
|
+
*/
|
|
158
|
+
declare function renderSVG(data: QrCodeGenerateData, options?: QrCodeGenerateSvgOptions): string;
|
|
159
|
+
|
|
160
|
+
export { QrCodeDataType, encode, renderANSI, renderSVG, renderUnicode, renderUnicodeCompact };
|
|
161
|
+
export type { QrCodeGenerateData, QrCodeGenerateInvertableOptions, QrCodeGenerateOptions, QrCodeGenerateResult, QrCodeGenerateSvgOptions, QrCodeGenerateUnicodeOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -82,17 +82,26 @@ interface QrCodeGenerateResult {
|
|
|
82
82
|
types: QrCodeDataType[][];
|
|
83
83
|
}
|
|
84
84
|
interface QrCodeGenerateInvertableOptions extends QrCodeGenerateOptions {
|
|
85
|
+
/**
|
|
86
|
+
* Adds the option to invert the colour scheme of the QR code in addition to the standard options.
|
|
87
|
+
*/
|
|
85
88
|
invert?: boolean;
|
|
86
89
|
}
|
|
87
90
|
interface QrCodeGenerateUnicodeOptions extends QrCodeGenerateInvertableOptions {
|
|
91
|
+
/**
|
|
92
|
+
* Character used to represent white modules in the QR code.
|
|
93
|
+
*/
|
|
88
94
|
whiteChar?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Character used to represent black modules in the QR code.
|
|
97
|
+
*/
|
|
89
98
|
blackChar?: string;
|
|
90
99
|
}
|
|
91
100
|
interface QrCodeGenerateSvgOptions extends QrCodeGenerateOptions {
|
|
92
101
|
/**
|
|
93
102
|
* Size of each pixel
|
|
94
103
|
*
|
|
95
|
-
* @default
|
|
104
|
+
* @default 10
|
|
96
105
|
*/
|
|
97
106
|
pixelSize?: number;
|
|
98
107
|
/**
|
|
@@ -109,24 +118,44 @@ interface QrCodeGenerateSvgOptions extends QrCodeGenerateOptions {
|
|
|
109
118
|
blackColor?: string;
|
|
110
119
|
}
|
|
111
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Encodes the given data into a QR code format according to the given options.
|
|
123
|
+
* @param {QrCodeGenerateData} data - The data to encode, either as a string or an array of bytes. See {@link QrCodeGenerateData}.
|
|
124
|
+
* @param {QrCodeGenerateOptions} [options] - QR Code generation configuration options. Optional. See {@link QrCodeGenerateOptions}.
|
|
125
|
+
* @returns {QrCodeGenerateResult} The result of the QR code generation, including the QR code matrix. See {@link QrCodeGenerateResult}.
|
|
126
|
+
*/
|
|
112
127
|
declare function encode(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): QrCodeGenerateResult;
|
|
113
128
|
|
|
114
129
|
/**
|
|
115
|
-
*
|
|
130
|
+
* Renders a QR code as a string using the specified Unicode characters for dark(`█`) and light(`░`) modules.
|
|
131
|
+
* @param {QrCodeGenerateData} data - The data to encode into the QR code. See {@link QrCodeGenerateData}.
|
|
132
|
+
* @param {QrCodeGenerateUnicodeOptions} [options] - Rendering options, including characters for white and black modules. optional. See {@link QrCodeGenerateUnicodeOptions}.
|
|
133
|
+
* Returns {string} A string representing the QR code, with each module replaced by the specified Unicode character.
|
|
116
134
|
*/
|
|
117
135
|
declare function renderUnicode(data: QrCodeGenerateData, options?: QrCodeGenerateUnicodeOptions): string;
|
|
118
136
|
/**
|
|
119
|
-
*
|
|
137
|
+
* Renders a QR code as a string suitable for display on terminals using ANSI background colours.
|
|
138
|
+
* @param {QrCodeGenerateData} data - The data to encode into the QR code. See {@link QrCodeGenerateData}.
|
|
139
|
+
* @param {QrCodeGenerateOptions} [options] - Options to render the QR code. optional. See {@link QrCodeGenerateOptions}.
|
|
140
|
+
* @returns {string} A string representing the QR code using ANSI colours, formatted for terminal display.
|
|
120
141
|
*/
|
|
121
142
|
declare function renderANSI(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): string;
|
|
122
143
|
/**
|
|
123
|
-
*
|
|
144
|
+
* Renders a QR code as a compact string using a combination of top half block(`▀`), bottom half block(`▄`), full block(`█`) and spaces to represent two lines in a single line.
|
|
145
|
+
* @param {QrCodeGenerateData} data - The data to encode into the QR code. See {@link QrCodeGenerateData}.
|
|
146
|
+
* @param {QrCodeGenerateOptions} [options] - Options to render the QR code in a compact form. optional. See {@link QrCodeGenerateOptions}.
|
|
147
|
+
* @returns {string} A string representing the QR code in a compact format, using Unicode block characters to combine two lines per line.
|
|
124
148
|
*/
|
|
125
149
|
declare function renderUnicodeCompact(data: QrCodeGenerateData, options?: QrCodeGenerateOptions): string;
|
|
126
150
|
|
|
127
151
|
/**
|
|
128
|
-
*
|
|
152
|
+
* Renders a QR code as an SVG string.
|
|
153
|
+
* The function converts the input data into a QR code and then generates an SVG representation using the specified colours and pixel sizes.
|
|
154
|
+
* @param {QrCodeGenerateData} data - The data to encode into the QR code. See {@link QrCodeGenerateData}.
|
|
155
|
+
* @param {QrCodeGenerateSvgOptions} [options] - Options to render the QR code in SVG format, including pixel size and colours for modules. optional. See {@link QrCodeGenerateSvgOptions}.
|
|
156
|
+
* @returns {string} An SVG string representing the QR code.
|
|
129
157
|
*/
|
|
130
158
|
declare function renderSVG(data: QrCodeGenerateData, options?: QrCodeGenerateSvgOptions): string;
|
|
131
159
|
|
|
132
|
-
export { QrCodeDataType,
|
|
160
|
+
export { QrCodeDataType, encode, renderANSI, renderSVG, renderUnicode, renderUnicodeCompact };
|
|
161
|
+
export type { QrCodeGenerateData, QrCodeGenerateInvertableOptions, QrCodeGenerateOptions, QrCodeGenerateResult, QrCodeGenerateSvgOptions, QrCodeGenerateUnicodeOptions };
|
package/dist/index.mjs
CHANGED
|
@@ -18,8 +18,8 @@ const EccMap = {
|
|
|
18
18
|
Q: QUARTILE,
|
|
19
19
|
H: HIGH
|
|
20
20
|
};
|
|
21
|
-
const NUMERIC_REGEX =
|
|
22
|
-
const ALPHANUMERIC_REGEX = /^[A-Z0-9
|
|
21
|
+
const NUMERIC_REGEX = /^\d*$/;
|
|
22
|
+
const ALPHANUMERIC_REGEX = /^[A-Z0-9 $%*+./:-]*$/;
|
|
23
23
|
const ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
|
|
24
24
|
const MIN_VERSION = 1;
|
|
25
25
|
const MAX_VERSION = 40;
|
|
@@ -60,16 +60,12 @@ class QrCode {
|
|
|
60
60
|
constructor(version, ecc, dataCodewords, msk) {
|
|
61
61
|
this.version = version;
|
|
62
62
|
this.ecc = ecc;
|
|
63
|
-
// The modules of this QR Code (false = light, true = dark).
|
|
64
|
-
// Immutable after constructor finishes. Accessed through getModule().
|
|
65
|
-
this.modules = [];
|
|
66
|
-
this.types = [];
|
|
67
63
|
if (version < MIN_VERSION || version > MAX_VERSION)
|
|
68
64
|
throw new RangeError("Version value out of range");
|
|
69
65
|
if (msk < -1 || msk > 7)
|
|
70
66
|
throw new RangeError("Mask value out of range");
|
|
71
67
|
this.size = version * 4 + 17;
|
|
72
|
-
const row = Array.from({ length: this.size }
|
|
68
|
+
const row = Array.from({ length: this.size }).fill(false);
|
|
73
69
|
for (let i = 0; i < this.size; i++) {
|
|
74
70
|
this.modules.push(row.slice());
|
|
75
71
|
this.types.push(row.map(() => 0));
|
|
@@ -94,6 +90,18 @@ class QrCode {
|
|
|
94
90
|
this.applyMask(msk);
|
|
95
91
|
this.drawFormatBits(msk);
|
|
96
92
|
}
|
|
93
|
+
/* -- Fields -- */
|
|
94
|
+
// The width and height of this QR Code, measured in modules, between
|
|
95
|
+
// 21 and 177 (inclusive). This is equal to version * 4 + 17.
|
|
96
|
+
size;
|
|
97
|
+
// The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).
|
|
98
|
+
// Even if a QR Code is created with automatic masking requested (mask = -1),
|
|
99
|
+
// the resulting object still has a mask value between 0 and 7.
|
|
100
|
+
mask;
|
|
101
|
+
// The modules of this QR Code (false = light, true = dark).
|
|
102
|
+
// Immutable after constructor finishes. Accessed through getModule().
|
|
103
|
+
modules = [];
|
|
104
|
+
types = [];
|
|
97
105
|
/* -- Accessor methods -- */
|
|
98
106
|
// Returns the color of the module (pixel) at the given coordinates, which is false
|
|
99
107
|
// for light or true for dark. The top left corner has the coordinates (x=0, y=0).
|
|
@@ -340,8 +348,9 @@ class QrCode {
|
|
|
340
348
|
for (let y = 0; y < this.size - 1; y++) {
|
|
341
349
|
for (let x = 0; x < this.size - 1; x++) {
|
|
342
350
|
const color = this.modules[y][x];
|
|
343
|
-
if (color === this.modules[y][x + 1] && color === this.modules[y + 1][x] && color === this.modules[y + 1][x + 1])
|
|
351
|
+
if (color === this.modules[y][x + 1] && color === this.modules[y + 1][x] && color === this.modules[y + 1][x + 1]) {
|
|
344
352
|
result += PENALTY_N2;
|
|
353
|
+
}
|
|
345
354
|
}
|
|
346
355
|
}
|
|
347
356
|
let dark = 0;
|
|
@@ -549,8 +558,9 @@ function reedSolomonMultiply(x, y) {
|
|
|
549
558
|
return z;
|
|
550
559
|
}
|
|
551
560
|
function encodeSegments(segs, ecl, minVersion = 1, maxVersion = 40, mask = -1, boostEcl = true) {
|
|
552
|
-
if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7)
|
|
561
|
+
if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7) {
|
|
553
562
|
throw new RangeError("Invalid value");
|
|
563
|
+
}
|
|
554
564
|
let version;
|
|
555
565
|
let dataUsedBits;
|
|
556
566
|
for (version = minVersion; ; version++) {
|
|
@@ -669,7 +679,7 @@ function renderANSI(data, options = {}) {
|
|
|
669
679
|
});
|
|
670
680
|
}
|
|
671
681
|
function renderUnicodeCompact(data, options = {}) {
|
|
672
|
-
const
|
|
682
|
+
const palette = {
|
|
673
683
|
WHITE_ALL: "\u2588",
|
|
674
684
|
WHITE_BLACK: "\u2580",
|
|
675
685
|
BLACK_WHITE: "\u2584",
|
|
@@ -684,13 +694,13 @@ function renderUnicodeCompact(data, options = {}) {
|
|
|
684
694
|
for (let row = 0; row < result.size; row += 2) {
|
|
685
695
|
for (let col = 0; col < result.size; col++) {
|
|
686
696
|
if (at(col, row) === WHITE && at(col, row + 1) === WHITE)
|
|
687
|
-
line +=
|
|
697
|
+
line += palette.WHITE_ALL;
|
|
688
698
|
else if (at(col, row) === WHITE && at(col, row + 1) === BLACK)
|
|
689
|
-
line +=
|
|
699
|
+
line += palette.WHITE_BLACK;
|
|
690
700
|
else if (at(col, row) === BLACK && at(col, row + 1) === WHITE)
|
|
691
|
-
line +=
|
|
701
|
+
line += palette.BLACK_WHITE;
|
|
692
702
|
else
|
|
693
|
-
line +=
|
|
703
|
+
line += palette.BLACK_ALL;
|
|
694
704
|
}
|
|
695
705
|
lines.push(line);
|
|
696
706
|
line = "";
|
|
@@ -698,6 +708,9 @@ function renderUnicodeCompact(data, options = {}) {
|
|
|
698
708
|
return lines.join("\n");
|
|
699
709
|
}
|
|
700
710
|
|
|
711
|
+
function escapeAttr(value) {
|
|
712
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
713
|
+
}
|
|
701
714
|
function renderSVG(data, options = {}) {
|
|
702
715
|
const result = encode(data, options);
|
|
703
716
|
const {
|
|
@@ -708,17 +721,17 @@ function renderSVG(data, options = {}) {
|
|
|
708
721
|
const height = result.size * pixelSize;
|
|
709
722
|
const width = result.size * pixelSize;
|
|
710
723
|
let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}">`;
|
|
711
|
-
const
|
|
724
|
+
const paths = [];
|
|
712
725
|
for (let row = 0; row < result.size; row++) {
|
|
713
726
|
for (let col = 0; col < result.size; col++) {
|
|
714
727
|
const x = col * pixelSize;
|
|
715
728
|
const y = row * pixelSize;
|
|
716
729
|
if (result.data[row][col])
|
|
717
|
-
|
|
730
|
+
paths.push(`M${x},${y}h${pixelSize}v${pixelSize}h-${pixelSize}z`);
|
|
718
731
|
}
|
|
719
732
|
}
|
|
720
|
-
svg += `<rect fill="${whiteColor}" width="${width}" height="${height}"/>`;
|
|
721
|
-
svg += `<path fill="${blackColor}" d="${
|
|
733
|
+
svg += `<rect fill="${escapeAttr(whiteColor)}" width="${width}" height="${height}"/>`;
|
|
734
|
+
svg += `<path fill="${escapeAttr(blackColor)}" d="${paths.join("")}"/>`;
|
|
722
735
|
svg += "</svg>";
|
|
723
736
|
return svg;
|
|
724
737
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uqr",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
5
|
-
"packageManager": "pnpm@8.6.12",
|
|
4
|
+
"version": "0.1.3",
|
|
6
5
|
"description": "Generate QR Code universally, in any runtime, to ANSI, Unicode or SVG.",
|
|
7
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
8
7
|
"license": "MIT",
|
|
@@ -16,7 +15,6 @@
|
|
|
16
15
|
"sideEffects": false,
|
|
17
16
|
"exports": {
|
|
18
17
|
".": {
|
|
19
|
-
"types": "./dist/index.d.ts",
|
|
20
18
|
"import": "./dist/index.mjs",
|
|
21
19
|
"require": "./dist/index.cjs"
|
|
22
20
|
}
|
|
@@ -35,38 +33,37 @@
|
|
|
35
33
|
"files": [
|
|
36
34
|
"dist"
|
|
37
35
|
],
|
|
38
|
-
"scripts": {
|
|
39
|
-
"build": "unbuild",
|
|
40
|
-
"dev": "unbuild --stub",
|
|
41
|
-
"lint": "eslint .",
|
|
42
|
-
"prepublishOnly": "nr build",
|
|
43
|
-
"release": "bumpp && npm publish",
|
|
44
|
-
"play": "esno play/run.ts",
|
|
45
|
-
"test": "vitest",
|
|
46
|
-
"typecheck": "tsc --noEmit"
|
|
47
|
-
},
|
|
48
36
|
"devDependencies": {
|
|
49
|
-
"@antfu/eslint-config": "^0.
|
|
50
|
-
"@antfu/ni": "^0.
|
|
51
|
-
"@antfu/utils": "^
|
|
52
|
-
"@types/node": "^
|
|
53
|
-
"bumpp": "^
|
|
54
|
-
"eslint": "^
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"typescript": "^
|
|
62
|
-
"unbuild": "^
|
|
63
|
-
"vite": "^
|
|
64
|
-
"vitest": "^
|
|
37
|
+
"@antfu/eslint-config": "^8.0.0",
|
|
38
|
+
"@antfu/ni": "^30.0.0",
|
|
39
|
+
"@antfu/utils": "^9.3.0",
|
|
40
|
+
"@types/node": "^25.5.0",
|
|
41
|
+
"bumpp": "^11.0.1",
|
|
42
|
+
"eslint": "^10.1.0",
|
|
43
|
+
"lint-staged": "^16.4.0",
|
|
44
|
+
"pnpm": "^10.33.0",
|
|
45
|
+
"rimraf": "^6.1.3",
|
|
46
|
+
"rollup": "^4.60.1",
|
|
47
|
+
"simple-git-hooks": "^2.13.1",
|
|
48
|
+
"tsx": "^4.21.0",
|
|
49
|
+
"typescript": "^6.0.2",
|
|
50
|
+
"unbuild": "^3.6.1",
|
|
51
|
+
"vite": "^8.0.3",
|
|
52
|
+
"vitest": "^4.1.2"
|
|
65
53
|
},
|
|
66
54
|
"simple-git-hooks": {
|
|
67
55
|
"pre-commit": "pnpm lint-staged"
|
|
68
56
|
},
|
|
69
57
|
"lint-staged": {
|
|
70
58
|
"*": "eslint --fix"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "unbuild",
|
|
62
|
+
"dev": "unbuild --stub",
|
|
63
|
+
"lint": "eslint .",
|
|
64
|
+
"release": "bumpp && npm publish",
|
|
65
|
+
"play": "tsx play/run.ts",
|
|
66
|
+
"test": "vitest",
|
|
67
|
+
"typecheck": "tsc --noEmit"
|
|
71
68
|
}
|
|
72
|
-
}
|
|
69
|
+
}
|