tauri-plugin-thermal-printer 1.1.0 → 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/LICENSE +21 -0
- package/README.md +395 -54
- package/dist-js/index.cjs +250 -3
- package/dist-js/index.d.ts +202 -18
- package/dist-js/index.js +220 -4
- package/package.json +2 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Luis Andres Gonzalez Corzo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -7,11 +7,9 @@ This plugin provides thermal printer functionality for Tauri applications, allow
|
|
|
7
7
|
| Linux | ✅ |
|
|
8
8
|
| macOS | ✅ |
|
|
9
9
|
| Windows | ✅ |
|
|
10
|
-
| Android |
|
|
10
|
+
| Android | ? |
|
|
11
11
|
| iOS | ❌ |
|
|
12
12
|
|
|
13
|
-
For mobile applications, this plugin is currently working on this...
|
|
14
|
-
|
|
15
13
|
## Table of Contents
|
|
16
14
|
|
|
17
15
|
- [How it Works](#how-it-works)
|
|
@@ -24,6 +22,8 @@ For mobile applications, this plugin is currently working on this...
|
|
|
24
22
|
- [List Printers](#list-printers)
|
|
25
23
|
- [Test Printer](#test-printer)
|
|
26
24
|
- [Print Document](#print-document)
|
|
25
|
+
- [Paper Size Helpers (TypeScript)](#paper-size-helpers-typescript)
|
|
26
|
+
- [Error Handling](#error-handling)
|
|
27
27
|
- [Section Types](#section-types)
|
|
28
28
|
- [Title](#title)
|
|
29
29
|
- [Subtitle](#subtitle)
|
|
@@ -41,6 +41,11 @@ For mobile applications, this plugin is currently working on this...
|
|
|
41
41
|
- [Logo](#logo)
|
|
42
42
|
- [Line](#line)
|
|
43
43
|
- [GlobalStyles](#globalstyles)
|
|
44
|
+
- [TypeScript Constants & Helpers](#typescript-constants--helpers)
|
|
45
|
+
- [CodePage](#codepage)
|
|
46
|
+
- [Style constants](#style-constants)
|
|
47
|
+
- [Section builder helpers](#section-builder-helpers)
|
|
48
|
+
- [Helper example (all builders)](#helper-example-all-builders)
|
|
44
49
|
- [Examples](#examples)
|
|
45
50
|
|
|
46
51
|
## How it Works
|
|
@@ -50,13 +55,17 @@ This plugin acts as a **translator** between a user-friendly JavaScript/TypeScri
|
|
|
50
55
|
### Architecture
|
|
51
56
|
|
|
52
57
|
```
|
|
53
|
-
Frontend (JavaScript/TypeScript)
|
|
58
|
+
Frontend (JavaScript/TypeScript)
|
|
54
59
|
↓ (IPC Commands)
|
|
55
|
-
Tauri Core (Rust)
|
|
60
|
+
Tauri Core (Rust) ←— ESC/POS generation (shared across all platforms)
|
|
56
61
|
↓ (Platform-specific implementations)
|
|
57
|
-
Operating System (Linux/macOS/Windows)
|
|
58
|
-
↓ (Raw binary data)
|
|
59
|
-
Thermal Printer (ESC/POS protocol)
|
|
62
|
+
├── Desktop: Operating System (Linux/macOS/Windows)
|
|
63
|
+
│ ↓ (Raw binary data)
|
|
64
|
+
│ Thermal Printer (ESC/POS protocol)
|
|
65
|
+
│
|
|
66
|
+
└── Android: Kotlin Plugin
|
|
67
|
+
↓ (Bluetooth SPP / RFCOMM)
|
|
68
|
+
Thermal Printer (ESC/POS protocol)
|
|
60
69
|
```
|
|
61
70
|
|
|
62
71
|
### Core Components
|
|
@@ -78,14 +87,14 @@ Converts data structures into ESC/POS binary commands:
|
|
|
78
87
|
pub fn generate_document(&mut self, print_job: &PrintJobRequest) -> Result<Vec<u8>, String>
|
|
79
88
|
```
|
|
80
89
|
|
|
81
|
-
#### 4. **OS Integration** (`src/desktop_printers/`)
|
|
90
|
+
#### 4. **OS Integration** (`src/desktop_printers/` and `android/`)
|
|
82
91
|
- **Linux/macOS**: Uses CUPS system (`lpstat`, `lp` commands)
|
|
83
92
|
- **Windows**: Uses WinAPI (Windows API) to directly access system printers via functions such as EnumPrintersW for listing printers, OpenPrinterW for opening printer handles, and WritePrinter for sending raw data
|
|
84
|
-
- **Android**:
|
|
93
|
+
- **Android**: Kotlin plugin with Bluetooth SPP and USB printer discovery and printing
|
|
85
94
|
|
|
86
95
|
### Workflow
|
|
87
96
|
|
|
88
|
-
#### Printing a Document:
|
|
97
|
+
#### Printing a Document (Desktop):
|
|
89
98
|
|
|
90
99
|
1. **Frontend** sends `PrintJobRequest` with sections and configuration
|
|
91
100
|
2. **Tauri** receives the command and processes it in Rust
|
|
@@ -93,6 +102,14 @@ pub fn generate_document(&mut self, print_job: &PrintJobRequest) -> Result<Vec<u
|
|
|
93
102
|
4. **Operating System** sends binary data to the printer
|
|
94
103
|
5. **Thermal Printer** interprets ESC/POS commands and prints
|
|
95
104
|
|
|
105
|
+
#### Printing a Document (Android):
|
|
106
|
+
|
|
107
|
+
1. **Frontend** sends `PrintJobRequest` with sections and configuration
|
|
108
|
+
2. **Rust** generates ESC/POS binary data using the same `ProcessPrint` pipeline
|
|
109
|
+
3. **Kotlin plugin** receives the binary data and the printer MAC address
|
|
110
|
+
4. **Bluetooth SPP** connection is established to the printer
|
|
111
|
+
5. **Thermal Printer** interprets ESC/POS commands and prints
|
|
112
|
+
|
|
96
113
|
#### Print Structure Example:
|
|
97
114
|
```json
|
|
98
115
|
{
|
|
@@ -133,15 +150,18 @@ The plugin translates all sections into **ESC/POS** (Escape Sequence for Point o
|
|
|
133
150
|
- ✅ **Linux**: Fully functional (CUPS)
|
|
134
151
|
- ✅ **macOS**: Fully functional (CUPS)
|
|
135
152
|
- ✅ **Windows**: Fully functional (WinAPI)
|
|
136
|
-
-
|
|
153
|
+
- ✅ **Android**: Bluetooth and USB printer discovery and printing
|
|
137
154
|
- ❌ **iOS**: Not implemented
|
|
138
155
|
|
|
139
156
|
### Supported Connections
|
|
140
157
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
158
|
+
| Connection | Linux | macOS | Windows | Android |
|
|
159
|
+
| ---------- | ----- | ----- | ------- | ------- |
|
|
160
|
+
| USB | ✅ | ✅ | ✅ | ✅ (discovery only) |
|
|
161
|
+
| Network | ✅ | ✅ | ✅ | ❌ |
|
|
162
|
+
| Bluetooth | ❌ | ❌ | ❌ | ✅ |
|
|
163
|
+
|
|
164
|
+
> **Android note**: The `printer` field in `PrintJobRequest` must be the Bluetooth MAC address of the printer (e.g. `"AA:BB:CC:DD:EE:FF"`). The printer must be previously paired in the Android Bluetooth settings. Bluetooth permissions are requested automatically at runtime.
|
|
145
165
|
|
|
146
166
|
## Installation
|
|
147
167
|
|
|
@@ -215,7 +235,11 @@ Get all printers available in the system. It just lists the configured printers.
|
|
|
215
235
|
```typescript
|
|
216
236
|
import { list_thermal_printers } from "tauri-plugin-thermal-printer";
|
|
217
237
|
|
|
218
|
-
|
|
238
|
+
try {
|
|
239
|
+
const response = await list_thermal_printers();
|
|
240
|
+
} catch (error) {
|
|
241
|
+
console.log("List printers failed: " + error)
|
|
242
|
+
}
|
|
219
243
|
```
|
|
220
244
|
|
|
221
245
|
#### Response
|
|
@@ -252,7 +276,7 @@ Send a print test to a specific printer to verify functionality.
|
|
|
252
276
|
```typescript
|
|
253
277
|
import { test_thermal_printer, type TestPrintRequest } from "tauri-plugin-thermal-printer";
|
|
254
278
|
|
|
255
|
-
|
|
279
|
+
try { await test_thermal_printer({
|
|
256
280
|
"printer_info": {
|
|
257
281
|
"printer": "TM-T20II",
|
|
258
282
|
"paper_size": "Mm80",
|
|
@@ -280,7 +304,7 @@ const response = await test_thermal_printer({
|
|
|
280
304
|
"test_all_fonts": false,
|
|
281
305
|
"test_invert": false,
|
|
282
306
|
"test_rotate": false
|
|
283
|
-
} as TestPrintRequest)
|
|
307
|
+
} as TestPrintRequest) } catch (error) { console.error("Test print failed:", error); }
|
|
284
308
|
```
|
|
285
309
|
|
|
286
310
|
#### Request parameters (TestPrintRequest):
|
|
@@ -307,9 +331,7 @@ const response = await test_thermal_printer({
|
|
|
307
331
|
| `test_rotate` | boolean | ❌ No | Text rotation test (default: `false`) |
|
|
308
332
|
|
|
309
333
|
#### Response:
|
|
310
|
-
Returns `
|
|
311
|
-
- `true`: Test completed successfully
|
|
312
|
-
- `false`: Test failed
|
|
334
|
+
Returns `Promise<void>`. Resolves when the test print completes successfully. **Throws a `string`** with the error message if it fails. Use `try/catch` to handle errors — see [Error Handling](#error-handling).
|
|
313
335
|
|
|
314
336
|
---
|
|
315
337
|
|
|
@@ -321,7 +343,7 @@ Print a personalized document with the specified sections.
|
|
|
321
343
|
```typescript
|
|
322
344
|
import { print_thermal_printer, type PrintJobRequest } from "tauri-plugin-thermal-printer";
|
|
323
345
|
|
|
324
|
-
|
|
346
|
+
try { await print_thermal_printer({
|
|
325
347
|
"printer": "TM-T20II",
|
|
326
348
|
"paper_size": "Mm80",
|
|
327
349
|
"options": {
|
|
@@ -338,34 +360,116 @@ const response = await print_thermal_printer({
|
|
|
338
360
|
{"Beep": {"times": 1, "duration": 100}},
|
|
339
361
|
{"Drawer": {"pin": 2, "pulse_time": 100}},
|
|
340
362
|
{"Qr": {"data": "https://example.com", "size": 5, "error_correction": "M", "model": 2}},
|
|
341
|
-
{"Barcode": {"data": "
|
|
342
|
-
{"Table": {"columns": 3, "column_widths": [
|
|
363
|
+
{"Barcode": {"data": "123456789012", "barcode_type": "CODE128", "width": 2, "height": 100, "text_position": "below"}},
|
|
364
|
+
{"Table": {"columns": 3, "column_widths": [16, 16, 16], "header": [{"text": "Col1"}, {"text": "Col2"}, {"text": "Col3"}], "body": [[{"text": "Data1"}, {"text": "Data2"}, {"text": "Data3"}]], "truncate": false}},
|
|
343
365
|
{"DataMatrix": {"data": "DataMatrix data", "size": 5}},
|
|
344
366
|
{"Pdf417": {"data": "PDF417 data", "columns": 2, "rows": 5, "width": 3, "height": 5, "error_correction": 2}},
|
|
345
|
-
{"Image": {"data": "{
|
|
367
|
+
{"Image": {"data": "{base64 image data}", "max_width": 384, "align": "center", "dithering": true, "size": "normal"}},
|
|
346
368
|
{"Logo": {"key_code": 1, "mode": "normal"}},
|
|
347
369
|
{"Line": {"character": "="}}
|
|
348
370
|
]
|
|
349
|
-
} as PrintJobRequest)
|
|
371
|
+
} as PrintJobRequest) } catch (error) { console.error("Print failed:", error); }
|
|
350
372
|
```
|
|
351
373
|
|
|
352
374
|
#### Response:
|
|
353
|
-
Returns `
|
|
354
|
-
- `true`: Print completed successfully
|
|
355
|
-
- `false`: Print failed
|
|
375
|
+
Returns `Promise<void>`. Resolves when printing completes successfully. **Throws a `string`** with the error message if the job fails (e.g., printer not found, invalid barcode data, QR data too long). Use `try/catch` to handle errors — see [Error Handling](#error-handling).
|
|
356
376
|
|
|
357
377
|
#### Main parameters (PrintJobRequest):
|
|
358
378
|
|
|
359
379
|
| Parameter | Type | Required | Description |
|
|
360
380
|
|-----------|------|----------|-------------|
|
|
361
381
|
| `printer` | string | ✅ Yes | Printer name |
|
|
362
|
-
| `paper_size` |
|
|
382
|
+
| `paper_size` | PaperSize | ❌ No | Paper size (default: `"Mm80"`) — see [Paper Sizes](#paper-sizes) |
|
|
363
383
|
| `options` | PrinterOptions | ❌ No | Configuration options |
|
|
364
384
|
| `options.cut_paper` | boolean | ❌ No | Cut paper after printing (default: `true`) |
|
|
365
385
|
| `options.beep` | boolean | ❌ No | Beep after printing (default: `false`) |
|
|
366
386
|
| `options.open_cash_drawer` | boolean | ❌ No | Open cash drawer after printing (default: `false`) |
|
|
387
|
+
| `options.code_page` | CodePage | ❌ No | Character encoding for special characters (default: `"Default"`) — see [CodePage](#codepage) |
|
|
367
388
|
| `sections` | array | ✅ Yes | Array of sections to print (see [Section Types](#section-types)) |
|
|
368
389
|
|
|
390
|
+
#### Paper Sizes
|
|
391
|
+
|
|
392
|
+
| Value | Paper width | Chars/line | Typical use |
|
|
393
|
+
|-------|-------------|------------|-------------|
|
|
394
|
+
| `"Mm40"` | 40mm | 21 | Handheld ticket printers |
|
|
395
|
+
| `"Mm44"` | 44mm | 24 | Compact POS |
|
|
396
|
+
| `"Mm58"` | 58mm | 32 | Small format (most common portable) |
|
|
397
|
+
| `"Mm72"` | 72mm | 42 | Mid-range printers |
|
|
398
|
+
| `"Mm80"` | 80mm | 48 | Standard large format (default) |
|
|
399
|
+
| `"Mm104"` | 104mm | 62 | Wide format |
|
|
400
|
+
|
|
401
|
+
#### Paper Size Helpers (TypeScript)
|
|
402
|
+
|
|
403
|
+
The TypeScript package exports constants and helper functions with the same values used by the Rust backend.
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
import {
|
|
407
|
+
PAPER_SIZE_CHARS_PER_LINE,
|
|
408
|
+
PAPER_SIZE_PIXELS_WIDTH,
|
|
409
|
+
DEFAULT_PAPER_SIZE,
|
|
410
|
+
getPaperSizeCharsPerLine,
|
|
411
|
+
getPaperSizePixelsWidth,
|
|
412
|
+
type PaperSize,
|
|
413
|
+
} from "tauri-plugin-thermal-printer";
|
|
414
|
+
|
|
415
|
+
const size: PaperSize = "Mm58";
|
|
416
|
+
|
|
417
|
+
console.log(DEFAULT_PAPER_SIZE); // "Mm80"
|
|
418
|
+
console.log(PAPER_SIZE_CHARS_PER_LINE[size]); // 32
|
|
419
|
+
console.log(PAPER_SIZE_PIXELS_WIDTH[size]); // 384
|
|
420
|
+
|
|
421
|
+
// Equivalent helper functions:
|
|
422
|
+
console.log(getPaperSizeCharsPerLine(size)); // 32
|
|
423
|
+
console.log(getPaperSizePixelsWidth(size)); // 384
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
Values per paper size:
|
|
427
|
+
|
|
428
|
+
| PaperSize | Chars/line | Pixels width |
|
|
429
|
+
|-----------|------------|--------------|
|
|
430
|
+
| `"Mm40"` | 21 | 256 |
|
|
431
|
+
| `"Mm44"` | 24 | 288 |
|
|
432
|
+
| `"Mm58"` | 32 | 384 |
|
|
433
|
+
| `"Mm72"` | 42 | 512 |
|
|
434
|
+
| `"Mm80"` | 48 | 576 |
|
|
435
|
+
| `"Mm104"` | 62 | 752 |
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
### Error Handling
|
|
440
|
+
|
|
441
|
+
`print_thermal_printer` and `test_thermal_printer` now return `Promise<void>` and **throw** a descriptive `string` when something fails. Always wrap calls in `try/catch`:
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
import { print_thermal_printer, type PrintJobRequest } from "tauri-plugin-thermal-printer";
|
|
445
|
+
|
|
446
|
+
try {
|
|
447
|
+
await print_thermal_printer(job);
|
|
448
|
+
} catch (error) {
|
|
449
|
+
// `error` is a string describing what went wrong, e.g.:
|
|
450
|
+
// "Printer not specified"
|
|
451
|
+
// "Barcode data cannot be empty"
|
|
452
|
+
// "Barcode type 'EAN13' only accepts numeric digits"
|
|
453
|
+
// "QR data length 5000 exceeds maximum 4296 for error correction level 'M'"
|
|
454
|
+
// "Table row 2 has 2 cells but 3 columns declared"
|
|
455
|
+
// "column_widths sum (45) must equal paper chars_per_line (48)"
|
|
456
|
+
// "Image data cannot be empty"
|
|
457
|
+
console.error("Print failed:", error);
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
`list_thermal_printers` also throws on failure (e.g., CUPS not available):
|
|
462
|
+
|
|
463
|
+
```typescript
|
|
464
|
+
try {
|
|
465
|
+
const printers = await list_thermal_printers();
|
|
466
|
+
} catch (error) {
|
|
467
|
+
console.error("Could not list printers:", error);
|
|
468
|
+
}
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
369
473
|
#### Section Types
|
|
370
474
|
|
|
371
475
|
Sections are defined as objects in the `sections` array. Each section is an enum variant with its data. Below are all supported section types:
|
|
@@ -503,8 +607,11 @@ Advances the paper by a specific number of lines.
|
|
|
503
607
|
}
|
|
504
608
|
```
|
|
505
609
|
|
|
506
|
-
- `feed_type` (string, required): Feed type
|
|
507
|
-
- `
|
|
610
|
+
- `feed_type` (string, required): Feed type:
|
|
611
|
+
- `"lines"` — advance N lines (`ESC d n`)
|
|
612
|
+
- `"dots"` — advance N dot rows (`ESC J n`)
|
|
613
|
+
- `"line_feed"` — send N raw LF characters
|
|
614
|
+
- `value` (number, required): Amount to advance
|
|
508
615
|
|
|
509
616
|
##### Cut
|
|
510
617
|
Cuts the paper.
|
|
@@ -518,7 +625,11 @@ Cuts the paper.
|
|
|
518
625
|
}
|
|
519
626
|
```
|
|
520
627
|
|
|
521
|
-
- `mode` (string, required): Cut mode
|
|
628
|
+
- `mode` (string, required): Cut mode:
|
|
629
|
+
- `"full"` — full cut
|
|
630
|
+
- `"partial"` — partial cut (default fallback)
|
|
631
|
+
- `"partial_alt"` — partial cut (alternate)
|
|
632
|
+
- `"partial_alt2"` — full cut (alternate)
|
|
522
633
|
- `feed` (number, required): Lines to advance before cutting
|
|
523
634
|
|
|
524
635
|
##### Beep
|
|
@@ -566,11 +677,11 @@ Prints a QR code.
|
|
|
566
677
|
}
|
|
567
678
|
```
|
|
568
679
|
|
|
569
|
-
- `data` (string, required): QR data
|
|
570
|
-
- `size` (number, required): Module size (1
|
|
571
|
-
- `error_correction` (string, required):
|
|
572
|
-
- `model` (number, required): QR model (1 or 2)
|
|
573
|
-
- `align` (string, optional):
|
|
680
|
+
- `data` (string, required): QR data. **Must not be empty.** Maximum length depends on error correction level — the backend will throw if exceeded.
|
|
681
|
+
- `size` (number, required): Module size (1–16)
|
|
682
|
+
- `error_correction` (string, required): `"L"` (7089 chars max) | `"M"` (4296, default) | `"Q"` (2953) | `"H"` (1817)
|
|
683
|
+
- `model` (number, required): QR model (`1` or `2`)
|
|
684
|
+
- `align` (string, optional): `"left"` | `"center"` | `"right"`
|
|
574
685
|
|
|
575
686
|
##### Barcode
|
|
576
687
|
Prints a barcode.
|
|
@@ -588,12 +699,12 @@ Prints a barcode.
|
|
|
588
699
|
}
|
|
589
700
|
```
|
|
590
701
|
|
|
591
|
-
- `data` (string, required): Barcode data
|
|
592
|
-
- `barcode_type` (string, required):
|
|
593
|
-
- `width` (number, required): Module width
|
|
594
|
-
- `height` (number, required): Height in dots
|
|
595
|
-
- `text_position` (string, required):
|
|
596
|
-
- `align` (string, optional):
|
|
702
|
+
- `data` (string, required): Barcode data. **Must not be empty.** Numeric-only types (`UPC-A`, `UPC-E`, `EAN13`, `EAN8`, `ITF`) only accept digit characters — the backend will throw an error otherwise.
|
|
703
|
+
- `barcode_type` (string, required): `"UPC-A"` | `"UPC-E"` | `"EAN13"` | `"EAN8"` | `"CODE39"` | `"ITF"` | `"CODABAR"` | `"CODE93"` | `"CODE128"`
|
|
704
|
+
- `width` (number, required): Module width (1–6)
|
|
705
|
+
- `height` (number, required): Height in dots (must be > 0)
|
|
706
|
+
- `text_position` (string, required): `"none"` | `"above"` | `"below"` | `"both"`
|
|
707
|
+
- `align` (string, optional): `"left"` | `"center"` | `"right"` (default: current global alignment)
|
|
597
708
|
|
|
598
709
|
##### Table
|
|
599
710
|
Prints a table.
|
|
@@ -638,10 +749,10 @@ Or simply:
|
|
|
638
749
|
```
|
|
639
750
|
|
|
640
751
|
- `columns` (number, required): Number of columns
|
|
641
|
-
- `column_widths` (array, optional): Widths of each column.
|
|
642
|
-
- `header` (array, optional): Column headers
|
|
643
|
-
- `body` (array, required): Data rows
|
|
644
|
-
- `truncate` (boolean, optional): Truncate long text (default: false)
|
|
752
|
+
- `column_widths` (array, optional): Widths of each column in characters. **When provided: length must equal `columns` and the sum must equal the paper's chars/line** (e.g., 48 for Mm80). If omitted, columns are distributed evenly.
|
|
753
|
+
- `header` (array, optional): Column headers — must have exactly `columns` elements if provided
|
|
754
|
+
- `body` (array, required): Data rows — each row must have exactly `columns` cells
|
|
755
|
+
- `truncate` (boolean, optional): Truncate long text instead of wrapping (default: `false`)
|
|
645
756
|
|
|
646
757
|
##### DataMatrix
|
|
647
758
|
Prints a DataMatrix code.
|
|
@@ -696,11 +807,11 @@ Prints an image.
|
|
|
696
807
|
}
|
|
697
808
|
```
|
|
698
809
|
|
|
699
|
-
- `data` (string, required): Base64 encoded image
|
|
700
|
-
- `max_width` (number, required): Maximum width in pixels
|
|
701
|
-
- `align` (string, required):
|
|
702
|
-
- `dithering` (boolean, required): Apply dithering
|
|
703
|
-
- `size` (string, required):
|
|
810
|
+
- `data` (string, required): Base64 encoded image. **Must not be empty.**
|
|
811
|
+
- `max_width` (number, required): Maximum width in pixels (0 or values larger than the paper width are clamped to the paper width automatically)
|
|
812
|
+
- `align` (string, required): `"left"` | `"center"` | `"right"`
|
|
813
|
+
- `dithering` (boolean, required): Apply Floyd-Steinberg dithering for better quality on monochrome printers
|
|
814
|
+
- `size` (string, required): `"normal"` | `"double_width"` | `"double_height"` | `"quadruple"`
|
|
704
815
|
|
|
705
816
|
##### Logo
|
|
706
817
|
Prints a logo stored in the printer.
|
|
@@ -762,6 +873,234 @@ Changes the current global styles that will be applied to subsequent text sectio
|
|
|
762
873
|
|
|
763
874
|
---
|
|
764
875
|
|
|
876
|
+
## TypeScript Constants & Helpers
|
|
877
|
+
|
|
878
|
+
The plugin exports typed constants and builder functions so you never have to type raw strings.
|
|
879
|
+
|
|
880
|
+
### CodePage
|
|
881
|
+
|
|
882
|
+
Set the character encoding once in `PrinterOptions.code_page` and all text sections (`Title`, `Subtitle`, `Text`, `Table`) will use it automatically.
|
|
883
|
+
|
|
884
|
+
Each printer model assigns its own numbers to code pages, so `CodePage` accepts the raw page number directly via `codePage(n)`. Check your printer's manual for the correct value.
|
|
885
|
+
|
|
886
|
+
```typescript
|
|
887
|
+
import { codePage, CODE_PAGE, type CodePage } from "tauri-plugin-thermal-printer";
|
|
888
|
+
|
|
889
|
+
const options = {
|
|
890
|
+
cut_paper: true,
|
|
891
|
+
beep: false,
|
|
892
|
+
open_cash_drawer: false,
|
|
893
|
+
code_page: codePage(2), // sends ESC t 2 — CP850 on most Epson-compatible printers
|
|
894
|
+
};
|
|
895
|
+
```
|
|
896
|
+
|
|
897
|
+
| Value | Description |
|
|
898
|
+
|---|---|
|
|
899
|
+
| `codePage(n)` | Sends `ESC t n` with the given number. The user is responsible for choosing the correct value for their printer model. |
|
|
900
|
+
| `CODE_PAGE.ACCENT_REMOVER` | Removes accents and special characters by converting them to their ASCII equivalents (á→a, ß→ss, ¿→?, €→EUR). Useful when printers do not support alternative code pages. |
|
|
901
|
+
|
|
902
|
+
> **Note**: Without a `code_page`, accented characters (á, ñ, ü, etc.) will print as `?`. Set it once in `options` and it applies to the entire document.
|
|
903
|
+
|
|
904
|
+
---
|
|
905
|
+
|
|
906
|
+
### Style constants
|
|
907
|
+
|
|
908
|
+
Instead of typing raw strings you can import typed constant objects:
|
|
909
|
+
|
|
910
|
+
```typescript
|
|
911
|
+
import {
|
|
912
|
+
TEXT_ALIGN,
|
|
913
|
+
TEXT_SIZE,
|
|
914
|
+
TEXT_FONT,
|
|
915
|
+
BARCODE_TYPE,
|
|
916
|
+
BARCODE_TEXT_POSITION,
|
|
917
|
+
QR_ERROR_CORRECTION,
|
|
918
|
+
IMAGE_MODE,
|
|
919
|
+
CUT_MODE,
|
|
920
|
+
} from "tauri-plugin-thermal-printer";
|
|
921
|
+
|
|
922
|
+
// Examples:
|
|
923
|
+
const styles = {
|
|
924
|
+
align: TEXT_ALIGN.CENTER, // "center"
|
|
925
|
+
size: TEXT_SIZE.DOUBLE, // "double"
|
|
926
|
+
font: TEXT_FONT.B, // "B"
|
|
927
|
+
bold: true,
|
|
928
|
+
};
|
|
929
|
+
|
|
930
|
+
const barcode = {
|
|
931
|
+
barcode_type: BARCODE_TYPE.EAN13, // "EAN13"
|
|
932
|
+
text_position: BARCODE_TEXT_POSITION.BELOW, // "below"
|
|
933
|
+
};
|
|
934
|
+
|
|
935
|
+
const qr = {
|
|
936
|
+
error_correction: QR_ERROR_CORRECTION.M, // "M"
|
|
937
|
+
};
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
| Export | Values |
|
|
941
|
+
|---|---|
|
|
942
|
+
| `TEXT_ALIGN` | `LEFT` `CENTER` `RIGHT` |
|
|
943
|
+
| `TEXT_SIZE` | `NORMAL` `HEIGHT` `WIDTH` `DOUBLE` |
|
|
944
|
+
| `TEXT_FONT` | `A` `B` `C` |
|
|
945
|
+
| `BARCODE_TYPE` | `UPC_A` `UPC_E` `EAN13` `EAN8` `CODE39` `ITF` `CODABAR` `CODE93` `CODE128` |
|
|
946
|
+
| `BARCODE_TEXT_POSITION` | `NONE` `ABOVE` `BELOW` `BOTH` |
|
|
947
|
+
| `QR_ERROR_CORRECTION` | `L` `M` `Q` `H` |
|
|
948
|
+
| `IMAGE_MODE` | `NORMAL` `DOUBLE_WIDTH` `DOUBLE_HEIGHT` `QUADRUPLE` |
|
|
949
|
+
| `CUT_MODE` | `FULL` `PARTIAL` |
|
|
950
|
+
|
|
951
|
+
---
|
|
952
|
+
|
|
953
|
+
### Section builder helpers
|
|
954
|
+
|
|
955
|
+
Short helper functions to build section types without enum wrapper boilerplate:
|
|
956
|
+
|
|
957
|
+
```typescript
|
|
958
|
+
import {
|
|
959
|
+
title, subtitle, text, line, feed, cut, globalStyles,
|
|
960
|
+
beep, drawer, table, qr, barcode, dataMatrix, pdf417, image, logo,
|
|
961
|
+
TEXT_ALIGN, TEXT_SIZE, BARCODE_TYPE, QR_ERROR_CORRECTION,
|
|
962
|
+
} from "tauri-plugin-thermal-printer";
|
|
963
|
+
|
|
964
|
+
const sections = [
|
|
965
|
+
title("My Business"),
|
|
966
|
+
subtitle("Receipt #001"),
|
|
967
|
+
text("Thank you for your purchase!", { align: TEXT_ALIGN.CENTER }),
|
|
968
|
+
line("="),
|
|
969
|
+
qr("https://example.com/order/123", {
|
|
970
|
+
size: 6,
|
|
971
|
+
error_correction: QR_ERROR_CORRECTION.M,
|
|
972
|
+
}),
|
|
973
|
+
barcode("123456789012", BARCODE_TYPE.EAN13),
|
|
974
|
+
beep(),
|
|
975
|
+
text("Total: $50.00", { bold: true, size: TEXT_SIZE.DOUBLE }),
|
|
976
|
+
line("-"),
|
|
977
|
+
feed(3),
|
|
978
|
+
cut(),
|
|
979
|
+
];
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
| Helper | Description |
|
|
983
|
+
|---|---|
|
|
984
|
+
| `title(text, styles?)` | Creates a `{ Title: ... }` section |
|
|
985
|
+
| `subtitle(text, styles?)` | Creates a `{ Subtitle: ... }` section |
|
|
986
|
+
| `text(text, styles?)` | Creates a `{ Text: ... }` section |
|
|
987
|
+
| `line(character?)` | Creates a `{ Line: ... }` section (default `"-"`) |
|
|
988
|
+
| `feed(value, type?)` | Creates a `{ Feed: ... }` section (default `"lines"`) |
|
|
989
|
+
| `cut(mode?, feedLines?)` | Creates a `{ Cut: ... }` section (default `"partial"`, 4 lines) |
|
|
990
|
+
| `globalStyles(styles)` | Creates a `{ GlobalStyles: ... }` section |
|
|
991
|
+
| `beep(times?, duration?)` | Creates a `{ Beep: ... }` section (default `1`, `3`) |
|
|
992
|
+
| `drawer(pin?, pulse_time?)` | Creates a `{ Drawer: ... }` section (default `2`, `120`) |
|
|
993
|
+
| `table(columns, body, options?)` | Creates a `{ Table: ... }` section (`truncate` default `true`) |
|
|
994
|
+
| `qr(data, options?)` | Creates a `{ Qr: ... }` section (`size=6`, `error_correction="M"`, `model=2`) |
|
|
995
|
+
| `barcode(data, barcode_type?, options?)` | Creates a `{ Barcode: ... }` section (`CODE128`, `width=3`, `height=80`, `text_position="below"`) |
|
|
996
|
+
| `dataMatrix(data, size?)` | Creates a `{ DataMatrix: ... }` section (default `size=6`) |
|
|
997
|
+
| `pdf417(data, options?)` | Creates a `{ Pdf417: ... }` section (`columns=0`, `rows=0`, `width=2`, `height=3`, `error_correction=2`) |
|
|
998
|
+
| `image(data, options?)` | Creates a `{ Image: ... }` section (`max_width=0`, `align="center"`, `dithering=true`, `size="normal"`) |
|
|
999
|
+
| `logo(key_code, mode?)` | Creates a `{ Logo: ... }` section (default `mode="normal"`) |
|
|
1000
|
+
|
|
1001
|
+
### Helper example (all builders)
|
|
1002
|
+
|
|
1003
|
+
```typescript
|
|
1004
|
+
import {
|
|
1005
|
+
print_thermal_printer,
|
|
1006
|
+
type PrintJobRequest,
|
|
1007
|
+
title,
|
|
1008
|
+
subtitle,
|
|
1009
|
+
text,
|
|
1010
|
+
line,
|
|
1011
|
+
feed,
|
|
1012
|
+
cut,
|
|
1013
|
+
globalStyles,
|
|
1014
|
+
beep,
|
|
1015
|
+
drawer,
|
|
1016
|
+
table,
|
|
1017
|
+
qr,
|
|
1018
|
+
barcode,
|
|
1019
|
+
dataMatrix,
|
|
1020
|
+
pdf417,
|
|
1021
|
+
image,
|
|
1022
|
+
logo,
|
|
1023
|
+
TEXT_ALIGN,
|
|
1024
|
+
TEXT_SIZE,
|
|
1025
|
+
BARCODE_TYPE,
|
|
1026
|
+
BARCODE_TEXT_POSITION,
|
|
1027
|
+
QR_ERROR_CORRECTION,
|
|
1028
|
+
IMAGE_MODE,
|
|
1029
|
+
CODE_PAGE,
|
|
1030
|
+
} from "tauri-plugin-thermal-printer";
|
|
1031
|
+
|
|
1032
|
+
const job: PrintJobRequest = {
|
|
1033
|
+
printer: "TM-T20II",
|
|
1034
|
+
paper_size: "Mm80",
|
|
1035
|
+
options: {
|
|
1036
|
+
cut_paper: true,
|
|
1037
|
+
beep: false,
|
|
1038
|
+
open_cash_drawer: false,
|
|
1039
|
+
code_page: CODE_PAGE.WINDOWS_LATIN,
|
|
1040
|
+
},
|
|
1041
|
+
sections: [
|
|
1042
|
+
globalStyles({ align: TEXT_ALIGN.LEFT }),
|
|
1043
|
+
title("DEMO STORE"),
|
|
1044
|
+
subtitle("Receipt #A-1001"),
|
|
1045
|
+
text("Date: 2026-03-30 14:22"),
|
|
1046
|
+
line("="),
|
|
1047
|
+
table(
|
|
1048
|
+
3,
|
|
1049
|
+
[
|
|
1050
|
+
[text("1"), text("Americano"), text("$2.50", { align: TEXT_ALIGN.RIGHT })],
|
|
1051
|
+
[text("2"), text("Croissant"), text("$7.00", { align: TEXT_ALIGN.RIGHT })],
|
|
1052
|
+
],
|
|
1053
|
+
{
|
|
1054
|
+
column_widths: [6, 28, 14],
|
|
1055
|
+
header: [
|
|
1056
|
+
text("QTY", { bold: true }),
|
|
1057
|
+
text("ITEM", { bold: true }),
|
|
1058
|
+
text("TOTAL", { bold: true, align: TEXT_ALIGN.RIGHT }),
|
|
1059
|
+
],
|
|
1060
|
+
truncate: true,
|
|
1061
|
+
},
|
|
1062
|
+
),
|
|
1063
|
+
line("-"),
|
|
1064
|
+
text("Grand total: $9.50", { bold: true, size: TEXT_SIZE.DOUBLE, align: TEXT_ALIGN.RIGHT }),
|
|
1065
|
+
qr("https://example.com/r/A-1001", {
|
|
1066
|
+
size: 6,
|
|
1067
|
+
error_correction: QR_ERROR_CORRECTION.M,
|
|
1068
|
+
model: 2,
|
|
1069
|
+
align: TEXT_ALIGN.CENTER,
|
|
1070
|
+
}),
|
|
1071
|
+
barcode("123456789012", BARCODE_TYPE.EAN13, {
|
|
1072
|
+
width: 3,
|
|
1073
|
+
height: 70,
|
|
1074
|
+
text_position: BARCODE_TEXT_POSITION.BELOW,
|
|
1075
|
+
align: TEXT_ALIGN.CENTER,
|
|
1076
|
+
}),
|
|
1077
|
+
dataMatrix("A-1001", 6),
|
|
1078
|
+
pdf417("A-1001|TOTAL=9.50|PAID", {
|
|
1079
|
+
columns: 0,
|
|
1080
|
+
rows: 0,
|
|
1081
|
+
width: 2,
|
|
1082
|
+
height: 3,
|
|
1083
|
+
error_correction: 2,
|
|
1084
|
+
}),
|
|
1085
|
+
image("<BASE64_IMAGE>", {
|
|
1086
|
+
max_width: 0,
|
|
1087
|
+
align: TEXT_ALIGN.CENTER,
|
|
1088
|
+
dithering: true,
|
|
1089
|
+
size: IMAGE_MODE.NORMAL,
|
|
1090
|
+
}),
|
|
1091
|
+
logo(1, IMAGE_MODE.NORMAL),
|
|
1092
|
+
drawer(2, 120),
|
|
1093
|
+
beep(1, 3),
|
|
1094
|
+
feed(3),
|
|
1095
|
+
cut(),
|
|
1096
|
+
],
|
|
1097
|
+
};
|
|
1098
|
+
|
|
1099
|
+
await print_thermal_printer(job);
|
|
1100
|
+
```
|
|
1101
|
+
|
|
1102
|
+
---
|
|
1103
|
+
|
|
765
1104
|
## Examples
|
|
766
1105
|
|
|
767
1106
|
This section contains practical examples for different use cases. Each example demonstrates how to structure print jobs for various business scenarios.
|
|
@@ -1221,6 +1560,8 @@ const paymentReceipt: PrintJobRequest = {
|
|
|
1221
1560
|
};
|
|
1222
1561
|
```
|
|
1223
1562
|
|
|
1563
|
+
|
|
1564
|
+
|
|
1224
1565
|
---
|
|
1225
1566
|
|
|
1226
1567
|
### 📋 Summary
|