somdigi-qr-generator 1.0.6 → 1.0.7

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 +74 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "somdigi-qr-generator",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
package/src/core.js CHANGED
@@ -2,37 +2,89 @@ const QRCode = require("qrcode");
2
2
  const sharp = require("sharp");
3
3
 
4
4
  class QRGenerator {
5
- static async generate({ data, type = "default", size = 512, gradient, logo }) {
6
- if (!data) throw new Error("data required");
5
+ /**
6
+ * Generate QR Code (Buffer PNG)
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
+ if (!options.type || options.type === "default") {
20
+ return QRCode.toBuffer(options.data, {
21
+ width: options.size ?? 512,
22
+ margin: 2
23
+ });
24
+ }
7
25
 
8
- if (type === "default") {
9
- return QRCode.toBuffer(data, { width: size, margin: 2 });
26
+ if (options.type === "rounded") {
27
+ return this.#generateRounded(options);
10
28
  }
11
29
 
12
- return this._rounded({ data, size, gradient, logo });
30
+ throw new Error("invalid type");
13
31
  }
14
32
 
15
- static async _rounded({ data, size, gradient, logo }) {
33
+ // ===============================
34
+ // ROUNDED QR CORE
35
+ // ===============================
36
+ static async #generateRounded({
37
+ data,
38
+ size = 512,
39
+ gradient,
40
+ logo
41
+ }) {
16
42
  const qr = QRCode.create(data, {
17
43
  errorCorrectionLevel: "H"
18
44
  });
19
45
 
20
46
  const cells = qr.modules;
21
47
  const count = cells.size;
22
- const cellSize = 1;
23
48
 
49
+ const useGradient = Array.isArray(gradient) && gradient.length > 1;
50
+ const fill = useGradient ? "url(#g)" : "#000";
51
+
52
+ // --- helpers ---
53
+ const isFinder = (x, y) =>
54
+ (x < 7 && y < 7) ||
55
+ (x >= count - 7 && y < 7) ||
56
+ (x < 7 && y >= count - 7);
57
+
58
+ const renderFinder = (x, y) => `
59
+ <g>
60
+ <circle cx="${x + 3.5}" cy="${y + 3.5}" r="3.5" fill="${fill}"/>
61
+ <circle cx="${x + 3.5}" cy="${y + 3.5}" r="2.3" fill="#fff"/>
62
+ <circle cx="${x + 3.5}" cy="${y + 3.5}" r="1.3" fill="${fill}"/>
63
+ </g>
64
+ `;
65
+
66
+ // --- dots ---
24
67
  const dots = [];
25
68
  for (let y = 0; y < count; y++) {
26
69
  for (let x = 0; x < count; x++) {
27
70
  if (!cells.get(x, y)) continue;
71
+ if (isFinder(x, y)) continue;
28
72
 
29
73
  dots.push(
30
- `<circle cx="${x + 0.5}" cy="${y + 0.5}" r="0.45" fill="${gradient ? "url(#g)" : "#000"}"/>`
74
+ `<circle cx="${x + 0.5}" cy="${y + 0.5}" r="0.45" fill="${fill}"/>`
31
75
  );
32
76
  }
33
77
  }
34
78
 
35
- const defs = gradient
79
+ // --- finders ---
80
+ const finders = [
81
+ renderFinder(0, 0),
82
+ renderFinder(count - 7, 0),
83
+ renderFinder(0, count - 7)
84
+ ];
85
+
86
+ // --- gradient defs ---
87
+ const defs = useGradient
36
88
  ? `
37
89
  <defs>
38
90
  <linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%">
@@ -46,16 +98,27 @@ class QRGenerator {
46
98
  </defs>`
47
99
  : "";
48
100
 
101
+ // --- logo ---
49
102
  const logoSvg = logo
50
- ? `<image href="${logo}" x="35%" y="35%" width="30%" height="30%" />`
103
+ ? `
104
+ <image
105
+ href="${logo}"
106
+ x="35%" y="35%"
107
+ width="30%" height="30%"
108
+ preserveAspectRatio="xMidYMid meet"
109
+ />`
51
110
  : "";
52
111
 
112
+ // --- final svg ---
53
113
  const svg = `
54
114
  <svg xmlns="http://www.w3.org/2000/svg"
55
- width="${size}" height="${size}"
115
+ width="${size}"
116
+ height="${size}"
56
117
  viewBox="0 0 ${count} ${count}">
118
+
57
119
  <rect width="100%" height="100%" fill="#fff"/>
58
120
  ${defs}
121
+ ${finders.join("")}
59
122
  ${dots.join("")}
60
123
  ${logoSvg}
61
124
  </svg>`;