ZPLr 0.3 is a deterministic ZPL and ZPL II parser and label renderer for ESM applications on Node.js 22/24 and evergreen browsers. It parses complete jobs, interprets virtual-printer state, renders a packed one-bit raster, and expands that raster to a required platform Canvas.
The renderer profile is pinned to Zebra's ZPL programming guide published October 10, 2025. Deterministic output does not claim proprietary Zebra font parity or pixel parity with a physical printer.
Node rendering uses the optional skia-canvas peer:
pnpm add zplr skia-canvasBrowser consumers install only ZPLr; the zplr/web entry neither resolves nor bundles skia-canvas.
zplr is the Node-default alias. zplr/node is equivalent and zplr/web supplies browser canvases.
import { renderZpl } from "zplr";
const job = await renderZpl(`
^XA
^CI28
^PW812
^LL1218
^FO40,40^A0N,42,24^FDDeterministic label^FS
^FO40,120^BQN,2,5,Q,7^FDQA,HELLO-ZPL^FS
^XZ
`);
const label = job.labels[0];
console.log(label.raster.bitOrder, label.diagnostics);
await label.canvas.toFile("label.png");import { renderZpl } from "zplr/web";
const job = await renderZpl(source, { printDensity: 8 });
document.body.append(job.labels[0].canvas);Every label contains resolved dimensions, print density, an MSB-first packed raster, diagnostics, source-linked highlight regions, and a required Canvas/HTMLCanvasElement. renderZplPNG() returns Buffer[] in Node and Blob[] in browsers.
The local /editor workbench keeps Monaco source and a selectable label canvas synchronized. It supports multi-layer layout, variable-data records, imported graphics and TrueType fonts, and portable workspace archives without hiding the generated ZPL. See the editor guide for workflows and shortcuts.
import {
findCommandAtOffset,
findHighlightRegionAtPoint,
parseDocument,
} from "zplr";
const document = parseDocument(source);
const command = findCommandAtOffset(document, cursorOffset);
const region = findHighlightRegionAtPoint(job.labels[0].highlightRegions, x, y);
console.log(command?.canonical, region?.sourceSpan);Command capability lookup requires the full identity: getCommandCapability("^FO") and getCommandCapability("~DG"). Prefixless lookups return undefined.
renderZpl() starts with fresh virtual-printer state. Use a session when syntax characters, settings, graphics, stored formats, encodings, or fonts must persist:
import { createRenderSession, parseDocument } from "zplr";
const printer = createRenderSession({ printDensity: 8 });
await printer.render("~DGR:MARK.GRF,1,1,80");
const parsed = parseDocument("^XA^PW400^LL240^FO20,20^XGR:MARK.GRF,4,4^FS^XZ");
const result = await printer.renderDocument(parsed);
await printer.reset();Session operations are FIFO-serialized and state is never global.
Syntax and semantic failures, unsupported behavior, missing resources, and safety-limit violations resolve through structured diagnostics. Parameters that Zebra defines as ignored or defaulted follow those rules without inventing an error. Operational failures from a host Canvas adapter or a user-supplied callback/provider reject the render promise. See the stable diagnostic-code catalog.
Defaults limit each dimension to 32,768 dots, each label or temporary field raster and the cumulative output of one render call to 40 million pixels, each decompressed graphic to 16 MiB, session resources to 32 MiB, stored-format depth to 16, expanded commands to 100,000, and output labels to 10,000. All limits are configurable downward or upward through RenderJobOptions.limits.
The pinned profile currently contains 94 supported, 11 partially supported, and 2 unsupported rendering/job command identities. The remaining 116 device, network, printer, and RFID commands are recognized and raster-neutral. Exact limitations are listed in the generated command table and conformance map.
Representative raster hashes, independent barcode decoding, source spans, session state, malformed input, resource limits, and Node/browser parity are tested. ZPLr does not perform printing, networking, RFID operations, or filesystem resource lookup.
0.3.0 removes the 0.2 compatibility layer and freezes the API described in api/0.3.0.json. A 0.3.x release may add compatible functionality but cannot remove or reinterpret that surface. Read the 0.2 → 0.3 migration guide before upgrading.
If stabilization reveals another necessary break, it will ship as 0.4.0 and restart the candidate cycle. 1.0.0 will promote the validated 0.3 API without a feature or API redesign. The complete process is in the release policy.
pnpm install
pnpm exec playwright install chromium firefox webkit
pnpm run verify
pnpm run test:e2e
pnpm run auditSee CONTRIBUTING.md, SECURITY.md, and SUPPORT.md. Bundled-font terms are in THIRD_PARTY_NOTICES.md.
MIT. ZPL, ZPL II, Zebra, and related marks belong to Zebra Technologies Corp. ZPLr is an independent open-source project and is not affiliated with, endorsed by, or certified by Zebra Technologies. See TRADEMARKS.md.