@connectedxm/zpl-generator
v0.0.24
Published
A TypeScript library for generating ZPL (Zebra Programming Language) code from structured badge configurations. This library provides type-safe APIs for creating thermal printer labels with text fields, barcodes, and QR codes.
Readme
ZPL Generator
A TypeScript library for generating ZPL (Zebra Programming Language) code from structured badge configurations. This library provides type-safe APIs for creating thermal printer labels with text fields, barcodes, and QR codes.
Features
- Type-Safe Configuration: Full TypeScript support with Zod validation schemas
- Thermal Badge Support: Generate ZPL for thermal transfer and direct thermal printers
- Multiple Block Types:
- Text fields with advanced formatting (word wrapping, alignment, vertical positioning)
- Barcodes (Code 128)
- QR codes with configurable error correction
- Comprehensive Printer Settings: Control print speed, darkness, orientation, media type, and more
- Validation: Built-in validation with detailed error messages
- Word Wrapping: Accurate line counting with optional word-width measurements for precise text layout
Installation
npm install cxm-zpl-generatorQuick Start
import { generate } from 'cxm-zpl-generator';
import {
ThermalBadge,
MediaType,
ThermalMediaType,
PrintOrientation,
FontOrientation,
TextAlignment,
VerticalAlignment,
PostPrintMode,
PrepeelMode,
AllMediaMode,
BackfeedAction,
ReverseMode,
PrintDensityAdjustment,
} from 'cxm-zpl-generator';
const badge: ThermalBadge = {
type: 'thermal',
tearOffAdjustment: 0,
backfeedActions: BackfeedAction.Normal,
media: MediaType.NonContinuousMarkSensing,
mediaOffset: 0,
thermalMediaType: ThermalMediaType.ThermalTransfer,
printOrientation: PrintOrientation.Normal,
mirror: MirrorMode.Normal,
labelHomeX: 20,
labelHomeY: 0,
printDensityAdjustment: PrintDensityAdjustment.Normal,
printSpeed: 1,
slewSpeed: 1,
backfeedSpeed: 1,
darkness: 30,
reverse: ReverseMode.Disable,
postPrintMode: PostPrintMode.TearOff,
prepeel: PrepeelMode.NoPrepeel,
printWidth: 900,
labelLength: 600,
allMedia: AllMediaMode.ContinuousOnly,
blocks: [
{
type: 'field',
name: 'title',
x: 0,
y: 100,
data: 'Hello World',
font: 'A',
fontHeight: 100,
maxWidth: 900,
maxLines: 1,
lineSpacing: 100,
alignment: TextAlignment.Center,
fontOrientation: FontOrientation.NoRotation,
hangingIndent: 0,
verticalAlignment: VerticalAlignment.Start,
},
],
};
const zpl = generate(badge);
console.log(zpl);
// Output: ^XA
// ~TA000
// ~JSN
// ...API Reference
generate(badge: Badge): string
Generates ZPL code from a badge configuration.
Parameters:
badge: A validatedBadgeobject (must be of type'thermal')
Returns: A string containing valid ZPL code
Example:
const zpl = generate(badge);
// Send zpl to your Zebra printervalidateBadge(data: unknown)
Validates a badge configuration object. Returns a Zod SafeParseReturnType with success/error information.
Example:
import { validateBadge } from 'cxm-zpl-generator';
const result = validateBadge(jsonData);
if (result.success) {
const badge = result.data; // Type-safe Badge object
const zpl = generate(badge);
} else {
console.error(result.error.errors);
}validateBadgeOrThrow(data: unknown)
Validates a badge configuration and throws a ZodError if validation fails.
Example:
import { validateBadgeOrThrow } from 'cxm-zpl-generator';
try {
const badge = validateBadgeOrThrow(jsonData);
const zpl = generate(badge);
} catch (error) {
// Handle validation error
}Badge Configuration
Base Badge Properties
All thermal badges require the following configuration:
| Property | Type | Description |
|----------|------|-------------|
| type | 'thermal' | Badge type (currently only thermal is supported) |
| tearOffAdjustment | number | Tear-off adjustment (0-120) |
| backfeedActions | BackfeedAction | Backfeed sequence configuration |
| media | MediaType | Media type (continuous, variable length, etc.) |
| mediaOffset | number | Media offset (-75 to 283) |
| thermalMediaType | ThermalMediaType | Direct thermal or thermal transfer |
| printOrientation | PrintOrientation | Normal or inverted |
| mirror | MirrorMode | Mirror mode setting |
| labelHomeX | number | Label home X coordinate (0-32000) |
| labelHomeY | number | Label home Y coordinate (0-32000) |
| printDensityAdjustment | PrintDensityAdjustment? | Optional print density adjustment |
| printSpeed | number | Print speed (1-14) |
| slewSpeed | number | Slew speed (1-14) |
| backfeedSpeed | number | Backfeed speed (1-14) |
| darkness | number | Print darkness (0-30) |
| reverse | ReverseMode | Reverse mode setting |
| postPrintMode | PostPrintMode | Post-print action (tear off, peel off, etc.) |
| prepeel | PrepeelMode | Prepeel mode setting |
| printWidth | number | Print width in dots (minimum 2) |
| labelLength | number | Label length in dots (1-32000) |
| allMedia | AllMediaMode | All media mode setting |
| blocks | Block[] | Array of content blocks |
Block Types
Field Block (Text)
Displays text with configurable font, size, alignment, and wrapping.
{
type: 'field',
name: 'field_name', // Identifier for the block
x: 0, // X position in dots
y: 100, // Y position in dots
data: 'Text content', // Text to display
font: 'A', // Font identifier (A-Z, 0-9)
fontHeight: 100, // Font height in dots (1-32000)
fontOrientation: FontOrientation, // Text rotation
maxWidth: 900, // Maximum width for wrapping (0-9999)
maxLines: 3, // Maximum number of lines (1-9999)
lineSpacing: 0, // Line spacing (-9999 to 9999)
alignment: TextAlignment, // Text alignment (Left, Right, Center, Justified)
hangingIndent: 0, // Hanging indent (0-9999)
verticalAlignment: VerticalAlignment, // Vertical alignment (Start, End)
wordWidths?: WordWidth[], // Optional word width measurements for accurate wrapping
}Vertical Alignment:
VerticalAlignment.Start: Text starts at the top of the fieldVerticalAlignment.End: Text is aligned to the bottom (uses only the lines needed, no line-break padding)
Word Widths:
For accurate text wrapping with proportional fonts, provide wordWidths:
wordWidths: [
{ word: 'Hello', width: 50, spaceWidth: 10 },
{ word: 'World', width: 60, spaceWidth: 10 },
]Barcode Block
Generates a Code 128 barcode.
{
type: 'barcode',
name: 'barcode_name',
x: 0,
y: 200,
data: '1234567890', // Barcode data
barWidth: 5, // Bar width multiplier (4-9999)
orientation: FontOrientation, // Barcode orientation
height: 60, // Barcode height in dots (1-32000)
line: YesNo, // Show human-readable line below
lineAbove: YesNo, // Show human-readable line above
checkDigit: YesNo, // Include check digit
}QR Code Block
Generates a QR code.
{
type: 'qrcode',
name: 'qrcode_name',
x: 0,
y: 300,
data: 'https://example.com', // QR code data
orientation: 'N', // Must be 'N' (no rotation)
model: '2', // Must be '2' (Model 2)
magnification: 5, // Magnification factor (1-100)
errorCorrection: QRCodeErrorCorrection, // Error correction level
mask: 0, // Mask pattern (0-7)
}Enums and Constants
Media Types
MediaType.Continuous- Continuous mediaMediaType.VariableLengthContinuous- Variable length continuousMediaType.NonContinuousWebSensing- Non-continuous web sensingMediaType.NonContinuousWebSensingAlt- Non-continuous web sensing (alternate)MediaType.NonContinuousMarkSensing- Non-continuous mark sensingMediaType.AutoDetect- Auto-detect media type
Thermal Media Types
ThermalMediaType.DirectThermal- Direct thermal printingThermalMediaType.ThermalTransfer- Thermal transfer printing
Text Alignment
TextAlignment.Left- Left-aligned textTextAlignment.Right- Right-aligned textTextAlignment.Center- Center-aligned textTextAlignment.Justified- Justified text
Font Orientation
FontOrientation.NoRotation- No rotation (0°)FontOrientation.Rotate90- Rotate 90° clockwiseFontOrientation.Rotate180- Rotate 180°FontOrientation.Rotate270- Rotate 270° clockwise
Post Print Modes
PostPrintMode.TearOff- Tear off after printingPostPrintMode.PeelOff- Peel off after printingPostPrintMode.Rewind- Rewind after printingPostPrintMode.Applicator- Applicator modePostPrintMode.Cut- Cut after printingPostPrintMode.DelayedCut- Delayed cutPostPrintMode.EncodeRFID- Encode RFIDPostPrintMode.Kiosk- Kiosk mode
QR Code Error Correction
QRCodeErrorCorrection.Highest- Highest error correction (~30%)QRCodeErrorCorrection.High- High error correction (~25%)QRCodeErrorCorrection.Medium- Medium error correction (~15%)QRCodeErrorCorrection.Lower- Lower error correction (~7%)
Advanced Usage
Dynamic Content with Templates
You can use template strings in your badge data and replace them before generating ZPL:
const badge: ThermalBadge = {
// ... configuration
blocks: [
{
type: 'field',
name: 'name',
x: 0,
y: 100,
data: '{{firstName}} {{lastName}}', // Template string
// ... other properties
},
],
};
// Replace template variables
const badgeWithData = {
...badge,
blocks: badge.blocks.map(block => ({
...block,
data: block.data
.replace('{{firstName}}', 'John')
.replace('{{lastName}}', 'Doe'),
})),
};
const zpl = generate(badgeWithData);Accurate Text Wrapping
For precise auto-shrink sizing with proportional fonts, measure each word of
the rendered value (after transformation/maxCharacters — use the
exported applyTextTransformation) and provide wordWidths on the text
field. Tokenize with the exported tokenizeWords so words line up with the
generator's wrap simulation. Widths are measured at the field's fontHeight;
the generator scales them when searching for a fitting height.
Line counting priority: wordWidths (exact ^FB word-wrap simulation, used
only when the measured words match the rendered value) → measuredWidth
(continuous-stream estimate) → charsPerLine heuristic.
import {
applyTextTransformation,
tokenizeWords,
generate,
WordWidth,
} from "@connectedxm/zpl-generator";
// In the consumer, after resolving the field's value:
const printed = applyTextTransformation(field, rawValue);
const spaceWidth = measure(" "); // e.g. canvas measureText at field.fontHeight
const wordWidths: WordWidth[] = tokenizeWords(printed)
.flat()
.map((word) => ({ word, width: measure(word), spaceWidth }));
const sizedField = { ...field, wordWidths };Validating JSON Configuration
When loading badge configurations from JSON files or APIs:
import { validateBadgeOrThrow, generate } from 'cxm-zpl-generator';
// Load from JSON file or API
const jsonData = await fetch('/api/badge-config').then(r => r.json());
try {
const badge = validateBadgeOrThrow(jsonData);
const zpl = generate(badge);
// Send to printer
} catch (error) {
if (error instanceof ZodError) {
console.error('Validation errors:', error.errors);
}
}Examples
See the examples/ directory for complete working examples:
simple-label.ts- Basic label with text fields and barcode
Testing
Run tests with:
npm testWatch mode:
npm run test:watchBuilding
Build the library:
npm run buildLicense
ISC
Contributing
Contributions are welcome! Please ensure all tests pass and follow the existing code style.
