@heybox/hb-sdk 0.3.3 → 0.4.1

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 (35) hide show
  1. package/README.md +63 -28
  2. package/dist/cli-chunks/browser-RAy8e8cV.cjs +635 -0
  3. package/dist/cli-chunks/create-Ds8A82lV.cjs +1376 -0
  4. package/dist/cli-chunks/deploy-D4uxwB2W.cjs +3730 -0
  5. package/dist/cli-chunks/dev-v-tcA7mM.cjs +955 -0
  6. package/dist/cli-chunks/doctor-C8NP7bow.cjs +186 -0
  7. package/dist/cli-chunks/index-BWrMUHh9.cjs +64023 -0
  8. package/dist/cli-chunks/index-DDqd9qAR.cjs +13348 -0
  9. package/dist/cli-chunks/login-BJVOo-hq.cjs +193 -0
  10. package/dist/cli-chunks/session-Iyxc2AGl.cjs +3040 -0
  11. package/dist/cli.cjs +19 -77707
  12. package/dist/devtools/mock-host/index.html +62 -2
  13. package/dist/devtools/mock-host/main.js +3246 -20
  14. package/dist/index.cjs.js +20 -0
  15. package/dist/index.esm.js +20 -0
  16. package/dist/miniapp-publish.cjs.js +2810 -4
  17. package/dist/miniapp-publish.esm.js +2809 -4
  18. package/dist/protocol.cjs.js +15 -0
  19. package/dist/protocol.esm.js +15 -1
  20. package/dist/templates/vue3-vite-ts/README.md.ejs +6 -2
  21. package/dist/vite.cjs.js +2814 -14
  22. package/dist/vite.esm.js +2814 -14
  23. package/package.json +6 -1
  24. package/skill/SKILL.md +19 -13
  25. package/skill/references/api-protocol.md +7 -2
  26. package/skill/references/api-root.md +24 -13
  27. package/skill/references/cli.md +339 -104
  28. package/skill/scripts/sync-references.mjs +17 -1
  29. package/skill/skill.json +4 -4
  30. package/types/index.d.ts +1 -1
  31. package/types/miniapp-manifest/schema.d.ts +2 -1
  32. package/types/miniapp-publish/index.d.ts +2 -1
  33. package/types/modules/viewport/index.d.ts +33 -0
  34. package/types/protocol/capabilities.d.ts +17 -2
  35. package/types/protocol.d.ts +2 -2
@@ -40,6 +40,13 @@ const SHARE_SCREENSHOT_METHOD = 'share.screenshot';
40
40
  * 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
41
41
  */
42
42
  const VIEWPORT_GET_WINDOW_INFO_METHOD = 'viewport.getWindowInfo';
