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;
|