- Created vite.standalone.config.js for optimized bundle building - Added build scripts for standalone bundle generation - Generated three formats: IIFE (28KB), UMD (28KB), ES Module (61KB) - Includes all dependencies: qrcode and imagetracer - Added comprehensive documentation and examples - Created build script with detailed bundle information - Added terser for minification optimization - Fixed package.json dependencies and scripts
2179 lines
60 KiB
JavaScript
2179 lines
60 KiB
JavaScript
var browser = {};
|
|
var canPromise$1 = function() {
|
|
return typeof Promise === "function" && Promise.prototype && Promise.prototype.then;
|
|
};
|
|
var qrcode = {};
|
|
var utils$1 = {};
|
|
let toSJISFunction;
|
|
const CODEWORDS_COUNT = [
|
|
0,
|
|
// Not used
|
|
26,
|
|
44,
|
|
70,
|
|
100,
|
|
134,
|
|
172,
|
|
196,
|
|
242,
|
|
292,
|
|
346,
|
|
404,
|
|
466,
|
|
532,
|
|
581,
|
|
655,
|
|
733,
|
|
815,
|
|
901,
|
|
991,
|
|
1085,
|
|
1156,
|
|
1258,
|
|
1364,
|
|
1474,
|
|
1588,
|
|
1706,
|
|
1828,
|
|
1921,
|
|
2051,
|
|
2185,
|
|
2323,
|
|
2465,
|
|
2611,
|
|
2761,
|
|
2876,
|
|
3034,
|
|
3196,
|
|
3362,
|
|
3532,
|
|
3706
|
|
];
|
|
utils$1.getSymbolSize = function getSymbolSize(version2) {
|
|
if (!version2) throw new Error('"version" cannot be null or undefined');
|
|
if (version2 < 1 || version2 > 40) throw new Error('"version" should be in range from 1 to 40');
|
|
return version2 * 4 + 17;
|
|
};
|
|
utils$1.getSymbolTotalCodewords = function getSymbolTotalCodewords(version2) {
|
|
return CODEWORDS_COUNT[version2];
|
|
};
|
|
utils$1.getBCHDigit = function(data) {
|
|
let digit = 0;
|
|
while (data !== 0) {
|
|
digit++;
|
|
data >>>= 1;
|
|
}
|
|
return digit;
|
|
};
|
|
utils$1.setToSJISFunction = function setToSJISFunction(f) {
|
|
if (typeof f !== "function") {
|
|
throw new Error('"toSJISFunc" is not a valid function.');
|
|
}
|
|
toSJISFunction = f;
|
|
};
|
|
utils$1.isKanjiModeEnabled = function() {
|
|
return typeof toSJISFunction !== "undefined";
|
|
};
|
|
utils$1.toSJIS = function toSJIS(kanji2) {
|
|
return toSJISFunction(kanji2);
|
|
};
|
|
var errorCorrectionLevel = {};
|
|
(function(exports) {
|
|
exports.L = { bit: 1 };
|
|
exports.M = { bit: 0 };
|
|
exports.Q = { bit: 3 };
|
|
exports.H = { bit: 2 };
|
|
function fromString(string) {
|
|
if (typeof string !== "string") {
|
|
throw new Error("Param is not a string");
|
|
}
|
|
const lcStr = string.toLowerCase();
|
|
switch (lcStr) {
|
|
case "l":
|
|
case "low":
|
|
return exports.L;
|
|
case "m":
|
|
case "medium":
|
|
return exports.M;
|
|
case "q":
|
|
case "quartile":
|
|
return exports.Q;
|
|
case "h":
|
|
case "high":
|
|
return exports.H;
|
|
default:
|
|
throw new Error("Unknown EC Level: " + string);
|
|
}
|
|
}
|
|
exports.isValid = function isValid2(level) {
|
|
return level && typeof level.bit !== "undefined" && level.bit >= 0 && level.bit < 4;
|
|
};
|
|
exports.from = function from(value, defaultValue) {
|
|
if (exports.isValid(value)) {
|
|
return value;
|
|
}
|
|
try {
|
|
return fromString(value);
|
|
} catch (e) {
|
|
return defaultValue;
|
|
}
|
|
};
|
|
})(errorCorrectionLevel);
|
|
function BitBuffer$1() {
|
|
this.buffer = [];
|
|
this.length = 0;
|
|
}
|
|
BitBuffer$1.prototype = {
|
|
get: function(index) {
|
|
const bufIndex = Math.floor(index / 8);
|
|
return (this.buffer[bufIndex] >>> 7 - index % 8 & 1) === 1;
|
|
},
|
|
put: function(num, length) {
|
|
for (let i = 0; i < length; i++) {
|
|
this.putBit((num >>> length - i - 1 & 1) === 1);
|
|
}
|
|
},
|
|
getLengthInBits: function() {
|
|
return this.length;
|
|
},
|
|
putBit: function(bit) {
|
|
const bufIndex = Math.floor(this.length / 8);
|
|
if (this.buffer.length <= bufIndex) {
|
|
this.buffer.push(0);
|
|
}
|
|
if (bit) {
|
|
this.buffer[bufIndex] |= 128 >>> this.length % 8;
|
|
}
|
|
this.length++;
|
|
}
|
|
};
|
|
var bitBuffer = BitBuffer$1;
|
|
function BitMatrix$1(size) {
|
|
if (!size || size < 1) {
|
|
throw new Error("BitMatrix size must be defined and greater than 0");
|
|
}
|
|
this.size = size;
|
|
this.data = new Uint8Array(size * size);
|
|
this.reservedBit = new Uint8Array(size * size);
|
|
}
|
|
BitMatrix$1.prototype.set = function(row, col, value, reserved) {
|
|
const index = row * this.size + col;
|
|
this.data[index] = value;
|
|
if (reserved) this.reservedBit[index] = true;
|
|
};
|
|
BitMatrix$1.prototype.get = function(row, col) {
|
|
return this.data[row * this.size + col];
|
|
};
|
|
BitMatrix$1.prototype.xor = function(row, col, value) {
|
|
this.data[row * this.size + col] ^= value;
|
|
};
|
|
BitMatrix$1.prototype.isReserved = function(row, col) {
|
|
return this.reservedBit[row * this.size + col];
|
|
};
|
|
var bitMatrix = BitMatrix$1;
|
|
var alignmentPattern = {};
|
|
(function(exports) {
|
|
const getSymbolSize3 = utils$1.getSymbolSize;
|
|
exports.getRowColCoords = function getRowColCoords(version2) {
|
|
if (version2 === 1) return [];
|
|
const posCount = Math.floor(version2 / 7) + 2;
|
|
const size = getSymbolSize3(version2);
|
|
const intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2;
|
|
const positions = [size - 7];
|
|
for (let i = 1; i < posCount - 1; i++) {
|
|
positions[i] = positions[i - 1] - intervals;
|
|
}
|
|
positions.push(6);
|
|
return positions.reverse();
|
|
};
|
|
exports.getPositions = function getPositions2(version2) {
|
|
const coords = [];
|
|
const pos = exports.getRowColCoords(version2);
|
|
const posLength = pos.length;
|
|
for (let i = 0; i < posLength; i++) {
|
|
for (let j = 0; j < posLength; j++) {
|
|
if (i === 0 && j === 0 || // top-left
|
|
i === 0 && j === posLength - 1 || // bottom-left
|
|
i === posLength - 1 && j === 0) {
|
|
continue;
|
|
}
|
|
coords.push([pos[i], pos[j]]);
|
|
}
|
|
}
|
|
return coords;
|
|
};
|
|
})(alignmentPattern);
|
|
var finderPattern = {};
|
|
const getSymbolSize2 = utils$1.getSymbolSize;
|
|
const FINDER_PATTERN_SIZE = 7;
|
|
finderPattern.getPositions = function getPositions(version2) {
|
|
const size = getSymbolSize2(version2);
|
|
return [
|
|
// top-left
|
|
[0, 0],
|
|
// top-right
|
|
[size - FINDER_PATTERN_SIZE, 0],
|
|
// bottom-left
|
|
[0, size - FINDER_PATTERN_SIZE]
|
|
];
|
|
};
|
|
var maskPattern = {};
|
|
(function(exports) {
|
|
exports.Patterns = {
|
|
PATTERN000: 0,
|
|
PATTERN001: 1,
|
|
PATTERN010: 2,
|
|
PATTERN011: 3,
|
|
PATTERN100: 4,
|
|
PATTERN101: 5,
|
|
PATTERN110: 6,
|
|
PATTERN111: 7
|
|
};
|
|
const PenaltyScores = {
|
|
N1: 3,
|
|
N2: 3,
|
|
N3: 40,
|
|
N4: 10
|
|
};
|
|
exports.isValid = function isValid2(mask) {
|
|
return mask != null && mask !== "" && !isNaN(mask) && mask >= 0 && mask <= 7;
|
|
};
|
|
exports.from = function from(value) {
|
|
return exports.isValid(value) ? parseInt(value, 10) : void 0;
|
|
};
|
|
exports.getPenaltyN1 = function getPenaltyN1(data) {
|
|
const size = data.size;
|
|
let points = 0;
|
|
let sameCountCol = 0;
|
|
let sameCountRow = 0;
|
|
let lastCol = null;
|
|
let lastRow = null;
|
|
for (let row = 0; row < size; row++) {
|
|
sameCountCol = sameCountRow = 0;
|
|
lastCol = lastRow = null;
|
|
for (let col = 0; col < size; col++) {
|
|
let module = data.get(row, col);
|
|
if (module === lastCol) {
|
|
sameCountCol++;
|
|
} else {
|
|
if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5);
|
|
lastCol = module;
|
|
sameCountCol = 1;
|
|
}
|
|
module = data.get(col, row);
|
|
if (module === lastRow) {
|
|
sameCountRow++;
|
|
} else {
|
|
if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5);
|
|
lastRow = module;
|
|
sameCountRow = 1;
|
|
}
|
|
}
|
|
if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5);
|
|
if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5);
|
|
}
|
|
return points;
|
|
};
|
|
exports.getPenaltyN2 = function getPenaltyN2(data) {
|
|
const size = data.size;
|
|
let points = 0;
|
|
for (let row = 0; row < size - 1; row++) {
|
|
for (let col = 0; col < size - 1; col++) {
|
|
const last = data.get(row, col) + data.get(row, col + 1) + data.get(row + 1, col) + data.get(row + 1, col + 1);
|
|
if (last === 4 || last === 0) points++;
|
|
}
|
|
}
|
|
return points * PenaltyScores.N2;
|
|
};
|
|
exports.getPenaltyN3 = function getPenaltyN3(data) {
|
|
const size = data.size;
|
|
let points = 0;
|
|
let bitsCol = 0;
|
|
let bitsRow = 0;
|
|
for (let row = 0; row < size; row++) {
|
|
bitsCol = bitsRow = 0;
|
|
for (let col = 0; col < size; col++) {
|
|
bitsCol = bitsCol << 1 & 2047 | data.get(row, col);
|
|
if (col >= 10 && (bitsCol === 1488 || bitsCol === 93)) points++;
|
|
bitsRow = bitsRow << 1 & 2047 | data.get(col, row);
|
|
if (col >= 10 && (bitsRow === 1488 || bitsRow === 93)) points++;
|
|
}
|
|
}
|
|
return points * PenaltyScores.N3;
|
|
};
|
|
exports.getPenaltyN4 = function getPenaltyN4(data) {
|
|
let darkCount = 0;
|
|
const modulesCount = data.data.length;
|
|
for (let i = 0; i < modulesCount; i++) darkCount += data.data[i];
|
|
const k = Math.abs(Math.ceil(darkCount * 100 / modulesCount / 5) - 10);
|
|
return k * PenaltyScores.N4;
|
|
};
|
|
function getMaskAt(maskPattern2, i, j) {
|
|
switch (maskPattern2) {
|
|
case exports.Patterns.PATTERN000:
|
|
return (i + j) % 2 === 0;
|
|
case exports.Patterns.PATTERN001:
|
|
return i % 2 === 0;
|
|
case exports.Patterns.PATTERN010:
|
|
return j % 3 === 0;
|
|
case exports.Patterns.PATTERN011:
|
|
return (i + j) % 3 === 0;
|
|
case exports.Patterns.PATTERN100:
|
|
return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0;
|
|
case exports.Patterns.PATTERN101:
|
|
return i * j % 2 + i * j % 3 === 0;
|
|
case exports.Patterns.PATTERN110:
|
|
return (i * j % 2 + i * j % 3) % 2 === 0;
|
|
case exports.Patterns.PATTERN111:
|
|
return (i * j % 3 + (i + j) % 2) % 2 === 0;
|
|
default:
|
|
throw new Error("bad maskPattern:" + maskPattern2);
|
|
}
|
|
}
|
|
exports.applyMask = function applyMask(pattern, data) {
|
|
const size = data.size;
|
|
for (let col = 0; col < size; col++) {
|
|
for (let row = 0; row < size; row++) {
|
|
if (data.isReserved(row, col)) continue;
|
|
data.xor(row, col, getMaskAt(pattern, row, col));
|
|
}
|
|
}
|
|
};
|
|
exports.getBestMask = function getBestMask(data, setupFormatFunc) {
|
|
const numPatterns = Object.keys(exports.Patterns).length;
|
|
let bestPattern = 0;
|
|
let lowerPenalty = Infinity;
|
|
for (let p = 0; p < numPatterns; p++) {
|
|
setupFormatFunc(p);
|
|
exports.applyMask(p, data);
|
|
const penalty = exports.getPenaltyN1(data) + exports.getPenaltyN2(data) + exports.getPenaltyN3(data) + exports.getPenaltyN4(data);
|
|
exports.applyMask(p, data);
|
|
if (penalty < lowerPenalty) {
|
|
lowerPenalty = penalty;
|
|
bestPattern = p;
|
|
}
|
|
}
|
|
return bestPattern;
|
|
};
|
|
})(maskPattern);
|
|
var errorCorrectionCode = {};
|
|
const ECLevel$1 = errorCorrectionLevel;
|
|
const EC_BLOCKS_TABLE = [
|
|
// L M Q H
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
2,
|
|
2,
|
|
1,
|
|
2,
|
|
2,
|
|
4,
|
|
1,
|
|
2,
|
|
4,
|
|
4,
|
|
2,
|
|
4,
|
|
4,
|
|
4,
|
|
2,
|
|
4,
|
|
6,
|
|
5,
|
|
2,
|
|
4,
|
|
6,
|
|
6,
|
|
2,
|
|
5,
|
|
8,
|
|
8,
|
|
4,
|
|
5,
|
|
8,
|
|
8,
|
|
4,
|
|
5,
|
|
8,
|
|
11,
|
|
4,
|
|
8,
|
|
10,
|
|
11,
|
|
4,
|
|
9,
|
|
12,
|
|
16,
|
|
4,
|
|
9,
|
|
16,
|
|
16,
|
|
6,
|
|
10,
|
|
12,
|
|
18,
|
|
6,
|
|
10,
|
|
17,
|
|
16,
|
|
6,
|
|
11,
|
|
16,
|
|
19,
|
|
6,
|
|
13,
|
|
18,
|
|
21,
|
|
7,
|
|
14,
|
|
21,
|
|
25,
|
|
8,
|
|
16,
|
|
20,
|
|
25,
|
|
8,
|
|
17,
|
|
23,
|
|
25,
|
|
9,
|
|
17,
|
|
23,
|
|
34,
|
|
9,
|
|
18,
|
|
25,
|
|
30,
|
|
10,
|
|
20,
|
|
27,
|
|
32,
|
|
12,
|
|
21,
|
|
29,
|
|
35,
|
|
12,
|
|
23,
|
|
34,
|
|
37,
|
|
12,
|
|
25,
|
|
34,
|
|
40,
|
|
13,
|
|
26,
|
|
35,
|
|
42,
|
|
14,
|
|
28,
|
|
38,
|
|
45,
|
|
15,
|
|
29,
|
|
40,
|
|
48,
|
|
16,
|
|
31,
|
|
43,
|
|
51,
|
|
17,
|
|
33,
|
|
45,
|
|
54,
|
|
18,
|
|
35,
|
|
48,
|
|
57,
|
|
19,
|
|
37,
|
|
51,
|
|
60,
|
|
19,
|
|
38,
|
|
53,
|
|
63,
|
|
20,
|
|
40,
|
|
56,
|
|
66,
|
|
21,
|
|
43,
|
|
59,
|
|
70,
|
|
22,
|
|
45,
|
|
62,
|
|
74,
|
|
24,
|
|
47,
|
|
65,
|
|
77,
|
|
25,
|
|
49,
|
|
68,
|
|
81
|
|
];
|
|
const EC_CODEWORDS_TABLE = [
|
|
// L M Q H
|
|
7,
|
|
10,
|
|
13,
|
|
17,
|
|
10,
|
|
16,
|
|
22,
|
|
28,
|
|
15,
|
|
26,
|
|
36,
|
|
44,
|
|
20,
|
|
36,
|
|
52,
|
|
64,
|
|
26,
|
|
48,
|
|
72,
|
|
88,
|
|
36,
|
|
64,
|
|
96,
|
|
112,
|
|
40,
|
|
72,
|
|
108,
|
|
130,
|
|
48,
|
|
88,
|
|
132,
|
|
156,
|
|
60,
|
|
110,
|
|
160,
|
|
192,
|
|
72,
|
|
130,
|
|
192,
|
|
224,
|
|
80,
|
|
150,
|
|
224,
|
|
264,
|
|
96,
|
|
176,
|
|
260,
|
|
308,
|
|
104,
|
|
198,
|
|
288,
|
|
352,
|
|
120,
|
|
216,
|
|
320,
|
|
384,
|
|
132,
|
|
240,
|
|
360,
|
|
432,
|
|
144,
|
|
280,
|
|
408,
|
|
480,
|
|
168,
|
|
308,
|
|
448,
|
|
532,
|
|
180,
|
|
338,
|
|
504,
|
|
588,
|
|
196,
|
|
364,
|
|
546,
|
|
650,
|
|
224,
|
|
416,
|
|
600,
|
|
700,
|
|
224,
|
|
442,
|
|
644,
|
|
750,
|
|
252,
|
|
476,
|
|
690,
|
|
816,
|
|
270,
|
|
504,
|
|
750,
|
|
900,
|
|
300,
|
|
560,
|
|
810,
|
|
960,
|
|
312,
|
|
588,
|
|
870,
|
|
1050,
|
|
336,
|
|
644,
|
|
952,
|
|
1110,
|
|
360,
|
|
700,
|
|
1020,
|
|
1200,
|
|
390,
|
|
728,
|
|
1050,
|
|
1260,
|
|
420,
|
|
784,
|
|
1140,
|
|
1350,
|
|
450,
|
|
812,
|
|
1200,
|
|
1440,
|
|
480,
|
|
868,
|
|
1290,
|
|
1530,
|
|
510,
|
|
924,
|
|
1350,
|
|
1620,
|
|
540,
|
|
980,
|
|
1440,
|
|
1710,
|
|
570,
|
|
1036,
|
|
1530,
|
|
1800,
|
|
570,
|
|
1064,
|
|
1590,
|
|
1890,
|
|
600,
|
|
1120,
|
|
1680,
|
|
1980,
|
|
630,
|
|
1204,
|
|
1770,
|
|
2100,
|
|
660,
|
|
1260,
|
|
1860,
|
|
2220,
|
|
720,
|
|
1316,
|
|
1950,
|
|
2310,
|
|
750,
|
|
1372,
|
|
2040,
|
|
2430
|
|
];
|
|
errorCorrectionCode.getBlocksCount = function getBlocksCount(version2, errorCorrectionLevel2) {
|
|
switch (errorCorrectionLevel2) {
|
|
case ECLevel$1.L:
|
|
return EC_BLOCKS_TABLE[(version2 - 1) * 4 + 0];
|
|
case ECLevel$1.M:
|
|
return EC_BLOCKS_TABLE[(version2 - 1) * 4 + 1];
|
|
case ECLevel$1.Q:
|
|
return EC_BLOCKS_TABLE[(version2 - 1) * 4 + 2];
|
|
case ECLevel$1.H:
|
|
return EC_BLOCKS_TABLE[(version2 - 1) * 4 + 3];
|
|
default:
|
|
return void 0;
|
|
}
|
|
};
|
|
errorCorrectionCode.getTotalCodewordsCount = function getTotalCodewordsCount(version2, errorCorrectionLevel2) {
|
|
switch (errorCorrectionLevel2) {
|
|
case ECLevel$1.L:
|
|
return EC_CODEWORDS_TABLE[(version2 - 1) * 4 + 0];
|
|
case ECLevel$1.M:
|
|
return EC_CODEWORDS_TABLE[(version2 - 1) * 4 + 1];
|
|
case ECLevel$1.Q:
|
|
return EC_CODEWORDS_TABLE[(version2 - 1) * 4 + 2];
|
|
case ECLevel$1.H:
|
|
return EC_CODEWORDS_TABLE[(version2 - 1) * 4 + 3];
|
|
default:
|
|
return void 0;
|
|
}
|
|
};
|
|
var polynomial = {};
|
|
var galoisField = {};
|
|
const EXP_TABLE = new Uint8Array(512);
|
|
const LOG_TABLE = new Uint8Array(256);
|
|
(function initTables() {
|
|
let x = 1;
|
|
for (let i = 0; i < 255; i++) {
|
|
EXP_TABLE[i] = x;
|
|
LOG_TABLE[x] = i;
|
|
x <<= 1;
|
|
if (x & 256) {
|
|
x ^= 285;
|
|
}
|
|
}
|
|
for (let i = 255; i < 512; i++) {
|
|
EXP_TABLE[i] = EXP_TABLE[i - 255];
|
|
}
|
|
})();
|
|
galoisField.log = function log(n) {
|
|
if (n < 1) throw new Error("log(" + n + ")");
|
|
return LOG_TABLE[n];
|
|
};
|
|
galoisField.exp = function exp(n) {
|
|
return EXP_TABLE[n];
|
|
};
|
|
galoisField.mul = function mul(x, y) {
|
|
if (x === 0 || y === 0) return 0;
|
|
return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]];
|
|
};
|
|
(function(exports) {
|
|
const GF = galoisField;
|
|
exports.mul = function mul2(p1, p2) {
|
|
const coeff = new Uint8Array(p1.length + p2.length - 1);
|
|
for (let i = 0; i < p1.length; i++) {
|
|
for (let j = 0; j < p2.length; j++) {
|
|
coeff[i + j] ^= GF.mul(p1[i], p2[j]);
|
|
}
|
|
}
|
|
return coeff;
|
|
};
|
|
exports.mod = function mod(divident, divisor) {
|
|
let result = new Uint8Array(divident);
|
|
while (result.length - divisor.length >= 0) {
|
|
const coeff = result[0];
|
|
for (let i = 0; i < divisor.length; i++) {
|
|
result[i] ^= GF.mul(divisor[i], coeff);
|
|
}
|
|
let offset = 0;
|
|
while (offset < result.length && result[offset] === 0) offset++;
|
|
result = result.slice(offset);
|
|
}
|
|
return result;
|
|
};
|
|
exports.generateECPolynomial = function generateECPolynomial(degree) {
|
|
let poly = new Uint8Array([1]);
|
|
for (let i = 0; i < degree; i++) {
|
|
poly = exports.mul(poly, new Uint8Array([1, GF.exp(i)]));
|
|
}
|
|
return poly;
|
|
};
|
|
})(polynomial);
|
|
const Polynomial = polynomial;
|
|
function ReedSolomonEncoder$1(degree) {
|
|
this.genPoly = void 0;
|
|
this.degree = degree;
|
|
if (this.degree) this.initialize(this.degree);
|
|
}
|
|
ReedSolomonEncoder$1.prototype.initialize = function initialize(degree) {
|
|
this.degree = degree;
|
|
this.genPoly = Polynomial.generateECPolynomial(this.degree);
|
|
};
|
|
ReedSolomonEncoder$1.prototype.encode = function encode(data) {
|
|
if (!this.genPoly) {
|
|
throw new Error("Encoder not initialized");
|
|
}
|
|
const paddedData = new Uint8Array(data.length + this.degree);
|
|
paddedData.set(data);
|
|
const remainder = Polynomial.mod(paddedData, this.genPoly);
|
|
const start = this.degree - remainder.length;
|
|
if (start > 0) {
|
|
const buff = new Uint8Array(this.degree);
|
|
buff.set(remainder, start);
|
|
return buff;
|
|
}
|
|
return remainder;
|
|
};
|
|
var reedSolomonEncoder = ReedSolomonEncoder$1;
|
|
var version = {};
|
|
var mode = {};
|
|
var versionCheck = {};
|
|
versionCheck.isValid = function isValid(version2) {
|
|
return !isNaN(version2) && version2 >= 1 && version2 <= 40;
|
|
};
|
|
var regex = {};
|
|
const numeric = "[0-9]+";
|
|
const alphanumeric = "[A-Z $%*+\\-./:]+";
|
|
let kanji = "(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";
|
|
kanji = kanji.replace(/u/g, "\\u");
|
|
const byte = "(?:(?![A-Z0-9 $%*+\\-./:]|" + kanji + ")(?:.|[\r\n]))+";
|
|
regex.KANJI = new RegExp(kanji, "g");
|
|
regex.BYTE_KANJI = new RegExp("[^A-Z0-9 $%*+\\-./:]+", "g");
|
|
regex.BYTE = new RegExp(byte, "g");
|
|
regex.NUMERIC = new RegExp(numeric, "g");
|
|
regex.ALPHANUMERIC = new RegExp(alphanumeric, "g");
|
|
const TEST_KANJI = new RegExp("^" + kanji + "$");
|
|
const TEST_NUMERIC = new RegExp("^" + numeric + "$");
|
|
const TEST_ALPHANUMERIC = new RegExp("^[A-Z0-9 $%*+\\-./:]+$");
|
|
regex.testKanji = function testKanji(str) {
|
|
return TEST_KANJI.test(str);
|
|
};
|
|
regex.testNumeric = function testNumeric(str) {
|
|
return TEST_NUMERIC.test(str);
|
|
};
|
|
regex.testAlphanumeric = function testAlphanumeric(str) {
|
|
return TEST_ALPHANUMERIC.test(str);
|
|
};
|
|
(function(exports) {
|
|
const VersionCheck = versionCheck;
|
|
const Regex = regex;
|
|
exports.NUMERIC = {
|
|
id: "Numeric",
|
|
bit: 1 << 0,
|
|
ccBits: [10, 12, 14]
|
|
};
|
|
exports.ALPHANUMERIC = {
|
|
id: "Alphanumeric",
|
|
bit: 1 << 1,
|
|
ccBits: [9, 11, 13]
|
|
};
|
|
exports.BYTE = {
|
|
id: "Byte",
|
|
bit: 1 << 2,
|
|
ccBits: [8, 16, 16]
|
|
};
|
|
exports.KANJI = {
|
|
id: "Kanji",
|
|
bit: 1 << 3,
|
|
ccBits: [8, 10, 12]
|
|
};
|
|
exports.MIXED = {
|
|
bit: -1
|
|
};
|
|
exports.getCharCountIndicator = function getCharCountIndicator(mode2, version2) {
|
|
if (!mode2.ccBits) throw new Error("Invalid mode: " + mode2);
|
|
if (!VersionCheck.isValid(version2)) {
|
|
throw new Error("Invalid version: " + version2);
|
|
}
|
|
if (version2 >= 1 && version2 < 10) return mode2.ccBits[0];
|
|
else if (version2 < 27) return mode2.ccBits[1];
|
|
return mode2.ccBits[2];
|
|
};
|
|
exports.getBestModeForData = function getBestModeForData(dataStr) {
|
|
if (Regex.testNumeric(dataStr)) return exports.NUMERIC;
|
|
else if (Regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC;
|
|
else if (Regex.testKanji(dataStr)) return exports.KANJI;
|
|
else return exports.BYTE;
|
|
};
|
|
exports.toString = function toString(mode2) {
|
|
if (mode2 && mode2.id) return mode2.id;
|
|
throw new Error("Invalid mode");
|
|
};
|
|
exports.isValid = function isValid2(mode2) {
|
|
return mode2 && mode2.bit && mode2.ccBits;
|
|
};
|
|
function fromString(string) {
|
|
if (typeof string !== "string") {
|
|
throw new Error("Param is not a string");
|
|
}
|
|
const lcStr = string.toLowerCase();
|
|
switch (lcStr) {
|
|
case "numeric":
|
|
return exports.NUMERIC;
|
|
case "alphanumeric":
|
|
return exports.ALPHANUMERIC;
|
|
case "kanji":
|
|
return exports.KANJI;
|
|
case "byte":
|
|
return exports.BYTE;
|
|
default:
|
|
throw new Error("Unknown mode: " + string);
|
|
}
|
|
}
|
|
exports.from = function from(value, defaultValue) {
|
|
if (exports.isValid(value)) {
|
|
return value;
|
|
}
|
|
try {
|
|
return fromString(value);
|
|
} catch (e) {
|
|
return defaultValue;
|
|
}
|
|
};
|
|
})(mode);
|
|
(function(exports) {
|
|
const Utils2 = utils$1;
|
|
const ECCode2 = errorCorrectionCode;
|
|
const ECLevel2 = errorCorrectionLevel;
|
|
const Mode2 = mode;
|
|
const VersionCheck = versionCheck;
|
|
const G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0;
|
|
const G18_BCH = Utils2.getBCHDigit(G18);
|
|
function getBestVersionForDataLength(mode2, length, errorCorrectionLevel2) {
|
|
for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {
|
|
if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel2, mode2)) {
|
|
return currentVersion;
|
|
}
|
|
}
|
|
return void 0;
|
|
}
|
|
function getReservedBitsCount(mode2, version2) {
|
|
return Mode2.getCharCountIndicator(mode2, version2) + 4;
|
|
}
|
|
function getTotalBitsFromDataArray(segments2, version2) {
|
|
let totalBits = 0;
|
|
segments2.forEach(function(data) {
|
|
const reservedBits = getReservedBitsCount(data.mode, version2);
|
|
totalBits += reservedBits + data.getBitsLength();
|
|
});
|
|
return totalBits;
|
|
}
|
|
function getBestVersionForMixedData(segments2, errorCorrectionLevel2) {
|
|
for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {
|
|
const length = getTotalBitsFromDataArray(segments2, currentVersion);
|
|
if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel2, Mode2.MIXED)) {
|
|
return currentVersion;
|
|
}
|
|
}
|
|
return void 0;
|
|
}
|
|
exports.from = function from(value, defaultValue) {
|
|
if (VersionCheck.isValid(value)) {
|
|
return parseInt(value, 10);
|
|
}
|
|
return defaultValue;
|
|
};
|
|
exports.getCapacity = function getCapacity(version2, errorCorrectionLevel2, mode2) {
|
|
if (!VersionCheck.isValid(version2)) {
|
|
throw new Error("Invalid QR Code version");
|
|
}
|
|
if (typeof mode2 === "undefined") mode2 = Mode2.BYTE;
|
|
const totalCodewords = Utils2.getSymbolTotalCodewords(version2);
|
|
const ecTotalCodewords = ECCode2.getTotalCodewordsCount(version2, errorCorrectionLevel2);
|
|
const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8;
|
|
if (mode2 === Mode2.MIXED) return dataTotalCodewordsBits;
|
|
const usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode2, version2);
|
|
switch (mode2) {
|
|
case Mode2.NUMERIC:
|
|
return Math.floor(usableBits / 10 * 3);
|
|
case Mode2.ALPHANUMERIC:
|
|
return Math.floor(usableBits / 11 * 2);
|
|
case Mode2.KANJI:
|
|
return Math.floor(usableBits / 13);
|
|
case Mode2.BYTE:
|
|
default:
|
|
return Math.floor(usableBits / 8);
|
|
}
|
|
};
|
|
exports.getBestVersionForData = function getBestVersionForData(data, errorCorrectionLevel2) {
|
|
let seg;
|
|
const ecl = ECLevel2.from(errorCorrectionLevel2, ECLevel2.M);
|
|
if (Array.isArray(data)) {
|
|
if (data.length > 1) {
|
|
return getBestVersionForMixedData(data, ecl);
|
|
}
|
|
if (data.length === 0) {
|
|
return 1;
|
|
}
|
|
seg = data[0];
|
|
} else {
|
|
seg = data;
|
|
}
|
|
return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl);
|
|
};
|
|
exports.getEncodedBits = function getEncodedBits2(version2) {
|
|
if (!VersionCheck.isValid(version2) || version2 < 7) {
|
|
throw new Error("Invalid QR Code version");
|
|
}
|
|
let d = version2 << 12;
|
|
while (Utils2.getBCHDigit(d) - G18_BCH >= 0) {
|
|
d ^= G18 << Utils2.getBCHDigit(d) - G18_BCH;
|
|
}
|
|
return version2 << 12 | d;
|
|
};
|
|
})(version);
|
|
var formatInfo = {};
|
|
const Utils$3 = utils$1;
|
|
const G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0;
|
|
const G15_MASK = 1 << 14 | 1 << 12 | 1 << 10 | 1 << 4 | 1 << 1;
|
|
const G15_BCH = Utils$3.getBCHDigit(G15);
|
|
formatInfo.getEncodedBits = function getEncodedBits(errorCorrectionLevel2, mask) {
|
|
const data = errorCorrectionLevel2.bit << 3 | mask;
|
|
let d = data << 10;
|
|
while (Utils$3.getBCHDigit(d) - G15_BCH >= 0) {
|
|
d ^= G15 << Utils$3.getBCHDigit(d) - G15_BCH;
|
|
}
|
|
return (data << 10 | d) ^ G15_MASK;
|
|
};
|
|
var segments = {};
|
|
const Mode$4 = mode;
|
|
function NumericData(data) {
|
|
this.mode = Mode$4.NUMERIC;
|
|
this.data = data.toString();
|
|
}
|
|
NumericData.getBitsLength = function getBitsLength(length) {
|
|
return 10 * Math.floor(length / 3) + (length % 3 ? length % 3 * 3 + 1 : 0);
|
|
};
|
|
NumericData.prototype.getLength = function getLength() {
|
|
return this.data.length;
|
|
};
|
|
NumericData.prototype.getBitsLength = function getBitsLength2() {
|
|
return NumericData.getBitsLength(this.data.length);
|
|
};
|
|
NumericData.prototype.write = function write(bitBuffer2) {
|
|
let i, group, value;
|
|
for (i = 0; i + 3 <= this.data.length; i += 3) {
|
|
group = this.data.substr(i, 3);
|
|
value = parseInt(group, 10);
|
|
bitBuffer2.put(value, 10);
|
|
}
|
|
const remainingNum = this.data.length - i;
|
|
if (remainingNum > 0) {
|
|
group = this.data.substr(i);
|
|
value = parseInt(group, 10);
|
|
bitBuffer2.put(value, remainingNum * 3 + 1);
|
|
}
|
|
};
|
|
var numericData = NumericData;
|
|
const Mode$3 = mode;
|
|
const ALPHA_NUM_CHARS = [
|
|
"0",
|
|
"1",
|
|
"2",
|
|
"3",
|
|
"4",
|
|
"5",
|
|
"6",
|
|
"7",
|
|
"8",
|
|
"9",
|
|
"A",
|
|
"B",
|
|
"C",
|
|
"D",
|
|
"E",
|
|
"F",
|
|
"G",
|
|
"H",
|
|
"I",
|
|
"J",
|
|
"K",
|
|
"L",
|
|
"M",
|
|
"N",
|
|
"O",
|
|
"P",
|
|
"Q",
|
|
"R",
|
|
"S",
|
|
"T",
|
|
"U",
|
|
"V",
|
|
"W",
|
|
"X",
|
|
"Y",
|
|
"Z",
|
|
" ",
|
|
"$",
|
|
"%",
|
|
"*",
|
|
"+",
|
|
"-",
|
|
".",
|
|
"/",
|
|
":"
|
|
];
|
|
function AlphanumericData(data) {
|
|
this.mode = Mode$3.ALPHANUMERIC;
|
|
this.data = data;
|
|
}
|
|
AlphanumericData.getBitsLength = function getBitsLength3(length) {
|
|
return 11 * Math.floor(length / 2) + 6 * (length % 2);
|
|
};
|
|
AlphanumericData.prototype.getLength = function getLength2() {
|
|
return this.data.length;
|
|
};
|
|
AlphanumericData.prototype.getBitsLength = function getBitsLength4() {
|
|
return AlphanumericData.getBitsLength(this.data.length);
|
|
};
|
|
AlphanumericData.prototype.write = function write2(bitBuffer2) {
|
|
let i;
|
|
for (i = 0; i + 2 <= this.data.length; i += 2) {
|
|
let value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45;
|
|
value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1]);
|
|
bitBuffer2.put(value, 11);
|
|
}
|
|
if (this.data.length % 2) {
|
|
bitBuffer2.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6);
|
|
}
|
|
};
|
|
var alphanumericData = AlphanumericData;
|
|
const Mode$2 = mode;
|
|
function ByteData(data) {
|
|
this.mode = Mode$2.BYTE;
|
|
if (typeof data === "string") {
|
|
this.data = new TextEncoder().encode(data);
|
|
} else {
|
|
this.data = new Uint8Array(data);
|
|
}
|
|
}
|
|
ByteData.getBitsLength = function getBitsLength5(length) {
|
|
return length * 8;
|
|
};
|
|
ByteData.prototype.getLength = function getLength3() {
|
|
return this.data.length;
|
|
};
|
|
ByteData.prototype.getBitsLength = function getBitsLength6() {
|
|
return ByteData.getBitsLength(this.data.length);
|
|
};
|
|
ByteData.prototype.write = function(bitBuffer2) {
|
|
for (let i = 0, l = this.data.length; i < l; i++) {
|
|
bitBuffer2.put(this.data[i], 8);
|
|
}
|
|
};
|
|
var byteData = ByteData;
|
|
const Mode$1 = mode;
|
|
const Utils$2 = utils$1;
|
|
function KanjiData(data) {
|
|
this.mode = Mode$1.KANJI;
|
|
this.data = data;
|
|
}
|
|
KanjiData.getBitsLength = function getBitsLength7(length) {
|
|
return length * 13;
|
|
};
|
|
KanjiData.prototype.getLength = function getLength4() {
|
|
return this.data.length;
|
|
};
|
|
KanjiData.prototype.getBitsLength = function getBitsLength8() {
|
|
return KanjiData.getBitsLength(this.data.length);
|
|
};
|
|
KanjiData.prototype.write = function(bitBuffer2) {
|
|
let i;
|
|
for (i = 0; i < this.data.length; i++) {
|
|
let value = Utils$2.toSJIS(this.data[i]);
|
|
if (value >= 33088 && value <= 40956) {
|
|
value -= 33088;
|
|
} else if (value >= 57408 && value <= 60351) {
|
|
value -= 49472;
|
|
} else {
|
|
throw new Error(
|
|
"Invalid SJIS character: " + this.data[i] + "\nMake sure your charset is UTF-8"
|
|
);
|
|
}
|
|
value = (value >>> 8 & 255) * 192 + (value & 255);
|
|
bitBuffer2.put(value, 13);
|
|
}
|
|
};
|
|
var kanjiData = KanjiData;
|
|
var dijkstra = { exports: {} };
|
|
(function(module) {
|
|
var dijkstra2 = {
|
|
single_source_shortest_paths: function(graph, s, d) {
|
|
var predecessors = {};
|
|
var costs = {};
|
|
costs[s] = 0;
|
|
var open = dijkstra2.PriorityQueue.make();
|
|
open.push(s, 0);
|
|
var closest, u, v, cost_of_s_to_u, adjacent_nodes, cost_of_e, cost_of_s_to_u_plus_cost_of_e, cost_of_s_to_v, first_visit;
|
|
while (!open.empty()) {
|
|
closest = open.pop();
|
|
u = closest.value;
|
|
cost_of_s_to_u = closest.cost;
|
|
adjacent_nodes = graph[u] || {};
|
|
for (v in adjacent_nodes) {
|
|
if (adjacent_nodes.hasOwnProperty(v)) {
|
|
cost_of_e = adjacent_nodes[v];
|
|
cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e;
|
|
cost_of_s_to_v = costs[v];
|
|
first_visit = typeof costs[v] === "undefined";
|
|
if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {
|
|
costs[v] = cost_of_s_to_u_plus_cost_of_e;
|
|
open.push(v, cost_of_s_to_u_plus_cost_of_e);
|
|
predecessors[v] = u;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (typeof d !== "undefined" && typeof costs[d] === "undefined") {
|
|
var msg = ["Could not find a path from ", s, " to ", d, "."].join("");
|
|
throw new Error(msg);
|
|
}
|
|
return predecessors;
|
|
},
|
|
extract_shortest_path_from_predecessor_list: function(predecessors, d) {
|
|
var nodes = [];
|
|
var u = d;
|
|
while (u) {
|
|
nodes.push(u);
|
|
predecessors[u];
|
|
u = predecessors[u];
|
|
}
|
|
nodes.reverse();
|
|
return nodes;
|
|
},
|
|
find_path: function(graph, s, d) {
|
|
var predecessors = dijkstra2.single_source_shortest_paths(graph, s, d);
|
|
return dijkstra2.extract_shortest_path_from_predecessor_list(
|
|
predecessors,
|
|
d
|
|
);
|
|
},
|
|
/**
|
|
* A very naive priority queue implementation.
|
|
*/
|
|
PriorityQueue: {
|
|
make: function(opts) {
|
|
var T = dijkstra2.PriorityQueue, t = {}, key;
|
|
opts = opts || {};
|
|
for (key in T) {
|
|
if (T.hasOwnProperty(key)) {
|
|
t[key] = T[key];
|
|
}
|
|
}
|
|
t.queue = [];
|
|
t.sorter = opts.sorter || T.default_sorter;
|
|
return t;
|
|
},
|
|
default_sorter: function(a, b) {
|
|
return a.cost - b.cost;
|
|
},
|
|
/**
|
|
* Add a new item to the queue and ensure the highest priority element
|
|
* is at the front of the queue.
|
|
*/
|
|
push: function(value, cost) {
|
|
var item = { value, cost };
|
|
this.queue.push(item);
|
|
this.queue.sort(this.sorter);
|
|
},
|
|
/**
|
|
* Return the highest priority element in the queue.
|
|
*/
|
|
pop: function() {
|
|
return this.queue.shift();
|
|
},
|
|
empty: function() {
|
|
return this.queue.length === 0;
|
|
}
|
|
}
|
|
};
|
|
{
|
|
module.exports = dijkstra2;
|
|
}
|
|
})(dijkstra);
|
|
var dijkstraExports = dijkstra.exports;
|
|
(function(exports) {
|
|
const Mode2 = mode;
|
|
const NumericData2 = numericData;
|
|
const AlphanumericData2 = alphanumericData;
|
|
const ByteData2 = byteData;
|
|
const KanjiData2 = kanjiData;
|
|
const Regex = regex;
|
|
const Utils2 = utils$1;
|
|
const dijkstra2 = dijkstraExports;
|
|
function getStringByteLength(str) {
|
|
return unescape(encodeURIComponent(str)).length;
|
|
}
|
|
function getSegments(regex2, mode2, str) {
|
|
const segments2 = [];
|
|
let result;
|
|
while ((result = regex2.exec(str)) !== null) {
|
|
segments2.push({
|
|
data: result[0],
|
|
index: result.index,
|
|
mode: mode2,
|
|
length: result[0].length
|
|
});
|
|
}
|
|
return segments2;
|
|
}
|
|
function getSegmentsFromString(dataStr) {
|
|
const numSegs = getSegments(Regex.NUMERIC, Mode2.NUMERIC, dataStr);
|
|
const alphaNumSegs = getSegments(Regex.ALPHANUMERIC, Mode2.ALPHANUMERIC, dataStr);
|
|
let byteSegs;
|
|
let kanjiSegs;
|
|
if (Utils2.isKanjiModeEnabled()) {
|
|
byteSegs = getSegments(Regex.BYTE, Mode2.BYTE, dataStr);
|
|
kanjiSegs = getSegments(Regex.KANJI, Mode2.KANJI, dataStr);
|
|
} else {
|
|
byteSegs = getSegments(Regex.BYTE_KANJI, Mode2.BYTE, dataStr);
|
|
kanjiSegs = [];
|
|
}
|
|
const segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs);
|
|
return segs.sort(function(s1, s2) {
|
|
return s1.index - s2.index;
|
|
}).map(function(obj) {
|
|
return {
|
|
data: obj.data,
|
|
mode: obj.mode,
|
|
length: obj.length
|
|
};
|
|
});
|
|
}
|
|
function getSegmentBitsLength(length, mode2) {
|
|
switch (mode2) {
|
|
case Mode2.NUMERIC:
|
|
return NumericData2.getBitsLength(length);
|
|
case Mode2.ALPHANUMERIC:
|
|
return AlphanumericData2.getBitsLength(length);
|
|
case Mode2.KANJI:
|
|
return KanjiData2.getBitsLength(length);
|
|
case Mode2.BYTE:
|
|
return ByteData2.getBitsLength(length);
|
|
}
|
|
}
|
|
function mergeSegments(segs) {
|
|
return segs.reduce(function(acc, curr) {
|
|
const prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null;
|
|
if (prevSeg && prevSeg.mode === curr.mode) {
|
|
acc[acc.length - 1].data += curr.data;
|
|
return acc;
|
|
}
|
|
acc.push(curr);
|
|
return acc;
|
|
}, []);
|
|
}
|
|
function buildNodes(segs) {
|
|
const nodes = [];
|
|
for (let i = 0; i < segs.length; i++) {
|
|
const seg = segs[i];
|
|
switch (seg.mode) {
|
|
case Mode2.NUMERIC:
|
|
nodes.push([
|
|
seg,
|
|
{ data: seg.data, mode: Mode2.ALPHANUMERIC, length: seg.length },
|
|
{ data: seg.data, mode: Mode2.BYTE, length: seg.length }
|
|
]);
|
|
break;
|
|
case Mode2.ALPHANUMERIC:
|
|
nodes.push([
|
|
seg,
|
|
{ data: seg.data, mode: Mode2.BYTE, length: seg.length }
|
|
]);
|
|
break;
|
|
case Mode2.KANJI:
|
|
nodes.push([
|
|
seg,
|
|
{ data: seg.data, mode: Mode2.BYTE, length: getStringByteLength(seg.data) }
|
|
]);
|
|
break;
|
|
case Mode2.BYTE:
|
|
nodes.push([
|
|
{ data: seg.data, mode: Mode2.BYTE, length: getStringByteLength(seg.data) }
|
|
]);
|
|
}
|
|
}
|
|
return nodes;
|
|
}
|
|
function buildGraph(nodes, version2) {
|
|
const table = {};
|
|
const graph = { start: {} };
|
|
let prevNodeIds = ["start"];
|
|
for (let i = 0; i < nodes.length; i++) {
|
|
const nodeGroup = nodes[i];
|
|
const currentNodeIds = [];
|
|
for (let j = 0; j < nodeGroup.length; j++) {
|
|
const node = nodeGroup[j];
|
|
const key = "" + i + j;
|
|
currentNodeIds.push(key);
|
|
table[key] = { node, lastCount: 0 };
|
|
graph[key] = {};
|
|
for (let n = 0; n < prevNodeIds.length; n++) {
|
|
const prevNodeId = prevNodeIds[n];
|
|
if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) {
|
|
graph[prevNodeId][key] = getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) - getSegmentBitsLength(table[prevNodeId].lastCount, node.mode);
|
|
table[prevNodeId].lastCount += node.length;
|
|
} else {
|
|
if (table[prevNodeId]) table[prevNodeId].lastCount = node.length;
|
|
graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) + 4 + Mode2.getCharCountIndicator(node.mode, version2);
|
|
}
|
|
}
|
|
}
|
|
prevNodeIds = currentNodeIds;
|
|
}
|
|
for (let n = 0; n < prevNodeIds.length; n++) {
|
|
graph[prevNodeIds[n]].end = 0;
|
|
}
|
|
return { map: graph, table };
|
|
}
|
|
function buildSingleSegment(data, modesHint) {
|
|
let mode2;
|
|
const bestMode = Mode2.getBestModeForData(data);
|
|
mode2 = Mode2.from(modesHint, bestMode);
|
|
if (mode2 !== Mode2.BYTE && mode2.bit < bestMode.bit) {
|
|
throw new Error('"' + data + '" cannot be encoded with mode ' + Mode2.toString(mode2) + ".\n Suggested mode is: " + Mode2.toString(bestMode));
|
|
}
|
|
if (mode2 === Mode2.KANJI && !Utils2.isKanjiModeEnabled()) {
|
|
mode2 = Mode2.BYTE;
|
|
}
|
|
switch (mode2) {
|
|
case Mode2.NUMERIC:
|
|
return new NumericData2(data);
|
|
case Mode2.ALPHANUMERIC:
|
|
return new AlphanumericData2(data);
|
|
case Mode2.KANJI:
|
|
return new KanjiData2(data);
|
|
case Mode2.BYTE:
|
|
return new ByteData2(data);
|
|
}
|
|
}
|
|
exports.fromArray = function fromArray(array) {
|
|
return array.reduce(function(acc, seg) {
|
|
if (typeof seg === "string") {
|
|
acc.push(buildSingleSegment(seg, null));
|
|
} else if (seg.data) {
|
|
acc.push(buildSingleSegment(seg.data, seg.mode));
|
|
}
|
|
return acc;
|
|
}, []);
|
|
};
|
|
exports.fromString = function fromString(data, version2) {
|
|
const segs = getSegmentsFromString(data, Utils2.isKanjiModeEnabled());
|
|
const nodes = buildNodes(segs);
|
|
const graph = buildGraph(nodes, version2);
|
|
const path = dijkstra2.find_path(graph.map, "start", "end");
|
|
const optimizedSegs = [];
|
|
for (let i = 1; i < path.length - 1; i++) {
|
|
optimizedSegs.push(graph.table[path[i]].node);
|
|
}
|
|
return exports.fromArray(mergeSegments(optimizedSegs));
|
|
};
|
|
exports.rawSplit = function rawSplit(data) {
|
|
return exports.fromArray(
|
|
getSegmentsFromString(data, Utils2.isKanjiModeEnabled())
|
|
);
|
|
};
|
|
})(segments);
|
|
const Utils$1 = utils$1;
|
|
const ECLevel = errorCorrectionLevel;
|
|
const BitBuffer = bitBuffer;
|
|
const BitMatrix = bitMatrix;
|
|
const AlignmentPattern = alignmentPattern;
|
|
const FinderPattern = finderPattern;
|
|
const MaskPattern = maskPattern;
|
|
const ECCode = errorCorrectionCode;
|
|
const ReedSolomonEncoder = reedSolomonEncoder;
|
|
const Version = version;
|
|
const FormatInfo = formatInfo;
|
|
const Mode = mode;
|
|
const Segments = segments;
|
|
function setupFinderPattern(matrix, version2) {
|
|
const size = matrix.size;
|
|
const pos = FinderPattern.getPositions(version2);
|
|
for (let i = 0; i < pos.length; i++) {
|
|
const row = pos[i][0];
|
|
const col = pos[i][1];
|
|
for (let r = -1; r <= 7; r++) {
|
|
if (row + r <= -1 || size <= row + r) continue;
|
|
for (let c = -1; c <= 7; c++) {
|
|
if (col + c <= -1 || size <= col + c) continue;
|
|
if (r >= 0 && r <= 6 && (c === 0 || c === 6) || c >= 0 && c <= 6 && (r === 0 || r === 6) || r >= 2 && r <= 4 && c >= 2 && c <= 4) {
|
|
matrix.set(row + r, col + c, true, true);
|
|
} else {
|
|
matrix.set(row + r, col + c, false, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function setupTimingPattern(matrix) {
|
|
const size = matrix.size;
|
|
for (let r = 8; r < size - 8; r++) {
|
|
const value = r % 2 === 0;
|
|
matrix.set(r, 6, value, true);
|
|
matrix.set(6, r, value, true);
|
|
}
|
|
}
|
|
function setupAlignmentPattern(matrix, version2) {
|
|
const pos = AlignmentPattern.getPositions(version2);
|
|
for (let i = 0; i < pos.length; i++) {
|
|
const row = pos[i][0];
|
|
const col = pos[i][1];
|
|
for (let r = -2; r <= 2; r++) {
|
|
for (let c = -2; c <= 2; c++) {
|
|
if (r === -2 || r === 2 || c === -2 || c === 2 || r === 0 && c === 0) {
|
|
matrix.set(row + r, col + c, true, true);
|
|
} else {
|
|
matrix.set(row + r, col + c, false, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function setupVersionInfo(matrix, version2) {
|
|
const size = matrix.size;
|
|
const bits = Version.getEncodedBits(version2);
|
|
let row, col, mod;
|
|
for (let i = 0; i < 18; i++) {
|
|
row = Math.floor(i / 3);
|
|
col = i % 3 + size - 8 - 3;
|
|
mod = (bits >> i & 1) === 1;
|
|
matrix.set(row, col, mod, true);
|
|
matrix.set(col, row, mod, true);
|
|
}
|
|
}
|
|
function setupFormatInfo(matrix, errorCorrectionLevel2, maskPattern2) {
|
|
const size = matrix.size;
|
|
const bits = FormatInfo.getEncodedBits(errorCorrectionLevel2, maskPattern2);
|
|
let i, mod;
|
|
for (i = 0; i < 15; i++) {
|
|
mod = (bits >> i & 1) === 1;
|
|
if (i < 6) {
|
|
matrix.set(i, 8, mod, true);
|
|
} else if (i < 8) {
|
|
matrix.set(i + 1, 8, mod, true);
|
|
} else {
|
|
matrix.set(size - 15 + i, 8, mod, true);
|
|
}
|
|
if (i < 8) {
|
|
matrix.set(8, size - i - 1, mod, true);
|
|
} else if (i < 9) {
|
|
matrix.set(8, 15 - i - 1 + 1, mod, true);
|
|
} else {
|
|
matrix.set(8, 15 - i - 1, mod, true);
|
|
}
|
|
}
|
|
matrix.set(size - 8, 8, 1, true);
|
|
}
|
|
function setupData(matrix, data) {
|
|
const size = matrix.size;
|
|
let inc = -1;
|
|
let row = size - 1;
|
|
let bitIndex = 7;
|
|
let byteIndex = 0;
|
|
for (let col = size - 1; col > 0; col -= 2) {
|
|
if (col === 6) col--;
|
|
while (true) {
|
|
for (let c = 0; c < 2; c++) {
|
|
if (!matrix.isReserved(row, col - c)) {
|
|
let dark = false;
|
|
if (byteIndex < data.length) {
|
|
dark = (data[byteIndex] >>> bitIndex & 1) === 1;
|
|
}
|
|
matrix.set(row, col - c, dark);
|
|
bitIndex--;
|
|
if (bitIndex === -1) {
|
|
byteIndex++;
|
|
bitIndex = 7;
|
|
}
|
|
}
|
|
}
|
|
row += inc;
|
|
if (row < 0 || size <= row) {
|
|
row -= inc;
|
|
inc = -inc;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function createData(version2, errorCorrectionLevel2, segments2) {
|
|
const buffer = new BitBuffer();
|
|
segments2.forEach(function(data) {
|
|
buffer.put(data.mode.bit, 4);
|
|
buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version2));
|
|
data.write(buffer);
|
|
});
|
|
const totalCodewords = Utils$1.getSymbolTotalCodewords(version2);
|
|
const ecTotalCodewords = ECCode.getTotalCodewordsCount(version2, errorCorrectionLevel2);
|
|
const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8;
|
|
if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) {
|
|
buffer.put(0, 4);
|
|
}
|
|
while (buffer.getLengthInBits() % 8 !== 0) {
|
|
buffer.putBit(0);
|
|
}
|
|
const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8;
|
|
for (let i = 0; i < remainingByte; i++) {
|
|
buffer.put(i % 2 ? 17 : 236, 8);
|
|
}
|
|
return createCodewords(buffer, version2, errorCorrectionLevel2);
|
|
}
|
|
function createCodewords(bitBuffer2, version2, errorCorrectionLevel2) {
|
|
const totalCodewords = Utils$1.getSymbolTotalCodewords(version2);
|
|
const ecTotalCodewords = ECCode.getTotalCodewordsCount(version2, errorCorrectionLevel2);
|
|
const dataTotalCodewords = totalCodewords - ecTotalCodewords;
|
|
const ecTotalBlocks = ECCode.getBlocksCount(version2, errorCorrectionLevel2);
|
|
const blocksInGroup2 = totalCodewords % ecTotalBlocks;
|
|
const blocksInGroup1 = ecTotalBlocks - blocksInGroup2;
|
|
const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks);
|
|
const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks);
|
|
const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1;
|
|
const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1;
|
|
const rs = new ReedSolomonEncoder(ecCount);
|
|
let offset = 0;
|
|
const dcData = new Array(ecTotalBlocks);
|
|
const ecData = new Array(ecTotalBlocks);
|
|
let maxDataSize = 0;
|
|
const buffer = new Uint8Array(bitBuffer2.buffer);
|
|
for (let b = 0; b < ecTotalBlocks; b++) {
|
|
const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2;
|
|
dcData[b] = buffer.slice(offset, offset + dataSize);
|
|
ecData[b] = rs.encode(dcData[b]);
|
|
offset += dataSize;
|
|
maxDataSize = Math.max(maxDataSize, dataSize);
|
|
}
|
|
const data = new Uint8Array(totalCodewords);
|
|
let index = 0;
|
|
let i, r;
|
|
for (i = 0; i < maxDataSize; i++) {
|
|
for (r = 0; r < ecTotalBlocks; r++) {
|
|
if (i < dcData[r].length) {
|
|
data[index++] = dcData[r][i];
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < ecCount; i++) {
|
|
for (r = 0; r < ecTotalBlocks; r++) {
|
|
data[index++] = ecData[r][i];
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
function createSymbol(data, version2, errorCorrectionLevel2, maskPattern2) {
|
|
let segments2;
|
|
if (Array.isArray(data)) {
|
|
segments2 = Segments.fromArray(data);
|
|
} else if (typeof data === "string") {
|
|
let estimatedVersion = version2;
|
|
if (!estimatedVersion) {
|
|
const rawSegments = Segments.rawSplit(data);
|
|
estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel2);
|
|
}
|
|
segments2 = Segments.fromString(data, estimatedVersion || 40);
|
|
} else {
|
|
throw new Error("Invalid data");
|
|
}
|
|
const bestVersion = Version.getBestVersionForData(segments2, errorCorrectionLevel2);
|
|
if (!bestVersion) {
|
|
throw new Error("The amount of data is too big to be stored in a QR Code");
|
|
}
|
|
if (!version2) {
|
|
version2 = bestVersion;
|
|
} else if (version2 < bestVersion) {
|
|
throw new Error(
|
|
"\nThe chosen QR Code version cannot contain this amount of data.\nMinimum version required to store current data is: " + bestVersion + ".\n"
|
|
);
|
|
}
|
|
const dataBits = createData(version2, errorCorrectionLevel2, segments2);
|
|
const moduleCount = Utils$1.getSymbolSize(version2);
|
|
const modules = new BitMatrix(moduleCount);
|
|
setupFinderPattern(modules, version2);
|
|
setupTimingPattern(modules);
|
|
setupAlignmentPattern(modules, version2);
|
|
setupFormatInfo(modules, errorCorrectionLevel2, 0);
|
|
if (version2 >= 7) {
|
|
setupVersionInfo(modules, version2);
|
|
}
|
|
setupData(modules, dataBits);
|
|
if (isNaN(maskPattern2)) {
|
|
maskPattern2 = MaskPattern.getBestMask(
|
|
modules,
|
|
setupFormatInfo.bind(null, modules, errorCorrectionLevel2)
|
|
);
|
|
}
|
|
MaskPattern.applyMask(maskPattern2, modules);
|
|
setupFormatInfo(modules, errorCorrectionLevel2, maskPattern2);
|
|
return {
|
|
modules,
|
|
version: version2,
|
|
errorCorrectionLevel: errorCorrectionLevel2,
|
|
maskPattern: maskPattern2,
|
|
segments: segments2
|
|
};
|
|
}
|
|
qrcode.create = function create(data, options) {
|
|
if (typeof data === "undefined" || data === "") {
|
|
throw new Error("No input text");
|
|
}
|
|
let errorCorrectionLevel2 = ECLevel.M;
|
|
let version2;
|
|
let mask;
|
|
if (typeof options !== "undefined") {
|
|
errorCorrectionLevel2 = ECLevel.from(options.errorCorrectionLevel, ECLevel.M);
|
|
version2 = Version.from(options.version);
|
|
mask = MaskPattern.from(options.maskPattern);
|
|
if (options.toSJISFunc) {
|
|
Utils$1.setToSJISFunction(options.toSJISFunc);
|
|
}
|
|
}
|
|
return createSymbol(data, version2, errorCorrectionLevel2, mask);
|
|
};
|
|
var canvas = {};
|
|
var utils = {};
|
|
(function(exports) {
|
|
function hex2rgba(hex) {
|
|
if (typeof hex === "number") {
|
|
hex = hex.toString();
|
|
}
|
|
if (typeof hex !== "string") {
|
|
throw new Error("Color should be defined as hex string");
|
|
}
|
|
let hexCode = hex.slice().replace("#", "").split("");
|
|
if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) {
|
|
throw new Error("Invalid hex color: " + hex);
|
|
}
|
|
if (hexCode.length === 3 || hexCode.length === 4) {
|
|
hexCode = Array.prototype.concat.apply([], hexCode.map(function(c) {
|
|
return [c, c];
|
|
}));
|
|
}
|
|
if (hexCode.length === 6) hexCode.push("F", "F");
|
|
const hexValue = parseInt(hexCode.join(""), 16);
|
|
return {
|
|
r: hexValue >> 24 & 255,
|
|
g: hexValue >> 16 & 255,
|
|
b: hexValue >> 8 & 255,
|
|
a: hexValue & 255,
|
|
hex: "#" + hexCode.slice(0, 6).join("")
|
|
};
|
|
}
|
|
exports.getOptions = function getOptions(options) {
|
|
if (!options) options = {};
|
|
if (!options.color) options.color = {};
|
|
const margin = typeof options.margin === "undefined" || options.margin === null || options.margin < 0 ? 4 : options.margin;
|
|
const width = options.width && options.width >= 21 ? options.width : void 0;
|
|
const scale = options.scale || 4;
|
|
return {
|
|
width,
|
|
scale: width ? 4 : scale,
|
|
margin,
|
|
color: {
|
|
dark: hex2rgba(options.color.dark || "#000000ff"),
|
|
light: hex2rgba(options.color.light || "#ffffffff")
|
|
},
|
|
type: options.type,
|
|
rendererOpts: options.rendererOpts || {}
|
|
};
|
|
};
|
|
exports.getScale = function getScale(qrSize, opts) {
|
|
return opts.width && opts.width >= qrSize + opts.margin * 2 ? opts.width / (qrSize + opts.margin * 2) : opts.scale;
|
|
};
|
|
exports.getImageWidth = function getImageWidth(qrSize, opts) {
|
|
const scale = exports.getScale(qrSize, opts);
|
|
return Math.floor((qrSize + opts.margin * 2) * scale);
|
|
};
|
|
exports.qrToImageData = function qrToImageData(imgData, qr, opts) {
|
|
const size = qr.modules.size;
|
|
const data = qr.modules.data;
|
|
const scale = exports.getScale(size, opts);
|
|
const symbolSize = Math.floor((size + opts.margin * 2) * scale);
|
|
const scaledMargin = opts.margin * scale;
|
|
const palette = [opts.color.light, opts.color.dark];
|
|
for (let i = 0; i < symbolSize; i++) {
|
|
for (let j = 0; j < symbolSize; j++) {
|
|
let posDst = (i * symbolSize + j) * 4;
|
|
let pxColor = opts.color.light;
|
|
if (i >= scaledMargin && j >= scaledMargin && i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) {
|
|
const iSrc = Math.floor((i - scaledMargin) / scale);
|
|
const jSrc = Math.floor((j - scaledMargin) / scale);
|
|
pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0];
|
|
}
|
|
imgData[posDst++] = pxColor.r;
|
|
imgData[posDst++] = pxColor.g;
|
|
imgData[posDst++] = pxColor.b;
|
|
imgData[posDst] = pxColor.a;
|
|
}
|
|
}
|
|
};
|
|
})(utils);
|
|
(function(exports) {
|
|
const Utils2 = utils;
|
|
function clearCanvas(ctx, canvas2, size) {
|
|
ctx.clearRect(0, 0, canvas2.width, canvas2.height);
|
|
if (!canvas2.style) canvas2.style = {};
|
|
canvas2.height = size;
|
|
canvas2.width = size;
|
|
canvas2.style.height = size + "px";
|
|
canvas2.style.width = size + "px";
|
|
}
|
|
function getCanvasElement() {
|
|
try {
|
|
return document.createElement("canvas");
|
|
} catch (e) {
|
|
throw new Error("You need to specify a canvas element");
|
|
}
|
|
}
|
|
exports.render = function render2(qrData, canvas2, options) {
|
|
let opts = options;
|
|
let canvasEl = canvas2;
|
|
if (typeof opts === "undefined" && (!canvas2 || !canvas2.getContext)) {
|
|
opts = canvas2;
|
|
canvas2 = void 0;
|
|
}
|
|
if (!canvas2) {
|
|
canvasEl = getCanvasElement();
|
|
}
|
|
opts = Utils2.getOptions(opts);
|
|
const size = Utils2.getImageWidth(qrData.modules.size, opts);
|
|
const ctx = canvasEl.getContext("2d");
|
|
const image = ctx.createImageData(size, size);
|
|
Utils2.qrToImageData(image.data, qrData, opts);
|
|
clearCanvas(ctx, canvasEl, size);
|
|
ctx.putImageData(image, 0, 0);
|
|
return canvasEl;
|
|
};
|
|
exports.renderToDataURL = function renderToDataURL(qrData, canvas2, options) {
|
|
let opts = options;
|
|
if (typeof opts === "undefined" && (!canvas2 || !canvas2.getContext)) {
|
|
opts = canvas2;
|
|
canvas2 = void 0;
|
|
}
|
|
if (!opts) opts = {};
|
|
const canvasEl = exports.render(qrData, canvas2, opts);
|
|
const type = opts.type || "image/png";
|
|
const rendererOpts = opts.rendererOpts || {};
|
|
return canvasEl.toDataURL(type, rendererOpts.quality);
|
|
};
|
|
})(canvas);
|
|
var svgTag = {};
|
|
const Utils = utils;
|
|
function getColorAttrib(color, attrib) {
|
|
const alpha = color.a / 255;
|
|
const str = attrib + '="' + color.hex + '"';
|
|
return alpha < 1 ? str + " " + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"' : str;
|
|
}
|
|
function svgCmd(cmd, x, y) {
|
|
let str = cmd + x;
|
|
if (typeof y !== "undefined") str += " " + y;
|
|
return str;
|
|
}
|
|
function qrToPath(data, size, margin) {
|
|
let path = "";
|
|
let moveBy = 0;
|
|
let newRow = false;
|
|
let lineLength = 0;
|
|
for (let i = 0; i < data.length; i++) {
|
|
const col = Math.floor(i % size);
|
|
const row = Math.floor(i / size);
|
|
if (!col && !newRow) newRow = true;
|
|
if (data[i]) {
|
|
lineLength++;
|
|
if (!(i > 0 && col > 0 && data[i - 1])) {
|
|
path += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
|
|
moveBy = 0;
|
|
newRow = false;
|
|
}
|
|
if (!(col + 1 < size && data[i + 1])) {
|
|
path += svgCmd("h", lineLength);
|
|
lineLength = 0;
|
|
}
|
|
} else {
|
|
moveBy++;
|
|
}
|
|
}
|
|
return path;
|
|
}
|
|
svgTag.render = function render(qrData, options, cb) {
|
|
const opts = Utils.getOptions(options);
|
|
const size = qrData.modules.size;
|
|
const data = qrData.modules.data;
|
|
const qrcodesize = size + opts.margin * 2;
|
|
const bg = !opts.color.light.a ? "" : "<path " + getColorAttrib(opts.color.light, "fill") + ' d="M0 0h' + qrcodesize + "v" + qrcodesize + 'H0z"/>';
|
|
const path = "<path " + getColorAttrib(opts.color.dark, "stroke") + ' d="' + qrToPath(data, size, opts.margin) + '"/>';
|
|
const viewBox = 'viewBox="0 0 ' + qrcodesize + " " + qrcodesize + '"';
|
|
const width = !opts.width ? "" : 'width="' + opts.width + '" height="' + opts.width + '" ';
|
|
const svgTag2 = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path + "</svg>\n";
|
|
if (typeof cb === "function") {
|
|
cb(null, svgTag2);
|
|
}
|
|
return svgTag2;
|
|
};
|
|
const canPromise = canPromise$1;
|
|
const QRCode = qrcode;
|
|
const CanvasRenderer = canvas;
|
|
const SvgRenderer = svgTag;
|
|
function renderCanvas(renderFunc, canvas2, text, opts, cb) {
|
|
const args = [].slice.call(arguments, 1);
|
|
const argsNum = args.length;
|
|
const isLastArgCb = typeof args[argsNum - 1] === "function";
|
|
if (!isLastArgCb && !canPromise()) {
|
|
throw new Error("Callback required as last argument");
|
|
}
|
|
if (isLastArgCb) {
|
|
if (argsNum < 2) {
|
|
throw new Error("Too few arguments provided");
|
|
}
|
|
if (argsNum === 2) {
|
|
cb = text;
|
|
text = canvas2;
|
|
canvas2 = opts = void 0;
|
|
} else if (argsNum === 3) {
|
|
if (canvas2.getContext && typeof cb === "undefined") {
|
|
cb = opts;
|
|
opts = void 0;
|
|
} else {
|
|
cb = opts;
|
|
opts = text;
|
|
text = canvas2;
|
|
canvas2 = void 0;
|
|
}
|
|
}
|
|
} else {
|
|
if (argsNum < 1) {
|
|
throw new Error("Too few arguments provided");
|
|
}
|
|
if (argsNum === 1) {
|
|
text = canvas2;
|
|
canvas2 = opts = void 0;
|
|
} else if (argsNum === 2 && !canvas2.getContext) {
|
|
opts = text;
|
|
text = canvas2;
|
|
canvas2 = void 0;
|
|
}
|
|
return new Promise(function(resolve, reject) {
|
|
try {
|
|
const data = QRCode.create(text, opts);
|
|
resolve(renderFunc(data, canvas2, opts));
|
|
} catch (e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
try {
|
|
const data = QRCode.create(text, opts);
|
|
cb(null, renderFunc(data, canvas2, opts));
|
|
} catch (e) {
|
|
cb(e);
|
|
}
|
|
}
|
|
browser.create = QRCode.create;
|
|
browser.toCanvas = renderCanvas.bind(null, CanvasRenderer.render);
|
|
browser.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL);
|
|
browser.toString = renderCanvas.bind(null, function(data, _, opts) {
|
|
return SvgRenderer.render(data, opts);
|
|
});
|
|
const generateQRCode = async (text, foregroundColor = "#000000", backgroundColor = "#FFFFFF") => {
|
|
try {
|
|
const dataUrl = await browser.toDataURL(text, {
|
|
color: {
|
|
dark: foregroundColor,
|
|
light: backgroundColor
|
|
},
|
|
width: 512,
|
|
margin: 2,
|
|
errorCorrectionLevel: "H"
|
|
});
|
|
return dataUrl;
|
|
} catch (error) {
|
|
console.error("Error generating QR code:", error);
|
|
return null;
|
|
}
|
|
};
|
|
const generateSVGQRCode = async (text, foregroundColor = "#000000", backgroundColor = "#FFFFFF") => {
|
|
try {
|
|
const svgString = await browser.toString(text, {
|
|
type: "svg",
|
|
width: 512,
|
|
margin: 2,
|
|
errorCorrectionLevel: "H",
|
|
color: {
|
|
dark: foregroundColor,
|
|
light: backgroundColor
|
|
}
|
|
});
|
|
return svgString;
|
|
} catch (error) {
|
|
console.error("Error generating SVG QR code:", error);
|
|
return null;
|
|
}
|
|
};
|
|
const addImageToQRCode = async (qrCodeUrl, imageUrl, imageSize = 20) => {
|
|
return new Promise((resolve) => {
|
|
const canvas2 = document.createElement("canvas");
|
|
const ctx = canvas2.getContext("2d");
|
|
canvas2.width = 512;
|
|
canvas2.height = 512;
|
|
const qrImage = new Image();
|
|
const customImage = new Image();
|
|
qrImage.onload = () => {
|
|
ctx.drawImage(qrImage, 0, 0, 512, 512);
|
|
customImage.onload = () => {
|
|
const calculatedImageSize = 512 * (imageSize / 100);
|
|
const margin = 16;
|
|
const boxSize = calculatedImageSize + margin * 2;
|
|
const boxX = (512 - boxSize) / 2;
|
|
const boxY = (512 - boxSize) / 2;
|
|
ctx.fillStyle = "#FFFFFF";
|
|
ctx.fillRect(boxX, boxY, boxSize, boxSize);
|
|
const imageX = boxX + margin;
|
|
const imageY = boxY + margin;
|
|
ctx.drawImage(customImage, imageX, imageY, calculatedImageSize, calculatedImageSize);
|
|
resolve(canvas2.toDataURL("image/png"));
|
|
};
|
|
customImage.onerror = () => {
|
|
console.error("Error loading custom image");
|
|
resolve(qrCodeUrl);
|
|
};
|
|
customImage.src = imageUrl;
|
|
};
|
|
qrImage.onerror = () => {
|
|
console.error("Error loading QR code");
|
|
resolve(qrCodeUrl);
|
|
};
|
|
qrImage.src = qrCodeUrl;
|
|
});
|
|
};
|
|
const vectorizeBitmap = (img, targetSize, x, y, svgDoc) => {
|
|
return new Promise((resolve) => {
|
|
const canvas2 = document.createElement("canvas");
|
|
const ctx = canvas2.getContext("2d");
|
|
canvas2.width = img.width;
|
|
canvas2.height = img.height;
|
|
ctx.drawImage(img, 0, 0);
|
|
const imageData = ctx.getImageData(0, 0, canvas2.width, canvas2.height);
|
|
const group = svgDoc.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
const scale = targetSize / Math.max(img.width, img.height);
|
|
group.setAttribute("transform", `translate(${x.toFixed(2)}, ${y.toFixed(2)}) scale(${scale.toFixed(4)})`);
|
|
const sampleSize = Math.max(1, Math.floor(Math.min(img.width, img.height) / 32));
|
|
const data = imageData.data;
|
|
for (let y2 = 0; y2 < img.height; y2 += sampleSize) {
|
|
for (let x2 = 0; x2 < img.width; x2 += sampleSize) {
|
|
const index = (y2 * img.width + x2) * 4;
|
|
const r = data[index];
|
|
const g = data[index + 1];
|
|
const b = data[index + 2];
|
|
const a = data[index + 3];
|
|
if (a > 128 && (r > 0 || g > 0 || b > 0)) {
|
|
const rect = svgDoc.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
rect.setAttribute("x", x2.toFixed(2));
|
|
rect.setAttribute("y", y2.toFixed(2));
|
|
rect.setAttribute("width", sampleSize.toFixed(2));
|
|
rect.setAttribute("height", sampleSize.toFixed(2));
|
|
rect.setAttribute("fill", `rgb(${r}, ${g}, ${b})`);
|
|
group.appendChild(rect);
|
|
}
|
|
}
|
|
}
|
|
resolve(group);
|
|
});
|
|
};
|
|
const addImageToSVG = async (svgString, imageUrl, imageSize = 20) => {
|
|
return new Promise((resolve) => {
|
|
const img = new Image();
|
|
img.onload = () => {
|
|
const parser = new DOMParser();
|
|
const svgDoc = parser.parseFromString(svgString, "image/svg+xml");
|
|
const svgElement = svgDoc.documentElement;
|
|
const qrSize = 33;
|
|
const calculatedImageSize = qrSize * (imageSize / 100);
|
|
const margin = 2;
|
|
const boxSize = calculatedImageSize + margin * 2;
|
|
const boxX = (qrSize - boxSize) / 2;
|
|
const boxY = (qrSize - boxSize) / 2;
|
|
const imageX = boxX + margin;
|
|
const imageY = boxY + margin;
|
|
const whiteBox = svgDoc.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
whiteBox.setAttribute("x", boxX.toFixed(2));
|
|
whiteBox.setAttribute("y", boxY.toFixed(2));
|
|
whiteBox.setAttribute("width", boxSize.toFixed(2));
|
|
whiteBox.setAttribute("height", boxSize.toFixed(2));
|
|
whiteBox.setAttribute("fill", "#FFFFFF");
|
|
svgElement.appendChild(whiteBox);
|
|
if (imageUrl.startsWith("data:image/svg+xml")) {
|
|
console.log("Processing SVG image");
|
|
const imageElement = svgDoc.createElementNS("http://www.w3.org/2000/svg", "image");
|
|
imageElement.setAttribute("x", imageX.toFixed(2));
|
|
imageElement.setAttribute("y", imageY.toFixed(2));
|
|
imageElement.setAttribute("width", calculatedImageSize.toFixed(2));
|
|
imageElement.setAttribute("height", calculatedImageSize.toFixed(2));
|
|
imageElement.setAttribute("href", imageUrl);
|
|
svgElement.appendChild(imageElement);
|
|
console.log("SVG image element added");
|
|
const serializer = new XMLSerializer();
|
|
resolve(serializer.serializeToString(svgElement));
|
|
} else {
|
|
console.log("Processing bitmap image");
|
|
vectorizeBitmap(img, calculatedImageSize, imageX, imageY, svgDoc).then((vectorizedImage) => {
|
|
svgElement.appendChild(vectorizedImage);
|
|
console.log("Vectorized image group added");
|
|
const serializer = new XMLSerializer();
|
|
resolve(serializer.serializeToString(svgElement));
|
|
}).catch((error) => {
|
|
console.error("Vectorization failed:", error);
|
|
const serializer = new XMLSerializer();
|
|
resolve(serializer.serializeToString(svgElement));
|
|
});
|
|
}
|
|
};
|
|
img.onerror = () => {
|
|
console.error("Error loading image for SVG");
|
|
resolve(svgString);
|
|
};
|
|
img.src = imageUrl;
|
|
});
|
|
};
|
|
const generateCompleteSVGQRCode = async (text, imageUrl = null, imageSize = 20, foregroundColor = "#000000", backgroundColor = "#FFFFFF") => {
|
|
try {
|
|
const svgString = await generateSVGQRCode(text, foregroundColor, backgroundColor);
|
|
if (!svgString) {
|
|
return null;
|
|
}
|
|
if (imageUrl) {
|
|
console.log("Adding custom image to SVG...");
|
|
const result = await addImageToSVG(svgString, imageUrl, imageSize);
|
|
console.log("SVG with image generated");
|
|
return result;
|
|
}
|
|
return svgString;
|
|
} catch (error) {
|
|
console.error("Error generating complete SVG QR code:", error);
|
|
return null;
|
|
}
|
|
};
|
|
const downloadSVG = (svgContent, filename = "qrcode.svg") => {
|
|
if (!svgContent) {
|
|
console.error("No SVG content to download");
|
|
return;
|
|
}
|
|
const blob = new Blob([svgContent], { type: "image/svg+xml" });
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement("a");
|
|
a.href = url;
|
|
a.download = filename;
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
document.body.removeChild(a);
|
|
URL.revokeObjectURL(url);
|
|
};
|
|
const fileToDataURL = (file) => {
|
|
return new Promise((resolve, reject) => {
|
|
const reader = new FileReader();
|
|
reader.onload = () => resolve(reader.result);
|
|
reader.onerror = reject;
|
|
reader.readAsDataURL(file);
|
|
});
|
|
};
|
|
const validateImageFile = (file, maxSize = 2 * 1024 * 1024) => {
|
|
const allowedTypes = ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"];
|
|
if (!allowedTypes.includes(file.type)) {
|
|
return {
|
|
success: false,
|
|
error: "Please select a valid image file (JPEG, PNG, GIF, WebP, or SVG)"
|
|
};
|
|
}
|
|
if (file.size > maxSize) {
|
|
return {
|
|
success: false,
|
|
error: `File size must be less than ${Math.round(maxSize / 1024 / 1024)}MB`
|
|
};
|
|
}
|
|
return { success: true };
|
|
};
|
|
export {
|
|
addImageToQRCode,
|
|
addImageToSVG,
|
|
downloadSVG,
|
|
fileToDataURL,
|
|
generateCompleteSVGQRCode,
|
|
generateQRCode,
|
|
generateSVGQRCode,
|
|
validateImageFile,
|
|
vectorizeBitmap
|
|
};
|
|
//# sourceMappingURL=qr-code-utils.es.js.map
|