1
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
class Barcode{
|
||||
constructor(data, options){
|
||||
this.data = data;
|
||||
this.text = options.text || data;
|
||||
this.options = options;
|
||||
}
|
||||
}
|
||||
|
||||
export default Barcode;
|
||||
@@ -0,0 +1,127 @@
|
||||
import Barcode from "../Barcode.js";
|
||||
import { SHIFT, SET_A, SET_B, MODULO, STOP, FNC1, SET_BY_CODE, SWAP, BARS } from './constants';
|
||||
|
||||
// This is the master class,
|
||||
// it does require the start code to be included in the string
|
||||
class CODE128 extends Barcode {
|
||||
constructor(data, options) {
|
||||
super(data.substring(1), options);
|
||||
|
||||
// Get array of ascii codes from data
|
||||
this.bytes = data.split('')
|
||||
.map(char => char.charCodeAt(0));
|
||||
}
|
||||
|
||||
valid() {
|
||||
// ASCII value ranges 0-127, 200-211
|
||||
return /^[\x00-\x7F\xC8-\xD3]+$/.test(this.data);
|
||||
}
|
||||
|
||||
// The public encoding function
|
||||
encode() {
|
||||
const bytes = this.bytes;
|
||||
// Remove the start code from the bytes and set its index
|
||||
const startIndex = bytes.shift() - 105;
|
||||
// Get start set by index
|
||||
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);
|
||||
}
|
||||
|
||||
// Start encode with the right type
|
||||
const encodingResult = CODE128.next(bytes, 1, startSet);
|
||||
|
||||
return {
|
||||
text:
|
||||
this.text === this.data
|
||||
? this.text.replace(/[^\x20-\x7E]/g, '')
|
||||
: this.text,
|
||||
data:
|
||||
// Add the start bits
|
||||
CODE128.getBar(startIndex) +
|
||||
// Add the encoded bits
|
||||
encodingResult.result +
|
||||
// Add the checksum
|
||||
CODE128.getBar((encodingResult.checksum + startIndex) % MODULO) +
|
||||
// Add the end bits
|
||||
CODE128.getBar(STOP)
|
||||
};
|
||||
}
|
||||
|
||||
// GS1-128/EAN-128
|
||||
shouldEncodeAsEan128() {
|
||||
let isEAN128 = this.options.ean128 || false;
|
||||
if (typeof isEAN128 === 'string') {
|
||||
isEAN128 = isEAN128.toLowerCase() === 'true';
|
||||
}
|
||||
return isEAN128;
|
||||
}
|
||||
|
||||
// Get a bar symbol by index
|
||||
static getBar(index) {
|
||||
return BARS[index] ? BARS[index].toString() : '';
|
||||
}
|
||||
|
||||
// Correct an index by a set and shift it from the bytes array
|
||||
static correctIndex(bytes, set) {
|
||||
if (set === SET_A) {
|
||||
const charCode = bytes.shift();
|
||||
return charCode < 32 ? charCode + 64 : charCode - 32;
|
||||
} else if (set === SET_B) {
|
||||
return bytes.shift() - 32;
|
||||
} else {
|
||||
return (bytes.shift() - 48) * 10 + bytes.shift() - 48;
|
||||
}
|
||||
}
|
||||
|
||||
static next(bytes, pos, set) {
|
||||
if (!bytes.length) {
|
||||
return { result: '', checksum: 0 };
|
||||
}
|
||||
|
||||
let nextCode, index;
|
||||
|
||||
// Special characters
|
||||
if (bytes[0] >= 200){
|
||||
index = bytes.shift() - 105;
|
||||
const nextSet = SWAP[index];
|
||||
|
||||
// Swap to other set
|
||||
if (nextSet !== undefined) {
|
||||
nextCode = CODE128.next(bytes, pos + 1, nextSet);
|
||||
}
|
||||
// Continue on current set but encode a special character
|
||||
else {
|
||||
// Shift
|
||||
if ((set === SET_A || set === SET_B) && index === SHIFT) {
|
||||
// Convert the next character so that is encoded correctly
|
||||
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);
|
||||
}
|
||||
}
|
||||
// Continue encoding
|
||||
else {
|
||||
index = CODE128.correctIndex(bytes, set);
|
||||
nextCode = CODE128.next(bytes, pos + 1, set);
|
||||
}
|
||||
|
||||
// Get the correct binary encoding and calculate the weight
|
||||
const enc = CODE128.getBar(index);
|
||||
const weight = index * pos;
|
||||
|
||||
return {
|
||||
result: enc + nextCode.result,
|
||||
checksum: weight + nextCode.checksum
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default CODE128;
|
||||
@@ -0,0 +1,14 @@
|
||||
import CODE128 from './CODE128.js';
|
||||
import { A_START_CHAR, A_CHARS } from './constants';
|
||||
|
||||
class CODE128A extends CODE128 {
|
||||
constructor(string, options) {
|
||||
super(A_START_CHAR + string, options);
|
||||
}
|
||||
|
||||
valid() {
|
||||
return (new RegExp(`^${A_CHARS}+$`)).test(this.data);
|
||||
}
|
||||
}
|
||||
|
||||
export default CODE128A;
|
||||
@@ -0,0 +1,14 @@
|
||||
import CODE128 from './CODE128.js';
|
||||
import { B_START_CHAR, B_CHARS } from './constants';
|
||||
|
||||
class CODE128B extends CODE128 {
|
||||
constructor(string, options) {
|
||||
super(B_START_CHAR + string, options);
|
||||
}
|
||||
|
||||
valid() {
|
||||
return (new RegExp(`^${B_CHARS}+$`)).test(this.data);
|
||||
}
|
||||
}
|
||||
|
||||
export default CODE128B;
|
||||
@@ -0,0 +1,14 @@
|
||||
import CODE128 from './CODE128.js';
|
||||
import { C_START_CHAR, C_CHARS } from './constants';
|
||||
|
||||
class CODE128C extends CODE128 {
|
||||
constructor(string, options) {
|
||||
super(C_START_CHAR + string, options);
|
||||
}
|
||||
|
||||
valid() {
|
||||
return (new RegExp(`^${C_CHARS}+$`)).test(this.data);
|
||||
}
|
||||
}
|
||||
|
||||
export default CODE128C;
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import CODE128 from './CODE128';
|
||||
import autoSelectModes from './auto';
|
||||
|
||||
class CODE128AUTO extends CODE128{
|
||||
constructor(data, options){
|
||||
// ASCII value ranges 0-127, 200-211
|
||||
if (/^[\x00-\x7F\xC8-\xD3]+$/.test(data)) {
|
||||
super(autoSelectModes(data), options);
|
||||
} else{
|
||||
super(data, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default CODE128AUTO;
|
||||
@@ -0,0 +1,68 @@
|
||||
import { A_START_CHAR, B_START_CHAR, C_START_CHAR, A_CHARS, B_CHARS, C_CHARS } from './constants';
|
||||
|
||||
// Match Set functions
|
||||
const matchSetALength = (string) => string.match(new RegExp(`^${A_CHARS}*`))[0].length;
|
||||
const matchSetBLength = (string) => string.match(new RegExp(`^${B_CHARS}*`))[0].length;
|
||||
const matchSetC = (string) => string.match(new RegExp(`^${C_CHARS}*`))[0];
|
||||
|
||||
// CODE128A or CODE128B
|
||||
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 chars = string.match(new RegExp(`^${ranges}+`))[0];
|
||||
|
||||
if (chars.length === string.length) {
|
||||
return string;
|
||||
}
|
||||
|
||||
return (
|
||||
chars +
|
||||
String.fromCharCode(isA ? 205 : 206) +
|
||||
autoSelectFromAB(string.substring(chars.length), !isA)
|
||||
);
|
||||
}
|
||||
|
||||
// CODE128C
|
||||
function autoSelectFromC(string) {
|
||||
const cMatch = matchSetC(string);
|
||||
const length = cMatch.length;
|
||||
|
||||
if (length === string.length) {
|
||||
return string;
|
||||
}
|
||||
|
||||
string = string.substring(length);
|
||||
|
||||
// Select A/B depending on the longest match
|
||||
const isA = matchSetALength(string) >= matchSetBLength(string);
|
||||
return cMatch + String.fromCharCode(isA ? 206 : 205) + autoSelectFromAB(string, isA);
|
||||
}
|
||||
|
||||
// Detect Code Set (A, B or C) and format the string
|
||||
export default (string) => {
|
||||
let newString;
|
||||
const cLength = matchSetC(string).length;
|
||||
|
||||
// Select 128C if the string start with enough digits
|
||||
if (cLength >= 2) {
|
||||
newString = C_START_CHAR + autoSelectFromC(string);
|
||||
} else {
|
||||
// Select A/B depending on the longest match
|
||||
const isA = matchSetALength(string) > matchSetBLength(string);
|
||||
newString = (isA ? A_START_CHAR : B_START_CHAR) + autoSelectFromAB(string, isA);
|
||||
}
|
||||
|
||||
return newString.replace(
|
||||
/[\xCD\xCE]([^])[\xCD\xCE]/, // Any sequence between 205 and 206 characters
|
||||
(match, char) => String.fromCharCode(203) + char
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
// constants for internal usage
|
||||
export const SET_A = 0;
|
||||
export const SET_B = 1;
|
||||
export const SET_C = 2;
|
||||
|
||||
// Special characters
|
||||
export const SHIFT = 98;
|
||||
export const START_A = 103;
|
||||
export const START_B = 104;
|
||||
export const START_C = 105;
|
||||
export const MODULO = 103;
|
||||
export const STOP = 106;
|
||||
export const FNC1 = 207;
|
||||
|
||||
// Get set by start code
|
||||
export const SET_BY_CODE = {
|
||||
[START_A]: SET_A,
|
||||
[START_B]: SET_B,
|
||||
[START_C]: SET_C,
|
||||
};
|
||||
|
||||
// Get next set by code
|
||||
export const SWAP = {
|
||||
101: SET_A,
|
||||
100: SET_B,
|
||||
99: SET_C,
|
||||
};
|
||||
|
||||
export const A_START_CHAR = String.fromCharCode(208); // START_A + 105
|
||||
export const B_START_CHAR = String.fromCharCode(209); // START_B + 105
|
||||
export const C_START_CHAR = String.fromCharCode(210); // START_C + 105
|
||||
|
||||
// 128A (Code Set A)
|
||||
// ASCII characters 00 to 95 (0–9, A–Z and control codes), special characters, and FNC 1–4
|
||||
export const A_CHARS = "[\x00-\x5F\xC8-\xCF]";
|
||||
|
||||
// 128B (Code Set B)
|
||||
// ASCII characters 32 to 127 (0–9, A–Z, a–z), special characters, and FNC 1–4
|
||||
export const B_CHARS = "[\x20-\x7F\xC8-\xCF]";
|
||||
|
||||
// 128C (Code Set C)
|
||||
// 00–99 (encodes two digits with a single code point) and FNC1
|
||||
export const C_CHARS = "(\xCF*[0-9]{2}\xCF*)";
|
||||
|
||||
// CODE128 includes 107 symbols:
|
||||
// 103 data symbols, 3 start symbols (A, B and C), and 1 stop symbol (the last one)
|
||||
// Each symbol consist of three black bars (1) and three white spaces (0).
|
||||
export const 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
|
||||
];
|
||||
@@ -0,0 +1,6 @@
|
||||
import CODE128 from './CODE128_AUTO.js';
|
||||
import CODE128A from './CODE128A.js';
|
||||
import CODE128B from './CODE128B.js';
|
||||
import CODE128C from './CODE128C.js';
|
||||
|
||||
export {CODE128, CODE128A, CODE128B, CODE128C};
|
||||
@@ -0,0 +1,105 @@
|
||||
// Encoding documentation:
|
||||
// https://en.wikipedia.org/wiki/Code_39#Encoding
|
||||
|
||||
import Barcode from "../Barcode.js";
|
||||
|
||||
class CODE39 extends Barcode {
|
||||
constructor(data, options){
|
||||
data = data.toUpperCase();
|
||||
|
||||
// Calculate mod43 checksum if enabled
|
||||
if(options.mod43){
|
||||
data += getCharacter(mod43checksum(data));
|
||||
}
|
||||
|
||||
super(data, options);
|
||||
}
|
||||
|
||||
encode(){
|
||||
// First character is always a *
|
||||
var result = getEncoding("*");
|
||||
|
||||
// Take every character and add the binary representation to the result
|
||||
for(let i = 0; i < this.data.length; i++){
|
||||
result += getEncoding(this.data[i]) + "0";
|
||||
}
|
||||
|
||||
// Last character is always a *
|
||||
result += getEncoding("*");
|
||||
|
||||
return {
|
||||
data: result,
|
||||
text: this.text
|
||||
};
|
||||
}
|
||||
|
||||
valid(){
|
||||
return this.data.search(/^[0-9A-Z\-\.\ \$\/\+\%]+$/) !== -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// All characters. The position in the array is the (checksum) value
|
||||
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",
|
||||
"-", ".", " ", "$",
|
||||
"/", "+", "%", "*"
|
||||
];
|
||||
|
||||
// The decimal representation of the characters, is converted to the
|
||||
// corresponding binary with the getEncoding function
|
||||
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
|
||||
];
|
||||
|
||||
// Get the binary representation of a character by converting the encodings
|
||||
// from decimal to binary
|
||||
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){
|
||||
var checksum = 0;
|
||||
for(let i = 0; i < data.length; i++){
|
||||
checksum += characterValue(data[i]);
|
||||
}
|
||||
|
||||
checksum = checksum % 43;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
export {CODE39};
|
||||
@@ -0,0 +1,73 @@
|
||||
// Encoding documentation:
|
||||
// https://en.wikipedia.org/wiki/Code_93#Detailed_outline
|
||||
|
||||
import { SYMBOLS, BINARIES, MULTI_SYMBOLS } from './constants';
|
||||
import Barcode from "../Barcode.js";
|
||||
|
||||
class CODE93 extends Barcode {
|
||||
constructor(data, options){
|
||||
super(data, options);
|
||||
}
|
||||
|
||||
valid(){
|
||||
return /^[0-9A-Z\-. $/+%]+$/.test(this.data);
|
||||
}
|
||||
|
||||
encode(){
|
||||
const symbols = this.data
|
||||
.split('')
|
||||
.flatMap(c => MULTI_SYMBOLS[c] || c);
|
||||
const encoded = symbols
|
||||
.map(s => CODE93.getEncoding(s))
|
||||
.join('');
|
||||
|
||||
// Compute checksum symbols
|
||||
const csumC = CODE93.checksum(symbols, 20);
|
||||
const csumK = CODE93.checksum(symbols.concat(csumC), 15);
|
||||
|
||||
return {
|
||||
text: this.text,
|
||||
data:
|
||||
// Add the start bits
|
||||
CODE93.getEncoding('\xff') +
|
||||
// Add the encoded bits
|
||||
encoded +
|
||||
// Add the checksum
|
||||
CODE93.getEncoding(csumC) + CODE93.getEncoding(csumK) +
|
||||
// Add the stop bits
|
||||
CODE93.getEncoding('\xff') +
|
||||
// Add the termination bit
|
||||
'1'
|
||||
};
|
||||
}
|
||||
|
||||
// Get the binary encoding of a symbol
|
||||
static getEncoding(symbol) {
|
||||
return BINARIES[CODE93.symbolValue(symbol)];
|
||||
}
|
||||
|
||||
// Get the symbol for a symbol value
|
||||
static getSymbol(symbolValue) {
|
||||
return SYMBOLS[symbolValue];
|
||||
}
|
||||
|
||||
// Get the symbol value of a symbol
|
||||
static symbolValue(symbol) {
|
||||
return SYMBOLS.indexOf(symbol);
|
||||
}
|
||||
|
||||
// Calculate a checksum symbol
|
||||
static checksum(symbols, maxWeight) {
|
||||
const csum = symbols
|
||||
.slice()
|
||||
.reverse()
|
||||
.reduce((sum, symbol, idx) => {
|
||||
const weight = (idx % maxWeight) + 1;
|
||||
return sum + (CODE93.symbolValue(symbol) * weight);
|
||||
}, 0);
|
||||
|
||||
return CODE93.getSymbol(csum % 47);
|
||||
}
|
||||
}
|
||||
|
||||
export default CODE93;
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// Encoding documentation
|
||||
// https://en.wikipedia.org/wiki/Code_93#Full_ASCII_Code_93
|
||||
|
||||
import CODE93 from './CODE93.js';
|
||||
|
||||
class CODE93FullASCII extends CODE93 {
|
||||
constructor(data, options) {
|
||||
super(data, options);
|
||||
}
|
||||
|
||||
valid() {
|
||||
return /^[\x00-\x7f]+$/.test(this.data);
|
||||
}
|
||||
}
|
||||
|
||||
export default CODE93FullASCII;
|
||||
@@ -0,0 +1,123 @@
|
||||
// The position in the array is the (checksum) value
|
||||
export const SYMBOLS = [
|
||||
'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',
|
||||
'-', '.', ' ', '$',
|
||||
'/', '+', '%',
|
||||
// Only used for csum and multi-symbols character encodings
|
||||
'($)', '(%)', '(/)', '(+)',
|
||||
// Start/Stop
|
||||
'\xff',
|
||||
];
|
||||
|
||||
// Order matches SYMBOLS array
|
||||
export const BINARIES = [
|
||||
'100010100', '101001000', '101000100', '101000010',
|
||||
'100101000', '100100100', '100100010', '101010000',
|
||||
'100010010', '100001010', '110101000', '110100100',
|
||||
'110100010', '110010100', '110010010', '110001010',
|
||||
'101101000', '101100100', '101100010', '100110100',
|
||||
'100011010', '101011000', '101001100', '101000110',
|
||||
'100101100', '100010110', '110110100', '110110010',
|
||||
'110101100', '110100110', '110010110', '110011010',
|
||||
'101101100', '101100110', '100110110', '100111010',
|
||||
'100101110', '111010100', '111010010', '111001010',
|
||||
'101101110', '101110110', '110101110', '100100110',
|
||||
'111011010', '111010110', '100110010', '101011110',
|
||||
];
|
||||
|
||||
// Multi-symbol characters (Full ASCII Code 93)
|
||||
export const MULTI_SYMBOLS = {
|
||||
'\x00': ['(%)', 'U'],
|
||||
'\x01': ['($)', 'A'],
|
||||
'\x02': ['($)', 'B'],
|
||||
'\x03': ['($)', 'C'],
|
||||
'\x04': ['($)', 'D'],
|
||||
'\x05': ['($)', 'E'],
|
||||
'\x06': ['($)', 'F'],
|
||||
'\x07': ['($)', 'G'],
|
||||
'\x08': ['($)', 'H'],
|
||||
'\x09': ['($)', 'I'],
|
||||
'\x0a': ['($)', 'J'],
|
||||
'\x0b': ['($)', 'K'],
|
||||
'\x0c': ['($)', 'L'],
|
||||
'\x0d': ['($)', 'M'],
|
||||
'\x0e': ['($)', 'N'],
|
||||
'\x0f': ['($)', 'O'],
|
||||
'\x10': ['($)', 'P'],
|
||||
'\x11': ['($)', 'Q'],
|
||||
'\x12': ['($)', 'R'],
|
||||
'\x13': ['($)', 'S'],
|
||||
'\x14': ['($)', 'T'],
|
||||
'\x15': ['($)', 'U'],
|
||||
'\x16': ['($)', 'V'],
|
||||
'\x17': ['($)', 'W'],
|
||||
'\x18': ['($)', 'X'],
|
||||
'\x19': ['($)', 'Y'],
|
||||
'\x1a': ['($)', 'Z'],
|
||||
'\x1b': ['(%)', 'A'],
|
||||
'\x1c': ['(%)', 'B'],
|
||||
'\x1d': ['(%)', 'C'],
|
||||
'\x1e': ['(%)', 'D'],
|
||||
'\x1f': ['(%)', 'E'],
|
||||
'!': ['(/)', 'A'],
|
||||
'"': ['(/)', 'B'],
|
||||
'#': ['(/)', 'C'],
|
||||
'&': ['(/)', 'F'],
|
||||
'\'': ['(/)', 'G'],
|
||||
'(': ['(/)', 'H'],
|
||||
')': ['(/)', 'I'],
|
||||
'*': ['(/)', 'J'],
|
||||
',': ['(/)', 'L'],
|
||||
':': ['(/)', 'Z'],
|
||||
';': ['(%)', 'F'],
|
||||
'<': ['(%)', 'G'],
|
||||
'=': ['(%)', 'H'],
|
||||
'>': ['(%)', 'I'],
|
||||
'?': ['(%)', 'J'],
|
||||
'@': ['(%)', 'V'],
|
||||
'[': ['(%)', 'K'],
|
||||
'\\': ['(%)', 'L'],
|
||||
']': ['(%)', 'M'],
|
||||
'^': ['(%)', 'N'],
|
||||
'_': ['(%)', 'O'],
|
||||
'`': ['(%)', 'W'],
|
||||
'a': ['(+)', 'A'],
|
||||
'b': ['(+)', 'B'],
|
||||
'c': ['(+)', 'C'],
|
||||
'd': ['(+)', 'D'],
|
||||
'e': ['(+)', 'E'],
|
||||
'f': ['(+)', 'F'],
|
||||
'g': ['(+)', 'G'],
|
||||
'h': ['(+)', 'H'],
|
||||
'i': ['(+)', 'I'],
|
||||
'j': ['(+)', 'J'],
|
||||
'k': ['(+)', 'K'],
|
||||
'l': ['(+)', 'L'],
|
||||
'm': ['(+)', 'M'],
|
||||
'n': ['(+)', 'N'],
|
||||
'o': ['(+)', 'O'],
|
||||
'p': ['(+)', 'P'],
|
||||
'q': ['(+)', 'Q'],
|
||||
'r': ['(+)', 'R'],
|
||||
's': ['(+)', 'S'],
|
||||
't': ['(+)', 'T'],
|
||||
'u': ['(+)', 'U'],
|
||||
'v': ['(+)', 'V'],
|
||||
'w': ['(+)', 'W'],
|
||||
'x': ['(+)', 'X'],
|
||||
'y': ['(+)', 'Y'],
|
||||
'z': ['(+)', 'Z'],
|
||||
'{': ['(%)', 'P'],
|
||||
'|': ['(%)', 'Q'],
|
||||
'}': ['(%)', 'R'],
|
||||
'~': ['(%)', 'S'],
|
||||
'\x7f': ['(%)', 'T'],
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
import CODE93 from './CODE93.js';
|
||||
import CODE93FullASCII from './CODE93FullASCII.js';
|
||||
|
||||
export {CODE93, CODE93FullASCII};
|
||||
@@ -0,0 +1,72 @@
|
||||
import { SIDE_BIN, MIDDLE_BIN } from './constants';
|
||||
import encode from './encoder';
|
||||
import Barcode from '../Barcode';
|
||||
|
||||
// Base class for EAN8 & EAN13
|
||||
class EAN extends Barcode {
|
||||
|
||||
constructor(data, options) {
|
||||
super(data, options);
|
||||
|
||||
// Make sure the font is not bigger than the space between the guard bars
|
||||
this.fontSize = !options.flat && options.fontSize > options.width * 10
|
||||
? options.width * 10
|
||||
: options.fontSize;
|
||||
|
||||
// Make the guard bars go down half the way of the text
|
||||
this.guardHeight = options.height + this.fontSize / 2 + options.textMargin;
|
||||
}
|
||||
|
||||
encode() {
|
||||
return this.options.flat
|
||||
? this.encodeFlat()
|
||||
: this.encodeGuarded();
|
||||
}
|
||||
|
||||
leftText(from, to) {
|
||||
return this.text.substr(from, to);
|
||||
}
|
||||
|
||||
leftEncode(data, structure) {
|
||||
return encode(data, structure);
|
||||
}
|
||||
|
||||
rightText(from, to) {
|
||||
return this.text.substr(from, to);
|
||||
}
|
||||
|
||||
rightEncode(data, 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
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default EAN;
|
||||
@@ -0,0 +1,90 @@
|
||||
// Encoding documentation:
|
||||
// https://en.wikipedia.org/wiki/International_Article_Number_(EAN)#Binary_encoding_of_data_digits_into_EAN-13_barcode
|
||||
|
||||
import { EAN13_STRUCTURE } from './constants';
|
||||
import EAN from './EAN';
|
||||
|
||||
// Calculate the checksum digit
|
||||
// https://en.wikipedia.org/wiki/International_Article_Number_(EAN)#Calculation_of_checksum_digit
|
||||
const checksum = (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 {
|
||||
|
||||
constructor(data, options) {
|
||||
// Add checksum if it does not exist
|
||||
if (data.search(/^[0-9]{12}$/) !== -1) {
|
||||
data += checksum(data);
|
||||
}
|
||||
|
||||
super(data, options);
|
||||
|
||||
// Adds a last character to the end of the barcode
|
||||
this.lastChar = options.lastChar;
|
||||
}
|
||||
|
||||
valid() {
|
||||
return (
|
||||
this.data.search(/^[0-9]{13}$/) !== -1 &&
|
||||
+this.data[12] === checksum(this.data)
|
||||
);
|
||||
}
|
||||
|
||||
leftText() {
|
||||
return super.leftText(1, 6);
|
||||
}
|
||||
|
||||
leftEncode() {
|
||||
const data = this.data.substr(1, 6);
|
||||
const structure = EAN13_STRUCTURE[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');
|
||||
}
|
||||
|
||||
// The "standard" way of printing EAN13 barcodes with guard bars
|
||||
encodeGuarded() {
|
||||
const data = super.encodeGuarded();
|
||||
|
||||
// Extend data with left digit & last character
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default EAN13;
|
||||
@@ -0,0 +1,30 @@
|
||||
// Encoding documentation:
|
||||
// https://en.wikipedia.org/wiki/EAN_2#Encoding
|
||||
|
||||
import { EAN2_STRUCTURE } from './constants';
|
||||
import encode from './encoder';
|
||||
import Barcode from '../Barcode';
|
||||
|
||||
class EAN2 extends Barcode {
|
||||
|
||||
constructor(data, options) {
|
||||
super(data, options);
|
||||
}
|
||||
|
||||
valid() {
|
||||
return this.data.search(/^[0-9]{2}$/) !== -1;
|
||||
}
|
||||
|
||||
encode(){
|
||||
// Choose the structure based on the number mod 4
|
||||
const structure = EAN2_STRUCTURE[parseInt(this.data) % 4];
|
||||
return {
|
||||
// Start bits + Encode the two digits with 01 in between
|
||||
data: '1011' + encode(this.data, structure, '01'),
|
||||
text: this.text
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default EAN2;
|
||||
@@ -0,0 +1,40 @@
|
||||
// Encoding documentation:
|
||||
// https://en.wikipedia.org/wiki/EAN_5#Encoding
|
||||
|
||||
import { EAN5_STRUCTURE } from './constants';
|
||||
import encode from './encoder';
|
||||
import Barcode from '../Barcode';
|
||||
|
||||
const 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 {
|
||||
|
||||
constructor(data, options) {
|
||||
super(data, options);
|
||||
}
|
||||
|
||||
valid() {
|
||||
return this.data.search(/^[0-9]{5}$/) !== -1;
|
||||
}
|
||||
|
||||
encode() {
|
||||
const structure = EAN5_STRUCTURE[checksum(this.data)];
|
||||
return {
|
||||
data: '1011' + encode(this.data, structure, '01'),
|
||||
text: this.text
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default EAN5;
|
||||
@@ -0,0 +1,57 @@
|
||||
// Encoding documentation:
|
||||
// http://www.barcodeisland.com/ean8.phtml
|
||||
|
||||
import EAN from './EAN';
|
||||
|
||||
// Calculate the checksum digit
|
||||
const checksum = (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) {
|
||||
// Add checksum if it does not exist
|
||||
if (data.search(/^[0-9]{7}$/) !== -1) {
|
||||
data += checksum(data);
|
||||
}
|
||||
|
||||
super(data, options);
|
||||
}
|
||||
|
||||
valid() {
|
||||
return (
|
||||
this.data.search(/^[0-9]{8}$/) !== -1 &&
|
||||
+this.data[7] === checksum(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');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default EAN8;
|
||||
@@ -0,0 +1,132 @@
|
||||
// Encoding documentation:
|
||||
// https://en.wikipedia.org/wiki/Universal_Product_Code#Encoding
|
||||
|
||||
import encode from './encoder';
|
||||
import Barcode from "../Barcode.js";
|
||||
|
||||
class UPC extends Barcode{
|
||||
constructor(data, options){
|
||||
// Add checksum if it does not exist
|
||||
if(data.search(/^[0-9]{11}$/) !== -1){
|
||||
data += checksum(data);
|
||||
}
|
||||
|
||||
super(data, options);
|
||||
|
||||
this.displayValue = options.displayValue;
|
||||
|
||||
// Make sure the font is not bigger than the space between the guard bars
|
||||
if(options.fontSize > options.width * 10){
|
||||
this.fontSize = options.width * 10;
|
||||
}
|
||||
else{
|
||||
this.fontSize = options.fontSize;
|
||||
}
|
||||
|
||||
// Make the guard bars go down half the way of the text
|
||||
this.guardHeight = options.height + this.fontSize / 2 + options.textMargin;
|
||||
}
|
||||
|
||||
valid(){
|
||||
return this.data.search(/^[0-9]{12}$/) !== -1 &&
|
||||
this.data[11] == checksum(this.data);
|
||||
}
|
||||
|
||||
encode(){
|
||||
if(this.options.flat){
|
||||
return this.flatEncoding();
|
||||
}
|
||||
else{
|
||||
return this.guardedEncoding();
|
||||
}
|
||||
}
|
||||
|
||||
flatEncoding(){
|
||||
var 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(){
|
||||
var result = [];
|
||||
|
||||
// Add the first digit
|
||||
if(this.displayValue){
|
||||
result.push({
|
||||
data: "00000000",
|
||||
text: this.text.substr(0, 1),
|
||||
options: {textAlign: "left", fontSize: this.fontSize}
|
||||
});
|
||||
}
|
||||
|
||||
// Add the guard bars
|
||||
result.push({
|
||||
data: "101" + encode(this.data[0], "L"),
|
||||
options: {height: this.guardHeight}
|
||||
});
|
||||
|
||||
// Add the left side
|
||||
result.push({
|
||||
data: encode(this.data.substr(1, 5), "LLLLL"),
|
||||
text: this.text.substr(1, 5),
|
||||
options: {fontSize: this.fontSize}
|
||||
});
|
||||
|
||||
// Add the middle bits
|
||||
result.push({
|
||||
data: "01010",
|
||||
options: {height: this.guardHeight}
|
||||
});
|
||||
|
||||
// Add the right side
|
||||
result.push({
|
||||
data: encode(this.data.substr(6, 5), "RRRRR"),
|
||||
text: this.text.substr(6, 5),
|
||||
options: {fontSize: this.fontSize}
|
||||
});
|
||||
|
||||
// Add the end bits
|
||||
result.push({
|
||||
data: encode(this.data[11], "R") + "101",
|
||||
options: {height: this.guardHeight}
|
||||
});
|
||||
|
||||
// Add the last digit
|
||||
if(this.displayValue){
|
||||
result.push({
|
||||
data: "00000000",
|
||||
text: this.text.substr(11, 1),
|
||||
options: {textAlign: "right", fontSize: this.fontSize}
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Calulate the checksum digit
|
||||
// https://en.wikipedia.org/wiki/International_Article_Number_(EAN)#Calculation_of_checksum_digit
|
||||
export function checksum(number){
|
||||
var result = 0;
|
||||
|
||||
var i;
|
||||
for(i = 1; i < 11; i += 2){
|
||||
result += parseInt(number[i]);
|
||||
}
|
||||
for(i = 0; i < 11; i += 2){
|
||||
result += parseInt(number[i]) * 3;
|
||||
}
|
||||
|
||||
return (10 - (result % 10)) % 10;
|
||||
}
|
||||
|
||||
export default UPC;
|
||||
@@ -0,0 +1,177 @@
|
||||
// Encoding documentation:
|
||||
// https://en.wikipedia.org/wiki/Universal_Product_Code#Encoding
|
||||
//
|
||||
// UPC-E documentation:
|
||||
// https://en.wikipedia.org/wiki/Universal_Product_Code#UPC-E
|
||||
|
||||
import encode from './encoder';
|
||||
import Barcode from "../Barcode.js";
|
||||
import { checksum } from './UPC.js';
|
||||
|
||||
const EXPANSIONS = [
|
||||
"XX00000XXX",
|
||||
"XX10000XXX",
|
||||
"XX20000XXX",
|
||||
"XXX00000XX",
|
||||
"XXXX00000X",
|
||||
"XXXXX00005",
|
||||
"XXXXX00006",
|
||||
"XXXXX00007",
|
||||
"XXXXX00008",
|
||||
"XXXXX00009"
|
||||
];
|
||||
|
||||
const 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{
|
||||
constructor(data, options){
|
||||
// Code may be 6 or 8 digits;
|
||||
// A 7 digit code is ambiguous as to whether the extra digit
|
||||
// is a UPC-A check or number system digit.
|
||||
super(data, options);
|
||||
this.isValid = false;
|
||||
if(data.search(/^[0-9]{6}$/) !== -1){
|
||||
this.middleDigits = data;
|
||||
this.upcA = expandToUPCA(data, "0");
|
||||
this.text = options.text ||
|
||||
`${this.upcA[0]}${data}${this.upcA[this.upcA.length - 1]}`;
|
||||
this.isValid = true;
|
||||
}
|
||||
else if(data.search(/^[01][0-9]{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{
|
||||
// checksum mismatch
|
||||
return;
|
||||
}
|
||||
}
|
||||
else{
|
||||
return;
|
||||
}
|
||||
|
||||
this.displayValue = options.displayValue;
|
||||
|
||||
// Make sure the font is not bigger than the space between the guard bars
|
||||
if(options.fontSize > options.width * 10){
|
||||
this.fontSize = options.width * 10;
|
||||
}
|
||||
else{
|
||||
this.fontSize = options.fontSize;
|
||||
}
|
||||
|
||||
// Make the guard bars go down half the way of the text
|
||||
this.guardHeight = options.height + this.fontSize / 2 + options.textMargin;
|
||||
}
|
||||
|
||||
valid(){
|
||||
return this.isValid;
|
||||
}
|
||||
|
||||
encode(){
|
||||
if(this.options.flat){
|
||||
return this.flatEncoding();
|
||||
}
|
||||
else{
|
||||
return this.guardedEncoding();
|
||||
}
|
||||
}
|
||||
|
||||
flatEncoding(){
|
||||
var result = "";
|
||||
|
||||
result += "101";
|
||||
result += this.encodeMiddleDigits();
|
||||
result += "010101";
|
||||
|
||||
return {
|
||||
data: result,
|
||||
text: this.text
|
||||
};
|
||||
}
|
||||
|
||||
guardedEncoding(){
|
||||
var result = [];
|
||||
|
||||
// Add the UPC-A number system digit beneath the quiet zone
|
||||
if(this.displayValue){
|
||||
result.push({
|
||||
data: "00000000",
|
||||
text: this.text[0],
|
||||
options: {textAlign: "left", fontSize: this.fontSize}
|
||||
});
|
||||
}
|
||||
|
||||
// Add the guard bars
|
||||
result.push({
|
||||
data: "101",
|
||||
options: {height: this.guardHeight}
|
||||
});
|
||||
|
||||
// Add the 6 UPC-E digits
|
||||
result.push({
|
||||
data: this.encodeMiddleDigits(),
|
||||
text: this.text.substring(1, 7),
|
||||
options: {fontSize: this.fontSize}
|
||||
});
|
||||
|
||||
// Add the end bits
|
||||
result.push({
|
||||
data: "010101",
|
||||
options: {height: this.guardHeight}
|
||||
});
|
||||
|
||||
// Add the UPC-A check digit beneath the quiet zone
|
||||
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[parseInt(checkDigit)][parseInt(numberSystem)];
|
||||
return encode(this.middleDigits, parity);
|
||||
}
|
||||
}
|
||||
|
||||
function expandToUPCA(middleDigits, numberSystem) {
|
||||
const lastUpcE = parseInt(middleDigits[middleDigits.length - 1]);
|
||||
const expansion = EXPANSIONS[lastUpcE];
|
||||
|
||||
let result = "";
|
||||
let digitIndex = 0;
|
||||
for(let i = 0; i < expansion.length; i++) {
|
||||
let c = expansion[i];
|
||||
if (c === 'X') {
|
||||
result += middleDigits[digitIndex++];
|
||||
} else {
|
||||
result += c;
|
||||
}
|
||||
}
|
||||
|
||||
result = `${numberSystem}${result}`;
|
||||
return `${result}${checksum(result)}`;
|
||||
}
|
||||
|
||||
export default UPCE;
|
||||
@@ -0,0 +1,41 @@
|
||||
// Standard start end and middle bits
|
||||
export const SIDE_BIN = '101';
|
||||
export const MIDDLE_BIN = '01010';
|
||||
|
||||
export const BINARIES = {
|
||||
'L': [ // The L (left) type of encoding
|
||||
'0001101', '0011001', '0010011', '0111101', '0100011',
|
||||
'0110001', '0101111', '0111011', '0110111', '0001011'
|
||||
],
|
||||
'G': [ // The G type of encoding
|
||||
'0100111', '0110011', '0011011', '0100001', '0011101',
|
||||
'0111001', '0000101', '0010001', '0001001', '0010111'
|
||||
],
|
||||
'R': [ // The R (right) type of encoding
|
||||
'1110010', '1100110', '1101100', '1000010', '1011100',
|
||||
'1001110', '1010000', '1000100', '1001000', '1110100'
|
||||
],
|
||||
'O': [ // The O (odd) encoding for UPC-E
|
||||
'0001101', '0011001', '0010011', '0111101', '0100011',
|
||||
'0110001', '0101111', '0111011', '0110111', '0001011'
|
||||
],
|
||||
'E': [ // The E (even) encoding for UPC-E
|
||||
'0100111', '0110011', '0011011', '0100001', '0011101',
|
||||
'0111001', '0000101', '0010001', '0001001', '0010111'
|
||||
]
|
||||
};
|
||||
|
||||
// Define the EAN-2 structure
|
||||
export const EAN2_STRUCTURE = ['LL', 'LG', 'GL', 'GG'];
|
||||
|
||||
// Define the EAN-5 structure
|
||||
export const EAN5_STRUCTURE = [
|
||||
'GGLLL', 'GLGLL', 'GLLGL', 'GLLLG', 'LGGLL',
|
||||
'LLGGL', 'LLLGG', 'LGLGL', 'LGLLG', 'LLGLG'
|
||||
];
|
||||
|
||||
// Define the EAN-13 structure
|
||||
export const EAN13_STRUCTURE = [
|
||||
'LLLLLL', 'LLGLGG', 'LLGGLG', 'LLGGGL', 'LGLLGG',
|
||||
'LGGLLG', 'LGGGLL', 'LGLGLG', 'LGLGGL', 'LGGLGL'
|
||||
];
|
||||
@@ -0,0 +1,20 @@
|
||||
import { BINARIES } from './constants';
|
||||
|
||||
// Encode data string
|
||||
const 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('');
|
||||
};
|
||||
|
||||
export default encode;
|
||||
@@ -0,0 +1,8 @@
|
||||
import EAN13 from './EAN13.js';
|
||||
import EAN8 from './EAN8.js';
|
||||
import EAN5 from './EAN5.js';
|
||||
import EAN2 from './EAN2.js';
|
||||
import UPC from './UPC.js';
|
||||
import UPCE from './UPCE.js';
|
||||
|
||||
export {EAN13, EAN8, EAN5, EAN2, UPC, UPCE};
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import Barcode from "../Barcode.js";
|
||||
|
||||
class GenericBarcode extends Barcode{
|
||||
constructor(data, options){
|
||||
super(data, options); // Sets this.data and this.text
|
||||
}
|
||||
|
||||
// Return the corresponding binary numbers for the data provided
|
||||
encode(){
|
||||
return {
|
||||
data: "10101010101010101010101010101010101010101",
|
||||
text: this.text
|
||||
};
|
||||
}
|
||||
|
||||
// Resturn true/false if the string provided is valid for this encoder
|
||||
valid(){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export {GenericBarcode};
|
||||
@@ -0,0 +1,37 @@
|
||||
import { START_BIN, END_BIN, BINARIES } from './constants';
|
||||
import Barcode from '../Barcode';
|
||||
|
||||
class ITF extends Barcode {
|
||||
|
||||
valid() {
|
||||
return this.data.search(/^([0-9]{2})+$/) !== -1;
|
||||
}
|
||||
|
||||
encode() {
|
||||
// Calculate all the digit pairs
|
||||
const encoded = this.data
|
||||
.match(/.{2}/g)
|
||||
.map(pair => this.encodePair(pair))
|
||||
.join('');
|
||||
|
||||
return {
|
||||
data: START_BIN + encoded + END_BIN,
|
||||
text: this.text
|
||||
};
|
||||
}
|
||||
|
||||
// Calculate the data of a number pair
|
||||
encodePair(pair) {
|
||||
const second = BINARIES[pair[1]];
|
||||
|
||||
return BINARIES[pair[0]]
|
||||
.split('')
|
||||
.map((first, idx) => (
|
||||
(first === '1' ? '111' : '1') +
|
||||
(second[idx] === '1' ? '000' : '0')
|
||||
))
|
||||
.join('');
|
||||
}
|
||||
}
|
||||
|
||||
export default ITF;
|
||||
@@ -0,0 +1,33 @@
|
||||
import ITF from './ITF';
|
||||
|
||||
// Calculate the checksum digit
|
||||
const checksum = (data) => {
|
||||
const res = data
|
||||
.substr(0, 13)
|
||||
.split('')
|
||||
.map(num => 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 {
|
||||
|
||||
constructor(data, options) {
|
||||
// Add checksum if it does not exist
|
||||
if (data.search(/^[0-9]{13}$/) !== -1) {
|
||||
data += checksum(data);
|
||||
}
|
||||
super(data, options);
|
||||
}
|
||||
|
||||
valid() {
|
||||
return (
|
||||
this.data.search(/^[0-9]{14}$/) !== -1 &&
|
||||
+this.data[13] === checksum(this.data)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ITF14;
|
||||
@@ -0,0 +1,7 @@
|
||||
export const START_BIN = '1010';
|
||||
export const END_BIN = '11101';
|
||||
|
||||
export const BINARIES = [
|
||||
'00110', '10001', '01001', '11000', '00101',
|
||||
'10100', '01100', '00011', '10010', '01010',
|
||||
];
|
||||
@@ -0,0 +1,4 @@
|
||||
import ITF from './ITF';
|
||||
import ITF14 from './ITF14';
|
||||
|
||||
export { ITF, ITF14 };
|
||||
@@ -0,0 +1,48 @@
|
||||
// Encoding documentation
|
||||
// https://en.wikipedia.org/wiki/MSI_Barcode#Character_set_and_binary_lookup
|
||||
|
||||
import Barcode from "../Barcode.js";
|
||||
|
||||
class MSI extends Barcode{
|
||||
constructor(data, options){
|
||||
super(data, options);
|
||||
}
|
||||
|
||||
encode(){
|
||||
// Start bits
|
||||
var ret = "110";
|
||||
|
||||
for(var i = 0; i < this.data.length; i++){
|
||||
// Convert the character to binary (always 4 binary digits)
|
||||
var digit = parseInt(this.data[i]);
|
||||
var bin = digit.toString(2);
|
||||
bin = addZeroes(bin, 4 - bin.length);
|
||||
|
||||
// Add 100 for every zero and 110 for every 1
|
||||
for(var b = 0; b < bin.length; b++){
|
||||
ret += bin[b] == "0" ? "100" : "110";
|
||||
}
|
||||
}
|
||||
|
||||
// End bits
|
||||
ret += "1001";
|
||||
|
||||
return {
|
||||
data: ret,
|
||||
text: this.text
|
||||
};
|
||||
}
|
||||
|
||||
valid(){
|
||||
return this.data.search(/^[0-9]+$/) !== -1;
|
||||
}
|
||||
}
|
||||
|
||||
function addZeroes(number, n){
|
||||
for(var i = 0; i < n; i++){
|
||||
number = "0" + number;
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
export default MSI;
|
||||
@@ -0,0 +1,10 @@
|
||||
import MSI from './MSI.js';
|
||||
import {mod10} from './checksums.js';
|
||||
|
||||
class MSI10 extends MSI{
|
||||
constructor(data, options){
|
||||
super(data + mod10(data), options);
|
||||
}
|
||||
}
|
||||
|
||||
export default MSI10;
|
||||
@@ -0,0 +1,12 @@
|
||||
import MSI from './MSI.js';
|
||||
import {mod10} from './checksums.js';
|
||||
|
||||
class MSI1010 extends MSI{
|
||||
constructor(data, options){
|
||||
data += mod10(data);
|
||||
data += mod10(data);
|
||||
super(data, options);
|
||||
}
|
||||
}
|
||||
|
||||
export default MSI1010;
|
||||
@@ -0,0 +1,10 @@
|
||||
import MSI from './MSI.js';
|
||||
import {mod11} from './checksums.js';
|
||||
|
||||
class MSI11 extends MSI{
|
||||
constructor(data, options){
|
||||
super(data + mod11(data), options);
|
||||
}
|
||||
}
|
||||
|
||||
export default MSI11;
|
||||
@@ -0,0 +1,12 @@
|
||||
import MSI from './MSI.js';
|
||||
import {mod10, mod11} from './checksums.js';
|
||||
|
||||
class MSI1110 extends MSI{
|
||||
constructor(data, options){
|
||||
data += mod11(data);
|
||||
data += mod10(data);
|
||||
super(data, options);
|
||||
}
|
||||
}
|
||||
|
||||
export default MSI1110;
|
||||
@@ -0,0 +1,23 @@
|
||||
export function mod10(number){
|
||||
var sum = 0;
|
||||
for(var i = 0; i < number.length; i++){
|
||||
var n = 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;
|
||||
}
|
||||
|
||||
export function mod11(number){
|
||||
var sum = 0;
|
||||
var weights = [2, 3, 4, 5, 6, 7];
|
||||
for(var i = 0; i < number.length; i++){
|
||||
var n = parseInt(number[number.length - 1 - i]);
|
||||
sum += weights[i % weights.length] * n;
|
||||
}
|
||||
return (11 - (sum % 11)) % 11;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import MSI from './MSI.js';
|
||||
import MSI10 from './MSI10.js';
|
||||
import MSI11 from './MSI11.js';
|
||||
import MSI1010 from './MSI1010.js';
|
||||
import MSI1110 from './MSI1110.js';
|
||||
|
||||
export {MSI, MSI10, MSI11, MSI1010, MSI1110};
|
||||
@@ -0,0 +1,63 @@
|
||||
// Encoding specification:
|
||||
// http://www.barcodeisland.com/codabar.phtml
|
||||
|
||||
import Barcode from "../Barcode.js";
|
||||
|
||||
class codabar extends Barcode{
|
||||
constructor(data, options){
|
||||
if (data.search(/^[0-9\-\$\:\.\+\/]+$/) === 0) {
|
||||
data = "A" + data + "A";
|
||||
}
|
||||
|
||||
super(data.toUpperCase(), options);
|
||||
|
||||
this.text = this.options.text || this.text.replace(/[A-D]/g, '');
|
||||
}
|
||||
|
||||
valid(){
|
||||
return this.data.search(/^[A-D][0-9\-\$\:\.\+\/]+[A-D]$/) !== -1;
|
||||
}
|
||||
|
||||
encode(){
|
||||
var result = [];
|
||||
var encodings = this.getEncodings();
|
||||
for(var i = 0; i < this.data.length; i++){
|
||||
result.push(encodings[this.data.charAt(i)]);
|
||||
// for all characters except the last, append a narrow-space ("0")
|
||||
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"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {codabar};
|
||||
@@ -0,0 +1,22 @@
|
||||
import {CODE39} from './CODE39/';
|
||||
import {CODE128, CODE128A, CODE128B, CODE128C} from './CODE128/';
|
||||
import {EAN13, EAN8, EAN5, EAN2, UPC, UPCE} from './EAN_UPC/';
|
||||
import {ITF, ITF14} from './ITF/';
|
||||
import {MSI, MSI10, MSI11, MSI1010, MSI1110} from './MSI/';
|
||||
import {pharmacode} from './pharmacode/';
|
||||
import {codabar} from './codabar';
|
||||
import {CODE93, CODE93FullASCII} from './CODE93/';
|
||||
import {GenericBarcode} from './GenericBarcode/';
|
||||
|
||||
export default {
|
||||
CODE39,
|
||||
CODE128, CODE128A, CODE128B, CODE128C,
|
||||
EAN13, EAN8, EAN5, EAN2, UPC, UPCE,
|
||||
ITF14,
|
||||
ITF,
|
||||
MSI, MSI10, MSI11, MSI1010, MSI1110,
|
||||
pharmacode,
|
||||
codabar,
|
||||
CODE93, CODE93FullASCII,
|
||||
GenericBarcode
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
// Encoding documentation
|
||||
// http://www.gomaro.ch/ftproot/Laetus_PHARMA-CODE.pdf
|
||||
|
||||
import Barcode from "../Barcode.js";
|
||||
|
||||
class pharmacode extends Barcode{
|
||||
constructor(data, options){
|
||||
super(data, options);
|
||||
this.number = parseInt(data, 10);
|
||||
}
|
||||
|
||||
encode(){
|
||||
var z = this.number;
|
||||
var result = "";
|
||||
|
||||
// http://i.imgur.com/RMm4UDJ.png
|
||||
// (source: http://www.gomaro.ch/ftproot/Laetus_PHARMA-CODE.pdf, page: 34)
|
||||
while(!isNaN(z) && z != 0){
|
||||
if(z % 2 === 0){ // Even
|
||||
result = "11100" + result;
|
||||
z = (z - 2) / 2;
|
||||
}
|
||||
else{ // Odd
|
||||
result = "100" + result;
|
||||
z = (z - 1) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the two last zeroes
|
||||
result = result.slice(0, -2);
|
||||
|
||||
return {
|
||||
data: result,
|
||||
text: this.text
|
||||
};
|
||||
}
|
||||
|
||||
valid(){
|
||||
return this.number >= 3 && this.number <= 131070;
|
||||
}
|
||||
}
|
||||
|
||||
export {pharmacode};
|
||||
Reference in New Issue
Block a user