@stacksjs/qrx
Version:
QR & Bar Code generating & reading. Lightweight & powerful.
1,952 lines (1,899 loc) • 85.3 kB
JavaScript
// src/config.ts
import { loadConfig } from "bunfig";
var defaults = {
type: "qr",
options: {
width: 100,
height: 100,
format: "auto",
displayValue: true,
fontOptions: "",
font: "monospace",
text: undefined,
textAlign: "center",
textPosition: "bottom",
textMargin: 2,
fontSize: 20,
background: "#ffffff",
lineColor: "#000000",
margin: 10,
marginTop: undefined,
marginBottom: undefined,
marginLeft: undefined,
marginRight: undefined,
valid() {
}
}
};
var config = await loadConfig({
name: "qrx",
defaultConfig: defaults
});
// src/bar/drivers/Barcode.ts
class Barcode {
data;
text;
options;
constructor(data, options) {
this.data = data;
this.text = options.text || data;
this.options = options;
}
}
var Barcode_default = Barcode;
// src/bar/drivers/Codabar/index.ts
class Codabar extends Barcode_default {
constructor(data, options) {
if (data.search(/^[0-9\-$:.+/]+$/) === 0) {
data = `A${data}A`;
}
super(data.toUpperCase(), options);
this.options = options;
this.text = this.options.text || "";
}
valid() {
return this.data.search(/^[A-D][0-9\-$:.+/]+[A-D]$/) !== -1;
}
encode() {
const result = [];
const encodings = this.getEncodings();
for (let i = 0;i < this.data.length; i++) {
result.push(encodings[this.data.charAt(i)]);
if (i !== this.data.length - 1) {
result.push("0");
}
}
return {
text: this.text,
data: result.join("")
};
}
getEncodings() {
return {
"0": "101010011",
"1": "101011001",
"2": "101001011",
"3": "110010101",
"4": "101101001",
"5": "110101001",
"6": "100101011",
"7": "100101101",
"8": "100110101",
"9": "110100101",
"-": "101001101",
$: "101100101",
":": "1101011011",
"/": "1101101011",
".": "1101101101",
"+": "1011011011",
A: "1011001001",
B: "1001001011",
C: "1010010011",
D: "1010011001"
};
}
}
// src/bar/drivers/CODE39/index.ts
class CODE39 extends Barcode_default {
constructor(data, options) {
data = data.toUpperCase();
if (options.mod43) {
data += getCharacter(mod43checksum(data));
}
super(data, options);
}
encode() {
let result = getEncoding("*");
for (let i = 0;i < this.data.length; i++) {
result += `${getEncoding(this.data[i])}0`;
}
result += getEncoding("*");
return {
data: result,
text: this.text
};
}
valid() {
return this.data.search(/^[0-9A-Z\-. $/+%]+$/) !== -1;
}
}
var characters = [
"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",
"-",
".",
" ",
"$",
"/",
"+",
"%",
"*"
];
var encodings = [
20957,
29783,
23639,
30485,
20951,
29813,
23669,
20855,
29789,
23645,
29975,
23831,
30533,
22295,
30149,
24005,
21623,
29981,
23837,
22301,
30023,
23879,
30545,
22343,
30161,
24017,
21959,
30065,
23921,
22385,
29015,
18263,
29141,
17879,
29045,
18293,
17783,
29021,
18269,
17477,
17489,
17681,
20753,
35770
];
function getEncoding(character) {
return getBinary(characterValue(character));
}
function getBinary(characterValue) {
return encodings[characterValue].toString(2);
}
function getCharacter(characterValue) {
return characters[characterValue];
}
function characterValue(character) {
return characters.indexOf(character);
}
function mod43checksum(data) {
let checksum = 0;
for (let i = 0;i < data.length; i++) {
checksum += characterValue(data[i]);
}
checksum = checksum % 43;
return checksum;
}
// src/bar/drivers/CODE128/constants.ts
var SET_A = 0;
var SET_B = 1;
var SET_C = 2;
var SHIFT = 98;
var START_A = 103;
var START_B = 104;
var START_C = 105;
var MODULO = 103;
var STOP = 106;
var FNC1 = 207;
var SET_BY_CODE = {
[START_A]: SET_A,
[START_B]: SET_B,
[START_C]: SET_C
};
var A_START_CHAR = String.fromCharCode(208);
var B_START_CHAR = String.fromCharCode(209);
var C_START_CHAR = String.fromCharCode(210);
var A_CHARS = "[\x00-_È-Ï]";
var B_CHARS = "[ -È-Ï]";
var C_CHARS = "(Ï*[0-9]{2}Ï*)";
var BARS = [
11011001100,
11001101100,
11001100110,
10010011000,
10010001100,
10001001100,
10011001000,
10011000100,
10001100100,
11001001000,
11001000100,
11000100100,
10110011100,
10011011100,
10011001110,
10111001100,
10011101100,
10011100110,
11001110010,
11001011100,
11001001110,
11011100100,
11001110100,
11101101110,
11101001100,
11100101100,
11100100110,
11101100100,
11100110100,
11100110010,
11011011000,
11011000110,
11000110110,
10100011000,
10001011000,
10001000110,
10110001000,
10001101000,
10001100010,
11010001000,
11000101000,
11000100010,
10110111000,
10110001110,
10001101110,
10111011000,
10111000110,
10001110110,
11101110110,
11010001110,
11000101110,
11011101000,
11011100010,
11011101110,
11101011000,
11101000110,
11100010110,
11101101000,
11101100010,
11100011010,
11101111010,
11001000010,
11110001010,
10100110000,
10100001100,
10010110000,
10010000110,
10000101100,
10000100110,
10110010000,
10110000100,
10011010000,
10011000010,
10000110100,
10000110010,
11000010010,
11001010000,
11110111010,
11000010100,
10001111010,
10100111100,
10010111100,
10010011110,
10111100100,
10011110100,
10011110010,
11110100100,
11110010100,
11110010010,
11011011110,
11011110110,
11110110110,
10101111000,
10100011110,
10001011110,
10111101000,
10111100010,
11110101000,
11110100010,
10111011110,
10111101110,
11101011110,
11110101110,
11010000100,
11010010000,
11010011100,
1100011101011
];
// src/bar/drivers/CODE128/auto.ts
var matchSetALength = (string) => string.match(new RegExp(`^${A_CHARS}*`))[0].length;
var matchSetBLength = (string) => string.match(new RegExp(`^${B_CHARS}*`))[0].length;
var matchSetC = (string) => string.match(new RegExp(`^${C_CHARS}*`))[0];
function autoSelectFromAB(string, isA) {
const ranges = isA ? A_CHARS : B_CHARS;
const untilC = string.match(new RegExp(`^(${ranges}+?)(([0-9]{2}){2,})([^0-9]|$)`));
if (untilC) {
return untilC[1] + String.fromCharCode(204) + autoSelectFromC(string.substring(untilC[1].length));
}
const matchResult = string.match(new RegExp(`^${ranges}+`));
const chars = matchResult ? matchResult[0] : "";
if (chars.length === string.length) {
return string;
}
return chars + String.fromCharCode(isA ? 205 : 206) + autoSelectFromAB(string.substring(chars.length), !isA);
}
function autoSelectFromC(string) {
const cMatch = matchSetC(string);
const length = cMatch.length;
if (length === string.length) {
return string;
}
string = string.substring(length);
const isA = matchSetALength(string) >= matchSetBLength(string);
return cMatch + String.fromCharCode(isA ? 206 : 205) + autoSelectFromAB(string, isA);
}
var auto_default = (string) => {
let newString;
const cLength = matchSetC(string).length;
if (cLength >= 2) {
newString = C_START_CHAR + autoSelectFromC(string);
} else {
const isA = matchSetALength(string) > matchSetBLength(string);
newString = (isA ? A_START_CHAR : B_START_CHAR) + autoSelectFromAB(string, isA);
}
return newString.replace(/[\xCD\xCE]([\s\S])[\xCD\xCE]/, (match, char) => String.fromCharCode(203) + char);
};
// src/bar/drivers/CODE128/CODE128.ts
class CODE128 extends Barcode_default {
bytes;
constructor(data, options) {
super(data.substring(1), options);
this.bytes = data.split("").map((char) => char.charCodeAt(0));
}
valid() {
return /^[\x00-\x7F\xC8-\xD3]+$/.test(this.data);
}
encode() {
const bytes = this.bytes;
const shiftedByte = bytes.shift();
if (shiftedByte === undefined) {
throw new Error("No more bytes available to shift.");
}
const startIndex = shiftedByte - 105;
const startSet = SET_BY_CODE[startIndex];
if (startSet === undefined) {
throw new RangeError("The encoding does not start with a start character.");
}
if (this.shouldEncodeAsEan128() === true) {
bytes.unshift(FNC1);
}
const encodingResult = CODE128.next(bytes, 1, startSet);
return {
text: this.text === this.data ? this.text.replace(/[^\x20-\x7E]/g, "") : this.text,
data: CODE128.getBar(startIndex) + encodingResult.result + CODE128.getBar((encodingResult.checksum + startIndex) % MODULO) + CODE128.getBar(STOP)
};
}
shouldEncodeAsEan128() {
let isEAN128 = this.options.ean128 || false;
if (typeof isEAN128 === "string") {
isEAN128 = isEAN128.toLowerCase() === "true";
}
return isEAN128;
}
static getBar(index) {
return BARS[index] ? BARS[index].toString() : "";
}
static correctIndex(bytes, set) {
if (set === SET_A) {
const charCode = bytes.shift();
if (charCode === undefined) {
throw new Error("No more bytes available to shift.");
}
return charCode < 32 ? charCode + 64 : charCode - 32;
}
if (set === SET_B) {
const charCode = bytes.shift();
if (charCode === undefined) {
throw new Error("No more bytes available to shift.");
}
return charCode - 32;
}
const firstCharCode = bytes.shift();
if (firstCharCode === undefined) {
throw new Error("No more bytes available to shift.");
}
const secondCharCode = bytes.shift();
if (secondCharCode === undefined) {
throw new Error("No more bytes available to shift.");
}
return (firstCharCode - 48) * 10 + secondCharCode - 48;
}
static next(bytes, pos, set) {
if (!bytes.length) {
return { result: "", checksum: 0 };
}
let nextCode, index;
if (bytes[0] >= 200) {
const shiftedByte = bytes.shift();
if (shiftedByte === undefined) {
throw new Error("No more bytes available to shift.");
}
const SWAP = {
101: 0,
100: 1,
99: 2
};
index = shiftedByte - 105;
const nextSet = SWAP[index];
if (nextSet !== undefined) {
nextCode = CODE128.next(bytes, pos + 1, nextSet);
} else {
if ((set === SET_A || set === SET_B) && index === SHIFT) {
bytes[0] = set === SET_A ? bytes[0] > 95 ? bytes[0] - 96 : bytes[0] : bytes[0] < 32 ? bytes[0] + 96 : bytes[0];
}
nextCode = CODE128.next(bytes, pos + 1, set);
}
} else {
index = CODE128.correctIndex(bytes, set);
nextCode = CODE128.next(bytes, pos + 1, set);
}
const enc = CODE128.getBar(index);
const weight = index * pos;
return {
result: enc + nextCode.result,
checksum: weight + nextCode.checksum
};
}
}
var CODE128_default = CODE128;
// src/bar/drivers/CODE128/CODE128_AUTO.ts
class CODE128AUTO extends CODE128_default {
constructor(data, options) {
if (/^[\x00-\x7F\xC8-\xD3]+$/.test(data)) {
super(auto_default(data), options);
} else {
super(data, options);
}
}
}
var CODE128_AUTO_default = CODE128AUTO;
// src/bar/drivers/CODE128/CODE128A.ts
class CODE128A extends CODE128_default {
constructor(string, options) {
super(A_START_CHAR + string, options);
}
valid() {
return new RegExp(`^${A_CHARS}+$`).test(this.data);
}
}
var CODE128A_default = CODE128A;
// src/bar/drivers/CODE128/CODE128B.ts
class CODE128B extends CODE128_default {
constructor(string, options) {
super(B_START_CHAR + string, options);
}
valid() {
return new RegExp(`^${B_CHARS}+$`).test(this.data);
}
}
var CODE128B_default = CODE128B;
// src/bar/drivers/CODE128/CODE128C.ts
class CODE128C extends CODE128_default {
constructor(string, options) {
super(C_START_CHAR + string, options);
}
valid() {
return new RegExp(`^${C_CHARS}+$`).test(this.data);
}
}
var CODE128C_default = CODE128C;
// src/bar/drivers/EAN_UPC/constants.ts
var SIDE_BIN = "101";
var MIDDLE_BIN = "01010";
var BINARIES = {
L: [
"0001101",
"0011001",
"0010011",
"0111101",
"0100011",
"0110001",
"0101111",
"0111011",
"0110111",
"0001011"
],
G: [
"0100111",
"0110011",
"0011011",
"0100001",
"0011101",
"0111001",
"0000101",
"0010001",
"0001001",
"0010111"
],
R: [
"1110010",
"1100110",
"1101100",
"1000010",
"1011100",
"1001110",
"1010000",
"1000100",
"1001000",
"1110100"
],
O: [
"0001101",
"0011001",
"0010011",
"0111101",
"0100011",
"0110001",
"0101111",
"0111011",
"0110111",
"0001011"
],
E: [
"0100111",
"0110011",
"0011011",
"0100001",
"0011101",
"0111001",
"0000101",
"0010001",
"0001001",
"0010111"
]
};
var EAN2_STRUCTURE = ["LL", "LG", "GL", "GG"];
var EAN5_STRUCTURE = [
"GGLLL",
"GLGLL",
"GLLGL",
"GLLLG",
"LGGLL",
"LLGGL",
"LLLGG",
"LGLGL",
"LGLLG",
"LLGLG"
];
var EAN13_STRUCTURE = [
"LLLLLL",
"LLGLGG",
"LLGGLG",
"LLGGGL",
"LGLLGG",
"LGGLLG",
"LGGGLL",
"LGLGLG",
"LGLGGL",
"LGGLGL"
];
// src/bar/drivers/EAN_UPC/encoder.ts
function encode(data, structure, separator) {
let encoded = data.split("").map((val, idx) => BINARIES[structure[idx]] || "").map((val, idx) => val ? val[data[idx]] : "");
if (separator) {
const last = data.length - 1;
encoded = encoded.map((val, idx) => idx < last ? val + separator : val);
}
return encoded.join("");
}
// src/bar/drivers/EAN_UPC/EAN5.ts
function checksum(data) {
const result = data.split("").map((n) => +n).reduce((sum, a, idx) => {
return idx % 2 ? sum + a * 9 : sum + a * 3;
}, 0);
return result % 10;
}
class EAN5 extends Barcode_default {
constructor(data, options) {
super(data, options);
}
valid() {
return this.data.search(/^\d{5}$/) !== -1;
}
encode() {
const structure = EAN5_STRUCTURE[checksum(this.data)];
return {
data: `1011${encode(this.data, structure, "01")}`,
text: this.text
};
}
}
var EAN5_default = EAN5;
// src/bar/drivers/EAN_UPC/EAN.ts
class EAN extends Barcode_default {
fontSize;
guardHeight;
constructor(data, options) {
super(data, options);
this.fontSize = !options.flat && options.fontSize > options.width * 10 ? options.width * 10 : options.fontSize;
this.guardHeight = options.height + this.fontSize / 2 + options.textMargin;
}
encode() {
return this.options.flat ? this.encodeFlat() : this.encodeGuarded();
}
leftText(from, to) {
if (!from)
from = 1;
if (!to)
to = 6;
return this.text.substr(from, to);
}
leftEncode(data, structure) {
if (!data)
data = this.data;
if (!structure)
structure = this.options.structure;
return encode(data, structure);
}
rightText(from, to) {
if (!from)
from = 1;
if (!to)
to = this.data.length;
return this.text.substr(from, to);
}
rightEncode(data, structure) {
if (!data)
data = this.data;
if (!structure)
structure = this.options.structure;
return encode(data, structure);
}
encodeGuarded() {
const textOptions = { fontSize: this.fontSize };
const guardOptions = { height: this.guardHeight };
return [
{ data: SIDE_BIN, options: guardOptions },
{ data: this.leftEncode(), text: this.leftText(), options: textOptions },
{ data: MIDDLE_BIN, options: guardOptions },
{ data: this.rightEncode(), text: this.rightText(), options: textOptions },
{ data: SIDE_BIN, options: guardOptions }
];
}
encodeFlat() {
const data = [
SIDE_BIN,
this.leftEncode(),
MIDDLE_BIN,
this.rightEncode(),
SIDE_BIN
];
return {
data: data.join(""),
text: this.text
};
}
}
// src/bar/drivers/EAN_UPC/EAN8.ts
function checksum2(number) {
const res = number.substr(0, 7).split("").map((n) => +n).reduce((sum, a, idx) => idx % 2 ? sum + a : sum + a * 3, 0);
return (10 - res % 10) % 10;
}
class EAN8 extends EAN {
constructor(data, options) {
if (data.search(/^\d{7}$/) !== -1) {
data += checksum2(data);
}
super(data, options);
}
valid() {
return this.data.search(/^\d{8}$/) !== -1 && +this.data[7] === checksum2(this.data);
}
leftText() {
return super.leftText(0, 4);
}
leftEncode() {
const data = this.data.substr(0, 4);
return super.leftEncode(data, "LLLL");
}
rightText() {
return super.rightText(4, 4);
}
rightEncode() {
const data = this.data.substr(4, 4);
return super.rightEncode(data, "RRRR");
}
}
var EAN8_default = EAN8;
// src/bar/drivers/EAN_UPC/EAN13.ts
function checksum3(number) {
const res = number.substr(0, 12).split("").map((n) => +n).reduce((sum, a, idx) => idx % 2 ? sum + a * 3 : sum + a, 0);
return (10 - res % 10) % 10;
}
class EAN13 extends EAN {
lastChar;
constructor(data, options) {
if (data.search(/^\d{12}$/) !== -1) {
data += checksum3(data);
}
super(data, options);
this.lastChar = options.lastChar;
}
valid() {
return this.data.search(/^\d{13}$/) !== -1 && +this.data[12] === checksum3(this.data);
}
leftText() {
return super.leftText(1, 6);
}
leftEncode() {
const data = this.data.substr(1, 6);
const structure = EAN13_STRUCTURE[Number(this.data[0])];
return super.leftEncode(data, structure);
}
rightText() {
return super.rightText(7, 6);
}
rightEncode() {
const data = this.data.substr(7, 6);
return super.rightEncode(data, "RRRRRR");
}
encodeGuarded() {
const data = super.encodeGuarded();
if (this.options.displayValue) {
data.unshift({
data: "000000000000",
text: this.text.substr(0, 1),
options: { textAlign: "left", fontSize: this.fontSize }
});
if (this.options.lastChar) {
data.push({
data: "00"
});
data.push({
data: "00000",
text: this.options.lastChar,
options: { fontSize: this.fontSize }
});
}
}
return data;
}
}
// src/bar/drivers/EAN_UPC/UPC.ts
class UPC extends Barcode_default {
displayValue;
fontSize;
guardHeight;
constructor(data, options) {
if (data.search(/^\d{11}$/) !== -1) {
data += checksum4(data);
}
super(data, options);
this.displayValue = options.displayValue;
if (options.fontSize > options.width * 10) {
this.fontSize = options.width * 10;
} else {
this.fontSize = options.fontSize;
}
this.guardHeight = options.height + this.fontSize / 2 + options.textMargin;
}
valid() {
return this.data.search(/^\d{12}$/) !== -1 && Number(this.data[11]) === checksum4(this.data);
}
encode() {
if (this.options.flat) {
return this.flatEncoding();
}
return this.guardedEncoding();
}
flatEncoding() {
let result = "";
result += "101";
result += encode(this.data.substr(0, 6), "LLLLLL");
result += "01010";
result += encode(this.data.substr(6, 6), "RRRRRR");
result += "101";
return {
data: result,
text: this.text
};
}
guardedEncoding() {
const result = [];
if (this.displayValue) {
result.push({
data: "00000000",
text: this.text.substr(0, 1),
options: { textAlign: "left", fontSize: this.fontSize }
});
}
result.push({
data: `101${encode(this.data[0], "L")}`,
options: { height: this.guardHeight }
});
result.push({
data: encode(this.data.substr(1, 5), "LLLLL"),
text: this.text.substr(1, 5),
options: { fontSize: this.fontSize }
});
result.push({
data: "01010",
options: { height: this.guardHeight }
});
result.push({
data: encode(this.data.substr(6, 5), "RRRRR"),
text: this.text.substr(6, 5),
options: { fontSize: this.fontSize }
});
result.push({
data: `${encode(this.data[11], "R")}101`,
options: { height: this.guardHeight }
});
if (this.displayValue) {
result.push({
data: "00000000",
text: this.text.substr(11, 1),
options: { textAlign: "right", fontSize: this.fontSize }
});
}
return result;
}
}
function checksum4(number) {
let result = 0;
let i;
for (i = 1;i < 11; i += 2) {
result += Number.parseInt(number[i]);
}
for (i = 0;i < 11; i += 2) {
result += Number.parseInt(number[i]) * 3;
}
return (10 - result % 10) % 10;
}
var UPC_default = UPC;
// src/bar/drivers/EAN_UPC/UPCE.ts
var EXPANSIONS = [
"XX00000XXX",
"XX10000XXX",
"XX20000XXX",
"XXX00000XX",
"XXXX00000X",
"XXXXX00005",
"XXXXX00006",
"XXXXX00007",
"XXXXX00008",
"XXXXX00009"
];
var PARITIES = [
["EEEOOO", "OOOEEE"],
["EEOEOO", "OOEOEE"],
["EEOOEO", "OOEEOE"],
["EEOOOE", "OOEEEO"],
["EOEEOO", "OEOOEE"],
["EOOEEO", "OEEOOE"],
["EOOOEE", "OEEEOO"],
["EOEOEO", "OEOEOE"],
["EOEOOE", "OEOEEO"],
["EOOEOE", "OEEOEO"]
];
class UPCE extends Barcode_default {
isValid;
middleDigits;
upcA;
displayValue;
fontSize;
guardHeight;
constructor(data, options) {
super(data, options);
this.isValid = false;
if (data.search(/^\d{6}$/) !== -1) {
this.middleDigits = data;
} else if (data.search(/^[01]\d{7}$/) !== -1) {
this.middleDigits = data.substring(1, data.length - 1);
this.upcA = expandToUPCA(this.middleDigits, data[0]);
if (this.upcA[this.upcA.length - 1] === data[data.length - 1]) {
this.isValid = true;
} else {
return;
}
} else {
return;
}
this.displayValue = options.displayValue;
if (options.fontSize > options.width * 10) {
this.fontSize = options.width * 10;
} else {
this.fontSize = options.fontSize;
}
this.guardHeight = options.height + this.fontSize / 2 + options.textMargin;
}
valid() {
return this.isValid;
}
encode() {
if (this.options.flat) {
return this.flatEncoding();
}
return this.guardedEncoding();
}
flatEncoding() {
let result = "";
result += "101";
result += this.encodeMiddleDigits();
result += "010101";
return {
data: result,
text: this.text
};
}
guardedEncoding() {
const result = [];
if (this.displayValue) {
result.push({
data: "00000000",
text: this.text[0],
options: { textAlign: "left", fontSize: this.fontSize }
});
}
result.push({
data: "101",
options: { height: this.guardHeight }
});
result.push({
data: this.encodeMiddleDigits(),
text: this.text.substring(1, 7),
options: { fontSize: this.fontSize }
});
result.push({
data: "010101",
options: { height: this.guardHeight }
});
if (this.displayValue) {
result.push({
data: "00000000",
text: this.text[7],
options: { textAlign: "right", fontSize: this.fontSize }
});
}
return result;
}
encodeMiddleDigits() {
const numberSystem = this.upcA[0];
const checkDigit = this.upcA[this.upcA.length - 1];
const parity = PARITIES[Number.parseInt(checkDigit)][Number.parseInt(numberSystem)];
return encode(this.middleDigits, parity);
}
}
function expandToUPCA(middleDigits, numberSystem) {
const lastUpcE = Number.parseInt(middleDigits[middleDigits.length - 1]);
const expansion = EXPANSIONS[lastUpcE];
let result = "";
let digitIndex = 0;
for (let i = 0;i < expansion.length; i++) {
const c = expansion[i];
if (c === "X") {
result += middleDigits[digitIndex++];
} else {
result += c;
}
}
result = `${numberSystem}${result}`;
return `${result}${checksum4(result)}`;
}
var UPCE_default = UPCE;
// src/bar/drivers/EAN_UPC/EAN2.ts
class EAN2 extends Barcode_default {
constructor(data, options) {
super(data, options);
}
valid() {
return this.data.search(/^\d{2}$/) !== -1;
}
encode() {
const structure = EAN2_STRUCTURE[Number.parseInt(this.data) % 4];
return {
data: `1011${encode(this.data, structure, "01")}`,
text: this.text
};
}
}
// src/bar/drivers/GenericBarcode/index.ts
class GenericBarcode extends Barcode_default {
constructor(data, options) {
super(data, options);
}
encode() {
return {
data: "10101010101010101010101010101010101010101",
text: this.text
};
}
valid() {
return true;
}
}
// src/bar/drivers/ITF/constants.ts
var START_BIN = "1010";
var END_BIN = "11101";
var BINARIES2 = [
"00110",
"10001",
"01001",
"11000",
"00101",
"10100",
"01100",
"00011",
"10010",
"01010"
];
// src/bar/drivers/ITF/ITF.ts
class ITF extends Barcode_default {
valid() {
return this.data.search(/^(\d{2})+$/) !== -1;
}
encode() {
const encoded = this.data.match(/.{2}/g) || [].map((pair) => this.encodePair(pair)).join("");
return {
data: START_BIN + encoded + END_BIN,
text: this.text
};
}
encodePair(pair) {
const second = BINARIES2[Number(pair[1])];
return BINARIES2[Number(pair[0])].split("").map((first, idx) => (first === "1" ? "111" : "1") + (second[idx] === "1" ? "000" : "0")).join("");
}
}
var ITF_default = ITF;
// src/bar/drivers/ITF/ITF14.ts
function checksum5(data) {
const res = data.substr(0, 13).split("").map((num) => Number.parseInt(num, 10)).reduce((sum, n, idx) => sum + n * (3 - idx % 2 * 2), 0);
return Math.ceil(res / 10) * 10 - res;
}
class ITF14 extends ITF_default {
constructor(data, options) {
if (data.search(/^\d{13}$/) !== -1) {
data += checksum5(data);
}
super(data, options);
}
valid() {
return this.data.search(/^\d{14}$/) !== -1 && +this.data[13] === checksum5(this.data);
}
}
var ITF14_default = ITF14;
// src/bar/drivers/MSI/MSI.ts
class MSI extends Barcode_default {
constructor(data, options) {
super(data, options);
}
encode() {
let ret = "110";
for (let i = 0;i < this.data.length; i++) {
const digit = Number.parseInt(this.data[i]);
let bin = digit.toString(2);
bin = addZeroes(bin, 4 - bin.length);
for (let b = 0;b < bin.length; b++) {
ret += bin[b] === "0" ? "100" : "110";
}
}
ret += "1001";
return {
data: ret,
text: this.text
};
}
valid() {
return this.data.search(/^\d+$/) !== -1;
}
}
function addZeroes(number, n) {
for (let i = 0;i < n; i++) {
number = `0${number}`;
}
return number;
}
var MSI_default = MSI;
// src/bar/drivers/MSI/checksums.ts
function mod10(number) {
let sum = 0;
for (let i = 0;i < number.length; i++) {
const n = Number.parseInt(number[i]);
if ((i + number.length) % 2 === 0) {
sum += n;
} else {
sum += n * 2 % 10 + Math.floor(n * 2 / 10);
}
}
return (10 - sum % 10) % 10;
}
function mod11(number) {
let sum = 0;
const weights = [2, 3, 4, 5, 6, 7];
for (let i = 0;i < number.length; i++) {
const n = Number.parseInt(number[number.length - 1 - i]);
sum += weights[i % weights.length] * n;
}
return (11 - sum % 11) % 11;
}
// src/bar/drivers/MSI/MSI10.ts
class MSI10 extends MSI_default {
constructor(data, options) {
super(data + mod10(data), options);
}
}
var MSI10_default = MSI10;
// src/bar/drivers/MSI/MSI11.ts
class MSI11 extends MSI_default {
constructor(data, options) {
super(data + mod11(data), options);
}
}
var MSI11_default = MSI11;
// src/bar/drivers/MSI/MSI1010.ts
class MSI1010 extends MSI_default {
constructor(data, options) {
data += mod10(data);
data += mod10(data);
super(data, options);
}
}
var MSI1010_default = MSI1010;
// src/bar/drivers/MSI/MSI1110.ts
class MSI1110 extends MSI_default {
constructor(data, options) {
data += mod11(data);
data += mod10(data);
super(data, options);
}
}
var MSI1110_default = MSI1110;
// src/bar/drivers/Pharmacode/index.ts
class Pharmacode extends Barcode_default {
number;
constructor(data, options) {
super(data, options);
this.number = Number.parseInt(data, 10);
}
encode() {
let z = this.number;
let result = "";
while (!Number.isNaN(z) && z !== 0) {
if (z % 2 === 0) {
result = `11100${result}`;
z = (z - 2) / 2;
} else {
result = `100${result}`;
z = (z - 1) / 2;
}
}
result = result.slice(0, -2);
return {
data: result,
text: this.text
};
}
valid() {
return this.number >= 3 && this.number <= 131070;
}
}
// src/bar/drivers/index.ts
var barcodes = {
CODE39,
CODE128: CODE128_AUTO_default,
CODE128A: CODE128A_default,
CODE128B: CODE128B_default,
CODE128C: CODE128C_default,
EAN13,
EAN8: EAN8_default,
EAN5: EAN5_default,
EAN2,
UPC: UPC_default,
UPCE: UPCE_default,
ITF14: ITF14_default,
ITF: ITF_default,
MSI: MSI_default,
MSI10: MSI10_default,
MSI11: MSI11_default,
MSI1010: MSI1010_default,
MSI1110: MSI1110_default,
Pharmacode,
Codabar,
GenericBarcode
};
// src/bar/exceptions/ErrorHandler.ts
class ErrorHandler {
api;
constructor(api) {
this.api = api;
}
handleCatch(e) {
if (e.name === "InvalidInputException") {
if (this.api._options.valid !== this.api._defaults.valid) {
this.api._options.valid(false);
} else {
throw e.message;
}
} else {
throw e;
}
this.api.render = function() {
};
}
wrapBarcodeCall(func, ...args) {
try {
const result = func(...args);
this.api._options.valid(true);
return result;
} catch (e) {
this.handleCatch(e);
return this.api;
}
}
}
var ErrorHandler_default = ErrorHandler;
// src/bar/exceptions/exceptions.ts
class InvalidInputException extends Error {
symbology;
input;
constructor(symbology, input) {
super();
this.name = "InvalidInputException";
this.symbology = symbology;
this.input = input;
this.message = `"${this.input}" is not a valid input for ${this.symbology}`;
}
}
class InvalidElementException extends Error {
constructor() {
super();
this.name = "InvalidElementException";
this.message = "Not supported type to render on";
}
}
class NoElementException extends Error {
constructor() {
super();
this.name = "NoElementException";
this.message = "No element to render on.";
}
}
// src/bar/utils/fixOptions.ts
function fixOptions(options) {
options.marginTop = options.marginTop || options.margin;
options.marginBottom = options.marginBottom || options.margin;
options.marginRight = options.marginRight || options.margin;
options.marginLeft = options.marginLeft || options.margin;
return options;
}
// src/bar/utils/merge.ts
var merge = (old, replaceObj) => ({ ...old, ...replaceObj });
var merge_default = merge;
// src/bar/renderers/shared.ts
function getEncodingHeight(encoding, options) {
return options.height + (options.displayValue && encoding.text.length > 0 ? options.fontSize + options.textMargin : 0) + options.marginTop + options.marginBottom;
}
function getBarcodePadding(textWidth, barcodeWidth, options) {
if (options.displayValue && barcodeWidth < textWidth) {
if (options.textAlign === "center") {
return Math.floor((textWidth - barcodeWidth) / 2);
}
if (options.textAlign === "left") {
return 0;
}
if (options.textAlign === "right") {
return Math.floor(textWidth - barcodeWidth);
}
}
return 0;
}
function calculateEncodingAttributes(encodings2, barcodeOptions, context) {
for (let i = 0;i < encodings2.length; i++) {
const encoding = encodings2[i];
const options = merge(barcodeOptions, encoding.options);
let textWidth;
if (options.displayValue) {
textWidth = measureText(encoding.text, options, context);
} else {
textWidth = 0;
}
const barcodeWidth = encoding.data.length * options.width;
encoding.width = Math.ceil(Math.max(textWidth, barcodeWidth));
encoding.height = getEncodingHeight(encoding, options);
encoding.barcodePadding = getBarcodePadding(textWidth, barcodeWidth, options);
}
}
function getTotalWidthOfEncodings(encodings2) {
let totalWidth = 0;
for (let i = 0;i < encodings2.length; i++) {
totalWidth += encodings2[i].width;
}
return totalWidth;
}
function getMaximumHeightOfEncodings(encodings2) {
let maxHeight = 0;
for (let i = 0;i < encodings2.length; i++) {
if (encodings2[i].height > maxHeight) {
maxHeight = encodings2[i].height;
}
}
return maxHeight;
}
function measureText(string, options, context) {
let ctx;
if (context) {
ctx = context;
} else if (typeof document !== "undefined") {
ctx = document.createElement("canvas").getContext("2d");
} else {
return 0;
}
ctx.font = `${options.fontOptions} ${options.fontSize}px ${options.font}`;
const measureTextResult = ctx.measureText(string);
if (!measureTextResult) {
return 0;
}
const size = measureTextResult.width;
return size;
}
// src/bar/renderers/canvas.ts
class CanvasRenderer {
canvas;
encodings;
options;
constructor(canvas, encodings2, options) {
this.canvas = canvas;
this.encodings = encodings2;
this.options = options;
}
render() {
if (!this.canvas.getContext) {
throw new Error("The browser does not support canvas.");
}
this.prepareCanvas();
for (let i = 0;i < this.encodings.length; i++) {
const encodingOptions = merge_default(this.options, this.encodings[i].options);
this.drawCanvasBarcode(encodingOptions, this.encodings[i]);
this.drawCanvasText(encodingOptions, this.encodings[i]);
this.moveCanvasDrawing(this.encodings[i]);
}
this.restoreCanvas();
}
prepareCanvas() {
const ctx = this.canvas.getContext("2d");
ctx.save();
calculateEncodingAttributes(this.encodings, this.options, ctx);
const totalWidth = getTotalWidthOfEncodings(this.encodings);
const maxHeight = getMaximumHeightOfEncodings(this.encodings);
this.canvas.width = totalWidth + this.options.marginLeft + this.options.marginRight;
this.canvas.height = maxHeight;
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
if (this.options.background) {
ctx.fillStyle = this.options.background;
ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
ctx.translate(this.options.marginLeft, 0);
}
drawCanvasBarcode(options, encoding) {
const ctx = this.canvas.getContext("2d");
const binary = encoding.data;
let yFrom;
if (options.textPosition === "top") {
yFrom = options.marginTop + options.fontSize + options.textMargin;
} else {
yFrom = options.marginTop;
}
ctx.fillStyle = options.lineColor;
for (let b = 0;b < binary.length; b++) {
const x = b * options.width + encoding.barcodePadding;
if (binary[b] === "1") {
ctx.fillRect(x, yFrom, options.width, options.height);
} else if (binary[b]) {
ctx.fillRect(x, yFrom, options.width, options.height * binary[b]);
}
}
}
drawCanvasText(options, encoding) {
const ctx = this.canvas.getContext("2d");
const font = `${options.fontOptions} ${options.fontSize}px ${options.font}`;
if (options.displayValue) {
let x, y;
if (options.textPosition === "top") {
y = options.marginTop + options.fontSize - options.textMargin;
} else {
y = options.height + options.textMargin + options.marginTop + options.fontSize;
}
ctx.font = font;
if (options.textAlign === "left" || encoding.barcodePadding > 0) {
x = 0;
ctx.textAlign = "left";
} else if (options.textAlign === "right") {
x = encoding.width - 1;
ctx.textAlign = "right";
} else {
x = encoding.width / 2;
ctx.textAlign = "center";
}
ctx.fillText(encoding.text, x, y);
}
}
moveCanvasDrawing(encoding) {
const ctx = this.canvas.getContext("2d");
ctx.translate(encoding.width, 0);
}
restoreCanvas() {
const ctx = this.canvas.getContext("2d");
ctx.restore();
}
}
var canvas_default = CanvasRenderer;
// src/bar/renderers/object.ts
class ObjectRenderer {
object;
encodings;
options;
constructor(object, encodings2, options) {
this.object = object;
this.encodings = encodings2;
this.options = options;
}
render() {
this.object.encodings = this.encodings;
}
}
var object_default = ObjectRenderer;
// src/bar/renderers/svg.ts
var svgns = "http://www.w3.org/2000/svg";
class SVGRenderer {
document;
svg;
encodings;
options;
constructor(svg, encodings2, options) {
this.svg = svg;
this.encodings = encodings2;
this.options = options;
this.document = options.xmlDocument || document;
}
render() {
let currentX = this.options.marginLeft;
this.prepareSVG();
for (let i = 0;i < this.encodings.length; i++) {
const encoding = this.encodings[i];
const encodingOptions = merge_default(this.options, encoding.options);
const group = this.createGroup(currentX, encodingOptions.marginTop, this.svg);
this.setGroupOptions(group, encodingOptions);
this.drawSvgBarcode(group, encodingOptions, encoding);
this.drawSVGText(group, encodingOptions, encoding);
currentX += encoding.width;
}
}
prepareSVG() {
while (this.svg.firstChild) {
this.svg.removeChild(this.svg.firstChild);
}
calculateEncodingAttributes(this.encodings, this.options);
const totalWidth = getTotalWidthOfEncodings(this.encodings);
const maxHeight = getMaximumHeightOfEncodings(this.encodings);
const width = totalWidth + this.options.marginLeft + this.options.marginRight;
this.setSvgAttributes(width, maxHeight);
if (this.options.background) {
this.drawRect(0, 0, width, maxHeight, this.svg).setAttribute("style", `fill:${this.options.background};`);
}
}
drawSvgBarcode(parent, options, encoding) {
const binary = encoding.data;
let yFrom;
if (options.textPosition === "top") {
yFrom = options.fontSize + options.textMargin;
} else {
yFrom = 0;
}
let barWidth = 0;
let x = 0;
for (let b = 0;b < binary.length; b++) {
x = b * options.width + encoding.barcodePadding;
if (binary[b] === "1") {
barWidth++;
} else if (barWidth > 0) {
this.drawRect(x - options.width * barWidth, yFrom, options.width * barWidth, options.height, parent);
barWidth = 0;
}
}
if (barWidth > 0) {
this.drawRect(x - options.width * (barWidth - 1), yFrom, options.width * barWidth, options.height, parent);
}
}
drawSVGText(parent, options, encoding) {
const textElem = this.document.createElementNS(svgns, "text");
if (options.displayValue) {
let x, y;
textElem.setAttribute("style", `font:${options.fontOptions} ${options.fontSize}px ${options.font}`);
if (options.textPosition === "top") {
y = options.fontSize - options.textMargin;
} else {
y = options.height + options.textMargin + options.fontSize;
}
if (options.textAlign === "left" || encoding.barcodePadding > 0) {
x = 0;
textElem.setAttribute("text-anchor", "start");
} else if (options.textAlign === "right") {
x = encoding.width - 1;
textElem.setAttribute("text-anchor", "end");
} else {
x = encoding.width / 2;
textElem.setAttribute("text-anchor", "middle");
}
textElem.setAttribute("x", x.toString());
textElem.setAttribute("y", y);
textElem.appendChild(this.document.createTextNode(encoding.text));
parent.appendChild(textElem);
}
}
setSvgAttributes(width, height) {
const svg = this.svg;
svg.setAttribute("width", `${width}px`);
svg.setAttribute("height", `${height}px`);
svg.setAttribute("x", "0px");
svg.setAttribute("y", "0px");
svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
svg.setAttribute("xmlns", svgns);
svg.setAttribute("version", "1.1");
svg.setAttribute("style", "transform: translate(0,0)");
}
createGroup(x, y, parent) {
const group = this.document.createElementNS(svgns, "g");
group.setAttribute("transform", `translate(${x}, ${y})`);
parent.appendChild(group);
return group;
}
setGroupOptions(group, options) {
group.setAttribute("style", `fill:${options.lineColor};`);
}
drawRect(x, y, width, height, parent) {
const rect = this.document.createElementNS(svgns, "rect");
rect.setAttribute("x", x.toString());
rect.setAttribute("y", y.toString());
rect.setAttribute("width", width.toString());
rect.setAttribute("height", height.toString());
parent.appendChild(rect);
return rect;
}
}
var svg_default = SVGRenderer;
// src/bar/renderers/index.ts
var renderers = {
CanvasRenderer: canvas_default,
ObjectRenderer: object_default,
SVGRenderer: svg_default
};
var renderers_default = renderers;
// src/bar/utils/optionsFromStrings.ts
function optionsFromStrings(options) {
const intOptions = [
"width",
"height",
"textMargin",
"fontSize",
"margin",
"marginTop",
"marginBottom",
"marginLeft",
"marginRight"
];
for (let intOption in intOptions) {
if (Object.prototype.hasOwnProperty.call(intOptions, intOption)) {
intOption = intOptions[intOption];
if (typeof options[intOption] === "string") {
options[intOption] = Number.parseInt(options[intOption], 10);
}
}
}
if (typeof options.displayValue === "string") {
options.displayValue = options.displayValue !== "false";
}
return options;
}
var optionsFromStrings_default = optionsFromStrings;
// src/bar/utils/getOptionsFromElement.ts
function getOptionsFromElement(element) {
let options = {};
for (const property in defaults) {
if (Object.prototype.hasOwnProperty.call(defaults, property)) {
if (element.hasAttribute(`jsbarcode-${property.toLowerCase()}`)) {
options[property] = element.getAttribute(`jsbarcode-${property.toLowerCase()}`);
}
if (element.hasAttribute(`data-${property.toLowerCase()}`)) {
options[property] = element.getAttribute(`data-${property.toLowerCase()}`);
}
}
}
options.value = element.getAttribute("jsbarcode-value") || element.getAttribute("data-value");
options = optionsFromStrings_default(options);
return options;
}
var getOptionsFromElement_default = getOptionsFromElement;
// src/bar/utils/getRenderProperties.ts
function getRenderProperties(element) {
if (typeof element === "string") {
return querySelectedRenderProperties(element);
}
if (Array.isArray(element)) {
const returnArray = [];
for (let i = 0;i < element.length; i++) {
returnArray.push(getRenderProperties(element[i]));
}
return returnArray;
}
if (typeof HTMLCanvasElement !== "undefined" && element instanceof HTMLImageElement) {
return newCanvasRenderProperties(element);
}
if (element && element.nodeName && element.nodeName.toLowerCase() === "svg" || typeof SVGElement !== "undefined" && element instanceof SVGElement) {
return {
element,
options: getOptionsFromElement_default(element),
renderer: renderers_default.SVGRenderer
};
}
if (typeof HTMLCanvasElement !== "undefined" && element instanceof HTMLCanvasElement) {
return {
element,
options: getOptionsFromElement_default(element),
renderer: renderers_default.CanvasRenderer
};
}
if (element && element.getContext) {
return {
element,
renderer: renderers_default.CanvasRenderer
};
}
if (element && typeof element === "object" && !element.nodeName) {
return {
element,
renderer: renderers_default.ObjectRenderer
};
}
throw new InvalidElementException;
}
function querySelectedRenderProperties(string) {
const selector = document.querySelectorAll(string);
if (selector.length === 0) {
return;
} else {
const returnArray = [];
for (let i = 0;i < selector.length; i++) {
returnArray.push(getRenderProperties(selector[i]));
}
return returnArray;
}
}
function newCanvasRenderProperties(imgElement) {
const canvas = document.createElement("canvas");
return {
element: canvas,
options: getOptionsFromElement_default(imgElement),
renderer: renderers_default.CanvasRenderer,
afterRender() {
imgElement.setAttribute("src", canvas.toDataURL());
}
};
}
// src/bar/utils/linearizeEncodings.ts
function linearizeEncodings(encodings2) {
const linearEncodings = [];
function nextLevel(encoded) {
if (Array.isArray(encoded)) {
for (let i = 0;i < encoded.length; i++) {
nextLevel(encoded[i]);
}
} else {
encoded.text = encoded.text || "";
encoded.data = encoded.data || "";
linearEncodings.push(encoded);
}
}
nextLevel(encodings2);
return linearEncodings;
}
// src/bar/index.ts
var API = function() {
};
var barcode = function(element, text, options) {
const api = new API;
if (typeof element === "undefined") {
throw new TypeError("No element to render on was provided.");
}
api._renderProperties = getRenderProperties(element);
api._encodings = [];
api._options = defaults;
api._errorHandler = new ErrorHandler_default(api);
if (typeof text !== "undefined") {
options = options || {};
if (!options.format) {
options.format = autoSelectBarcode();
}
api.options(options)[options.format](text, options).render();
}
return api;
};
for (const name in barcodes) {
if (Object.prototype.hasOwnProperty.call(barcodes, name)) {
registerBarcode(barcodes, name);
}
}
function registerBarcode(barcodes2, name) {
API.prototype[name] = API.prototype[name.toUpperCase()] = API.prototype[name.toLowerCase()] = function(text, options) {
return this._errorHandler.wrapBarcodeCall(() => {
options.text = typeof options.text === "undefined" ? undefined : `${options.text}`;
let newOptions = merge(this._options, options);
newOptions = optionsFromStrings_default(newOptions);
const Encoder = barcodes2[name];
const encoded = encode2(text, Encoder, newOptions);
this._encodings.push(encoded);
return this;
});
};
}
function encode2(text, Encoder, options) {
text = `${text}`;
const encoder = new Encoder(text, options);
if (!encoder.valid()) {
throw new InvalidInputException(encoder.constructor.name, text);
}
let encoded = encoder.encode();
encoded = linearizeEncodings(encoded);
for (let i = 0;i < encoded.length; i++) {
encoded[i].options = merge(options, encoded[i].options);
}
return encoded;
}
function autoSelectBarcode() {
if (barcodes.CODE128) {
return "CODE128";
}
return Object.keys(barcodes)[0];
}
API.prototype.options = function(options) {
this._options = merge(this._options, options);
return this;
};
API.prototype.blank = function(size) {
const zeroes = new Array(size + 1).join("0");
this._encodings.push({ data: zeroes });
return this;
};
API.prototype.init = function() {
if (!this._renderProperties) {
return;
}
if (!Array.isArray(this._renderProperties)) {
this._renderProperties = [this._renderProperties];
}
let renderProperty;
let options;
for (const i in this._renderProperties) {
renderProperty = this._renderProperties[i];
options = merge(this._options, renderProperty.options);
if (options.format === "auto") {
options.format = autoSelectBarcode();
}
this._errorHandler.wrapBarcodeCall(() => {
const text = options.value;
const Encoder = barcodes[options.format.toUpperCase()];
const encoded = encode2(text, Encoder, options);
render(renderProperty, encoded, options);
});
}
};
API.prototype.render = function() {
if (!this._renderProperties) {
throw new NoElementException;
}
if (Array.isArray(this._renderProperties)) {
for (let i = 0;i < this._renderProperties.length; i++) {
render(this._renderProperties[i], this._encodings, this._options);
}
} else {
render(this._renderProperties, this._encodings, this._options);
}
return this;
};
API.prototype._defaults = defaults;
function render(renderProperties, encodings2, options) {
encodings2 = linearizeEncodings(encodings2);
for (let i = 0;i < encodings2.length; i++) {
encodings2[i].options = merge(options, encodings2[i].options);
fixOptions(encodings2[i].options);
}
fixOptions(options);
const Renderer = renderProperties.renderer;
const renderer = new Renderer(renderProperties.element, encodings2, options);
renderer.render();
if (renderProperties.afterRender) {
renderProperties.afterRender();
}
}
if (typeof window !== "undefined") {
window.barcode = barcode;
}
// src/qr/types.ts
var QRErrorCorrectLevel;
((QRErrorCorrectLevel2) => {
QRErrorCorrectLevel2[QRErrorCorrectLevel2["L"] = 1] = "L";
QRErrorCorrectLevel2[QRErrorCorrectLevel2["M"] = 0] = "M";
QRErrorCorrectLevel2[QRErrorCorrectLevel2["Q"] = 3] = "Q";
QRErrorCorrectLevel2[QRErrorCorrectLevel2["H"] = 2] = "H";
})(QRErrorCorrectLevel ||= {});
// src/qr/utils.ts
function isSupportCanvas() {
return typeof CanvasRenderingContext2D !== "undefined";
}
function getAndroid() {
const sAgent = navigator.userAgent.toLowerCase();
if (sAgent.includes("android")) {
const match = sAgent.match(/android (\d\.\d)/i);
if (match && match[1]) {
return Number.parseFloat(match[1]);
}
return 1;
}
return false;
}
function getUTF8Length(sText) {
const replacedText = encodeURI(sText).toString().replace(