From cfd42dd92aebf462c66f1f7acc2d413453dce5c1 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Wed, 27 May 2026 10:04:36 -0400 Subject: [PATCH] TODO: mark JPEG P1 shipped; refine P2/P4 + selection-chrome scope Co-Authored-By: Claude Opus 4.7 --- TODO.md | 68 ++++++++++++++++++++++++--------------------------------- 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/TODO.md b/TODO.md index 66c51c7..1a86e8e 100644 --- a/TODO.md +++ b/TODO.md @@ -18,26 +18,24 @@ Running list of deferred work. Detailed specs for the larger items live in automatically on first import) so the canvas dims = image dims. Edge cases: huge images (clamp to CUSTOM_ART_MAX), aspect-locked layouts (Slide is locked 16:9 — should be skipped or warn). -- **JPEG export: hide layer-selection outlines.** The Save-as-JPEG - flow currently renders the selected-layer dashed outline in the - output. Add `body.exporting` (or similar) state that strips - selection chrome before the raster snapshot. -- **One-click JPEG export (skip the PDF round-trip).** Today the - flow is: print → user saves PDF → user re-picks PDF → PDF.js - converts to JPEG. We can't cache the PDF in between — `window - .print()` doesn't expose the generated bytes to JS. Instead, - write a direct canvas rasterizer that walks the layer model - (image / text / shape / color / qr / pixelart) and draws each - layer onto an off-screen canvas at the artboard's design dims, - then `toBlob('image/jpeg')`. Same approach the pixel-art PNG - export already uses, generalised. CORS-tainted remote images - (cross-origin host without `Access-Control-Allow-Origin`) would - break the direct path — fall back to the existing PDF round-trip - for those with a one-line "this image needs the PDF route" toast. - Most modern image hosts (CDNs, Blossom blobs) send CORS so the - fallback should be rare. ~300–500 LoC of layer-by-layer drawing - code; reuses `renderShapeIntoElement` etc. as references for - geometry but writes to canvas instead of DOM. +- **Hide layer-selection outlines in PDF Print + JPEG-PDF-fallback.** + The direct JPEG rasterizer (P1) draws to canvas via the canvas API + without ever touching the DOM, so selection chrome never appears in + the JPEG. The PDF Print / Save path AND the JPEG-fallback-via-PDF + path still render the live DOM though, so a dashed selected-layer + outline can sneak into those outputs. Add `body.exporting` (or + similar) class that strips `.freeLayer.selected` outlines and the + resize handles before either flow snapshots. +- **JPEG export — rich-text rendering (P2).** Plain-text only today + in the direct JPEG flow (drawTextLayerToCanvas uses + layerHtmlToPlainText). Add an SVG-foreignObject renderer that + fires when `layer.html` contains inline marks (``/``/``/ + ``/`
    `/`
      `/`
    1. `), with the existing fillText path as + fallback for plain text. ~150 LoC. +- **JPEG export — DPI / quality selector (P4 polish).** Currently + hard-coded to dpi=150 / quality=0.92. Add a small dropdown in the + Export panel: Low (96 dpi, 0.8) / Standard (150, 0.92) / Print + (300, 0.95). ~40 LoC. - **Independent-axis corner-node resize.** Corner resize handles currently lock the aspect ratio (or scale both axes together). Behaviour should follow the actual drag vector: dragging mostly @@ -46,26 +44,6 @@ Running list of deferred work. Detailed specs for the larger items live in movement, not to each other. Applies to every layer type's resize handles, not just text. -## CORS for remote-image raster export - -Quick reply, no action yet: - -- The PDF Print/Save path renders via `window.print()` → the browser's - native print/PDF engine, which handles cross-origin images fine. No - CORS issue there. -- The JPEG export path already round-trips through PDF.js (PDF → JPEG), - so it inherits the PDF path's CORS tolerance. If it's failing for - some images, the root cause is likely the print path itself, not a - canvas taint. -- The canvas-tainted situation only bites if we ever do a direct - `.toBlob('image/jpeg')` against a layout that contains a - cross-origin remote `` without CORS headers. Options if it - becomes a real problem: (a) keep using the PDF.js round-trip; - (b) recommend CORS-friendly hosts (Blossom blobs, ImgBB, most - CDNs send `Access-Control-Allow-Origin: *`); (c) add an - optional same-origin proxy endpoint — needs a server, which the - app currently doesn't have. - ## QR code layer — remaining phases Phases A and B shipped (the `qr` layer type: data, error-correction level, @@ -142,6 +120,16 @@ Each has a full spec in `docs/`. ## Shipped (recent) +- **JPEG export — one-click direct rasterizer (P1).** Replaces the + print-to-PDF-then-re-pick flow for Cover, Disc sheet, Jewel, + Disc design, Custom Art, and Slide canvases. The infrastructure + was already 90% built (drawLayerToCanvas + four canvas-type + rasterizers existed but were never wired to any entry point); + P1 added the missing Custom-Art rasterizer + the orchestrator + that picks the right rasterizer per templateMode, pre-flights + CORS via the existing _exportFailedImages set, and falls back to + the print modal when any image can't be embedded directly. + - **Slide deck PDF export** — multi-page PDF, one page per slide. The existing Print / Save PDF button is context-aware: in the Deck Builder it builds a hidden print-only container with one page per slide (themed