Skip to content

Commit b867857

Browse files
authored
V2.0.2: ASCII strikes again (#67)
Turns out TextEncoder and TextDecoder both will end up generating invalid ASCII text on a round-trip. The v2 rewrite made EPL image commands round-trip back through a string, which introduced opportunities for non-ASCII characters to sneak in undetected. This moves completely to homegrown encoder/decoder functions everywhere and adds explicit 1:1 tests for all 256 ASCII characters because I am so done playing this game.
1 parent b6eb29f commit b867857

13 files changed

Lines changed: 7112 additions & 44 deletions

demo/advanced.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,11 +338,11 @@ <h4>${titleHtml}</h4>
338338
const form = formElement.elements as ConfigModalForm;
339339

340340
// Only show ZPL settings if the printer language is ZPL.
341-
for (const e of formElement.getElementsByTagName('modal-setting-zpl')) {
341+
for (const e of formElement.querySelectorAll('.modal-setting-zpl')) {
342342
if (isZpl) {
343-
e.classList.remove('d-hide');
343+
e.classList.remove('d-none');
344344
} else {
345-
e.classList.add('d-hide');
345+
e.classList.add('d-none');
346346
}
347347
}
348348

@@ -994,7 +994,7 @@ <h5>Printer Settings</h5>
994994
</div>
995995
</div>
996996
</div>
997-
<div class="mb-3 modal-settings-zpl">
997+
<div class="mb-3 modal-setting-zpl">
998998
<hr/>
999999
<div class="row">
10001000
<div class="col-md-7">

demo/editor.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,11 +304,11 @@ <h4>${titleHtml}</h4>
304304
const form = formElement.elements as ConfigModalForm;
305305

306306
// Only show ZPL settings if the printer language is ZPL.
307-
for (const e of formElement.getElementsByTagName('modal-setting-zpl')) {
307+
for (const e of formElement.querySelectorAll('.modal-setting-zpl')) {
308308
if (isZpl) {
309-
e.classList.remove('d-hide');
309+
e.classList.remove('d-none');
310310
} else {
311-
e.classList.add('d-hide');
311+
e.classList.add('d-none');
312312
}
313313
}
314314

@@ -907,7 +907,7 @@ <h5>Printer Settings</h5>
907907
</div>
908908
</div>
909909
</div>
910-
<div class="mb-3 modal-settings-zpl">
910+
<div class="mb-3 modal-setting-zpl">
911911
<hr/>
912912
<div class="row">
913913
<div class="col-md-7">

demo/test_advanced.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,11 @@ class BasicLabelDesignerApp {
269269
const form = formElement.elements as ConfigModalForm;
270270

271271
// Only show ZPL settings if the printer language is ZPL.
272-
for (const e of formElement.getElementsByTagName('modal-setting-zpl')) {
272+
for (const e of formElement.querySelectorAll('.modal-setting-zpl')) {
273273
if (isZpl) {
274-
e.classList.remove('d-hide');
274+
e.classList.remove('d-none');
275275
} else {
276-
e.classList.add('d-hide');
276+
e.classList.add('d-none');
277277
}
278278
}
279279

demo/test_editor.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,11 +240,11 @@ class BasicLabelDesignerApp {
240240
const form = formElement.elements as ConfigModalForm;
241241

242242
// Only show ZPL settings if the printer language is ZPL.
243-
for (const e of formElement.getElementsByTagName('modal-setting-zpl')) {
243+
for (const e of formElement.querySelectorAll('.modal-setting-zpl')) {
244244
if (isZpl) {
245-
e.classList.remove('d-hide');
245+
e.classList.remove('d-none');
246246
} else {
247-
e.classList.add('d-hide');
247+
e.classList.add('d-none');
248248
}
249249
}
250250

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "webzlp",
3-
"version": "2.0.1",
3+
"version": "2.0.2",
44
"description": "A small library using WebUSB to print labels on label printers.",
55
"type": "module",
66
"repository": {

src/Commands/Messages.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export class StringMessageTransformer implements MessageTransformer<string> {
5959

6060
export function asUint8Array(commands: Conf.MessageArrayLike): Uint8Array {
6161
if (typeof commands === "string") {
62-
return new TextEncoder().encode(commands);
62+
return Util.EncodeAscii(commands);
6363
} else if (commands instanceof Uint8Array) {
6464
return commands;
6565
} else {

src/Languages/Epl/BasicCommands.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,7 @@ export function addImageCommand(
246246
// EPL only supports raw binary, get that.
247247
const bitmap = cmd.bitmap;
248248
const rawBitmap = bitmap.toBinaryGRF();
249-
const decoder = new TextDecoder("ascii");
250-
const buffer = decoder.decode(rawBitmap);
249+
const buffer = Util.DecodeAscii(rawBitmap);
251250

252251
// Add the text command prefix to the buffer data
253252
const parameters = [

src/Util/ASCII.test.ts

Lines changed: 268 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,265 @@
11
import { expect, describe, it } from 'vitest';
22
import { asciiToDisplay, DecodeAscii, EncodeAscii, hex } from './ASCII.js';
33

4+
const asciiTable = [
5+
[0, '\x00'],
6+
[1, '\x01'],
7+
[2, '\x02'],
8+
[3, '\x03'],
9+
[4, '\x04'],
10+
[5, '\x05'],
11+
[6, '\x06'],
12+
[7, '\x07'],
13+
[8, '\x08'],
14+
[9, '\x09'],
15+
[10, '\x0A'],
16+
[11, '\x0B'],
17+
[12, '\x0C'],
18+
[13, '\x0D'],
19+
[14, '\x0E'],
20+
[15, '\x0F'],
21+
[16, '\x10'],
22+
[17, '\x11'],
23+
[18, '\x12'],
24+
[19, '\x13'],
25+
[20, '\x14'],
26+
[21, '\x15'],
27+
[22, '\x16'],
28+
[23, '\x17'],
29+
[24, '\x18'],
30+
[25, '\x19'],
31+
[26, '\x1A'],
32+
[27, '\x1B'],
33+
[28, '\x1C'],
34+
[29, '\x1D'],
35+
[30, '\x1E'],
36+
[31, '\x1F'],
37+
[32, '\x20'],
38+
[33, '\x21'],
39+
[34, '\x22'],
40+
[35, '\x23'],
41+
[36, '\x24'],
42+
[37, '\x25'],
43+
[38, '\x26'],
44+
[39, '\x27'],
45+
[40, '\x28'],
46+
[41, '\x29'],
47+
[42, '\x2A'],
48+
[43, '\x2B'],
49+
[44, '\x2C'],
50+
[45, '\x2D'],
51+
[46, '\x2E'],
52+
[47, '\x2F'],
53+
[48, '\x30'],
54+
[49, '\x31'],
55+
[50, '\x32'],
56+
[51, '\x33'],
57+
[52, '\x34'],
58+
[53, '\x35'],
59+
[54, '\x36'],
60+
[55, '\x37'],
61+
[56, '\x38'],
62+
[57, '\x39'],
63+
[58, '\x3A'],
64+
[59, '\x3B'],
65+
[60, '\x3C'],
66+
[61, '\x3D'],
67+
[62, '\x3E'],
68+
[63, '\x3F'],
69+
[64, '\x40'],
70+
[65, '\x41'],
71+
[66, '\x42'],
72+
[67, '\x43'],
73+
[68, '\x44'],
74+
[69, '\x45'],
75+
[70, '\x46'],
76+
[71, '\x47'],
77+
[72, '\x48'],
78+
[73, '\x49'],
79+
[74, '\x4A'],
80+
[75, '\x4B'],
81+
[76, '\x4C'],
82+
[77, '\x4D'],
83+
[78, '\x4E'],
84+
[79, '\x4F'],
85+
[80, '\x50'],
86+
[81, '\x51'],
87+
[82, '\x52'],
88+
[83, '\x53'],
89+
[84, '\x54'],
90+
[85, '\x55'],
91+
[86, '\x56'],
92+
[87, '\x57'],
93+
[88, '\x58'],
94+
[89, '\x59'],
95+
[90, '\x5A'],
96+
[91, '\x5B'],
97+
[92, '\x5C'],
98+
[93, '\x5D'],
99+
[94, '\x5E'],
100+
[95, '\x5F'],
101+
[96, '\x60'],
102+
[97, '\x61'],
103+
[98, '\x62'],
104+
[99, '\x63'],
105+
[100, '\x64'],
106+
[101, '\x65'],
107+
[102, '\x66'],
108+
[103, '\x67'],
109+
[104, '\x68'],
110+
[105, '\x69'],
111+
[106, '\x6A'],
112+
[107, '\x6B'],
113+
[108, '\x6C'],
114+
[109, '\x6D'],
115+
[110, '\x6E'],
116+
[111, '\x6F'],
117+
[112, '\x70'],
118+
[113, '\x71'],
119+
[114, '\x72'],
120+
[115, '\x73'],
121+
[116, '\x74'],
122+
[117, '\x75'],
123+
[118, '\x76'],
124+
[119, '\x77'],
125+
[120, '\x78'],
126+
[121, '\x79'],
127+
[122, '\x7A'],
128+
[123, '\x7B'],
129+
[124, '\x7C'],
130+
[125, '\x7D'],
131+
[126, '\x7E'],
132+
[127, '\x7F'],
133+
[128, '\x80'],
134+
[129, '\x81'],
135+
[130, '\x82'],
136+
[131, '\x83'],
137+
[132, '\x84'],
138+
[133, '\x85'],
139+
[134, '\x86'],
140+
[135, '\x87'],
141+
[136, '\x88'],
142+
[137, '\x89'],
143+
[138, '\x8A'],
144+
[139, '\x8B'],
145+
[140, '\x8C'],
146+
[141, '\x8D'],
147+
[142, '\x8E'],
148+
[143, '\x8F'],
149+
[144, '\x90'],
150+
[145, '\x91'],
151+
[146, '\x92'],
152+
[147, '\x93'],
153+
[148, '\x94'],
154+
[149, '\x95'],
155+
[150, '\x96'],
156+
[151, '\x97'],
157+
[152, '\x98'],
158+
[153, '\x99'],
159+
[154, '\x9A'],
160+
[155, '\x9B'],
161+
[156, '\x9C'],
162+
[157, '\x9D'],
163+
[158, '\x9E'],
164+
[159, '\x9F'],
165+
[160, '\xA0'],
166+
[161, '\xA1'],
167+
[162, '\xA2'],
168+
[163, '\xA3'],
169+
[164, '\xA4'],
170+
[165, '\xA5'],
171+
[166, '\xA6'],
172+
[167, '\xA7'],
173+
[168, '\xA8'],
174+
[169, '\xA9'],
175+
[170, '\xAA'],
176+
[171, '\xAB'],
177+
[172, '\xAC'],
178+
[173, '\xAD'],
179+
[174, '\xAE'],
180+
[175, '\xAF'],
181+
[176, '\xB0'],
182+
[177, '\xB1'],
183+
[178, '\xB2'],
184+
[179, '\xB3'],
185+
[180, '\xB4'],
186+
[181, '\xB5'],
187+
[182, '\xB6'],
188+
[183, '\xB7'],
189+
[184, '\xB8'],
190+
[185, '\xB9'],
191+
[186, '\xBA'],
192+
[187, '\xBB'],
193+
[188, '\xBC'],
194+
[189, '\xBD'],
195+
[190, '\xBE'],
196+
[191, '\xBF'],
197+
[192, '\xC0'],
198+
[193, '\xC1'],
199+
[194, '\xC2'],
200+
[195, '\xC3'],
201+
[196, '\xC4'],
202+
[197, '\xC5'],
203+
[198, '\xC6'],
204+
[199, '\xC7'],
205+
[200, '\xC8'],
206+
[201, '\xC9'],
207+
[202, '\xCA'],
208+
[203, '\xCB'],
209+
[204, '\xCC'],
210+
[205, '\xCD'],
211+
[206, '\xCE'],
212+
[207, '\xCF'],
213+
[208, '\xD0'],
214+
[209, '\xD1'],
215+
[210, '\xD2'],
216+
[211, '\xD3'],
217+
[212, '\xD4'],
218+
[213, '\xD5'],
219+
[214, '\xD6'],
220+
[215, '\xD7'],
221+
[216, '\xD8'],
222+
[217, '\xD9'],
223+
[218, '\xDA'],
224+
[219, '\xDB'],
225+
[220, '\xDC'],
226+
[221, '\xDD'],
227+
[222, '\xDE'],
228+
[223, '\xDF'],
229+
[224, '\xE0'],
230+
[225, '\xE1'],
231+
[226, '\xE2'],
232+
[227, '\xE3'],
233+
[228, '\xE4'],
234+
[229, '\xE5'],
235+
[230, '\xE6'],
236+
[231, '\xE7'],
237+
[232, '\xE8'],
238+
[233, '\xE9'],
239+
[234, '\xEA'],
240+
[235, '\xEB'],
241+
[236, '\xEC'],
242+
[237, '\xED'],
243+
[238, '\xEE'],
244+
[239, '\xEF'],
245+
[240, '\xF0'],
246+
[241, '\xF1'],
247+
[242, '\xF2'],
248+
[243, '\xF3'],
249+
[244, '\xF4'],
250+
[245, '\xF5'],
251+
[246, '\xF6'],
252+
[247, '\xF7'],
253+
[248, '\xF8'],
254+
[249, '\xF9'],
255+
[250, '\xFA'],
256+
[251, '\xFB'],
257+
[252, '\xFC'],
258+
[253, '\xFD'],
259+
[254, '\xFE'],
260+
[255, '\xFF'],
261+
]
262+
4263
describe('asciiToDisplay', () => {
5264
it('Encodes ascii as human legible output', () => {
6265
expect(asciiToDisplay(2, 69, 69, 3, 13, 10))
@@ -28,7 +287,7 @@ describe('Encode and Decode', () => {
28287
});
29288

30289
it('Complains about non-ASCII', () => {
31-
expect(() => {EncodeAscii("🐁")}).toThrow();
290+
expect(() => { EncodeAscii("🐁") }).toThrow();
32291
});
33292

34293
it('Decodes ASCII', () => {
@@ -38,4 +297,12 @@ describe('Encode and Decode', () => {
38297
"
39298
`);
40299
});
300+
301+
it.for(asciiTable)('%i from encode(%i)', ([expected, s]) => {
302+
expect(EncodeAscii(s as string)[0]).toBe(expected);
303+
});
304+
305+
it.for(asciiTable)('decode(%i) -> %s', ([a, expected]) => {
306+
expect(DecodeAscii(new Uint8Array([a as number]))).toBe(expected);
307+
});
41308
});

0 commit comments

Comments
 (0)