{"id":44062463,"url":"https://github.com/trevordcampbell/zpl-toolchain","last_synced_at":"2026-02-14T06:03:44.549Z","repository":{"id":337143118,"uuid":"1152469791","full_name":"trevordcampbell/zpl-toolchain","owner":"trevordcampbell","description":"Spec-first, offline, deterministic ZPL II toolchain — parser, validator, formatter, and CLI with language bindings for TypeScript, Python, Go, and .NET","archived":false,"fork":false,"pushed_at":"2026-02-08T06:19:20.000Z","size":390,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-08T08:58:41.240Z","etag":null,"topics":["dotnet","go","golang","label-printer","label-printers","labeling","labeling-tool","labels","rust","typescript","zebra-label-printers","zebra-printer","zebra-printers","zebra-programming-language","zpl","zpl-commands","zpl-language","zpl-programming-language","zpl2"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trevordcampbell.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"MIT-LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-07T23:15:25.000Z","updated_at":"2026-02-08T06:19:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/trevordcampbell/zpl-toolchain","commit_stats":null,"previous_names":["trevordcampbell/zpl-toolchain"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/trevordcampbell/zpl-toolchain","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trevordcampbell%2Fzpl-toolchain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trevordcampbell%2Fzpl-toolchain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trevordcampbell%2Fzpl-toolchain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trevordcampbell%2Fzpl-toolchain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trevordcampbell","download_url":"https://codeload.github.com/trevordcampbell/zpl-toolchain/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trevordcampbell%2Fzpl-toolchain/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29435917,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T03:34:37.767Z","status":"ssl_error","status_checked_at":"2026-02-14T03:34:09.092Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dotnet","go","golang","label-printer","label-printers","labeling","labeling-tool","labels","rust","typescript","zebra-label-printers","zebra-printer","zebra-printers","zebra-programming-language","zpl","zpl-commands","zpl-language","zpl-programming-language","zpl2"],"created_at":"2026-02-08T02:14:05.017Z","updated_at":"2026-02-14T06:03:44.544Z","avatar_url":"https://github.com/trevordcampbell.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zpl-toolchain\n\n[![CI](https://github.com/trevordcampbell/zpl-toolchain/actions/workflows/ci.yml/badge.svg)](https://github.com/trevordcampbell/zpl-toolchain/actions/workflows/ci.yml)\n[![crates.io](https://img.shields.io/crates/v/zpl_toolchain_cli.svg)](https://crates.io/crates/zpl_toolchain_cli)\n[![npm](https://img.shields.io/npm/v/@zpl-toolchain/core.svg)](https://www.npmjs.com/package/@zpl-toolchain/core)\n[![PyPI](https://img.shields.io/pypi/v/zpl-toolchain.svg)](https://pypi.org/project/zpl-toolchain/)\n[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](#license)\n\nA spec-first ZPL II toolchain for parsing, validating, formatting, and printing Zebra label files. Built in Rust with a CLI and bindings for TypeScript, Python, Go, and .NET.\n\n---\n\n## Why zpl-toolchain?\n\nZPL II is the standard language for Zebra thermal label printers, used across logistics, healthcare, retail, and manufacturing. Despite its ubiquity, there are no comprehensive open-source tools for working with it programmatically.\n\n**zpl-toolchain** fills that gap: a complete, spec-driven toolkit that understands every ZPL II command, catches errors before they waste labels, auto-formats messy code, and sends labels directly to printers — all from one unified toolchain.\n\n---\n\n## Features\n\n### Parsing \u0026 Analysis\n\n- **Full ZPL II command coverage** — 223/223 commands (100%) across 216 per-command spec files, each audited against the official Zebra Programming Guide\n- **Hand-written parser** — opcode trie for longest-match, signature-driven argument parsing, prefix/delimiter state tracking, UTF-8 safe, lossless round-trip capable\n- **46 diagnostic codes** — structured errors and warnings with byte-offset spans, coloured source annotations via `ariadne`, and `explain` for every code\n- **Printer profiles** — 11 shipped profiles covering desktop, industrial, and mobile Zebra printers with DPI, page bounds, speed/darkness ranges, and hardware feature gates\n\n### Validation\n\n- **Table-driven validator** — arity, types, ranges, enums, typed cross-command state defaults (`defaultFrom` + `defaultFromStateKey`), constraint DSL (`requires`, `incompatible`, `order`, `emptyData`), profile-aware bounds checking\n- **Preflight diagnostics** — graphics bounds checking (`^GF` exceeds printable area), memory estimation (`^GF` total exceeds printer RAM), and missing explicit label dimension warnings — catch layout issues before printing\n- **Barcode data validation** — field data checked against barcode symbology rules (Code 128, QR, EAN/UPC, etc.)\n\n### Formatting\n\n- **Auto-formatter** — spec-driven, configurable indentation (none / label / field), trailing-arg trimming, idempotent output\n\n### Printing\n\n- **Three transports** — TCP (port 9100), USB (`nusb`), and serial/Bluetooth SPP (`serialport`)\n- **Status querying** — parse `~HS` (24-field host status) and `~HI` (printer info: model, firmware, DPI, memory)\n- **Batch printing** — send multiple labels with progress tracking, status polling, and abort support\n- **Retry with backoff** — exponential backoff with jitter; optional automatic reconnection between attempts\n- **Lint-then-print** — the CLI validates ZPL before sending, catching errors before they waste labels\n- **TypeScript print client** — pure Node.js TCP client with persistent connections, write queue serialization, and one-shot convenience functions\n- **Browser printing** — HTTP/WebSocket proxy bridges browser apps to TCP printers with SSRF protection, port restriction, connection limits, and CORS; Zebra Browser Print SDK wrapper for direct local printing\n- **Wait for completion** — poll the printer until all queued labels finish printing, with configurable timeout\n\n### Developer Experience\n\n- **CLI** — `parse`, `syntax-check` (`check` alias), `lint` (`validate` alias), `format`, `print`, `explain`, `doctor` with `--output pretty|json` auto-detection\n- **Language bindings** — unified API across WASM, Python, C FFI, Go, and .NET\n- **Zero clippy warnings, 465+ passing tests** — parser, validator, emitter, print client, preflight, batch API, browser SDK, and more\n\n---\n\n## Quick Start\n\n### Install\n\n```bash\n# CLI (Rust) — all transports included (TCP, USB, serial/Bluetooth)\ncargo install zpl_toolchain_cli\n# Or use cargo-binstall for a pre-built binary (no compile wait):\ncargo binstall zpl_toolchain_cli\n# Or use the npm wrapper (downloads a pre-built binary on first run):\nnpx @zpl-toolchain/cli --help\n\n# TypeScript\nnpm install @zpl-toolchain/core     # parsing, validation, formatting (WASM)\nnpm install @zpl-toolchain/print    # printing (Node.js TCP, browser proxy)\n\n# Python\npip install zpl-toolchain\n\n# Go\ngo get github.com/trevordcampbell/zpl-toolchain/packages/go/zpltoolchain\n```\n\n\u003e Pre-built binaries are also available from [GitHub Releases](https://github.com/trevordcampbell/zpl-toolchain/releases).\n\u003e The npm wrapper currently supports `linux/x64`, `darwin/arm64`, and `win32/x64`. For unsupported platforms (for example Intel Mac or Linux ARM64), use `cargo install zpl_toolchain_cli`.\n\n### Lint a label\n\n```bash\nzpl lint label.zpl --profile profiles/ZD421-300dpi.json\n```\n\n```\n  warning[ZPL2302]: Field position exceeds label dimensions\n    ┌─ label.zpl:3:1\n    │\n  3 │ ^FO900,50^FDOverflow^FS\n    │ ^^^^^^^^ x=900 exceeds width=832\n    │\n  1 warning emitted\n```\n\n### Print a label\n\n```bash\nzpl print label.zpl -p 192.168.1.55\n```\n\n```\nconnected to 192.168.1.55:9100\nsent: label.zpl\nprint complete: 1 file(s) sent to 192.168.1.55:9100\n```\n\n### Validate then print (strict mode)\n\n```bash\nzpl print label.zpl -p 192.168.1.55 --strict --profile profiles/ZT411-203dpi.json\n```\n\nAborts with a non-zero exit code if the validator finds any errors — no wasted labels.\n\n---\n\n## CLI Reference\n\n```\nUSAGE: zpl \u003cCOMMAND\u003e [OPTIONS]\n\nCOMMANDS:\n  parse          Parse a ZPL file and output the AST as JSON\n  syntax-check   Quick syntax check (exit 0 = ok, exit 1 = errors)\n  lint           Parse + validate with optional printer profile\n  format         Auto-format ZPL files\n  print          Send ZPL to a printer (TCP, USB, or serial)\n  serial-probe   Probe serial/Bluetooth endpoint health\n  explain        Explain a diagnostic code (e.g., ZPL1401)\n  doctor         Run environment/configuration diagnostics\n\nGLOBAL OPTIONS:\n  --output \u003cpretty|json\u003e   Output format (default: auto-detect TTY)\n```\n\n`parse`, `syntax-check`, `lint`, and `format` accept `-` as the file path to read ZPL from stdin.\n\n### Print command\n\n```\nUSAGE: zpl print \u003cFILES...\u003e --printer \u003cADDR\u003e [OPTIONS]\n\nARGUMENTS:\n  \u003cFILES...\u003e               One or more ZPL files to send\n\nREQUIRED:\n  -p, --printer \u003cADDR\u003e     Printer address (see formats below)\n\nOPTIONS:\n  --profile \u003cPATH\u003e         Printer profile JSON for pre-print validation\n  --strict                 Abort on any validation warning (not just errors)\n  --no-lint                Skip validation entirely\n  --dry-run                Validate without connecting to the printer\n  --status                 Query ~HS printer status after sending\n  --verify                 Require post-send status verification and fail on fault flags\n  --info                   Query ~HI printer info (model, firmware, DPI) before sending\n  --wait                   Poll until the printer finishes all labels\n  --wait-timeout \u003cSECS\u003e    Timeout for --wait polling (default: 120)\n  --timeout \u003cSECS\u003e         Connection timeout in seconds (default: 5; write=6x, read=2x)\n  --serial                 Use serial/Bluetooth SPP transport\n  --baud \u003cRATE\u003e            Serial baud rate (default: 9600, requires --serial)\n```\n\n**Printer address formats:**\n\n| Format | Transport | Example |\n|--------|-----------|---------|\n| IP or hostname | TCP (port 9100) | `192.168.1.55`, `printer.local` |\n| IP:port | TCP (custom port) | `192.168.1.55:6101` |\n| `usb` | USB (auto-discover) | `usb` |\n| `usb:VID:PID` | USB (specific device, hex) | `usb:0A5F:0100` |\n| Serial port path | Serial/BT SPP (with `--serial`) | `/dev/ttyUSB0`, `COM3` |\n\n\u003e All transports (TCP, USB, serial/Bluetooth) are included by default in every install method.\n\u003e For a minimal TCP-only build: `cargo install zpl_toolchain_cli --no-default-features --features tcp`.\n\u003e There is no separate `--usb` flag: USB is selected with `--printer usb` or `--printer usb:VID:PID`.\n\n**Optional minimal CLI builds (feature-selective):**\n\n```bash\n# TCP only\ncargo install zpl_toolchain_cli --no-default-features --features tcp\n\n# USB only\ncargo install zpl_toolchain_cli --no-default-features --features usb\n\n# Serial/Bluetooth only\ncargo install zpl_toolchain_cli --no-default-features --features serial\n\n# TCP + Serial (no USB)\ncargo install zpl_toolchain_cli --no-default-features --features \"tcp serial\"\n\n# TCP + USB (no serial/Bluetooth)\ncargo install zpl_toolchain_cli --no-default-features --features \"tcp usb\"\n```\n\n\u003e **Note:** Serial/Bluetooth addresses require the `--serial` flag and an OS serial port path (for example `/dev/cu.*`, `/dev/tty*`, `COM*`, `/dev/rfcomm*`), not a Bluetooth MAC address. USB printing on Linux may require [udev rules](docs/PRINT_CLIENT.md#linux-udev-rules). See the [Print Client Guide](docs/PRINT_CLIENT.md) for transport setup details.\n\u003e For stronger delivery checks, use `--verify` (or `--status` / `--wait`). With `--wait`, verification re-queries status after completion. Write success alone does not guarantee physical print completion.\n\n### Examples\n\n```bash\n# Parse → AST JSON\nzpl parse label.zpl\n\n# Lint with printer profile\nzpl lint label.zpl --profile profiles/zebra-generic-203.json\n\n# Auto-format in place\nzpl format label.zpl --write\n\n# Explain a diagnostic\nzpl explain ZPL1401\n\n# Print via TCP\nzpl print label.zpl -p 192.168.1.55\n\n# Print via USB with status query\nzpl print label.zpl -p usb --status --info\n\n# Print via serial/Bluetooth\nzpl print label.zpl -p /dev/ttyUSB0 --serial --baud 115200\n\n# Dry-run: validate without sending\nzpl print label.zpl -p 192.168.1.55 --dry-run --profile profiles/ZD421-300dpi.json\n\n# JSON output for scripting\nzpl print label.zpl -p 192.168.1.55 --status --output json | jq .\n```\n\n---\n\n## Language Bindings\n\nAll bindings expose the same core API: **parse**, **validate**, **format**, **explain**.\nTransport scope for printing is runtime-specific:\n- CLI + Rust print-client API: TCP + USB + serial/Bluetooth\n- TypeScript `@zpl-toolchain/print`: TCP (plus browser proxy/Browser Print integrations)\n- Python / Go / .NET / C FFI wrappers: TCP print + `~HS` status + `~HI` info\n\n| Language | Package | Mechanism | Print Support |\n|----------|---------|-----------|---------------|\n| TypeScript | [`@zpl-toolchain/core`](packages/ts/core/) | WASM | [`@zpl-toolchain/print`](packages/ts/print/) — TCP, batch, proxy, browser |\n| Python | [`zpl_toolchain`](crates/python/) | PyO3 / maturin | `print_zpl[_with_options]()`, `query_printer_status[_with_options]()`, `query_printer_info[_with_options]()` |\n| Go | [`zpltoolchain`](packages/go/zpltoolchain/) | cgo over C FFI | `ValidateWithTables()`, `Print[WithOptions]()`, `QueryStatus[Typed|WithOptions]()`, `QueryInfo[Typed|WithOptions]()` |\n| .NET (C#) | [`ZplToolchain`](packages/dotnet/ZplToolchain/) | P/Invoke over C FFI | `Zpl.ValidateWithTables()`, `Zpl.Print[WithOptions]()`, `Zpl.QueryStatus[Typed|WithOptions]()`, `Zpl.QueryInfo[Typed|WithOptions]()` |\n| C | [`zpl_toolchain_ffi`](crates/ffi/) | cdylib + staticlib | `zpl_validate_with_tables()`, `zpl_print[_with_options]()`, `zpl_query_status[_with_options]()`, `zpl_query_info[_with_options]()` |\n\n### TypeScript\n\n```typescript\nimport { validate } from '@zpl-toolchain/core';\nimport { print, TcpPrinter } from '@zpl-toolchain/print';\n\n// One-shot: validate and print\nconst validation = validate('^XA^FO50,50^FDHello^FS^XZ');\nif (validation.ok) {\n  await print('^XA^FO50,50^FDHello^FS^XZ', { host: '192.168.1.55' });\n}\n\n// Persistent connection for batch printing\nconst printer = new TcpPrinter({ host: '192.168.1.55' });\nawait printer.printBatch(labels, {}, (p) =\u003e {\n  console.log(`${p.sent}/${p.total}`);\n});\nawait printer.close();\n```\n\n### Python\n\n```python\nfrom zpl_toolchain import validate, print_zpl\n\nvalidation = validate(\"^XA^FO50,50^FDHello^FS^XZ\")\nresult = print_zpl(\"^XA^FO50,50^FDHello^FS^XZ\", \"192.168.1.55\")\n```\n\n### Go\n\n```go\nresult, _ := zpltoolchain.Validate(\"^XA^FO50,50^FDHello^FS^XZ\", \"\")\nprintResult, _ := zpltoolchain.Print(\"^XA^FDHello^FS^XZ\", \"192.168.1.55\", \"\", true)\n```\n\n### .NET (C#)\n\n```csharp\nvar result = Zpl.Validate(\"^XA^FO50,50^FDHello^FS^XZ\");\nvar printResult = Zpl.Print(\"^XA^FDHello^FS^XZ\", \"192.168.1.55\");\n```\n\n---\n\n## Architecture\n\n```mermaid\ngraph TD\n    SPEC[\"spec/commands/*.jsonc\u003cbr/\u003e\u003ci\u003e216 files — single source of truth\u003c/i\u003e\"]\n    SPEC --\u003e COMPILER[\"spec-compiler\u003cbr/\u003e\u003ci\u003eload → validate → generate\u003c/i\u003e\"]\n    COMPILER --\u003e TABLES[\"parser_tables.json\u003cbr/\u003e\u003ci\u003eopcode trie + args + constraints\u003c/i\u003e\"]\n    TABLES --\u003e|\"embedded at\u003cbr/\u003ebuild time\"| CORE[\"Core\u003cbr/\u003e\u003ci\u003eparser + validator + emitter\u003c/i\u003e\"]\n    CORE --\u003e COMMON[\"bindings-common\u003cbr/\u003e\u003ci\u003eshared parse / validate / format / explain\u003c/i\u003e\"]\n    COMMON --\u003e CLI[\"CLI\u003cbr/\u003e\u003ci\u003eparse, lint, format, print\u003c/i\u003e\"]\n    COMMON --\u003e WASM[\"WASM\u003cbr/\u003e\u003ci\u003eTypeScript / browser\u003c/i\u003e\"]\n    COMMON --\u003e PYTHON[\"Python\u003cbr/\u003e\u003ci\u003ePyO3\u003c/i\u003e\"]\n    COMMON --\u003e FFI[\"C FFI\u003cbr/\u003e\u003ci\u003ecdylib\u003c/i\u003e\"]\n    FFI --\u003e GO[\"Go\u003cbr/\u003e\u003ci\u003ecgo\u003c/i\u003e\"]\n    FFI --\u003e DOTNET[\".NET\u003cbr/\u003e\u003ci\u003eP/Invoke\u003c/i\u003e\"]\n    PRINT[\"print-client\u003cbr/\u003e\u003ci\u003eTCP / USB / serial\u003c/i\u003e\"]\n    PRINT --\u003e CLI\n    COMMON -.-\u003e|\"validate before print\"| PRINT\n```\n\n## Printer Profiles\n\nProfiles are JSON files describing a Zebra printer's capabilities — DPI, page size, speed/darkness ranges, hardware features, and media support. The validator enforces printer-specific bounds and feature gates, all data-driven from the spec files.\n\n11 shipped profiles cover popular Zebra printers plus two generic baselines:\n\n| Profile | Type | DPI | Page (dots) |\n|---------|------|-----|-------------|\n| GK420t | Desktop | 203 | 832 x 1218 |\n| ZD420 | Desktop | 203 | 832 x 1218 |\n| ZD620 | Desktop | 203/300 | 832/1248 x 1218 |\n| ZD621 | Desktop | 203/300 | 832/1248 x 1218 |\n| ZT231 | Industrial | 203/300 | 832/1248 x 1218 |\n| ZT410/ZT411 | Industrial | 203/300/600 | varies |\n| ZT610 | Industrial | 203/300 | 832/1248 x 1218 |\n| ZQ520 | Mobile | 203 | 576 x 1218 |\n\nSee the [Profile Guide](docs/PROFILE_GUIDE.md) for details on creating custom profiles.\n\n## Repo Layout\n\n```\nzpl-toolchain/\n  crates/\n    core/              Parser, validator, emitter, AST\n    cli/               CLI (parse, syntax-check, lint, format, print, explain)\n    print-client/      TCP, USB, serial print client with retry and batch\n    diagnostics/       46 diagnostic codes (auto-generated from spec)\n    spec-tables/       Shared types (CommandEntry, Arg, Constraint, etc.)\n    spec-compiler/     Spec compiler (validate specs → generate tables)\n    profile/           Printer profile loading and validation\n    bindings-common/   Shared logic for all language bindings\n    wasm/              WASM bindings (wasm-bindgen)\n    python/            Python bindings (PyO3)\n    ffi/               C FFI (cdylib + staticlib)\n  packages/\n    ts/core/           @zpl-toolchain/core (TypeScript, WASM-based)\n    ts/print/          @zpl-toolchain/print (TypeScript, Node.js TCP)\n    ts/cli/            @zpl-toolchain/cli (npx wrapper for pre-built CLI binary)\n    go/zpltoolchain/   Go wrapper (cgo)\n    dotnet/ZplToolchain/  .NET wrapper (P/Invoke)\n  spec/\n    commands/          216 per-command JSONC spec files\n    schema/            JSONC schema + profile schema\n  profiles/            11 shipped printer profiles\n  samples/             Sample ZPL label files\n  docs/                Guides, references, ADRs\n```\n\n## Building from Source\n\n```bash\n# Build and test (parser tables are committed at crates/cli/data/ — no generation needed)\ncargo build --workspace\ncargo test --workspace\n\n# Run the CLI\ncargo run -p zpl_toolchain_cli -- lint samples/usps_surepost_sample.zpl\n\n# If you modify spec files, regenerate tables (pre-commit hook syncs the CLI copy automatically):\ncargo run -p zpl_toolchain_spec_compiler -- build --spec-dir spec --out-dir generated\n```\n\n## Documentation\n\n| Document | Description |\n|----------|-------------|\n| [Print Client Guide](docs/PRINT_CLIENT.md) | Printing: transports, CLI, TypeScript, proxy, troubleshooting |\n| [Diagnostic Codes](docs/DIAGNOSTIC_CODES.md) | All 46 diagnostic codes explained |\n| [Profile Guide](docs/PROFILE_GUIDE.md) | Printer profile system reference |\n| [Spec Authoring Guide](docs/public/schema/SPEC_AUTHORING.md) | How to write command specs |\n| [Barcode Data Rules](docs/BARCODE_DATA_RULES.md) | Barcode field data validation |\n| [State Map](docs/STATE_MAP.md) | Cross-command state tracking |\n| [Roadmap](docs/ROADMAP.md) | Long-term vision, phases, and priorities |\n| [Release Process](docs/RELEASE.md) | Automated release workflow and publishing |\n| [Changelog](CHANGELOG.md) | Release history |\n| [Contributing](CONTRIBUTING.md) | Development workflow and guidelines |\n\n## What's Next\n\n- **Web playground** — browser-based editor with live diagnostics and preview (WASM-powered)\n- **VS Code extension** — diagnostics, format-on-save, hover docs, and command completions\n- **ZPL renderer** — native SVG/PNG rendering with incremental command support\n- **Label builder API** — programmatic label construction across all bindings\n- **mDNS printer discovery** — zero-configuration printer finding on local networks\n\nSee [docs/ROADMAP.md](docs/ROADMAP.md) for the full phased roadmap.\n\n## License\n\nDual-licensed under MIT or Apache-2.0. See [MIT-LICENSE.txt](MIT-LICENSE.txt) and [APACHE-2.0-LICENSE.txt](APACHE-2.0-LICENSE.txt).\n\n## Trademarks\n\nThis project is not affiliated with, endorsed by, or sponsored by Zebra Technologies Corporation. \"Zebra\" and the stylized Zebra head are trademarks of Zebra Technologies Corp. \"ZPL\" and \"ZPL II\" refer to the Zebra Programming Language. All other trademarks are the property of their respective owners.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrevordcampbell%2Fzpl-toolchain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrevordcampbell%2Fzpl-toolchain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrevordcampbell%2Fzpl-toolchain/lists"}