Skip to content

Commit ce67387

Browse files
author
Xelio Cheong
committed
For Xprinter brand printer
- Add printer model "xprinter" - Add util function to print CODE128 barcode on Xprinter - Add util function to optimize CODE128 barcode length
1 parent 46b687f commit ce67387

File tree

3 files changed

+140
-4
lines changed

3 files changed

+140
-4
lines changed

packages/core/src/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export interface PrinterOptions {
2525
width?: number | undefined
2626
}
2727

28-
export type PrinterModel = null | "qsprinter";
28+
export type PrinterModel = null | "qsprinter" | "xprinter";
2929

3030
/**
3131
* 'dhdw', 'dwh' and 'dhw' are treated as 'dwdh'
@@ -642,7 +642,13 @@ export class Printer<AdapterCloseArgs extends []> extends EventEmitter {
642642
if (type === "CODE128" || type === "CODE93")
643643
codeLength = utils.codeLength(convertCode);
644644

645-
this.buffer.write(`${codeLength + convertCode + (options.includeParity ? parityBit : "")}\x00`); // Allow to skip the parity byte
645+
if ((this._model === "xprinter") && type === "CODE128") {
646+
const code128Data = utils.genCode128forXprinter(convertCode);
647+
this.buffer.write(code128Data);
648+
} else {
649+
this.buffer.write(`${codeLength + convertCode + (options.includeParity ? parityBit : "")}\x00`); // Allow to skip the parity byte
650+
}
651+
646652
if (this._model === "qsprinter")
647653
this.buffer.write(_.MODEL.QSPRINTER.BARCODE_MODE.OFF);
648654

packages/core/src/utils.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,56 @@ export function intLowHighHex(input: number, length: number = 1): string {
6363
input = Math.floor(input / 256);
6464
}
6565
return ret;
66-
}
66+
}
67+
68+
const SPLIT_REGEX = /(^(?:\d\d){2,})|((?<=\D)(?:(?:\d\d){3,})(?=\d?\D))|((?:\d\d){2,}$)/;
69+
// /(--beginning--)|--------(------middle--)----------|(-----end-----)/
70+
/**
71+
* Helper function for barcode type CODE128, split string into blocks to optimize barcode length
72+
* Refer to following Wikipedia page
73+
* https://en.wikipedia.org/wiki/Code_128#Barcode_length_optimization_by_Code_128_Type-C
74+
* @param {[string]} input
75+
* @returns {[string[]]} blocks of string for optimized CODE128 barcode length
76+
*/
77+
export function splitForCode128(str: string): string[] {
78+
// No need to match REGEX for short string
79+
if(str.length <= 4)
80+
return [str];
81+
82+
// Find 4+ consecutive and even number of digits at the beginning or end
83+
// Find 6+ consecutive and even number of digits at the middle
84+
//
85+
// "12345ABC2345678BCD3456789CDE98765" =>
86+
// ["1234","5ABC","234567","8BCD","345678","9CDE9","8765"]
87+
return str.split(SPLIT_REGEX).filter(s => s !== "" && s !== undefined);
88+
}
89+
90+
const USE_CODEC_REGEX = /^((?:\d\d){1,})$/;
91+
/**
92+
* Generate control code to print CODE128 on Xprinter brand printer
93+
* Barcode length is optimized
94+
* Documentation (Chinese only):
95+
* https://www.xprinter.net/companyfile/1/
96+
* @param {[string]} input
97+
* @returns {[string]} control code for printing
98+
*/
99+
export function genCode128forXprinter(barcode:string): string {
100+
const toCodeC = (s:string) =>
101+
"{C" + s.match(/\d{2}/g) // split every 2 digit
102+
?.map(num => String.fromCharCode(Number(num)))
103+
?.join('');
104+
105+
const toCodeB = (s:string) => "{B" + s.replace('{','{{');
106+
107+
const blocks = splitForCode128(barcode)
108+
const dataPart = blocks.map(block => USE_CODEC_REGEX.test(block) ? toCodeC(block) : toCodeB(block))
109+
.join('');
110+
const dataLength = dataPart.length;
111+
112+
if (dataLength > 255)
113+
throw new Error("Barcode data is too long");
114+
115+
return String.fromCharCode(dataLength) + dataPart;
116+
}
117+
118+

packages/core/test/index.test.ts

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,85 @@
11
import { describe, expect, it } from 'vitest'
2+
import { splitForCode128, genCode128forXprinter } from '../src/utils';
23

34
describe('should', () => {
45
it('exported', () => {
56
expect(1).toEqual(1)
6-
})
7+
});
8+
9+
it('Split string to optimized blocks for CODE128 barcode', () => {
10+
const inputs: string[] = [];
11+
const expected: string[][] = [];
12+
13+
inputs.push("12");
14+
expected.push(["12"]);
15+
16+
inputs.push("123");
17+
expected.push(["123"]);
18+
19+
inputs.push("1234");
20+
expected.push(["1234"]);
21+
22+
inputs.push("12345");
23+
expected.push(["1234", '5']);
24+
25+
inputs.push("123456789");
26+
expected.push(["12345678","9"]);
27+
28+
inputs.push("123A4567C");
29+
expected.push(["123A4567C"]);
30+
31+
inputs.push("1234A4567C");
32+
expected.push(["1234","A4567C"]);
33+
34+
inputs.push("AAA1234");
35+
expected.push(["AAA","1234"]);
36+
37+
inputs.push("AAA12345");
38+
expected.push(["AAA1","2345"]);
39+
40+
inputs.push("4321AAA1234");
41+
expected.push(["4321","AAA","1234"]);
42+
43+
inputs.push("AAA123456BBB");
44+
expected.push(["AAA","123456","BBB"]);
45+
46+
inputs.push("12345ABC2345678BCD3456789CDE98765");
47+
expected.push(["1234","5ABC","234567","8BCD","345678","9CDE9","8765"]);
48+
49+
inputs.forEach((input,index) => {
50+
expect(splitForCode128(input)).toEqual(expected[index]);
51+
});
52+
});
53+
54+
it('generate CODE128 barcode printing control code for Xprinter', () => {
55+
const inputs: string[] = [];
56+
const expected: string[] = [];
57+
58+
inputs.push("AB");
59+
expected.push("\x04{BAB");
60+
61+
inputs.push("12");
62+
expected.push("\x03{C\x0c");
63+
64+
inputs.push("123456789");
65+
expected.push("\x09{C\x0c\x22\x38\x4e{B9");
66+
67+
inputs.push("1234ABC");
68+
expected.push("\x09{C\x0c\x22{BABC");
69+
70+
inputs.push("ABC1234");
71+
expected.push("\x09{BABC{C\x0c\x22");
72+
73+
inputs.push("AAA123456BBB");
74+
expected.push("\x0f{BAAA{C\x0c\x22\x38{BBBB");
75+
76+
inputs.push("12345ABC2345678BCD3456789CDE98765");
77+
expected.push("\x25{C\x0c\x22{B5ABC{C\x17\x2d\x43{B8BCD{C\x22\x38\x4e{B9CDE9{C\x57\x41");
78+
79+
inputs.forEach((input,index) => {
80+
expect(genCode128forXprinter(input)).toEqual(expected[index]);
81+
});
82+
83+
});
784
})
85+

0 commit comments

Comments
 (0)