UNPKG

@stacksjs/qrx

Version:

QR & Bar Code generating & reading. Lightweight & powerful.

1,952 lines (1,899 loc) 85.3 kB
// 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(