react-native-earl-thermal-printer 1.0.1 → 1.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/README.md +114 -22
- package/android/.project +0 -6
- package/android/src/main/java/com/pinmi/react/printer/RNBLEPrinterModule.java +4 -4
- package/android/src/main/java/com/pinmi/react/printer/RNNetPrinterModule.java +4 -4
- package/android/src/main/java/com/pinmi/react/printer/RNPrinterModule.java +2 -2
- package/android/src/main/java/com/pinmi/react/printer/RNUSBPrinterModule.java +4 -4
- package/android/src/main/java/com/pinmi/react/printer/adapter/BLEPrinterAdapter.java +17 -15
- package/android/src/main/java/com/pinmi/react/printer/adapter/NetPrinterAdapter.java +17 -15
- package/android/src/main/java/com/pinmi/react/printer/adapter/PrinterAdapter.java +2 -2
- package/android/src/main/java/com/pinmi/react/printer/adapter/USBPrinterAdapter.java +17 -15
- package/dist/NativeBLEPrinter.d.ts +2 -2
- package/dist/NativeBLEPrinter.d.ts.map +1 -1
- package/dist/NativeNetPrinter.d.ts +2 -2
- package/dist/NativeNetPrinter.d.ts.map +1 -1
- package/dist/NativeUSBPrinter.d.ts +2 -2
- package/dist/NativeUSBPrinter.d.ts.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/utils/EPToolkit.d.ts +4 -1
- package/dist/utils/EPToolkit.d.ts.map +1 -1
- package/dist/utils/EPToolkit.js +212 -20
- package/dist/utils/EPToolkit.js.map +1 -1
- package/ios/RNBLEPrinter.mm +4 -1
- package/ios/RNNetPrinter.mm +4 -1
- package/ios/RNUSBPrinter.mm +2 -0
- package/package.json +1 -1
- package/src/NativeBLEPrinter.ts +2 -2
- package/src/NativeNetPrinter.ts +2 -2
- package/src/NativeUSBPrinter.ts +2 -2
- package/src/index.ts +12 -12
- package/src/utils/EPToolkit.ts +270 -20
package/src/utils/EPToolkit.ts
CHANGED
|
@@ -4,34 +4,150 @@ import * as iconv from "iconv-lite";
|
|
|
4
4
|
|
|
5
5
|
import BufferHelper from "./buffer-helper";
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
// ── Printer initialization ──────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
const init_printer_bytes = Buffer.from([27, 64]); // ESC @
|
|
10
|
+
|
|
11
|
+
// ── Alignment ───────────────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
const l_start_bytes = Buffer.from([27, 97, 0]); // ESC a 0 — Left
|
|
9
14
|
const l_end_bytes = Buffer.from([]);
|
|
10
|
-
const c_start_bytes = Buffer.from([27, 97, 1]);
|
|
11
|
-
const c_end_bytes = Buffer.from([]);
|
|
12
|
-
const r_start_bytes = Buffer.from([27, 97, 2]);
|
|
15
|
+
const c_start_bytes = Buffer.from([27, 97, 1]); // ESC a 1 — Center
|
|
16
|
+
const c_end_bytes = Buffer.from([]);
|
|
17
|
+
const r_start_bytes = Buffer.from([27, 97, 2]); // ESC a 2 — Right
|
|
13
18
|
const r_end_bytes = Buffer.from([]);
|
|
14
19
|
|
|
15
|
-
|
|
20
|
+
// ── Spacing ─────────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
const default_space_bytes = Buffer.from([27, 50]); // ESC 2 — Default line spacing
|
|
23
|
+
|
|
24
|
+
// ── Reset (sent after every newline) ────────────────────────────────────────
|
|
16
25
|
|
|
17
|
-
const reset_bytes = Buffer.from([
|
|
18
|
-
|
|
26
|
+
const reset_bytes = Buffer.from([
|
|
27
|
+
27,
|
|
28
|
+
97,
|
|
29
|
+
0, // ESC a 0 — Left align
|
|
30
|
+
29,
|
|
31
|
+
33,
|
|
32
|
+
0, // GS ! 0 — Normal character size
|
|
33
|
+
27,
|
|
34
|
+
33,
|
|
35
|
+
0, // ESC ! 0 — Normal print mode
|
|
36
|
+
28,
|
|
37
|
+
33,
|
|
38
|
+
0, // FS ! 0 — Normal CJK mode
|
|
39
|
+
27,
|
|
40
|
+
45,
|
|
41
|
+
0, // ESC - 0 — Underline off
|
|
42
|
+
27,
|
|
43
|
+
69,
|
|
44
|
+
0, // ESC E 0 — Bold/emphasis off
|
|
45
|
+
29,
|
|
46
|
+
66,
|
|
47
|
+
0, // GS B 0 — Reverse off
|
|
48
|
+
27,
|
|
49
|
+
123,
|
|
50
|
+
0, // ESC { 0 — Upside-down off
|
|
51
|
+
27,
|
|
52
|
+
50, // ESC 2 — Default line spacing
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
// ── Legacy formatting (ESC ! / FS !) ────────────────────────────────────────
|
|
56
|
+
// These use the master print-mode byte; kept for backward compatibility.
|
|
57
|
+
|
|
58
|
+
const m_start_bytes = Buffer.from([27, 33, 16, 28, 33, 8]); // Double-height
|
|
19
59
|
const m_end_bytes = Buffer.from([27, 33, 0, 28, 33, 0]);
|
|
20
|
-
const b_start_bytes = Buffer.from([27, 33, 48, 28, 33, 12]);
|
|
60
|
+
const b_start_bytes = Buffer.from([27, 33, 48, 28, 33, 12]); // Double-height + double-width
|
|
21
61
|
const b_end_bytes = Buffer.from([27, 33, 0, 28, 33, 0]);
|
|
62
|
+
const d_start_bytes = Buffer.from([27, 33, 32, 28, 33, 4]); // Double-width
|
|
63
|
+
const d_end_bytes = Buffer.from([27, 33, 0, 28, 33, 0]);
|
|
64
|
+
const db_start_bytes = Buffer.from([27, 33, 40, 28, 33, 12]); // Double-width + bold emphasis
|
|
65
|
+
const db_end_bytes = Buffer.from([27, 33, 0, 28, 33, 0]);
|
|
66
|
+
|
|
67
|
+
// ── Legacy alignment + size combos ──────────────────────────────────────────
|
|
68
|
+
|
|
22
69
|
const cm_start_bytes = Buffer.from([27, 97, 1, 27, 33, 16, 28, 33, 8]);
|
|
23
70
|
const cm_end_bytes = Buffer.from([27, 33, 0, 28, 33, 0]);
|
|
24
71
|
const cb_start_bytes = Buffer.from([27, 97, 1, 27, 33, 48, 28, 33, 12]);
|
|
25
72
|
const cb_end_bytes = Buffer.from([27, 33, 0, 28, 33, 0]);
|
|
26
73
|
const cd_start_bytes = Buffer.from([27, 97, 1, 27, 33, 32, 28, 33, 4]);
|
|
27
74
|
const cd_end_bytes = Buffer.from([27, 33, 0, 28, 33, 0]);
|
|
28
|
-
const d_start_bytes = Buffer.from([27, 33, 32, 28, 33, 4]);
|
|
29
|
-
const d_end_bytes = Buffer.from([27, 33, 0, 28, 33, 0]);
|
|
30
75
|
|
|
31
|
-
|
|
76
|
+
// ── Underline ───────────────────────────────────────────────────────────────
|
|
77
|
+
|
|
78
|
+
const u_start_bytes = Buffer.from([27, 45, 1]); // ESC - 1 — 1-dot underline
|
|
79
|
+
const u_end_bytes = Buffer.from([27, 45, 0]); // ESC - 0 — underline off
|
|
80
|
+
const u2_start_bytes = Buffer.from([27, 45, 2]); // ESC - 2 — 2-dot (thick) underline
|
|
81
|
+
const u2_end_bytes = Buffer.from([27, 45, 0]);
|
|
82
|
+
|
|
83
|
+
// ── Bold / Emphasis (no size change) ────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
const bold_start_bytes = Buffer.from([27, 69, 1]); // ESC E 1
|
|
86
|
+
const bold_end_bytes = Buffer.from([27, 69, 0]); // ESC E 0
|
|
87
|
+
|
|
88
|
+
// ── Reverse (white-on-black) ────────────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
const rev_start_bytes = Buffer.from([29, 66, 1]); // GS B 1
|
|
91
|
+
const rev_end_bytes = Buffer.from([29, 66, 0]); // GS B 0
|
|
92
|
+
|
|
93
|
+
// ── Upside-down ─────────────────────────────────────────────────────────────
|
|
94
|
+
|
|
95
|
+
const updown_start_bytes = Buffer.from([27, 123, 1]); // ESC { 1
|
|
96
|
+
const updown_end_bytes = Buffer.from([27, 123, 0]); // ESC { 0
|
|
97
|
+
|
|
98
|
+
// ── Font selection ──────────────────────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
const font_a_bytes = Buffer.from([27, 77, 0]); // ESC M 0 — Font A (default, 12×24)
|
|
101
|
+
const font_b_bytes = Buffer.from([27, 77, 1]); // ESC M 1 — Font B (smaller, 9×17)
|
|
102
|
+
|
|
103
|
+
// ── Character size helpers (GS ! n) ─────────────────────────────────────────
|
|
104
|
+
// Width multiplier = bits 0-3 (0–7 → 1×–8×)
|
|
105
|
+
// Height multiplier = bits 4-7 (0–7 → 1×–8×)
|
|
106
|
+
|
|
107
|
+
function sizeBytes(w: number, h: number): Buffer {
|
|
108
|
+
const cw = Math.min(Math.max(w, 1), 8) - 1;
|
|
109
|
+
const ch = Math.min(Math.max(h, 1), 8) - 1;
|
|
110
|
+
return Buffer.from([29, 33, cw | (ch << 4)]); // GS ! n
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const size_reset_bytes = Buffer.from([29, 33, 0]); // GS ! 0 — 1×1
|
|
114
|
+
|
|
115
|
+
// Pre-built size presets
|
|
116
|
+
const w2_start_bytes = sizeBytes(2, 1); // Width ×2
|
|
117
|
+
const w3_start_bytes = sizeBytes(3, 1); // Width ×3
|
|
118
|
+
const h2_start_bytes = sizeBytes(1, 2); // Height ×2
|
|
119
|
+
const h3_start_bytes = sizeBytes(1, 3); // Height ×3
|
|
120
|
+
const x2_start_bytes = sizeBytes(2, 2); // Width ×2, Height ×2
|
|
121
|
+
const x3_start_bytes = sizeBytes(3, 3); // Width ×3, Height ×3
|
|
122
|
+
const x4_start_bytes = sizeBytes(4, 4); // Width ×4, Height ×4
|
|
123
|
+
|
|
124
|
+
// ── Line spacing ────────────────────────────────────────────────────────────
|
|
125
|
+
|
|
126
|
+
function lineSpacingBytes(n: number): Buffer {
|
|
127
|
+
return Buffer.from([27, 51, Math.min(Math.max(n, 0), 255)]); // ESC 3 n
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const default_line_spacing_bytes = Buffer.from([27, 50]); // ESC 2
|
|
131
|
+
|
|
132
|
+
// ── Character spacing ───────────────────────────────────────────────────────
|
|
133
|
+
|
|
134
|
+
function charSpacingBytes(n: number): Buffer {
|
|
135
|
+
return Buffer.from([27, 32, Math.min(Math.max(n, 0), 255)]); // ESC SP n
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ── Cut / Beep / Tail ───────────────────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
const cut_bytes = Buffer.from([27, 105]); // ESC i — full cut
|
|
141
|
+
const partial_cut_bytes = Buffer.from([27, 109]); // ESC m — partial cut
|
|
32
142
|
const beep_bytes = Buffer.from([27, 66, 3, 2]);
|
|
33
143
|
const line_bytes = Buffer.from([10, 10, 10, 10, 10]);
|
|
34
144
|
|
|
145
|
+
// ── Cash drawer ─────────────────────────────────────────────────────────────
|
|
146
|
+
|
|
147
|
+
const drawer_bytes = Buffer.from([27, 112, 0, 60, 120]); // ESC p 0 60 120
|
|
148
|
+
|
|
149
|
+
// ── Encoding ────────────────────────────────────────────────────────────────
|
|
150
|
+
|
|
35
151
|
const encoding_mappings_bytes: { [key: string]: Buffer } = {
|
|
36
152
|
// single byte encodings
|
|
37
153
|
CP437: Buffer.from([27, 116, 0]),
|
|
@@ -48,27 +164,130 @@ const options_controller = {
|
|
|
48
164
|
encoding: encoding_mappings_bytes,
|
|
49
165
|
};
|
|
50
166
|
|
|
167
|
+
// ── Static tag → bytes map ──────────────────────────────────────────────────
|
|
168
|
+
// Tags are matched longest-first at parse time to avoid prefix collisions.
|
|
169
|
+
|
|
51
170
|
const controller: { [key: string]: Buffer } = {
|
|
171
|
+
// Legacy formatting
|
|
52
172
|
"<M>": m_start_bytes,
|
|
53
173
|
"</M>": m_end_bytes,
|
|
54
174
|
"<B>": b_start_bytes,
|
|
55
175
|
"</B>": b_end_bytes,
|
|
56
176
|
"<D>": d_start_bytes,
|
|
57
177
|
"</D>": d_end_bytes,
|
|
178
|
+
"<DB>": db_start_bytes,
|
|
179
|
+
"</DB>": db_end_bytes,
|
|
180
|
+
|
|
181
|
+
// Alignment
|
|
58
182
|
"<C>": c_start_bytes,
|
|
59
183
|
"</C>": c_end_bytes,
|
|
184
|
+
"<L>": l_start_bytes,
|
|
185
|
+
"</L>": l_end_bytes,
|
|
186
|
+
"<R>": r_start_bytes,
|
|
187
|
+
"</R>": r_end_bytes,
|
|
188
|
+
|
|
189
|
+
// Legacy alignment + size combos
|
|
60
190
|
"<CM>": cm_start_bytes,
|
|
61
191
|
"</CM>": cm_end_bytes,
|
|
62
192
|
"<CD>": cd_start_bytes,
|
|
63
193
|
"</CD>": cd_end_bytes,
|
|
64
194
|
"<CB>": cb_start_bytes,
|
|
65
195
|
"</CB>": cb_end_bytes,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"<
|
|
69
|
-
"</
|
|
196
|
+
|
|
197
|
+
// Underline
|
|
198
|
+
"<U>": u_start_bytes,
|
|
199
|
+
"</U>": u_end_bytes,
|
|
200
|
+
"<U2>": u2_start_bytes,
|
|
201
|
+
"</U2>": u2_end_bytes,
|
|
202
|
+
|
|
203
|
+
// Bold emphasis only (no size change)
|
|
204
|
+
"<BOLD>": bold_start_bytes,
|
|
205
|
+
"</BOLD>": bold_end_bytes,
|
|
206
|
+
|
|
207
|
+
// Reverse (white on black)
|
|
208
|
+
"<REV>": rev_start_bytes,
|
|
209
|
+
"</REV>": rev_end_bytes,
|
|
210
|
+
|
|
211
|
+
// Upside-down
|
|
212
|
+
"<UPDOWN>": updown_start_bytes,
|
|
213
|
+
"</UPDOWN>": updown_end_bytes,
|
|
214
|
+
|
|
215
|
+
// Font selection
|
|
216
|
+
"<FONT_A>": font_a_bytes,
|
|
217
|
+
"<FONT_B>": font_b_bytes,
|
|
218
|
+
|
|
219
|
+
// Size presets (GS !)
|
|
220
|
+
"<W2>": w2_start_bytes,
|
|
221
|
+
"</W2>": size_reset_bytes,
|
|
222
|
+
"<W3>": w3_start_bytes,
|
|
223
|
+
"</W3>": size_reset_bytes,
|
|
224
|
+
"<H2>": h2_start_bytes,
|
|
225
|
+
"</H2>": size_reset_bytes,
|
|
226
|
+
"<H3>": h3_start_bytes,
|
|
227
|
+
"</H3>": size_reset_bytes,
|
|
228
|
+
"<X2>": x2_start_bytes,
|
|
229
|
+
"</X2>": size_reset_bytes,
|
|
230
|
+
"<X3>": x3_start_bytes,
|
|
231
|
+
"</X3>": size_reset_bytes,
|
|
232
|
+
"<X4>": x4_start_bytes,
|
|
233
|
+
"</X4>": size_reset_bytes,
|
|
234
|
+
|
|
235
|
+
// Close tags for parameterized tags
|
|
236
|
+
"</FS>": size_reset_bytes,
|
|
237
|
+
"</LINESPC>": default_line_spacing_bytes,
|
|
238
|
+
"</CHARSPC>": Buffer.from([27, 32, 0]),
|
|
239
|
+
|
|
240
|
+
// Inline action tags (no closing tag)
|
|
241
|
+
"<PARTCUT>": partial_cut_bytes,
|
|
242
|
+
"<DRAWER>": drawer_bytes,
|
|
243
|
+
"<TAB>": Buffer.from([9]),
|
|
244
|
+
"<RESET>": reset_bytes,
|
|
70
245
|
};
|
|
71
246
|
|
|
247
|
+
// Sort tag keys longest-first so that e.g. "</BOLD>" is tried before "</B>"
|
|
248
|
+
const sorted_tags = Object.keys(controller).sort((a, b) => b.length - a.length);
|
|
249
|
+
|
|
250
|
+
// ── Parameterized tag regexes ───────────────────────────────────────────────
|
|
251
|
+
|
|
252
|
+
const parameterized_tags: Array<{
|
|
253
|
+
regex: RegExp;
|
|
254
|
+
handler: (match: RegExpMatchArray) => Buffer;
|
|
255
|
+
}> = [
|
|
256
|
+
{
|
|
257
|
+
// <FS:W,H> — custom font size (width 1–8, height 1–8)
|
|
258
|
+
regex: /^<FS:(\d+),(\d+)>/,
|
|
259
|
+
handler: (m) => sizeBytes(parseInt(m[1], 10), parseInt(m[2], 10)),
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
// <LINESPC:N> — line spacing in dots (0–255)
|
|
263
|
+
regex: /^<LINESPC:(\d+)>/,
|
|
264
|
+
handler: (m) => lineSpacingBytes(parseInt(m[1], 10)),
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
// <CHARSPC:N> — character spacing in dots (0–255)
|
|
268
|
+
regex: /^<CHARSPC:(\d+)>/,
|
|
269
|
+
handler: (m) => charSpacingBytes(parseInt(m[1], 10)),
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
// <FEED:N> — feed N lines (1–255)
|
|
273
|
+
regex: /^<FEED:(\d+)>/,
|
|
274
|
+
handler: (m) => {
|
|
275
|
+
const n = Math.min(Math.max(parseInt(m[1], 10), 1), 255);
|
|
276
|
+
return Buffer.from([27, 100, n]); // ESC d n
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
// <RAW:HH,HH,...> — send raw hex bytes
|
|
281
|
+
regex: /^<RAW:([0-9A-Fa-f,]+)>/,
|
|
282
|
+
handler: (m) => {
|
|
283
|
+
const hexParts = m[1].split(",").filter(Boolean);
|
|
284
|
+
return Buffer.from(hexParts.map((h) => parseInt(h, 16)));
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
];
|
|
288
|
+
|
|
289
|
+
// ── Options ─────────────────────────────────────────────────────────────────
|
|
290
|
+
|
|
72
291
|
type IOptions = {
|
|
73
292
|
beep: boolean;
|
|
74
293
|
cut: boolean;
|
|
@@ -83,6 +302,8 @@ const default_options: IOptions = {
|
|
|
83
302
|
encoding: "UTF8",
|
|
84
303
|
};
|
|
85
304
|
|
|
305
|
+
// ── Main text → buffer converter ────────────────────────────────────────────
|
|
306
|
+
|
|
86
307
|
export function exchange_text(text: string, options: IOptions): Buffer {
|
|
87
308
|
const m_options = options || default_options;
|
|
88
309
|
|
|
@@ -103,17 +324,42 @@ export function exchange_text(text: string, options: IOptions): Buffer {
|
|
|
103
324
|
for (let i = 0; i < text.length; i++) {
|
|
104
325
|
let ch = text[i];
|
|
105
326
|
switch (ch) {
|
|
106
|
-
case "<":
|
|
327
|
+
case "<": {
|
|
107
328
|
bytes.concat(iconv.encode(temp, m_options.encoding));
|
|
108
329
|
temp = "";
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
330
|
+
|
|
331
|
+
const remaining = text.substring(i);
|
|
332
|
+
|
|
333
|
+
// 1. Try static tags (longest-first to avoid prefix collisions)
|
|
334
|
+
let matched = false;
|
|
335
|
+
for (const tag of sorted_tags) {
|
|
336
|
+
if (remaining.startsWith(tag)) {
|
|
112
337
|
bytes.concat(controller[tag]);
|
|
113
338
|
i += tag.length - 1;
|
|
339
|
+
matched = true;
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// 2. Try parameterized tags
|
|
345
|
+
if (!matched) {
|
|
346
|
+
for (const pt of parameterized_tags) {
|
|
347
|
+
const m = remaining.match(pt.regex);
|
|
348
|
+
if (m) {
|
|
349
|
+
bytes.concat(pt.handler(m));
|
|
350
|
+
i += m[0].length - 1;
|
|
351
|
+
matched = true;
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
114
354
|
}
|
|
115
355
|
}
|
|
356
|
+
|
|
357
|
+
// 3. Not a known tag — keep the literal '<'
|
|
358
|
+
if (!matched) {
|
|
359
|
+
temp = "<";
|
|
360
|
+
}
|
|
116
361
|
break;
|
|
362
|
+
}
|
|
117
363
|
case "\n":
|
|
118
364
|
temp = `${temp}${ch}`;
|
|
119
365
|
bytes.concat(iconv.encode(temp, m_options.encoding));
|
|
@@ -148,6 +394,10 @@ export function exchange_text(text: string, options: IOptions): Buffer {
|
|
|
148
394
|
return bytes.toBuffer();
|
|
149
395
|
}
|
|
150
396
|
|
|
397
|
+
// ── Public helpers (re-exported for advanced usage) ─────────────────────────
|
|
398
|
+
|
|
399
|
+
export { sizeBytes, lineSpacingBytes, charSpacingBytes };
|
|
400
|
+
|
|
151
401
|
// export async function exchange_image(
|
|
152
402
|
// imagePath: string,
|
|
153
403
|
// threshold: number
|