2026-07-04 — v18 print / PDF-friendly export
Unit C ships: a "Print / Save as PDF" action renders the active view — respecting the current zoom window, reverse-complement state, trim mode, and visible quality track — through a clean print stylesheet tuned for the browser's native print-to-PDF dialog.
What shipped
-
New pure module
src/export/print.ts—buildPrintSection()assembles a self-contained<section id="print-view">element containing: a metadata header (file name, total length, strand, trim mode, mean quality, ISO date), a raster PNG snapshot of the chromatogram canvas at the current zoom window, a raster PNG snapshot of the quality-bar track (when visible), the currently visible sequence window as monospaced text, and an annotation summary when features are in view. -
New 🖨 Print / Save as PDF button in the toolbar — enabled only when a trace
is loaded; captures canvas data URLs synchronously, appends
#print-viewtodocument.body, callswindow.print(), then removes the overlay via anafterprintlistener so the live DOM is not polluted. -
@media printblock added tosrc/style.css: hides all direct children of<body>except#print-view; applies A4-landscape page setup (@page), serif body type, and width-100% image blocks for the chromatogram and quality-track snapshots. - Light and dark theme parity: the print CSS forces white background / black text regardless of the active colour scheme, so the PDF output is always paper-legible.
Design rationale
The viewer already captures canvas state correctly (zoom window, revcomp, trim).
Reusing canvas.toDataURL() means the print snapshot is pixel-for-pixel
identical to what the user sees on screen — no re-render path to maintain.
The afterprint event cleans up without race conditions: it fires only
after the print dialog closes, so the DOM snapshot is always available for inspection
(and for the Playwright test, which mocks window.print to prevent the
native dialog from blocking).
Verification added
-
tests/e2e/print.e2e.test.ts— 6 E2E tests with exact-value assertions:- Button disabled before a trace loads; enabled once loaded.
-
Metadata header contains the exact file name (
310.ab1), length formatted as\d+ bp, today's ISO date, and correct strand / trim labels. -
Sequence text starts with the known first base
"T"(cross-checked against base-inspector fixture constants) and contains only valid IUPAC characters. - Chromatogram and quality-track images are valid PNG data URLs.
- Strand label flips to "Reverse complement (3′→5′)" after toggling the strand.
- Trim label updates to "Trimmed" after switching to trimmed mode.
- Annotation section is present when the fixture contains annotations.
@media printCSS rule is verified to exist in the loaded stylesheet.- All content assertions also pass in dark mode.