43
+ /**
44
+ * 设置导航栏样式能力方法名。
45
+ *
46
+ * @remarks
47
+ * 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
48
+ */
49
+ const VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD = 'viewport.setNavigationBarStyle';
43
50
  /**
44
51
  * 读取小程序隔离 storage 能力方法名。
45
52
  *
@@ -103,6 +110,13 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
103
110
  permission: 'viewport.windowInfo',
104
111
  risk: 'low',
105
112
  },
113
+ {
114
+ method: VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD,
115
+ module: 'viewport',
116
+ capability: VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD,
117
+ permission: 'viewport.navigationBarStyle',
118
+ risk: 'low',
119
+ },
106
120
  {
107
121
  method: STORAGE_GET_STORAGE_METHOD,
108
122
  module: 'storage',
@@ -126,24 +140,3077 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
126
140
  },
127
141
  ];
128
142
 
129
- const MINI_PROGRAM_URL_QUERY_PARAM = 'mini_url';
130
- const MINI_PROGRAM_DEV_SHELL_URL = 'heybox-mini-dev://sandbox';
131
- function createMacAppProtocol(appUrl) {
132
- const devShellUrl = new URL(MINI_PROGRAM_DEV_SHELL_URL);
133
- devShellUrl.searchParams.set(MINI_PROGRAM_URL_QUERY_PARAM, appUrl);
134
- const protocolPayload = {
135
- protocol_type: 'openWindow',
136
- full_screen: true,
137
- mini_program: '1',
138
- webview: {
139
- url: devShellUrl.toString(),
140
- pull: false,
141
- refresh: false,
142
- },
143
- };
144
- return `heybox://${encodeURIComponent(JSON.stringify(protocolPayload))}`;
143
+ var browser = {};
144
+
145
+ var canPromise;
146
+ var hasRequiredCanPromise;
147
+
148
+ function requireCanPromise () {
149
+ if (hasRequiredCanPromise) return canPromise;
150
+ hasRequiredCanPromise = 1;
151
+ // can-promise has a crash in some versions of react native that dont have
152
+ // standard global objects
153
+ // https://github.com/soldair/node-qrcode/issues/157
154
+
155
+ canPromise = function () {
156
+ return typeof Promise === 'function' && Promise.prototype && Promise.prototype.then
157
+ };
158
+ return canPromise;
159
+ }
160
+
161
+ var qrcode = {};
162
+
163
+ var utils$1 = {};
164
+
165
+ var hasRequiredUtils$1;
166
+
167
+ function requireUtils$1 () {
168
+ if (hasRequiredUtils$1) return utils$1;
169
+ hasRequiredUtils$1 = 1;
170
+ let toSJISFunction;
171
+ const CODEWORDS_COUNT = [
172
+ 0, // Not used
173
+ 26, 44, 70, 100, 134, 172, 196, 242, 292, 346,
174
+ 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085,
175
+ 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185,
176
+ 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706
177
+ ];
178
+
179
+ /**
180
+ * Returns the QR Code size for the specified version
181
+ *
182
+ * @param {Number} version QR Code version
183
+ * @return {Number} size of QR code
184
+ */
185
+ utils$1.getSymbolSize = function getSymbolSize (version) {
186
+ if (!version) throw new Error('"version" cannot be null or undefined')
187
+ if (version < 1 || version > 40) throw new Error('"version" should be in range from 1 to 40')
188
+ return version * 4 + 17
189
+ };
190
+
191
+ /**
192
+ * Returns the total number of codewords used to store data and EC information.
193
+ *
194
+ * @param {Number} version QR Code version
195
+ * @return {Number} Data length in bits
196
+ */
197
+ utils$1.getSymbolTotalCodewords = function getSymbolTotalCodewords (version) {
198
+ return CODEWORDS_COUNT[version]
199
+ };
200
+
201
+ /**
202
+ * Encode data with Bose-Chaudhuri-Hocquenghem
203
+ *
204
+ * @param {Number} data Value to encode
205
+ * @return {Number} Encoded value
206
+ */
207
+ utils$1.getBCHDigit = function (data) {
208
+ let digit = 0;
209
+
210
+ while (data !== 0) {
211
+ digit++;
212
+ data >>>= 1;
213
+ }
214
+
215
+ return digit
216
+ };
217
+
218
+ utils$1.setToSJISFunction = function setToSJISFunction (f) {
219
+ if (typeof f !== 'function') {
220
+ throw new Error('"toSJISFunc" is not a valid function.')
221
+ }
222
+
223
+ toSJISFunction = f;
224
+ };
225
+
226
+ utils$1.isKanjiModeEnabled = function () {
227
+ return typeof toSJISFunction !== 'undefined'
228
+ };
229
+
230
+ utils$1.toSJIS = function toSJIS (kanji) {
231
+ return toSJISFunction(kanji)
232
+ };
233
+ return utils$1;
234
+ }
235
+
236
+ var errorCorrectionLevel = {};
237
+
238
+ var hasRequiredErrorCorrectionLevel;
239
+
240
+ function requireErrorCorrectionLevel () {
241
+ if (hasRequiredErrorCorrectionLevel) return errorCorrectionLevel;
242
+ hasRequiredErrorCorrectionLevel = 1;
243
+ (function (exports) {
244
+ exports.L = { bit: 1 };
245
+ exports.M = { bit: 0 };
246
+ exports.Q = { bit: 3 };
247
+ exports.H = { bit: 2 };
248
+
249
+ function fromString (string) {
250
+ if (typeof string !== 'string') {
251
+ throw new Error('Param is not a string')
252
+ }
253
+
254
+ const lcStr = string.toLowerCase();
255
+
256
+ switch (lcStr) {
257
+ case 'l':
258
+ case 'low':
259
+ return exports.L
260
+
261
+ case 'm':
262
+ case 'medium':
263
+ return exports.M
264
+
265
+ case 'q':
266
+ case 'quartile':
267
+ return exports.Q
268
+
269
+ case 'h':
270
+ case 'high':
271
+ return exports.H
272
+
273
+ default:
274
+ throw new Error('Unknown EC Level: ' + string)
275
+ }
276
+ }
277
+
278
+ exports.isValid = function isValid (level) {
279
+ return level && typeof level.bit !== 'undefined' &&
280
+ level.bit >= 0 && level.bit < 4
281
+ };
282
+
283
+ exports.from = function from (value, defaultValue) {
284
+ if (exports.isValid(value)) {
285
+ return value
286
+ }
287
+
288
+ try {
289
+ return fromString(value)
290
+ } catch (e) {
291
+ return defaultValue
292
+ }
293
+ };
294
+ } (errorCorrectionLevel));
295
+ return errorCorrectionLevel;
296
+ }
297
+
298
+ var bitBuffer;
299
+ var hasRequiredBitBuffer;
300
+
301
+ function requireBitBuffer () {
302
+ if (hasRequiredBitBuffer) return bitBuffer;
303
+ hasRequiredBitBuffer = 1;
304
+ function BitBuffer () {
305
+ this.buffer = [];
306
+ this.length = 0;
307
+ }
308
+
309
+ BitBuffer.prototype = {
310
+
311
+ get: function (index) {
312
+ const bufIndex = Math.floor(index / 8);
313
+ return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) === 1
314
+ },
315
+
316
+ put: function (num, length) {
317
+ for (let i = 0; i < length; i++) {
318
+ this.putBit(((num >>> (length - i - 1)) & 1) === 1);
319
+ }
320
+ },
321
+
322
+ getLengthInBits: function () {
323
+ return this.length
324
+ },
325
+
326
+ putBit: function (bit) {
327
+ const bufIndex = Math.floor(this.length / 8);
328
+ if (this.buffer.length <= bufIndex) {
329
+ this.buffer.push(0);
330
+ }
331
+
332
+ if (bit) {
333
+ this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
334
+ }
335
+
336
+ this.length++;
337
+ }
338
+ };
339
+
340
+ bitBuffer = BitBuffer;
341
+ return bitBuffer;
342
+ }
343
+
344
+ /**
345
+ * Helper class to handle QR Code symbol modules
346
+ *
347
+ * @param {Number} size Symbol size
348
+ */
349
+
350
+ var bitMatrix;
351
+ var hasRequiredBitMatrix;
352
+
353
+ function requireBitMatrix () {
354
+ if (hasRequiredBitMatrix) return bitMatrix;
355
+ hasRequiredBitMatrix = 1;
356
+ function BitMatrix (size) {
357
+ if (!size || size < 1) {
358
+ throw new Error('BitMatrix size must be defined and greater than 0')
359
+ }
360
+
361
+ this.size = size;
362
+ this.data = new Uint8Array(size * size);
363
+ this.reservedBit = new Uint8Array(size * size);
364
+ }
365
+
366
+ /**
367
+ * Set bit value at specified location
368
+ * If reserved flag is set, this bit will be ignored during masking process
369
+ *
370
+ * @param {Number} row
371
+ * @param {Number} col
372
+ * @param {Boolean} value
373
+ * @param {Boolean} reserved
374
+ */
375
+ BitMatrix.prototype.set = function (row, col, value, reserved) {
376
+ const index = row * this.size + col;
377
+ this.data[index] = value;
378
+ if (reserved) this.reservedBit[index] = true;
379
+ };
380
+
381
+ /**
382
+ * Returns bit value at specified location
383
+ *
384
+ * @param {Number} row
385
+ * @param {Number} col
386
+ * @return {Boolean}
387
+ */
388
+ BitMatrix.prototype.get = function (row, col) {
389
+ return this.data[row * this.size + col]
390
+ };
391
+
392
+ /**
393
+ * Applies xor operator at specified location
394
+ * (used during masking process)
395
+ *
396
+ * @param {Number} row
397
+ * @param {Number} col
398
+ * @param {Boolean} value
399
+ */
400
+ BitMatrix.prototype.xor = function (row, col, value) {
401
+ this.data[row * this.size + col] ^= value;
402
+ };
403
+
404
+ /**
405
+ * Check if bit at specified location is reserved
406
+ *
407
+ * @param {Number} row
408
+ * @param {Number} col
409
+ * @return {Boolean}
410
+ */
411
+ BitMatrix.prototype.isReserved = function (row, col) {
412
+ return this.reservedBit[row * this.size + col]
413
+ };
414
+
415
+ bitMatrix = BitMatrix;
416
+ return bitMatrix;
417
+ }
418
+
419
+ var alignmentPattern = {};
420
+
421
+ /**
422
+ * Alignment pattern are fixed reference pattern in defined positions
423
+ * in a matrix symbology, which enables the decode software to re-synchronise
424
+ * the coordinate mapping of the image modules in the event of moderate amounts
425
+ * of distortion of the image.
426
+ *
427
+ * Alignment patterns are present only in QR Code symbols of version 2 or larger
428
+ * and their number depends on the symbol version.
429
+ */
430
+
431
+ var hasRequiredAlignmentPattern;
432
+
433
+ function requireAlignmentPattern () {
434
+ if (hasRequiredAlignmentPattern) return alignmentPattern;
435
+ hasRequiredAlignmentPattern = 1;
436
+ (function (exports) {
437
+ const getSymbolSize = requireUtils$1().getSymbolSize;
438
+
439
+ /**
440
+ * Calculate the row/column coordinates of the center module of each alignment pattern
441
+ * for the specified QR Code version.
442
+ *
443
+ * The alignment patterns are positioned symmetrically on either side of the diagonal
444
+ * running from the top left corner of the symbol to the bottom right corner.
445
+ *
446
+ * Since positions are simmetrical only half of the coordinates are returned.
447
+ * Each item of the array will represent in turn the x and y coordinate.
448
+ * @see {@link getPositions}
449
+ *
450
+ * @param {Number} version QR Code version
451
+ * @return {Array} Array of coordinate
452
+ */
453
+ exports.getRowColCoords = function getRowColCoords (version) {
454
+ if (version === 1) return []
455
+
456
+ const posCount = Math.floor(version / 7) + 2;
457
+ const size = getSymbolSize(version);
458
+ const intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2;
459
+ const positions = [size - 7]; // Last coord is always (size - 7)
460
+
461
+ for (let i = 1; i < posCount - 1; i++) {
462
+ positions[i] = positions[i - 1] - intervals;
463
+ }
464
+
465
+ positions.push(6); // First coord is always 6
466
+
467
+ return positions.reverse()
468
+ };
469
+
470
+ /**
471
+ * Returns an array containing the positions of each alignment pattern.
472
+ * Each array's element represent the center point of the pattern as (x, y) coordinates
473
+ *
474
+ * Coordinates are calculated expanding the row/column coordinates returned by {@link getRowColCoords}
475
+ * and filtering out the items that overlaps with finder pattern
476
+ *
477
+ * @example
478
+ * For a Version 7 symbol {@link getRowColCoords} returns values 6, 22 and 38.
479
+ * The alignment patterns, therefore, are to be centered on (row, column)
480
+ * positions (6,22), (22,6), (22,22), (22,38), (38,22), (38,38).
481
+ * Note that the coordinates (6,6), (6,38), (38,6) are occupied by finder patterns
482
+ * and are not therefore used for alignment patterns.
483
+ *
484
+ * let pos = getPositions(7)
485
+ * // [[6,22], [22,6], [22,22], [22,38], [38,22], [38,38]]
486
+ *
487
+ * @param {Number} version QR Code version
488
+ * @return {Array} Array of coordinates
489
+ */
490
+ exports.getPositions = function getPositions (version) {
491
+ const coords = [];
492
+ const pos = exports.getRowColCoords(version);
493
+ const posLength = pos.length;
494
+
495
+ for (let i = 0; i < posLength; i++) {
496
+ for (let j = 0; j < posLength; j++) {
497
+ // Skip if position is occupied by finder patterns
498
+ if ((i === 0 && j === 0) || // top-left
499
+ (i === 0 && j === posLength - 1) || // bottom-left
500
+ (i === posLength - 1 && j === 0)) { // top-right
501
+ continue
502
+ }
503
+
504
+ coords.push([pos[i], pos[j]]);
505
+ }
506
+ }
507
+
508
+ return coords
509
+ };
510
+ } (alignmentPattern));
511
+ return alignmentPattern;
512
+ }
513
+
514
+ var finderPattern = {};
515
+
516
+ var hasRequiredFinderPattern;
517
+
518
+ function requireFinderPattern () {
519
+ if (hasRequiredFinderPattern) return finderPattern;
520
+ hasRequiredFinderPattern = 1;
521
+ const getSymbolSize = requireUtils$1().getSymbolSize;
522
+ const FINDER_PATTERN_SIZE = 7;
523
+
524
+ /**
525
+ * Returns an array containing the positions of each finder pattern.
526
+ * Each array's element represent the top-left point of the pattern as (x, y) coordinates
527
+ *
528
+ * @param {Number} version QR Code version
529
+ * @return {Array} Array of coordinates
530
+ */
531
+ finderPattern.getPositions = function getPositions (version) {
532
+ const size = getSymbolSize(version);
533
+
534
+ return [
535
+ // top-left
536
+ [0, 0],
537
+ // top-right
538
+ [size - FINDER_PATTERN_SIZE, 0],
539
+ // bottom-left
540
+ [0, size - FINDER_PATTERN_SIZE]
541
+ ]
542
+ };
543
+ return finderPattern;
544
+ }
545
+
546
+ var maskPattern = {};
547
+
548
+ /**
549
+ * Data mask pattern reference
550
+ * @type {Object}
551
+ */
552
+
553
+ var hasRequiredMaskPattern;
554
+
555
+ function requireMaskPattern () {
556
+ if (hasRequiredMaskPattern) return maskPattern;
557
+ hasRequiredMaskPattern = 1;
558
+ (function (exports) {
559
+ exports.Patterns = {
560
+ PATTERN000: 0,
561
+ PATTERN001: 1,
562
+ PATTERN010: 2,
563
+ PATTERN011: 3,
564
+ PATTERN100: 4,
565
+ PATTERN101: 5,
566
+ PATTERN110: 6,
567
+ PATTERN111: 7
568
+ };
569
+
570
+ /**
571
+ * Weighted penalty scores for the undesirable features
572
+ * @type {Object}
573
+ */
574
+ const PenaltyScores = {
575
+ N1: 3,
576
+ N2: 3,
577
+ N3: 40,
578
+ N4: 10
579
+ };
580
+
581
+ /**
582
+ * Check if mask pattern value is valid
583
+ *
584
+ * @param {Number} mask Mask pattern
585
+ * @return {Boolean} true if valid, false otherwise
586
+ */
587
+ exports.isValid = function isValid (mask) {
588
+ return mask != null && mask !== '' && !isNaN(mask) && mask >= 0 && mask <= 7
589
+ };
590
+
591
+ /**
592
+ * Returns mask pattern from a value.
593
+ * If value is not valid, returns undefined
594
+ *
595
+ * @param {Number|String} value Mask pattern value
596
+ * @return {Number} Valid mask pattern or undefined
597
+ */
598
+ exports.from = function from (value) {
599
+ return exports.isValid(value) ? parseInt(value, 10) : undefined
600
+ };
601
+
602
+ /**
603
+ * Find adjacent modules in row/column with the same color
604
+ * and assign a penalty value.
605
+ *
606
+ * Points: N1 + i
607
+ * i is the amount by which the number of adjacent modules of the same color exceeds 5
608
+ */
609
+ exports.getPenaltyN1 = function getPenaltyN1 (data) {
610
+ const size = data.size;
611
+ let points = 0;
612
+ let sameCountCol = 0;
613
+ let sameCountRow = 0;
614
+ let lastCol = null;
615
+ let lastRow = null;
616
+
617
+ for (let row = 0; row < size; row++) {
618
+ sameCountCol = sameCountRow = 0;
619
+ lastCol = lastRow = null;
620
+
621
+ for (let col = 0; col < size; col++) {
622
+ let module = data.get(row, col);
623
+ if (module === lastCol) {
624
+ sameCountCol++;
625
+ } else {
626
+ if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5);
627
+ lastCol = module;
628
+ sameCountCol = 1;
629
+ }
630
+
631
+ module = data.get(col, row);
632
+ if (module === lastRow) {
633
+ sameCountRow++;
634
+ } else {
635
+ if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5);
636
+ lastRow = module;
637
+ sameCountRow = 1;
638
+ }
639
+ }
640
+
641
+ if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5);
642
+ if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5);
643
+ }
644
+
645
+ return points
646
+ };
647
+
648
+ /**
649
+ * Find 2x2 blocks with the same color and assign a penalty value
650
+ *
651
+ * Points: N2 * (m - 1) * (n - 1)
652
+ */
653
+ exports.getPenaltyN2 = function getPenaltyN2 (data) {
654
+ const size = data.size;
655
+ let points = 0;
656
+
657
+ for (let row = 0; row < size - 1; row++) {
658
+ for (let col = 0; col < size - 1; col++) {
659
+ const last = data.get(row, col) +
660
+ data.get(row, col + 1) +
661
+ data.get(row + 1, col) +
662
+ data.get(row + 1, col + 1);
663
+
664
+ if (last === 4 || last === 0) points++;
665
+ }
666
+ }
667
+
668
+ return points * PenaltyScores.N2
669
+ };
670
+
671
+ /**
672
+ * Find 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column,
673
+ * preceded or followed by light area 4 modules wide
674
+ *
675
+ * Points: N3 * number of pattern found
676
+ */
677
+ exports.getPenaltyN3 = function getPenaltyN3 (data) {
678
+ const size = data.size;
679
+ let points = 0;
680
+ let bitsCol = 0;
681
+ let bitsRow = 0;
682
+
683
+ for (let row = 0; row < size; row++) {
684
+ bitsCol = bitsRow = 0;
685
+ for (let col = 0; col < size; col++) {
686
+ bitsCol = ((bitsCol << 1) & 0x7FF) | data.get(row, col);
687
+ if (col >= 10 && (bitsCol === 0x5D0 || bitsCol === 0x05D)) points++;
688
+
689
+ bitsRow = ((bitsRow << 1) & 0x7FF) | data.get(col, row);
690
+ if (col >= 10 && (bitsRow === 0x5D0 || bitsRow === 0x05D)) points++;
691
+ }
692
+ }
693
+
694
+ return points * PenaltyScores.N3
695
+ };
696
+
697
+ /**
698
+ * Calculate proportion of dark modules in entire symbol
699
+ *
700
+ * Points: N4 * k
701
+ *
702
+ * k is the rating of the deviation of the proportion of dark modules
703
+ * in the symbol from 50% in steps of 5%
704
+ */
705
+ exports.getPenaltyN4 = function getPenaltyN4 (data) {
706
+ let darkCount = 0;
707
+ const modulesCount = data.data.length;
708
+
709
+ for (let i = 0; i < modulesCount; i++) darkCount += data.data[i];
710
+
711
+ const k = Math.abs(Math.ceil((darkCount * 100 / modulesCount) / 5) - 10);
712
+
713
+ return k * PenaltyScores.N4
714
+ };
715
+
716
+ /**
717
+ * Return mask value at given position
718
+ *
719
+ * @param {Number} maskPattern Pattern reference value
720
+ * @param {Number} i Row
721
+ * @param {Number} j Column
722
+ * @return {Boolean} Mask value
723
+ */
724
+ function getMaskAt (maskPattern, i, j) {
725
+ switch (maskPattern) {
726
+ case exports.Patterns.PATTERN000: return (i + j) % 2 === 0
727
+ case exports.Patterns.PATTERN001: return i % 2 === 0
728
+ case exports.Patterns.PATTERN010: return j % 3 === 0
729
+ case exports.Patterns.PATTERN011: return (i + j) % 3 === 0
730
+ case exports.Patterns.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0
731
+ case exports.Patterns.PATTERN101: return (i * j) % 2 + (i * j) % 3 === 0
732
+ case exports.Patterns.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 === 0
733
+ case exports.Patterns.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 === 0
734
+
735
+ default: throw new Error('bad maskPattern:' + maskPattern)
736
+ }
737
+ }
738
+
739
+ /**
740
+ * Apply a mask pattern to a BitMatrix
741
+ *
742
+ * @param {Number} pattern Pattern reference number
743
+ * @param {BitMatrix} data BitMatrix data
744
+ */
745
+ exports.applyMask = function applyMask (pattern, data) {
746
+ const size = data.size;
747
+
748
+ for (let col = 0; col < size; col++) {
749
+ for (let row = 0; row < size; row++) {
750
+ if (data.isReserved(row, col)) continue
751
+ data.xor(row, col, getMaskAt(pattern, row, col));
752
+ }
753
+ }
754
+ };
755
+
756
+ /**
757
+ * Returns the best mask pattern for data
758
+ *
759
+ * @param {BitMatrix} data
760
+ * @return {Number} Mask pattern reference number
761
+ */
762
+ exports.getBestMask = function getBestMask (data, setupFormatFunc) {
763
+ const numPatterns = Object.keys(exports.Patterns).length;
764
+ let bestPattern = 0;
765
+ let lowerPenalty = Infinity;
766
+
767
+ for (let p = 0; p < numPatterns; p++) {
768
+ setupFormatFunc(p);
769
+ exports.applyMask(p, data);
770
+
771
+ // Calculate penalty
772
+ const penalty =
773
+ exports.getPenaltyN1(data) +
774
+ exports.getPenaltyN2(data) +
775
+ exports.getPenaltyN3(data) +
776
+ exports.getPenaltyN4(data);
777
+
778
+ // Undo previously applied mask
779
+ exports.applyMask(p, data);
780
+
781
+ if (penalty < lowerPenalty) {
782
+ lowerPenalty = penalty;
783
+ bestPattern = p;
784
+ }
785
+ }
786
+
787
+ return bestPattern
788
+ };
789
+ } (maskPattern));
790
+ return maskPattern;
791
+ }
792
+
793
+ var errorCorrectionCode = {};
794
+
795
+ var hasRequiredErrorCorrectionCode;
796
+
797
+ function requireErrorCorrectionCode () {
798
+ if (hasRequiredErrorCorrectionCode) return errorCorrectionCode;
799
+ hasRequiredErrorCorrectionCode = 1;
800
+ const ECLevel = requireErrorCorrectionLevel();
801
+
802
+ const EC_BLOCKS_TABLE = [
803
+ // L M Q H
804
+ 1, 1, 1, 1,
805
+ 1, 1, 1, 1,
806
+ 1, 1, 2, 2,
807
+ 1, 2, 2, 4,
808
+ 1, 2, 4, 4,
809
+ 2, 4, 4, 4,
810
+ 2, 4, 6, 5,
811
+ 2, 4, 6, 6,
812
+ 2, 5, 8, 8,
813
+ 4, 5, 8, 8,
814
+ 4, 5, 8, 11,
815
+ 4, 8, 10, 11,
816
+ 4, 9, 12, 16,
817
+ 4, 9, 16, 16,
818
+ 6, 10, 12, 18,
819
+ 6, 10, 17, 16,
820
+ 6, 11, 16, 19,
821
+ 6, 13, 18, 21,
822
+ 7, 14, 21, 25,
823
+ 8, 16, 20, 25,
824
+ 8, 17, 23, 25,
825
+ 9, 17, 23, 34,
826
+ 9, 18, 25, 30,
827
+ 10, 20, 27, 32,
828
+ 12, 21, 29, 35,
829
+ 12, 23, 34, 37,
830
+ 12, 25, 34, 40,
831
+ 13, 26, 35, 42,
832
+ 14, 28, 38, 45,
833
+ 15, 29, 40, 48,
834
+ 16, 31, 43, 51,
835
+ 17, 33, 45, 54,
836
+ 18, 35, 48, 57,
837
+ 19, 37, 51, 60,
838
+ 19, 38, 53, 63,
839
+ 20, 40, 56, 66,
840
+ 21, 43, 59, 70,
841
+ 22, 45, 62, 74,
842
+ 24, 47, 65, 77,
843
+ 25, 49, 68, 81
844
+ ];
845
+
846
+ const EC_CODEWORDS_TABLE = [
847
+ // L M Q H
848
+ 7, 10, 13, 17,
849
+ 10, 16, 22, 28,
850
+ 15, 26, 36, 44,
851
+ 20, 36, 52, 64,
852
+ 26, 48, 72, 88,
853
+ 36, 64, 96, 112,
854
+ 40, 72, 108, 130,
855
+ 48, 88, 132, 156,
856
+ 60, 110, 160, 192,
857
+ 72, 130, 192, 224,
858
+ 80, 150, 224, 264,
859
+ 96, 176, 260, 308,
860
+ 104, 198, 288, 352,
861
+ 120, 216, 320, 384,
862
+ 132, 240, 360, 432,
863
+ 144, 280, 408, 480,
864
+ 168, 308, 448, 532,
865
+ 180, 338, 504, 588,
866
+ 196, 364, 546, 650,
867
+ 224, 416, 600, 700,
868
+ 224, 442, 644, 750,
869
+ 252, 476, 690, 816,
870
+ 270, 504, 750, 900,
871
+ 300, 560, 810, 960,
872
+ 312, 588, 870, 1050,
873
+ 336, 644, 952, 1110,
874
+ 360, 700, 1020, 1200,
875
+ 390, 728, 1050, 1260,
876
+ 420, 784, 1140, 1350,
877
+ 450, 812, 1200, 1440,
878
+ 480, 868, 1290, 1530,
879
+ 510, 924, 1350, 1620,
880
+ 540, 980, 1440, 1710,
881
+ 570, 1036, 1530, 1800,
882
+ 570, 1064, 1590, 1890,
883
+ 600, 1120, 1680, 1980,
884
+ 630, 1204, 1770, 2100,
885
+ 660, 1260, 1860, 2220,
886
+ 720, 1316, 1950, 2310,
887
+ 750, 1372, 2040, 2430
888
+ ];
889
+
890
+ /**
891
+ * Returns the number of error correction block that the QR Code should contain
892
+ * for the specified version and error correction level.
893
+ *
894
+ * @param {Number} version QR Code version
895
+ * @param {Number} errorCorrectionLevel Error correction level
896
+ * @return {Number} Number of error correction blocks
897
+ */
898
+ errorCorrectionCode.getBlocksCount = function getBlocksCount (version, errorCorrectionLevel) {
899
+ switch (errorCorrectionLevel) {
900
+ case ECLevel.L:
901
+ return EC_BLOCKS_TABLE[(version - 1) * 4 + 0]
902
+ case ECLevel.M:
903
+ return EC_BLOCKS_TABLE[(version - 1) * 4 + 1]
904
+ case ECLevel.Q:
905
+ return EC_BLOCKS_TABLE[(version - 1) * 4 + 2]
906
+ case ECLevel.H:
907
+ return EC_BLOCKS_TABLE[(version - 1) * 4 + 3]
908
+ default:
909
+ return undefined
910
+ }
911
+ };
912
+
913
+ /**
914
+ * Returns the number of error correction codewords to use for the specified
915
+ * version and error correction level.
916
+ *
917
+ * @param {Number} version QR Code version
918
+ * @param {Number} errorCorrectionLevel Error correction level
919
+ * @return {Number} Number of error correction codewords
920
+ */
921
+ errorCorrectionCode.getTotalCodewordsCount = function getTotalCodewordsCount (version, errorCorrectionLevel) {
922
+ switch (errorCorrectionLevel) {
923
+ case ECLevel.L:
924
+ return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0]
925
+ case ECLevel.M:
926
+ return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1]
927
+ case ECLevel.Q:
928
+ return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2]
929
+ case ECLevel.H:
930
+ return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3]
931
+ default:
932
+ return undefined
933
+ }
934
+ };
935
+ return errorCorrectionCode;
936
+ }
937
+
938
+ var polynomial = {};
939
+
940
+ var galoisField = {};
941
+
942
+ var hasRequiredGaloisField;
943
+
944
+ function requireGaloisField () {
945
+ if (hasRequiredGaloisField) return galoisField;
946
+ hasRequiredGaloisField = 1;
947
+ const EXP_TABLE = new Uint8Array(512);
948
+ const LOG_TABLE = new Uint8Array(256)
949
+ /**
950
+ * Precompute the log and anti-log tables for faster computation later
951
+ *
952
+ * For each possible value in the galois field 2^8, we will pre-compute
953
+ * the logarithm and anti-logarithm (exponential) of this value
954
+ *
955
+ * ref {@link https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#Introduction_to_mathematical_fields}
956
+ */
957
+ ;(function initTables () {
958
+ let x = 1;
959
+ for (let i = 0; i < 255; i++) {
960
+ EXP_TABLE[i] = x;
961
+ LOG_TABLE[x] = i;
962
+
963
+ x <<= 1; // multiply by 2
964
+
965
+ // The QR code specification says to use byte-wise modulo 100011101 arithmetic.
966
+ // This means that when a number is 256 or larger, it should be XORed with 0x11D.
967
+ if (x & 0x100) { // similar to x >= 256, but a lot faster (because 0x100 == 256)
968
+ x ^= 0x11D;
969
+ }
970
+ }
971
+
972
+ // Optimization: double the size of the anti-log table so that we don't need to mod 255 to
973
+ // stay inside the bounds (because we will mainly use this table for the multiplication of
974
+ // two GF numbers, no more).
975
+ // @see {@link mul}
976
+ for (let i = 255; i < 512; i++) {
977
+ EXP_TABLE[i] = EXP_TABLE[i - 255];
978
+ }
979
+ }());
980
+
981
+ /**
982
+ * Returns log value of n inside Galois Field
983
+ *
984
+ * @param {Number} n
985
+ * @return {Number}
986
+ */
987
+ galoisField.log = function log (n) {
988
+ if (n < 1) throw new Error('log(' + n + ')')
989
+ return LOG_TABLE[n]
990
+ };
991
+
992
+ /**
993
+ * Returns anti-log value of n inside Galois Field
994
+ *
995
+ * @param {Number} n
996
+ * @return {Number}
997
+ */
998
+ galoisField.exp = function exp (n) {
999
+ return EXP_TABLE[n]
1000
+ };
1001
+
1002
+ /**
1003
+ * Multiplies two number inside Galois Field
1004
+ *
1005
+ * @param {Number} x
1006
+ * @param {Number} y
1007
+ * @return {Number}
1008
+ */
1009
+ galoisField.mul = function mul (x, y) {
1010
+ if (x === 0 || y === 0) return 0
1011
+
1012
+ // should be EXP_TABLE[(LOG_TABLE[x] + LOG_TABLE[y]) % 255] if EXP_TABLE wasn't oversized
1013
+ // @see {@link initTables}
1014
+ return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]]
1015
+ };
1016
+ return galoisField;
1017
+ }
1018
+
1019
+ var hasRequiredPolynomial;
1020
+
1021
+ function requirePolynomial () {
1022
+ if (hasRequiredPolynomial) return polynomial;
1023
+ hasRequiredPolynomial = 1;
1024
+ (function (exports) {
1025
+ const GF = requireGaloisField();
1026
+
1027
+ /**
1028
+ * Multiplies two polynomials inside Galois Field
1029
+ *
1030
+ * @param {Uint8Array} p1 Polynomial
1031
+ * @param {Uint8Array} p2 Polynomial
1032
+ * @return {Uint8Array} Product of p1 and p2
1033
+ */
1034
+ exports.mul = function mul (p1, p2) {
1035
+ const coeff = new Uint8Array(p1.length + p2.length - 1);
1036
+
1037
+ for (let i = 0; i < p1.length; i++) {
1038
+ for (let j = 0; j < p2.length; j++) {
1039
+ coeff[i + j] ^= GF.mul(p1[i], p2[j]);
1040
+ }
1041
+ }
1042
+
1043
+ return coeff
1044
+ };
1045
+
1046
+ /**
1047
+ * Calculate the remainder of polynomials division
1048
+ *
1049
+ * @param {Uint8Array} divident Polynomial
1050
+ * @param {Uint8Array} divisor Polynomial
1051
+ * @return {Uint8Array} Remainder
1052
+ */
1053
+ exports.mod = function mod (divident, divisor) {
1054
+ let result = new Uint8Array(divident);
1055
+
1056
+ while ((result.length - divisor.length) >= 0) {
1057
+ const coeff = result[0];
1058
+
1059
+ for (let i = 0; i < divisor.length; i++) {
1060
+ result[i] ^= GF.mul(divisor[i], coeff);
1061
+ }
1062
+
1063
+ // remove all zeros from buffer head
1064
+ let offset = 0;
1065
+ while (offset < result.length && result[offset] === 0) offset++;
1066
+ result = result.slice(offset);
1067
+ }
1068
+
1069
+ return result
1070
+ };
1071
+
1072
+ /**
1073
+ * Generate an irreducible generator polynomial of specified degree
1074
+ * (used by Reed-Solomon encoder)
1075
+ *
1076
+ * @param {Number} degree Degree of the generator polynomial
1077
+ * @return {Uint8Array} Buffer containing polynomial coefficients
1078
+ */
1079
+ exports.generateECPolynomial = function generateECPolynomial (degree) {
1080
+ let poly = new Uint8Array([1]);
1081
+ for (let i = 0; i < degree; i++) {
1082
+ poly = exports.mul(poly, new Uint8Array([1, GF.exp(i)]));
1083
+ }
1084
+
1085
+ return poly
1086
+ };
1087
+ } (polynomial));
1088
+ return polynomial;
1089
+ }
1090
+
1091
+ var reedSolomonEncoder;
1092
+ var hasRequiredReedSolomonEncoder;
1093
+
1094
+ function requireReedSolomonEncoder () {
1095
+ if (hasRequiredReedSolomonEncoder) return reedSolomonEncoder;
1096
+ hasRequiredReedSolomonEncoder = 1;
1097
+ const Polynomial = requirePolynomial();
1098
+
1099
+ function ReedSolomonEncoder (degree) {
1100
+ this.genPoly = undefined;
1101
+ this.degree = degree;
1102
+
1103
+ if (this.degree) this.initialize(this.degree);
1104
+ }
1105
+
1106
+ /**
1107
+ * Initialize the encoder.
1108
+ * The input param should correspond to the number of error correction codewords.
1109
+ *
1110
+ * @param {Number} degree
1111
+ */
1112
+ ReedSolomonEncoder.prototype.initialize = function initialize (degree) {
1113
+ // create an irreducible generator polynomial
1114
+ this.degree = degree;
1115
+ this.genPoly = Polynomial.generateECPolynomial(this.degree);
1116
+ };
1117
+
1118
+ /**
1119
+ * Encodes a chunk of data
1120
+ *
1121
+ * @param {Uint8Array} data Buffer containing input data
1122
+ * @return {Uint8Array} Buffer containing encoded data
1123
+ */
1124
+ ReedSolomonEncoder.prototype.encode = function encode (data) {
1125
+ if (!this.genPoly) {
1126
+ throw new Error('Encoder not initialized')
1127
+ }
1128
+
1129
+ // Calculate EC for this data block
1130
+ // extends data size to data+genPoly size
1131
+ const paddedData = new Uint8Array(data.length + this.degree);
1132
+ paddedData.set(data);
1133
+
1134
+ // The error correction codewords are the remainder after dividing the data codewords
1135
+ // by a generator polynomial
1136
+ const remainder = Polynomial.mod(paddedData, this.genPoly);
1137
+
1138
+ // return EC data blocks (last n byte, where n is the degree of genPoly)
1139
+ // If coefficients number in remainder are less than genPoly degree,
1140
+ // pad with 0s to the left to reach the needed number of coefficients
1141
+ const start = this.degree - remainder.length;
1142
+ if (start > 0) {
1143
+ const buff = new Uint8Array(this.degree);
1144
+ buff.set(remainder, start);
1145
+
1146
+ return buff
1147
+ }
1148
+
1149
+ return remainder
1150
+ };
1151
+
1152
+ reedSolomonEncoder = ReedSolomonEncoder;
1153
+ return reedSolomonEncoder;
1154
+ }
1155
+
1156
+ var version = {};
1157
+
1158
+ var mode = {};
1159
+
1160
+ var versionCheck = {};
1161
+
1162
+ /**
1163
+ * Check if QR Code version is valid
1164
+ *
1165
+ * @param {Number} version QR Code version
1166
+ * @return {Boolean} true if valid version, false otherwise
1167
+ */
1168
+
1169
+ var hasRequiredVersionCheck;
1170
+
1171
+ function requireVersionCheck () {
1172
+ if (hasRequiredVersionCheck) return versionCheck;
1173
+ hasRequiredVersionCheck = 1;
1174
+ versionCheck.isValid = function isValid (version) {
1175
+ return !isNaN(version) && version >= 1 && version <= 40
1176
+ };
1177
+ return versionCheck;
1178
+ }
1179
+
1180
+ var regex = {};
1181
+
1182
+ var hasRequiredRegex;
1183
+
1184
+ function requireRegex () {
1185
+ if (hasRequiredRegex) return regex;
1186
+ hasRequiredRegex = 1;
1187
+ const numeric = '[0-9]+';
1188
+ const alphanumeric = '[A-Z $%*+\\-./:]+';
1189
+ let kanji = '(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|' +
1190
+ '[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|' +
1191
+ '[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|' +
1192
+ '[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+';
1193
+ kanji = kanji.replace(/u/g, '\\u');
1194
+
1195
+ const byte = '(?:(?![A-Z0-9 $%*+\\-./:]|' + kanji + ')(?:.|[\r\n]))+';
1196
+
1197
+ regex.KANJI = new RegExp(kanji, 'g');
1198
+ regex.BYTE_KANJI = new RegExp('[^A-Z0-9 $%*+\\-./:]+', 'g');
1199
+ regex.BYTE = new RegExp(byte, 'g');
1200
+ regex.NUMERIC = new RegExp(numeric, 'g');
1201
+ regex.ALPHANUMERIC = new RegExp(alphanumeric, 'g');
1202
+
1203
+ const TEST_KANJI = new RegExp('^' + kanji + '$');
1204
+ const TEST_NUMERIC = new RegExp('^' + numeric + '$');
1205
+ const TEST_ALPHANUMERIC = new RegExp('^[A-Z0-9 $%*+\\-./:]+$');
1206
+
1207
+ regex.testKanji = function testKanji (str) {
1208
+ return TEST_KANJI.test(str)
1209
+ };
1210
+
1211
+ regex.testNumeric = function testNumeric (str) {
1212
+ return TEST_NUMERIC.test(str)
1213
+ };
1214
+
1215
+ regex.testAlphanumeric = function testAlphanumeric (str) {
1216
+ return TEST_ALPHANUMERIC.test(str)
1217
+ };
1218
+ return regex;
1219
+ }
1220
+
1221
+ var hasRequiredMode;
1222
+
1223
+ function requireMode () {
1224
+ if (hasRequiredMode) return mode;
1225
+ hasRequiredMode = 1;
1226
+ (function (exports) {
1227
+ const VersionCheck = requireVersionCheck();
1228
+ const Regex = requireRegex();
1229
+
1230
+ /**
1231
+ * Numeric mode encodes data from the decimal digit set (0 - 9)
1232
+ * (byte values 30HEX to 39HEX).
1233
+ * Normally, 3 data characters are represented by 10 bits.
1234
+ *
1235
+ * @type {Object}
1236
+ */
1237
+ exports.NUMERIC = {
1238
+ id: 'Numeric',
1239
+ bit: 1 << 0,
1240
+ ccBits: [10, 12, 14]
1241
+ };
1242
+
1243
+ /**
1244
+ * Alphanumeric mode encodes data from a set of 45 characters,
1245
+ * i.e. 10 numeric digits (0 - 9),
1246
+ * 26 alphabetic characters (A - Z),
1247
+ * and 9 symbols (SP, $, %, *, +, -, ., /, :).
1248
+ * Normally, two input characters are represented by 11 bits.
1249
+ *
1250
+ * @type {Object}
1251
+ */
1252
+ exports.ALPHANUMERIC = {
1253
+ id: 'Alphanumeric',
1254
+ bit: 1 << 1,
1255
+ ccBits: [9, 11, 13]
1256
+ };
1257
+
1258
+ /**
1259
+ * In byte mode, data is encoded at 8 bits per character.
1260
+ *
1261
+ * @type {Object}
1262
+ */
1263
+ exports.BYTE = {
1264
+ id: 'Byte',
1265
+ bit: 1 << 2,
1266
+ ccBits: [8, 16, 16]
1267
+ };
1268
+
1269
+ /**
1270
+ * The Kanji mode efficiently encodes Kanji characters in accordance with
1271
+ * the Shift JIS system based on JIS X 0208.
1272
+ * The Shift JIS values are shifted from the JIS X 0208 values.
1273
+ * JIS X 0208 gives details of the shift coded representation.
1274
+ * Each two-byte character value is compacted to a 13-bit binary codeword.
1275
+ *
1276
+ * @type {Object}
1277
+ */
1278
+ exports.KANJI = {
1279
+ id: 'Kanji',
1280
+ bit: 1 << 3,
1281
+ ccBits: [8, 10, 12]
1282
+ };
1283
+
1284
+ /**
1285
+ * Mixed mode will contain a sequences of data in a combination of any of
1286
+ * the modes described above
1287
+ *
1288
+ * @type {Object}
1289
+ */
1290
+ exports.MIXED = {
1291
+ bit: -1
1292
+ };
1293
+
1294
+ /**
1295
+ * Returns the number of bits needed to store the data length
1296
+ * according to QR Code specifications.
1297
+ *
1298
+ * @param {Mode} mode Data mode
1299
+ * @param {Number} version QR Code version
1300
+ * @return {Number} Number of bits
1301
+ */
1302
+ exports.getCharCountIndicator = function getCharCountIndicator (mode, version) {
1303
+ if (!mode.ccBits) throw new Error('Invalid mode: ' + mode)
1304
+
1305
+ if (!VersionCheck.isValid(version)) {
1306
+ throw new Error('Invalid version: ' + version)
1307
+ }
1308
+
1309
+ if (version >= 1 && version < 10) return mode.ccBits[0]
1310
+ else if (version < 27) return mode.ccBits[1]
1311
+ return mode.ccBits[2]
1312
+ };
1313
+
1314
+ /**
1315
+ * Returns the most efficient mode to store the specified data
1316
+ *
1317
+ * @param {String} dataStr Input data string
1318
+ * @return {Mode} Best mode
1319
+ */
1320
+ exports.getBestModeForData = function getBestModeForData (dataStr) {
1321
+ if (Regex.testNumeric(dataStr)) return exports.NUMERIC
1322
+ else if (Regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC
1323
+ else if (Regex.testKanji(dataStr)) return exports.KANJI
1324
+ else return exports.BYTE
1325
+ };
1326
+
1327
+ /**
1328
+ * Return mode name as string
1329
+ *
1330
+ * @param {Mode} mode Mode object
1331
+ * @returns {String} Mode name
1332
+ */
1333
+ exports.toString = function toString (mode) {
1334
+ if (mode && mode.id) return mode.id
1335
+ throw new Error('Invalid mode')
1336
+ };
1337
+
1338
+ /**
1339
+ * Check if input param is a valid mode object
1340
+ *
1341
+ * @param {Mode} mode Mode object
1342
+ * @returns {Boolean} True if valid mode, false otherwise
1343
+ */
1344
+ exports.isValid = function isValid (mode) {
1345
+ return mode && mode.bit && mode.ccBits
1346
+ };
1347
+
1348
+ /**
1349
+ * Get mode object from its name
1350
+ *
1351
+ * @param {String} string Mode name
1352
+ * @returns {Mode} Mode object
1353
+ */
1354
+ function fromString (string) {
1355
+ if (typeof string !== 'string') {
1356
+ throw new Error('Param is not a string')
1357
+ }
1358
+
1359
+ const lcStr = string.toLowerCase();
1360
+
1361
+ switch (lcStr) {
1362
+ case 'numeric':
1363
+ return exports.NUMERIC
1364
+ case 'alphanumeric':
1365
+ return exports.ALPHANUMERIC
1366
+ case 'kanji':
1367
+ return exports.KANJI
1368
+ case 'byte':
1369
+ return exports.BYTE
1370
+ default:
1371
+ throw new Error('Unknown mode: ' + string)
1372
+ }
1373
+ }
1374
+
1375
+ /**
1376
+ * Returns mode from a value.
1377
+ * If value is not a valid mode, returns defaultValue
1378
+ *
1379
+ * @param {Mode|String} value Encoding mode
1380
+ * @param {Mode} defaultValue Fallback value
1381
+ * @return {Mode} Encoding mode
1382
+ */
1383
+ exports.from = function from (value, defaultValue) {
1384
+ if (exports.isValid(value)) {
1385
+ return value
1386
+ }
1387
+
1388
+ try {
1389
+ return fromString(value)
1390
+ } catch (e) {
1391
+ return defaultValue
1392
+ }
1393
+ };
1394
+ } (mode));
1395
+ return mode;
1396
+ }
1397
+
1398
+ var hasRequiredVersion;
1399
+
1400
+ function requireVersion () {
1401
+ if (hasRequiredVersion) return version;
1402
+ hasRequiredVersion = 1;
1403
+ (function (exports) {
1404
+ const Utils = requireUtils$1();
1405
+ const ECCode = requireErrorCorrectionCode();
1406
+ const ECLevel = requireErrorCorrectionLevel();
1407
+ const Mode = requireMode();
1408
+ const VersionCheck = requireVersionCheck();
1409
+
1410
+ // Generator polynomial used to encode version information
1411
+ const G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
1412
+ const G18_BCH = Utils.getBCHDigit(G18);
1413
+
1414
+ function getBestVersionForDataLength (mode, length, errorCorrectionLevel) {
1415
+ for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {
1416
+ if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode)) {
1417
+ return currentVersion
1418
+ }
1419
+ }
1420
+
1421
+ return undefined
1422
+ }
1423
+
1424
+ function getReservedBitsCount (mode, version) {
1425
+ // Character count indicator + mode indicator bits
1426
+ return Mode.getCharCountIndicator(mode, version) + 4
1427
+ }
1428
+
1429
+ function getTotalBitsFromDataArray (segments, version) {
1430
+ let totalBits = 0;
1431
+
1432
+ segments.forEach(function (data) {
1433
+ const reservedBits = getReservedBitsCount(data.mode, version);
1434
+ totalBits += reservedBits + data.getBitsLength();
1435
+ });
1436
+
1437
+ return totalBits
1438
+ }
1439
+
1440
+ function getBestVersionForMixedData (segments, errorCorrectionLevel) {
1441
+ for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {
1442
+ const length = getTotalBitsFromDataArray(segments, currentVersion);
1443
+ if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, Mode.MIXED)) {
1444
+ return currentVersion
1445
+ }
1446
+ }
1447
+
1448
+ return undefined
1449
+ }
1450
+
1451
+ /**
1452
+ * Returns version number from a value.
1453
+ * If value is not a valid version, returns defaultValue
1454
+ *
1455
+ * @param {Number|String} value QR Code version
1456
+ * @param {Number} defaultValue Fallback value
1457
+ * @return {Number} QR Code version number
1458
+ */
1459
+ exports.from = function from (value, defaultValue) {
1460
+ if (VersionCheck.isValid(value)) {
1461
+ return parseInt(value, 10)
1462
+ }
1463
+
1464
+ return defaultValue
1465
+ };
1466
+
1467
+ /**
1468
+ * Returns how much data can be stored with the specified QR code version
1469
+ * and error correction level
1470
+ *
1471
+ * @param {Number} version QR Code version (1-40)
1472
+ * @param {Number} errorCorrectionLevel Error correction level
1473
+ * @param {Mode} mode Data mode
1474
+ * @return {Number} Quantity of storable data
1475
+ */
1476
+ exports.getCapacity = function getCapacity (version, errorCorrectionLevel, mode) {
1477
+ if (!VersionCheck.isValid(version)) {
1478
+ throw new Error('Invalid QR Code version')
1479
+ }
1480
+
1481
+ // Use Byte mode as default
1482
+ if (typeof mode === 'undefined') mode = Mode.BYTE;
1483
+
1484
+ // Total codewords for this QR code version (Data + Error correction)
1485
+ const totalCodewords = Utils.getSymbolTotalCodewords(version);
1486
+
1487
+ // Total number of error correction codewords
1488
+ const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel);
1489
+
1490
+ // Total number of data codewords
1491
+ const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8;
1492
+
1493
+ if (mode === Mode.MIXED) return dataTotalCodewordsBits
1494
+
1495
+ const usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode, version);
1496
+
1497
+ // Return max number of storable codewords
1498
+ switch (mode) {
1499
+ case Mode.NUMERIC:
1500
+ return Math.floor((usableBits / 10) * 3)
1501
+
1502
+ case Mode.ALPHANUMERIC:
1503
+ return Math.floor((usableBits / 11) * 2)
1504
+
1505
+ case Mode.KANJI:
1506
+ return Math.floor(usableBits / 13)
1507
+
1508
+ case Mode.BYTE:
1509
+ default:
1510
+ return Math.floor(usableBits / 8)
1511
+ }
1512
+ };
1513
+
1514
+ /**
1515
+ * Returns the minimum version needed to contain the amount of data
1516
+ *
1517
+ * @param {Segment} data Segment of data
1518
+ * @param {Number} [errorCorrectionLevel=H] Error correction level
1519
+ * @param {Mode} mode Data mode
1520
+ * @return {Number} QR Code version
1521
+ */
1522
+ exports.getBestVersionForData = function getBestVersionForData (data, errorCorrectionLevel) {
1523
+ let seg;
1524
+
1525
+ const ecl = ECLevel.from(errorCorrectionLevel, ECLevel.M);
1526
+
1527
+ if (Array.isArray(data)) {
1528
+ if (data.length > 1) {
1529
+ return getBestVersionForMixedData(data, ecl)
1530
+ }
1531
+
1532
+ if (data.length === 0) {
1533
+ return 1
1534
+ }
1535
+
1536
+ seg = data[0];
1537
+ } else {
1538
+ seg = data;
1539
+ }
1540
+
1541
+ return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl)
1542
+ };
1543
+
1544
+ /**
1545
+ * Returns version information with relative error correction bits
1546
+ *
1547
+ * The version information is included in QR Code symbols of version 7 or larger.
1548
+ * It consists of an 18-bit sequence containing 6 data bits,
1549
+ * with 12 error correction bits calculated using the (18, 6) Golay code.
1550
+ *
1551
+ * @param {Number} version QR Code version
1552
+ * @return {Number} Encoded version info bits
1553
+ */
1554
+ exports.getEncodedBits = function getEncodedBits (version) {
1555
+ if (!VersionCheck.isValid(version) || version < 7) {
1556
+ throw new Error('Invalid QR Code version')
1557
+ }
1558
+
1559
+ let d = version << 12;
1560
+
1561
+ while (Utils.getBCHDigit(d) - G18_BCH >= 0) {
1562
+ d ^= (G18 << (Utils.getBCHDigit(d) - G18_BCH));
1563
+ }
1564
+
1565
+ return (version << 12) | d
1566
+ };
1567
+ } (version));
1568
+ return version;
1569
+ }
1570
+
1571
+ var formatInfo = {};
1572
+
1573
+ var hasRequiredFormatInfo;
1574
+
1575
+ function requireFormatInfo () {
1576
+ if (hasRequiredFormatInfo) return formatInfo;
1577
+ hasRequiredFormatInfo = 1;
1578
+ const Utils = requireUtils$1();
1579
+
1580
+ const G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
1581
+ const G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);
1582
+ const G15_BCH = Utils.getBCHDigit(G15);
1583
+
1584
+ /**
1585
+ * Returns format information with relative error correction bits
1586
+ *
1587
+ * The format information is a 15-bit sequence containing 5 data bits,
1588
+ * with 10 error correction bits calculated using the (15, 5) BCH code.
1589
+ *
1590
+ * @param {Number} errorCorrectionLevel Error correction level
1591
+ * @param {Number} mask Mask pattern
1592
+ * @return {Number} Encoded format information bits
1593
+ */
1594
+ formatInfo.getEncodedBits = function getEncodedBits (errorCorrectionLevel, mask) {
1595
+ const data = ((errorCorrectionLevel.bit << 3) | mask);
1596
+ let d = data << 10;
1597
+
1598
+ while (Utils.getBCHDigit(d) - G15_BCH >= 0) {
1599
+ d ^= (G15 << (Utils.getBCHDigit(d) - G15_BCH));
1600
+ }
1601
+
1602
+ // xor final data with mask pattern in order to ensure that
1603
+ // no combination of Error Correction Level and data mask pattern
1604
+ // will result in an all-zero data string
1605
+ return ((data << 10) | d) ^ G15_MASK
1606
+ };
1607
+ return formatInfo;
1608
+ }
1609
+
1610
+ var segments = {};
1611
+
1612
+ var numericData;
1613
+ var hasRequiredNumericData;
1614
+
1615
+ function requireNumericData () {
1616
+ if (hasRequiredNumericData) return numericData;
1617
+ hasRequiredNumericData = 1;
1618
+ const Mode = requireMode();
1619
+
1620
+ function NumericData (data) {
1621
+ this.mode = Mode.NUMERIC;
1622
+ this.data = data.toString();
1623
+ }
1624
+
1625
+ NumericData.getBitsLength = function getBitsLength (length) {
1626
+ return 10 * Math.floor(length / 3) + ((length % 3) ? ((length % 3) * 3 + 1) : 0)
1627
+ };
1628
+
1629
+ NumericData.prototype.getLength = function getLength () {
1630
+ return this.data.length
1631
+ };
1632
+
1633
+ NumericData.prototype.getBitsLength = function getBitsLength () {
1634
+ return NumericData.getBitsLength(this.data.length)
1635
+ };
1636
+
1637
+ NumericData.prototype.write = function write (bitBuffer) {
1638
+ let i, group, value;
1639
+
1640
+ // The input data string is divided into groups of three digits,
1641
+ // and each group is converted to its 10-bit binary equivalent.
1642
+ for (i = 0; i + 3 <= this.data.length; i += 3) {
1643
+ group = this.data.substr(i, 3);
1644
+ value = parseInt(group, 10);
1645
+
1646
+ bitBuffer.put(value, 10);
1647
+ }
1648
+
1649
+ // If the number of input digits is not an exact multiple of three,
1650
+ // the final one or two digits are converted to 4 or 7 bits respectively.
1651
+ const remainingNum = this.data.length - i;
1652
+ if (remainingNum > 0) {
1653
+ group = this.data.substr(i);
1654
+ value = parseInt(group, 10);
1655
+
1656
+ bitBuffer.put(value, remainingNum * 3 + 1);
1657
+ }
1658
+ };
1659
+
1660
+ numericData = NumericData;
1661
+ return numericData;
1662
+ }
1663
+
1664
+ var alphanumericData;
1665
+ var hasRequiredAlphanumericData;
1666
+
1667
+ function requireAlphanumericData () {
1668
+ if (hasRequiredAlphanumericData) return alphanumericData;
1669
+ hasRequiredAlphanumericData = 1;
1670
+ const Mode = requireMode();
1671
+
1672
+ /**
1673
+ * Array of characters available in alphanumeric mode
1674
+ *
1675
+ * As per QR Code specification, to each character
1676
+ * is assigned a value from 0 to 44 which in this case coincides
1677
+ * with the array index
1678
+ *
1679
+ * @type {Array}
1680
+ */
1681
+ const ALPHA_NUM_CHARS = [
1682
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
1683
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
1684
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
1685
+ ' ', '$', '%', '*', '+', '-', '.', '/', ':'
1686
+ ];
1687
+
1688
+ function AlphanumericData (data) {
1689
+ this.mode = Mode.ALPHANUMERIC;
1690
+ this.data = data;
1691
+ }
1692
+
1693
+ AlphanumericData.getBitsLength = function getBitsLength (length) {
1694
+ return 11 * Math.floor(length / 2) + 6 * (length % 2)
1695
+ };
1696
+
1697
+ AlphanumericData.prototype.getLength = function getLength () {
1698
+ return this.data.length
1699
+ };
1700
+
1701
+ AlphanumericData.prototype.getBitsLength = function getBitsLength () {
1702
+ return AlphanumericData.getBitsLength(this.data.length)
1703
+ };
1704
+
1705
+ AlphanumericData.prototype.write = function write (bitBuffer) {
1706
+ let i;
1707
+
1708
+ // Input data characters are divided into groups of two characters
1709
+ // and encoded as 11-bit binary codes.
1710
+ for (i = 0; i + 2 <= this.data.length; i += 2) {
1711
+ // The character value of the first character is multiplied by 45
1712
+ let value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45;
1713
+
1714
+ // The character value of the second digit is added to the product
1715
+ value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1]);
1716
+
1717
+ // The sum is then stored as 11-bit binary number
1718
+ bitBuffer.put(value, 11);
1719
+ }
1720
+
1721
+ // If the number of input data characters is not a multiple of two,
1722
+ // the character value of the final character is encoded as a 6-bit binary number.
1723
+ if (this.data.length % 2) {
1724
+ bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6);
1725
+ }
1726
+ };
1727
+
1728
+ alphanumericData = AlphanumericData;
1729
+ return alphanumericData;
1730
+ }
1731
+
1732
+ var byteData;
1733
+ var hasRequiredByteData;
1734
+
1735
+ function requireByteData () {
1736
+ if (hasRequiredByteData) return byteData;
1737
+ hasRequiredByteData = 1;
1738
+ const Mode = requireMode();
1739
+
1740
+ function ByteData (data) {
1741
+ this.mode = Mode.BYTE;
1742
+ if (typeof (data) === 'string') {
1743
+ this.data = new TextEncoder().encode(data);
1744
+ } else {
1745
+ this.data = new Uint8Array(data);
1746
+ }
1747
+ }
1748
+
1749
+ ByteData.getBitsLength = function getBitsLength (length) {
1750
+ return length * 8
1751
+ };
1752
+
1753
+ ByteData.prototype.getLength = function getLength () {
1754
+ return this.data.length
1755
+ };
1756
+
1757
+ ByteData.prototype.getBitsLength = function getBitsLength () {
1758
+ return ByteData.getBitsLength(this.data.length)
1759
+ };
1760
+
1761
+ ByteData.prototype.write = function (bitBuffer) {
1762
+ for (let i = 0, l = this.data.length; i < l; i++) {
1763
+ bitBuffer.put(this.data[i], 8);
1764
+ }
1765
+ };
1766
+
1767
+ byteData = ByteData;
1768
+ return byteData;
1769
+ }
1770
+
1771
+ var kanjiData;
1772
+ var hasRequiredKanjiData;
1773
+
1774
+ function requireKanjiData () {
1775
+ if (hasRequiredKanjiData) return kanjiData;
1776
+ hasRequiredKanjiData = 1;
1777
+ const Mode = requireMode();
1778
+ const Utils = requireUtils$1();
1779
+
1780
+ function KanjiData (data) {
1781
+ this.mode = Mode.KANJI;
1782
+ this.data = data;
1783
+ }
1784
+
1785
+ KanjiData.getBitsLength = function getBitsLength (length) {
1786
+ return length * 13
1787
+ };
1788
+
1789
+ KanjiData.prototype.getLength = function getLength () {
1790
+ return this.data.length
1791
+ };
1792
+
1793
+ KanjiData.prototype.getBitsLength = function getBitsLength () {
1794
+ return KanjiData.getBitsLength(this.data.length)
1795
+ };
1796
+
1797
+ KanjiData.prototype.write = function (bitBuffer) {
1798
+ let i;
1799
+
1800
+ // In the Shift JIS system, Kanji characters are represented by a two byte combination.
1801
+ // These byte values are shifted from the JIS X 0208 values.
1802
+ // JIS X 0208 gives details of the shift coded representation.
1803
+ for (i = 0; i < this.data.length; i++) {
1804
+ let value = Utils.toSJIS(this.data[i]);
1805
+
1806
+ // For characters with Shift JIS values from 0x8140 to 0x9FFC:
1807
+ if (value >= 0x8140 && value <= 0x9FFC) {
1808
+ // Subtract 0x8140 from Shift JIS value
1809
+ value -= 0x8140;
1810
+
1811
+ // For characters with Shift JIS values from 0xE040 to 0xEBBF
1812
+ } else if (value >= 0xE040 && value <= 0xEBBF) {
1813
+ // Subtract 0xC140 from Shift JIS value
1814
+ value -= 0xC140;
1815
+ } else {
1816
+ throw new Error(
1817
+ 'Invalid SJIS character: ' + this.data[i] + '\n' +
1818
+ 'Make sure your charset is UTF-8')
1819
+ }
1820
+
1821
+ // Multiply most significant byte of result by 0xC0
1822
+ // and add least significant byte to product
1823
+ value = (((value >>> 8) & 0xff) * 0xC0) + (value & 0xff);
1824
+
1825
+ // Convert result to a 13-bit binary string
1826
+ bitBuffer.put(value, 13);
1827
+ }
1828
+ };
1829
+
1830
+ kanjiData = KanjiData;
1831
+ return kanjiData;
1832
+ }
1833
+
1834
+ var dijkstra = {exports: {}};
1835
+
1836
+ var hasRequiredDijkstra;
1837
+
1838
+ function requireDijkstra () {
1839
+ if (hasRequiredDijkstra) return dijkstra.exports;
1840
+ hasRequiredDijkstra = 1;
1841
+ (function (module) {
1842
+
1843
+ /******************************************************************************
1844
+ * Created 2008-08-19.
1845
+ *
1846
+ * Dijkstra path-finding functions. Adapted from the Dijkstar Python project.
1847
+ *
1848
+ * Copyright (C) 2008
1849
+ * Wyatt Baldwin <self@wyattbaldwin.com>
1850
+ * All rights reserved
1851
+ *
1852
+ * Licensed under the MIT license.
1853
+ *
1854
+ * http://www.opensource.org/licenses/mit-license.php
1855
+ *
1856
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1857
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1858
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1859
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1860
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1861
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1862
+ * THE SOFTWARE.
1863
+ *****************************************************************************/
1864
+ var dijkstra = {
1865
+ single_source_shortest_paths: function(graph, s, d) {
1866
+ // Predecessor map for each node that has been encountered.
1867
+ // node ID => predecessor node ID
1868
+ var predecessors = {};
1869
+
1870
+ // Costs of shortest paths from s to all nodes encountered.
1871
+ // node ID => cost
1872
+ var costs = {};
1873
+ costs[s] = 0;
1874
+
1875
+ // Costs of shortest paths from s to all nodes encountered; differs from
1876
+ // `costs` in that it provides easy access to the node that currently has
1877
+ // the known shortest path from s.
1878
+ // XXX: Do we actually need both `costs` and `open`?
1879
+ var open = dijkstra.PriorityQueue.make();
1880
+ open.push(s, 0);
1881
+
1882
+ var closest,
1883
+ u, v,
1884
+ cost_of_s_to_u,
1885
+ adjacent_nodes,
1886
+ cost_of_e,
1887
+ cost_of_s_to_u_plus_cost_of_e,
1888
+ cost_of_s_to_v,
1889
+ first_visit;
1890
+ while (!open.empty()) {
1891
+ // In the nodes remaining in graph that have a known cost from s,
1892
+ // find the node, u, that currently has the shortest path from s.
1893
+ closest = open.pop();
1894
+ u = closest.value;
1895
+ cost_of_s_to_u = closest.cost;
1896
+
1897
+ // Get nodes adjacent to u...
1898
+ adjacent_nodes = graph[u] || {};
1899
+
1900
+ // ...and explore the edges that connect u to those nodes, updating
1901
+ // the cost of the shortest paths to any or all of those nodes as
1902
+ // necessary. v is the node across the current edge from u.
1903
+ for (v in adjacent_nodes) {
1904
+ if (adjacent_nodes.hasOwnProperty(v)) {
1905
+ // Get the cost of the edge running from u to v.
1906
+ cost_of_e = adjacent_nodes[v];
1907
+
1908
+ // Cost of s to u plus the cost of u to v across e--this is *a*
1909
+ // cost from s to v that may or may not be less than the current
1910
+ // known cost to v.
1911
+ cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e;
1912
+
1913
+ // If we haven't visited v yet OR if the current known cost from s to
1914
+ // v is greater than the new cost we just found (cost of s to u plus
1915
+ // cost of u to v across e), update v's cost in the cost list and
1916
+ // update v's predecessor in the predecessor list (it's now u).
1917
+ cost_of_s_to_v = costs[v];
1918
+ first_visit = (typeof costs[v] === 'undefined');
1919
+ if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {
1920
+ costs[v] = cost_of_s_to_u_plus_cost_of_e;
1921
+ open.push(v, cost_of_s_to_u_plus_cost_of_e);
1922
+ predecessors[v] = u;
1923
+ }
1924
+ }
1925
+ }
1926
+ }
1927
+
1928
+ if (typeof d !== 'undefined' && typeof costs[d] === 'undefined') {
1929
+ var msg = ['Could not find a path from ', s, ' to ', d, '.'].join('');
1930
+ throw new Error(msg);
1931
+ }
1932
+
1933
+ return predecessors;
1934
+ },
1935
+
1936
+ extract_shortest_path_from_predecessor_list: function(predecessors, d) {
1937
+ var nodes = [];
1938
+ var u = d;
1939
+ while (u) {
1940
+ nodes.push(u);
1941
+ predecessors[u];
1942
+ u = predecessors[u];
1943
+ }
1944
+ nodes.reverse();
1945
+ return nodes;
1946
+ },
1947
+
1948
+ find_path: function(graph, s, d) {
1949
+ var predecessors = dijkstra.single_source_shortest_paths(graph, s, d);
1950
+ return dijkstra.extract_shortest_path_from_predecessor_list(
1951
+ predecessors, d);
1952
+ },
1953
+
1954
+ /**
1955
+ * A very naive priority queue implementation.
1956
+ */
1957
+ PriorityQueue: {
1958
+ make: function (opts) {
1959
+ var T = dijkstra.PriorityQueue,
1960
+ t = {},
1961
+ key;
1962
+ opts = opts || {};
1963
+ for (key in T) {
1964
+ if (T.hasOwnProperty(key)) {
1965
+ t[key] = T[key];
1966
+ }
1967
+ }
1968
+ t.queue = [];
1969
+ t.sorter = opts.sorter || T.default_sorter;
1970
+ return t;
1971
+ },
1972
+
1973
+ default_sorter: function (a, b) {
1974
+ return a.cost - b.cost;
1975
+ },
1976
+
1977
+ /**
1978
+ * Add a new item to the queue and ensure the highest priority element
1979
+ * is at the front of the queue.
1980
+ */
1981
+ push: function (value, cost) {
1982
+ var item = {value: value, cost: cost};
1983
+ this.queue.push(item);
1984
+ this.queue.sort(this.sorter);
1985
+ },
1986
+
1987
+ /**
1988
+ * Return the highest priority element in the queue.
1989
+ */
1990
+ pop: function () {
1991
+ return this.queue.shift();
1992
+ },
1993
+
1994
+ empty: function () {
1995
+ return this.queue.length === 0;
1996
+ }
1997
+ }
1998
+ };
1999
+
2000
+
2001
+ // node.js module exports
2002
+ {
2003
+ module.exports = dijkstra;
2004
+ }
2005
+ } (dijkstra));
2006
+ return dijkstra.exports;
2007
+ }
2008
+
2009
+ var hasRequiredSegments;
2010
+
2011
+ function requireSegments () {
2012
+ if (hasRequiredSegments) return segments;
2013
+ hasRequiredSegments = 1;
2014
+ (function (exports) {
2015
+ const Mode = requireMode();
2016
+ const NumericData = requireNumericData();
2017
+ const AlphanumericData = requireAlphanumericData();
2018
+ const ByteData = requireByteData();
2019
+ const KanjiData = requireKanjiData();
2020
+ const Regex = requireRegex();
2021
+ const Utils = requireUtils$1();
2022
+ const dijkstra = requireDijkstra();
2023
+
2024
+ /**
2025
+ * Returns UTF8 byte length
2026
+ *
2027
+ * @param {String} str Input string
2028
+ * @return {Number} Number of byte
2029
+ */
2030
+ function getStringByteLength (str) {
2031
+ return unescape(encodeURIComponent(str)).length
2032
+ }
2033
+
2034
+ /**
2035
+ * Get a list of segments of the specified mode
2036
+ * from a string
2037
+ *
2038
+ * @param {Mode} mode Segment mode
2039
+ * @param {String} str String to process
2040
+ * @return {Array} Array of object with segments data
2041
+ */
2042
+ function getSegments (regex, mode, str) {
2043
+ const segments = [];
2044
+ let result;
2045
+
2046
+ while ((result = regex.exec(str)) !== null) {
2047
+ segments.push({
2048
+ data: result[0],
2049
+ index: result.index,
2050
+ mode: mode,
2051
+ length: result[0].length
2052
+ });
2053
+ }
2054
+
2055
+ return segments
2056
+ }
2057
+
2058
+ /**
2059
+ * Extracts a series of segments with the appropriate
2060
+ * modes from a string
2061
+ *
2062
+ * @param {String} dataStr Input string
2063
+ * @return {Array} Array of object with segments data
2064
+ */
2065
+ function getSegmentsFromString (dataStr) {
2066
+ const numSegs = getSegments(Regex.NUMERIC, Mode.NUMERIC, dataStr);
2067
+ const alphaNumSegs = getSegments(Regex.ALPHANUMERIC, Mode.ALPHANUMERIC, dataStr);
2068
+ let byteSegs;
2069
+ let kanjiSegs;
2070
+
2071
+ if (Utils.isKanjiModeEnabled()) {
2072
+ byteSegs = getSegments(Regex.BYTE, Mode.BYTE, dataStr);
2073
+ kanjiSegs = getSegments(Regex.KANJI, Mode.KANJI, dataStr);
2074
+ } else {
2075
+ byteSegs = getSegments(Regex.BYTE_KANJI, Mode.BYTE, dataStr);
2076
+ kanjiSegs = [];
2077
+ }
2078
+
2079
+ const segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs);
2080
+
2081
+ return segs
2082
+ .sort(function (s1, s2) {
2083
+ return s1.index - s2.index
2084
+ })
2085
+ .map(function (obj) {
2086
+ return {
2087
+ data: obj.data,
2088
+ mode: obj.mode,
2089
+ length: obj.length
2090
+ }
2091
+ })
2092
+ }
2093
+
2094
+ /**
2095
+ * Returns how many bits are needed to encode a string of
2096
+ * specified length with the specified mode
2097
+ *
2098
+ * @param {Number} length String length
2099
+ * @param {Mode} mode Segment mode
2100
+ * @return {Number} Bit length
2101
+ */
2102
+ function getSegmentBitsLength (length, mode) {
2103
+ switch (mode) {
2104
+ case Mode.NUMERIC:
2105
+ return NumericData.getBitsLength(length)
2106
+ case Mode.ALPHANUMERIC:
2107
+ return AlphanumericData.getBitsLength(length)
2108
+ case Mode.KANJI:
2109
+ return KanjiData.getBitsLength(length)
2110
+ case Mode.BYTE:
2111
+ return ByteData.getBitsLength(length)
2112
+ }
2113
+ }
2114
+
2115
+ /**
2116
+ * Merges adjacent segments which have the same mode
2117
+ *
2118
+ * @param {Array} segs Array of object with segments data
2119
+ * @return {Array} Array of object with segments data
2120
+ */
2121
+ function mergeSegments (segs) {
2122
+ return segs.reduce(function (acc, curr) {
2123
+ const prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null;
2124
+ if (prevSeg && prevSeg.mode === curr.mode) {
2125
+ acc[acc.length - 1].data += curr.data;
2126
+ return acc
2127
+ }
2128
+
2129
+ acc.push(curr);
2130
+ return acc
2131
+ }, [])
2132
+ }
2133
+
2134
+ /**
2135
+ * Generates a list of all possible nodes combination which
2136
+ * will be used to build a segments graph.
2137
+ *
2138
+ * Nodes are divided by groups. Each group will contain a list of all the modes
2139
+ * in which is possible to encode the given text.
2140
+ *
2141
+ * For example the text '12345' can be encoded as Numeric, Alphanumeric or Byte.
2142
+ * The group for '12345' will contain then 3 objects, one for each
2143
+ * possible encoding mode.
2144
+ *
2145
+ * Each node represents a possible segment.
2146
+ *
2147
+ * @param {Array} segs Array of object with segments data
2148
+ * @return {Array} Array of object with segments data
2149
+ */
2150
+ function buildNodes (segs) {
2151
+ const nodes = [];
2152
+ for (let i = 0; i < segs.length; i++) {
2153
+ const seg = segs[i];
2154
+
2155
+ switch (seg.mode) {
2156
+ case Mode.NUMERIC:
2157
+ nodes.push([seg,
2158
+ { data: seg.data, mode: Mode.ALPHANUMERIC, length: seg.length },
2159
+ { data: seg.data, mode: Mode.BYTE, length: seg.length }
2160
+ ]);
2161
+ break
2162
+ case Mode.ALPHANUMERIC:
2163
+ nodes.push([seg,
2164
+ { data: seg.data, mode: Mode.BYTE, length: seg.length }
2165
+ ]);
2166
+ break
2167
+ case Mode.KANJI:
2168
+ nodes.push([seg,
2169
+ { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }
2170
+ ]);
2171
+ break
2172
+ case Mode.BYTE:
2173
+ nodes.push([
2174
+ { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }
2175
+ ]);
2176
+ }
2177
+ }
2178
+
2179
+ return nodes
2180
+ }
2181
+
2182
+ /**
2183
+ * Builds a graph from a list of nodes.
2184
+ * All segments in each node group will be connected with all the segments of
2185
+ * the next group and so on.
2186
+ *
2187
+ * At each connection will be assigned a weight depending on the
2188
+ * segment's byte length.
2189
+ *
2190
+ * @param {Array} nodes Array of object with segments data
2191
+ * @param {Number} version QR Code version
2192
+ * @return {Object} Graph of all possible segments
2193
+ */
2194
+ function buildGraph (nodes, version) {
2195
+ const table = {};
2196
+ const graph = { start: {} };
2197
+ let prevNodeIds = ['start'];
2198
+
2199
+ for (let i = 0; i < nodes.length; i++) {
2200
+ const nodeGroup = nodes[i];
2201
+ const currentNodeIds = [];
2202
+
2203
+ for (let j = 0; j < nodeGroup.length; j++) {
2204
+ const node = nodeGroup[j];
2205
+ const key = '' + i + j;
2206
+
2207
+ currentNodeIds.push(key);
2208
+ table[key] = { node: node, lastCount: 0 };
2209
+ graph[key] = {};
2210
+
2211
+ for (let n = 0; n < prevNodeIds.length; n++) {
2212
+ const prevNodeId = prevNodeIds[n];
2213
+
2214
+ if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) {
2215
+ graph[prevNodeId][key] =
2216
+ getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) -
2217
+ getSegmentBitsLength(table[prevNodeId].lastCount, node.mode);
2218
+
2219
+ table[prevNodeId].lastCount += node.length;
2220
+ } else {
2221
+ if (table[prevNodeId]) table[prevNodeId].lastCount = node.length;
2222
+
2223
+ graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) +
2224
+ 4 + Mode.getCharCountIndicator(node.mode, version); // switch cost
2225
+ }
2226
+ }
2227
+ }
2228
+
2229
+ prevNodeIds = currentNodeIds;
2230
+ }
2231
+
2232
+ for (let n = 0; n < prevNodeIds.length; n++) {
2233
+ graph[prevNodeIds[n]].end = 0;
2234
+ }
2235
+
2236
+ return { map: graph, table: table }
2237
+ }
2238
+
2239
+ /**
2240
+ * Builds a segment from a specified data and mode.
2241
+ * If a mode is not specified, the more suitable will be used.
2242
+ *
2243
+ * @param {String} data Input data
2244
+ * @param {Mode | String} modesHint Data mode
2245
+ * @return {Segment} Segment
2246
+ */
2247
+ function buildSingleSegment (data, modesHint) {
2248
+ let mode;
2249
+ const bestMode = Mode.getBestModeForData(data);
2250
+
2251
+ mode = Mode.from(modesHint, bestMode);
2252
+
2253
+ // Make sure data can be encoded
2254
+ if (mode !== Mode.BYTE && mode.bit < bestMode.bit) {
2255
+ throw new Error('"' + data + '"' +
2256
+ ' cannot be encoded with mode ' + Mode.toString(mode) +
2257
+ '.\n Suggested mode is: ' + Mode.toString(bestMode))
2258
+ }
2259
+
2260
+ // Use Mode.BYTE if Kanji support is disabled
2261
+ if (mode === Mode.KANJI && !Utils.isKanjiModeEnabled()) {
2262
+ mode = Mode.BYTE;
2263
+ }
2264
+
2265
+ switch (mode) {
2266
+ case Mode.NUMERIC:
2267
+ return new NumericData(data)
2268
+
2269
+ case Mode.ALPHANUMERIC:
2270
+ return new AlphanumericData(data)
2271
+
2272
+ case Mode.KANJI:
2273
+ return new KanjiData(data)
2274
+
2275
+ case Mode.BYTE:
2276
+ return new ByteData(data)
2277
+ }
2278
+ }
2279
+
2280
+ /**
2281
+ * Builds a list of segments from an array.
2282
+ * Array can contain Strings or Objects with segment's info.
2283
+ *
2284
+ * For each item which is a string, will be generated a segment with the given
2285
+ * string and the more appropriate encoding mode.
2286
+ *
2287
+ * For each item which is an object, will be generated a segment with the given
2288
+ * data and mode.
2289
+ * Objects must contain at least the property "data".
2290
+ * If property "mode" is not present, the more suitable mode will be used.
2291
+ *
2292
+ * @param {Array} array Array of objects with segments data
2293
+ * @return {Array} Array of Segments
2294
+ */
2295
+ exports.fromArray = function fromArray (array) {
2296
+ return array.reduce(function (acc, seg) {
2297
+ if (typeof seg === 'string') {
2298
+ acc.push(buildSingleSegment(seg, null));
2299
+ } else if (seg.data) {
2300
+ acc.push(buildSingleSegment(seg.data, seg.mode));
2301
+ }
2302
+
2303
+ return acc
2304
+ }, [])
2305
+ };
2306
+
2307
+ /**
2308
+ * Builds an optimized sequence of segments from a string,
2309
+ * which will produce the shortest possible bitstream.
2310
+ *
2311
+ * @param {String} data Input string
2312
+ * @param {Number} version QR Code version
2313
+ * @return {Array} Array of segments
2314
+ */
2315
+ exports.fromString = function fromString (data, version) {
2316
+ const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled());
2317
+
2318
+ const nodes = buildNodes(segs);
2319
+ const graph = buildGraph(nodes, version);
2320
+ const path = dijkstra.find_path(graph.map, 'start', 'end');
2321
+
2322
+ const optimizedSegs = [];
2323
+ for (let i = 1; i < path.length - 1; i++) {
2324
+ optimizedSegs.push(graph.table[path[i]].node);
2325
+ }
2326
+
2327
+ return exports.fromArray(mergeSegments(optimizedSegs))
2328
+ };
2329
+
2330
+ /**
2331
+ * Splits a string in various segments with the modes which
2332
+ * best represent their content.
2333
+ * The produced segments are far from being optimized.
2334
+ * The output of this function is only used to estimate a QR Code version
2335
+ * which may contain the data.
2336
+ *
2337
+ * @param {string} data Input string
2338
+ * @return {Array} Array of segments
2339
+ */
2340
+ exports.rawSplit = function rawSplit (data) {
2341
+ return exports.fromArray(
2342
+ getSegmentsFromString(data, Utils.isKanjiModeEnabled())
2343
+ )
2344
+ };
2345
+ } (segments));
2346
+ return segments;
2347
+ }
2348
+
2349
+ var hasRequiredQrcode;
2350
+
2351
+ function requireQrcode () {
2352
+ if (hasRequiredQrcode) return qrcode;
2353
+ hasRequiredQrcode = 1;
2354
+ const Utils = requireUtils$1();
2355
+ const ECLevel = requireErrorCorrectionLevel();
2356
+ const BitBuffer = requireBitBuffer();
2357
+ const BitMatrix = requireBitMatrix();
2358
+ const AlignmentPattern = requireAlignmentPattern();
2359
+ const FinderPattern = requireFinderPattern();
2360
+ const MaskPattern = requireMaskPattern();
2361
+ const ECCode = requireErrorCorrectionCode();
2362
+ const ReedSolomonEncoder = requireReedSolomonEncoder();
2363
+ const Version = requireVersion();
2364
+ const FormatInfo = requireFormatInfo();
2365
+ const Mode = requireMode();
2366
+ const Segments = requireSegments();
2367
+
2368
+ /**
2369
+ * QRCode for JavaScript
2370
+ *
2371
+ * modified by Ryan Day for nodejs support
2372
+ * Copyright (c) 2011 Ryan Day
2373
+ *
2374
+ * Licensed under the MIT license:
2375
+ * http://www.opensource.org/licenses/mit-license.php
2376
+ *
2377
+ //---------------------------------------------------------------------
2378
+ // QRCode for JavaScript
2379
+ //
2380
+ // Copyright (c) 2009 Kazuhiko Arase
2381
+ //
2382
+ // URL: http://www.d-project.com/
2383
+ //
2384
+ // Licensed under the MIT license:
2385
+ // http://www.opensource.org/licenses/mit-license.php
2386
+ //
2387
+ // The word "QR Code" is registered trademark of
2388
+ // DENSO WAVE INCORPORATED
2389
+ // http://www.denso-wave.com/qrcode/faqpatent-e.html
2390
+ //
2391
+ //---------------------------------------------------------------------
2392
+ */
2393
+
2394
+ /**
2395
+ * Add finder patterns bits to matrix
2396
+ *
2397
+ * @param {BitMatrix} matrix Modules matrix
2398
+ * @param {Number} version QR Code version
2399
+ */
2400
+ function setupFinderPattern (matrix, version) {
2401
+ const size = matrix.size;
2402
+ const pos = FinderPattern.getPositions(version);
2403
+
2404
+ for (let i = 0; i < pos.length; i++) {
2405
+ const row = pos[i][0];
2406
+ const col = pos[i][1];
2407
+
2408
+ for (let r = -1; r <= 7; r++) {
2409
+ if (row + r <= -1 || size <= row + r) continue
2410
+
2411
+ for (let c = -1; c <= 7; c++) {
2412
+ if (col + c <= -1 || size <= col + c) continue
2413
+
2414
+ if ((r >= 0 && r <= 6 && (c === 0 || c === 6)) ||
2415
+ (c >= 0 && c <= 6 && (r === 0 || r === 6)) ||
2416
+ (r >= 2 && r <= 4 && c >= 2 && c <= 4)) {
2417
+ matrix.set(row + r, col + c, true, true);
2418
+ } else {
2419
+ matrix.set(row + r, col + c, false, true);
2420
+ }
2421
+ }
2422
+ }
2423
+ }
2424
+ }
2425
+
2426
+ /**
2427
+ * Add timing pattern bits to matrix
2428
+ *
2429
+ * Note: this function must be called before {@link setupAlignmentPattern}
2430
+ *
2431
+ * @param {BitMatrix} matrix Modules matrix
2432
+ */
2433
+ function setupTimingPattern (matrix) {
2434
+ const size = matrix.size;
2435
+
2436
+ for (let r = 8; r < size - 8; r++) {
2437
+ const value = r % 2 === 0;
2438
+ matrix.set(r, 6, value, true);
2439
+ matrix.set(6, r, value, true);
2440
+ }
2441
+ }
2442
+
2443
+ /**
2444
+ * Add alignment patterns bits to matrix
2445
+ *
2446
+ * Note: this function must be called after {@link setupTimingPattern}
2447
+ *
2448
+ * @param {BitMatrix} matrix Modules matrix
2449
+ * @param {Number} version QR Code version
2450
+ */
2451
+ function setupAlignmentPattern (matrix, version) {
2452
+ const pos = AlignmentPattern.getPositions(version);
2453
+
2454
+ for (let i = 0; i < pos.length; i++) {
2455
+ const row = pos[i][0];
2456
+ const col = pos[i][1];
2457
+
2458
+ for (let r = -2; r <= 2; r++) {
2459
+ for (let c = -2; c <= 2; c++) {
2460
+ if (r === -2 || r === 2 || c === -2 || c === 2 ||
2461
+ (r === 0 && c === 0)) {
2462
+ matrix.set(row + r, col + c, true, true);
2463
+ } else {
2464
+ matrix.set(row + r, col + c, false, true);
2465
+ }
2466
+ }
2467
+ }
2468
+ }
2469
+ }
2470
+
2471
+ /**
2472
+ * Add version info bits to matrix
2473
+ *
2474
+ * @param {BitMatrix} matrix Modules matrix
2475
+ * @param {Number} version QR Code version
2476
+ */
2477
+ function setupVersionInfo (matrix, version) {
2478
+ const size = matrix.size;
2479
+ const bits = Version.getEncodedBits(version);
2480
+ let row, col, mod;
2481
+
2482
+ for (let i = 0; i < 18; i++) {
2483
+ row = Math.floor(i / 3);
2484
+ col = i % 3 + size - 8 - 3;
2485
+ mod = ((bits >> i) & 1) === 1;
2486
+
2487
+ matrix.set(row, col, mod, true);
2488
+ matrix.set(col, row, mod, true);
2489
+ }
2490
+ }
2491
+
2492
+ /**
2493
+ * Add format info bits to matrix
2494
+ *
2495
+ * @param {BitMatrix} matrix Modules matrix
2496
+ * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level
2497
+ * @param {Number} maskPattern Mask pattern reference value
2498
+ */
2499
+ function setupFormatInfo (matrix, errorCorrectionLevel, maskPattern) {
2500
+ const size = matrix.size;
2501
+ const bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern);
2502
+ let i, mod;
2503
+
2504
+ for (i = 0; i < 15; i++) {
2505
+ mod = ((bits >> i) & 1) === 1;
2506
+
2507
+ // vertical
2508
+ if (i < 6) {
2509
+ matrix.set(i, 8, mod, true);
2510
+ } else if (i < 8) {
2511
+ matrix.set(i + 1, 8, mod, true);
2512
+ } else {
2513
+ matrix.set(size - 15 + i, 8, mod, true);
2514
+ }
2515
+
2516
+ // horizontal
2517
+ if (i < 8) {
2518
+ matrix.set(8, size - i - 1, mod, true);
2519
+ } else if (i < 9) {
2520
+ matrix.set(8, 15 - i - 1 + 1, mod, true);
2521
+ } else {
2522
+ matrix.set(8, 15 - i - 1, mod, true);
2523
+ }
2524
+ }
2525
+
2526
+ // fixed module
2527
+ matrix.set(size - 8, 8, 1, true);
2528
+ }
2529
+
2530
+ /**
2531
+ * Add encoded data bits to matrix
2532
+ *
2533
+ * @param {BitMatrix} matrix Modules matrix
2534
+ * @param {Uint8Array} data Data codewords
2535
+ */
2536
+ function setupData (matrix, data) {
2537
+ const size = matrix.size;
2538
+ let inc = -1;
2539
+ let row = size - 1;
2540
+ let bitIndex = 7;
2541
+ let byteIndex = 0;
2542
+
2543
+ for (let col = size - 1; col > 0; col -= 2) {
2544
+ if (col === 6) col--;
2545
+
2546
+ while (true) {
2547
+ for (let c = 0; c < 2; c++) {
2548
+ if (!matrix.isReserved(row, col - c)) {
2549
+ let dark = false;
2550
+
2551
+ if (byteIndex < data.length) {
2552
+ dark = (((data[byteIndex] >>> bitIndex) & 1) === 1);
2553
+ }
2554
+
2555
+ matrix.set(row, col - c, dark);
2556
+ bitIndex--;
2557
+
2558
+ if (bitIndex === -1) {
2559
+ byteIndex++;
2560
+ bitIndex = 7;
2561
+ }
2562
+ }
2563
+ }
2564
+
2565
+ row += inc;
2566
+
2567
+ if (row < 0 || size <= row) {
2568
+ row -= inc;
2569
+ inc = -inc;
2570
+ break
2571
+ }
2572
+ }
2573
+ }
2574
+ }
2575
+
2576
+ /**
2577
+ * Create encoded codewords from data input
2578
+ *
2579
+ * @param {Number} version QR Code version
2580
+ * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level
2581
+ * @param {ByteData} data Data input
2582
+ * @return {Uint8Array} Buffer containing encoded codewords
2583
+ */
2584
+ function createData (version, errorCorrectionLevel, segments) {
2585
+ // Prepare data buffer
2586
+ const buffer = new BitBuffer();
2587
+
2588
+ segments.forEach(function (data) {
2589
+ // prefix data with mode indicator (4 bits)
2590
+ buffer.put(data.mode.bit, 4);
2591
+
2592
+ // Prefix data with character count indicator.
2593
+ // The character count indicator is a string of bits that represents the
2594
+ // number of characters that are being encoded.
2595
+ // The character count indicator must be placed after the mode indicator
2596
+ // and must be a certain number of bits long, depending on the QR version
2597
+ // and data mode
2598
+ // @see {@link Mode.getCharCountIndicator}.
2599
+ buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version));
2600
+
2601
+ // add binary data sequence to buffer
2602
+ data.write(buffer);
2603
+ });
2604
+
2605
+ // Calculate required number of bits
2606
+ const totalCodewords = Utils.getSymbolTotalCodewords(version);
2607
+ const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel);
2608
+ const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8;
2609
+
2610
+ // Add a terminator.
2611
+ // If the bit string is shorter than the total number of required bits,
2612
+ // a terminator of up to four 0s must be added to the right side of the string.
2613
+ // If the bit string is more than four bits shorter than the required number of bits,
2614
+ // add four 0s to the end.
2615
+ if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) {
2616
+ buffer.put(0, 4);
2617
+ }
2618
+
2619
+ // If the bit string is fewer than four bits shorter, add only the number of 0s that
2620
+ // are needed to reach the required number of bits.
2621
+
2622
+ // After adding the terminator, if the number of bits in the string is not a multiple of 8,
2623
+ // pad the string on the right with 0s to make the string's length a multiple of 8.
2624
+ while (buffer.getLengthInBits() % 8 !== 0) {
2625
+ buffer.putBit(0);
2626
+ }
2627
+
2628
+ // Add pad bytes if the string is still shorter than the total number of required bits.
2629
+ // Extend the buffer to fill the data capacity of the symbol corresponding to
2630
+ // the Version and Error Correction Level by adding the Pad Codewords 11101100 (0xEC)
2631
+ // and 00010001 (0x11) alternately.
2632
+ const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8;
2633
+ for (let i = 0; i < remainingByte; i++) {
2634
+ buffer.put(i % 2 ? 0x11 : 0xEC, 8);
2635
+ }
2636
+
2637
+ return createCodewords(buffer, version, errorCorrectionLevel)
2638
+ }
2639
+
2640
+ /**
2641
+ * Encode input data with Reed-Solomon and return codewords with
2642
+ * relative error correction bits
2643
+ *
2644
+ * @param {BitBuffer} bitBuffer Data to encode
2645
+ * @param {Number} version QR Code version
2646
+ * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level
2647
+ * @return {Uint8Array} Buffer containing encoded codewords
2648
+ */
2649
+ function createCodewords (bitBuffer, version, errorCorrectionLevel) {
2650
+ // Total codewords for this QR code version (Data + Error correction)
2651
+ const totalCodewords = Utils.getSymbolTotalCodewords(version);
2652
+
2653
+ // Total number of error correction codewords
2654
+ const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel);
2655
+
2656
+ // Total number of data codewords
2657
+ const dataTotalCodewords = totalCodewords - ecTotalCodewords;
2658
+
2659
+ // Total number of blocks
2660
+ const ecTotalBlocks = ECCode.getBlocksCount(version, errorCorrectionLevel);
2661
+
2662
+ // Calculate how many blocks each group should contain
2663
+ const blocksInGroup2 = totalCodewords % ecTotalBlocks;
2664
+ const blocksInGroup1 = ecTotalBlocks - blocksInGroup2;
2665
+
2666
+ const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks);
2667
+
2668
+ const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks);
2669
+ const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1;
2670
+
2671
+ // Number of EC codewords is the same for both groups
2672
+ const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1;
2673
+
2674
+ // Initialize a Reed-Solomon encoder with a generator polynomial of degree ecCount
2675
+ const rs = new ReedSolomonEncoder(ecCount);
2676
+
2677
+ let offset = 0;
2678
+ const dcData = new Array(ecTotalBlocks);
2679
+ const ecData = new Array(ecTotalBlocks);
2680
+ let maxDataSize = 0;
2681
+ const buffer = new Uint8Array(bitBuffer.buffer);
2682
+
2683
+ // Divide the buffer into the required number of blocks
2684
+ for (let b = 0; b < ecTotalBlocks; b++) {
2685
+ const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2;
2686
+
2687
+ // extract a block of data from buffer
2688
+ dcData[b] = buffer.slice(offset, offset + dataSize);
2689
+
2690
+ // Calculate EC codewords for this data block
2691
+ ecData[b] = rs.encode(dcData[b]);
2692
+
2693
+ offset += dataSize;
2694
+ maxDataSize = Math.max(maxDataSize, dataSize);
2695
+ }
2696
+
2697
+ // Create final data
2698
+ // Interleave the data and error correction codewords from each block
2699
+ const data = new Uint8Array(totalCodewords);
2700
+ let index = 0;
2701
+ let i, r;
2702
+
2703
+ // Add data codewords
2704
+ for (i = 0; i < maxDataSize; i++) {
2705
+ for (r = 0; r < ecTotalBlocks; r++) {
2706
+ if (i < dcData[r].length) {
2707
+ data[index++] = dcData[r][i];
2708
+ }
2709
+ }
2710
+ }
2711
+
2712
+ // Apped EC codewords
2713
+ for (i = 0; i < ecCount; i++) {
2714
+ for (r = 0; r < ecTotalBlocks; r++) {
2715
+ data[index++] = ecData[r][i];
2716
+ }
2717
+ }
2718
+
2719
+ return data
2720
+ }
2721
+
2722
+ /**
2723
+ * Build QR Code symbol
2724
+ *
2725
+ * @param {String} data Input string
2726
+ * @param {Number} version QR Code version
2727
+ * @param {ErrorCorretionLevel} errorCorrectionLevel Error level
2728
+ * @param {MaskPattern} maskPattern Mask pattern
2729
+ * @return {Object} Object containing symbol data
2730
+ */
2731
+ function createSymbol (data, version, errorCorrectionLevel, maskPattern) {
2732
+ let segments;
2733
+
2734
+ if (Array.isArray(data)) {
2735
+ segments = Segments.fromArray(data);
2736
+ } else if (typeof data === 'string') {
2737
+ let estimatedVersion = version;
2738
+
2739
+ if (!estimatedVersion) {
2740
+ const rawSegments = Segments.rawSplit(data);
2741
+
2742
+ // Estimate best version that can contain raw splitted segments
2743
+ estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel);
2744
+ }
2745
+
2746
+ // Build optimized segments
2747
+ // If estimated version is undefined, try with the highest version
2748
+ segments = Segments.fromString(data, estimatedVersion || 40);
2749
+ } else {
2750
+ throw new Error('Invalid data')
2751
+ }
2752
+
2753
+ // Get the min version that can contain data
2754
+ const bestVersion = Version.getBestVersionForData(segments, errorCorrectionLevel);
2755
+
2756
+ // If no version is found, data cannot be stored
2757
+ if (!bestVersion) {
2758
+ throw new Error('The amount of data is too big to be stored in a QR Code')
2759
+ }
2760
+
2761
+ // If not specified, use min version as default
2762
+ if (!version) {
2763
+ version = bestVersion;
2764
+
2765
+ // Check if the specified version can contain the data
2766
+ } else if (version < bestVersion) {
2767
+ throw new Error('\n' +
2768
+ 'The chosen QR Code version cannot contain this amount of data.\n' +
2769
+ 'Minimum version required to store current data is: ' + bestVersion + '.\n'
2770
+ )
2771
+ }
2772
+
2773
+ const dataBits = createData(version, errorCorrectionLevel, segments);
2774
+
2775
+ // Allocate matrix buffer
2776
+ const moduleCount = Utils.getSymbolSize(version);
2777
+ const modules = new BitMatrix(moduleCount);
2778
+
2779
+ // Add function modules
2780
+ setupFinderPattern(modules, version);
2781
+ setupTimingPattern(modules);
2782
+ setupAlignmentPattern(modules, version);
2783
+
2784
+ // Add temporary dummy bits for format info just to set them as reserved.
2785
+ // This is needed to prevent these bits from being masked by {@link MaskPattern.applyMask}
2786
+ // since the masking operation must be performed only on the encoding region.
2787
+ // These blocks will be replaced with correct values later in code.
2788
+ setupFormatInfo(modules, errorCorrectionLevel, 0);
2789
+
2790
+ if (version >= 7) {
2791
+ setupVersionInfo(modules, version);
2792
+ }
2793
+
2794
+ // Add data codewords
2795
+ setupData(modules, dataBits);
2796
+
2797
+ if (isNaN(maskPattern)) {
2798
+ // Find best mask pattern
2799
+ maskPattern = MaskPattern.getBestMask(modules,
2800
+ setupFormatInfo.bind(null, modules, errorCorrectionLevel));
2801
+ }
2802
+
2803
+ // Apply mask pattern
2804
+ MaskPattern.applyMask(maskPattern, modules);
2805
+
2806
+ // Replace format info bits with correct values
2807
+ setupFormatInfo(modules, errorCorrectionLevel, maskPattern);
2808
+
2809
+ return {
2810
+ modules: modules,
2811
+ version: version,
2812
+ errorCorrectionLevel: errorCorrectionLevel,
2813
+ maskPattern: maskPattern,
2814
+ segments: segments
2815
+ }
2816
+ }
2817
+
2818
+ /**
2819
+ * QR Code
2820
+ *
2821
+ * @param {String | Array} data Input data
2822
+ * @param {Object} options Optional configurations
2823
+ * @param {Number} options.version QR Code version
2824
+ * @param {String} options.errorCorrectionLevel Error correction level
2825
+ * @param {Function} options.toSJISFunc Helper func to convert utf8 to sjis
2826
+ */
2827
+ qrcode.create = function create (data, options) {
2828
+ if (typeof data === 'undefined' || data === '') {
2829
+ throw new Error('No input text')
2830
+ }
2831
+
2832
+ let errorCorrectionLevel = ECLevel.M;
2833
+ let version;
2834
+ let mask;
2835
+
2836
+ if (typeof options !== 'undefined') {
2837
+ // Use higher error correction level as default
2838
+ errorCorrectionLevel = ECLevel.from(options.errorCorrectionLevel, ECLevel.M);
2839
+ version = Version.from(options.version);
2840
+ mask = MaskPattern.from(options.maskPattern);
2841
+
2842
+ if (options.toSJISFunc) {
2843
+ Utils.setToSJISFunction(options.toSJISFunc);
2844
+ }
2845
+ }
2846
+
2847
+ return createSymbol(data, version, errorCorrectionLevel, mask)
2848
+ };
2849
+ return qrcode;
2850
+ }
2851
+
2852
+ var canvas = {};
2853
+
2854
+ var utils = {};
2855
+
2856
+ var hasRequiredUtils;
2857
+
2858
+ function requireUtils () {
2859
+ if (hasRequiredUtils) return utils;
2860
+ hasRequiredUtils = 1;
2861
+ (function (exports) {
2862
+ function hex2rgba (hex) {
2863
+ if (typeof hex === 'number') {
2864
+ hex = hex.toString();
2865
+ }
2866
+
2867
+ if (typeof hex !== 'string') {
2868
+ throw new Error('Color should be defined as hex string')
2869
+ }
2870
+
2871
+ let hexCode = hex.slice().replace('#', '').split('');
2872
+ if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) {
2873
+ throw new Error('Invalid hex color: ' + hex)
2874
+ }
2875
+
2876
+ // Convert from short to long form (fff -> ffffff)
2877
+ if (hexCode.length === 3 || hexCode.length === 4) {
2878
+ hexCode = Array.prototype.concat.apply([], hexCode.map(function (c) {
2879
+ return [c, c]
2880
+ }));
2881
+ }
2882
+
2883
+ // Add default alpha value
2884
+ if (hexCode.length === 6) hexCode.push('F', 'F');
2885
+
2886
+ const hexValue = parseInt(hexCode.join(''), 16);
2887
+
2888
+ return {
2889
+ r: (hexValue >> 24) & 255,
2890
+ g: (hexValue >> 16) & 255,
2891
+ b: (hexValue >> 8) & 255,
2892
+ a: hexValue & 255,
2893
+ hex: '#' + hexCode.slice(0, 6).join('')
2894
+ }
2895
+ }
2896
+
2897
+ exports.getOptions = function getOptions (options) {
2898
+ if (!options) options = {};
2899
+ if (!options.color) options.color = {};
2900
+
2901
+ const margin = typeof options.margin === 'undefined' ||
2902
+ options.margin === null ||
2903
+ options.margin < 0
2904
+ ? 4
2905
+ : options.margin;
2906
+
2907
+ const width = options.width && options.width >= 21 ? options.width : undefined;
2908
+ const scale = options.scale || 4;
2909
+
2910
+ return {
2911
+ width: width,
2912
+ scale: width ? 4 : scale,
2913
+ margin: margin,
2914
+ color: {
2915
+ dark: hex2rgba(options.color.dark || '#000000ff'),
2916
+ light: hex2rgba(options.color.light || '#ffffffff')
2917
+ },
2918
+ type: options.type,
2919
+ rendererOpts: options.rendererOpts || {}
2920
+ }
2921
+ };
2922
+
2923
+ exports.getScale = function getScale (qrSize, opts) {
2924
+ return opts.width && opts.width >= qrSize + opts.margin * 2
2925
+ ? opts.width / (qrSize + opts.margin * 2)
2926
+ : opts.scale
2927
+ };
2928
+
2929
+ exports.getImageWidth = function getImageWidth (qrSize, opts) {
2930
+ const scale = exports.getScale(qrSize, opts);
2931
+ return Math.floor((qrSize + opts.margin * 2) * scale)
2932
+ };
2933
+
2934
+ exports.qrToImageData = function qrToImageData (imgData, qr, opts) {
2935
+ const size = qr.modules.size;
2936
+ const data = qr.modules.data;
2937
+ const scale = exports.getScale(size, opts);
2938
+ const symbolSize = Math.floor((size + opts.margin * 2) * scale);
2939
+ const scaledMargin = opts.margin * scale;
2940
+ const palette = [opts.color.light, opts.color.dark];
2941
+
2942
+ for (let i = 0; i < symbolSize; i++) {
2943
+ for (let j = 0; j < symbolSize; j++) {
2944
+ let posDst = (i * symbolSize + j) * 4;
2945
+ let pxColor = opts.color.light;
2946
+
2947
+ if (i >= scaledMargin && j >= scaledMargin &&
2948
+ i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) {
2949
+ const iSrc = Math.floor((i - scaledMargin) / scale);
2950
+ const jSrc = Math.floor((j - scaledMargin) / scale);
2951
+ pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0];
2952
+ }
2953
+
2954
+ imgData[posDst++] = pxColor.r;
2955
+ imgData[posDst++] = pxColor.g;
2956
+ imgData[posDst++] = pxColor.b;
2957
+ imgData[posDst] = pxColor.a;
2958
+ }
2959
+ }
2960
+ };
2961
+ } (utils));
2962
+ return utils;
2963
+ }
2964
+
2965
+ var hasRequiredCanvas;
2966
+
2967
+ function requireCanvas () {
2968
+ if (hasRequiredCanvas) return canvas;
2969
+ hasRequiredCanvas = 1;
2970
+ (function (exports) {
2971
+ const Utils = requireUtils();
2972
+
2973
+ function clearCanvas (ctx, canvas, size) {
2974
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
2975
+
2976
+ if (!canvas.style) canvas.style = {};
2977
+ canvas.height = size;
2978
+ canvas.width = size;
2979
+ canvas.style.height = size + 'px';
2980
+ canvas.style.width = size + 'px';
2981
+ }
2982
+
2983
+ function getCanvasElement () {
2984
+ try {
2985
+ return document.createElement('canvas')
2986
+ } catch (e) {
2987
+ throw new Error('You need to specify a canvas element')
2988
+ }
2989
+ }
2990
+
2991
+ exports.render = function render (qrData, canvas, options) {
2992
+ let opts = options;
2993
+ let canvasEl = canvas;
2994
+
2995
+ if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) {
2996
+ opts = canvas;
2997
+ canvas = undefined;
2998
+ }
2999
+
3000
+ if (!canvas) {
3001
+ canvasEl = getCanvasElement();
3002
+ }
3003
+
3004
+ opts = Utils.getOptions(opts);
3005
+ const size = Utils.getImageWidth(qrData.modules.size, opts);
3006
+
3007
+ const ctx = canvasEl.getContext('2d');
3008
+ const image = ctx.createImageData(size, size);
3009
+ Utils.qrToImageData(image.data, qrData, opts);
3010
+
3011
+ clearCanvas(ctx, canvasEl, size);
3012
+ ctx.putImageData(image, 0, 0);
3013
+
3014
+ return canvasEl
3015
+ };
3016
+
3017
+ exports.renderToDataURL = function renderToDataURL (qrData, canvas, options) {
3018
+ let opts = options;
3019
+
3020
+ if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) {
3021
+ opts = canvas;
3022
+ canvas = undefined;
3023
+ }
3024
+
3025
+ if (!opts) opts = {};
3026
+
3027
+ const canvasEl = exports.render(qrData, canvas, opts);
3028
+
3029
+ const type = opts.type || 'image/png';
3030
+ const rendererOpts = opts.rendererOpts || {};
3031
+
3032
+ return canvasEl.toDataURL(type, rendererOpts.quality)
3033
+ };
3034
+ } (canvas));
3035
+ return canvas;
3036
+ }
3037
+
3038
+ var svgTag = {};
3039
+
3040
+ var hasRequiredSvgTag;
3041
+
3042
+ function requireSvgTag () {
3043
+ if (hasRequiredSvgTag) return svgTag;
3044
+ hasRequiredSvgTag = 1;
3045
+ const Utils = requireUtils();
3046
+
3047
+ function getColorAttrib (color, attrib) {
3048
+ const alpha = color.a / 255;
3049
+ const str = attrib + '="' + color.hex + '"';
3050
+
3051
+ return alpha < 1
3052
+ ? str + ' ' + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"'
3053
+ : str
3054
+ }
3055
+
3056
+ function svgCmd (cmd, x, y) {
3057
+ let str = cmd + x;
3058
+ if (typeof y !== 'undefined') str += ' ' + y;
3059
+
3060
+ return str
3061
+ }
3062
+
3063
+ function qrToPath (data, size, margin) {
3064
+ let path = '';
3065
+ let moveBy = 0;
3066
+ let newRow = false;
3067
+ let lineLength = 0;
3068
+
3069
+ for (let i = 0; i < data.length; i++) {
3070
+ const col = Math.floor(i % size);
3071
+ const row = Math.floor(i / size);
3072
+
3073
+ if (!col && !newRow) newRow = true;
3074
+
3075
+ if (data[i]) {
3076
+ lineLength++;
3077
+
3078
+ if (!(i > 0 && col > 0 && data[i - 1])) {
3079
+ path += newRow
3080
+ ? svgCmd('M', col + margin, 0.5 + row + margin)
3081
+ : svgCmd('m', moveBy, 0);
3082
+
3083
+ moveBy = 0;
3084
+ newRow = false;
3085
+ }
3086
+
3087
+ if (!(col + 1 < size && data[i + 1])) {
3088
+ path += svgCmd('h', lineLength);
3089
+ lineLength = 0;
3090
+ }
3091
+ } else {
3092
+ moveBy++;
3093
+ }
3094
+ }
3095
+
3096
+ return path
3097
+ }
3098
+
3099
+ svgTag.render = function render (qrData, options, cb) {
3100
+ const opts = Utils.getOptions(options);
3101
+ const size = qrData.modules.size;
3102
+ const data = qrData.modules.data;
3103
+ const qrcodesize = size + opts.margin * 2;
3104
+
3105
+ const bg = !opts.color.light.a
3106
+ ? ''
3107
+ : '<path ' + getColorAttrib(opts.color.light, 'fill') +
3108
+ ' d="M0 0h' + qrcodesize + 'v' + qrcodesize + 'H0z"/>';
3109
+
3110
+ const path =
3111
+ '<path ' + getColorAttrib(opts.color.dark, 'stroke') +
3112
+ ' d="' + qrToPath(data, size, opts.margin) + '"/>';
3113
+
3114
+ const viewBox = 'viewBox="' + '0 0 ' + qrcodesize + ' ' + qrcodesize + '"';
3115
+
3116
+ const width = !opts.width ? '' : 'width="' + opts.width + '" height="' + opts.width + '" ';
3117
+
3118
+ const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path + '</svg>\n';
3119
+
3120
+ if (typeof cb === 'function') {
3121
+ cb(null, svgTag);
3122
+ }
3123
+
3124
+ return svgTag
3125
+ };
3126
+ return svgTag;
3127
+ }
3128
+
3129
+ var hasRequiredBrowser;
3130
+
3131
+ function requireBrowser () {
3132
+ if (hasRequiredBrowser) return browser;
3133
+ hasRequiredBrowser = 1;
3134
+ const canPromise = requireCanPromise();
3135
+
3136
+ const QRCode = requireQrcode();
3137
+ const CanvasRenderer = requireCanvas();
3138
+ const SvgRenderer = requireSvgTag();
3139
+
3140
+ function renderCanvas (renderFunc, canvas, text, opts, cb) {
3141
+ const args = [].slice.call(arguments, 1);
3142
+ const argsNum = args.length;
3143
+ const isLastArgCb = typeof args[argsNum - 1] === 'function';
3144
+
3145
+ if (!isLastArgCb && !canPromise()) {
3146
+ throw new Error('Callback required as last argument')
3147
+ }
3148
+
3149
+ if (isLastArgCb) {
3150
+ if (argsNum < 2) {
3151
+ throw new Error('Too few arguments provided')
3152
+ }
3153
+
3154
+ if (argsNum === 2) {
3155
+ cb = text;
3156
+ text = canvas;
3157
+ canvas = opts = undefined;
3158
+ } else if (argsNum === 3) {
3159
+ if (canvas.getContext && typeof cb === 'undefined') {
3160
+ cb = opts;
3161
+ opts = undefined;
3162
+ } else {
3163
+ cb = opts;
3164
+ opts = text;
3165
+ text = canvas;
3166
+ canvas = undefined;
3167
+ }
3168
+ }
3169
+ } else {
3170
+ if (argsNum < 1) {
3171
+ throw new Error('Too few arguments provided')
3172
+ }
3173
+
3174
+ if (argsNum === 1) {
3175
+ text = canvas;
3176
+ canvas = opts = undefined;
3177
+ } else if (argsNum === 2 && !canvas.getContext) {
3178
+ opts = text;
3179
+ text = canvas;
3180
+ canvas = undefined;
3181
+ }
3182
+
3183
+ return new Promise(function (resolve, reject) {
3184
+ try {
3185
+ const data = QRCode.create(text, opts);
3186
+ resolve(renderFunc(data, canvas, opts));
3187
+ } catch (e) {
3188
+ reject(e);
3189
+ }
3190
+ })
3191
+ }
3192
+
3193
+ try {
3194
+ const data = QRCode.create(text, opts);
3195
+ cb(null, renderFunc(data, canvas, opts));
3196
+ } catch (e) {
3197
+ cb(e);
3198
+ }
3199
+ }
3200
+
3201
+ browser.create = QRCode.create;
3202
+ browser.toCanvas = renderCanvas.bind(null, CanvasRenderer.render);
3203
+ browser.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL);
3204
+
3205
+ // only svg for now.
3206
+ browser.toString = renderCanvas.bind(null, function (data, _, opts) {
3207
+ return SvgRenderer.render(data, opts)
3208
+ });
3209
+ return browser;
145
3210
  }
