Skip to content

feat(code128): the mode prop emits ^BC m=A and the canvas packs digit runs into Subset C - #588

Merged
u8array merged 2 commits into
u8array:mainfrom
hieptuanle:feat/code128-auto-mode
Oct 31, 2026
Merged

u8array merged 2 commits into
u8array:mainfrom
hieptuanle:feat/code128-auto-mode

Conversation

@hieptuanle

Copy link
Copy Markdown
Contributor

Summary

Code 128 had no way to set the ^BC m parameter. Every export was mode N (Subset B, one symbol per character), and an imported ^BC…,A silently lost its A: the parser kept the field, the preview rendered it at Subset B width, and the next export wrote it back as mode N.

For numeric payloads that costs a lot of label width. 0240018268623 at ^BY2:

modules dots
mode N (today) 178 356
mode A 123 246

Changes:

  • Barcode1DProps gains an optional mode ('N' | 'A', CODE128_MODES), honoured by Code 128 only. gs1 (m=D) still wins, so a GS1-128 field never emits A.
  • Emit: ^BCo,h,f,g,e,A when mode === 'A'; the default stays the bare command, so existing designs export byte-identically.
  • Import: ^BC…,A parses into mode: 'A' (new bcAuto field flag, reset alongside bcGs1).
  • Canvas: planCode128AutoSymbols (in code128Subset.ts) plans mode A per ISO/IEC 15417 Annex E over Subsets B/C (start in C on a leading run of 4+ digits or a 2-digit payload; mid-payload runs of 4+ switch to C, an odd run leaves its first digit in B; drop back to B for a trailing single digit). buildBwipOptions renders that plan as bwip raw, so the preview width equals the printed width. Payloads with control bytes return null and keep the existing A/B invocation path.
  • Panel: an "Auto subset (compact digits)" checkbox on Code 128, hidden while GS1 mode is on. Label added to every locale (including the new ca).
  • MCP: code128 props doc lists mode.

Note: Annex E is the reference here, not firmware measurements. When a run has an odd digit count, Zebra's auto mode may leave a different digit outside Subset C. Symbol count and width are the same either way, and so is the decoded data, but bar-for-bar parity with a real ZD-series print is unverified. I don't have a Zebra handy to measure; happy to adjust if you see a difference.

Test plan

  • pnpm exec vitest run: 374 files / 6138 tests pass. New packages/core/src/lib/code128Auto.test.ts covers the planner (even/odd leading runs, short runs stay in B, 2-digit payload, mid-payload switches, control-byte fallback), emit with and without A, GS1 winning over A, import of ^BC…,A vs bare ^BC, and the rendered footprint (246 vs 356 dots)
  • tsc -b and eslint on the changed files clean
  • Used in production behind our vendored copy (subtree of v0.8.1) in a label designer since 2026-10-27

🤖 Generated with Claude Code

@u8array

u8array commented Oct 30, 2026

Copy link
Copy Markdown
Owner

Thanks for the PR! Since #593 landed, the canvas's existing ^FD reader should handle mode A as well, while mode derivation and capability handling should move into core.

I'll take it from here.

hieptuanle and others added 2 commits October 31, 2026 08:52
… runs into Subset C

Code 128 had no way to pick the ^BC m parameter, so every export was mode N
(Subset B, one symbol per digit) and import dropped an m=A. A numeric payload
prints much wider than it needs to: 0240018268623 at ^BY2 is 356 dots in mode
N and 246 dots in mode A.

- `mode` (N | A) on the 1D props, honoured by Code 128 only; gs1 (m=D) wins
- emit `^BC…,A`, parse m=A back into `mode: 'A'`
- canvas renders mode A from an automatic subset plan (ISO/IEC 15417 Annex E,
  Subsets B/C) so the preview width matches the print
- panel checkbox (hidden while GS1 is on), MCP prop doc, label in every locale

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h its bound chips, and an unmodeled m is reported
@u8array
u8array force-pushed the feat/code128-auto-mode branch from 78605a8 to 5c83712 Compare October 31, 2026 12:33
@u8array
u8array merged commit 3748846 into u8array:main Oct 31, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants