From 081639fd45ecce7e570be810955a44e4dccf056e Mon Sep 17 00:00:00 2001 From: u8array Date: Sat, 30 May 2026 22:24:40 +0200 Subject: [PATCH 1/4] chore(cleanup): post-printer-profile housekeeping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Five themes folded into one commit: 1. designFile: require explicit \`schemaVersion\` (= 1) on the exported design-file JSON, drop the two legacy fallback shapes (pre-version pages-only + pre-multipage objects-only). The project is young; carrying those branches forward would mean a v1→v2 migration later having to dispatch over three shapes instead of one. Files saved by older builds now fail loud (invalid_schema) instead of silently upgrading. 2. Visual-regression re-framing: the text visual suite uploads PrintLabZPL-Bold.ttf to Labelary and registers the same TTF locally with @napi-rs/canvas, so both sides render with identical glyph data. The test measures Skia-vs-Labelary anti-aliasing drift, NOT firmware fidelity. Renamed and re-documented to reflect what it actually checks. 3. Comment trim across the printer-profile epic files (zplSetupScript, PrinterProfile, PrinterSettingsModal, pruneUndefined, useCopyToClipboard) — drop multi-paragraph module headers and per-field docstrings that restate the spec; keep firmware-quirk anchors (^TA padding, ^KN trim, ^SL three- shape), schema cross-field rule, live-clock mode rationale. ~120 lines of retroactive review-prose removed. 4. Dead-code: two locale keys orphaned by the modal refactor (\`output.setupScriptHeading\`, \`output.hiddenSecondaryHint\`) removed across all 32 locales; \`src/registry/_template.ts\` scaffold-only file removed (never imported, no value as documentation — contributors can copy any concrete registry entry instead). 5. API-surface trim: 8 internal-only exports demoted from \`export\` to local scope so the public module surface tracks what's actually consumed elsewhere — LabelaryError, partialLoss, AUTO_SNAP_TOLERANCE_DEG, GRAPHIC_EXT, LIGHT_COLORS, ROOT_CONTAINER, toCode128BRaw, commitRotatedSizeTransform. --- src/components/Canvas/bwipHelpers.ts | 2 +- .../PrinterSettings/PrinterSettingsModal.tsx | 57 ++----- src/components/Properties/useLayerDnd.ts | 2 +- src/lib/designFile.test.ts | 50 +++--- src/lib/designFile.ts | 53 +++---- src/lib/importReport.ts | 2 +- src/lib/labelary.ts | 2 +- src/lib/lineConstrain.ts | 2 +- src/lib/pruneUndefined.ts | 14 +- src/lib/storagePath.ts | 2 +- src/lib/useColorScheme.ts | 2 +- src/lib/useCopyToClipboard.ts | 18 +-- src/lib/zplSetupScript.ts | 150 ++++-------------- src/locales/ar.ts | 2 - src/locales/bg.ts | 2 - src/locales/cs.ts | 2 - src/locales/da.ts | 2 - src/locales/de.ts | 2 - src/locales/el.ts | 2 - src/locales/en.ts | 2 - src/locales/es.ts | 2 - src/locales/et.ts | 2 - src/locales/fa.ts | 2 - src/locales/fi.ts | 2 - src/locales/fr.ts | 2 - src/locales/he.ts | 2 - src/locales/hr.ts | 2 - src/locales/hu.ts | 2 - src/locales/it.ts | 2 - src/locales/ja.ts | 2 - src/locales/ko.ts | 2 - src/locales/lt.ts | 2 - src/locales/lv.ts | 2 - src/locales/nl.ts | 2 - src/locales/no.ts | 2 - src/locales/pl.ts | 2 - src/locales/pt.ts | 2 - src/locales/ro.ts | 2 - src/locales/sk.ts | 2 - src/locales/sl.ts | 2 - src/locales/sr.ts | 2 - src/locales/sv.ts | 2 - src/locales/tr.ts | 2 - src/locales/zh-hans.ts | 2 - src/locales/zh-hant.ts | 2 - src/registry/_template.ts | 25 --- src/registry/transformHelpers.ts | 2 +- src/test/textVisualRegression.test.ts | 19 ++- src/types/PrinterProfile.ts | 40 ++--- tests/fixtures/textTestCases.ts | 14 +- 50 files changed, 136 insertions(+), 384 deletions(-) delete mode 100644 src/registry/_template.ts diff --git a/src/components/Canvas/bwipHelpers.ts b/src/components/Canvas/bwipHelpers.ts index 3755d060..61f14e6e 100644 --- a/src/components/Canvas/bwipHelpers.ts +++ b/src/components/Canvas/bwipHelpers.ts @@ -267,7 +267,7 @@ export { eanCheckDigit, upceCheckDigit } from "../../lib/barcodeCheckDigits"; * Code B here keeps the designer's module count in sync with Labelary. * Returns null for characters outside Code B range (ASCII 32–126). */ -export function toCode128BRaw(text: string): string | null { +function toCode128BRaw(text: string): string | null { if (!text) return null; const parts = ["^104"]; // Start B for (const ch of text) { diff --git a/src/components/PrinterSettings/PrinterSettingsModal.tsx b/src/components/PrinterSettings/PrinterSettingsModal.tsx index a3032058..ec4df60e 100644 --- a/src/components/PrinterSettings/PrinterSettingsModal.tsx +++ b/src/components/PrinterSettings/PrinterSettingsModal.tsx @@ -15,11 +15,8 @@ import { PrintQualityTab } from "./PrintQualityTab"; type TopTabId = 'perLabel' | 'setupScript'; -/** Sub-tab → top-tab assignment. `satisfies` makes TypeScript flag - * any `PrinterSettingsTab` literal that is added to the union but - * forgotten here — without this, a missing tab would silently - * default at runtime. This is the source of truth; rail groups - * below are derived from it. */ +/** Sub-tab → top-tab. `satisfies` flags any PrinterSettingsTab union + * literal that gets added but forgotten here at compile time. */ const TOP_TAB_OF = { mediaFeed: 'perLabel', printQuality: 'perLabel', @@ -35,12 +32,6 @@ const TOP_TAB_LABEL_KEY = { setupScript: 'railGroupSetupScript', } as const satisfies Record; -/** Rail-tab order per top-tab, derived from TOP_TAB_OF so the source - * of truth stays the single literal map above. Iteration order over - * TOP_TAB_OF entries is insertion order, which is the desired rail - * order — keep entries in the map in the order the rail should show - * them. Seed is derived from TOP_TAB_ORDER so a new TopTabId added - * there can't silently produce `undefined.push(...)` at runtime. */ const TABS_BY_TOP_TAB: Record = (() => { const acc = Object.fromEntries( TOP_TAB_ORDER.map((id) => [id, [] as PrinterSettingsTab[]]), @@ -51,9 +42,7 @@ const TABS_BY_TOP_TAB: Record = (() => return acc; })(); -/** Per-tab content registry. Tabs absent here render as disabled - * WIP rail entries; the rail prevents selection so the modal - * never has to handle a missing-component branch. */ +/** Tabs absent here render as disabled WIP rail entries. */ const TAB_COMPONENTS: Partial> = { mediaFeed: MediaFeedTab, printQuality: PrintQualityTab, @@ -62,21 +51,10 @@ const TAB_COMPONENTS: Partial> = { identity: IdentityTab, }; -/** Modal-box class kept as a constant rather than inline so the - * width / shadow tuning is named and stays consistent if other - * modals adopt the same shell. Fixed height (h-[600px]) so the - * modal does not resize when switching tabs of different field - * counts; the docked preview anchors at the bottom. `max-h-[85vh]` - * is a fallback cap for very short viewports. */ const MODAL_BOX_CLS = "bg-surface border border-border rounded-lg shadow-2xl " + "w-[720px] max-w-[95vw] h-[600px] max-h-[85vh] flex flex-col overflow-hidden"; -/** Docked preview height. 160px = ~9 lines of mono ZPL at 13px/1.45 - * plus the header strip and padding. Fixed (not collapsible) so the - * modal's vertical rhythm stays identical across top-tabs; the empty - * per-label state keeps the same height as the populated setup-script - * state. */ const PREVIEW_HEIGHT = "h-40"; export function PrinterSettingsModal() { @@ -126,11 +104,8 @@ export function PrinterSettingsModal() {
@@ -210,10 +185,8 @@ export function PrinterSettingsModal() { ); } -/** Docked preview pane at the bottom of the modal, rendered only on - * the Setup-Script top-tab. Shows the freshly-generated script plus - * Copy + Send actions. Per-Label has no preview here because per- - * label ZPL still lives in the editor's main output panel. */ +/** Docked preview pane on the Setup-Script top-tab. Per-Label has no + * preview here — its ZPL still lives in the editor's main output. */ function PreviewDock({ setupScript, printerProfile, @@ -226,8 +199,7 @@ function PreviewDock({ onSend: () => void; }) { const t = useT(); - // Live-clock mode (useCurrentTimeForClock) needs the payload - // freshly generated at click-time, not the closured snapshot. + // Live-clock mode needs the payload generated at click-time. const { copy, copied } = useCopyToClipboard(() => generateSetupScript(printerProfile)); const hasScript = !!setupScript; @@ -239,21 +211,14 @@ function PreviewDock({ {t.printerSettings.previewHeading}
- {/* Clear sits on the destructive side of a divider so the - red-hover affordance + spatial separation make a mis- - click into the adjacent primary (Send) much less - likely. Same muted resting state as Copy keeps the - header visually quiet until hover. */} + {/* Clear: separated from Send by a divider; red hover + + red focus-visible ring so destructive intent is visible + to both pointer and keyboard users. */}