somdigi-qr-generator 1.0.4 → 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 +34 -60
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "somdigi-qr-generator",
3
- "version": "1.0.4",
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,93 +2,67 @@ 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
15
+ static async _rounded({ data, size, gradient, logo }) {
16
+ const qr = QRCode.create(data, {
17
+ errorCorrectionLevel: "H"
40
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 fill = options.gradient?.length
46
- ? "url(#g)"
47
- : "#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;
48
28
 
49
- const defs = options.gradient?.length
29
+ dots.push(
30
+ `<circle cx="${x + 0.5}" cy="${y + 0.5}" r="0.45" fill="${gradient ? "url(#g)" : "#000"}"/>`
31
+ );
32
+ }
33
+ }
34
+
35
+ const defs = gradient
50
36
  ? `
51
37
  <defs>
52
38
  <linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%">
53
- ${options.gradient
39
+ ${gradient
54
40
  .map(
55
41
  (c, i) =>
56
- `<stop offset="${(i / (options.gradient.length - 1)) * 100}%" stop-color="${c}" />`
42
+ `<stop offset="${(i / (gradient.length - 1)) * 100}%" stop-color="${c}"/>`
57
43
  )
58
44
  .join("")}
59
45
  </linearGradient>
60
46
  </defs>`
61
47
  : "";
62
48
 
63
- const dots = paths
64
- .map(p => {
65
- const m = p.match(/M(\d+) (\d+)/);
66
- if (!m) return "";
67
- return `<circle cx="${+m[1] + 0.5}" cy="${+m[2] + 0.5}" r="0.45" fill="${fill}" />`;
68
- })
69
- .join("");
70
-
71
- const logo = options.logo
72
- ? `
73
- <image
74
- href="${options.logo}"
75
- x="35%" y="35%"
76
- width="30%" height="30%"
77
- preserveAspectRatio="xMidYMid meet"
78
- />`
49
+ const logoSvg = logo
50
+ ? `<image href="${logo}" x="35%" y="35%" width="30%" height="30%" />`
79
51
  : "";
80
52
 
81
53
  const svg = `
82
54
  <svg xmlns="http://www.w3.org/2000/svg"
83
- width="${options.size ?? 512}"
84
- height="${options.size ?? 512}"
85
- viewBox="${viewBox}">
55
+ width="${size}" height="${size}"
56
+ viewBox="0 0 ${count} ${count}">
57
+ <rect width="100%" height="100%" fill="#fff"/>
86
58
  ${defs}
87
- ${dots}
88
- ${logo}
59
+ ${dots.join("")}
60
+ ${logoSvg}
89
61
  </svg>`;
90
62
 
91
- return sharp(Buffer.from(svg)).png().toBuffer();
63
+ return sharp(Buffer.from(svg))
64
+ .png({ background: "#fff" })
65
+ .toBuffer();
92
66
  }
93
67
  }
94
68