Skip to content

Releases: jonathanspiva/zplkit

Release list

ZPLKit 1.0.0

Choose a tag to compare

@jonathanspiva jonathanspiva released this 15 Aug 05:26
92f1dee

First public release.

Breaking changes

These affect anyone who built against pre-release code:

  • The ZPLVerifier module (product) was renamed to ZPLKitVerifier. Update imports to import ZPLKitVerifier. The entry type is still named ZPLVerifier.
  • ZPLVerifier.analyze(_:) and the verify(...) overloads are now async throws (migrated to the Swift-native Vision API).
  • ZPLKitVerifier's expectation types were renamed TextTextExpectation and
    BarcodeBarcodeExpectation, so Text no longer collides with ZPLKit.Text
    when both modules are imported for the build → render → verify workflow.
  • Minimum platforms are iOS 26 / macOS 26 / tvOS 26 / watchOS 26, and Swift 6.3
    is required (swift-tools-version: 6.3). An earlier pre-release targeted 27 /
    Swift 6.4; the floor was lowered so the package installs on a shipping
    toolchain rather than a beta OS. Nothing in the library needed the higher
    floor: the Swift-native Vision API shipped in iOS 18 / macOS 15, and
    NetworkConnection is macOS 26.
  • Removed the inert dpi: parameter from ZPLRenderer.render(_:) and
    renderToPNG(_:). Output dimensions are derived from the label's ^PW/^LL
    dot values, so the parameter never had any effect.
  • ZPLRenderer.renderToPNG(_:) returns a PNGRenderResult struct instead of a
    (data:metrics:) tuple. A tuple return type can never gain a member, so it
    would have been frozen at 1.0.
  • Removed five public error cases that nothing ever threw:
    PrinterError.printerNotFound / .receiveFailed, VerifierError.unexpected,
    and ZPLRendererError.parseError / .unsupportedCommand. They documented
    conditions that could not occur, and deleting them after 1.0 would be a break.
    ZPLParser.parse keeps throws for future use.
  • CGImage.pngData() and CoreGraphicsRenderer are now internal. The former is
    a retroactive extension on a system type, which collides with the same
    extension anywhere else in a consumer's dependency graph; the latter is
    unreachable in practice (ParsedLabel has no public initializer) and kept the
    internal parse-to-draw pipeline frozen. Use ZPLRenderer.render(_:).
  • ZPLTemplate.render(with:) is now render(substituting:), matching
    ZPLLabel; DataMatrix.size(_:) is now moduleSize(_:), matching
    moduleWidth(_:) / magnification(_:) on its siblings.
  • PrinterConfiguration.fieldRotation is a typed FieldRotation enum instead of
    a String, and its cases spell the same as ZPLKit.Rotation
    (.normal / .rotated90 / .inverted / .rotated270).
  • VerifierError.visionError was removed (no consumers).

Added

ZPLKit (Label Generation)

  • Declarative Swift API using result builders for building ZPL labels
  • Text elements: Text, TextBlock with fonts, rotation, reverse print, baseline positioning
  • 1D Barcodes: Barcode128, Code39, EAN13, EAN8, UPCA, UPCE, Interleaved2of5
  • 2D Barcodes: QRCode, DataMatrix, PDF417, Aztec, IntelligentMail
  • Shapes: Box, Circle, Ellipse, HorizontalLine, VerticalLine, DiagonalLine
  • Graphics: Graphic element for embedding CGImage content, with dithering (Floyd-Steinberg, Atkinson) and aspect-fill cropping
  • Utilities: Comment, SerialNumber for label metadata and sequential numbering
  • Label configuration: print quantity, print speed, darkness, reverse print, label home
  • Template substitution: {{variable}} syntax for dynamic label content
  • Printer commands: PrinterCommand enum for ~WL, ~JC, ~JR, ~JA
  • Type system: DPI, Dimension, Position, Rotation, ZPLFont types
  • Full Swift 6 concurrency support with Sendable conformance on all types
  • Protocol conformances: Codable, Equatable, Hashable, CustomStringConvertible

ZPLKitRenderer (Parsing & Rendering)

  • Native Swift ZPL parser supporting all major commands
  • CoreGraphics-based rendering engine for PNG output
  • Bundled Roboto Condensed Bold font for accurate Font 0 rendering
  • Barcode rendering: Code128, Code39, EAN-13/8, UPC-A/E, Interleaved 2 of 5, QR, Aztec, PDF417
  • Parser sub-modules: BarcodeParser, ShapeParser, TextParser, GraphicParser
  • ^GF graphic decoding: binary (^GFB), ASCII run-length compression in ^GFA (repeat-count letters, ,/! row fills, : row repeat), and ^GFC :B64:/:Z64: (zlib) formats
  • Hex character decoding (^FH with _XX sequences)
  • Render metrics: parse time, render time, image dimensions

