### 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 ``` -------------------------------- ### 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 `