somdigi-qr-generator 1.0.5 → 1.0.6
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/package.json +1 -1
- package/src/core.js +48 -82
package/package.json
CHANGED
package/src/core.js
CHANGED
|
@@ -2,102 +2,68 @@ const QRCode = require("qrcode");
|
|
|
2
2
|
const sharp = require("sharp");
|
|
3
3
|
|
|
4
4
|
class QRGenerator {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* @param {Object} options
|
|
8
|
-
* @param {string} options.data (required)
|
|
9
|
-
* @param {"default"|"rounded"} options.type
|
|
10
|
-
* @param {number} options.size
|
|
11
|
-
* @param {string[]} options.gradient
|
|
12
|
-
* @param {string} options.logo (url / base64)
|
|
13
|
-
*/
|
|
14
|
-
static async generate(options) {
|
|
15
|
-
if (!options || !options.data) {
|
|
16
|
-
throw new Error("data is required");
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// 🔵 DEFAULT QR (FASTEST)
|
|
20
|
-
if (!options.type || options.type === "default") {
|
|
21
|
-
return QRCode.toBuffer(options.data, {
|
|
22
|
-
width: options.size ?? 512,
|
|
23
|
-
margin: 2
|
|
24
|
-
});
|
|
25
|
-
}
|
|
5
|
+
static async generate({ data, type = "default", size = 512, gradient, logo }) {
|
|
6
|
+
if (!data) throw new Error("data required");
|
|
26
7
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return this._rounded(options);
|
|
8
|
+
if (type === "default") {
|
|
9
|
+
return QRCode.toBuffer(data, { width: size, margin: 2 });
|
|
30
10
|
}
|
|
31
11
|
|
|
32
|
-
|
|
12
|
+
return this._rounded({ data, size, gradient, logo });
|
|
33
13
|
}
|
|
34
14
|
|
|
35
|
-
static async _rounded(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
margin: 1
|
|
40
|
-
});
|
|
15
|
+
static async _rounded({ data, size, gradient, logo }) {
|
|
16
|
+
const qr = QRCode.create(data, {
|
|
17
|
+
errorCorrectionLevel: "H"
|
|
18
|
+
});
|
|
41
19
|
|
|
42
|
-
|
|
43
|
-
|
|
20
|
+
const cells = qr.modules;
|
|
21
|
+
const count = cells.size;
|
|
22
|
+
const cellSize = 1;
|
|
44
23
|
|
|
45
|
-
|
|
46
|
-
|
|
24
|
+
const dots = [];
|
|
25
|
+
for (let y = 0; y < count; y++) {
|
|
26
|
+
for (let x = 0; x < count; x++) {
|
|
27
|
+
if (!cells.get(x, y)) continue;
|
|
47
28
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
.map(
|
|
54
|
-
(c, i) =>
|
|
55
|
-
`<stop offset="${(i / (options.gradient.length - 1)) * 100}%" stop-color="${c}" />`
|
|
56
|
-
)
|
|
57
|
-
.join("")}
|
|
58
|
-
</linearGradient>
|
|
59
|
-
</defs>`
|
|
60
|
-
: "";
|
|
61
|
-
|
|
62
|
-
const dots = paths
|
|
63
|
-
.map(p => {
|
|
64
|
-
const m = p.match(/M(\d+) (\d+)/);
|
|
65
|
-
if (!m) return "";
|
|
66
|
-
return `<circle cx="${+m[1] + 0.5}" cy="${+m[2] + 0.5}" r="0.45" fill="${fill}" />`;
|
|
67
|
-
})
|
|
68
|
-
.join("");
|
|
69
|
-
|
|
70
|
-
const logo = options.logo
|
|
71
|
-
? `
|
|
72
|
-
<image
|
|
73
|
-
href="${options.logo}"
|
|
74
|
-
x="35%" y="35%"
|
|
75
|
-
width="30%" height="30%"
|
|
76
|
-
preserveAspectRatio="xMidYMid meet"
|
|
77
|
-
/>`
|
|
78
|
-
: "";
|
|
29
|
+
dots.push(
|
|
30
|
+
`<circle cx="${x + 0.5}" cy="${y + 0.5}" r="0.45" fill="${gradient ? "url(#g)" : "#000"}"/>`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
79
34
|
|
|
80
|
-
|
|
35
|
+
const defs = gradient
|
|
36
|
+
? `
|
|
37
|
+
<defs>
|
|
38
|
+
<linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
39
|
+
${gradient
|
|
40
|
+
.map(
|
|
41
|
+
(c, i) =>
|
|
42
|
+
`<stop offset="${(i / (gradient.length - 1)) * 100}%" stop-color="${c}"/>`
|
|
43
|
+
)
|
|
44
|
+
.join("")}
|
|
45
|
+
</linearGradient>
|
|
46
|
+
</defs>`
|
|
47
|
+
: "";
|
|
48
|
+
|
|
49
|
+
const logoSvg = logo
|
|
50
|
+
? `<image href="${logo}" x="35%" y="35%" width="30%" height="30%" />`
|
|
51
|
+
: "";
|
|
52
|
+
|
|
53
|
+
const svg = `
|
|
81
54
|
<svg xmlns="http://www.w3.org/2000/svg"
|
|
82
|
-
width="${
|
|
83
|
-
|
|
84
|
-
viewBox="${viewBox}">
|
|
85
|
-
|
|
86
|
-
<!-- BACKGROUND WAJIB -->
|
|
55
|
+
width="${size}" height="${size}"
|
|
56
|
+
viewBox="0 0 ${count} ${count}">
|
|
87
57
|
<rect width="100%" height="100%" fill="#fff"/>
|
|
88
|
-
|
|
89
58
|
${defs}
|
|
90
|
-
${dots}
|
|
91
|
-
${
|
|
59
|
+
${dots.join("")}
|
|
60
|
+
${logoSvg}
|
|
92
61
|
</svg>`;
|
|
93
62
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
.toBuffer();
|
|
99
|
-
}
|
|
100
|
-
|
|
63
|
+
return sharp(Buffer.from(svg))
|
|
64
|
+
.png({ background: "#fff" })
|
|
65
|
+
.toBuffer();
|
|
66
|
+
}
|
|
101
67
|
}
|
|
102
68
|
|
|
103
69
|
module.exports = QRGenerator;
|