Repository navigation
fix(print): accented/non-Latin receipts refused or silently missing rows on pack, merchant and WebUSB paths #1350
Description
Parent: #830 (chat leftovers: "accent and non-Latin text blocking the whole receipt", re-reported recently). Root cause reproduced on main @ 8e39053.
Bug
A receipt with accented or non-Latin item text (for example "Burrito de Camarón") can be refused entirely: Receipt not printed: a financial row contains unsupported printer text ... (makeFinancialPrintRefusalMessage, main/printers/thermal.ts ~L151). The expected behavior is that unsupported lines print as a raster image (#643, #659).
What works (verified)
On the default setup (core classic or compact template, any shipped profile, desktop app after the window is ready), accented, CJK, Arabic, Hindi and Thai item names print through raster. This was confirmed end to end with the real Chromium renderer over TCP. Every shipped profile has raster enabled (main/printers/profiles.ts ~L45-116).
Root causes (each reproduced)
- Country-pack bill templates skip raster.
receiptDocumentLinesreturnsnullforpackandmerchant(thermal.ts~L1681), andformatReceiptforcesraster.enabled=falsefor both (~L2032-2035). Item rows are financial, so any character outside the code page refuses the whole receipt. This has been the case since feat(printers): add capability-gated raster printing for non-Latin thermal output #643 (5 Sep). No bundled tax pack ships print templates, so this only hits stores that installed a signed pack template. - Merchant templates silently drop the item row (worse).
document-merchant.tsfinish()callsbuildEscPoswithoutfinancialLineRanges, so the unsupported item row is classified as a plainlineand skipped. Subtotal and TOTAL still print, which is a silent financial omission (the thing fix(printers): prevent silent financial receipt omissions #603 was meant to prevent). - Renderer not ready means refusal. Any raster failure turns into a financial refusal. A reproduced trigger: printing before the Electron app is ready ("Cannot create BrowserWindow before app is ready"). Timeouts (15 s,
raster-renderer.ts~L19) or GPU/offscreen issues on Windows or MAS would look identical. Not verified on those OSes. - WebUSB from a browser or LAN client has no raster.
frontend/src/hooks/usePrinter.ts(~L431-497) rasterizes only throughwindow.electronAPI.rasterizePrintDocument, only for core templates, and only with exactly one WebUSB printer. Otherwise it falls back to the native encoder and refuses (frontend/src/lib/printer/warnings.ts~L72).
Not a regression in the default path. Before #603 (2 Sep), accented text was sent raw instead of being refused, which is likely why it "used to work".
Decisions (maintainer, 23 Oct)
- Raster fallback on every path: core, merchant and pack templates, desktop and browser/WebUSB. Refuse only when the raster image itself cannot be produced.
- A refusal must stay fail-closed: never print a receipt with a missing financial row.
Fix plan
- Merchant: build raster groups through
receiptDocumentLines, stop disabling raster for merchant, and passfinancialLineRangesinfinish()so the native fallback refuses instead of dropping rows. - Pack: add raster grouping and financial ranges to the pack (
escpos-line-template-v1) renderer, and stop disabling raster for pack. - Renderer: wait for
app.whenReady()before creating the raster window instead of failing. - Browser/WebUSB: when the Electron rasterizer is unavailable, rasterize unsupported lines in the browser (canvas) using the same raster grouping, and apply this to core, merchant and pack templates.
- Clearer refusal text when raster genuinely fails (which document, which line, what to try).
Tests
- Pack and merchant templates with an accented item rasterize with no financial warning.
- Merchant native fallback emits a
financialwarning (no silent drop). Add this case totests/printer.test.tstoo. - Core classic/compact on generic-80/58 with "Burrito de Camarón" rasterizes.
- Renderer requested before ready waits instead of refusing.
- Browser canvas rasterization path (unit plus e2e with a WebUSB stub).
- Run
npm run test:printer,npm run test:raster,tests/receipt-column-oracle.test.ts, thennpm test.
Activity