@thermal-label/brother-ql-core 0.0.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/devices.test.js +16 -2
- package/dist/__tests__/devices.test.js.map +1 -1
- package/dist/__tests__/media.test.js +37 -6
- package/dist/__tests__/media.test.js.map +1 -1
- package/dist/__tests__/pack-bits.test.d.ts +2 -0
- package/dist/__tests__/pack-bits.test.d.ts.map +1 -0
- package/dist/__tests__/pack-bits.test.js +90 -0
- package/dist/__tests__/pack-bits.test.js.map +1 -0
- package/dist/__tests__/preview.test.d.ts +2 -0
- package/dist/__tests__/preview.test.d.ts.map +1 -0
- package/dist/__tests__/preview.test.js +41 -0
- package/dist/__tests__/preview.test.js.map +1 -0
- package/dist/__tests__/protocol.test.js +46 -1
- package/dist/__tests__/protocol.test.js.map +1 -1
- package/dist/__tests__/status.test.js +28 -22
- package/dist/__tests__/status.test.js.map +1 -1
- package/dist/devices.d.ts +40 -21
- package/dist/devices.d.ts.map +1 -1
- package/dist/devices.js +38 -20
- package/dist/devices.js.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/media.d.ts +43 -4
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +92 -24
- package/dist/media.js.map +1 -1
- package/dist/orientation.d.ts +11 -0
- package/dist/orientation.d.ts.map +1 -0
- package/dist/orientation.js +10 -0
- package/dist/orientation.js.map +1 -0
- package/dist/pack-bits.d.ts +20 -0
- package/dist/pack-bits.d.ts.map +1 -0
- package/dist/pack-bits.js +61 -0
- package/dist/pack-bits.js.map +1 -0
- package/dist/preview.d.ts +13 -0
- package/dist/preview.d.ts.map +1 -0
- package/dist/preview.js +31 -0
- package/dist/preview.js.map +1 -0
- package/dist/protocol.d.ts +2 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +14 -8
- package/dist/protocol.js.map +1 -1
- package/dist/status.d.ts +20 -2
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +59 -45
- package/dist/status.js.map +1 -1
- package/dist/types.d.ts +46 -30
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -2
- package/src/__tests__/devices.test.ts +18 -2
- package/src/__tests__/media.test.ts +39 -6
- package/src/__tests__/pack-bits.test.ts +92 -0
- package/src/__tests__/preview.test.ts +52 -0
- package/src/__tests__/protocol.test.ts +47 -1
- package/src/__tests__/status.test.ts +31 -22
- package/src/devices.ts +41 -22
- package/src/index.ts +45 -11
- package/src/media.ts +105 -27
- package/src/orientation.ts +11 -0
- package/src/pack-bits.ts +64 -0
- package/src/preview.ts +35 -0
- package/src/protocol.ts +16 -9
- package/src/status.ts +62 -47
- package/src/types.ts +52 -32
package/dist/protocol.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
|
package/dist/status.d.ts
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function parseStatus(bytes: Uint8Array): PrinterStatus;
|
|
1
|
+
import type { BrotherQLStatus } from './types.js';
|
|
3
2
|
export declare const STATUS_REQUEST: Uint8Array;
|
|
3
|
+
/**
|
|
4
|
+
* Parse a Brother QL 32-byte status response.
|
|
5
|
+
*
|
|
6
|
+
* Fields:
|
|
7
|
+
* byte 8 — error info 1 (bit mask, see ERROR_INFO_1)
|
|
8
|
+
* byte 9 — error info 2 (bit mask, see ERROR_INFO_2)
|
|
9
|
+
* byte 10 — media width (mm)
|
|
10
|
+
* byte 11 — media type (0x0A continuous, 0x0B die-cut)
|
|
11
|
+
* byte 17 — media length (mm), 0 for continuous
|
|
12
|
+
* byte 18 — status type (0x02 = error response)
|
|
13
|
+
*
|
|
14
|
+
* `detectedMedia` is resolved against the media registry via
|
|
15
|
+
* `findMediaByDimensions`. `editorLiteMode` is a driver-specific
|
|
16
|
+
* extension on `BrotherQLStatus` — the status-type byte doesn't
|
|
17
|
+
* actually report it, but keeping the field here means callers can
|
|
18
|
+
* set it from other signals (e.g. mass-storage PID detected during
|
|
19
|
+
* discovery) without changing the return type.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseStatus(bytes: Uint8Array): BrotherQLStatus;
|
|
4
22
|
//# sourceMappingURL=status.d.ts.map
|
package/dist/status.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,eAAO,MAAM,cAAc,YAAqC,CAAC;AAyBjE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,eAAe,CAkC9D"}
|
package/dist/status.js
CHANGED
|
@@ -1,61 +1,75 @@
|
|
|
1
|
-
import {} from './
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
1
|
+
import { findMediaByDimensions } from './media.js';
|
|
2
|
+
export const STATUS_REQUEST = new Uint8Array([0x1b, 0x69, 0x53]);
|
|
3
|
+
/** Error-info 1 bit → structured PrinterError code + human message. */
|
|
4
|
+
const ERROR_INFO_1 = [
|
|
5
|
+
{ bit: 0, code: 'no_media', message: 'No media' },
|
|
6
|
+
{ bit: 1, code: 'media_end', message: 'End of media' },
|
|
7
|
+
{ bit: 2, code: 'cutter_jam', message: 'Cutter jam' },
|
|
8
|
+
{ bit: 3, code: 'system_error', message: 'Weak battery' },
|
|
9
|
+
{ bit: 4, code: 'not_ready', message: 'Printer in use' },
|
|
10
|
+
{ bit: 6, code: 'system_error', message: 'High voltage adapter' },
|
|
11
|
+
{ bit: 7, code: 'system_error', message: 'Fan motor error' },
|
|
12
|
+
];
|
|
13
|
+
/** Error-info 2 bit → structured PrinterError code + human message. */
|
|
14
|
+
const ERROR_INFO_2 = [
|
|
15
|
+
{ bit: 0, code: 'wrong_media', message: 'Replace media' },
|
|
16
|
+
{ bit: 1, code: 'system_error', message: 'Expansion buffer full' },
|
|
17
|
+
{ bit: 2, code: 'system_error', message: 'Transmission error' },
|
|
18
|
+
{ bit: 3, code: 'system_error', message: 'Communication buffer full' },
|
|
19
|
+
{ bit: 4, code: 'cover_open', message: 'Cover open' },
|
|
20
|
+
{ bit: 5, code: 'not_ready', message: 'Cancel key pressed' },
|
|
21
|
+
{ bit: 6, code: 'media_end', message: 'Media cannot be fed' },
|
|
22
|
+
{ bit: 7, code: 'system_error', message: 'System error' },
|
|
23
|
+
];
|
|
24
|
+
/**
|
|
25
|
+
* Parse a Brother QL 32-byte status response.
|
|
26
|
+
*
|
|
27
|
+
* Fields:
|
|
28
|
+
* byte 8 — error info 1 (bit mask, see ERROR_INFO_1)
|
|
29
|
+
* byte 9 — error info 2 (bit mask, see ERROR_INFO_2)
|
|
30
|
+
* byte 10 — media width (mm)
|
|
31
|
+
* byte 11 — media type (0x0A continuous, 0x0B die-cut)
|
|
32
|
+
* byte 17 — media length (mm), 0 for continuous
|
|
33
|
+
* byte 18 — status type (0x02 = error response)
|
|
34
|
+
*
|
|
35
|
+
* `detectedMedia` is resolved against the media registry via
|
|
36
|
+
* `findMediaByDimensions`. `editorLiteMode` is a driver-specific
|
|
37
|
+
* extension on `BrotherQLStatus` — the status-type byte doesn't
|
|
38
|
+
* actually report it, but keeping the field here means callers can
|
|
39
|
+
* set it from other signals (e.g. mass-storage PID detected during
|
|
40
|
+
* discovery) without changing the return type.
|
|
41
|
+
*/
|
|
21
42
|
export function parseStatus(bytes) {
|
|
22
|
-
if (bytes.length < 32)
|
|
43
|
+
if (bytes.length < 32) {
|
|
23
44
|
throw new Error(`Status response too short: ${bytes.length.toString()} bytes`);
|
|
24
|
-
|
|
25
|
-
// the length check above. DataView avoids the issue: getUint8 returns number.
|
|
45
|
+
}
|
|
26
46
|
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
27
|
-
const errors = [];
|
|
28
47
|
const errInfo1 = view.getUint8(8);
|
|
29
48
|
const errInfo2 = view.getUint8(9);
|
|
30
|
-
for (const [bitStr, msg] of Object.entries(ERROR_INFO_1)) {
|
|
31
|
-
if (errInfo1 & (1 << Number(bitStr)))
|
|
32
|
-
errors.push(msg);
|
|
33
|
-
}
|
|
34
|
-
for (const [bitStr, msg] of Object.entries(ERROR_INFO_2)) {
|
|
35
|
-
if (errInfo2 & (1 << Number(bitStr)))
|
|
36
|
-
errors.push(msg);
|
|
37
|
-
}
|
|
38
49
|
const mediaWidthMm = view.getUint8(10);
|
|
39
50
|
const mediaTypeByte = view.getUint8(11);
|
|
40
51
|
const mediaLengthMm = view.getUint8(17);
|
|
41
|
-
let mediaType = null;
|
|
42
|
-
if (mediaTypeByte === 0x0a)
|
|
43
|
-
mediaType = 'continuous';
|
|
44
|
-
else if (mediaTypeByte === 0x0b)
|
|
45
|
-
mediaType = 'die-cut';
|
|
46
|
-
// Status type is at byte 18, not 14. Byte 14 is an undocumented media-type
|
|
47
|
-
// code that carries non-zero values and is not the status type field.
|
|
48
52
|
const statusType = view.getUint8(18);
|
|
49
|
-
const
|
|
53
|
+
const errors = [];
|
|
54
|
+
for (const { bit, code, message } of ERROR_INFO_1) {
|
|
55
|
+
if (errInfo1 & (1 << bit))
|
|
56
|
+
errors.push({ code, message });
|
|
57
|
+
}
|
|
58
|
+
for (const { bit, code, message } of ERROR_INFO_2) {
|
|
59
|
+
if (errInfo2 & (1 << bit))
|
|
60
|
+
errors.push({ code, message });
|
|
61
|
+
}
|
|
62
|
+
const mediaLoaded = mediaWidthMm > 0 && mediaTypeByte !== 0;
|
|
63
|
+
const detected = mediaLoaded
|
|
64
|
+
? findMediaByDimensions(mediaWidthMm, mediaLengthMm, false)
|
|
65
|
+
: undefined;
|
|
50
66
|
return {
|
|
51
|
-
ready,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
mediaType,
|
|
67
|
+
ready: errors.length === 0 && statusType !== 0x02,
|
|
68
|
+
mediaLoaded,
|
|
69
|
+
...(detected === undefined ? {} : { detectedMedia: detected }),
|
|
55
70
|
errors,
|
|
56
71
|
editorLiteMode: false,
|
|
57
72
|
rawBytes: bytes,
|
|
58
73
|
};
|
|
59
74
|
}
|
|
60
|
-
export const STATUS_REQUEST = new Uint8Array([0x1b, 0x69, 0x53]);
|
|
61
75
|
//# sourceMappingURL=status.js.map
|
package/dist/status.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,39 +1,64 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { LabelBitmap } from '@mbtech-nl/bitmap';
|
|
2
|
+
import type { DeviceDescriptor, MediaDescriptor, PrintOptions, PrinterStatus } from '@thermal-label/contracts';
|
|
2
3
|
export type MediaType = 'continuous' | 'die-cut';
|
|
3
4
|
export type HeadWidth = 720 | 1296;
|
|
4
5
|
export type ColorMode = 'single' | 'two-color';
|
|
5
6
|
export type NetworkSupport = 'none' | 'wifi' | 'wired' | 'wifi+wired';
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Brother QL device descriptor.
|
|
9
|
+
*
|
|
10
|
+
* Extends the contracts base with QL-specific fields: head geometry,
|
|
11
|
+
* protocol feature flags, and the optional mass-storage PID for Editor
|
|
12
|
+
* Lite mode.
|
|
13
|
+
*
|
|
14
|
+
* **Bluetooth on the QL-820NWB / 820NWBc**: not exposed over GATT.
|
|
15
|
+
* Classic Bluetooth (SPP) is paired at the OS level; the kernel/driver
|
|
16
|
+
* exposes an RFCOMM serial port, reachable via the `'serial'` transport
|
|
17
|
+
* in Node.js and the `'web-serial'` transport in Chrome/Edge. macOS has
|
|
18
|
+
* dropped classic Bluetooth SPP — no serial route there.
|
|
19
|
+
*/
|
|
20
|
+
export interface BrotherQLDevice extends DeviceDescriptor {
|
|
21
|
+
family: 'brother-ql';
|
|
8
22
|
vid: number;
|
|
9
23
|
pid: number;
|
|
10
24
|
headPins: HeadWidth;
|
|
11
25
|
bytesPerRow: number;
|
|
12
26
|
twoColor: boolean;
|
|
13
27
|
network: NetworkSupport;
|
|
14
|
-
bluetooth: boolean;
|
|
15
28
|
autocut: boolean;
|
|
16
29
|
compression: boolean;
|
|
17
30
|
editorLite: boolean;
|
|
31
|
+
/** Alternate PID seen when the printer is in Editor Lite mass-storage mode. */
|
|
18
32
|
massStoragePid?: number;
|
|
19
33
|
}
|
|
20
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Brother QL media descriptor.
|
|
36
|
+
*
|
|
37
|
+
* Extends `MediaDescriptor` with the dots-based geometry the raster
|
|
38
|
+
* encoder needs. The base `palette` field flips the driver into
|
|
39
|
+
* multi-plane mode — only DK-22251 declares one in the registry.
|
|
40
|
+
*/
|
|
41
|
+
export interface BrotherQLMedia extends MediaDescriptor {
|
|
21
42
|
id: number;
|
|
22
|
-
name: string;
|
|
23
43
|
type: MediaType;
|
|
24
|
-
widthMm: number;
|
|
25
|
-
lengthMm: number;
|
|
26
44
|
printAreaDots: number;
|
|
27
45
|
leftMarginPins: number;
|
|
28
46
|
rightMarginPins: number;
|
|
47
|
+
/** Die-cut masked area in dots (registration windows). */
|
|
29
48
|
dieCutMaskedAreaDots?: number;
|
|
30
|
-
|
|
31
|
-
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Brother QL status — contracts `PrinterStatus` plus the
|
|
52
|
+
* `editorLiteMode` flag (pre-paired QL-820NWB silently drops raster
|
|
53
|
+
* jobs when in Editor Lite mode; callers need to know).
|
|
54
|
+
*/
|
|
55
|
+
export interface BrotherQLStatus extends PrinterStatus {
|
|
56
|
+
editorLiteMode: boolean;
|
|
32
57
|
}
|
|
33
58
|
export interface PageData {
|
|
34
59
|
bitmap: LabelBitmap;
|
|
35
60
|
redBitmap?: LabelBitmap;
|
|
36
|
-
media:
|
|
61
|
+
media: BrotherQLMedia;
|
|
37
62
|
options?: PageOptions;
|
|
38
63
|
}
|
|
39
64
|
export interface PageOptions {
|
|
@@ -46,24 +71,15 @@ export interface PageOptions {
|
|
|
46
71
|
export interface JobOptions {
|
|
47
72
|
copies?: number;
|
|
48
73
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
rotate?: 0 | 90 | 180 | 270;
|
|
59
|
-
}
|
|
60
|
-
export interface PrinterStatus {
|
|
61
|
-
ready: boolean;
|
|
62
|
-
mediaWidthMm: number;
|
|
63
|
-
mediaLengthMm: number;
|
|
64
|
-
mediaType: MediaType | null;
|
|
65
|
-
errors: string[];
|
|
66
|
-
editorLiteMode: boolean;
|
|
67
|
-
rawBytes: Uint8Array;
|
|
74
|
+
/**
|
|
75
|
+
* Per-call print options for `BrotherQLPrinter.print()`.
|
|
76
|
+
*
|
|
77
|
+
* Extends the cross-driver `PrintOptions` with QL-specific knobs. The
|
|
78
|
+
* `rotate` override picks the rotation angle passed to
|
|
79
|
+
* `renderImage` / `renderMultiPlaneImage` — `'auto'` (the default)
|
|
80
|
+
* defers to the media's `defaultOrientation` heuristic.
|
|
81
|
+
*/
|
|
82
|
+
export interface BrotherQLPrintOptions extends PrintOptions {
|
|
83
|
+
rotate?: 'auto' | 0 | 90 | 180 | 270;
|
|
68
84
|
}
|
|
69
85
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,aAAa,EACd,MAAM,0BAA0B,CAAC;AAElC,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;AACjD,MAAM,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,CAAC;AACnC,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;AAC/C,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,YAAY,CAAC;AAEtE;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,MAAM,EAAE,YAAY,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,SAAS,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,cAAc,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAe,SAAQ,eAAe;IACrD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAsB,SAAQ,YAAY;IACzD,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,CAAC;CACtC"}
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thermal-label/brother-ql-core",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Protocol encoding, device registry, and media registry for Brother QL label printers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"brother",
|
|
@@ -53,7 +53,8 @@
|
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@mbtech-nl/bitmap": "^
|
|
56
|
+
"@mbtech-nl/bitmap": "^1.2.1",
|
|
57
|
+
"@thermal-label/contracts": "^0.2.0"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
60
|
"@mbtech-nl/tsconfig": "^1.0.0",
|
|
@@ -65,9 +65,25 @@ describe('Device registry invariants', () => {
|
|
|
65
65
|
}
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
it('every device
|
|
68
|
+
it('every device belongs to the brother-ql family', () => {
|
|
69
69
|
for (const dev of Object.values(DEVICES)) {
|
|
70
|
-
expect(dev.
|
|
70
|
+
expect(dev.family).toBe('brother-ql');
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('QL-820NWB(c) advertise serial/web-serial for OS-paired Bluetooth', () => {
|
|
75
|
+
for (const key of ['QL_820NWB', 'QL_820NWBc'] as const) {
|
|
76
|
+
const dev = DEVICES[key];
|
|
77
|
+
expect(dev.transports).toContain('serial');
|
|
78
|
+
expect(dev.transports).toContain('web-serial');
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('no device descriptor declares web-bluetooth', () => {
|
|
83
|
+
// Bluetooth on the 820 series is classic SPP, not GATT — the
|
|
84
|
+
// serial transports cover it. See packages/core/src/types.ts.
|
|
85
|
+
for (const dev of Object.values(DEVICES)) {
|
|
86
|
+
expect(dev.transports).not.toContain('web-bluetooth');
|
|
71
87
|
}
|
|
72
88
|
});
|
|
73
89
|
});
|
|
@@ -7,14 +7,14 @@ describe('findMedia', () => {
|
|
|
7
7
|
expect(m).toBeDefined();
|
|
8
8
|
expect(m!.widthMm).toBe(62);
|
|
9
9
|
expect(m!.type).toBe('continuous');
|
|
10
|
-
expect(m!.
|
|
10
|
+
expect(m!.heightMm).toBeUndefined();
|
|
11
11
|
});
|
|
12
12
|
|
|
13
13
|
it('returns correct descriptor for 62x29mm die-cut (ID 274)', () => {
|
|
14
14
|
const m = findMedia(274);
|
|
15
15
|
expect(m).toBeDefined();
|
|
16
16
|
expect(m!.type).toBe('die-cut');
|
|
17
|
-
expect(m!.
|
|
17
|
+
expect(m!.heightMm).toBe(29);
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
it('returns undefined for unknown ID', () => {
|
|
@@ -46,22 +46,55 @@ describe('findMediaByWidth', () => {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
describe('Media registry invariants', () => {
|
|
49
|
-
it('die-cut media has
|
|
49
|
+
it('die-cut media has a heightMm', () => {
|
|
50
50
|
for (const m of Object.values(MEDIA)) {
|
|
51
51
|
if (m.type === 'die-cut') {
|
|
52
|
-
expect(m.
|
|
52
|
+
expect(m.heightMm).toBeDefined();
|
|
53
|
+
expect(m.heightMm!).toBeGreaterThan(0);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
});
|
|
56
57
|
|
|
57
|
-
it('continuous media
|
|
58
|
+
it('continuous media omits heightMm', () => {
|
|
58
59
|
for (const m of Object.values(MEDIA)) {
|
|
59
60
|
if (m.type === 'continuous') {
|
|
60
|
-
expect(m.
|
|
61
|
+
expect(m.heightMm).toBeUndefined();
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
});
|
|
64
65
|
|
|
66
|
+
it('only DK-22251 carries a multi-ink palette', () => {
|
|
67
|
+
for (const m of Object.values(MEDIA)) {
|
|
68
|
+
if (m.id === 251) {
|
|
69
|
+
expect(m.palette).toBeDefined();
|
|
70
|
+
const palette = m.palette!;
|
|
71
|
+
expect(palette).toHaveLength(2);
|
|
72
|
+
expect(palette[0]!.name).toBe('black');
|
|
73
|
+
expect(palette[1]!.name).toBe('red');
|
|
74
|
+
} else {
|
|
75
|
+
expect(m.palette).toBeUndefined();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('rectangular die-cut entries declare defaultOrientation: horizontal', () => {
|
|
81
|
+
const rectangularDieCutIds = [269, 270, 370, 271, 272, 367, 374, 274, 275, 365, 366];
|
|
82
|
+
for (const id of rectangularDieCutIds) {
|
|
83
|
+
const m = MEDIA[id]!;
|
|
84
|
+
expect(m, `entry ${id.toString()}`).toBeDefined();
|
|
85
|
+
expect(m.defaultOrientation, `entry ${id.toString()}`).toBe('horizontal');
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('round die-cut entries set cornerRadiusMm to widthMm / 2', () => {
|
|
90
|
+
const roundDieCutIds = [362, 363, 273];
|
|
91
|
+
for (const id of roundDieCutIds) {
|
|
92
|
+
const m = MEDIA[id]!;
|
|
93
|
+
expect(m, `entry ${id.toString()}`).toBeDefined();
|
|
94
|
+
expect(m.cornerRadiusMm, `entry ${id.toString()}`).toBe(m.widthMm / 2);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
65
98
|
it('all IDs are unique', () => {
|
|
66
99
|
const ids = Object.values(MEDIA).map(m => m.id);
|
|
67
100
|
const unique = new Set(ids);
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { packBits } from '../pack-bits.js';
|
|
3
|
+
|
|
4
|
+
// Reference TIFF PackBits decoder. Used to round-trip arbitrary inputs and
|
|
5
|
+
// confirm the encoder emits a stream the canonical algorithm can decode.
|
|
6
|
+
function unpackBits(input: Uint8Array): Uint8Array {
|
|
7
|
+
const out: number[] = [];
|
|
8
|
+
let i = 0;
|
|
9
|
+
while (i < input.length) {
|
|
10
|
+
const header = input[i]!;
|
|
11
|
+
const signed = header > 127 ? header - 256 : header;
|
|
12
|
+
if (signed >= 0) {
|
|
13
|
+
const n = signed + 1;
|
|
14
|
+
for (let j = 0; j < n; j++) out.push(input[i + 1 + j]!);
|
|
15
|
+
i += 1 + n;
|
|
16
|
+
} else if (signed >= -127) {
|
|
17
|
+
const n = 1 - signed;
|
|
18
|
+
for (let j = 0; j < n; j++) out.push(input[i + 1]!);
|
|
19
|
+
i += 2;
|
|
20
|
+
} else {
|
|
21
|
+
i++; // signed === -128: no-op
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return new Uint8Array(out);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe('packBits', () => {
|
|
28
|
+
it('emits empty output for empty input', () => {
|
|
29
|
+
expect(packBits(new Uint8Array(0)).length).toBe(0);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('encodes a single byte as a 1-byte literal', () => {
|
|
33
|
+
expect(Array.from(packBits(new Uint8Array([0x42])))).toEqual([0x00, 0x42]);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('encodes a 2-byte repeat as 2 wire bytes', () => {
|
|
37
|
+
// -(2-1) = -1 → 0xFF
|
|
38
|
+
expect(Array.from(packBits(new Uint8Array([0x42, 0x42])))).toEqual([0xff, 0x42]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('compresses an all-zero 90-byte row to 2 bytes (the common case)', () => {
|
|
42
|
+
const result = packBits(new Uint8Array(90));
|
|
43
|
+
// -(90-1) = -89 = 0xA7
|
|
44
|
+
expect(Array.from(result)).toEqual([0xa7, 0x00]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('caps repeat runs at 128 bytes — 130 zeros split into 128 + 2', () => {
|
|
48
|
+
const result = packBits(new Uint8Array(130));
|
|
49
|
+
// -(128-1) = -127 = 0x81; -(2-1) = -1 = 0xFF
|
|
50
|
+
expect(Array.from(result)).toEqual([0x81, 0x00, 0xff, 0x00]);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('caps literal runs at 128 bytes', () => {
|
|
54
|
+
// 130 distinct bytes split into 128 + 2 literals.
|
|
55
|
+
const input = new Uint8Array(130);
|
|
56
|
+
for (let i = 0; i < 130; i++) input[i] = i & 0xff;
|
|
57
|
+
const result = packBits(input);
|
|
58
|
+
expect(result[0]).toBe(0x7f); // header for 128 literals
|
|
59
|
+
expect(result[129]).toBe(0x01); // header for 2 literals
|
|
60
|
+
expect(result.length).toBe(132);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('mixes literal and repeat runs', () => {
|
|
64
|
+
// A A B C D D D E
|
|
65
|
+
const input = new Uint8Array([0x10, 0x10, 0x20, 0x30, 0x40, 0x40, 0x40, 0x50]);
|
|
66
|
+
expect(Array.from(packBits(input))).toEqual([
|
|
67
|
+
0xff,
|
|
68
|
+
0x10, // -1: 2 repeats of 0x10
|
|
69
|
+
0x01,
|
|
70
|
+
0x20,
|
|
71
|
+
0x30, // 1: 2 literals
|
|
72
|
+
0xfe,
|
|
73
|
+
0x40, // -2: 3 repeats of 0x40
|
|
74
|
+
0x00,
|
|
75
|
+
0x50, // 0: 1 literal
|
|
76
|
+
]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('round-trips a label-like row (margins + bar + scattered) through the spec decoder', () => {
|
|
80
|
+
// Mimic a typical raster row: 12 zero-byte margin, 50 bytes of 0xFF
|
|
81
|
+
// (solid bar), 12 mixed bytes (text), 16 zero-byte trailing margin.
|
|
82
|
+
const original = new Uint8Array(90);
|
|
83
|
+
for (let i = 12; i < 62; i++) original[i] = 0xff;
|
|
84
|
+
for (let i = 62; i < 74; i++) original[i] = (i * 7) & 0xff;
|
|
85
|
+
|
|
86
|
+
const compressed = packBits(original);
|
|
87
|
+
const decoded = unpackBits(compressed);
|
|
88
|
+
expect(Array.from(decoded)).toEqual(Array.from(original));
|
|
89
|
+
// And it actually saves bytes — the whole point.
|
|
90
|
+
expect(compressed.length).toBeLessThan(original.length);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { MEDIA } from '../media.js';
|
|
3
|
+
import { createPreviewOffline } from '../preview.js';
|
|
4
|
+
|
|
5
|
+
function solidRgba(
|
|
6
|
+
width: number,
|
|
7
|
+
height: number,
|
|
8
|
+
rgba: [number, number, number, number],
|
|
9
|
+
): {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
data: Uint8Array;
|
|
13
|
+
} {
|
|
14
|
+
const data = new Uint8Array(width * height * 4);
|
|
15
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
16
|
+
data[i] = rgba[0];
|
|
17
|
+
data[i + 1] = rgba[1];
|
|
18
|
+
data[i + 2] = rgba[2];
|
|
19
|
+
data[i + 3] = rgba[3];
|
|
20
|
+
}
|
|
21
|
+
return { width, height, data };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe('createPreviewOffline', () => {
|
|
25
|
+
it('returns a single black plane for single-colour media', () => {
|
|
26
|
+
const image = solidRgba(8, 8, [0, 0, 0, 255]);
|
|
27
|
+
const preview = createPreviewOffline(image, MEDIA[259]!);
|
|
28
|
+
expect(preview.planes).toHaveLength(1);
|
|
29
|
+
expect(preview.planes[0]!.name).toBe('black');
|
|
30
|
+
expect(preview.planes[0]!.displayColor).toBe('#000000');
|
|
31
|
+
expect(preview.media).toBe(MEDIA[259]);
|
|
32
|
+
expect(preview.assumed).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('returns black + red planes for multi-ink media (DK-22251)', () => {
|
|
36
|
+
const image = solidRgba(8, 8, [255, 0, 0, 255]);
|
|
37
|
+
const preview = createPreviewOffline(image, MEDIA[251]!);
|
|
38
|
+
expect(preview.planes.map(p => p.name)).toEqual(['black', 'red']);
|
|
39
|
+
expect(preview.planes[1]!.displayColor).toBe('#ff0000');
|
|
40
|
+
expect(preview.media).toBe(MEDIA[251]);
|
|
41
|
+
expect(preview.assumed).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('planes share the source image dimensions', () => {
|
|
45
|
+
const image = solidRgba(24, 12, [128, 128, 128, 255]);
|
|
46
|
+
const preview = createPreviewOffline(image, MEDIA[251]!);
|
|
47
|
+
for (const plane of preview.planes) {
|
|
48
|
+
expect(plane.bitmap.widthPx).toBe(24);
|
|
49
|
+
expect(plane.bitmap.heightPx).toBe(12);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
});
|