ZPLKitPrinter (Network Printing)

  • ZPLPrinter: Send ZPL to printers via TCP (port 9100)
  • ZPLPrinterBrowser: LAN discovery via Zebra's UDP broadcast protocol (port 4201)
  • DiscoveredPrinter: Printer metadata from network discovery
  • Two-way communication: query() method for bidirectional printer queries
  • Status queries: queryStatus() for ~HS (Host Status) response parsing
  • Printer info: queryInfo() for ~HI (Host Identification) response parsing
  • Memory status: queryMemory() for ~HM (Host Memory) response parsing
  • Configuration: PrinterConfiguration with type-safe enums, presets, and apply/setup methods
  • Diagnostics: combined status, info, memory, and settings in one call
  • Test pages: printConfigurationLabel(), printNetworkConfigLabel()
  • Structured response types: PrinterStatus, PrinterInfo, MemoryStatus
  • Async/await API with configurable connection and response timeouts, plus an idle timeout for automatic connection cleanup

ZPLKitVerifier (Label Verification)

  • Barcode detection via Vision framework (Code128, QR, Code39, EAN-13, Aztec, PDF417, etc.), covering all 24 Vision symbologies
  • Text OCR via the Swift-native RecognizeTextRequest
  • Discovery mode: analyze() to discover all barcodes and text in an image
  • Assertion mode: verify() with a declarative expectations DSL
  • Expectation types: Barcode(symbology, exactly/containing:), Text(exactly/containing:)
  • Vision hints optimization for faster detection
  • Bounds/clipping detection for edge content
  • Result types: AnalysisResult, VerificationResult, DetectedBarcode, DetectedText

Test Fixtures

  • 125 ZPL fixture files covering text, barcodes, shapes, and graphics
  • fixtures.json metadata with descriptions, categories, features, expected barcodes
  • Reference images from Labelary for comparison
  • Visual test harness with HTML comparison output
  • Renderer accuracy scoring (90.5% baseline vs Labelary)

Documentation

  • DocC documentation for all public types
  • Getting Started guide with full API reference
  • Test Fixtures guide for parser/renderer validation
  • README with quick start examples

Quality

  • Unit and integration tests across all modules
  • GitHub Actions CI with visual comparison artifacts
  • MIT license

Changed

  • ParsedLabel / ParsedElement and the other Parsed* types are documented as
    part of the public, semver-stable API, with doc comments on every property.
    ParsedElement may still gain cases in minor releases, so switch over it with
    a default.
  • BarcodeSymbology is not @frozen, so future Vision symbologies can be added
    without a source break (switch over it with a default case).
  • Expectation provides a default visionHints, so future protocol
    requirements will not break external conformers.
  • PrinterConfiguration.networkConfig(...) / dhcp() (the ^NS path) are
    documented as experimental / not hardware-verified: a static-IP change via
    ^NSP + ~JR was observed not to take effect on a GX420t (V56), so the
    emitted command shape and reset sequence are still unconfirmed. Use with
    caution and a recoverable printer.
  • Adopted Swift 6.2's "approachable concurrency" upcoming-feature flags via a shared swiftSettings block applied to every first-party target: NonisolatedNonsendingByDefault and InferIsolatedConformances. (InferSendableFromCaptures is already enabled by default in Swift 6 language mode, so it is intentionally not enabled explicitly.) Default isolation remains nonisolated; the package is a library and does not force callers onto the main actor.
  • ZPLVerifier.analyze/verify timing now uses ContinuousClock; the reported *TimeSeconds fields are documented as wall-clock (including time suspended at await).
  • Set swiftLanguageModes: [.v6] explicitly in the manifest.
  • Migrated ZPLVerifier to the Swift-native Vision API (DetectBarcodesRequest, RecognizeTextRequest, ImageRequestHandler), replacing the legacy VN-prefixed completion-handler API.
  • ZPLVerifier now runs barcode and text recognition concurrently (async let), roughly halving analysis latency.
  • Removed the Awesome dependency (and the GraphicsTest dev tool that used it); the library now has zero external dependencies.
  • The README documents which ZPL commands the preview renderer implements, and
    what the four unimplemented ones (^LR, ^CI, ^CC/^CT, raw-binary
    ^GFB) do on a printer versus in the preview.
  • CI builds the package at its advertised floor on a GitHub-hosted macos-26
    runner (Xcode 26.6 / Swift 6.3) with -warnings-as-errors, which also gives
    fork PRs a CI signal. The self-hosted runner additionally covers the visual
    comparison and the opt-in live-printer job, gated behind a minimum accuracy
    score and per-job timeouts.

Fixed

Label generation

  • ^BY module width is now emitted by every 1-D barcode (Code39, EAN13,
    EAN8, UPCA, UPCE, joining Barcode128/Interleaved2of5), and all expose
    a moduleWidth(_:) modifier. Previously a preceding barcode's module width
    could leak in via ^BY stickiness.
  • EAN13/EAN8/UPCA now reject a fully-specified value whose trailing check
    digit doesn't match the computed one, instead of letting the printer silently
    re-derive a different digit.
  • Template substitution corrupted Code 128 payloads. Inside a ^BC field a
    literal > is an invocation...
Read more