portakal-lite 0.0.1 → 2.0.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 +105 -7
- package/dist/index.cjs +19482 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +676 -0
- package/dist/index.d.ts +672 -15
- package/dist/index.mjs +19433 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +8 -9
- package/dist/builder.d.ts +0 -39
- package/dist/builder.js +0 -250
- package/dist/builder.js.map +0 -1
- package/dist/errors.d.ts +0 -11
- package/dist/errors.js +0 -18
- package/dist/errors.js.map +0 -1
- package/dist/index.js +0 -17
- package/dist/index.js.map +0 -1
- package/dist/lang/tsc.d.ts +0 -16
- package/dist/lang/tsc.js +0 -217
- package/dist/lang/tsc.js.map +0 -1
- package/dist/lang/zpl.d.ts +0 -16
- package/dist/lang/zpl.js +0 -262
- package/dist/lang/zpl.js.map +0 -1
- package/dist/languages/tsc.d.ts +0 -3
- package/dist/languages/tsc.js +0 -161
- package/dist/languages/tsc.js.map +0 -1
- package/dist/languages/zpl.d.ts +0 -3
- package/dist/languages/zpl.js +0 -205
- package/dist/languages/zpl.js.map +0 -1
- package/dist/profiles.d.ts +0 -61
- package/dist/profiles.js +0 -102
- package/dist/profiles.js.map +0 -1
- package/dist/raster.d.ts +0 -39
- package/dist/raster.js +0 -204
- package/dist/raster.js.map +0 -1
- package/dist/receipt.d.ts +0 -22
- package/dist/receipt.js +0 -91
- package/dist/receipt.js.map +0 -1
- package/dist/types.d.ts +0 -336
- package/dist/types.js +0 -6
- package/dist/types.js.map +0 -1
- package/dist/utils.d.ts +0 -15
- package/dist/utils.js +0 -28
- package/dist/utils.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Integrates [etiket](https://github.com/productdevbook/etiket) package for seamle
|
|
|
5
5
|
|
|
6
6
|
- Fluent `label()` builder — text, boxes, lines, circles, ellipses, reverse/erase regions, images, raw commands
|
|
7
7
|
- `.barcode()` / `.qrcode()` — 40+ symbologies via [etiket](https://github.com/productdevbook/etiket)
|
|
8
|
-
- `tsc.compile()` / `zpl.compile()` → **printer-ready
|
|
8
|
+
- `tsc.compile()` / `zpl.compile()` → **printer-ready output** — TSC as a `Uint8Array` (binary bitmap payload), ZPL as a string. No transport, no connection — you send it.
|
|
9
9
|
- `tsc.preview()` / `zpl.preview()` → SVG rendering with per-language font metrics
|
|
10
10
|
- Receipt layout helpers: `formatPair`, `formatRow`, `formatTable`, `separator`, `wordWrap`
|
|
11
11
|
- One runtime dependency (`etiket`, itself zero-dep), pure ESM, works in Node, browsers, Deno, Bun
|
|
@@ -32,6 +32,21 @@ const zplCode = zpl.compile(myLabel); // ZPL II commands
|
|
|
32
32
|
const svg = zpl.preview(myLabel); // SVG preview
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
### Fonts
|
|
36
|
+
|
|
37
|
+
`.text()` accepts any TSC font id via `font`:
|
|
38
|
+
|
|
39
|
+
- `"0"` — the scalable TrueType font. `size`/`xScale` are point sizes (or
|
|
40
|
+
multipliers of `fontBase` per `font0Mode`), with independent X/Y.
|
|
41
|
+
- `"1"`–`"8"` — fixed-pitch dot fonts (`TSC_DOT_FONTS`): `size`/`xScale` are
|
|
42
|
+
integer multipliers 1–10 of the base dot size (8×12, 12×20, 16×24, 24×32,
|
|
43
|
+
32×48, 14×19 OCR-B, 21×27 OCR-B, 14×25 OCR-A).
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
label({ width: 40, height: 30 }).text("CUT: 9.00 m", { x: 10, y: 10, font: "3", size: 3, xScale: 2 });
|
|
47
|
+
// → TEXT 10,10,"3",0,2,3,"CUT: 9.00 m"
|
|
48
|
+
```
|
|
49
|
+
|
|
35
50
|
## Barcodes & QR codes
|
|
36
51
|
|
|
37
52
|
```ts
|
|
@@ -57,25 +72,84 @@ Barcode options: `x`, `y`, `height`, `moduleWidth`, `ratio`, `rotation`, `readab
|
|
|
57
72
|
|
|
58
73
|
QR options: `x`, `y`, `cellSize`, `ecc` (`L`/`M`/`Q`/`H`), `rotation`, `version`, `mode`, `mask`, `eci`, `gs1`.
|
|
59
74
|
|
|
60
|
-
###
|
|
75
|
+
### Sending to a printer
|
|
61
76
|
|
|
62
|
-
|
|
77
|
+
`tsc.compile()` returns a **`Uint8Array`**, not a string: the text commands are
|
|
78
|
+
ASCII, but a `BITMAP` payload is raw packed pixels. Send those bytes as-is — the
|
|
79
|
+
compiler has already concatenated the whole stream for you. `zpl.compile()`
|
|
80
|
+
returns a string (ZPL has no binary payload).
|
|
63
81
|
|
|
64
82
|
```ts
|
|
65
83
|
import { label, tsc } from "portakal-lite";
|
|
66
84
|
import net from "node:net";
|
|
67
85
|
|
|
68
|
-
const
|
|
86
|
+
const bytes = tsc.compile(
|
|
69
87
|
label({ width: 40, height: 30 }).text("Hello", { x: 10, y: 10 }),
|
|
70
88
|
);
|
|
71
89
|
|
|
72
90
|
// TCP label printers usually listen on port 9100
|
|
73
91
|
const socket = net.createConnection({ host: "192.168.1.100", port: 9100 });
|
|
74
|
-
socket.write(
|
|
92
|
+
socket.write(bytes);
|
|
75
93
|
socket.end();
|
|
76
94
|
|
|
77
95
|
// ...or write to a file for a print spooler
|
|
78
|
-
// fs.writeFileSync("label.prn",
|
|
96
|
+
// fs.writeFileSync("label.prn", bytes);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Do **not** decode the output to text before sending. `new TextDecoder().decode(bytes)`,
|
|
100
|
+
`String.fromCharCode(...bytes)`, `bytes.toString()` and `JSON.stringify(bytes)` all
|
|
101
|
+
mangle bytes ≥ `0x80` and change the total length, so the printer reads the wrong
|
|
102
|
+
byte count — images print as noise, while text-only labels still look fine
|
|
103
|
+
because those bytes are pure ASCII.
|
|
104
|
+
|
|
105
|
+
For HTTP, post the bytes directly (no encoding needed):
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
await fetch("/print", {
|
|
109
|
+
method: "POST",
|
|
110
|
+
headers: { "Content-Type": "application/octet-stream" },
|
|
111
|
+
body: bytes, // React Native: new Blob([bytes], { type: "application/octet-stream" })
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
If a transport only accepts a `string` (some BLE and Expo bridges), wrap the
|
|
116
|
+
bytes losslessly with base64 and let the transport decode them:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import { bytesToBase64, chunkBytes } from "portakal-lite";
|
|
120
|
+
|
|
121
|
+
await ble.write(deviceId, characteristicId, bytesToBase64(bytes));
|
|
122
|
+
|
|
123
|
+
// MTU-limited link? Split the BYTES, then encode each chunk — never split
|
|
124
|
+
// an encoded string.
|
|
125
|
+
for (const chunk of chunkBytes(bytes, 180)) {
|
|
126
|
+
await ble.write(deviceId, characteristicId, bytesToBase64(chunk));
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
TSC output uses LF (`\n`) line endings by default. If your printer firmware
|
|
131
|
+
requires CRLF, pass `lineEnding: "\r\n"` (either to `label()` or as the second
|
|
132
|
+
argument to `tsc.compile()`):
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const commands = tsc.compile(
|
|
136
|
+
label({ width: 40, height: 30, lineEnding: "\r\n" }).text("Hello", { x: 10, y: 10 }),
|
|
137
|
+
);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Showing the output
|
|
141
|
+
|
|
142
|
+
`formatTSCBytes` (or `tsc.text(builder)`) renders the stream for display — ASCII
|
|
143
|
+
commands verbatim, with any binary `BITMAP` payload elided. Use it for a UI, a
|
|
144
|
+
log, or a "show compiled commands" panel; never send it in place of the bytes.
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
import { formatTSCBytes, tsc } from "portakal-lite";
|
|
148
|
+
|
|
149
|
+
formatTSCBytes(bytes);
|
|
150
|
+
// 'SIZE 40 mm,30 mm\nCLS\nTEXT 10,10,"2",0,1,1,"Hello"\nPRINT 1\n'
|
|
151
|
+
|
|
152
|
+
tsc.text(builder); // an image label shows: '… BITMAP 10,10,2,16,0,<32 bytes of bitmap data>\nPRINT 1\n'
|
|
79
153
|
```
|
|
80
154
|
|
|
81
155
|
### Receipt-style aligned lines
|
|
@@ -125,6 +199,29 @@ const b = label({ width: 40, height: 30 })
|
|
|
125
199
|
|
|
126
200
|
`MonochromeBitmap` is a 1-bit packed `Uint8Array`: `{ data, width, height, bytesPerRow }` with `bytesPerRow === Math.ceil(width / 8)`.
|
|
127
201
|
|
|
202
|
+
### Images
|
|
203
|
+
|
|
204
|
+
Raster graphics need packed 1-bit pixels. `toMonochromeBitmap` converts raw
|
|
205
|
+
grayscale or RGB/RGBA pixels (e.g. a decoded photo) into that shape, with
|
|
206
|
+
threshold or error-diffusion dithering:
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
import { label, tsc, toMonochromeBitmap } from "portakal-lite";
|
|
210
|
+
|
|
211
|
+
// pixels: row-major, 1 (grayscale), 3 (RGB) or 4 (RGBA) bytes per pixel.
|
|
212
|
+
const bitmap = toMonochromeBitmap(pixels, width, height, {
|
|
213
|
+
dither: "floyd-steinberg", // "threshold" | "floyd-steinberg" | "atkinson" | "ordered"
|
|
214
|
+
threshold: 128, // luminance cutoff (default 128)
|
|
215
|
+
invert: false,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
const myLabel = label({ width: 40, height: 30 }).image(bitmap, { x: 20, y: 60 });
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
RGBA is composited over white, so transparent areas print as unmarked paper.
|
|
222
|
+
Note that TSC `BITMAP` cannot scale — emit the bitmap at the size you want
|
|
223
|
+
printed (ZPL `^GFA` is fixed-size too). See [`examples/image-label.js`](./examples/image-label.js).
|
|
224
|
+
|
|
128
225
|
## Examples
|
|
129
226
|
|
|
130
227
|
Runnable examples live in [`examples/`](./examples) — build the package first (`npm run build`), then run any:
|
|
@@ -134,6 +231,7 @@ node examples/basic-label.js # text + box + Code 128 + QR, both language
|
|
|
134
231
|
node examples/shipping-label.js # shipping label with tracking barcode + QR
|
|
135
232
|
node examples/receipt-label.js # receipt-style label with order barcode
|
|
136
233
|
node examples/max-symbologies.js # native + rasterized (EAN-13, UPC-A, Code 39, ITF, DataMatrix, PDF417, Aztec)
|
|
234
|
+
node examples/image-label.js # dithered bitmap image (BITMAP / ^GFA)
|
|
137
235
|
```
|
|
138
236
|
|
|
139
237
|
## Security
|
|
@@ -152,7 +250,7 @@ The compilers are hardened against command injection — the most important thin
|
|
|
152
250
|
|
|
153
251
|
## Differences from portakal
|
|
154
252
|
|
|
155
|
-
`portakal-lite` keeps the label builder, TSC/ZPL compilers, per-language preview, receipt helpers, and adds barcode/QR support backed by etiket
|
|
253
|
+
`portakal-lite` keeps the label builder, TSC/ZPL compilers, per-language preview, receipt helpers, and adds barcode/QR support backed by etiket plus image dithering via `toMonochromeBitmap()`. It drops the other 7 languages, parsers, `validate()`, cross-compiler, encoding engine, and the transport layer. Behavior of the generated TSC/ZPL commands is identical to portakal's, plus the hardening above.
|
|
156
254
|
|
|
157
255
|
## License
|
|
158
256
|
|