### Install Portakal SDK
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Install the Portakal SDK using npm. This is the first step to start generating printer commands.
```sh
npm install portakal
```
--------------------------------
### Install Dependencies with pnpm
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Use this command to install all necessary project dependencies before running or developing.
```bash
pnpm install
```
--------------------------------
### HTML-like Label Markup Example
Source: https://github.com/productdevbook/portakal/blob/main/web/index.html
This example demonstrates how to define a label using an HTML-like markup language. It includes text elements, lines, and boxes with specified dimensions and styles.
```html
ACME Corp SKU: PRD-00123
```
--------------------------------
### Configure Label Builder Options
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Initialize a label builder with various configuration options to control label dimensions, printer settings, and spacing. This setup is essential for defining the physical characteristics of the label.
```typescript
const builder = label({
width: 40, // Label width
height: 30, // Label height (omit for receipt/continuous)
unit: "mm", // "mm" | "inch" | "dot" (default: "mm")
dpi: 203, // Printer DPI (default: 203)
gap: 3, // Gap between labels in mm (default: 3)
speed: 4, // Print speed 1-10 (default: 4)
density: 8, // Darkness 0-15 (default: 8)
copies: 1, // Number of copies (default: 1)
});
```
--------------------------------
### ZPL Test Label Example
Source: https://github.com/productdevbook/portakal/blob/main/README.md
This ZPL code defines a test label. Paste it into the Portakal Playground's Validate tab (select ZPL) for comparison with Labelary or a physical printer.
```zpl
^XA
^CF0,60
^FO50,50^GB100,100,100^FS
^FO75,75^FR^GB100,100,100^FS
^FO93,93^GB40,40,40^FS
^FO220,50^FDIntershipping, Inc.^FS
^CF0,30
^FO220,115^FD1000 Shipping Lane^FS
^FO220,155^FDShelbyville TN 38102^FS
^FO50,250^GB700,3,3^FS
^CFA,30
^FO50,300^FDJohn Doe^FS
^FO50,340^FD100 Main Street^FS
^FO50,380^FDSpringfield TN 39021^FS
^BY5,2,270
^FO100,550^BC^FD12345678^FS
^FO50,900^GB700,250,3^FS
^FO400,900^GB3,250,3^FS
^CF0,40
^FO100,960^FDCtr. X34B-1^FS
^CF0,190
^FO470,955^FDCA^FS
^XZ
```
--------------------------------
### Generate and Send Printer Commands via TCP and WebUSB
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Portakal generates commands; you handle the transport. This example shows sending TSC commands over TCP and ESC/POS commands via WebUSB.
```typescript
import { label } from "portakal/core";
import { tsc } from "portakal/lang/tsc";
import { escpos } from "portakal/lang/escpos";
import net from "node:net";
const myLabel = label({ width: 40, height: 30 }).text("Hello", { x: 10, y: 10 });
const commands = tsc.compile(myLabel);
// TCP (port 9100)
const socket = net.createConnection({ host: "192.168.1.100", port: 9100 });
socket.write(commands);
socket.end();
// ESC/POS (binary) over WebUSB
const receipt = label({ width: 80 }).text("Receipt");
const bytes = escpos.compile(receipt);
await usbDevice.transferOut(endpointNumber, bytes);
```
--------------------------------
### Add Box Element with `.box()`
Source: https://context7.com/productdevbook/portakal/llms.txt
Draws a rectangle border or filled box with customizable thickness and rounded corners. The example compiles to ESC/POS format.
```typescript
import { label } from "portakal";
import { escpos } from "portakal/lang/escpos";
const lbl = label({ width: 80, unit: "mm" })
.box({ x: 5, y: 5, width: 550, height: 300, thickness: 3, radius: 8 })
.box({ x: 10, y: 10, width: 100, height: 100, thickness: 50 }); // filled (thickness >= min dim)
const bytes: Uint8Array = escpos.compile(lbl);
// send bytes to printer over USB/TCP/BLE
```
--------------------------------
### Add Image Element with `.image()`
Source: https://context7.com/productdevbook/portakal/llms.txt
Embeds a monochrome bitmap image into the label. Requires pre-dithering using `imageToMonochrome`. Supports scaling to a target size. The example compiles to ZPL II format.
```typescript
import { label, imageToMonochrome } from "portakal";
import { zpl } from "portakal/lang/zpl";
// e.g. from a element
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d")!;
// ... draw onto canvas ...
const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const bitmap = imageToMonochrome(imgData.data, canvas.width, canvas.height, {
dither: "floyd-steinberg", // "threshold" | "floyd-steinberg" | "atkinson" | "ordered"
threshold: 128,
});
const lbl = label({ width: 40, height: 30, unit: "mm" })
.image(bitmap, { x: 10, y: 10, width: 200, height: 100 });
console.log(zpl.compile(lbl));
// ^XA^PW332^LL240^GFA,...^XZ
```
--------------------------------
### Build and Script Commands
Source: https://github.com/productdevbook/portakal/blob/main/AGENTS.md
Common commands for building, developing, linting, formatting, testing, and releasing the Portakal project.
```bash
pnpm build # obuild (rolldown)
pnpm dev # vitest watch
pnpm lint # oxlint + oxfmt --check
pnpm lint:fix # oxlint --fix + oxfmt
pnpm fmt # oxfmt
pnpm test # pnpm lint && pnpm typecheck && vitest run
pnpm typecheck # tsgo --noEmit
pnpm release # pnpm test && pnpm build && bumpp
```
--------------------------------
### Add Line Element with `.line()`
Source: https://context7.com/productdevbook/portakal/llms.txt
Draws a straight line or diagonal between two points with specified thickness. The example compiles to TSC/TSPL2 format.
```typescript
import { label } from "portakal";
import { tsc } from "portakal/lang/tsc";
const lbl = label({ width: 40, height: 30, unit: "mm" })
.line({ x1: 5, y1: 80, x2: 315, y2: 80, thickness: 2 }) // horizontal rule
.line({ x1: 160, y1: 5, x2: 160, y2: 230, thickness: 1 }) // vertical divider
.line({ x1: 5, y1: 5, x2: 100, y2: 100, thickness: 1 }); // diagonal
console.log(tsc.compile(lbl));
```
--------------------------------
### Build for Production with pnpm
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Generate a production-ready build of the project.
```bash
pnpm build
```
--------------------------------
### Create and Print a Label with ZPL
Source: https://github.com/productdevbook/portakal/blob/main/AGENTS.md
Demonstrates creating a label with text, barcode, QR code, and an image using the fluent API, then compiling it to ZPL II commands and generating an SVG preview. Import 'label' from 'portakal/core' and the specific language module (e.g., 'zpl' from 'portakal/lang/zpl').
```typescript
import { label } from "portakal/core";
import { zpl } from "portakal/lang/zpl";
const myLabel = label({ width: 40, height: 30, unit: "mm" })
.text("Hello World", { x: 10, y: 10, font: "A", size: 2 })
.barcode("123456789", { x: 10, y: 50, type: "code128", height: 60 })
.qrcode("https://example.com", { x: 10, y: 120, size: 6 })
.image(buffer, { x: 200, y: 10, width: 100 })
.print(2);
const code = zpl.compile(myLabel); // ZPL II commands
const svg = zpl.preview(myLabel); // SVG preview with ZPL font metrics
```
--------------------------------
### Add Text Element with `.text()`
Source: https://context7.com/productdevbook/portakal/llms.txt
Adds text to the label with options for positioning, font, size, rotation, and styling. Supports word-wrapping with `maxWidth`. The example shows compilation to TSC/TSPL2 format.
```typescript
import { label } from "portakal";
import { tsc } from "portakal/lang/tsc";
const lbl = label({ width: 40, height: 30, unit: "mm" })
.text("ACME Corp", { x: 10, y: 10, font: "2", size: 2, bold: true })
.text("SKU: PRD-00123", { x: 10, y: 50, size: 1 })
.text("SALE", { x: 200, y: 80, size: 3, reverse: true })
.text("Long description that should wrap", { x: 10, y: 130, maxWidth: 300, align: "left" })
.text("Rotated", { x: 50, y: 200, rotation: 90 });
console.log(tsc.compile(lbl));
// SIZE 40 mm,30 mm\nGAP 3 mm,0 mm\nCLS\nTEXT 10,10,"2",0,2,2,"ACME Corp"\n...PRINT 1,1
```
--------------------------------
### Core Label Building and Language Module Usage
Source: https://github.com/productdevbook/portakal/blob/main/AGENTS.md
Demonstrates how to use the core `label` builder to construct a label and then compile it using a specific language module like ZPL.
```APIDOC
## Core Label Building and Language Module Usage
### Description
This example shows how to create a label object using the fluent API and then compile it into printer-specific commands using a language module. It also demonstrates generating an SVG preview.
### Usage
```ts
import { label } from "portakal/core";
import { zpl } from "portakal/lang/zpl";
const myLabel = label({ width: 40, height: 30, unit: "mm" })
.text("Hello World", { x: 10, y: 10, font: "A", size: 2 })
.barcode("123456789", { x: 10, y: 50, type: "code128", height: 60 })
.qrcode("https://example.com", { x: 10, y: 120, size: 6 })
.image(buffer, { x: 200, y: 10, width: 100 })
.print(2);
const code = zpl.compile(myLabel); // ZPL II commands
const svg = zpl.preview(myLabel); // SVG preview with ZPL font metrics
```
```
--------------------------------
### Import Available Language Modules
Source: https://github.com/productdevbook/portakal/blob/main/AGENTS.md
Shows how to import various language modules for different printer types. Each module provides 'compile()', 'parse()', 'preview()', and 'validate()' functions.
```typescript
import { tsc } from "portakal/lang/tsc"; // TSC/TSPL2
import { zpl } from "portakal/lang/zpl"; // Zebra ZPL II
import { epl } from "portakal/lang/epl"; // Eltron EPL2
import { escpos } from "portakal/lang/escpos"; // ESC/POS
import { cpcl } from "portakal/lang/cpcl"; // Comtec CPCL
import { dpl } from "portakal/lang/dpl"; // Datamax DPL
import { ipl } from "portakal/lang/ipl"; // Intermec IPL
import { sbpl } from "portakal/lang/sbpl"; // SATO SBPL
import { starprnt } from "portakal/lang/starprnt"; // Star PRNT
```
--------------------------------
### Utilize Portakal Language Modules for Compilation and More
Source: https://context7.com/productdevbook/portakal/llms.txt
Each language module (e.g., `tsc`, `zpl`, `escpos`) provides methods for `compile()`, `parse()`, `preview()`, and `validate()`. Import only the necessary modules for tree-shaking. The `compile()` method converts a `LabelBuilder` object into printer commands, while `parse()` converts commands back into structured data.
```typescript
import { label } from "portakal/core";
import { tsc } from "portakal/lang/tsc";
import { zpl } from "portakal/lang/zpl";
import { epl } from "portakal/lang/epl";
import { escpos } from "portakal/lang/escpos";
import { cpcl } from "portakal/lang/cpcl";
import { dpl } from "portakal/lang/dpl";
import { sbpl } from "portakal/lang/sbpl";
import { starprnt } from "portakal/lang/starprnt";
import { ipl } from "portakal/lang/ipl";
const lbl = label({ width: 40, height: 30, unit: "mm" })
.text("Hello World", { x: 10, y: 10, size: 2 })
.box({ x: 5, y: 5, width: 310, height: 230, thickness: 2 });
// compile: LabelBuilder → printer commands
const tscCode: string = tsc.compile(lbl); // TSC/TSPL2
const zplCode: string = zpl.compile(lbl); // ZPL II
const eplCode: string = epl.compile(lbl); // EPL2
const escposBytes: Uint8Array = escpos.compile(lbl); // ESC/POS binary
const cpclCode: string = cpcl.compile(lbl); // CPCL
const dplCode: string = dpl.compile(lbl); // DPL
const sbplCode: string = sbpl.compile(lbl); // SBPL
const starCode: string = starprnt.compile(lbl); // Star PRNT
const iplCode: string = ipl.compile(lbl); // IPL
// preview: LabelBuilder → SVG string (per-language font metrics)
const svg: string = zpl.preview(lbl);
// parse: printer commands → structured data
const parsed = tsc.parse(tscCode);
// { commands: [...], elements: [...], widthDots: 332, heightDots: 240 }
// validate: printer commands → error report
const result = zpl.validate(zplCode);
// { valid: true, errors: 0, warnings: 0, infos: 0, issues: [] }
// validate with errors
const bad = zpl.validate("^FO10,10^FDMissing XA/XZ^FS");
console.log(bad.valid); // false
console.log(bad.errors); // 2
console.log(bad.issues);
// [
// { level: "error", command: "^XA", message: "Label must start with ^XA" },
// { level: "error", command: "^XZ", message: "Label must end with ^XZ" },
// ]
```
--------------------------------
### Encode Text for ESC/POS Printers with Portakal
Source: https://context7.com/productdevbook/portakal/llms.txt
Use `encodeText` to get UTF-8 string segments with code page information, or `encodeTextForPrinter` to directly generate a `Uint8Array` with ESC/POS switch commands. `isASCII` provides a quick check for plain ASCII strings.
```typescript
import { encodeText, encodeTextForPrinter, isASCII, CODE_PAGES } from "portakal";
// isASCII: fast check before encoding
console.log(isASCII("Hello World")); // true
console.log(isASCII("Héllo")); // false
// encodeText: returns segments with code page info
const segments = encodeText("Café €10");
// [
// { codePage: -1, data: Uint8Array([67,97,102]) }, // "Caf" — ASCII, no switch
// { codePage: 0, data: Uint8Array([130]) }, // "é" in CP437
// { codePage: -1, data: Uint8Array([32]) }, // " " — ASCII
// { codePage: 19, data: Uint8Array([213, 49, 48]) }, // "€10" in CP858 (€ = 0xD5)
// ]
// encodeTextForPrinter: includes ESC t n switch commands
const bytes = encodeTextForPrinter("Café €10");
// Uint8Array with ESC t 0 + "Caf" + ESC t 0 + 0x82 + ESC t 19 + 0xD5 + "10"
console.log(CODE_PAGES.map((cp) => cp.name)); // ["CP437","CP858","CP1252","CP866","CP857"]
```
--------------------------------
### Run All Tests with pnpm
Source: https://github.com/productdevbook/portakal/blob/main/AGENTS.md
Execute all tests in the project using the pnpm test command.
```bash
pnpm test
```
--------------------------------
### Module Operations: Compile, Parse, Preview, Validate
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Illustrates the core operations available for each Portakal language module, including compiling a label to printer commands, previewing as SVG, parsing commands back into structured data, and validating command syntax.
```ts
import { tsc } from "portakal/lang/tsc";
// Compile: label → printer commands
tsc.compile(myLabel);
// Preview: label → SVG (per-language font metrics)
tsc.preview(myLabel);
// Parse: printer commands → structured data
tsc.parse(tscCode); // { commands, elements, widthDots, ... }
// Validate: check for errors
tsc.validate(tscCode); // { valid, errors, issues }
```
--------------------------------
### Compile a Label to Multiple Printer Languages
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Demonstrates how to compile the same label definition into commands for various printer languages including TSC/TSPL2, Zebra ZPL II, Eltron EPL2, and ESC/POS. This highlights Portakal's universal API.
```ts
import { label } from "portakal/core";
import { tsc } from "portakal/lang/tsc";
import { zpl } from "portakal/lang/zpl";
import { epl } from "portakal/lang/epl";
import { escpos } from "portakal/lang/escpos";
const myLabel = label({ width: 40, height: 30, unit: "mm" }).text("Hello World", {
x: 10,
y: 10,
size: 2,
});
tsc.compile(myLabel); // TSC/TSPL2 — TSC, Gprinter, Xprinter, iDPRT
zpl.compile(myLabel); // Zebra ZPL II — GK420, ZT410, ZD620
epl.compile(myLabel); // Eltron EPL2 — LP/TLP 2824, GX420, ZD220
escpos.compile(myLabel); // ESC/POS — Epson, Bixolon, Star, Citizen (Uint8Array)
```
--------------------------------
### Create Label Builder with `label()`
Source: https://context7.com/productdevbook/portakal/llms.txt
Initializes a LabelBuilder instance. Width is required; height is optional for continuous/receipt mode. Supports standard units, DPI, and built-in printer profiles.
```typescript
import { label } from "portakal";
// Standard label (mm units, 203 DPI)
const lbl = label({ width: 40, height: 30, unit: "mm", dpi: 203, gap: 3, density: 8, copies: 1 });
// With a built-in printer profile (auto-sets DPI and paper width)
const lbl2 = label({ printer: "tsc-te310", width: 40, height: 30 }); // 300 DPI
// Receipt / continuous mode (no height)
const receipt = label({ width: 80, unit: "mm" });
```
--------------------------------
### Run Tests in Watch Mode with pnpm
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Execute tests continuously in watch mode for rapid feedback during development.
```bash
pnpm dev
```
--------------------------------
### Create a Receipt with ESC/POS
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Generate a store receipt using the Portakal core API and compile it into ESC/POS byte format using the `escpos` module. An SVG preview of the receipt can also be generated.
```ts
import { label } from "portakal/core";
import { escpos } from "portakal/lang/escpos";
const receipt = label({ width: 80, unit: "mm" })
.text("MY STORE", { align: "center", bold: true, size: 2 })
.text("123 Market St", { align: "center" })
.text("================================")
.text("Hamburger x2 $25.98")
.text("Cola x1 $3.50")
.text("================================")
.text("TOTAL $29.48", { bold: true, size: 2 });
const bytes = escpos.compile(receipt); // Uint8Array
const svg = escpos.preview(receipt); // Receipt-style SVG
```
--------------------------------
### Run Single Test File with pnpm
Source: https://github.com/productdevbook/portakal/blob/main/AGENTS.md
Execute a specific test file using the pnpm vitest run command, specifying the file path.
```bash
pnpm vitest run test/.test.ts
```
--------------------------------
### convert(code, from, to, options?)
Source: https://context7.com/productdevbook/portakal/llms.txt
Translates printer commands from one language to another via an intermediate element representation. Supports 7 source languages × 9 target languages = 63 conversion paths.
```APIDOC
## `convert(code, from, to, options?)` — Cross-Language Converter
Translates printer commands from one language to another via an intermediate element representation. Supports 7 source languages × 9 target languages = 63 conversion paths.
```ts
import { convert, SUPPORTED_SOURCES, SUPPORTED_TARGETS } from "portakal";
const tscCode = `SIZE 40 mm,30 mm\nGAP 3 mm,0\nCLS\nTEXT 10,10,"2",0,1,1,"Hello"\nPRINT 1,1`;
// TSC → ZPL
const r1 = convert(tscCode, "tsc", "zpl");
console.log(r1.output); // "^XA^PW332^LL240^FO10,10^A0N,20,20^FDHello^FS^XZ"
console.log(r1.warnings); // []
// ZPL → ESC/POS (returns Uint8Array)
const zplCode = "^XA^PW576^FO10,10^A0N,30,30^FDReceipt^FS^XZ";
const r2 = convert(zplCode, "zpl", "escpos", { dpi: 203, density: 10 });
console.log(r2.output instanceof Uint8Array); // true
// EPL → CPCL
const eplCode = `\nq609\nB10,10,0,1,2,5,40,B,"12345678"\nP1\n`;
const r3 = convert(eplCode, "epl", "cpcl");
console.log(r3.widthDots, r3.heightDots); // 609, 240
console.log(SUPPORTED_SOURCES); // ["tsc","zpl","epl","cpcl","dpl","sbpl","ipl"]
console.log(SUPPORTED_TARGETS); // ["tsc","zpl","epl","escpos","cpcl","dpl","sbpl","starprnt","ipl"]
```
```
--------------------------------
### Inject Raw Printer Commands with Portakal
Source: https://context7.com/productdevbook/portakal/llms.txt
Use the `.raw()` method to insert printer-specific commands directly into the output. This method accepts either a string for text-based languages or a `Uint8Array` for binary data like ESC/POS.
```typescript
import { label } from "portakal";
import { tsc } from "portakal/lang/tsc";
import { escpos } from "portakal/lang/escpos";
// TSC-specific cutter command
const tscLabel = label({ width: 40, height: 30, unit: "mm" })
.text("Hello", { x: 10, y: 10 })
.raw("SET CUTTER ON");
// ZPL field escape
const zplLabel = label({ width: 40, height: 30, unit: "mm" })
.raw("^FO10,10^FDCustom ZPL field^FS");
// ESC/POS cash drawer open via raw bytes
const receiptLabel = label({ width: 80, unit: "mm" })
.text("Thank you!")
.raw(new Uint8Array([0x1b, 0x70, 0x00, 0x32, 0x32])); // open cash drawer
const bytes = escpos.compile(receiptLabel);
```
--------------------------------
### Manage Printer Profiles with Portakal
Source: https://context7.com/productdevbook/portakal/llms.txt
Retrieve hardware capability profiles for various printer models using `getProfile`, `listProfiles`, `findByVendorId`, or `findByLanguage`. These profiles contain details like DPI, paper width, and supported features, enabling auto-configuration.
```typescript
import { getProfile, listProfiles, findByVendorId, findByLanguage, label } from "portakal";
// Look up a specific model
const epson = getProfile("epson-tm-t88vi");
console.log(epson?.dpi); // 203
console.log(epson?.paperWidth); // 80
console.log(epson?.features.cutter); // "partial"
console.log(epson?.features.cashDrawer); // true
// Auto-configure label from profile
const lbl = label({ printer: "tsc-te310", width: 40, height: 30 }); // DPI=300 auto-set
// List all profile IDs
console.log(listProfiles());
// ["epson-tm-t88vi","epson-tm-t88v","star-tsp143","zebra-zd420","tsc-te310",...]
// Find all Epson printers by USB vendor ID
const epsonPrinters = findByVendorId(0x04b8);
console.log(epsonPrinters.map(p => p.name));
// ["Epson TM-T88VI","Epson TM-T88V","Epson TM-T20III","Epson TM-m30II"]
// Find all ZPL printers
const zplPrinters = findByLanguage("zpl");
console.log(zplPrinters.map(p => p.name));
// ["Zebra ZD420","Zebra ZT410"]
```
--------------------------------
### Auto-Configure Printer Settings with Portakal Profiles
Source: https://github.com/productdevbook/portakal/blob/main/README.md
The `label` function can auto-configure DPI and paper width based on the specified printer model. Use `getProfile` or `findByVendorId` to look up printer profiles.
```typescript
import { label, getProfile, findByVendorId } from "portakal";
// Auto-DPI from profile
label({ width: 40, height: 30, printer: "tsc-te310" }); // 300 DPI
label({ width: 80, printer: "epson-tm-t88vi" }); // 203 DPI
// Lookup profiles
getProfile("zebra-zd420"); // { name, dpi, paperWidth, ... }
findByVendorId(0x04b8); // All Epson printers
```
--------------------------------
### Language Module Methods
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Interact with different printer language modules for compiling, previewing, parsing, and validating printer commands.
```APIDOC
## Language Module Methods
Each language module (`tsc`, `zpl`, `epl`, `cpcl`, `dpl`, `sbpl`, `escpos`, `starprnt`, `ipl`) provides the following methods:
| Method | Output | Description |
| :-------------------- | :----------------------- | :--------------------------------------- |
| `lang.compile(label)` | `string` or `Uint8Array` | Compile to printer commands |
| `lang.preview(label)` | `string` | SVG preview with language-specific fonts |
| `lang.parse(code)` | `object` | Parse printer commands → structured data |
| `lang.validate(code)` | `object` | Validate commands for errors/warnings |
### Example Usage
```ts
import { tsc } from "portakal/lang/tsc";
const myLabel = label({ width: 40, height: 30 });
const compiledCode = tsc.compile(myLabel);
const svgPreview = tsc.preview(myLabel);
const parsedData = tsc.parse(compiledCode);
const validationResult = tsc.validate(compiledCode);
```
```
--------------------------------
### Format Multi-Column Tables for Receipts
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Organize data into multi-column tables for receipts using `formatTable`. Define column widths and alignment, then provide the data rows.
```typescript
formatTable(
[
{ width: 30, align: "left" },
{ width: 5, align: "center" },
{ width: 13, align: "right" },
],
[
["Item", "Qty", "Price"],
["Hamburger", "2", "$25.98"],
],
48,
);
```
--------------------------------
### Create a Product Label with TSC/TSPL2
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Define a product label with text and lines using the Portakal core API. The `tsc` module is then used to compile the label into TSC/TSPL2 commands or generate an SVG preview.
```ts
import { label } from "portakal/core";
import { tsc } from "portakal/lang/tsc";
const myLabel = label({ width: 40, height: 30, unit: "mm" })
.text("ACME Corp", { x: 10, y: 10, size: 2 })
.text("SKU: PRD-00123", { x: 10, y: 35 })
.line({ x1: 5, y1: 55, x2: 310, y2: 55 })
.box({ x: 5, y: 5, width: 310, height: 230, thickness: 2 });
const code = tsc.compile(myLabel); // TSC/TSPL2 commands
const svg = tsc.preview(myLabel); // SVG preview with TSC font metrics
```
--------------------------------
### Available Language Modules
Source: https://github.com/productdevbook/portakal/blob/main/AGENTS.md
Lists the available language modules that can be imported and used for compiling, parsing, previewing, and validating labels for different printer languages.
```APIDOC
## Available Language Modules
### Description
Portakal provides tree-shakeable language modules for various printer languages. Each module exports `compile()`, `parse()`, `preview()`, and `validate()` functions.
### Imports
```ts
import { tsc } from "portakal/lang/tsc"; // TSC/TSPL2
import { zpl } from "portakal/lang/zpl"; // Zebra ZPL II
import { epl } from "portakal/lang/epl"; // Eltron EPL2
import { escpos } from "portakal/lang/escpos"; // ESC/POS
import { cpcl } from "portakal/lang/cpcl"; // Comtec CPCL
import { dpl } from "portakal/lang/dpl"; // Datamax DPL
import { ipl } from "portakal/lang/ipl"; // Intermec IPL
import { sbpl } from "portakal/lang/sbpl"; // SATO SBPL
import { starprnt } from "portakal/lang/starprnt"; // Star PRNT
```
```
--------------------------------
### Catching Portakal Errors
Source: https://context7.com/productdevbook/portakal/llms.txt
Demonstrates how to catch and differentiate between `InvalidConfigError`, `UnsupportedFeatureError`, and the base `PortakalError`.
```typescript
import { label, InvalidConfigError, UnsupportedFeatureError, PortakalError } from "portakal";
try {
label({ width: 0, height: 30 }); // invalid — width must be positive
} catch (err) {
if (err instanceof InvalidConfigError) {
console.error("Config error:", err.message);
// "Label width must be a positive number"
}
}
// UnsupportedFeatureError is thrown by compilers when a feature
// has no equivalent in the target language
try {
// ... some unsupported operation
} catch (err) {
if (err instanceof UnsupportedFeatureError) {
console.error(err.message); // "epl does not support: ellipse"
}
if (err instanceof PortakalError) {
// catches both InvalidConfigError and UnsupportedFeatureError
console.error("Portakal error:", err.name, err.message);
}
}
```
--------------------------------
### Apply Region Effects with Portakal
Source: https://context7.com/productdevbook/portakal/llms.txt
Utilize `.reverse()` to fill a region with black (white-on-black inversion) or `.erase()` to fill with white (clearing content). These methods are useful for creating contrast or removing specific areas of the label.
```typescript
import { label } from "portakal";
import { tsc } from "portakal/lang/tsc";
const lbl = label({ width: 40, height: 30, unit: "mm" })
.reverse({ x: 0, y: 0, width: 320, height: 40 })
.text("WHITE ON BLACK", { x: 10, y: 5, size: 2 }) // text appears white
.erase({ x: 50, y: 100, width: 100, height: 30 }); // clear a region
console.log(tsc.compile(lbl));
```
--------------------------------
### imageToMonochrome(rgba, width, height, options?)
Source: https://context7.com/productdevbook/portakal/llms.txt
Converts RGBA pixel data to a `MonochromeBitmap` (1-bit packed, row-major, MSB-first) ready for `.image()`. Supports four dithering algorithms.
```APIDOC
## `imageToMonochrome(rgba, width, height, options?)` — Convert Image to Bitmap
Converts RGBA pixel data to a `MonochromeBitmap` (1-bit packed, row-major, MSB-first) ready for `.image()`. Supports four dithering algorithms.
```ts
import { imageToMonochrome, rgbaToGrayscale, packBitmap, ditherFloydSteinberg } from "portakal";
// High-level: one call converts RGBA → MonochromeBitmap
const bitmap = imageToMonochrome(rgbaPixels, 200, 100, { dither: "floyd-steinberg" });
console.log(bitmap.width); // 200
console.log(bitmap.height); // 100
console.log(bitmap.bytesPerRow); // 25 (ceil(200/8))
console.log(bitmap.data.length); // 2500
// Low-level pipeline (custom control)
const gray = rgbaToGrayscale(rgbaPixels, 200, 100); // BT.601 luminance, alpha→white
const dithered = ditherFloydSteinberg(gray, 200, 100); // error-diffusion
const bmp = packBitmap(dithered, 200, 100); // pack to 1-bit
// All four dithering modes
imageToMonochrome(rgba, w, h, { dither: "threshold", threshold: 128 }); // fast, high-contrast
imageToMonochrome(rgba, w, h, { dither: "floyd-steinberg" }); // best quality, smooth gradients
imageToMonochrome(rgba, w, h, { dither: "atkinson" }); // high contrast, preserves whites
imageToMonochrome(rgba, w, h, { dither: "ordered" }); // Bayer matrix, patterned look
```
```
--------------------------------
### Transport Utilities: chunkedWrite and writeWithRetry
Source: https://context7.com/productdevbook/portakal/llms.txt
Provides transport-agnostic helpers for sending printer data. `chunkedWrite` splits large payloads into smaller pieces, essential for protocols like BLE with MTU limits. `writeWithRetry` adds automatic reconnection logic with exponential backoff for unreliable connections.
```APIDOC
## chunkedWrite(transport, data, options?)
### Description
Splits large data payloads into smaller chunks to respect transport limitations, such as BLE MTU.
### Parameters
#### transport
- **transport** (PrinterTransport) - Required - The transport interface to write data through.
#### data
- **data** (Uint8Array) - Required - The data to be written.
#### options
- **chunkSize** (number) - Optional - The maximum size of each chunk. Defaults to a sensible value based on the transport.
- **chunkDelay** (number) - Optional - The delay in milliseconds between sending chunks. Defaults to 0.
### Example
```ts
import { chunkedWrite } from "portakal";
// Assuming 'transport' is an instance of a PrinterTransport and 'data' is a Uint8Array
await chunkedWrite(transport, data, { chunkSize: 512, chunkDelay: 20 });
```
## writeWithRetry(transport, data, options?)
### Description
Writes data to the transport with automatic retry logic, including reconnection attempts with exponential backoff, to handle transient connection issues.
### Parameters
#### transport
- **transport** (PrinterTransport) - Required - The transport interface to write data through.
#### data
- **data** (Uint8Array) - Required - The data to be written.
#### options
- **maxRetries** (number) - Optional - The maximum number of retry attempts. Defaults to 3.
- **initialDelay** (number) - Optional - The initial delay in milliseconds before the first retry. Defaults to 1000.
- **maxDelay** (number) - Optional - The maximum delay in milliseconds between retries. Defaults to 10000.
### Example
```ts
import { writeWithRetry } from "portakal";
// Assuming 'transport' is an instance of a PrinterTransport and 'data' is a Uint8Array
await writeWithRetry(transport, data, { maxRetries: 3, initialDelay: 1000, maxDelay: 10000 });
```
```
--------------------------------
### Generate Barcode and QR Code Labels with Etiket
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Use the etiket library to generate barcode and QR code images and embed them into a label. This is suitable for creating product labels with dynamic information.
```typescript
import { label } from "portakal/core";
import { tsc } from "portakal/lang/tsc";
import { barcodePNG, qrcodePNG } from "etiket";
const myLabel = label({ width: 40, height: 30, unit: "mm" })
.text("Product Label", { x: 10, y: 5 })
.image(barcodePNG("123456789", { type: "code128" }), { x: 10, y: 40, width: 200 })
.image(qrcodePNG("https://example.com"), { x: 220, y: 40, width: 80 });
const code = tsc.compile(myLabel);
```
--------------------------------
### Send Raw Printer Commands
Source: https://github.com/productdevbook/portakal/blob/main/README.md
Utilize the `.raw()` method to send printer-specific commands directly. This provides an escape hatch for functionalities not covered by the SDK's abstraction layer.
```typescript
builder.raw("SET CUTTER ON"); // TSC
builder.raw("^FO10,10^FDCustom^FS"); // ZPL
builder.raw(new Uint8Array([0x1b, 0x70, 0x00, 0x32, 0x32])); // ESC/POS cash drawer
```
--------------------------------
### markup(source)
Source: https://context7.com/productdevbook/portakal/llms.txt
Parses an HTML-like `` markup string into a `LabelBuilder` object. This is useful for defining label layouts in a human-readable string format, which can then be compiled into printer-specific code.
```APIDOC
## markup(source)
### Description
Parses an HTML-like markup string representing a label definition into a structured `LabelBuilder` object.
### Parameters
#### source
- **source** (string) - Required - A string containing HTML-like markup for the label, including elements like ``, ``, ``, ``, etc.
### Returns
- **LabelBuilder** - An object representing the parsed label structure, ready to be compiled or previewed.
### Example
```ts
import { markup } from "portakal";
const lbl = markup(`
Hello World
`);
```
```
--------------------------------
### Receipt Layout Utilities
Source: https://context7.com/productdevbook/portakal/llms.txt
Helper functions for formatting ESC/POS receipt text, including same-line left+right pairs, multi-column tables, separator lines, and word-wrap.
```APIDOC
## Receipt Layout Utilities — `formatPair()`, `formatTable()`, `separator()`, `wordWrap()`
Helper functions for formatting ESC/POS receipt text — same-line left+right pairs, multi-column tables, separator lines, and word-wrap.
```ts
import { formatPair, formatTable, separator, wordWrap } from "portakal";
const WIDTH = 48; // chars per line for 80mm at Font A
// formatPair: item name left, price right
console.log(formatPair("Hamburger x2", "$25.98", WIDTH));
// "Hamburger x2 $25.98"
// separator: full-width divider
console.log(separator("=", WIDTH));
// "================================================="
// formatTable: multi-column aligned rows
const lines = formatTable(
[{ width: 28, align: "left" }, { width: 5, align: "center" }, { width: 13, align: "right" }],
[
["Item", "Qty", "Price"],
["Hamburger", "2", "$25.98"],
["Cola", "1", "$3.50"],
],
WIDTH,
);
// ["Item Qty Price", ...]
// wordWrap: break long text
const wrapped = wordWrap("This is a very long description that must wrap at word boundaries", 32);
// ["This is a very long description", "that must wrap at word", "boundaries"]
```
```