@qr-render/qrcode-cli 0.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 OctaEDLP00
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # QRCodeCLI
package/dist/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 OctaEDLP00
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/README.md ADDED
@@ -0,0 +1 @@
1
+ # QRCodeCLI
package/dist/cli.js ADDED
@@ -0,0 +1,839 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/libs/QRMath.ts
4
+ var QRMath = {
5
+ /**
6
+ *
7
+ * @param n
8
+ * @returns number
9
+ */
10
+ glog: (n) => {
11
+ if (n < 1) throw new Error(`glog(${n}): ${QRMath.glog(n)}`);
12
+ return LOG_TABLE[n];
13
+ },
14
+ /**
15
+ *
16
+ * @param n
17
+ * @returns number
18
+ */
19
+ gexp: (n) => {
20
+ while (n < 0) n += 255;
21
+ while (n >= 256) n -= 255;
22
+ return EXP_TABLE[n];
23
+ }
24
+ };
25
+ var EXP_TABLE = new Array(256);
26
+ var LOG_TABLE = new Array(256);
27
+ (function initTables() {
28
+ let x = 1;
29
+ for (let i = 0; i < 256; i++) {
30
+ EXP_TABLE[i] = x;
31
+ LOG_TABLE[x] = i;
32
+ x <<= 1;
33
+ if (x & 256) x ^= 285;
34
+ }
35
+ })();
36
+
37
+ // src/libs/QRPolynomial.ts
38
+ var QRPolynomial = class _QRPolynomial {
39
+ num;
40
+ /**
41
+ *
42
+ * @param num
43
+ * @param shift
44
+ */
45
+ constructor(num, shift) {
46
+ let offset = 0;
47
+ while (offset < num.length && num[offset] === 0) {
48
+ offset++;
49
+ }
50
+ this.num = new Array(num.length - offset + shift).fill(0);
51
+ for (let i = 0; i < num.length - offset; i++) {
52
+ this.num[i] = num[i + offset];
53
+ }
54
+ }
55
+ /**
56
+ *
57
+ * @param index
58
+ * @returns number
59
+ */
60
+ get(index) {
61
+ return this.num[index];
62
+ }
63
+ /**
64
+ *
65
+ * @returns number
66
+ */
67
+ getLength() {
68
+ return this.num.length;
69
+ }
70
+ /**
71
+ * Multiply the current polynomial by another.
72
+ * @param e
73
+ * @returns QRPolynomial
74
+ */
75
+ multiply(e) {
76
+ const num = new Array(this.getLength() + e.getLength() - 1).fill(0);
77
+ for (let i = 0; i < this.getLength(); i++) {
78
+ for (let j = 0; j < e.getLength(); j++) {
79
+ num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
80
+ }
81
+ }
82
+ return new _QRPolynomial(num, 0);
83
+ }
84
+ /**
85
+ * Calculate the remainder of the division (modulo) to obtain the correction bytes.
86
+ * @returns QRPolynomial
87
+ */
88
+ mod(e) {
89
+ if (this.getLength() - e.getLength() < 0) {
90
+ return this;
91
+ }
92
+ const ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0));
93
+ const num = [...this.num];
94
+ for (let i = 0; i < e.getLength(); i++) {
95
+ num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
96
+ }
97
+ return new _QRPolynomial(num, 0).mod(e);
98
+ }
99
+ };
100
+
101
+ // src/core/QRBitBuffer.ts
102
+ var QRBitBuffer = class {
103
+ buffer = [];
104
+ length = 0;
105
+ /**
106
+ *
107
+ * @param index
108
+ * @returns
109
+ */
110
+ get(index) {
111
+ const bufIndex = Math.floor(index / 8);
112
+ return (this.buffer[bufIndex] >>> 7 - index % 8 & 1) === 1;
113
+ }
114
+ /**
115
+ *
116
+ * @param num
117
+ * @param length
118
+ */
119
+ put(num, length) {
120
+ for (let i = 0; i < length; i++) {
121
+ this.putBit((num >>> length - i - 1 & 1) === 1);
122
+ }
123
+ }
124
+ /**
125
+ *
126
+ * @param bit
127
+ * @returns
128
+ */
129
+ putBit(bit) {
130
+ const bufIndex = Math.floor(this.length / 8);
131
+ if (this.buffer.length <= bufIndex) {
132
+ this.buffer.push(0);
133
+ }
134
+ if (bit) {
135
+ this.buffer[bufIndex] |= 128 >>> this.length % 8;
136
+ }
137
+ this.length++;
138
+ }
139
+ /**
140
+ *
141
+ * @returns
142
+ */
143
+ getLengthInBits() {
144
+ return this.length;
145
+ }
146
+ getBuffer() {
147
+ return this.buffer;
148
+ }
149
+ };
150
+
151
+ // src/core/QRRSBlock.ts
152
+ var QRRSBlock = class _QRRSBlock {
153
+ /**
154
+ *
155
+ * @param totalCount
156
+ * @param dataCount
157
+ */
158
+ constructor(totalCount, dataCount) {
159
+ this.totalCount = totalCount;
160
+ this.dataCount = dataCount;
161
+ }
162
+ /**
163
+ *
164
+ * @param typeNumber
165
+ * @param errorCorrectLevel
166
+ * @returns
167
+ */
168
+ static getRSBlocks(typeNumber, errorCorrectLevel) {
169
+ const rsBlock = _QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
170
+ if (!rsBlock)
171
+ throw new Error(
172
+ `bad rs block @ typeNumber:${typeNumber}/errorCorrectLevel:${errorCorrectLevel}`
173
+ );
174
+ const length = rsBlock.length / 3;
175
+ const list = [];
176
+ for (let i = 0; i < length; i++) {
177
+ const count = rsBlock[i * 3 + 0];
178
+ const totalCount = rsBlock[i * 3 + 1];
179
+ const dataCount = rsBlock[i * 3 + 2];
180
+ for (let j = 0; j < count; j++) {
181
+ list.push(new _QRRSBlock(totalCount, dataCount));
182
+ }
183
+ }
184
+ return list;
185
+ }
186
+ /**
187
+ *
188
+ * @param typeNumber
189
+ * @param errorCorrectLevel
190
+ * @returns
191
+ */
192
+ static getRsBlockTable(typeNumber, errorCorrectLevel) {
193
+ switch (errorCorrectLevel) {
194
+ case 1:
195
+ return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
196
+ // L
197
+ case 0:
198
+ return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
199
+ // M
200
+ case 3:
201
+ return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
202
+ // Q
203
+ case 2:
204
+ return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
205
+ }
206
+ return void 0;
207
+ }
208
+ };
209
+ var PATTERN_POSITION_TABLE = [
210
+ [],
211
+ [6, 18],
212
+ [6, 22],
213
+ [6, 26],
214
+ [6, 30],
215
+ [6, 34],
216
+ [6, 22, 38],
217
+ [6, 24, 42],
218
+ [6, 26, 46],
219
+ [6, 28, 50],
220
+ [6, 30, 54],
221
+ [6, 32, 58],
222
+ [6, 34, 62],
223
+ [6, 26, 46, 66],
224
+ [6, 26, 48, 70],
225
+ [6, 26, 50, 74],
226
+ [6, 30, 54, 78],
227
+ [6, 30, 56, 82],
228
+ [6, 30, 58, 86],
229
+ [6, 34, 62, 90],
230
+ [6, 28, 50, 72, 94],
231
+ [6, 26, 50, 74, 98],
232
+ [6, 30, 54, 78, 102],
233
+ [6, 28, 54, 80, 106],
234
+ [6, 32, 58, 84, 110],
235
+ [6, 30, 58, 86, 114],
236
+ [6, 34, 62, 90, 118],
237
+ [6, 26, 50, 74, 98, 122],
238
+ [6, 30, 54, 78, 102, 126],
239
+ [6, 26, 52, 78, 104, 130],
240
+ [6, 30, 56, 82, 108, 134],
241
+ [6, 34, 60, 86, 112, 138],
242
+ [6, 30, 58, 86, 114, 142],
243
+ [6, 34, 62, 90, 118, 146],
244
+ [6, 30, 54, 78, 102, 126, 150],
245
+ [6, 24, 50, 76, 102, 128, 154],
246
+ [6, 28, 54, 80, 106, 132, 158],
247
+ [6, 32, 58, 84, 110, 136, 162],
248
+ [6, 26, 54, 82, 110, 138, 166],
249
+ [6, 30, 58, 86, 114, 142, 170]
250
+ ];
251
+ var RS_BLOCK_TABLE = [
252
+ // Version 1
253
+ [1, 26, 19],
254
+ [1, 26, 16],
255
+ [1, 26, 13],
256
+ [1, 26, 9],
257
+ // Version 2
258
+ [1, 44, 34],
259
+ [1, 44, 28],
260
+ [1, 44, 22],
261
+ [1, 44, 16],
262
+ // Version 3
263
+ [1, 70, 55],
264
+ [1, 70, 44],
265
+ [2, 35, 17],
266
+ [2, 35, 13],
267
+ // Version 4
268
+ [1, 100, 80],
269
+ [2, 50, 32],
270
+ [2, 50, 24],
271
+ [4, 25, 9],
272
+ // Version 5
273
+ [1, 134, 108],
274
+ [2, 67, 43],
275
+ [2, 33, 15, 2, 34, 16],
276
+ [2, 33, 11, 2, 34, 12],
277
+ // Version 6
278
+ [2, 86, 68],
279
+ [4, 43, 27],
280
+ [4, 43, 19],
281
+ [4, 43, 15],
282
+ // Version 7
283
+ [2, 98, 78],
284
+ [4, 49, 31],
285
+ [2, 32, 14, 4, 33, 15],
286
+ [4, 39, 13, 1, 40, 14],
287
+ // Version 8
288
+ [2, 121, 97],
289
+ [2, 60, 38, 2, 61, 39],
290
+ [4, 40, 18, 2, 41, 19],
291
+ [4, 40, 14, 2, 41, 15],
292
+ // Version 9
293
+ [2, 146, 116],
294
+ [3, 58, 36, 2, 59, 37],
295
+ [4, 36, 16, 4, 37, 17],
296
+ [4, 36, 12, 4, 37, 13],
297
+ // Version 10
298
+ [2, 86, 68, 2, 87, 69],
299
+ [4, 69, 43, 1, 70, 44],
300
+ [6, 43, 19, 2, 44, 20],
301
+ [6, 43, 15, 2, 44, 16]
302
+ // ... Para un soporte completo hasta V40, esta tabla continua, pero V1-10 cubre el 99% de usos web.
303
+ ];
304
+
305
+ // src/core/QRCodeModel.ts
306
+ var QRCodeModel = class {
307
+ /**
308
+ *
309
+ * @param typeNumber
310
+ * @param errorCorrectLevel
311
+ */
312
+ constructor(typeNumber, errorCorrectLevel) {
313
+ this.typeNumber = typeNumber;
314
+ this.errorCorrectLevel = errorCorrectLevel;
315
+ this.moduleCount = 0;
316
+ }
317
+ moduleCount;
318
+ modules = [];
319
+ dataCache = null;
320
+ dataList = [];
321
+ /**
322
+ *
323
+ * @param data
324
+ */
325
+ addData(data) {
326
+ this.dataList.push(data);
327
+ this.dataCache = null;
328
+ }
329
+ /**
330
+ *
331
+ * @param row
332
+ * @param col
333
+ * @returns
334
+ */
335
+ isDark(row, col) {
336
+ if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) {
337
+ throw new Error(`Coordinates out of bounds: ${row},${col}`);
338
+ }
339
+ return this.modules[row][col] === true;
340
+ }
341
+ /**
342
+ *
343
+ * @returns
344
+ */
345
+ getModuleCount() {
346
+ return this.moduleCount;
347
+ }
348
+ /**
349
+ *
350
+ */
351
+ make() {
352
+ this.makeImpl(false, this.getBestMaskPattern());
353
+ }
354
+ /**
355
+ *
356
+ * @param test
357
+ * @param maskPattern
358
+ */
359
+ makeImpl(test, maskPattern) {
360
+ this.moduleCount = this.typeNumber * 4 + 17;
361
+ this.modules = Array.from(
362
+ { length: this.moduleCount },
363
+ () => new Array(this.moduleCount).fill(null)
364
+ );
365
+ this.setupPositionProbePattern(0, 0);
366
+ this.setupPositionProbePattern(this.moduleCount - 7, 0);
367
+ this.setupPositionProbePattern(0, this.moduleCount - 7);
368
+ this.setupPositionAdjustPattern();
369
+ this.setupTimingPattern();
370
+ this.setupTypeInfo(test, maskPattern);
371
+ if (this.typeNumber >= 7) {
372
+ this.setupTypeNumber(test);
373
+ }
374
+ if (this.dataCache == null) {
375
+ this.dataCache = this.createData(this.typeNumber, this.errorCorrectLevel, this.dataList);
376
+ }
377
+ this.mapData(this.dataCache, maskPattern);
378
+ }
379
+ /**
380
+ *
381
+ * @returns
382
+ */
383
+ getBestMaskPattern() {
384
+ let minPenalty = 0;
385
+ let bestPattern = 0;
386
+ for (let i = 0; i < 8; i++) {
387
+ this.makeImpl(true, i);
388
+ const penalty = this.getPenaltyScore();
389
+ if (i === 0 || penalty < minPenalty) {
390
+ minPenalty = penalty;
391
+ bestPattern = i;
392
+ }
393
+ }
394
+ return bestPattern;
395
+ }
396
+ /**
397
+ *
398
+ * @param row
399
+ * @param col
400
+ */
401
+ setupPositionProbePattern(row, col) {
402
+ for (let r = -1; r <= 7; r++) {
403
+ if (row + r <= -1 || this.moduleCount <= row + r) continue;
404
+ for (let c = -1; c <= 7; c++) {
405
+ if (col + c <= -1 || this.moduleCount <= col + c) continue;
406
+ if (0 <= r && r <= 6 && (c === 0 || c === 6) || 0 <= c && c <= 6 && (r === 0 || r === 6) || 2 <= r && r <= 4 && 2 <= c && c <= 4) {
407
+ this.modules[row + r][col + c] = true;
408
+ } else {
409
+ this.modules[row + r][col + c] = false;
410
+ }
411
+ }
412
+ }
413
+ }
414
+ /**
415
+ *
416
+ */
417
+ setupTimingPattern() {
418
+ for (let r = 8; r < this.moduleCount - 8; r++) {
419
+ if (this.modules[r][6] !== null) continue;
420
+ this.modules[r][6] = r % 2 === 0;
421
+ }
422
+ for (let c = 8; c < this.moduleCount - 8; c++) {
423
+ if (this.modules[6][c] !== null) continue;
424
+ this.modules[6][c] = c % 2 === 0;
425
+ }
426
+ }
427
+ /**
428
+ *
429
+ */
430
+ setupPositionAdjustPattern() {
431
+ const pos = QRUtil.getPatternPosition(this.typeNumber);
432
+ for (let i = 0; i < pos.length; i++) {
433
+ for (let j = 0; j < pos.length; j++) {
434
+ const row = pos[i];
435
+ const col = pos[j];
436
+ if (this.modules[row][col] !== null) continue;
437
+ for (let r = -2; r <= 2; r++) {
438
+ for (let c = -2; c <= 2; c++) {
439
+ if (r === -2 || r === 2 || c === -2 || c === 2 || r === 0 && c === 0) {
440
+ this.modules[row + r][col + c] = true;
441
+ } else {
442
+ this.modules[row + r][col + c] = false;
443
+ }
444
+ }
445
+ }
446
+ }
447
+ }
448
+ }
449
+ /**
450
+ *
451
+ * @param test
452
+ */
453
+ setupTypeNumber(test) {
454
+ const bits = QRUtil.getBCHTypeNumber(this.typeNumber);
455
+ for (let i = 0; i < 18; i++) {
456
+ const mod = !test && (bits >> i & 1) === 1;
457
+ this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
458
+ this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
459
+ }
460
+ }
461
+ /**
462
+ *
463
+ * @param test
464
+ * @param maskPattern
465
+ */
466
+ setupTypeInfo(test, maskPattern) {
467
+ const data = this.errorCorrectLevel << 3 | maskPattern;
468
+ const bits = QRUtil.getBCHTypeInfo(data);
469
+ for (let i = 0; i < 15; i++) {
470
+ const mod = !test && (bits >> i & 1) === 1;
471
+ if (i < 6) {
472
+ this.modules[i][8] = mod;
473
+ } else if (i < 8) {
474
+ this.modules[i + 1][8] = mod;
475
+ } else {
476
+ this.modules[this.moduleCount - 15 + i][8] = mod;
477
+ }
478
+ if (i < 8) {
479
+ this.modules[8][this.moduleCount - i - 1] = mod;
480
+ } else if (i < 9) {
481
+ this.modules[8][15 - i - 1 + 1] = mod;
482
+ } else {
483
+ this.modules[8][15 - i - 1] = mod;
484
+ }
485
+ }
486
+ this.modules[this.moduleCount - 8][8] = !test;
487
+ }
488
+ /**
489
+ *
490
+ * @param data
491
+ * @param maskPattern
492
+ */
493
+ mapData(data, maskPattern) {
494
+ let inc = -1;
495
+ let row = this.moduleCount - 1;
496
+ let bitIndex = 7;
497
+ let byteIndex = 0;
498
+ for (let col = this.moduleCount - 1; col > 0; col -= 2) {
499
+ if (col === 6) col--;
500
+ while (true) {
501
+ for (let c = 0; c < 2; c++) {
502
+ if (this.modules[row][col - c] === null) {
503
+ let dark = false;
504
+ if (byteIndex < data.length) {
505
+ dark = (data[byteIndex] >>> bitIndex & 1) === 1;
506
+ }
507
+ const mask = QRUtil.getMask(maskPattern, row, col - c);
508
+ if (mask) {
509
+ dark = !dark;
510
+ }
511
+ this.modules[row][col - c] = dark;
512
+ bitIndex--;
513
+ if (bitIndex === -1) {
514
+ byteIndex++;
515
+ bitIndex = 7;
516
+ }
517
+ }
518
+ }
519
+ row += inc;
520
+ if (row < 0 || this.moduleCount <= row) {
521
+ row -= inc;
522
+ inc = -inc;
523
+ break;
524
+ }
525
+ }
526
+ }
527
+ }
528
+ /**
529
+ *
530
+ * @param typeNumber
531
+ * @param errorCorrectLevel
532
+ * @param dataList
533
+ * @returns
534
+ */
535
+ createData(typeNumber, errorCorrectLevel, dataList) {
536
+ const rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
537
+ const buffer = new QRBitBuffer();
538
+ for (const data of dataList) {
539
+ buffer.put(4, 4);
540
+ buffer.put(data.length, QRUtil.getLengthInBits(4, typeNumber) || 8);
541
+ for (let i = 0; i < data.length; i++) {
542
+ buffer.put(data.charCodeAt(i), 8);
543
+ }
544
+ }
545
+ let totalDataCount = 0;
546
+ for (const block of rsBlocks) {
547
+ totalDataCount += block.dataCount;
548
+ }
549
+ if (buffer.getLengthInBits() > totalDataCount * 8) {
550
+ throw new Error(`Code length overflow. (${buffer.getLengthInBits()} > ${totalDataCount * 8})`);
551
+ }
552
+ if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
553
+ buffer.put(0, 4);
554
+ }
555
+ while (buffer.getLengthInBits() % 8 !== 0) {
556
+ buffer.putBit(false);
557
+ }
558
+ while (true) {
559
+ if (buffer.getLengthInBits() >= totalDataCount * 8) break;
560
+ buffer.put(236, 8);
561
+ if (buffer.getLengthInBits() >= totalDataCount * 8) break;
562
+ buffer.put(17, 8);
563
+ }
564
+ return this.createBytes(buffer, rsBlocks);
565
+ }
566
+ /**
567
+ *
568
+ * @param buffer
569
+ * @param rsBlocks
570
+ * @returns
571
+ */
572
+ createBytes(buffer, rsBlocks) {
573
+ let offset = 0;
574
+ let maxDcCount = 0;
575
+ let maxEcCount = 0;
576
+ const dcdata = new Array(rsBlocks.length);
577
+ const ecdata = new Array(rsBlocks.length);
578
+ for (let r = 0; r < rsBlocks.length; r++) {
579
+ const dcCount = rsBlocks[r].dataCount;
580
+ const ecCount = rsBlocks[r].totalCount - dcCount;
581
+ maxDcCount = Math.max(maxDcCount, dcCount);
582
+ maxEcCount = Math.max(maxEcCount, ecCount);
583
+ dcdata[r] = new Array(dcCount);
584
+ for (let i = 0; i < dcdata[r].length; i++) {
585
+ dcdata[r][i] = 255 & buffer.getBuffer()[i + offset];
586
+ }
587
+ offset += dcCount;
588
+ const rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
589
+ const rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
590
+ const modPoly = rawPoly.mod(rsPoly);
591
+ ecdata[r] = new Array(rsPoly.getLength() - 1);
592
+ for (let i = 0; i < ecdata[r].length; i++) {
593
+ const modIndex = i + modPoly.getLength() - ecdata[r].length;
594
+ ecdata[r][i] = modIndex >= 0 ? modPoly.get(modIndex) : 0;
595
+ }
596
+ }
597
+ let totalCodeCount = 0;
598
+ for (const block of rsBlocks) {
599
+ totalCodeCount += block.totalCount;
600
+ }
601
+ const data = new Array(totalCodeCount);
602
+ let index = 0;
603
+ for (let i = 0; i < maxDcCount; i++) {
604
+ for (let r = 0; r < rsBlocks.length; r++) {
605
+ if (i < dcdata[r].length) {
606
+ data[index++] = dcdata[r][i];
607
+ }
608
+ }
609
+ }
610
+ for (let i = 0; i < maxEcCount; i++) {
611
+ for (let r = 0; r < rsBlocks.length; r++) {
612
+ if (i < ecdata[r].length) {
613
+ data[index++] = ecdata[r][i];
614
+ }
615
+ }
616
+ }
617
+ return data;
618
+ }
619
+ /**
620
+ *
621
+ * @returns number
622
+ */
623
+ getPenaltyScore() {
624
+ let score = 0;
625
+ for (let row = 0; row < this.moduleCount; row++) {
626
+ for (let col = 0; col < this.moduleCount; col++) {
627
+ let sameCount = 0;
628
+ let dark = this.isDark(row, col);
629
+ for (let r = -1; r <= 1; r++) {
630
+ if (row + r < 0 || this.moduleCount <= row + r) continue;
631
+ for (let c = -1; c <= 1; c++) {
632
+ if (col + c < 0 || this.moduleCount <= col + c) continue;
633
+ if (r === 0 && c === 0) continue;
634
+ if (dark === this.isDark(row + r, col + c)) sameCount++;
635
+ }
636
+ }
637
+ if (sameCount > 5) score += 3 + sameCount - 5;
638
+ }
639
+ }
640
+ for (let row = 0; row < this.moduleCount - 1; row++) {
641
+ for (let col = 0; col < this.moduleCount - 1; col++) {
642
+ const count = (this.isDark(row, col) ? 1 : 0) + (this.isDark(row + 1, col) ? 1 : 0) + (this.isDark(row, col + 1) ? 1 : 0) + (this.isDark(row + 1, col + 1) ? 1 : 0);
643
+ if (count === 0 || count === 4) score += 3;
644
+ }
645
+ }
646
+ let darkCount = 0;
647
+ for (let row = 0; row < this.moduleCount; row++) {
648
+ for (let col = 0; col < this.moduleCount; col++) {
649
+ if (this.isDark(row, col)) darkCount++;
650
+ }
651
+ }
652
+ const ratio = Math.abs(100 * darkCount / this.moduleCount / this.moduleCount - 50) / 5;
653
+ score += ratio * 10;
654
+ return score;
655
+ }
656
+ };
657
+ var QRUtil = {
658
+ getBCHTypeInfo(data) {
659
+ let d = data << 10;
660
+ while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(1335) >= 0) {
661
+ d ^= 1335 << QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(1335);
662
+ }
663
+ return (data << 10 | d) ^ 21522;
664
+ },
665
+ getBCHTypeNumber(data) {
666
+ let d = data << 12;
667
+ while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(7973) >= 0) {
668
+ d ^= 7973 << QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(7973);
669
+ }
670
+ return data << 12 | d;
671
+ },
672
+ getBCHDigit(data) {
673
+ let digit = 0;
674
+ while (data !== 0) {
675
+ digit++;
676
+ data >>>= 1;
677
+ }
678
+ return digit;
679
+ },
680
+ getPatternPosition(typeNumber) {
681
+ return PATTERN_POSITION_TABLE[typeNumber - 1];
682
+ },
683
+ getMask(maskPattern, i, j) {
684
+ switch (maskPattern) {
685
+ case 0:
686
+ return (i + j) % 2 === 0;
687
+ case 1:
688
+ return i % 2 === 0;
689
+ case 2:
690
+ return j % 3 === 0;
691
+ case 3:
692
+ return (i + j) % 3 === 0;
693
+ case 4:
694
+ return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0;
695
+ case 5:
696
+ return i * j % 2 + i * j % 3 === 0;
697
+ case 6:
698
+ return (i * j % 2 + i * j % 3) % 2 === 0;
699
+ case 7:
700
+ return (i * j % 3 + (i + j) % 2) % 2 === 0;
701
+ default:
702
+ throw new Error(`bad maskPattern: ${maskPattern}`);
703
+ }
704
+ },
705
+ getErrorCorrectPolynomial(errorCorrectLength) {
706
+ let a = new QRPolynomial([1], 0);
707
+ for (let i = 0; i < errorCorrectLength; i++) {
708
+ a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
709
+ }
710
+ return a;
711
+ },
712
+ getLengthInBits(mode, type) {
713
+ if (1 <= type && type < 10) return 8;
714
+ if (type < 27) return 16;
715
+ if (type < 41) return 16;
716
+ return 0;
717
+ }
718
+ };
719
+
720
+ // src/renderer/ConsoleDrawing.ts
721
+ var ConsoleDrawing = class {
722
+ _options;
723
+ /**
724
+ * @param {Required<QRCodeOptionCLI>} vOption
725
+ */
726
+ constructor(vOption) {
727
+ this._options = vOption;
728
+ }
729
+ /**
730
+ * Draws the QR Code in the terminal using Unicode blocks.
731
+ * @param model
732
+ */
733
+ draw(model) {
734
+ const moduleCount = model.getModuleCount();
735
+ const { quietZone } = this._options;
736
+ const BG_BLACK = "\x1B[40m";
737
+ const BG_WHITE = "\x1B[47m";
738
+ const RESET = "\x1B[0m";
739
+ let output = "\n";
740
+ for (let r = -quietZone; r < moduleCount + quietZone; r++) {
741
+ let line = "";
742
+ for (let c = -quietZone; c < moduleCount + quietZone; c++) {
743
+ const isInside = r >= 0 && r < moduleCount && c >= 0 && c < moduleCount;
744
+ const isDark = isInside && model.isDark(r, c);
745
+ if (isDark) {
746
+ line += `${BG_BLACK} ${RESET}`;
747
+ } else {
748
+ line += `${BG_WHITE} ${RESET}`;
749
+ }
750
+ }
751
+ output += line + "\n";
752
+ }
753
+ process.stdout.write(output + "\n");
754
+ }
755
+ /**
756
+ * Clears the terminal screen.
757
+ */
758
+ clear() {
759
+ process.stdout.write("\x1B[2J\x1B[0f");
760
+ }
761
+ };
762
+
763
+ // src/types/index.d.ts
764
+ var QrErrorCorrectLevel = {
765
+ /**
766
+ * Low error correction.
767
+ * Allows up to ~7% data recovery.
768
+ */
769
+ L: 0,
770
+ /**
771
+ * Medium error correction.
772
+ * Allows up to ~15% data recovery.
773
+ */
774
+ M: 1,
775
+ /**
776
+ * Quartile error correction.
777
+ * Allows up to ~25% data recovery.
778
+ */
779
+ Q: 2,
780
+ /**
781
+ * High error correction.
782
+ * Allows up to ~30% data recovery.
783
+ */
784
+ H: 3
785
+ };
786
+
787
+ // src/cli.ts
788
+ import { Command } from "commander";
789
+ var getOptimalVersion = (data, level) => {
790
+ for (let v = 1; v <= 40; v++) {
791
+ try {
792
+ const testModel = new QRCodeModel(v, level);
793
+ testModel.addData(data);
794
+ testModel.make();
795
+ return v;
796
+ } catch (e) {
797
+ if (v === 40) throw new Error("Data too long for a standard QR Code.");
798
+ continue;
799
+ }
800
+ }
801
+ return 4;
802
+ };
803
+ var program = new Command();
804
+ program.name("qrx").description("Professional QR Code generation in your terminal").version("1.0.0");
805
+ program.argument("<text>", "Text or URL to encode").option("-s, --size <number>", "Scale factor (1, 2, 3...)", (v) => parseInt(v, 10), 1).option("-q, --quiet-zone <number>", "Quiet zone (padding)", (v) => parseInt(v, 10), 4).option("-l, --level <type>", "Error correction level (L, M, Q, H)", "M").option("--dark <color>", "ANSI for dark modules", "\x1B[40m \x1B[0m").option("--light <color>", "ANSI for light modules", "\x1B[47m \x1B[0m").action((text, options) => {
806
+ try {
807
+ const levelMap = {
808
+ L: QrErrorCorrectLevel.L,
809
+ M: QrErrorCorrectLevel.M,
810
+ Q: QrErrorCorrectLevel.Q,
811
+ H: QrErrorCorrectLevel.H
812
+ };
813
+ const selectedLevel = options.level.toUpperCase();
814
+ if (!(selectedLevel in levelMap)) {
815
+ throw new Error(`Invalid error level: ${options.level}. Use L, M, Q, or H.`);
816
+ }
817
+ const correctLevel = levelMap[selectedLevel] ?? "M";
818
+ const cliOptions = {
819
+ text,
820
+ quietZone: options.quietZone ?? 4,
821
+ correctLevel,
822
+ colorDark: options.dark,
823
+ colorLight: options.light,
824
+ size: options.size
825
+ };
826
+ const optimalVersion = getOptimalVersion(text, correctLevel);
827
+ const model = new QRCodeModel(optimalVersion, correctLevel);
828
+ model.addData(text);
829
+ model.make();
830
+ const terminal = new ConsoleDrawing(cliOptions);
831
+ terminal.draw(model);
832
+ } catch (error) {
833
+ const msg = error instanceof Error ? error.message : "Unknown error";
834
+ process.stderr.write(`\x1B[31m[ERROR]\x1B[0m ${msg}
835
+ `);
836
+ process.exit(1);
837
+ }
838
+ });
839
+ program.parse();
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@qr-render/qrcode-cli",
3
+ "version": "0.0.3",
4
+ "description": "",
5
+ "keywords": [
6
+ "builder",
7
+ "cli",
8
+ "installer",
9
+ "readline",
10
+ "typescript"
11
+ ],
12
+ "homepage": "https://github.com/OctaEDLP00/QrCodeCLI#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/OctaEDLP00/QrCodeCLI/issues"
15
+ },
16
+ "license": "MIT",
17
+ "author": "OctaEDLP00",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/OctaEDLP00/QrCodeCLI.git"
21
+ },
22
+ "bin": "dist/cli.js",
23
+ "files": [
24
+ "dist/cli.js",
25
+ "dist/README.md",
26
+ "dist/LICENSE",
27
+ "dist/package.json",
28
+ "dist/tsconfig.json"
29
+ ],
30
+ "type": "module",
31
+ "types": "./index.d.ts",
32
+ "scripts": {
33
+ "build": "tsup",
34
+ "lint": "oxlint src/**/*.ts",
35
+ "lint:fix": "oxlint src/**/*.ts --fix",
36
+ "fmt": "oxfmt",
37
+ "fmt:check": "oxfmt --check",
38
+ "prepublishOnly": "pnpm run build && pnpm run test:run && pnpm run lint",
39
+ "test": "vitest",
40
+ "test:coverage": "vitest run --coverage",
41
+ "test:run": "vitest run",
42
+ "test:ui": "vitest --ui",
43
+ "type-check": "tsc --noEmit"
44
+ },
45
+ "dependencies": {
46
+ "commander": "14.0.2"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "25.0.10",
50
+ "@vitest/coverage-v8": "4.0.18",
51
+ "@vitest/ui": "4.0.18",
52
+ "oxfmt": "^0.27.0",
53
+ "oxlint": "1.42.0",
54
+ "tsup": "8.5.1",
55
+ "tsx": "4.21.0",
56
+ "typescript": "5.9.3",
57
+ "vitest": "4.0.18"
58
+ },
59
+ "pnpm": {
60
+ "onlyBuiltDependencies": [
61
+ "esbuild"
62
+ ]
63
+ }
64
+ }
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@qr-render/qrcode-cli",
3
+ "version": "0.0.3",
4
+ "description": "",
5
+ "keywords": [
6
+ "builder",
7
+ "cli",
8
+ "installer",
9
+ "readline",
10
+ "typescript"
11
+ ],
12
+ "homepage": "https://github.com/OctaEDLP00/QrCodeCLI#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/OctaEDLP00/QrCodeCLI/issues"
15
+ },
16
+ "license": "MIT",
17
+ "author": "OctaEDLP00",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/OctaEDLP00/QrCodeCLI.git"
21
+ },
22
+ "bin": "dist/cli.js",
23
+ "files": [
24
+ "dist/cli.js",
25
+ "dist/README.md",
26
+ "dist/LICENSE",
27
+ "dist/package.json",
28
+ "dist/tsconfig.json"
29
+ ],
30
+ "type": "module",
31
+ "types": "./index.d.ts",
32
+ "dependencies": {
33
+ "commander": "14.0.2"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "25.0.10",
37
+ "@vitest/coverage-v8": "4.0.18",
38
+ "@vitest/ui": "4.0.18",
39
+ "oxfmt": "^0.27.0",
40
+ "oxlint": "1.42.0",
41
+ "tsup": "8.5.1",
42
+ "tsx": "4.21.0",
43
+ "typescript": "5.9.3",
44
+ "vitest": "4.0.18"
45
+ },
46
+ "scripts": {
47
+ "build": "tsup",
48
+ "lint": "oxlint src/**/*.ts",
49
+ "lint:fix": "oxlint src/**/*.ts --fix",
50
+ "fmt": "oxfmt",
51
+ "fmt:check": "oxfmt --check",
52
+ "test": "vitest",
53
+ "test:coverage": "vitest run --coverage",
54
+ "test:run": "vitest run",
55
+ "test:ui": "vitest --ui",
56
+ "type-check": "tsc --noEmit"
57
+ }
58
+ }