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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/core.js +48 -82
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "somdigi-qr-generator",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
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
- * Generate QR Buffer
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
- // 🔵 ROUNDED QR
28
- if (options.type === "rounded") {
29
- return this._rounded(options);
8
+ if (type === "default") {
9
+ return QRCode.toBuffer(data, { width: size, margin: 2 });
30
10
  }
31
11
 
32
- throw new Error("invalid type");
12
+ return this._rounded({ data, size, gradient, logo });
33
13
  }
34
14
 
35
- static async _rounded(options) {
36
- const rawSVG = await QRCode.toString(options.data, {
37
- type: "svg",
38
- errorCorrectionLevel: "H",
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
- const viewBox = rawSVG.match(/viewBox="([^"]+)"/)[1];
43
- const paths = rawSVG.match(/<path[^>]*>/g) || [];
20
+ const cells = qr.modules;
21
+ const count = cells.size;
22
+ const cellSize = 1;
44
23
 
45
- const useGradient = options.gradient?.length > 1;
46
- const fill = useGradient ? "url(#g)" : "#000";
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
- const defs = useGradient
49
- ? `
50
- <defs>
51
- <linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%">
52
- ${options.gradient
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
- const svg = `
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="${options.size ?? 512}"
83
- height="${options.size ?? 512}"
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
- ${logo}
59
+ ${dots.join("")}
60
+ ${logoSvg}
92
61
  </svg>`;
93
62
 
94
- return sharp(Buffer.from(svg))
95
- .png({
96
- background: "#ffffff"
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;