146
3211
 
3212
+ var browserExports = requireBrowser();
3213
+
147
3214
  async function getMiniProgramRuntimeUserInfo(platformAdapter) {
148
3215
  const userId = await resolveCurrentUserId(platformAdapter);
149
3216
  if (!userId) {
@@ -317,6 +3384,24 @@ function stringifyMiniProgramRuntimeJsonData(data, options) {
317
3384
  return value;
318
3385
  }
319
3386
 
3387
+ /** 设置导航栏关闭按钮与状态栏图标/文字的前景样式。 */
3388
+ function setMiniProgramRuntimeNavigationBarStyle(payload, platformAdapter) {
3389
+ return platformAdapter.viewport.setNavigationBarStyle(readMiniProgramNavigationBarStyleOptions(payload));
3390
+ }
3391
+ function readMiniProgramNavigationBarStyleOptions(payload) {
3392
+ assertMiniProgramRuntimeRecord(payload, 'viewport.setNavigationBarStyle 参数必须是对象');
3393
+ const foregroundStyle = payload.foregroundStyle;
3394
+ if (!isNavigationBarForegroundStyle(foregroundStyle)) {
3395
+ throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'viewport.setNavigationBarStyle foregroundStyle 必须是 light 或 dark');
3396
+ }
3397
+ return {
3398
+ foregroundStyle,
3399
+ };
3400
+ }
3401
+ function isNavigationBarForegroundStyle(value) {
3402
+ return value === 'light' || value === 'dark';
3403
+ }
3404
+
320
3405
  /** 展示基础分享面板。 */
321
3406
  function showMiniProgramRuntimeShareMenu(payload, platformAdapter) {
322
3407
  return platformAdapter.share.showShareMenu(readMiniProgramShareMenuOptions(payload));
@@ -684,6 +3769,7 @@ const MINI_PROGRAM_MOCK_RUNTIME_METHOD_HANDLERS = {
684
3769
  [SHARE_SHOW_SHARE_MENU_METHOD]: (runtime, payload) => runtime.showShareMenu(payload),
685
3770
  [SHARE_SCREENSHOT_METHOD]: (runtime, payload) => runtime.shareScreenshot(payload),
686
3771
  [VIEWPORT_GET_WINDOW_INFO_METHOD]: runtime => runtime.getWindowInfo(),
3772
+ [VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD]: (runtime, payload) => runtime.setNavigationBarStyle(payload),
687
3773
  [STORAGE_GET_STORAGE_METHOD]: (runtime, payload) => runtime.getStorage(payload),
688
3774
  [STORAGE_SET_STORAGE_METHOD]: (runtime, payload) => runtime.setStorage(payload),
689
3775
  [NETWORK_REQUEST_METHOD]: (runtime, payload) => runtime.requestNetwork(payload),
@@ -717,6 +3803,9 @@ class MiniProgramMockRuntime {
717
3803
  getWindowInfo() {
718
3804
  return getMiniProgramRuntimeWindowInfo(this.adapter);
719
3805
  }
3806
+ async setNavigationBarStyle(payload) {
3807
+ await setMiniProgramRuntimeNavigationBarStyle(payload, this.adapter);
3808
+ }
720
3809
  getStorage(payload) {
721
3810
  return getMiniProgramRuntimeStorage(payload, this.options.storage || {}, this.adapter);
722
3811
  }
@@ -756,13 +3845,21 @@ function isObjectLike(value) {
756
3845
  return (typeof value === 'object' || typeof value === 'function') && value !== null;
757
3846
  }
758
3847
 
3848
+ const MINI_PROGRAM_URL_QUERY_PARAM = 'mini_url';
3849
+ const MINI_PROGRAM_DEV_SHELL_URL = 'heybox-mini-dev://sandbox';
3850
+ const OPEN_IN_APP_URL = 'https://api.xiaoheihe.cn/open_inapp/';
759
3851
  const NETWORK_PROXY_PATH = '/__hb_sdk_mock_network__';
3852
+ const LAN_ADDRESSES_PATH = '/__hb_sdk_lan_addresses__';
760
3853
  const params = new URL(location.href).searchParams;
761
3854
  const miniUrl = params.get('mini_url');
3855
+ let lanAddresses = [];
3856
+ let defaultLanAddressId;
3857
+ let macAppProtocol;
762
3858
  const nonce = createNonce();
763
3859
  const storage = new Map();
764
3860
  const logs = [];
765
3861
  let handshaken = false;
3862
+ let navigationBarStyle = 'dark';
766
3863
  let currentUser = {
767
3864
  heybox_id: 'debug_user',
768
3865
  nickname: 'PC Debug User',
@@ -778,6 +3875,9 @@ const elements = {
778
3875
  macAppButton: queryElement('#mac-app-button'),
779
3876
  macAppStatus: queryElement('#mac-app-status'),
780
3877
  miniUrl: queryElement('#mini-url'),
3878
+ mobileLanSelect: queryElement('#mobile-lan-select'),
3879
+ mobileQrImage: queryElement('#mobile-qr-image'),
3880
+ mobileQrStatus: queryElement('#mobile-qr-status'),
781
3881
  nicknameInput: queryElement('#nickname-input'),
782
3882
  storageSnapshot: queryElement('#storage-snapshot'),
783
3883
  userStatus: queryElement('#user-status'),
@@ -816,14 +3916,15 @@ queryElement('#hide-button').addEventListener('click', () => {
816
3916
  postEvent('hide', { timestamp: Date.now(), source: 'mock-host' });
817
3917
  });
818
3918
  elements.macAppButton.addEventListener('click', () => {
819
- const protocol = createMacAppProtocol(miniProgramUrl);
820
- console.log('[hb-sdk] Mac App launch protocol:', protocol);
821
- showMacAppLaunchHint();
822
- window.location.href = protocol;
3919
+ void openMacApp();
823
3920
  });
824
3921
  elements.copyDebugPageUrlButton.addEventListener('click', () => {
825
3922
  void copyDebugPageUrl();
826
3923
  });
3924
+ elements.mobileLanSelect.addEventListener('change', () => {
3925
+ void updateMobileQrCode();
3926
+ });
3927
+ const mobileAppQrReady = setupMobileAppQr();
827
3928
  function createBrowserMockRuntimeAdapter() {
828
3929
  return {
829
3930
  app: {
@@ -880,6 +3981,10 @@ function createBrowserMockRuntimeAdapter() {
880
3981
  setDocumentTitle(title) {
881
3982
  document.title = title;
882
3983
  },
3984
+ setNavigationBarStyle(options) {
3985
+ navigationBarStyle = options.foregroundStyle;
3986
+ document.documentElement.dataset.navigationBarStyle = navigationBarStyle;
3987
+ },
883
3988
  getViewportMetrics() {
884
3989
  const rect = iframe.getBoundingClientRect();
885
3990
  const width = Math.max(1, Math.round(rect.width));
@@ -1073,6 +4178,124 @@ async function copyDebugPageUrl() {
1073
4178
  elements.debugPageCopyStatus.textContent = '复制失败,请手动复制调试页面地址';
1074
4179
  }
1075
4180
  }
4181
+ async function setupMobileAppQr() {
4182
+ const config = await loadMobileLanConfig();
4183
+ lanAddresses = config.lanAddresses;
4184
+ defaultLanAddressId = config.defaultLanAddressId;
4185
+ macAppProtocol = config.macAppProtocol;
4186
+ setupMobileLanSelect();
4187
+ await updateMobileQrCode();
4188
+ }
4189
+ async function openMacApp() {
4190
+ await mobileAppQrReady.catch(() => undefined);
4191
+ const protocol = macAppProtocol ?? createMacAppProtocol(miniProgramUrl);
4192
+ console.log('[hb-sdk] Mac App launch protocol:', protocol);
4193
+ showMacAppLaunchHint();
4194
+ window.location.href = protocol;
4195
+ }
4196
+ async function loadMobileLanConfig() {
4197
+ try {
4198
+ const response = await fetch(LAN_ADDRESSES_PATH, {
4199
+ cache: 'no-store',
4200
+ });
4201
+ const payload = await response.json();
4202
+ if (!isRecord(payload)) {
4203
+ return { lanAddresses: [] };
4204
+ }
4205
+ return {
4206
+ defaultLanAddressId: typeof payload.defaultLanAddressId === 'string' ? payload.defaultLanAddressId : undefined,
4207
+ lanAddresses: Array.isArray(payload.lanAddresses) ? payload.lanAddresses.filter(isLanAddress) : [],
4208
+ macAppProtocol: typeof payload.macAppProtocol === 'string' ? payload.macAppProtocol : undefined,
4209
+ };
4210
+ }
4211
+ catch {
4212
+ elements.mobileQrStatus.textContent = '二维码初始化失败';
4213
+ return { lanAddresses: [] };
4214
+ }
4215
+ }
4216
+ function setupMobileLanSelect() {
4217
+ elements.mobileLanSelect.innerHTML = '';
4218
+ lanAddresses.forEach((address) => {
4219
+ const option = document.createElement('option');
4220
+ option.value = address.id;
4221
+ option.textContent = `${address.name} · ${address.address}`;
4222
+ elements.mobileLanSelect.appendChild(option);
4223
+ });
4224
+ const defaultAddress = lanAddresses.find((address) => address.id === defaultLanAddressId) ?? lanAddresses[0];
4225
+ if (defaultAddress) {
4226
+ elements.mobileLanSelect.value = defaultAddress.id;
4227
+ }
4228
+ const hasLanAddress = lanAddresses.length > 0;
4229
+ elements.mobileLanSelect.disabled = !hasLanAddress;
4230
+ }
4231
+ async function updateMobileQrCode() {
4232
+ const selected = readSelectedLanAddress();
4233
+ if (!selected) {
4234
+ elements.mobileQrImage.removeAttribute('src');
4235
+ elements.mobileQrImage.hidden = true;
4236
+ elements.mobileQrStatus.textContent = '';
4237
+ return;
4238
+ }
4239
+ const payload = selected.mobileAppQrPayload ?? createMobileAppQrPayload(selected.appUrl);
4240
+ elements.mobileQrStatus.textContent = '正在生成二维码...';
4241
+ try {
4242
+ elements.mobileQrImage.src = await browserExports.toDataURL(payload, {
4243
+ errorCorrectionLevel: 'M',
4244
+ margin: 1,
4245
+ width: 176,
4246
+ });
4247
+ elements.mobileQrImage.hidden = false;
4248
+ elements.mobileQrStatus.textContent = '';
4249
+ }
4250
+ catch {
4251
+ elements.mobileQrImage.removeAttribute('src');
4252
+ elements.mobileQrImage.hidden = true;
4253
+ elements.mobileQrStatus.textContent = '二维码生成失败';
4254
+ }
4255
+ }
4256
+ function readSelectedLanAddress() {
4257
+ return lanAddresses.find((address) => address.id === elements.mobileLanSelect.value) ?? lanAddresses[0];
4258
+ }
4259
+ function createMacAppProtocol(appUrl) {
4260
+ return createHeyboxProtocol(createMiniProgramDevShellOpenWindowPayload(appUrl));
4261
+ }
4262
+ function createMobileAppQrPayload(appUrl) {
4263
+ return `${OPEN_IN_APP_URL}#${createHeyboxProtocol(createMiniProgramDevShellOpenWindowPayload(appUrl, { encodeMiniUrl: false }))}`;
4264
+ }
4265
+ function createMiniProgramDevShellOpenWindowPayload(appUrl, options = {}) {
4266
+ return {
4267
+ protocol_type: 'openWindow',
4268
+ full_screen: true,
4269
+ mini_program: '1',
4270
+ navigation_bar: {
4271
+ title: '',
4272
+ },
4273
+ webview: {
4274
+ url: createMiniProgramDevShellUrl(appUrl, options),
4275
+ pull: false,
4276
+ refresh: false,
4277
+ },
4278
+ };
4279
+ }
4280
+ function createMiniProgramDevShellUrl(appUrl, options) {
4281
+ if (options.encodeMiniUrl === false) {
4282
+ return `${MINI_PROGRAM_DEV_SHELL_URL}?${MINI_PROGRAM_URL_QUERY_PARAM}=${appUrl}`;
4283
+ }
4284
+ const devShellUrl = new URL(MINI_PROGRAM_DEV_SHELL_URL);
4285
+ devShellUrl.searchParams.set(MINI_PROGRAM_URL_QUERY_PARAM, appUrl);
4286
+ return devShellUrl.toString();
4287
+ }
4288
+ function createHeyboxProtocol(payload) {
4289
+ return `heybox://${encodeURIComponent(JSON.stringify(payload))}`;
4290
+ }
4291
+ function isLanAddress(value) {
4292
+ return (isRecord(value) &&
4293
+ typeof value.address === 'string' &&
4294
+ typeof value.appUrl === 'string' &&
4295
+ typeof value.id === 'string' &&
4296
+ typeof value.name === 'string' &&
4297
+ (value.mobileAppQrPayload === undefined || typeof value.mobileAppQrPayload === 'string'));
4298
+ }
1076
4299
  async function copyText(value) {
1077
4300
  if (navigator.clipboard?.writeText) {
1078
4301
  await navigator.clipboard.writeText(value);
@@ -1139,6 +4362,9 @@ function safeJsonParse(value) {
1139
4362
  return value;
1140
4363
  }
1141
4364
  }
4365
+ function isRecord(value) {
4366
+ return typeof value === 'object' && value !== null;
4367
+ }
1142
4368
  function escapeHtml(value) {
1143
4369
  return String(value)
1144
4370
  .replace(/&/g, '&amp;')