@thermal-print/escpos 0.3.1-beta.2 → 0.3.1-beta.4
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/command-adapters/escbematech-adapter.d.ts +1 -1
- package/dist/command-adapters/escbematech-adapter.d.ts.map +1 -1
- package/dist/command-adapters/escbematech-adapter.js +1 -1
- package/dist/command-adapters/escpos-adapter.d.ts +1 -1
- package/dist/command-adapters/escpos-adapter.d.ts.map +1 -1
- package/dist/command-adapters/escpos-adapter.js +7 -12
- package/dist/command-adapters/types.d.ts +2 -2
- package/dist/command-adapters/types.d.ts.map +1 -1
- package/dist/commands/escbematech.d.ts +1 -1
- package/dist/commands/escbematech.js +2 -2
- package/dist/commands/escpos.d.ts +1 -2
- package/dist/commands/escpos.d.ts.map +1 -1
- package/dist/commands/escpos.js +4 -3
- package/dist/converter.d.ts +10 -1
- package/dist/converter.d.ts.map +1 -1
- package/dist/converter.js +15 -5
- package/dist/generator.d.ts +26 -16
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +53 -42
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/traverser.d.ts +3 -1
- package/dist/traverser.d.ts.map +1 -1
- package/dist/traverser.js +83 -92
- package/package.json +2 -2
|
@@ -19,7 +19,7 @@ export declare class ESCBematechCommandAdapter implements CommandAdapter {
|
|
|
19
19
|
getMaxCharacterSize(): CharacterSize;
|
|
20
20
|
getInitCommand(): number[];
|
|
21
21
|
getAlignCommand(align: 'left' | 'center' | 'right'): number[];
|
|
22
|
-
getCharacterSizeCommand(width: number, height: number, bold: boolean,
|
|
22
|
+
getCharacterSizeCommand(width: number, height: number, bold: boolean, useFontB?: boolean): number[];
|
|
23
23
|
getLineSpacingCommand(dots?: number): number[];
|
|
24
24
|
getCutCommand(type: 'full' | 'partial', feedLines?: number): number[];
|
|
25
25
|
getQRCodeCommand(data: string, size: number): number[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"escbematech-adapter.d.ts","sourceRoot":"","sources":["../../src/command-adapters/escbematech-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxD;;;GAGG;AACH,qBAAa,yBAA0B,YAAW,cAAc;IAC9D,OAAO,IAAI,MAAM;IAIjB,mBAAmB,IAAI,aAAa;IAMpC,cAAc,IAAI,MAAM,EAAE;IAK1B,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,EAAE;IAY7D,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"escbematech-adapter.d.ts","sourceRoot":"","sources":["../../src/command-adapters/escbematech-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxD;;;GAGG;AACH,qBAAa,yBAA0B,YAAW,cAAc;IAC9D,OAAO,IAAI,MAAM;IAIjB,mBAAmB,IAAI,aAAa;IAMpC,cAAc,IAAI,MAAM,EAAE;IAK1B,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,EAAE;IAY7D,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,EAAE;IAiBnG,qBAAqB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAW9C,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAqBrE,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAgBtD,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAuBnF,kBAAkB,CAAC,KAAK,GAAE,MAAU,GAAG,MAAM,EAAE;IAU/C,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAa7C"}
|
|
@@ -38,7 +38,7 @@ export class ESCBematechCommandAdapter {
|
|
|
38
38
|
return ESCBema.ALIGN_RIGHT;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
getCharacterSizeCommand(width, height, bold,
|
|
41
|
+
getCharacterSizeCommand(width, height, bold, useFontB) {
|
|
42
42
|
/**
|
|
43
43
|
* ESC/Bema character sizing:
|
|
44
44
|
* - Uses ESC ! n for combined mode (emphasis, double-height, double-width)
|
|
@@ -14,7 +14,7 @@ export declare class ESCPOSCommandAdapter implements CommandAdapter {
|
|
|
14
14
|
getMaxCharacterSize(): CharacterSize;
|
|
15
15
|
getInitCommand(): number[];
|
|
16
16
|
getAlignCommand(align: "left" | "center" | "right"): number[];
|
|
17
|
-
getCharacterSizeCommand(width: number, height: number, bold: boolean,
|
|
17
|
+
getCharacterSizeCommand(width: number, height: number, bold: boolean, useFontB?: boolean): number[];
|
|
18
18
|
getLineSpacingCommand(dots?: number): number[];
|
|
19
19
|
getCutCommand(type: "full" | "partial", feedLines?: number): number[];
|
|
20
20
|
getQRCodeCommand(data: string, size: number): number[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"escpos-adapter.d.ts","sourceRoot":"","sources":["../../src/command-adapters/escpos-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAQxD;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,cAAc;IACzD,OAAO,IAAI,MAAM;IAIjB,mBAAmB,IAAI,aAAa;IAMpC,cAAc,IAAI,MAAM,EAAE;
|
|
1
|
+
{"version":3,"file":"escpos-adapter.d.ts","sourceRoot":"","sources":["../../src/command-adapters/escpos-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAQxD;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,cAAc;IACzD,OAAO,IAAI,MAAM;IAIjB,mBAAmB,IAAI,aAAa;IAMpC,cAAc,IAAI,MAAM,EAAE;IAa1B,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,EAAE;IAY7D,uBAAuB,CACrB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,QAAQ,GAAE,OAAc,GACvB,MAAM,EAAE;IASX,qBAAqB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAU9C,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAoBrE,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAKtD,qBAAqB,CACnB,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,MAAM,EAAE;IAKX,kBAAkB,CAAC,KAAK,GAAE,MAAU,GAAG,MAAM,EAAE;IAU/C,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAI7C"}
|
|
@@ -25,16 +25,11 @@ export class ESCPOSCommandAdapter {
|
|
|
25
25
|
getInitCommand() {
|
|
26
26
|
const commands = [];
|
|
27
27
|
// ESC @ - Reset printer to default state
|
|
28
|
+
// This resets all settings to factory defaults including print area width
|
|
29
|
+
// and motion units. We intentionally do NOT send GS P or GS W here —
|
|
30
|
+
// the printer's factory defaults handle paper width correctly for
|
|
31
|
+
// centering and line wrapping.
|
|
28
32
|
commands.push(...ESCPOS.INIT);
|
|
29
|
-
// GS P x y - Set horizontal and vertical motion units
|
|
30
|
-
// Set both to 203 DPI (standard thermal printer resolution)
|
|
31
|
-
// This ensures GS W and other commands use 1/203 inch per unit
|
|
32
|
-
commands.push(0x1D, 0x50, 203, 203);
|
|
33
|
-
// GS W nL nH - Set printing area width
|
|
34
|
-
// For 80mm paper at 203 DPI: 80mm ≈ 3.15" × 203 = 640 dots
|
|
35
|
-
// Using 640 dots to match physical paper width
|
|
36
|
-
const width = 640;
|
|
37
|
-
commands.push(0x1D, 0x57, width & 0xFF, (width >> 8) & 0xFF);
|
|
38
33
|
return commands;
|
|
39
34
|
}
|
|
40
35
|
getAlignCommand(align) {
|
|
@@ -48,13 +43,13 @@ export class ESCPOSCommandAdapter {
|
|
|
48
43
|
return ESCPOS.ALIGN_RIGHT;
|
|
49
44
|
}
|
|
50
45
|
}
|
|
51
|
-
getCharacterSizeCommand(width, height, bold,
|
|
46
|
+
getCharacterSizeCommand(width, height, bold, useFontB = true) {
|
|
52
47
|
/**
|
|
53
48
|
* ESC ! n - Select print mode
|
|
54
49
|
* Uses the calculateCharacterSize function from escpos.ts
|
|
55
|
-
* This provides character sizing up to 2x2 with optional bold
|
|
50
|
+
* This provides character sizing up to 2x2 with optional bold
|
|
56
51
|
*/
|
|
57
|
-
return ESCPOS.calculateCharacterSize(width, height, bold,
|
|
52
|
+
return ESCPOS.calculateCharacterSize(width, height, bold, useFontB);
|
|
58
53
|
}
|
|
59
54
|
getLineSpacingCommand(dots) {
|
|
60
55
|
if (dots === undefined) {
|
|
@@ -38,9 +38,9 @@ export interface CommandAdapter {
|
|
|
38
38
|
* @param width - Width multiplier
|
|
39
39
|
* @param height - Height multiplier
|
|
40
40
|
* @param bold - Whether text should be bold
|
|
41
|
-
* @param
|
|
41
|
+
* @param useFontB - Use Font B (narrower) instead of Font A (optional, default: false)
|
|
42
42
|
*/
|
|
43
|
-
getCharacterSizeCommand(width: number, height: number, bold: boolean,
|
|
43
|
+
getCharacterSizeCommand(width: number, height: number, bold: boolean, useFontB?: boolean): number[];
|
|
44
44
|
/**
|
|
45
45
|
* Set line spacing command
|
|
46
46
|
* @param dots - Line spacing in dots (0-255), undefined for default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/command-adapters/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,OAAO,IAAI,MAAM,CAAC;IAElB;;OAEG;IACH,mBAAmB,IAAI,aAAa,CAAC;IAErC;;;OAGG;IACH,cAAc,IAAI,MAAM,EAAE,CAAC;IAE3B;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC;IAE9D;;;;;;OAMG;IACH,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/command-adapters/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,OAAO,IAAI,MAAM,CAAC;IAElB;;OAEG;IACH,mBAAmB,IAAI,aAAa,CAAC;IAErC;;;OAGG;IACH,cAAc,IAAI,MAAM,EAAE,CAAC;IAE3B;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC;IAE9D;;;;;;OAMG;IACH,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,EAAE,CAAC;IAEpG;;;OAGG;IACH,qBAAqB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAE/C;;;;OAIG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAEtE;;;;OAIG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAEvD;;;;;OAKG;IACH,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAEpF;;;OAGG;IACH,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAE7C;;;OAGG;IACH,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC9C"}
|
|
@@ -301,7 +301,7 @@ export declare const feedPaper: (n: number) => number[];
|
|
|
301
301
|
export declare const SET_LINE_HEIGHT_DEFAULT: number[];
|
|
302
302
|
/**
|
|
303
303
|
* ESC 3 n - Set line feed to n/144 inches
|
|
304
|
-
* Range:
|
|
304
|
+
* Range: 18 ≤ n ≤ 255
|
|
305
305
|
* Takes effect immediately
|
|
306
306
|
*/
|
|
307
307
|
export declare const setLineSpacing: (n: number) => number[];
|
|
@@ -367,11 +367,11 @@ export const feedPaper = (n) => {
|
|
|
367
367
|
export const SET_LINE_HEIGHT_DEFAULT = [ESC, 0x32];
|
|
368
368
|
/**
|
|
369
369
|
* ESC 3 n - Set line feed to n/144 inches
|
|
370
|
-
* Range:
|
|
370
|
+
* Range: 18 ≤ n ≤ 255
|
|
371
371
|
* Takes effect immediately
|
|
372
372
|
*/
|
|
373
373
|
export const setLineSpacing = (n) => {
|
|
374
|
-
const value = Math.max(
|
|
374
|
+
const value = Math.max(18, Math.min(255, n));
|
|
375
375
|
return [ESC, 0x33, value];
|
|
376
376
|
};
|
|
377
377
|
/**
|
|
@@ -30,10 +30,9 @@ export declare const UNDERLINE_OFF: number[];
|
|
|
30
30
|
* @param width - Width multiplier (1 or 2)
|
|
31
31
|
* @param height - Height multiplier (1 or 2)
|
|
32
32
|
* @param bold - Whether text should be bold (optional, default: false)
|
|
33
|
-
* @param font - Font selection: 0 = Font A (12x24), 1 = Font B (9x17) (optional, default: 0)
|
|
34
33
|
* @returns ESC/POS ESC ! n command bytes
|
|
35
34
|
*/
|
|
36
|
-
export declare const calculateCharacterSize: (width: number, height: number, bold?: boolean,
|
|
35
|
+
export declare const calculateCharacterSize: (width: number, height: number, bold?: boolean, useFontB?: boolean) => number[];
|
|
37
36
|
export declare const setLineSpacing: (dots: number) => number[];
|
|
38
37
|
export declare const LINE_SPACING_DEFAULT: number[];
|
|
39
38
|
export declare const LINE_FEED: number[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"escpos.d.ts","sourceRoot":"","sources":["../../src/commands/escpos.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,eAAO,MAAM,EAAE,IAAO,CAAC;AACvB,eAAO,MAAM,EAAE,KAAO,CAAC;AACvB,eAAO,MAAM,EAAE,KAAO,CAAC;AACvB,eAAO,MAAM,EAAE,KAAO,CAAC;AACvB,eAAO,MAAM,GAAG,KAAO,CAAC;AACxB,eAAO,MAAM,GAAG,KAAO,CAAC;AACxB,eAAO,MAAM,GAAG,KAAO,CAAC;AACxB,eAAO,MAAM,EAAE,KAAO,CAAC;AACvB,eAAO,MAAM,EAAE,KAAO,CAAC;AAIvB,eAAO,MAAM,IAAI,UAAc,CAAC;AAIhC,eAAO,MAAM,UAAU,UAAoB,CAAC;AAC5C,eAAO,MAAM,YAAY,UAAoB,CAAC;AAC9C,eAAO,MAAM,WAAW,UAAoB,CAAC;AAI7C,eAAO,MAAM,OAAO,UAAoB,CAAC;AACzC,eAAO,MAAM,QAAQ,UAAoB,CAAC;AAG1C,eAAO,MAAM,YAAY,UAAoB,CAAC;AAC9C,eAAO,MAAM,aAAa,UAAoB,CAAC;AAE/C
|
|
1
|
+
{"version":3,"file":"escpos.d.ts","sourceRoot":"","sources":["../../src/commands/escpos.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,eAAO,MAAM,EAAE,IAAO,CAAC;AACvB,eAAO,MAAM,EAAE,KAAO,CAAC;AACvB,eAAO,MAAM,EAAE,KAAO,CAAC;AACvB,eAAO,MAAM,EAAE,KAAO,CAAC;AACvB,eAAO,MAAM,GAAG,KAAO,CAAC;AACxB,eAAO,MAAM,GAAG,KAAO,CAAC;AACxB,eAAO,MAAM,GAAG,KAAO,CAAC;AACxB,eAAO,MAAM,EAAE,KAAO,CAAC;AACvB,eAAO,MAAM,EAAE,KAAO,CAAC;AAIvB,eAAO,MAAM,IAAI,UAAc,CAAC;AAIhC,eAAO,MAAM,UAAU,UAAoB,CAAC;AAC5C,eAAO,MAAM,YAAY,UAAoB,CAAC;AAC9C,eAAO,MAAM,WAAW,UAAoB,CAAC;AAI7C,eAAO,MAAM,OAAO,UAAoB,CAAC;AACzC,eAAO,MAAM,QAAQ,UAAoB,CAAC;AAG1C,eAAO,MAAM,YAAY,UAAoB,CAAC;AAC9C,eAAO,MAAM,aAAa,UAAoB,CAAC;AAE/C;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,GACjC,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,OAAM,OAAe,EACrB,WAAU,OAAc,KACvB,MAAM,EA2BR,CAAC;AAKF,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,MAAM,EAGnD,CAAC;AAGF,eAAO,MAAM,oBAAoB,UAAkB,CAAC;AAIpD,eAAO,MAAM,SAAS,UAAO,CAAC;AAG9B,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,MAAM,EAAwB,CAAC;AAIzE,eAAO,MAAM,QAAQ,UAAmB,CAAC;AACzC,eAAO,MAAM,WAAW,UAAmB,CAAC;AAE5C,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,KAAG,MAAM,EAA6B,CAAC;AAKhF,eAAO,MAAM,cAAc,UAAoB,CAAC;AAChD,eAAO,MAAM,cAAc,UAAoB,CAAC;AAChD,eAAO,MAAM,gBAAgB,UAAoB,CAAC;AAMlD;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,aAAQ,KAAG,MAAM,EAyB7D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC9B,WAAW,MAAM,EAAE,EACnB,OAAO,MAAM,EACb,QAAQ,MAAM,KACb,MAAM,EA0BR,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,MAAM,EAI/C,CAAC;AAMF;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,GAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,KAAG,MAAM,EAI/D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,GAAG,CAAC,GAAG,CAAC,KAAG,MAAM,EAAoB,CAAC;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,MAAM,KAAG,MAAM,EAMtE,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,MAAM,KAAG,MAAM,EAI5D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,MAAM,KAAG,MAAM,EAI5D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,KAAG,MAAM,EAIxD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,WAAW,MAAM,EAAE,KAAG,MAAM,EAM3D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,UAAoB,CAAC;AAM5C;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,UAAoB,CAAC;AAClD,eAAO,MAAM,iBAAiB,UAAoB,CAAC;AAEnD;;GAEG;AACH,oBAAY,aAAa;IACvB,MAAM,IAAI,CAAE,uBAAuB;IACnC,MAAM,IAAI,CAAE,YAAY;IACxB,MAAM,IAAI;CACX;AAED;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,aAAa,KAAG,MAAM,EAAuB,CAAC;AAE/E;;;;GAIG;AACH,eAAO,MAAM,aAAa,UAAc,CAAC;AAEzC;;;;GAIG;AACH,eAAO,MAAM,YAAY,UAAoB,CAAC;AAC9C,eAAO,MAAM,aAAa,UAAoB,CAAC;AAE/C;;;;GAIG;AACH,eAAO,MAAM,cAAc,UAAoB,CAAC;AAChD,eAAO,MAAM,eAAe,UAAoB,CAAC;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,cAAc,UAAoB,CAAC;AAChD,eAAO,MAAM,cAAc,UAAoB,CAAC;AAMhD;;;GAGG;AACH,eAAO,MAAM,wBAAwB,UAAmB,CAAC;AAEzD;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,MAAM,EAIjD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,KAAG,MAAM,EAIxD,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,YAAY,UAAc,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,eAAe,UAAc,CAAC;AAE3C;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,MAAM,EAKnD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,MAAM,EAKtD,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,OAAO,KAAG,MAAM,EAIzD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,GACxB,WAAW,CAAC,GAAG,CAAC,EAChB,QAAQ,MAAM,EACd,SAAS,MAAM,KACd,MAAM,EAMR,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAAI,YAAY,MAAM,KAAG,MAAM,EAKlE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,YAAY,MAAM,KAAG,MAAM,EAKhE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAO,MAAM,EAA6B,CAAC;AAC1E,eAAO,MAAM,mBAAmB,QAAO,MAAM,EAA6B,CAAC;AAM3E;;GAEG;AACH,oBAAY,oBAAoB;IAC9B,GAAG,IAAI;IACP,MAAM,IAAI;IACV,OAAO,IAAI;IACX,EAAE,IAAI;IACN,SAAS,IAAI;IACb,MAAM,IAAI;IACV,KAAK,IAAI;IACT,OAAO,IAAI;IACX,KAAK,IAAI;IACT,MAAM,IAAI;IACV,UAAU,KAAK;IACf,QAAQ,KAAK;IACb,aAAa,KAAK;IAClB,KAAK,KAAK;CACX;AAED;;GAEG;AACH,eAAO,MAAM,0BAA0B,GACrC,SAAS,oBAAoB,KAC5B,MAAM,EAA0B,CAAC;AAEpC;;GAEG;AACH,oBAAY,QAAQ;IAClB,KAAK,IAAI,CAAE,uBAAuB;IAClC,KAAK,IAAI,CAAE,eAAe;IAC1B,KAAK,IAAI,CAAE,aAAa;IACxB,KAAK,IAAI,CAAE,kBAAkB;IAC7B,KAAK,IAAI,CAAE,SAAS;IACpB,KAAK,KAAK,CAAE,QAAQ;IACpB,KAAK,KAAK,CAAE,UAAU;IACtB,KAAK,KAAK,CAAE,UAAU;IACtB,KAAK,KAAK,CAAE,QAAQ;IACpB,KAAK,KAAK,CAAE,QAAQ;IACpB,KAAK,KAAK,CAAE,cAAc;IAC1B,KAAK,KAAK,CAAE,UAAU;IACtB,KAAK,KAAK,CAAE,OAAO;IACnB,OAAO,KAAK;CACb;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,QAAQ,KAAG,MAAM,EAAuB,CAAC;AAM3E;;GAEG;AACH,oBAAY,YAAY;IACtB,aAAa,IAAI,CAAE,gCAAgC;IACnD,aAAa,IAAI,CAAE,iCAAiC;IACpD,cAAc,KAAK,CAAE,kCAAkC;IACvD,cAAc,KAAK;CACpB;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,YAAY,EAClB,OAAO,MAAM,EACb,MAAM,MAAM,EAAE,KACb,MAAM,EAIR,CAAC;AAMF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,GACnC,GAAG,MAAM,EACT,GAAG,MAAM,EACT,MAAM,MAAM,EAAE,KACb,MAAM,EAIR,CAAC;AAEF;;GAEG;AACH,oBAAY,mBAAmB;IAC7B,MAAM,IAAI,CAAE,uBAAuB;IACnC,YAAY,IAAI,CAAE,6BAA6B;IAC/C,aAAa,IAAI,CAAE,8BAA8B;IACjD,SAAS,IAAI;CACd;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,mBAAmB,KACxB,MAAM,EAAsB,CAAC;AAMhC;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,aAAa,MAAM,EACnB,MAAM,mBAAmB,KACxB,MAAM,EAA+D,CAAC;AAEzE;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,KAC/D,MAAM,EAYR,CAAC;AAMF;;GAEG;AACH,oBAAY,kBAAkB;IAC5B,WAAW,IAAI,CAAE,kBAAkB;IACnC,KAAK,IAAI,CAAE,oBAAoB;IAC/B,KAAK,IAAI,CAAE,oBAAoB;IAC/B,IAAI,IAAI;CACT;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,UAAU,kBAAkB,KAAG,MAAM,EAIlE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAAM,EAIrD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,KAAG,MAAM,EAIvD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,KAAG,MAAM,EAIrD,CAAC;AAMF;;GAEG;AACH,oBAAY,WAAW;IACrB,KAAK,IAAI,CAAE,uBAAuB;IAClC,KAAK,IAAI,CAAE,qBAAqB;IAChC,KAAK,IAAI,CAAE,wBAAwB;IACnC,IAAI,IAAI,CAAE,qBAAqB;IAC/B,MAAM,IAAI,CAAE,2BAA2B;IACvC,GAAG,IAAI,CAAE,iDAAiD;IAC1D,OAAO,IAAI,CAAE,4BAA4B;IACzC,MAAM,KAAK,CAAE,2BAA2B;IACxC,OAAO,KAAK;CACb;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,WAAW,EAAE,MAAM,MAAM,KAAG,MAAM,EAGpE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GACjC,MAAM,MAAM,EACZ,MAAM,MAAM,KACX,MAAM,EAGR,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,MAAM,EAKrD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,MAAM,EAKrD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,MAAM,EAKtD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,MAAM,EAKrD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,MAAM,EAKvD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,KAAG,MAAM,EAKpD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,KAAG,MAAM,EAOxD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,MAAM,EAEvD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,KAAG,MAAM,EAExD,CAAC;AAMF;;;GAGG;AAEH;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,MAAM,KAAG,MAAM,EAGxD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,MAAM,EAGlD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAAM,EAGpD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,MAAM,KAAG,MAAM,EAGzD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,OAAO,MAAM,KAAG,MAAM,EAG9D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,KAAG,MAAM,EAKpD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,QAAO,MAAM,EASpC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EACZ,UAAU;IACR,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,KACA,MAAM,EAuBR,CAAC;AAMF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,iBAAiB,MAAM,EACvB,kBAAkB,MAAM,KACvB,MAAM,EAKR,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,UAAmB,CAAC;AACjD,eAAO,MAAM,iBAAiB,UAAmB,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,CAAC,GAAG,CAAC,KAAG,MAAM,EAQtD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,SAAS,OAAO,KAAG,MAAM,EAQ9D,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,SAAS,GAAI,YAAY,MAAM,KAAG,MAAM,EAIpD,CAAC;AAEF,eAAO,MAAM,UAAU,QAAO,MAAM,EAAsB,CAAC;AAE3D;;GAEG;AACH,oBAAY,aAAa;IACvB,aAAa,IAAI,CAAE,mBAAmB;IACtC,OAAO,IAAI,CAAE,UAAU;IACvB,WAAW,KAAK,CAAE,iBAAiB;IACnC,SAAS,KAAK,CAAE,0BAA0B;IAC1C,YAAY,KAAK;CAClB;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,aAAa,KAAG,MAAM,EAI5D,CAAC;AAEF;;GAEG;AACH,oBAAY,UAAU;IACpB,YAAY,IAAI,CAAE,sBAAsB;IACxC,aAAa,IAAI,CAAE,mCAAmC;IACtD,UAAU,IAAI,CAAE,kCAAkC;IAClD,iBAAiB,KAAK;CACvB;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,UAAU,KAAG,MAAM,EAAsB,CAAC;AAM9E;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,MAAM,EAIlD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,MAAM,EAIzD,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,WAAW,UAAa,CAAC;AACtC,eAAO,MAAM,SAAS,UAAa,CAAC;AAEpC;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GACvB,aAAa,MAAM,EACnB,UAAU,MAAM,EAChB,MAAM,CAAC,GAAG,CAAC,KACV,MAAM,EAMR,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,UAAoB,CAAC;AACnD,eAAO,MAAM,kBAAkB,UAAoB,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,MAAM,UAAQ,CAAC;AAE5B;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAC3B,SAAS,MAAM,EACf,MAAM,MAAM,EACZ,QAAQ,MAAM,KACb,MAAM,EAUR,CAAC"}
|
package/dist/commands/escpos.js
CHANGED
|
@@ -41,17 +41,17 @@ export const UNDERLINE_OFF = [ESC, 0x2d, 0x00];
|
|
|
41
41
|
* @param width - Width multiplier (1 or 2)
|
|
42
42
|
* @param height - Height multiplier (1 or 2)
|
|
43
43
|
* @param bold - Whether text should be bold (optional, default: false)
|
|
44
|
-
* @param font - Font selection: 0 = Font A (12x24), 1 = Font B (9x17) (optional, default: 0)
|
|
45
44
|
* @returns ESC/POS ESC ! n command bytes
|
|
46
45
|
*/
|
|
47
|
-
export const calculateCharacterSize = (width, height, bold = false,
|
|
46
|
+
export const calculateCharacterSize = (width, height, bold = false, useFontB = true) => {
|
|
48
47
|
// ESC ! command format:
|
|
49
48
|
// Bit 0: Character font (0=Font A, 1=Font B)
|
|
50
49
|
// Bit 3: Emphasis (bold)
|
|
51
50
|
// Bit 4: Double-height
|
|
52
51
|
// Bit 5: Double-width
|
|
53
52
|
// Bit 7: Underline
|
|
54
|
-
|
|
53
|
+
// Font selection: Font A (12×24, 48 cols) or Font B (9×17, 64 cols)
|
|
54
|
+
let n = useFontB ? 0x01 : 0x00;
|
|
55
55
|
// Set double-height bit (bit 4 = 0x10)
|
|
56
56
|
if (height >= 2) {
|
|
57
57
|
n |= 0x10;
|
|
@@ -68,6 +68,7 @@ export const calculateCharacterSize = (width, height, bold = false, font = 0) =>
|
|
|
68
68
|
};
|
|
69
69
|
// Line spacing
|
|
70
70
|
// ESC 3 n - Set line spacing to n dots
|
|
71
|
+
// n=0 means no extra spacing (just character height)
|
|
71
72
|
export const setLineSpacing = (dots) => {
|
|
72
73
|
const value = Math.max(0, Math.min(255, dots));
|
|
73
74
|
return [ESC, 0x33, value];
|
package/dist/converter.d.ts
CHANGED
|
@@ -3,6 +3,14 @@ import { CommandAdapter } from './command-adapters';
|
|
|
3
3
|
/**
|
|
4
4
|
* Options for converting PrintNodes to ESC/POS commands
|
|
5
5
|
*/
|
|
6
|
+
/**
|
|
7
|
+
* Font mode for ESC/POS output.
|
|
8
|
+
* Controls which ESC/POS font is used globally, ignoring component fontSize.
|
|
9
|
+
*
|
|
10
|
+
* - "small": Font B 1x1 (56 columns on 80mm paper)
|
|
11
|
+
* - "medium": Font A 1x1 (42 columns on 80mm paper) — default
|
|
12
|
+
*/
|
|
13
|
+
export type FontMode = 'small' | 'medium';
|
|
6
14
|
export interface PrintNodeToESCPOSOptions {
|
|
7
15
|
paperWidth?: number;
|
|
8
16
|
encoding?: string;
|
|
@@ -10,7 +18,8 @@ export interface PrintNodeToESCPOSOptions {
|
|
|
10
18
|
cut?: boolean | 'full' | 'partial';
|
|
11
19
|
feedBeforeCut?: number;
|
|
12
20
|
commandAdapter?: CommandAdapter | 'escpos' | 'escbematech';
|
|
13
|
-
|
|
21
|
+
fontMode?: FontMode;
|
|
22
|
+
compact?: boolean;
|
|
14
23
|
}
|
|
15
24
|
/**
|
|
16
25
|
* Converts PrintNode tree to ESC/POS buffer
|
package/dist/converter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../src/converter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EAAE,cAAc,EAAmD,MAAM,oBAAoB,CAAC;AAErG;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,cAAc,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC3D,
|
|
1
|
+
{"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../src/converter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EAAE,cAAc,EAAmD,MAAM,oBAAoB,CAAC;AAErG;;GAEG;AACH;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1C,MAAM,WAAW,wBAAwB;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,cAAc,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC3D,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA2BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,MAAM,CAAC,CAqDjB"}
|
package/dist/converter.js
CHANGED
|
@@ -56,22 +56,32 @@ function createCommandAdapter(config) {
|
|
|
56
56
|
* ```
|
|
57
57
|
*/
|
|
58
58
|
export async function printNodesToESCPOS(printNode, options) {
|
|
59
|
-
const { paperWidth =
|
|
60
|
-
encoding = "utf-8", debug = false, cut = "full", // Default to full cut
|
|
59
|
+
const { paperWidth: paperWidthOverride, encoding = "utf-8", debug = false, cut = "full", // Default to full cut
|
|
61
60
|
feedBeforeCut = 3, // Default to 3 lines feed before cut
|
|
62
61
|
commandAdapter: commandAdapterConfig, // Command protocol adapter
|
|
63
|
-
|
|
62
|
+
fontMode = "medium", // Default to Font A 42 cols
|
|
63
|
+
compact = false, // Minimal line spacing
|
|
64
64
|
} = options || {};
|
|
65
|
+
// Determine paperWidth based on fontMode (unless explicitly overridden)
|
|
66
|
+
// Values calibrated for 80mm thermal printers (e.g., MP-4200 TH):
|
|
67
|
+
// Font A (medium): 42 chars per line
|
|
68
|
+
// Font B (small): 56 chars per line
|
|
69
|
+
const fontModePaperWidths = {
|
|
70
|
+
small: 56,
|
|
71
|
+
medium: 42,
|
|
72
|
+
};
|
|
73
|
+
const paperWidth = paperWidthOverride ?? fontModePaperWidths[fontMode] ?? 42;
|
|
65
74
|
// Create command adapter (defaults to ESC/POS if not provided)
|
|
66
75
|
const commandAdapter = createCommandAdapter(commandAdapterConfig);
|
|
67
76
|
if (debug) {
|
|
68
77
|
console.log(`Using command adapter: ${commandAdapter.getName()}`);
|
|
78
|
+
console.log(`Font mode: ${fontMode} (paperWidth: ${paperWidth})`);
|
|
69
79
|
console.log("\n========== PRINT NODE TREE (JSON) ==========");
|
|
70
80
|
console.log(JSON.stringify(printNode, null, 2));
|
|
71
81
|
console.log("============================================\n");
|
|
72
82
|
}
|
|
73
|
-
// Create ESC/POS generator with command adapter
|
|
74
|
-
const generator = new ESCPOSGenerator(paperWidth, encoding, debug, commandAdapter,
|
|
83
|
+
// Create ESC/POS generator with command adapter, font mode and compact flag
|
|
84
|
+
const generator = new ESCPOSGenerator(paperWidth, encoding, debug, commandAdapter, fontMode, compact);
|
|
75
85
|
// Traverse tree and generate commands
|
|
76
86
|
const traverser = new TreeTraverser(generator);
|
|
77
87
|
await traverser.traverse(printNode);
|
package/dist/generator.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { FontMode } from "./converter";
|
|
1
2
|
import { CommandAdapter } from "./command-adapters";
|
|
2
3
|
/**
|
|
3
4
|
* ESC/POS Command Generator
|
|
@@ -8,8 +9,9 @@ export declare class ESCPOSGenerator {
|
|
|
8
9
|
private buffer;
|
|
9
10
|
private context;
|
|
10
11
|
private commandAdapter;
|
|
11
|
-
private
|
|
12
|
-
|
|
12
|
+
private fontMode;
|
|
13
|
+
private compact;
|
|
14
|
+
constructor(paperWidth?: number, encoding?: string, debug?: boolean, commandAdapter?: CommandAdapter, fontMode?: FontMode, compact?: boolean);
|
|
13
15
|
/**
|
|
14
16
|
* Initialize printer
|
|
15
17
|
* Sets up the printer with default settings and comfortable line spacing
|
|
@@ -30,23 +32,17 @@ export declare class ESCPOSGenerator {
|
|
|
30
32
|
*/
|
|
31
33
|
setBold(bold: boolean): void;
|
|
32
34
|
/**
|
|
33
|
-
* Set text size using width
|
|
34
|
-
* Uses ESC ! command which combines size
|
|
35
|
-
* @param size - Character size
|
|
35
|
+
* Set text size using width and height multipliers
|
|
36
|
+
* Uses ESC ! command which combines size and emphasis
|
|
37
|
+
* @param size - Character size as {width, height} multipliers (max 2x2 for ESC !)
|
|
36
38
|
*/
|
|
37
39
|
setSize(size: {
|
|
38
40
|
width: number;
|
|
39
41
|
height: number;
|
|
40
|
-
font?: 0 | 1;
|
|
41
42
|
}): void;
|
|
42
43
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*/
|
|
46
|
-
private updatePaperWidth;
|
|
47
|
-
/**
|
|
48
|
-
* Apply current print mode (font + size + bold) using command adapter
|
|
49
|
-
* This combines font selection, character size, and emphasis into a single command
|
|
44
|
+
* Apply current print mode (size + bold + font) using command adapter.
|
|
45
|
+
* Uses fontMode to determine Font A vs Font B base.
|
|
50
46
|
*/
|
|
51
47
|
private applyPrintMode;
|
|
52
48
|
/**
|
|
@@ -59,7 +55,8 @@ export declare class ESCPOSGenerator {
|
|
|
59
55
|
*/
|
|
60
56
|
addText(text: string): void;
|
|
61
57
|
/**
|
|
62
|
-
* Add newline using command adapter
|
|
58
|
+
* Add newline using command adapter.
|
|
59
|
+
* In compact mode, skips if the buffer already ends with a LF (prevents double spacing).
|
|
63
60
|
*/
|
|
64
61
|
addNewline(count?: number): void;
|
|
65
62
|
/**
|
|
@@ -67,9 +64,14 @@ export declare class ESCPOSGenerator {
|
|
|
67
64
|
*/
|
|
68
65
|
addLineFeed(lines?: number): void;
|
|
69
66
|
/**
|
|
70
|
-
* Add divider line
|
|
67
|
+
* Add divider line.
|
|
68
|
+
* In compact mode, avoids emitting a leading LF if the buffer already ends with one.
|
|
71
69
|
*/
|
|
72
70
|
addDivider(dashed?: boolean): void;
|
|
71
|
+
/**
|
|
72
|
+
* Check if the last byte in the buffer is a LF
|
|
73
|
+
*/
|
|
74
|
+
lastByteIsLF(): boolean;
|
|
73
75
|
/**
|
|
74
76
|
* Add QR code using command adapter
|
|
75
77
|
*/
|
|
@@ -83,9 +85,17 @@ export declare class ESCPOSGenerator {
|
|
|
83
85
|
uri: string;
|
|
84
86
|
}): Promise<void>;
|
|
85
87
|
/**
|
|
86
|
-
* Apply text styles from style object
|
|
88
|
+
* Apply text styles from style object.
|
|
89
|
+
* When fontMode is set, fontSize from components is IGNORED for font selection.
|
|
90
|
+
* The fontMode determines the global ESC/POS font (small/medium/large).
|
|
87
91
|
*/
|
|
88
92
|
applyTextStyle(style: any): void;
|
|
93
|
+
/**
|
|
94
|
+
* Get the ESC/POS character size based on the global fontMode.
|
|
95
|
+
* - small: Font B 1x1 (64 cols)
|
|
96
|
+
* - medium: Font A 1x1 (48 cols)
|
|
97
|
+
*/
|
|
98
|
+
private getFontModeSize;
|
|
89
99
|
/**
|
|
90
100
|
* Apply spacing from view style
|
|
91
101
|
*/
|
package/dist/generator.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAwB,MAAM,oBAAoB,CAAC;AA4C1E;;;;GAIG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,OAAO,CAAU;gBAGvB,UAAU,SAAK,EACf,QAAQ,SAAU,EAClB,KAAK,UAAQ,EACb,cAAc,CAAC,EAAE,cAAc,EAC/B,QAAQ,GAAE,QAAmB,EAC7B,OAAO,UAAQ;IAyBjB;;;OAGG;IACH,UAAU,IAAI,IAAI;IAWlB;;;OAGG;IACH,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAKnC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,IAAI;IAQlD;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAO5B;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAWtD;;;OAGG;IACH,OAAO,CAAC,cAAc;IAYtB;;;OAGG;IACH,eAAe,IAAI,IAAI;IAMvB;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ3B;;;OAGG;IACH,UAAU,CAAC,KAAK,SAAI,GAAG,IAAI;IAQ3B;;OAEG;IACH,WAAW,CAAC,KAAK,SAAI,GAAG,IAAI;IAK5B;;;OAGG;IACH,UAAU,CAAC,MAAM,UAAQ,GAAG,IAAI;IAOhC;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAI,GAAG,IAAI;IAYvC;;;;OAIG;IACG,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA2F/D;;;;OAIG;IACH,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAgBhC;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACH,gBAAgB,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI;IAgB5D;;OAEG;IACH,OAAO,IAAI,IAAI;IAKf;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;;OAGG;IACH,eAAe,CAAC,KAAK,SAAI,GAAG,IAAI;IAMhC;;;OAGG;IACH,kBAAkB,CAAC,KAAK,SAAI,GAAG,IAAI;IAMnC;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIjC;;OAEG;IACH,SAAS,IAAI,MAAM;IAYnB;;OAEG;IACH,aAAa,IAAI,MAAM;CAGxB"}
|
package/dist/generator.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { encodeText } from "./commands/escpos";
|
|
2
|
-
import { extractTextStyle, extractViewStyle, generateDividerLine, isBold, isDashedBorder,
|
|
2
|
+
import { extractTextStyle, extractViewStyle, generateDividerLine, isBold, isDashedBorder, mapTextAlign, } from "./styles";
|
|
3
3
|
import { ESCPOSCommandAdapter } from "./command-adapters";
|
|
4
4
|
/**
|
|
5
5
|
* Simple buffer implementation for accumulating ESC/POS commands
|
|
@@ -32,6 +32,12 @@ class ESCPOSBuffer {
|
|
|
32
32
|
get size() {
|
|
33
33
|
return this.buffer.length;
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Get the last byte in the buffer
|
|
37
|
+
*/
|
|
38
|
+
lastByte() {
|
|
39
|
+
return this.buffer.length > 0 ? this.buffer[this.buffer.length - 1] : undefined;
|
|
40
|
+
}
|
|
35
41
|
}
|
|
36
42
|
/**
|
|
37
43
|
* ESC/POS Command Generator
|
|
@@ -39,11 +45,12 @@ class ESCPOSBuffer {
|
|
|
39
45
|
* Pure JavaScript implementation - no Node.js dependencies
|
|
40
46
|
*/
|
|
41
47
|
export class ESCPOSGenerator {
|
|
42
|
-
constructor(paperWidth =
|
|
48
|
+
constructor(paperWidth = 42, encoding = "cp860", debug = false, commandAdapter, fontMode = "medium", compact = false) {
|
|
49
|
+
this.fontMode = fontMode;
|
|
50
|
+
this.compact = compact;
|
|
43
51
|
this.buffer = new ESCPOSBuffer();
|
|
44
52
|
// Use provided adapter or default to ESC/POS
|
|
45
53
|
this.commandAdapter = commandAdapter || new ESCPOSCommandAdapter();
|
|
46
|
-
this.lineSpacing = lineSpacing;
|
|
47
54
|
this.context = {
|
|
48
55
|
paperWidth,
|
|
49
56
|
basePaperWidth: paperWidth,
|
|
@@ -63,9 +70,12 @@ export class ESCPOSGenerator {
|
|
|
63
70
|
* Sets up the printer with default settings and comfortable line spacing
|
|
64
71
|
*/
|
|
65
72
|
initialize() {
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
//
|
|
73
|
+
// Line spacing:
|
|
74
|
+
// - compact=true: 5 dots (tightest practical spacing)
|
|
75
|
+
// - compact=false: default spacing (ESC 2)
|
|
76
|
+
const lineSpacing = this.compact ? 1 : undefined;
|
|
77
|
+
this.setLineSpacing(lineSpacing);
|
|
78
|
+
// Apply initial print mode
|
|
69
79
|
this.applyPrintMode();
|
|
70
80
|
}
|
|
71
81
|
/**
|
|
@@ -97,46 +107,26 @@ export class ESCPOSGenerator {
|
|
|
97
107
|
}
|
|
98
108
|
}
|
|
99
109
|
/**
|
|
100
|
-
* Set text size using width
|
|
101
|
-
* Uses ESC ! command which combines size
|
|
102
|
-
* @param size - Character size
|
|
110
|
+
* Set text size using width and height multipliers
|
|
111
|
+
* Uses ESC ! command which combines size and emphasis
|
|
112
|
+
* @param size - Character size as {width, height} multipliers (max 2x2 for ESC !)
|
|
103
113
|
*/
|
|
104
114
|
setSize(size) {
|
|
105
|
-
|
|
106
|
-
// Only update if size or font actually changed
|
|
115
|
+
// Only update if size actually changed
|
|
107
116
|
if (this.context.currentSize.width !== size.width ||
|
|
108
|
-
this.context.currentSize.height !== size.height
|
|
109
|
-
this.context.currentFont !== font) {
|
|
117
|
+
this.context.currentSize.height !== size.height) {
|
|
110
118
|
this.context.currentSize = size;
|
|
111
|
-
this.context.currentFont = font;
|
|
112
|
-
this.updatePaperWidth();
|
|
113
119
|
this.applyPrintMode();
|
|
114
120
|
}
|
|
115
121
|
}
|
|
116
122
|
/**
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*/
|
|
120
|
-
updatePaperWidth() {
|
|
121
|
-
if (this.context.currentFont === 1) {
|
|
122
|
-
// Font B: 64 cols
|
|
123
|
-
this.context.paperWidth = 64;
|
|
124
|
-
}
|
|
125
|
-
else if (this.context.currentSize.width >= 2) {
|
|
126
|
-
// Font A double-width: 24 cols
|
|
127
|
-
this.context.paperWidth = Math.floor(this.context.basePaperWidth / 2);
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
// Font A normal: 48 cols (basePaperWidth)
|
|
131
|
-
this.context.paperWidth = this.context.basePaperWidth;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Apply current print mode (font + size + bold) using command adapter
|
|
136
|
-
* This combines font selection, character size, and emphasis into a single command
|
|
123
|
+
* Apply current print mode (size + bold + font) using command adapter.
|
|
124
|
+
* Uses fontMode to determine Font A vs Font B base.
|
|
137
125
|
*/
|
|
138
126
|
applyPrintMode() {
|
|
139
|
-
|
|
127
|
+
// For "small" mode, use Font B (bit 0 = 1). For "medium", use Font A (bit 0 = 0).
|
|
128
|
+
const useFontB = this.fontMode === "small";
|
|
129
|
+
const command = this.commandAdapter.getCharacterSizeCommand(this.context.currentSize.width, this.context.currentSize.height, this.context.currentBold, useFontB);
|
|
140
130
|
this.buffer.pushArray(command);
|
|
141
131
|
}
|
|
142
132
|
/**
|
|
@@ -146,7 +136,7 @@ export class ESCPOSGenerator {
|
|
|
146
136
|
resetFormatting() {
|
|
147
137
|
this.setAlign("left");
|
|
148
138
|
this.setBold(false);
|
|
149
|
-
this.setSize({ width: 1, height: 1
|
|
139
|
+
this.setSize({ width: 1, height: 1 });
|
|
150
140
|
}
|
|
151
141
|
/**
|
|
152
142
|
* Add text with current formatting
|
|
@@ -159,9 +149,13 @@ export class ESCPOSGenerator {
|
|
|
159
149
|
}
|
|
160
150
|
}
|
|
161
151
|
/**
|
|
162
|
-
* Add newline using command adapter
|
|
152
|
+
* Add newline using command adapter.
|
|
153
|
+
* In compact mode, skips if the buffer already ends with a LF (prevents double spacing).
|
|
163
154
|
*/
|
|
164
155
|
addNewline(count = 1) {
|
|
156
|
+
if (this.compact && count === 1 && this.buffer.lastByte() === 0x0a) {
|
|
157
|
+
return; // Skip duplicate LF in compact mode
|
|
158
|
+
}
|
|
165
159
|
const command = this.commandAdapter.getLineFeedCommand(count);
|
|
166
160
|
this.buffer.pushArray(command);
|
|
167
161
|
}
|
|
@@ -173,7 +167,8 @@ export class ESCPOSGenerator {
|
|
|
173
167
|
this.buffer.pushArray(command);
|
|
174
168
|
}
|
|
175
169
|
/**
|
|
176
|
-
* Add divider line
|
|
170
|
+
* Add divider line.
|
|
171
|
+
* In compact mode, avoids emitting a leading LF if the buffer already ends with one.
|
|
177
172
|
*/
|
|
178
173
|
addDivider(dashed = false) {
|
|
179
174
|
this.setAlign("left");
|
|
@@ -181,6 +176,12 @@ export class ESCPOSGenerator {
|
|
|
181
176
|
this.addText(line);
|
|
182
177
|
this.addNewline();
|
|
183
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Check if the last byte in the buffer is a LF
|
|
181
|
+
*/
|
|
182
|
+
lastByteIsLF() {
|
|
183
|
+
return this.buffer.lastByte() === 0x0a;
|
|
184
|
+
}
|
|
184
185
|
/**
|
|
185
186
|
* Add QR code using command adapter
|
|
186
187
|
*/
|
|
@@ -277,7 +278,9 @@ export class ESCPOSGenerator {
|
|
|
277
278
|
}
|
|
278
279
|
}
|
|
279
280
|
/**
|
|
280
|
-
* Apply text styles from style object
|
|
281
|
+
* Apply text styles from style object.
|
|
282
|
+
* When fontMode is set, fontSize from components is IGNORED for font selection.
|
|
283
|
+
* The fontMode determines the global ESC/POS font (small/medium/large).
|
|
281
284
|
*/
|
|
282
285
|
applyTextStyle(style) {
|
|
283
286
|
const textStyle = extractTextStyle(style);
|
|
@@ -287,10 +290,18 @@ export class ESCPOSGenerator {
|
|
|
287
290
|
// Set bold
|
|
288
291
|
const bold = isBold(textStyle);
|
|
289
292
|
this.setBold(bold);
|
|
290
|
-
//
|
|
291
|
-
const size =
|
|
293
|
+
// Font mode determines the fixed size — fontSize from components is ignored
|
|
294
|
+
const size = this.getFontModeSize();
|
|
292
295
|
this.setSize(size);
|
|
293
296
|
}
|
|
297
|
+
/**
|
|
298
|
+
* Get the ESC/POS character size based on the global fontMode.
|
|
299
|
+
* - small: Font B 1x1 (64 cols)
|
|
300
|
+
* - medium: Font A 1x1 (48 cols)
|
|
301
|
+
*/
|
|
302
|
+
getFontModeSize() {
|
|
303
|
+
return { width: 1, height: 1 };
|
|
304
|
+
}
|
|
294
305
|
/**
|
|
295
306
|
* Apply spacing from view style
|
|
296
307
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Main API: printNodesToESCPOS(printNode, options) -> Buffer
|
|
7
7
|
*/
|
|
8
8
|
export { printNodesToESCPOS } from './converter';
|
|
9
|
-
export type { PrintNodeToESCPOSOptions } from './converter';
|
|
9
|
+
export type { PrintNodeToESCPOSOptions, FontMode } from './converter';
|
|
10
10
|
export { ESCPOSGenerator } from './generator';
|
|
11
11
|
export { TreeTraverser } from './traverser';
|
|
12
12
|
export type { CommandAdapter, CharacterSize } from './command-adapters/types';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,wBAAwB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGtE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAGnF,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,EACN,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,QAAQ,GACT,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,mBAAmB,SAAS,CAAC"}
|
package/dist/traverser.d.ts
CHANGED
|
@@ -37,11 +37,13 @@ export declare class TreeTraverser {
|
|
|
37
37
|
*/
|
|
38
38
|
private findFirstTextNode;
|
|
39
39
|
/**
|
|
40
|
-
* Collect text content from a node and its children
|
|
40
|
+
* Collect text content from a node and its children.
|
|
41
|
+
* Returns lines separated by \n when nested column Views contain multiple Text elements.
|
|
41
42
|
*/
|
|
42
43
|
private collectTextContent;
|
|
43
44
|
/**
|
|
44
45
|
* Handle Text element
|
|
46
|
+
* Collects ALL text (props + nested children) then applies word wrap
|
|
45
47
|
*/
|
|
46
48
|
private handleText;
|
|
47
49
|
/**
|
package/dist/traverser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traverser.d.ts","sourceRoot":"","sources":["../src/traverser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAkB;gBAEvB,SAAS,EAAE,eAAe;IAItC;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BvD;;OAEG;YACW,cAAc;IAO5B;;OAEG;YACW,UAAU;IAIxB;;OAEG;YACW,UAAU;IAkBxB;;;OAGG;YACW,kBAAkB;IAchC;;OAEG;YACW,eAAe;
|
|
1
|
+
{"version":3,"file":"traverser.d.ts","sourceRoot":"","sources":["../src/traverser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAkB;gBAEvB,SAAS,EAAE,eAAe;IAItC;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BvD;;OAEG;YACW,cAAc;IAO5B;;OAEG;YACW,UAAU;IAIxB;;OAEG;YACW,UAAU;IAkBxB;;;OAGG;YACW,kBAAkB;IAchC;;OAEG;YACW,eAAe;IA4G7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAczB;;;OAGG;YACW,kBAAkB;IAyChC;;;OAGG;YACW,UAAU;IA6BxB;;OAEG;YACW,cAAc;IAM5B;;OAEG;YACW,WAAW;IA+BzB;;OAEG;YACW,gBAAgB;CAK/B"}
|
package/dist/traverser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { alignTextInColumn, extractTextStyle, extractViewStyle,
|
|
1
|
+
import { alignTextInColumn, extractTextStyle, extractViewStyle, mapTextAlign, mergeStyles, parseWidth, wrapText } from "./styles";
|
|
2
2
|
/**
|
|
3
3
|
* Tree Traverser
|
|
4
4
|
* Walks through the element tree and generates ESC/POS commands
|
|
@@ -101,6 +101,7 @@ export class TreeTraverser {
|
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
const viewStyle = extractViewStyle(node.style);
|
|
104
|
+
const paperWidth = this.generator.getPaperWidth();
|
|
104
105
|
// Check layout justification mode
|
|
105
106
|
const isSpaceBetween = viewStyle.justifyContent === "space-between";
|
|
106
107
|
const isCentered = viewStyle.justifyContent === "center";
|
|
@@ -113,40 +114,21 @@ export class TreeTraverser {
|
|
|
113
114
|
if (firstTextNode && firstTextNode.style) {
|
|
114
115
|
rowTextStyle = mergeStyles(firstTextNode.style);
|
|
115
116
|
}
|
|
116
|
-
// Calculate effective paper width based on the row's font/size
|
|
117
|
-
let paperWidth = this.generator.getPaperWidth();
|
|
118
|
-
if (rowTextStyle) {
|
|
119
|
-
const rowFontSize = mapFontSizeToESCPOS(rowTextStyle.fontSize);
|
|
120
|
-
if (rowFontSize.font === 1) {
|
|
121
|
-
paperWidth = 64; // Font B: 64 cols
|
|
122
|
-
}
|
|
123
|
-
else if (rowFontSize.width >= 2) {
|
|
124
|
-
paperWidth = Math.floor(this.generator.getPaperWidth() / 2); // Font A 2x: 24 cols
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
paperWidth = 48; // Font A normal: 48 cols
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
// First pass: calculate explicit widths and track remaining space
|
|
131
|
-
let usedWidth = 0;
|
|
132
|
-
let columnsWithoutWidth = 0;
|
|
133
|
-
const childData = [];
|
|
134
117
|
for (const child of children) {
|
|
135
118
|
const childStyle = extractViewStyle(child.style);
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
if (hasWidth)
|
|
139
|
-
usedWidth += explicitWidth;
|
|
140
|
-
else
|
|
141
|
-
columnsWithoutWidth++;
|
|
119
|
+
const width = parseWidth(childStyle.width, paperWidth);
|
|
120
|
+
// Collect text content from child
|
|
142
121
|
const content = await this.collectTextContent(child);
|
|
122
|
+
// Determine alignment - check for Text node textAlign first
|
|
143
123
|
let align = "left";
|
|
124
|
+
// Look for Text element with textAlign
|
|
144
125
|
const textNode = this.findFirstTextNode(child);
|
|
145
126
|
if (textNode && textNode.style) {
|
|
146
127
|
const textStyle = extractTextStyle(textNode.style);
|
|
147
128
|
align = mapTextAlign(textStyle.textAlign);
|
|
148
129
|
}
|
|
149
130
|
else {
|
|
131
|
+
// Fall back to View alignment
|
|
150
132
|
if (childStyle.alignItems === "center" || childStyle.justifyContent === "center") {
|
|
151
133
|
align = "center";
|
|
152
134
|
}
|
|
@@ -154,61 +136,50 @@ export class TreeTraverser {
|
|
|
154
136
|
align = "right";
|
|
155
137
|
}
|
|
156
138
|
}
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
// Second pass: distribute remaining width to columns without explicit widths
|
|
160
|
-
const remainingWidth = Math.max(0, paperWidth - usedWidth);
|
|
161
|
-
const autoWidth = columnsWithoutWidth > 0 ? Math.floor(remainingWidth / columnsWithoutWidth) : paperWidth;
|
|
162
|
-
for (const data of childData) {
|
|
163
|
-
const width = data.hasWidth ? data.explicitWidth : autoWidth;
|
|
164
|
-
columns.push({ node: data.node, width, content: data.content, align: data.align });
|
|
139
|
+
columns.push({ node: child, width, content, align });
|
|
165
140
|
}
|
|
166
|
-
// Build row text
|
|
167
|
-
let rowText = "";
|
|
168
141
|
// Check if columns have explicit widths (table layout) or should use space-between
|
|
169
142
|
const hasExplicitWidths = columns.some((col) => {
|
|
170
143
|
const childStyle = extractViewStyle(col.node.style);
|
|
171
144
|
return childStyle.width !== undefined;
|
|
172
145
|
});
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
rowText = columns[0].content + " ".repeat(gap) + columns[1].content;
|
|
146
|
+
// Determine max number of sub-lines across all columns
|
|
147
|
+
const columnLines = columns.map(col => col.content.split("\n"));
|
|
148
|
+
const maxLines = Math.max(...columnLines.map(lines => lines.length));
|
|
149
|
+
// Apply text style (bold, fontSize) before adding the row text
|
|
150
|
+
if (rowTextStyle) {
|
|
151
|
+
this.generator.applyTextStyle(rowTextStyle);
|
|
180
152
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
153
|
+
// Emit one output line per sub-line
|
|
154
|
+
for (let lineIdx = 0; lineIdx < maxLines; lineIdx++) {
|
|
155
|
+
let rowText = "";
|
|
156
|
+
if (isSpaceBetween && columns.length === 2 && !hasExplicitWidths) {
|
|
157
|
+
const left = (columnLines[0][lineIdx] || "");
|
|
158
|
+
const right = (columnLines[1][lineIdx] || "");
|
|
159
|
+
const usedSpace = left.length + right.length;
|
|
160
|
+
const gap = Math.max(1, paperWidth - usedSpace);
|
|
161
|
+
rowText = left + " ".repeat(gap) + right;
|
|
162
|
+
}
|
|
163
|
+
else if (isCentered && !hasExplicitWidths) {
|
|
164
|
+
const parts = [];
|
|
165
|
+
for (let i = 0; i < columns.length; i++) {
|
|
166
|
+
parts.push(columnLines[i][lineIdx] || "");
|
|
194
167
|
}
|
|
195
|
-
|
|
168
|
+
const spacingBetweenColumns = Math.max(0, columns.length - 1);
|
|
169
|
+
const totalContentWidth = parts.reduce((sum, p) => sum + p.length, 0) + spacingBetweenColumns;
|
|
170
|
+
const leadingSpaces = Math.max(0, Math.floor((paperWidth - totalContentWidth) / 2));
|
|
171
|
+
rowText = " ".repeat(leadingSpaces) + parts.join(" ");
|
|
196
172
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
rowText += cellText;
|
|
173
|
+
else {
|
|
174
|
+
for (let i = 0; i < columns.length; i++) {
|
|
175
|
+
const cellContent = columnLines[i][lineIdx] || "";
|
|
176
|
+
const cellText = alignTextInColumn(cellContent, columns[i].width, columns[i].align);
|
|
177
|
+
rowText += cellText;
|
|
178
|
+
}
|
|
204
179
|
}
|
|
180
|
+
this.generator.addText(rowText);
|
|
181
|
+
this.generator.addNewline();
|
|
205
182
|
}
|
|
206
|
-
// Apply text style (bold, fontSize) before adding the row text
|
|
207
|
-
if (rowTextStyle) {
|
|
208
|
-
this.generator.applyTextStyle(rowTextStyle);
|
|
209
|
-
}
|
|
210
|
-
this.generator.addText(rowText);
|
|
211
|
-
this.generator.addNewline();
|
|
212
183
|
// Reset formatting after the row
|
|
213
184
|
if (rowTextStyle) {
|
|
214
185
|
this.generator.resetFormatting();
|
|
@@ -230,50 +201,70 @@ export class TreeTraverser {
|
|
|
230
201
|
return null;
|
|
231
202
|
}
|
|
232
203
|
/**
|
|
233
|
-
* Collect text content from a node and its children
|
|
204
|
+
* Collect text content from a node and its children.
|
|
205
|
+
* Returns lines separated by \n when nested column Views contain multiple Text elements.
|
|
234
206
|
*/
|
|
235
207
|
async collectTextContent(node) {
|
|
236
|
-
let text = "";
|
|
237
208
|
const normalizedType = node.type.toLowerCase();
|
|
238
|
-
if (normalizedType === "
|
|
239
|
-
|
|
209
|
+
if (normalizedType === "textnode") {
|
|
210
|
+
if (node.props.children !== undefined) {
|
|
211
|
+
return String(node.props.children);
|
|
212
|
+
}
|
|
213
|
+
return "";
|
|
214
|
+
}
|
|
215
|
+
if (normalizedType === "text") {
|
|
216
|
+
// Collect all nested text into one string (inline)
|
|
217
|
+
let text = "";
|
|
240
218
|
if (node.props.children !== undefined) {
|
|
241
219
|
text += String(node.props.children);
|
|
242
220
|
}
|
|
221
|
+
for (const child of node.children) {
|
|
222
|
+
text += await this.collectTextContent(child);
|
|
223
|
+
}
|
|
224
|
+
return text;
|
|
243
225
|
}
|
|
244
|
-
//
|
|
226
|
+
// For View nodes: check if it's a column layout with multiple children
|
|
227
|
+
// If so, join children with \n (each child = separate line)
|
|
228
|
+
const viewStyle = extractViewStyle(node.style);
|
|
229
|
+
const isColumn = viewStyle.flexDirection !== "row";
|
|
230
|
+
const parts = [];
|
|
245
231
|
for (const child of node.children) {
|
|
246
|
-
|
|
232
|
+
const childText = await this.collectTextContent(child);
|
|
233
|
+
if (childText) {
|
|
234
|
+
parts.push(childText);
|
|
235
|
+
}
|
|
247
236
|
}
|
|
248
|
-
|
|
237
|
+
if (isColumn && parts.length > 1) {
|
|
238
|
+
return parts.join("\n");
|
|
239
|
+
}
|
|
240
|
+
return parts.join("");
|
|
249
241
|
}
|
|
250
242
|
/**
|
|
251
243
|
* Handle Text element
|
|
244
|
+
* Collects ALL text (props + nested children) then applies word wrap
|
|
252
245
|
*/
|
|
253
246
|
async handleText(node) {
|
|
254
247
|
// Merge styles from parent if needed
|
|
255
248
|
const style = mergeStyles(node.style);
|
|
256
249
|
// Apply text styling (sets alignment, bold, size)
|
|
257
250
|
this.generator.applyTextStyle(style);
|
|
258
|
-
//
|
|
259
|
-
|
|
260
|
-
//
|
|
261
|
-
if (
|
|
262
|
-
|
|
263
|
-
|
|
251
|
+
// Collect ALL text content from this node and all nested children
|
|
252
|
+
const fullText = await this.collectTextContent(node);
|
|
253
|
+
// Word wrap the full text to fit paper width
|
|
254
|
+
if (fullText) {
|
|
255
|
+
const paperWidth = this.generator.getPaperWidth();
|
|
256
|
+
const lines = wrapText(fullText, paperWidth);
|
|
257
|
+
for (let i = 0; i < lines.length; i++) {
|
|
258
|
+
this.generator.addText(lines[i]);
|
|
259
|
+
if (i < lines.length - 1) {
|
|
260
|
+
this.generator.addNewline();
|
|
261
|
+
}
|
|
264
262
|
}
|
|
265
263
|
}
|
|
266
|
-
//
|
|
267
|
-
if (textContent) {
|
|
268
|
-
this.generator.addText(textContent);
|
|
269
|
-
}
|
|
270
|
-
// Traverse children (nested Text elements)
|
|
271
|
-
await this.traverseChildren(node);
|
|
272
|
-
// Add newline BEFORE resetting formatting so alignment takes effect at LF
|
|
273
|
-
// (ESC/POS applies alignment at print time, i.e. when LF is sent)
|
|
274
|
-
this.generator.addNewline();
|
|
275
|
-
// Reset formatting after the line is printed
|
|
264
|
+
// Reset formatting after text (especially bold)
|
|
276
265
|
this.generator.resetFormatting();
|
|
266
|
+
// Add newline after text element
|
|
267
|
+
this.generator.addNewline();
|
|
277
268
|
}
|
|
278
269
|
/**
|
|
279
270
|
* Handle TextNode (raw text)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thermal-print/escpos",
|
|
3
|
-
"version": "0.3.1-beta.
|
|
3
|
+
"version": "0.3.1-beta.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "ESC/POS command generation and thermal printer control",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"author": "",
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@thermal-print/core": "
|
|
29
|
+
"@thermal-print/core": "workspace:*",
|
|
30
30
|
"jimp": "^1.6.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|