Zigmoon Apps

Releases & Changelog

SUPER PRINT v1.7.259

Released July 2–3, 2026

✍️ Write in / around a shape & Write on path new

  • Grouped copy/paste — click either member to copy both. The pasted pair is fully linked and stays on the page.
  • Around mode: shape in front — shape is in front; double-click shape to insert image, double-click text to edit.
  • Proportional resize — font, stroke and shape geometry all scale together.
  • Inside mode: no more ghost shapes — single clean regeneration on resize.

📄 Vector PDF export — major fixes fix

  • Pen strokes & write-on-path text now fully exported (were missing).
  • Around text: no stray masks — true vector glyphs along the curve.
  • Polygons & polylines now exported in vector mode.
  • Open pen trace used as guide: removing its stroke now fully hides it from the PDF.

🔧 Technical

SW: superprint-shell-v1.7.259-penfill-fix. Vector paths use calcTransformMatrix() for pixel-perfect accuracy.

→ Open SUPER PRINT


CUT THE FLOW v4.2.0 — Full Touch Support + Robustness + Accessibility

Released — July 1, 2026

📱 Timeline & preview enfin pilotables au doigt new

  • Timeline 100 % tactile — déplacement de la tête de lecture, drag des clips (simple + multi-sélection), trim (poignées gauche/droite) et changement de piste utilisaient exclusivement les événements souris → inutilisables sur tablette / mobile. Tout est migré vers les Pointer Events (avec pointercancel). La souris se comporte à l'identique ; le tactile fonctionne désormais parfaitement sur iPad / Android / écrans hybrides.
  • Overlays de preview tactiles — drag du texte, drag + redimensionnement des blocs (8 poignées) et repositionnement/scale de la vidéo (4 poignées) passent aussi en Pointer Events.
  • touch-action: none sur les éléments draggables pour que le geste tactile pilote le drag au lieu de scroller/zoomer la page.

🛡️ Robustesse — plus de défaillance silencieuse new

  • Nouveau gestionnaire d'erreurs global (error + unhandledrejection) : les erreurs non capturées et rejets de promesses affichent un message discret et rate-limité, avec trace console pour le debug. Les bruits bénins (ResizeObserver, erreurs cross-origin) sont ignorés.

♿ Accessibilité (WCAG) new

  • Anneau de focus clavier (:focus-visible) restauré sur les éléments interactifs qui masquaient l'outline pour le rendu souris — visible uniquement au clavier (WCAG 2.4.7).
  • Splash screen doté de role="status" + aria-live pour une annonce correcte par les lecteurs d'écran.

🔧 Technical

Service Worker bumped to cuttheflow-shell-v4.2.0-touch-a11y.

📝 Details

Single-page editor · Vanilla JS class CutTheFlow · 100% client-side, no backend

→ Open CUT THE FLOW


CUT THE FLOW v4.1.1 — Export Engines Audio Audit + Adaptive Preview

Released — July 1, 2026

🎧 Audit des 5 moteurs d'export — audio+vidéo enfin parfait partout fix

  • WebCodecs (MP4 H.264) n'exportait plus le son — les clips audio étaient collectés puis jamais muxés → fichier muet. Désormais, dès qu'un projet contient de l'audio, WebCodecs bascule automatiquement vers le moteur MP4 audio+vidéo (MediaRecorder / H.264). Les montages 100 % muets gardent le chemin hardware ultra-rapide.
  • Lite (WebM VP9) exportait muet — l'ancien code montait tout le pipeline audio, le jouait à voix haute pendant l'export, l'enregistrait dans un flux jeté, puis l'ignorait. Le muxer WebM interne étant vidéo-seule, Lite délègue maintenant les projets sonores au muxage WebM VP9/Opus natif (audio+vidéo garanti), en conservant la réduction de résolution des petites machines.
  • Studio perdait l'audio embarqué dans les vidéos — l'extraction via captureStream()OfflineAudioContext est un no-op. On décode désormais le fichier source (fetch + decodeAudioData) dans le mix offline, exactement comme les clips audio.
  • Volume de piste respecté à l'exporttrackVolume était ignoré par Studio/Lite (toujours 100 %). Il est maintenant propagé depuis la piste, comme le fait déjà le moteur MediaRecorder.

🐢 Mode performance preview — contrôle manuel pour petites machines new

  • Nouvelle préférence « Mode performance (preview) » (section EXPORT & QUALITÉ) : force la preview en mode allégé (frames allégées + horloge JS stable) sans attendre la détection automatique. Idéal Mac Intel / petites machines. À laisser OFF sur grosse machine pour une preview ultra-fluide. Appliqué en direct, persisté, pris en compte par l'auto-optimisation.

🎥 Timeline multi-piste — audit

  • Logique de composition vérifiée et confirmée cohérente : piste du haut au premier plan, overlays texte/formes empilés correctement, pistes audio exclues de la composition vidéo. Aucune régression.

🔧 Technical

Service Worker bumped to cuttheflow-shell-v4.1.1-audio-engines.

📝 Details

Single-page editor · Vanilla JS class CutTheFlow · 100% client-side, no backend

→ Open CUT THE FLOW


SUPER PRINT v1.7.259

Released July 2–3, 2026

✍️ Write in / around a shape & Write on path new

  • Grouped copy/paste — click either member to copy both. The pasted pair is fully linked and stays on the page.
  • Around mode: shape in front — shape is in front; double-click shape to insert image, double-click text to edit.
  • Proportional resize — font, stroke and shape geometry all scale together.
  • Inside mode: no more ghost shapes — single clean regeneration on resize.

📄 Vector PDF export — major fixes fix

  • Pen strokes & write-on-path text now fully exported (were missing).
  • Around text: no stray masks — true vector glyphs along the curve.
  • Polygons & polylines now exported in vector mode.
  • Open pen trace used as guide: removing its stroke now fully hides it from the PDF.

🔧 Technical

SW: superprint-shell-v1.7.259-penfill-fix. Vector paths use calcTransformMatrix() for pixel-perfect accuracy.

→ Open SUPER PRINT


SUPER PRINT v1.7.232

Released June 17, 2026

🔲 Rounded corners new

  • New rounded corners panel in right sidebar — auto-shows for rectangles.
  • Linked mode: one slider for all 4 corners.
  • Unlinked mode: 4 independent corner sliders.
  • One-click linked/unlinked toggle. Image masks preserved on conversion.
  • Fully persisted in .sp and .json exports.

🍏🐛 Bug Fixes fix

  • Safari Mac text tool completely reworked.
  • Mac font size fix for vectorization & vector PDF.
  • Vector PDF export text section fully rewritten.
  • Fixed text disappearing on paste.

⌨️ New Shortcuts new

  • Ctrl+T now toggles right sidebar instead of opening a new tab.

→ Open SUPER PRINT


SUPER PRINT v1.7.216

Released June 15, 2026

🐛 Bug Fixes fix

  • bold → 700, normal400) in WOFF2 font loading." data-i18n-jp="ネイティブベクターPDF出力(「ベクタータイポグラフィ」チェック時):プレビューと生成PDF間でフォントサイズが完全に保持されるようになりました。WOFF2フォント読み込み時のフォントウェイト正規化(bold700normal400)を修正。">Font sizes perfectly preserved in native vector PDF export. Fixed fontWeight normalization in WOFF2 font loading.
  • Vectorization now preserves original size and style.
  • Splash screen no longer freezes on startup.
  • Imposed PDF export loader no longer hangs.

✨ New Features new

  • Native vector PDF with selectable text, embedded fonts, vector shapes — like InDesign.
  • User-uploaded custom fonts supported in vector export.
  • Added fontkit.min.js for TTF parsing.

→ Open SUPER PRINT


SUPER PRINT v1.7.179

Released June 11, 2026

🔤 Vectorization final fix fix

Y inversion in SVG, correct baseline, unified right-click/sidebar.

🔢 Version

Service-worker and cache-bust updated to v1.7.179.

→ Open SUPER PRINT


SUPER PRINT v1.7.176

Released June 8, 2026

🔤 Figma-like vectorization new

Real glyph-to-Bézier paths via opentype.js. Font cache, kerning, 2 modes.

🩹 Fixes fix

  • Fixed right-click vectorize not working.

🔢 Version

Service-worker and cache-bust updated to v1.7.176.

→ Open SUPER PRINT


SUPER PRINT v1.7.175

Released June 8, 2026

🔤 Figma-like text vectorization new

Text vectorization now uses opentype.js for real Bézier paths. Font cache, kerning, 2 modes.

📐 Automatic columns new

Column choice now creates empty text blocks automatically.

🖊️ Text in/around/on shape — InDesign-like new

Visible cursor, auto sidebar, IText typography panel for all shape text modes.

🩹 Fixes fix

  • Undo/Redo returns to correct page.
  • Cross-page multi-selection fixed.
  • Cover checkbox removed.

🔢 Version

Service-worker and cache-bust updated to v1.7.175.

→ Open SUPER PRINT


SUPER PRINT v1.7.174

Released June 8, 2026

🏷️ Version sync fix

Version numbers in Settings pop-in and documentation synced to v1.7.174.

🖼️ Template images now local fix

Templates now use local photos instead of external URLs.

🔢 Version

Service-worker CACHE_NAMEsuperprint-shell-v1.7.174-version-sync. Cache-bust JS/main.js?v=20260608-v174-version-sync.

→ Open SUPER PRINT


SUPER PRINT v1.7.173

Released June 8, 2026

🖼️ Local themed images new

Automatic layout images are now stored locally in img/auto/ (75 real Unsplash photos, free license). No more network calls freezing the browser on large documents. Each theme has 4 dedicated photos.

🎨 New color themes new

6 new themes: Swiss, Editorial, Warm, Cool, Neon, Pastel.

🔤 Extended font pairs new

13 font pairs including IBM Plex Mono and IBM Plex Sans. Fonts are now consistent with the chosen theme.

📐 7 layout patterns new

7 print-inspired patterns: Hero, Full Image, Swiss Grid, Editorial, Asymmetric, Grid, Color Block, Minimal.

🩹 Fixes & optimizations fix

  • Z-order : text is always on top, above images and shapes.
  • Bleed : all shapes touching edges use elFull (3 mm on each side).
  • Footer margin : content stops 32 mm from the bottom.
  • Spreads : per-page backgrounds, no bleed at center fold.
  • Performance : image loading throttled in batches of 4.

🔢 Version

Service-worker CACHE_NAMEsuperprint-shell-v1.7.173-local-images-zorder. Cache-bust JS/main.js?v=20260608-v173-local-zorder. All version labels synced to v1.7.173.

→ Open SUPER PRINT


SUPER PRINT v1.7.172

Released June 8, 2026

🎨 Varied AI layouts by document type new

The automatic layout engine now detects document type and adapts the layout:

  • Magazine/Brochure/Catalog/Portfolio : classic hero band with image and title
  • Lookbook/Poster : full-page image with minimal text overlay
  • Book/Report/Newsletter : clean layout, centered title, no hero band

🔢 Version

Service-worker CACHE_NAMEsuperprint-shell-v1.7.172-doctype-layouts. Cache-bust JS/main.js?v=20260608-v172-doctype-layouts. All version labels in index.html synced to v1.7.172.

→ Open SUPER PRINT


SUPER PRINT v1.7.170

Released June 8, 2026

✏️ InDesign-style text on path new

Text inside, around and on shapes and paths has been completely redesigned to match InDesign behavior:

  • Text inside : automatic inner padding (4%), source shape in semi-transparent light gray to suggest the container, adaptive width (72% circle, 88% rectangle).
  • Text around : repeating pattern that wraps the full perimeter, adaptive font size based on shape dimensions, proportional character spacing. Source shape becomes invisible — only the curved text is visible.
  • Text on path : path length measured automatically, font size calculated to fill the path (14-36pt), compatible with pen, pencil and freeform.

🤖 Automatic layout engine (no AI required) new

New Automatic tab in the New Project pop-in. A pure JavaScript engine generates professional layouts from keywords:

  • Keywords : brochure, 8 pages, 2 columns, corporate, cover, title → full layout with cover, titles, subtitles, Lorem ipsum columns, decorative shapes.
  • 6 color themes : corporate, creative, nature, modern, luxury, tech — each with its own primary/accent/text palette.
  • 6 font pairs : Bebas Neue+Open Sans, Playfair Display+Lato, Poppins+Open Sans, Montserrat+Roboto...
  • 🎲 Random example button : generates a prompt and layout automatically to discover keywords.

🧲 Z-index preserved during drag fix

Moving an object (image, text, shape) no longer sends it behind other elements. The dragged object is automatically brought to front (bringToFront) at drag start.

🌐 i18n & DeepSeek as default new

The Basic/Advanced tabs in the New Project pop-in are now translated (EN/FR/JP). DeepSeek is the default AI engine (🚀 Recommended), with 4 models available including V3 and R1.

🧹 Console log cleanup fix

Removed diagnostic console.log calls that were running in production (PDF export, master injection, vector font loading, multi-page asset build). Imposition logs remain protected behind window.__sp_imp_debug.

🔢 Version

Service-worker CACHE_NAMEsuperprint-shell-v1.7.170-indesign-text-curve. Cache-bust JS/main.js?v=20260608-v170-indesign-text-curve. All version labels in index.html synced to v1.7.170.

→ Open SUPER PRINT


SUPER PRINT v1.7.169

Released — June 8, 2026

📋 Copier-coller entièrement refondu fix stable

Le copier-coller (Ctrl+C / Ctrl+V) a été intégralement audité et corrigé pour tous les types d'objets — shapes, SVG, images, texte, sélections multiples — sur tous les chemins : raccourcis clavier, menu contextuel mobile, Alt+clic, Alt+drag. Les correctifs couvrent :

  • Clone direct natif Fabric : le presse-papier stocke maintenant des clones obj.clone() natifs au lieu de JSON toObject() + enlivenObjects(). Le chemin JSON perdait des propriétés géométriques internes (surtout sur polygon et path) → la forme collée était déformée ou "toute petite".
  • Sélections multiples scalées : l'échelle du groupe ActiveSelection n'était pas propagée aux enfants lors du collage → objets collés à leur taille de base au lieu de la taille affichée. Capture maintenant la matrice de transformation monde complète (calcTransformMatrix() + qrDecompose()) avant le dégroupage.
  • Position de collage : les objets collés en multi-sélection atterrissaient en haut à gauche de la page au lieu d'être décalés de 10 px par rapport aux sources. Le _spRestoreSourceXforms écrivait des coordonnées monde dans des propriétés interprétées comme relatives au centre du groupe → positions négatives.
  • Cache bitmap Fabric désactivé sur les formes : le cache objectCaching de Fabric.js produisait un bitmap périmé sur les clones de formes (polygon, path, rect, circle…). Résultat : le cadre bleu de sélection était à la bonne taille mais l'intérieur restait vide ou minuscule jusqu'à ce qu'on touche une poignée. Le cache est maintenant désactivé (objectCaching = false) sur toutes les formes vectorielles après collage — rendu direct, toujours correct.
  • Source non mutée : le _spRestoreSourceXforms du Ctrl+C objet seul pouvait réappliquer des valeurs périmées après que obj.clone() ait muté des propriétés internes de la source (ex: polygon._pathOffset recalé) → la shape source devenait "toute petite". Supprimé — comme Alt+clic qui fonctionnait déjà.

↩️ Undo/Redo : déplacement d'objets fix

Ctrl+Z après avoir déplacé une image ou une forme ne la ramenait jamais à sa position d'origine. Cause : un trou temporel dans l'historique — le saveState n'était fait qu'au mouse:up (avec 300 ms de debounce). Si Ctrl+Z arrivait avant, l'état pré-déplacement n'existait pas. Un saveState('Déplacement') est maintenant posé au mouse:down, avant le début du drag. L'entrée est renommée en "Objet modifié" au mouse:up pour éviter les doublons.

✏️ Texte sur forme/tracé : édition immédiate new

Ajouter du texte dedans, autour ou dessus une forme ou un tracé (clic-droit) ouvre maintenant automatiquement le panneau typographie de la sidebar droite et passe en mode édition. L'utilisateur peut changer police, corps, couleur et taille sans friction. Le double-clic sur un texte-dans-forme active un mode "déplacement détaché" (bouger le texte indépendamment dans la forme) sans bloquer l'édition.

🖼️ Boutons d'image restylés new

Les boutons recadrer et remplacer sur les images sélectionnées passent d'un carré noir à un fond blanc arrondi avec ombre, icônes foncées par-dessus, empilés verticalement le long du bord droit. L'icône "ciseaux" est remplacée par une icône de cadrage (équerres) bien plus parlante, et l'icône remplacer par une boucle de flèches (repeat).

🔢 Version bumps

Service-worker CACHE_NAMEsuperprint-shell-v1.7.169-multipaste-position. Cache-bust JS/main.js?v=20260608-v169-multipaste-position. Tous les labels de version dans index.html (splash screen, badge, footer, meta generator, SEO) synchronisés sur v1.7.169. Le service-worker fait maintenant skipWaiting() dans l'event install pour activation immédiate (plus de version "waiting" fantôme).

→ Open SUPER PRINT


MAT v1.7.4 — Import/Export .mat fix

Released — June 1, 2026

🐛 Critical: .mat files could not be reopened fix

  • saveElle() exported as .mat (JSON), but openFile() only matched .elle and .json — so any saved .mat fell through to the XLSX parser and failed silently.
  • Fix: openFile() now accepts .mat, .elle and .json.

🛡️ Workbook normalization on load new

  • New normalizeWB() / normalizeSheet() applied to every load path (file open, IPFS, autosave Resume).
  • Converts legacy 2D-array cells to address-keyed map, grows rows/cols to fit all stored cells, clamps activeSheet, fills missing meta/app/version fields.
  • Active sheet is now preserved on load (was hard-reset to 0).

🔧 Technical

Pure browser spreadsheet · Vanilla JS · IndexedDB autosave · IPFS backup via Pinata · offline PWA.

→ Open MAT


CUT THE FLOW v3.7.9 — Shapes & Text Drag + FX Stacking + Fades

Released — June 1, 2026

🖐️ Texte & Formes — déplacement enfin fluide fix

  • Fin du « blocage » — le glisser d'une forme appelait updatePreview() à chaque mouvement, ce qui reconstruisait les overlays et annulait le signal du drag en cours → le geste décrochait. Le déplacement et le redimensionnement mettent désormais à jour le style en direct (rAF), sans reconstruction, avec sauvegarde uniquement au relâchement.
  • Pointer Events partout — texte et formes passent en pointerdown/move/up avec setPointerCapture : souris + tactile + stylet, le drag ne se perd plus si le curseur sort de la zone, touch-action:none (plus de scroll parasite), curseur move/grabbing, sélection du clip au début du geste, sliders du panneau Propriétés synchronisés en direct.

✨ Cumul de FX (effets empilables) new

  • Plusieurs effets par clip — modèle clip.effects[] ({name, intensity}) avec migration auto de l'ancien clip.effect. Clic = ajoute & sélectionne · re-clic d'un FX actif = règle son intensité · encore une fois = le retire · « None » vide la pile.
  • Aperçu = export — la pile est rendue dans un seul canvas via les mêmes algorithmes que l'export (_applyEffectToCtx) ; le color grading reste appliqué par-dessus.

🌗 Intro / Outro — fade in/out audio + vidéo

  • Le panneau Fade s'applique à n'importe quel clip (vidéo, image, audio, forme, texte), en aperçu et à l'export — fade vidéo (images / vidéos / overlays) et fade audio (baseGain × _calcFadeOpacity), audio de vidéo inclus.

🔍 Audit export (.ctf / .json / vidéo+audio)

  • Vérifié que effects[] et fadeIn/fadeOut sont persistés par les 3 formats de sauvegarde (.ctf, .json, Pinata) et restaurés au chargement.
  • Export vidéo confirmé cohérent : fades, pile de FX (_getClipEffects) et color grading rendus à l'identique de l'aperçu.

🔧 Technical

Service Worker bumped to cuttheflow-shell-v3.7.9-shapes-text-drag.

📝 Details

Single-page editor · Vanilla JS class CutTheFlow · 100% client-side, no backend

→ Open CUT THE FLOW


CUT THE FLOW v3.7.6 — Timeline + Export Quality Pass

Released — May 24, 2026

🎬 Timeline + Preview improved

  • Pixel-perfect playheadplayhead & rulerPlayhead rounded to integer pixels (Math.round) → no more sub-pixel jitter during playback
  • Quantized frame-step← / → (1 frame) and J / L (1 s) now routed through quantizeTime() → zero float drift after 100+ steps
  • Wheel hijack fixed — timeline zoom only on Ctrl + wheel (previously every wheel event was hijacked, breaking normal scroll) fix
  • isTimeInClip boundary fix — symmetric epsilon at both ends → no more 1-frame black flash between abutted clips fix

🚀 Export Quality improved

  • Video bitrates raised to YouTube SDR levels (VP9/VP8):
    • HIGH — 720p 5 → 8 Mbps, 1080p 8 → 16 Mbps, 4K 12 → 30 Mbps
    • MEDIUM — 720p 3 → 6 Mbps, 1080p 5 → 10 Mbps, 4K 8 → 18 Mbps
    • Default 6 → 10 Mbps · WebM/VP8 fallback 4 → 8 Mbps
  • Color grading memoizedapplyColorGradingToContext() skips ctx.filter reassignment when the filter string is unchanged (avoids re-parsing the GPU filter chain every frame)
  • GPU-friendly grading canvas — created with { alpha: false, willReadFrequently: false } + imageSmoothingQuality: 'high'

🔧 Technical

Service Worker bumped to cuttheflow-shell-v3.7.6-timeline-export-quality.

📝 Details

Single-page editor · Vanilla JS class CutTheFlow · 100% client-side, no backend

→ Open CUT THE FLOW


CUT THE FLOW v3.7.5 — Audio Pipeline Audit

Released — May 24, 2026

🎧 Audio Quality — End of the Crackles fix

  • AudioContext locked to 48 kHz — built with { sampleRate: 48000, latencyHint: 'playback' } → no more browser resampling artifacts on MP3/AAC sources
  • Opus bitrate doubled — export audioBitsPerSecond bumped 128 kbps → 192 kbps on both primary and fallback MediaRecorder paths (matches optimized-export.js)
  • Seed-once audio sync — export per-frame loop no longer writes audioEl.currentTime on every frame (the cause of decoder click/crackle). Seek once at clip entry, then only resync on catastrophic drift (> 250 ms)
  • Preview drift threshold — relaxed during playback (0.25 s while playing, 0.05 s when paused) → no micro-seeks while listening
  • playbackRate + preservesPitch enforced each tick → zero time-stretch artifacts

🎙️ Extract Audio — No More Double Playback fix

  • Source video is now marked audioUnlinked = true + audioMuted = true after extraction → no more double audio / clipping when both the video clip and the extracted audio track play together
  • Extraction now uses media.originalUrl (full-quality source) instead of the lightweight preview proxy

📝 Details

Single-page editor · Vanilla JS class CutTheFlow · 100% client-side, no backend

→ Open CUT THE FLOW


SUPER PRINT v1.7.150

Released — June 3, 2026

👻 Copier / coller d'images : fin des images « fantômes » fix

En copiant-collant des images d'une page à une autre, certaines images ou blocs apparaissaient sur la page de destination comme des images « fantômes » : elles clignotaient (apparition / disparition aléatoire, juste après le collage et plus tard) et semblaient s'ajouter en double à la composition. En cause : le cache de rendu de Fabric (objectCaching, activé par défaut sur les images) pouvait dessiner un bitmap périmé du clone collé tant qu'un rendu complet ne l'avait pas régénéré — notamment parce que le clonage d'une image est asynchrone. Le collage invalide désormais explicitement le cache de chaque objet collé (et de ses enfants dans un groupe) puis force un rendu complet immédiat et différé, ce qui élimine le clignotement et les doublons visuels.

🔢 Version bumps

Service-worker CACHE_NAME et la query JS/main.js?v=… sont alignés sur v1.7.150 / superprint-shell-v1.7.150-paste-ghost-fix / v=20260603-v150-paste-ghost-fix.

SUPER PRINT v1.7.149

Released — June 3, 2026

🎠 Pop-in « Nouveau projet » : 10 modèles de plus dans le carrousel new

La bande défilante de modèles charge désormais 10 modèles supplémentaires issus de la bibliothèque d'assets principale (gastronomie, sport, architecture, voyage, danse, animaux, burger, flyers restaurant / événement / concert), à la suite de ceux déjà présents.

⌨️ Barre de prompt IA : saisie de texte normale fix

Dans la barre de prompt IA dockée en pied de preview, il était impossible d'effacer le texte (Retour arrière / Suppr) ou de naviguer avec les flèches : seule la frappe de caractères fonctionnait. Le champ étant positionné dans la zone du canevas, les raccourcis globaux interceptaient ces touches. La saisie (effacement, flèches, annulation) est désormais entièrement normale.

🔢 Version bumps

Service-worker CACHE_NAME et la query JS/main.js?v=… sont alignés sur v1.7.149 / superprint-shell-v1.7.149-carousel-assets-ai-input / v=20260603-v149-carousel-assets-ai-input.

SUPER PRINT v1.7.148

Released — June 2, 2026

🖼️ Modèles de magazine : photos uniques & pages mieux remplies new

Passe en profondeur sur les trois derniers modèles (Coiffure, Cuisine, Musique). Chaque emplacement d'image reçoit désormais une photo unique et vérifiée : fini les visuels répétés au sein d'une même maquette. Les pages du grand format Coiffure sont enrichies : feature « Le geste du coiffeur », routine d'entretien en 4 étapes, « Salon du mois » illustré et encart d'abonnement. La page « Albums du mois » du magazine Musique gagne un bloc « Coup de cœur ».

🎯 Pop-in « Nouveau projet » : carrousel de modèles repositionné fix

La bande défilante « Ou partez d'un modèle » revient en bas de la fenêtre, sous les réglages, avec une barre de défilement horizontale plus fine et discrète.

🌐 Traduction du libellé des modèles fix

Le titre « Ou partez d'un modèle » et l'indication « faites glisser » restaient en français quelle que soit la langue. Ils sont désormais correctement traduits en FR / EN / JP et suivent la langue de l'interface.

📑 Export PDF « imposition » en mode page simple fix

L'export d'imposition fonctionnait en double page mais buguait au niveau de la couture en mode page à page (chevauchement dû au fond perdu intérieur). Le rognage par emplacement (gauche / droite) corrige le raccord.

👻 Copier-coller : fin des images « fantômes » fix

Copier-coller (Ctrl+C / Ctrl+V) d'une page à l'autre pouvait faire apparaître des blocs « fantômes » qui clignotaient et s'ajoutaient à la composition. Les objets internes (gabarits, numéros de page, miroirs, indicateurs) sont désormais exclus de la copie.

🔢 Version bumps

Service-worker CACHE_NAME et la query JS/main.js?v=… sont alignés sur v1.7.148 / superprint-shell-v1.7.148-template-photos-unique-fill / v=20260603-v148-template-photos-unique-fill.

SUPER PRINT v1.7.143

Released — June 2, 2026

🤖 Outil IA entièrement repensé new

La pop-in IA a été simplifiée pour être plus claire et plus efficace : on prompte moins, on obtient mieux. Trois nouveautés clés :

  • Sélecteur de structure : un choix explicite Page simple / Double page / Multi-pages (avec nombre de pages). Ce réglage est désormais autoritaire sur l'analyse du texte — l'IA sait sans ambiguïté combien de pages produire, ce qui rend les maquettes nettement plus probantes.
  • Inspiration rapide : 8 puces courtes (couverture magazine, page éditoriale 2 colonnes, affiche, catalogue, menu, CV, flyer, page de garde) qui pré-remplissent un prompt naturel au lieu des longues séries de prompts verbeux d'avant.
  • Barre de prompt IA en pied de preview : activable via une case dans la pop-in (état mémorisé). Une barre dockée en bas de l'aperçu permet de générer directement sur la page active sans rouvrir la fenêtre.

🧹 Fin des placeholders « à générer » fix

Les pages créées en surplus n'affichent plus le texte gris [ CONTENU À GÉNÉRER VIA IA ] qui donnait un rendu « à côté ». Les pages supplémentaires restent propres et vides, prêtes à être générées une par une. Le contexte envoyé à l'IA injecte aussi le type de document et le nombre de pages pour une compréhension non ambiguë de SUPER PRINT.

🆕 Nouvel écran de création de document new

La fenêtre « Nouveau document » est scindée en deux onglets : Basique (formats prédéfinis, nombre de pages, mode page simple / double) et Avancé (largeur/hauteur précises, marge, fond perdu, mode couleur RVB / CMJN). Une bande d'assets défilante propose des modèles directement cliquables depuis cet écran.

📒 5 nouveaux modèles prêts à l'emploi new

  • Magazine 8 pages — Cuisine (double page)
  • Magazine 8 pages — Musique (double page)
  • Menu de restaurant 4 pages
  • CV professionnel 1 page
  • Livre 12 pages tout-texte, typographie clean

💾 Import / Export .sp & .json renforcé fix

Re-audit complet de l'import/export dans les deux sens. Le mode couleur (RVB / CMJN) et les repères manuels (guides) sont désormais persistés et restaurés correctement dans les fichiers .sp, .json local et .json IPFS. Les repères sont ré-appliqués par index de page après le rendu.

🔢 Version bumps

Splash, header badge, JSON-LD softwareVersion, service-worker CACHE_NAME et la query JS/main.js?v=… sont alignés sur v1.7.143 / superprint-shell-v1.7.143-ai-newdoc-templates-importexport / v=20260602-v143-ai-newdoc-templates-importexport.

SUPER PRINT v1.7.139l

Released — May 16, 2026

🎨 Icônes des widgets restaurées (menu masque, ancrage 3×3, pagination) fix

Les emojis du menu « Masque d'image » (Importer/Remplacer, Remplir, Ajuster, Positionner, Retirer) et les flèches de la grille d'ancrage 3×3 s'affichaient comme ? ou ??. Cause : conversion ASCII destructive ancienne (caractères non-BMP perdus, pas du mojibake encodage classique — donc invisible aux scanners ftfy). Restauration : icônes du menu masque → 🖼️ / 🔄 / / / 🎯 / 🗑️ ; grille d'ancrage → ↖ ↑ ↗ ← • → ↙ ↓ ↘ ; bouton de pagination « Précédent » restauré.

🔤 Réparation massive des substitutions et É dans main.js fix

Le même incident historique avait remplacé des centaines de caractères accentués par ou É partout dans le source : commentaires, libellés, noms de filtres (Sépia, Bleu électrique, Vert émeraude), labels d'unités, messages console, libellés de la documentation embarquée. ~140 mots reconstruits avec dictionnaire contextuel (le peut représenter é, è, ê, ô, ç, î ou ' selon le mot — pas de mapping 1:1). Mots traités : Empêcher, Rafraîchir, flèches, excès, Contrôle, forçant, boîte, déplaçables, MÊME, CARACTÉRISTIQUES, etc.

🧹 Nettoyage des préfixes ?? Verbe dans commentaires et chaînes fix

~200 commentaires et chaînes commençaient par ?? (vestige d'emojis perdus en début de log). Ex. // ?? Capturer l'état, console.warn('?? Objet étendu...'). Préfixes supprimés via regex contextuelles. Bullets é Verbe (perdues en début de ligne dans la documentation embarquée) restaurées en ✅ Verbe.

🔢 Version bumps

Splash, header badge, JSON-LD softwareVersion, documentation manuals, service-worker CACHE_NAME et la query JS/main.js?v=… sont alignés sur v1.7.139l / v=20260516-v139l-icons-restored. Backup pré-correctifs disponible : JS/main.js.icon-restore-bak.

SUPER PRINT v1.7.139k

Released — May 16, 2026

⌨️ Saisie texte : la frappe n'écrase plus la sélection après Ctrl+A fix

Sur Cmd/Ctrl+A dans un bloc texte (notamment sur le placeholder « Your text here »), le premier caractère tapé remplaçait correctement la sélection — mais les caractères suivants effaçaient à leur tour la lettre précédente, donnant l'impression que « la sélection se réapplique entre chaque frappe ». Deux mécanismes « sticky-selectAll » (boucle requestAnimationFrame sur select du hidden textarea + chaîne setTimeout à 0/30/350 ms dans text:editing:entered) ré-appliquaient la sélection complète après que l'utilisateur ait tapé. Correctif : snapshot du texte initial au démarrage de chaque boucle, abort immédiat dès que text.length ou le contenu changent.

📐 Justify Maj+Entrée : le flag soft break survit jusqu'à insertChars fix

Suite à la livraison v1.7.139i, le saut doux ne déclenchait toujours pas le justify : la ligne avant Maj+Entrée restait courte avec un trou à droite. Cause : le flag _spNextNewlineIsSoft était posé dans onKeyDown puis immédiatement remis à false dans le finally. Or l'insertion réelle du \n ne passe pas par onKeyDown — elle passe par hiddenTextarea → événement inputinsertChars, qui s'exécute après le retour de keydown. Quand notre patch insertChars regardait le flag, il était déjà false. Correctif : suppression du reset dans finally, le flag est désormais consommé/reset à l'intérieur de insertChars après l'ajout dans __spSoftBreakIndices.

🔤 Encodage UTF-8 : réparation des fichiers double/triple-mojibake'd fix

4 fichiers texte (service-worker.js, index.html, documentation.html, CSS/main.css) étaient corrompus : apparaissait comme â€", é comme é, et la barre du commentaire d'en-tête du SW était devenue â"€ répétée des centaines de fois (triple-encodage). Visible côté utilisateur : icônes et libellés du header s'affichaient avec des caractères « € » / « $ » / « A » parasites. Cause probable : un éditeur tiers a lu les fichiers comme Latin-1 puis ré-enregistré comme UTF-8 lors d'une session précédente. Correctif : script Python _fix_mojibake.py (basé sur ftfy) qui détecte les marqueurs caractéristiques, applique fix_text itérativement (gère N niveaux d'encodage), sauvegarde l'original en .mojibake-bak avant écriture. JS/main.js (3 Mo) était sain — non touché.

🔍 Audit import / export .sp / .json / PDF

Revue complète des chaînes saveProjectSP / loadProjectSP, saveProjectLocal (.json), import depuis le modal Import et confirmExport (PDF). Tous les flux ont :

  • Purge complète des canvases / history / textLinks / charWidthsCache avant chargement (évite la fuite mémoire et les objets fantômes).
  • Validation stricte de pageFormat, margin, bleed (rejet des NaN / valeurs négatives).
  • Sérialisation correcte des soft-breaks via le toObject patché de fabric.Textbox (__spSoftBreakIndices Set → _spSoftBreakIndices Array, lazy-restauré côté load).
  • saveAllPages(force=true) dans saveProjectSP_toObject pour bypasser les guards _isRenderingAllPages / _isRestoringState / _isLoading.

Aucune régression détectée dans ces flux après les correctifs des sections précédentes.

🔢 Version bumps

Splash, header badge, JSON-LD softwareVersion, documentation manuals, service-worker CACHE_NAME et la query JS/main.js?v=… sont alignés sur v1.7.139k / v=20260516-v139k-mojibake-and-soft-break.

SUPER PRINT v1.7.139i

Released — May 16, 2026

📐 Justify : Entrée vs Maj+Entrée distingués (comportement InDesign / Word) new

Dans les modes justify, justify-left, justify-right (et justify-center), les deux types de saut de ligne sont désormais traités différemment, comme dans une PAO professionnelle :

  • Entrée (saut dur, nouveau paragraphe) → la phrase est coupée et continue sur la ligne du dessous. La ligne avant le saut n'est PAS étirée — elle garde sa largeur naturelle, comme le dernier vers d'un paragraphe.
  • Maj+Entrée (saut doux, retour forcé dans le même paragraphe) → la ligne avant le saut est étirée jusqu'à la limite du bloc texte. Si un espace traîne juste avant le saut, il est visuellement consommé (collapse à largeur 0 contre le bord) — le texte vient coller proprement au bord droit.
  • Dernière ligne du bloc → jamais étirée (fin de contenu).

Cause précédente (v1.7.139e → v1.7.139h) : enlargeSpaces traitait tout \n comme une fin de paragraphe (hard et soft confondus), parce que Fabric.js ne distingue pas les deux dans son flux text. Conséquence : le saut forcé Maj+Entrée ne fonctionnait pas comme un vrai « line break » PAO — la ligne précédente restait courte avec un trou à droite.

Correctif : la version patchée de enlargeSpaces consulte le Set __spSoftBreakIndices (positions des \n insérés via Maj+Entrée) en plus du résultat de isEndOfWrapping(i). Si la ligne i se termine par un \n dont la position est dans le Set des soft breaks → on JUSTIFIE (skipLine = false). Sinon (vrai hard \n ou dernière ligne) → on saute (skipLine = true). Les espaces traînants sur les lignes justifiées sont déjà collapsés depuis v1.7.136 (largeur 0, position au bord droit), ce qui assure le comportement « l'espace est supprimé pour que le texte colle au bord » demandé.

🔢 Version bumps

Splash, header badge, JSON-LD softwareVersion, documentation manuals, service-worker CACHE_NAME et la query JS/main.js?v=… sont alignés sur v1.7.139i / v=20260516-v139i-justify-soft-break.

SUPER PRINT v1.7.139h

Released — May 15, 2026

🪟 Export Web-to-Print : le texte qui dépasse d'un bloc est désormais correctement masqué fix

À l'export Web-to-Print (mini site HTML / images PNG), un bloc texte dont le contenu débordait sous le cadre montrait l'overflow dans l'image rendue, alors que l'éditeur le masquait correctement. Symétriquement, certains blocs voyaient leur typographie partiellement coupée à cheval sur la bordure inférieure.

Cause racine : la méthode initDimensions() de Fabric.js réécrit textbox.height = calcTextHeight() à chaque appel (le cadre se gonfle pour accueillir tout le texte). Dans l'éditeur live, un override par-instance installé par createSimpleTextBox bloquait ce comportement et restaurait la hauteur fixe du cadre. Mais cet override est perdu à la sérialisation JSON : au moment de l'export, le canvas temporaire tempFabric rappelait initDimensions() sur du Fabric stock → la hauteur grimpait à la hauteur naturelle du contenu → le clipPath calculé ensuite couvrait tout le contenu → aucun clipping visible.

Correctif : dans renderPageToImage (Web-to-Print) et renderPageToImageWithBleed (PDF / PNG / JPEG / Print-to-Web avec fond perdu), snapshot de height/width du cadre avant initDimensions(), puis restore du cadre après. Au passage on fixe aussi _fixedHeight/_fixedWidth pour les blocs legacy qui n'avaient jamais été redimensionnés. Résultat : le PNG du minisite et le PDF affichent désormais l'overflow exactement comme l'éditeur (= masqué à la dernière ligne complète qui rentre).

🔢 Version bumps

Splash, header badge, JSON-LD softwareVersion, documentation manuals, service-worker CACHE_NAME et la query JS/main.js?v=… sont alignés sur v1.7.139h / v=20260515-v139h-export-text-clip.

Released — May 15, 2026

🖱️ Texte dans une forme : double-clic = déplacement libre dans les limites de l'objet new

Quand on ajoute du texte dans une forme via le clic-droit (cercle, rectangle, polygone, tracé fermé plume, forme libre crayon, image, SVG…), le bloc texte est cliqué dans le clipPath de la forme et la paire forme↔texte se déplace désormais en bloc. Nouveau dans cette release : un double-clic sur le bloc texte le passe en mode déplacement décroché (curseur déplacement, bordure pointillée bleue) : il glisse alors librement à l'intérieur de la forme, sans entraîner cette dernière, et son centre est clampé sur la bbox de la forme — impossible de le perdre dehors. Un nouveau double-clic re-couple texte et forme. La désélection sort aussi du mode automatiquement.

L'édition typographique (police, corps, couleur, alignement…) passe désormais uniquement par le clic-droit → Éditer le texte (déjà en place depuis v1.7.132). Cela libère le double-clic pour la nouvelle interaction de positionnement intra-forme.

✏️ Éditer le texte d'objets liés — rappel des cas couverts info

  • Texte dans une forme (rect, cercle, polygone, tracé plume fermé, forme libre crayon, image, SVG) → clic-droit sur la forme OU sur le texte → Éditer le texte → entrée en édition + sélection complète + panneau typographie ouvert dans la sidebar.
  • Texte autour d'une forme → idem ; le curseur d'édition suit les caractères le long du périmètre.
  • Texte sur un tracé plume ouvert → idem ; le contour du tracé source est mis en transparent à la pose du texte (le tracé reste sélectionnable et entraîne le texte).
  • Texte sur un trait crayon (groupe Plume) → idem (pris en charge par la même branche « tracé ouvert »).
  • Texte dans / autour d'une forme libre (crayon-Formes) → idem (les paths fermés _isPencilShape passent par les actions dedans / autour).

🔢 Version bumps

Splash, header badge, JSON-LD softwareVersion, documentation manuals, service-worker CACHE_NAME et la query JS/main.js?v=… sont alignés sur v1.7.139g / v=20260515-v139g-text-in-shape-dblclick.

Released — May 15, 2026

🎯 Cursor & selection mapping rebuilt on a gap-based source-of-truth fix

Bug (reproduced in align-left & justify, with word-wrap & hyphenation): in a wrapped text block, after pressing Enter to start a new paragraph, every subsequent Shift+Enter (forced break) shifted the caret one extra pixel to the right — cumulatively. After several forced breaks the caret was no longer aligned with the first letter of the new line. In hyphenation mode the same drift occurred even without a prior hard newline. As a knock-on effect, Cmd/Ctrl+A stopped short of the real text end — the visual selection rectangle missed words on the last line.

Root cause: Fabric maps a 1D selection index to a 2D (line, column) cursor position by summing, for each visual line, line.length + missingNewlineOffset(line). When this sum exceeds the real text.length (over-count), selectionEnd = text.length resolves to a point earlier than the actual end — hence the missing words and the caret drift. Two independent over-counts were combining: (a) Fabric’s stock _generateStyleMap only skips one separator char per wrap boundary, but our patched _wrapLine can consume a multi-character whitespace token (e.g. "   ") at a wrap; (b) the previous missingNewlineOffset override mixed three sources (styleMap, isEndOfWrapping, __spMissingOffsets) which could disagree on edge cases (leading-space preserved at start of paragraph, hyphenation, soft breaks).

Fix: replaced both with a single gap-based algorithm grounded in _styleMap + _unwrappedTextLines + _textLines.length:

  • Patched _generateStyleMap: at each wrap boundary, compares the leading-whitespace count of the next visual line vs. the source, and skips the actual consumed whitespace (0 for break-word/hyphenation, 1 for normal wrap, N for multi-space wrap). Hard/soft \n handled separately as before.
  • Patched missingNewlineOffset: missingNewlineOffset(i) = absStart(i+1) - (absStart(i) + textLines[i].length) — the mathematical definition of « source chars consumed between visual line i and i+1 ». Same formula covers hard \n, soft \n (Shift+Enter), single-space wrap, multi-space wrap, hyphenation, break-word, and leading-space-preserved paragraphs uniformly.

Result: sum(line.length + missingNewlineOffset) now equals text.length exactly. The caret stays in front of the letter that wraps, no matter how many Enter / Shift+Enter combinations precede it. Cmd/Ctrl+A selects every word, including the very last one of the last line.

🔢 Version bumps

Splash, header badge, JSON-LD softwareVersion, documentation manuals, service-worker CACHE_NAME and the JS/main.js?v=… cache-bust query are all aligned to v1.7.139f / v=20260515-v139f-cursor-mapping.

SUPER PRINT v1.7.139e

Released — May 15, 2026

📏 Justify with hard and soft line breaks: line before is no longer stretched fix

Bug: in any justify variant (justify, justify-left, justify-center, justify-right), lines ending in a hard newline (Enter, new paragraph) were correctly left short (not stretched), but lines ending in a soft newline (Shift+Enter, forced break inside the same paragraph) were still being stretched to the column edge. Users were getting visibly different treatment of the two kinds of break in fluent text — not the PAO / InDesign / Word behavior they expected.

Fix: the patched enlargeSpaces() now treats both hard and soft breaks identically — any line whose source ends with a \n (regardless of origin) is a « terminated » line and is not stretched. Only auto-wrapped lines (overflow at the column edge) are justified. Same logic mirrored in the vector PDF export path (_drawTextViaOpentype), via _styleMap + __spSoftBreakIndices introspection per visual line. Editor, raster PNG/JPEG and vector PDF now behave identically.

🎚️ Justification fine controls (word spacing / glyph scale) wired to visible rendering fix

Bug: the right-sidebar Min / Opt / Max fields under « Justification fine » for word spacing, letter spacing and glyph scale were partially dead. Only letter spacing Opt reached the canvas (via Fabric’s charSpacing). word spacing Opt only affected wrap decisions internally (invisible), and glyph scale wasn’t consumed anywhere — clicking Apply changed the stored value but produced no visible result.

Fix: added two new low-level Fabric patches:

  • wordSpaceOpt → multiplies the measured width of every space-class glyph (U+0020, U+00A0, U+202F) via the patched _measureChar. 100 % = natural, 120 % = wider word spacing, 80 % = tighter. Affects wrap, line width, alignment and visible space gaps in one consistent pass.
  • glyphScaleOpt → horizontal canvas scale around _renderTextCommon. 100 % = natural, 110 % = wider glyphs, 90 % = narrower (condensed look without changing the actual font).

Both kick in immediately on Apply; Reset restores 100 % / 0 across the board. The Min / Max fields remain advisory (stored, serialized, exposed in the UI) — engaging them as range constraints per line would require a custom paragraph-shaping pass, which is outside this release.

🔢 Version bumps

Splash, header badge, JSON-LD softwareVersion, documentation manuals, service-worker CACHE_NAME and the JS/main.js?v=… cache-bust query are all aligned to v1.7.139e / v=20260515-v139e-justify-and-glyphscale.

SUPER PRINT v1.7.139

Released — May 15, 2026

🚚 v1.7.138 fixes were never delivered — cache-bust restored fix

Bug: the v1.7.138 release shipped two real fixes (placeholder-pile-up sticky-loop abort + trailing-space char-bound collapse) but the <script src="JS/main.js?v=…"> query string in index.html was still pointing at the v1.7.137 cache key. Browsers and the Service Worker therefore kept serving the old cached main.js and the bug reports kept coming. The two fixes were sitting in the file, just not loaded.

Fix: bumped the cache-bust query to v=20260515-v139-text-block-audit-leading-space and the SW CACHE_NAME to the matching v1.7.139 token. v1.7.138 fixes are now actually live alongside the v1.7.139 ones.

📐 Text block audit: leading whitespace at paragraph start was being silently dropped fix

Bug: in _wrapLine (custom wrap engine), every leading whitespace token at the start of a subline was unconditionally discarded. That mirrors Fabric's behavior at wrap boundaries (the wrap separator is consumed) but is wrong at paragraph boundaries: the very first token of a paragraph after a hard \n or a Shift+Enter soft break is real source content. Dropping it produced a 1-character desync between text and _textLines[i] per affected paragraph → cumulative cursor drift, wrong selection rectangles, and Cmd/Ctrl+A stopping short of the actual end of text.

Fix: the « leading-space drop » branch now distinguishes the very first iteration of _wrapLine for a paragraph (no resultLines yet, tokenStart === 0) and preserves that whitespace as the initial current with proper measurement. Subsequent leading-whitespace at wrap boundaries is still dropped (Fabric-compatible). Paragraphs that start with a space (typical for indented prose, dialogue, or text pasted from word processors) now render and select with no off-by-N drift.

🔍 Re-audit: justify, hyphenation, soft-breaks, missingNewlineOffset

End-to-end re-read of the textbox patch stack (6 patched __sp*Patched flags + 20 patch sites): missingNewlineOffset styleMap detection, _wrapLine tokenization with hyphenation try-fit-with-hyphen and break-word fallback, paragraph indents (_spIndentLeft/Right/_spFirstLineIndent), enlargeSpaces trailing-space exclusion + collapse, soft-break \n style inheritance, _spForceSelectAllSticky abort logic. Math-checked the source ↔ rendered char count for hard \n, soft \n, wrap, hyphenation and leading-space cases. Only the leading-space drop was a real synchronisation bug; the other paths are mathematically consistent.

🖼️ Print-to-Web (Web2Print) export: text was missing from the PNG snapshots fix

Bug: when generating the static mini-site (D4Export) and the raster PDF/PNG/JPEG with bleed, every textbox / text block came out empty in the rendered PNG. The editor and the vector PDF were fine, only the rasterised images were blank.

Cause: the v1.7.135 fix added applyTextboxClipPath() right before toDataURL in both export paths to stop overflow leaking into the image. But (a) it was called before custom fonts had finished loading in the temp canvas context, and (b) it was called without first forcing initDimensions() on each textbox — so _textLines + getHeightOfLine() returned stale / fallback-font measurements. The clip ended up snapped to a near-zero height → the visible rectangle covered no glyphs → PNG rendered the blocks as empty.

Fix: both renderPageToImage (Print-to-Web) and renderPageToImageWithBleed (raster PDF/PNG/JPEG) now await document.fonts.ready, then run _clearCache() + initDimensions() + setCoords() on every textbox / text in the temp canvas, then apply the clip and render. Texts are back in the PNGs and the clip still cleanly cuts overflow at the last fully-fitting line.

📄 PDF vector export: justify-left / justify-center / justify-right honored fix

Bug: while auditing the import / export round-trip after the new "justify" button + "right justify" Styles option were added, the vector PDF path (_drawTextViaOpentype) only matched the bare 'justify' value. Every variant (justify-left, justify-center, justify-right) silently fell through to the 'left' branch, so a textbox right-justified on screen + in raster PNG was rendered left-aligned in the vector PDF.

Fix: normalised the align switch to detect any justify family (align === 'justify' || align.indexOf('justify-') === 0). Non-final lines are stretched (justify), the last line (or any line with no spaces) gets the suffix's alignment: justify-left/justify → left, justify-center → center, justify-right → right. Same logic now applied for both xStart computation and the per-word stretch loop.

Round-trip audit (.sp / .json): SP_CUSTOM_PROPS already serializes _justSettings, _spIndentLeft / _spIndentRight / _spFirstLineIndent, _spSoftBreakIndices; toObject() persists enableHyphenation + hyphenLanguage; textAlign (incl. all justify variants) is a standard Fabric prop. No data is dropped on save / reload.

⌨️ Empty textbox → type: letters were stacking on the same position fix

Bug: select all (Ctrl/Cmd+A) in a text block, delete everything, then start typing — the second, third, fourth keystroke landed on top of the first one instead of advancing the caret. Result: A, then B overwrote it → only the last typed character remained visible at position 0.

Cause: the text:selection:changed handler kept honouring the _spCmdARequestedAt sticky flag for 500 ms after Ctrl+A. Once the user emptied + retyped, every keystroke fired this handler, saw collapsed && len > 0, and re-extended the selection over the freshly-typed character — so the next keystroke replaced it via Fabric's insertChars selection-replacement.

Fix: snapshot text.length in a new _spCmdAInitialLen property at Ctrl+A capture time. The selection-changed restorer now bails out (and clears both flags) the moment text.length differs from the snapshot — the user has typed or deleted, so we have no business reviving a long-gone selection. Same guard added in the sticky abort path for symmetry.

SUPER PRINT v1.7.138

Released — May 14, 2026

⌨️ New textbox: typing on the placeholder no longer stacks letters fix

Bug: after creating a new text block and selecting the auto placeholder text (« Your text here » / « Votre texte ici ») — typically with Cmd/Ctrl+A — the first keystroke replaced the placeholder correctly, but every subsequent keystroke also replaced the previous letter instead of being appended. End result : only the last letter typed remained visible, the rest stacked on top of each other.

Cause: the « sticky » select-all loop introduced in v1.7.x to survive Fabric’s asynchronous editing init was re-asserting the full selection on every animation frame for 2 s. After the first input, the new (single-character) text was being re-selected before the next keystroke could insert, so each new keystroke kept replacing a 1-character selection.

Fix: _spForceSelectAllSticky() now snapshots the text length / value at start, and aborts immediately the moment user input mutates it. The Ctrl+A flag is also cleared so no later setTimeout resurrects the selection. Subsequent keystrokes append normally.

✍️ Justify: cursor drift past the column edge after Enter / Shift+Enter fix

Bug: in justify mode, every classic Enter and every Shift+Enter performed on or right after a space pushed the cursor on the next line by one extra character to the right; the drift was cumulative (5 returns → 5-character offset). Additionally, Cmd/Ctrl+A on a paragraph ending in trailing whitespace + returns showed a selection rectangle that visually stopped short of (or shot past) the actual end of text.

Cause: the v1.7.137 trailing-space exclusion correctly skipped enlarging trailing spaces but still applied the cumulative accumulatedSpace to their charBound.left. The trailing chars (and the pseudo end-of-line bound at j == line.length) ended up positioned at realWidth + trailingSpaceWidth, which is what Fabric uses to compute cursor X and selection rectangles.

Fix: trailing whitespace char bounds are now collapsed visually — left = realWidth, width = 0. The pseudo end-of-line bound is also pinned to realWidth. Cursor and selection rectangles stop precisely at the column edge regardless of how many soft / hard returns precede them.

SUPER PRINT v1.7.137

Released — May 13, 2026

🧬 Sidebar text panel: regrouped style buttons

The four advanced text controls — highlight color picker, Stroke, Outline and Reset — used to live in a separate « Options avancées » group below the main format buttons. They now sit directly under top & bottom highlight, highlight and shadow in the same button row, so every text-decoration / color tool is grouped together with no extra label noise.

✍️ Justify: trailing-space exclusion + Shift+Enter cursor drift fix fix

Bug A: in justify mode (especially « justifier à droite » with hyphenation), every Shift+Enter placed on or right after a space was shifting the cursor on the new line one extra character to the right. Each subsequent forced return added another character of drift. Cause : the trailing space at the soft-break was being inflated by the justify pass (charBound.width += diffSpace), and the cumulative accumulatedSpace leaked into the cursor X computation of the next character.

Bug B: a space placed right before a wrap or a soft-break was visible as a « trou » against the right edge of the column instead of being neutralized.

Fix: the patched enlargeSpaces() now detects trailing whitespace on every line and excludes it from both the divisor (numberOfSpaces -= trailingCount) and the visible width (currentLineWidth -= trailingWidth), and skips enlarging those trailing-space char bounds. The character is still kept in text, so reorganizing the sentence (delete / type more) brings the space back between words — InDesign / Word behavior. Also strengthened soft-break detection to scan past trailing whitespace when matching __spSoftBreakIndices, so the line keeps its justify treatment regardless of whether _textLines[i] includes the trailing space or not.

SUPER PRINT v1.7.136

Released — May 13, 2026

✍️ Justify alignment is now stable on every wrapped line fix

Bug: when a textbox was set to justify, lines whose natural width was below 85 % of the column width were skipped by the justify pass and stayed left-aligned, leaving a visible gap on the right edge. This used to fire on lorem ipsum / placeholder text and on every line preceding a Shift+Enter soft break.

Fix: the « < 85 % » safety net is removed. We now trust isEndOfWrapping() (= last line of paragraph) and the existing endsAtSoftBreak flag (Shift+Enter → justify like a wrapped line). Every other wrapped line is justified to the column edge, even when a long word forced an early wrap.

🎨 Highlight color picker is live fix

Bug: the typo sidebar « Couleur surlignage » / « Highlight color » picker had no listener — changing the color did nothing until you also clicked the Highlight button (and even then it acted as a toggle, not a re-color).

Fix: input & change events on #highlightColor now re-apply the new color in place. If a selection is highlighted, only the selection is recolored. Otherwise the whole textbox textBackgroundColor is updated when one was already set. Auto-save is triggered.

🧹 Sidebar typography panel cleanup

Removed the redundant « Espaces spéciaux / Special spaces » label and the « Insère une espace typographique au curseur » hint above the NBSP / thin NBSP buttons — the same characters are already exposed by the Glyphes panel just below.

🖼️ Print-to-Web export now respects the textbox bottom edge fix

Bug: when exporting via Print-to-Web (D4Export), the generated PNG of each page kept rendering the text that overflowed below a textbox — so the minisite showed text the editor and the PDF both clip away.

Fix: renderPageToImage (Print-to-Web) and renderPageToImageWithBleed (PDF / PNG / JPEG with bleed) now run applyTextboxClipPath() on every textbox/text just before toDataURL. The helper already snaps the clip to the last fully-fitting line and skips text-on-path / text-inside-shape, so curved and shaped text are unaffected.

SUPER PRINT v1.7.135

Released — May 13, 2026

💾 Text-inside-shape now survives save / reload / .sp import / PDF export fix

Bug: textboxes created by right-click → Add text inside kept their shape clipPath at runtime, but the auto-save / manual-save serializer stripped the clipPath for every textbox / text object (a 2026-05-01 fix to avoid stale chained-text snap clips). At reload, the saved data was missing the clip and applyTextboxClipPath() is intentionally by-passed for _isShapeClippedText, so the text reverted to a plain rectangular block (the circle / polygon clip was gone).

Fix: the strip is now skipped when _isShapeClippedText is set, so the cloned shape clip is persisted and restored verbatim. Applied at both serialize sites (single-page saveAllPages and double-page saveSpreadContent). The chained-text strip behaviour is preserved for every other case.

✅ Import / export audit (.sp, .json, PDF) for the new contextual text tools

  • Custom flags (_spShapeTextPairId, _isShapeClippedText, _isCtxPathText, _simplePenData, _isPencilStroke, _isPencilShape) are all in SP_CUSTOM_PROPS → written to JSON / .sp without loss.
  • IText with path (Add text on path / around): fabric.Text.toObject() already serializes path as a sub-object and fromObject rebuilds it via fabric.Path.fromObject (Fabric 5.3) → geometry is round-tripped exactly.
  • Pair re-link: window._spInstallShapeTextLinkListeners (v1.7.132) is invoked from both loadFromJSON callbacks (single-page and spread) and re-snapshots _spLastLeft/_spLastTop on every persisted pair, so post-reload moves compute the right delta.
  • PDF export: _classifyObjectForHybrid forces every text with obj.path to raster (since v1.7.126), so curved / shape-clipped text is rendered correctly via canvas snapshot rather than going through opentype.js (which would ignore path).
  • Stroke-hidden source shape / path: stroke:'transparent' and fill:'transparent' are stock fabric properties, serialized as-is on the rect / circle / pen / pencil container, so the visual stays « text only » after reload.

SUPER PRINT v1.7.134

Released — May 13, 2026

🌐 Right-click menu now respects the UI language · ✏️ Text-on-path hides the source stroke polish

  • i18n: every label of the canvas right-click menu (Edit path, Edit text, Add text inside / around / on path, Bring to front / Forward / Backward / To back, Duplicate, Delete, plus the Del shortcut hint) is now switched between French and English based on currentLanguage. Japanese keeps the French baseline (no JP strings provided yet).
  • Add text on path (open pen path or pencil stroke): the source path's stroke and fill are now stripped to transparent, so only the text is visible — mirrors the behaviour already in place for Add text around on closed shapes. The path stays selectable / movable in the background and still drags the text via the shape↔text pair link.
  • Editable text on a pen / pencil path: thanks to the v1.7.133 « Edit text » item, a 2nd right-click on a pen-drawn line that already carries text reveals « Edit text » (« Éditer le texte » in FR), which selects the IText, enters edit mode and selects every character — the right sidebar typography panel takes over for font, size, color and tracking. Same applies to text inside / around freeform (pencil) shapes.

SUPER PRINT v1.7.133

Released — May 13, 2026

📝 Edit text on / inside / around a shape from the right-click menu new

  • New context-menu item « Éditer le texte »: shown on a 2nd right-click on a shape that already carries a text (text-inside, text-around, text-on-path) and on text blocks themselves. Clicking it selects the linked text, enters edit mode and selects all characters — the right sidebar's typography panel takes over so font, size, color and tracking can be changed live.
  • Text-around (IText on path): the cursor and character selection now track the glyphs along the perimeter (sidebar typography editing applies to every selected character).
  • « Add text inside / around »: hidden when the shape already owns a text pair, so a 2nd right-click no longer creates a duplicated overlapping text block.
  • Round-trip: _spShapeTextPairId, _isShapeClippedText and _isCtxPathText were already in SP_CUSTOM_PROPS, so auto-save, manual save, .sp import and PDF/PNG export all preserve the linked-text behaviour and the editing entry-point survives reloads.

SUPER PRINT v1.7.132

Released — May 13, 2026

📝 Write-around: text now lands on the shape, and survives reload fix

  • Position: with v1.7.131 the IText was created with default left/top = 0 while its path held absolute coordinates — fabric internally translates glyphs by (path.left - text.left, path.top - text.top), so the text appeared offset by (path.left, path.top) from where the shape actually was (typically projected to the top-left of the page). Fix: align the text's left/top on the path's, so the translation collapses to zero and glyphs render exactly on the shape outline.
  • Save / load: the canvas-level listeners that mirror movement and deletion between shape and text were only installed when the user created a pair via right-click. After a full page reload (or after a saved .sp document was reopened), existing pairs deserialized correctly but were no longer linked. Fix: the listener installer is now exposed as window._spInstallShapeTextLinkListeners and called from both loadFromJSON callbacks (page canvas and spread canvas), with a snapshot reset on every persisted pair so the first post-reload move computes the correct delta.
  • Same fix applied to Add text on path (the Dessus command had the same offset bug).

SUPER PRINT v1.7.131

Released — May 13, 2026

📝 Write-around: text now sits exactly on the shape outline refine

Change: Add text around no longer wraps the text on a halo offset outside the shape. The text now lays out directly on the perimeter of the source shape, and the source shape's fill and stroke are stripped (set to transparent) so only the text is visible.

The shape stays selectable and movable in the background — thanks to the _spShapeTextPairId link from v1.7.129, moving the (now invisible) shape still drags the text with it, and deleting either removes both. Result: a single editorial unit where the rectangle / triangle / circle outline becomes the text baseline.

SUPER PRINT v1.7.130

Released — May 13, 2026

📝 Write-around now follows the actual shape outline fix

Bug: Add text around always wrapped the text on an ellipse approximating the bounding box, even when the source shape was a rectangle, triangle or polygon. Right angles became curves and the text floated visibly off the corners.

Fix: the path used by the wrapped text now follows the real perimeter of the shape:

  • Rectangle → 4 straight segments offset outward, sharp 90° corners (rotation supported).
  • Triangle → 3 segments offset outward, sharp corners.
  • Polygon / polyline → the actual vertex outline, offset outward.
  • Circle / ellipse → ellipse perimeter (unchanged).

Implementation: convex polygon offset via per-edge perpendicular shift + adjacent edge intersection (handles any orientation, including rotated rectangles).

SUPER PRINT v1.7.129

Released — May 13, 2026

📝 Write-on-shape (right-click) is now fully usable fix

Bugs fixed:

  • Editable text: Around / On path previously created a non-editable fabric.Text; users could not change the placeholder. Now uses fabric.IText — double-click to edit.
  • Visible path artifact: the helper geometry used to lay out path-text was sometimes drawn (faint X / extra strokes inside the shape). Path is now fully transparent, non-evented, non-selectable and excluded from PDF/PNG export.
  • Shape ↔ text linked as one object (the missing piece): the source shape and the generated text now share a _spShapeTextPairId. Move one → the other follows. Delete one → the other goes too. The pair behaves as a single editorial unit (closer to InDesign's text-frame model).

Applies to all three commands: Ajouter du texte dedans, autour, dessus.

Released — May 13, 2026

🔤 Custom font: select-all apply now sticks through Shift+Enter fix

Bug: with a custom-imported typeface (e.g. Lekton-regular) applied via Select All → font picker on a justified textbox, pressing Shift+Enter caused the next line to revert to the previous block font (Open Sans) after a few characters.

Fix: when the selection covers the entire text, the new font is now promoted to the block level (and per-character font overrides are stripped), so the loaded typeface becomes the single source of truth. In addition, insertChars now propagates the neighbour character's per-char style to the inserted \n, so soft line breaks never lose typography information across line splits.

✒️ Pen tool: Enter no longer auto-closes the path fix

Bug: pressing Enter to finish a pen drawing automatically closed the path and filled it, even when the user just wanted a stroked open curve.

Fix: Enter now finalizes the path as open (stroke only, no fill). To close a path, click the first anchor explicitly (the existing close-on-first-anchor gesture is unchanged). In edit mode, Enter still preserves the existing open/closed state of the edited path.

🔤 Custom font import: multi-file selection new

  • What's new. The Load custom font dialog now accepts multiple files at once (Shift / Ctrl click in the OS file picker). When several files are picked, each font is named from its own filename (no global name prompt) and registered sequentially.
  • Why. Loading a family with 4–8 weights/styles used to require 4–8 round trips through the dialog. Now a single pick.

📐 Text stability after font import fix

  • Symptom. After loading a custom typeface, applying it to an existing block, then reformatting (justify + syllable hyphenation, line break with Shift+Enter), a portion of the text changed visually — looked like a different font for the lines laid out before the font was ready.
  • Root cause. The textbox had been measured with the fallback font (Times) before the FontFace.load() promise resolved. Cached __charBounds / __lineWidths / _styleMap stayed stale until the next manual edit.
  • Fix. A new helper _spRefreshTextboxesAfterFontLoad() is now called after document.fonts.ready at the end of every custom-font import. It walks every page canvas, resets the textbox metric caches, re-runs initDimensions() while preserving _fixedWidth / _fixedHeight, re-applies shape clip-paths, then requests a render.

📐 Justify + word ⇄ syllable toggle: no more gaps fix

  • Symptom. In a justified textbox, switching the hyphenation mode between word wrap and syllable left wide gaps in the typography — lines didn't expand fully to the textbox edge as they should in justify.
  • Root cause. The previous mode had run enlargeSpaces() and written stretched widths into Fabric's __charBounds cache. The mode-change handler cleared _styleMap and __lineWidths but not __charBounds nor __lineOffsets, so the next enlargeSpaces() pass read the old enlarged values as a starting point.
  • Fix. Both applyHyphenation() and the hyphenLanguage change handler now also clear __charBounds and __lineOffsets, set _forceClearCache, and force a fresh measure of every line width before the next render.

↵ Shift+Enter is a real soft line break (InDesign-style) fix

  • Symptom. In a justified textbox with syllable hyphenation, pressing Shift+Enter to force a line break left the broken line short of the textbox edge (justification was lost) and the typography appeared to shift around the break.
  • Root cause. Fabric.js maps Enter and Shift+Enter to the same insertNewline, both inserting a hard \n. Our patched enlargeSpaces() then treats the line just before that \n as last line of paragraph via isEndOfWrapping() and skips justification.
  • Fix. Shift+Enter is now intercepted at fabric.IText.prototype.onKeyDown and the absolute grapheme position of the inserted newline is recorded in a per-textbox __spSoftBreakIndices Set. insertChars() and removeChars() are also patched to keep these indices in sync through edits. enlargeSpaces() consults the Set: lines that end at a soft break are justified to the textbox edge like normal wrapped lines. The Set is serialized as _spSoftBreakIndices in .sp / .json exports for round-trip persistence.

🔤 Custom font: no more partial reverts to the previous font fix

  • Symptom. After loading a new typeface and applying it to a textbox, then changing format / justify / line height / pressing Shift+Enter, parts of the text reverted visually to the previous (or fallback Times) font — typically the lines or characters that already carried per-character style overrides from a paste, a template, or a prior partial selection.
  • Root cause. The whole-block font picker called obj.set({ fontFamily, fontWeight }) but never cleaned the per-character obj.styles[line][char].fontFamily / fontWeight overrides. Those overrides took precedence over the block value at every subsequent re-measure, and any cache invalidation (justify toggle, hyphenation mode change, soft line break) made them visible again.
  • Fix. A new helper _spStripPerCharFontOverrides(textbox) walks obj.styles and deletes per-char fontFamily / fontWeight / fontStyle keys (cleaning up empty entries afterwards). It is called right after the whole-block font apply, so the new face is now the single source of truth across the whole textbox. Per-selection font changes still work as before — they only target the selected range.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS · Service Worker superprint-shell-v1.7.127-font-import-justify-stability

→ Open SUPER PRINT


SUPER PRINT v1.7.126

Released — May 13, 2026

📝 Right-click Add text: real shape-aware behavior rework

  • Why a rework. The first iteration (v1.7.122) just spawned a horizontal textbox at the bounding box of the shape — no clipping, no curve following. Visual result didn't match what users expected from a print-design app.
  • Add text inside. Now creates a centered fabric.Textbox with a clipPath built by cloning the source shape (circle, ellipse, rect, polygon, path), so the text is visually contained by the shape's outline. Round shapes (circle/ellipse) get a tighter width (78 % of bbox) so lines fit better inside the curve. Font size auto-tuned from the bbox height.
  • Add text around. Creates a fabric.Text bound to an elliptical path that encloses the shape's bounding box (offset outward by ~½ font size). Result: real text-on-curve following the perimeter, clockwise, readable from the top.
  • Add text on a path. Creates a fabric.Text whose path is a clone of the source pen/pencil-stroke geometry — converted to absolute canvas coordinates via obj.calcTransformMatrix() × T(-pathOffset) so the text follows the exact source curve, regardless of source position/rotation/scale.
  • Round-trip safe. Two new flags _isShapeClippedText and _isCtxPathText are added to SP_CUSTOM_PROPS so they survive .sp/.json save-and-reload. The internal applyTextboxClipPath() guard now bails out for both, preventing it from overwriting the shape clipPath with a rectangle on every modification cycle (latent bug that would have silently broken the feature on the first re-render).
  • PDF export safety. Text-on-path objects (obj.path set) are now classified as raster in the HD hybrid pipeline (and skipped by _drawTextViaOpentype), because the opentype.js renderer cannot follow a path and would output flat horizontal text at the wrong position. Raster fallback at 300 dpi keeps print quality.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS · Service Worker superprint-shell-v1.7.126-ctxmenu-text-rework

→ Open SUPER PRINT


SUPER PRINT v1.7.122

Released — May 12, 2026

📝 Right-click on any object: add text inside, around or on top new

  • What's new. The desktop right-click menu (and mobile long-press menu) now offers context-aware text actions depending on the object you clicked:
    • Open paths (pen tool, pencil-stroke from the Pen group) → Add text on top. A textbox is created centered over the path's bounding box.
    • Any other visual object (rectangle, circle, image, star, free-form pencil shape from the Shapes group, imported SVG…) → Add text inside + Add text around. The inside action drops a centered textbox sized to the bounding box minus a 6 % padding; the around action drops a left-aligned textbox just below the object with a 6 px gap.
  • Object discrimination. Two new internal flags differentiate the three drawing tools that all output a fabric.Path: _isPencilStroke on free-stroke pencil output (Pen group, editable as a Bézier path), and _isPencilShape on free-form filled shape (Shapes group). Both are added to the SP_CUSTOM_PROPS allowlist for round-trip persistence in .sp and .json exports. _simplePenData itself was also explicitly added to the allowlist (it was previously persisted only via a toObject override that didn't survive a reload — latent bug fixed).
  • New textboxes. Created via a small helper that produces a standard fabric.Textbox with the same _fixedHeight/_fixedWidth protection as native blocks (consistent with copy-paste behavior). Three new SVG icons inline in the menu (text-inside, text-around, text-on).

✏️ Distinct icons for the two pencil tools UX

  • Symptom. The pencil under the Pen group (free Bézier-editable stroke) and the free-form pencil under the Shapes group (filled closed shape) shared the exact same icon — confusing because they produce very different objects.
  • Fix. A new icons/freeform-pen-shape.svg draws a wider and shorter pencil silhouette for the Shapes-group entry. The Pen-group pencil keeps the original taller/sharper icon. Visually telling them apart at a glance.

📱 Mobile: "Select all" in a textbox now shows the selection band fix

  • Symptom. Mobile only — inside an editing textbox, choosing Select all (either from SuperPrint's long-press menu or from the OS native context menu) left no visible blue selection band, even though the selection was technically active.
  • Root cause. Fabric.js IText.selectAll() only updates selectionStart/selectionEnd + fires the change event; it does not draw the selection rectangle. On desktop the next mouseup canvas triggers a full render that paints it. On mobile, the tap that closes the menu has no equivalent, and the cursor's _tick animation often clears the upper-canvas right after the initial render — selection band gone before the user sees it.
  • Fix. Both code paths (custom mobile menu and native OS hiddenTextarea 'select' listener) now: force a higher-opacity selectionColor (rgba(13,153,255,0.45)) for better mobile visibility, call abortCursorAnimation() to prevent the cursor tick from clearing the contextTop, request a full render, then explicitly call renderCursorOrSelection() over multiple frames (RAF, RAF×2, +120 ms, +320 ms) to survive panel repaints and keyboard show/hide events.

🖨️ Print-to-Web export now produces a viewable mini-site fix critical

  • Symptom. The Print-to-Web export ran the spinner but never produced the ZIP. No error in the UI.
  • Root cause. The HTML viewer template inlined a ${googleFonts} placeholder that no longer existed in the surrounding scope — a silent ReferenceError swallowed by _spGuardExport. The template literal evaluation crashed before the ZIP could be built.
  • Fix. Removed the dangling <link> tag (the bundled CSS already includes the matching @font-face declarations, so no font is lost). Export now reliably produces the ZIP.

📑 Duplicate page: source page and copy stay perfectly identical fix

  • Symptom. Duplicating a page from the pageboard subtly modified the source: images on it shrank slightly. Repeated duplications accumulated the drift.
  • Root cause. Inside createPageCanvas and loadSpreadContent, fabric.Image.fromObject recomputes width/height from the cached underlying <img> during loadFromJSON, ignoring the JSON-stored dimensions. Combined with stored scaleX/scaleY, this produced a per-cycle visual size shift.
  • Fix. Both load paths now snapshot every image's {width, height, scaleX, scaleY} from the JSON before loadFromJSON, then re-apply them via set() after the callback when they differ by > 0.0001. The original page is no longer mutated by the duplication; the copy is a pixel-perfect mirror.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS · Service Worker superprint-shell-v1.7.122-ctxmenu-text

→ Open SUPER PRINT


SUPER PRINT v1.7.121

Released — May 11, 2026

🖨️ Imposition + spread + multi-page assets: left pages finally visible fix critical

  • User-facing symptom. In spread mode, after dropping a multi-page asset (e.g. Music Magazine 8p) and running Calculate Imposition, the left pages of every imposed sheet only displayed the background — texts and images were missing. Right pages were correct. Only sheet n°1 (cover-4 | cover-1, with no mate spread) came out correctly.
  • Root cause. saveSpreadContent legitimately duplicates full-page objects that span the spread gutter (typically the background) into both pages with an _isOverflowFromLeft / _isOverflowFromRight flag — necessary for visual continuity in the spread view. But during imposition, buildImposedSheetCanvas loads pages sequentially into sheetCanvas and these overflows arrive last in the z-order. Concretely: the last object drawn on each sheet (page L | page R) is the LEFT-bg overflow of page R, which — after offsetX is applied — covers almost the entire left slot (x = 25..462 on 0..437), masking the page L content under its own background.
  • Fix. Added the _isOverflowFromLeft || _isOverflowFromRight filter to the exclusion lists of the three per-page load paths: loadOnePage in buildImposedSheetCanvas (main fix), renderPageToImageWithBleed (PDF export with bleed), and renderPageToImage (per-page image export). Overflows are spread-edition artifacts and have no business being re-injected into per-page exports. The spread render path (renderSpreadToImage) already handles these flags via its own dedup and stays unchanged.
  • Full audit. All .sp / .json / PDF (RGB & CMYK) import/export paths have been audited: no side effects. Overflow flags are kept in the SP_CUSTOM_PROPS allowlist for edit-session continuity.

✒️ Pen tool: double-click = image, right-click = edit path UX

  • User request. A pen-drawn shape should behave like a rectangle or a circle on double-click (image insertion). Path editing, until then triggered by double-click, should move into the context menu.
  • Behavior in v1.7.121.
    • Double-click on a pen shape → opens image import (openImageMaskDialog), exactly like a rectangle or a circle. If an image is already present, toggles the mask edit mode (pan + zoom).
    • Right-click on a pen shape → context menu with a new "Edit path" item in first position (pen icon). This item re-activates simplePenTool on the path to manipulate Bézier anchors and handles.
  • Consistency. The right-click menu stays identical for other object types (Bring to front / Forward / Backward / Send to back / Duplicate / Delete). The pen item only appears if the object carries _simplePenData.

🖼️ Auto-strip stroke when inserting an image into a shape UX

  • User-facing symptom. When placing an image inside a pen shape (which has a black stroke by default), the stroke remained visible and visually overlapped the image.
  • Fix. applyImageMaskToShape now automatically removes the stroke (stroke = null, strokeWidth = 0) when an image is inserted, while memorizing the original values in _originalStroke / _originalStrokeWidth. The user can re-add a stroke at any time via the stroke controls. When the image is removed (removeImageMask), the original stroke is restored.
  • Persistence. The new properties _originalStroke and _originalStrokeWidth are included in SP_CUSTOM_PROPS for proper serialization in .sp and .json files.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


ZORD v0.0.6

Released — May 8, 2026

🔁 Import / export — audit complet et corrections fix quality

  • .zord natif synchronisé. L'en-tête d'un fichier .zord reflète désormais la vraie version de l'application : _zord.version et _zord.generator ne sont plus codés en dur (1.0.0 / v0.0.1) mais lus depuis la constante unique ZORD_APP_VERSION. Le validateur d'import accepte aussi tout en-tête commençant par ZORD, garantissant la rétro-compatibilité avec les futures variantes du format.
  • Export DOCX — tailles en points correctes. Le convertisseur traitait les valeurs "13pt" et "13px" de la même façon (multiplication par 2 pour obtenir les half-points Word), ce qui surdimensionnait les anciens documents stockés en pixels. Une fonction sizeStringToPt() normalise désormais pt, px (×0.75), em/rem (×12) et l'unité implicite avant conversion en half-points.
  • Export DOCX — interlignage personnalisé exporté. L'attribut lineheight (Parchment block) est désormais transcrit en spacing.line Word (vingtièmes de point, LineRuleType.EXACT), ce qui préserve les interlignages saisis par l'utilisateur via le double-clic Custom….
  • Export DOCX — listes ordonnées, exposants/indices. Une configuration numbering (zord-ordered, 4 niveaux : décimal → lettre → romain → décimal) est injectée dans chaque document Word, et les attributs script: 'super' / 'sub' de Quill sont mappés vers superScript / subScript.
  • Export DOCX — sauts de page propres. Plus de paragraphe vide intercalaire entre deux pages : on utilise pageBreakBefore: true sur le premier paragraphe de chaque page secondaire (au lieu d'insérer un PageBreak isolé).
  • JSON — export non destructif. buildExportData() clone désormais le delta Quill (JSON.parse(JSON.stringify(...))) avant de retirer les attributs transitoires selection-highlight. L'éditeur live ne perd plus jamais sa surbrillance de sélection à cause d'un export en arrière-plan.
  • Service Worker bump. Cache renommé zord-v13-0.0.6-import-export-audit pour forcer la récupération des nouveaux app.js, index.html et index_FR.html sur tous les appareils déjà installés.

✏️ Typographie personnalisée — taille & interlignage en pt libres new

  • Pickers Custom… dans la toolbar. Sur les sélecteurs Taille et Interlignage, un nouvel élément Custom… / Personnaliser… ouvre un prompt qui accepte une valeur libre entre 0.1 et 999 pt et l'applique à la sélection en cours. Les whitelists Quill (SizeStyle, LineHeightStyle) sont désactivées (= null) pour autoriser n'importe quelle valeur arbitraire.
  • Mobile. Sur écran tactile, un appui long (550 ms) sur l'étiquette du picker déclenche le même prompt — pas besoin de double-clic.
  • Bilingue. Tous les libellés, tooltips et messages d'erreur sont disponibles en FR et EN (détection via <html lang>).

🖼️ Drag & drop d'images depuis le bureau new

  • Formats acceptés. .jpg / .jpeg, .png, .webp, .gif, .svg, .ico, .avif, .bmp, .tif / .tiff, .eps. L'image est lue via FileReader.readAsDataURL() puis insérée à la position du curseur dans le Quill actif (même comportement que le drop d'un .json / .zord / .docx).
  • Overlay de drop mis à jour. Liste des extensions affichée en clair, et message d'alerte de fallback enrichi pour les fichiers non reconnus.
  • TIFF / EPS. Insérés tels quels (data URL) avec un console.warn indiquant que certains navigateurs ne les rendent pas nativement — l'export PDF/Word reste correct.

� Poignées de redimensionnement d'images new

  • Filet bleu + 8 poignées. Un clic sur n'importe quelle image dans le Quill actif affiche un fin contour bleu (1 px) et 8 petites poignées carrées (4 coins + 4 milieux de côté). Glisser une poignée d'angle conserve par défaut le ratio (maintenir Shift pour le briser) ; les poignées latérales redimensionnent sur un seul axe.
  • Tag dimensions. Une étiquette bleue affiche en temps réel la taille en pixels (L × H) sous le coin bas-droit pendant le drag.
  • Persistance & historique. Au relâchement, l'attribut width de l'image est commité via q.update('user') pour que l'autosave et l'undo Quill capturent le changement. Suppr / Backspace sur une image sélectionnée la supprime via Quill (annulable). Échap ou clic ailleurs ferme la sélection.

🎨 Pop-in design pour la typo personnalisée UX

  • Adieu window.prompt. Le double-clic (ou appui long mobile) sur un picker Taille ou Interlignage ouvre désormais une vraie modale design : titre clair, champ type="text" inputmode="decimal" avec suffixe pt intégré, hint inline (« Entre 0,1 et 999 pt — ex. 13,5 »), boutons Annuler / Appliquer, fermeture par Échap ou clic backdrop, validation Entrée.
  • Validation visuelle. Une valeur invalide passe le champ en rouge avec message d'erreur aria-live, sans plus jamais clôner d'alert() bloquant.
  • Theme-aware. Variantes html.dark intégrées (fond #0a0a0a, bouton primaire blanc) alignées sur le reste de l'UI ZORD. FR + EN détectés via <html lang>.

📥 Drop overlay revu (style VIZION) UX

  • Plus d'overlay noir agressif. Le drag d'un fichier sur la fenêtre affiche désormais une teinte très subtile (rgba(17,24,39,0.08)) avec contour pointillé fin (2 px) et coins arrondis 14 px, comme dans VIZION.
  • Badge icône circulaire. Pastille blanche Ø 96 px avec icône SVG flèche-vers-le-haut, ombre douce, et anneau spinner prêt à être activé (.loading) pour un feedback de traitement futur.
  • Typographie corporate. Texte Déposez votre fichier / Drop your file en uppercase letterspacé, liste d'extensions acceptées en libellé secondaire normalement casé.
  • Dark mode natif. Variantes html.dark avec wash blanc léger, badge blanc, texte clair, icône foncée sur badge clair (lisible même sur photo plein écran).

✏️ Pickers typo — listes raccourcies UX

  • Moitié moins d'options par défaut. Maintenant que Custom… couvre toutes les valeurs entre 0,1 et 999 pt, les pickers ont été dégraissés : Taille passe de 17 valeurs (8–72 pt) à 8 valeurs curées (8, 10, 12, 13, 16, 24, 48, 72 pt) ; Interlignage passe de 15 à 8 (10, 12, 14, 16, 18, 20, 28, 36 pt). Résultat : dropdown plus court, scan visuel immédiat, et tout reste accessible via le double-clic / appui-long.

�️ Export PDF — audit post-resize d'images fix

  • Plus de chrome bleu dans le PDF. Si l'utilisateur lançait l'impression alors qu'une image était sélectionnée (filet bleu + 8 poignées + tag dimensions), tout cela se retrouvait sur le PDF exporté. Désormais : (a) une règle @media print masque .zord-img-resize-overlay et neutralise le outline sur .zord-img-resize-selected ; (b) un listener beforeprint appelle clearSelection() juste avant que le navigateur capture la page — ceinture et bretelles.
  • Ratio d'aspect garanti même quand la page A4 force un shrink. Le module de redimensionnement ne pose plus que la dimension réellement contrôlée par l'utilisateur : poignée d'angle avec ratio = style.width uniquement (la hauteur reste implicite → ratio intrinsèque préservé par le navigateur), poignées latérales E/W = style.width uniquement, poignées N/S = style.height uniquement, Shift+coin (free-form) = les deux. Conséquence : pour les cas avec ratio, la règle CSS .ql-editor img { max-width: 100%; height: auto } peut maintenant recalculer une hauteur correcte si l'image est trop large pour la zone imprimable A4 (210 mm – marges ≈ 643 px à 96 dpi).
  • Attribut width HTML dropé. L'ancienne version posait à la fois img width="X" ET style.width, ce qui pouvait entrer en conflit avec max-width:100% au moment du print. On ne garde plus que les inline styles.
  • Comportement Shift+coin véritablement free-form. Avant, la branche « break ratio » calculait bien w et h indépendamment… mais n'écrivait que la largeur. Résultat : Shift ne déformait jamais l'image. Corrigé : les deux dimensions sont écrites dans ce mode.

📝 Details

Quill 1.3.6 · docx.js · mammoth.js (DOCX import) · JSZip + Pako (ODT) · Service Worker zord-v17-0.0.6-pdf-img-resize-audit · softwareVersion 0.0.6 dans JSON-LD, splash et popin de don · llms.txt / humans.txt alignés.

→ Open ZORD


SUPER PRINT v1.7.110

Released — May 8, 2026

📋 Copier/coller : l'original n'est plus jamais modifié fix

  • Symptôme utilisateur. Lors d'un copier/coller (image, objet ou typo), l'objet source était légèrement modifié — déplacement de quelques pixels et réduction du format. C'était visible surtout en répétant Ctrl+C / Ctrl+V plusieurs fois sur la même image : le drift s'accumulait.
  • Cause racine. Le cycle Fabric discardActiveObject() → reconstruction d'ActiveSelection introduit un micro-drift d'arrondi sur left/top/scaleX/scaleY des enfants (recalculés relatifs au centre de la sélection). Idem au paste : discardActiveObject() + setActiveObject(clonedObj) peuvent muter par effet de bord les coords de la sélection précédente (= le source).
  • Fix défensif bulletproof. Helper _spSnapshotXform(obj) qui capture {left, top, scaleX, scaleY, angle, width, height, skewX, skewY, originX, originY, flipX, flipY}, et _spRestoreSourceXforms(snaps, canvas) qui restaure UNIQUEMENT si une valeur a drifté (tolérance 0.0001 px). Appliqué aux 4 chemins :
    1. Ctrl+C single : snapshot avant obj.clone(), restore dans le callback.
    2. Ctrl+C multi : snapshot des enfants avant discardActiveObject(), restore après reconstruction de la sélection.
    3. Ctrl+V single : snapshot du source (objet actif) avant paste, restore après ajout du clone.
    4. Ctrl+V multi : idem snapshot/restore du source.
  • Zéro régression. Si rien n'a drifté (cas nominal), le restore est un no-op total. La fonction _spRestoreSourceXforms ne touche jamais une propriété qui correspond déjà au snapshot. Pas d'effet sur la performance ni sur les autres comportements.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.109

Released — May 8, 2026

🚨 Réorganisation chemin de fer mode spread : pertes d'objets éliminées critical fix

  • Symptôme utilisateur. En mode double page, réorganiser les pages dans le chemin de fer (drag-drop, ajout, suppression) faisait perdre des images, des textes, et provoquait des duplications non contrôlées de texte.
  • Cause racine identifiée. Dans renderAllPages(), le guard _isRenderingAllPages = true était posé après la boucle deepCleanupCanvas(c). Conséquence : pendant la destruction de chaque canvas spread, chaque fabricCanvas.remove(obj) déclenche le listener object:removed qui appelle saveSpreadContent(fabricCanvas, leftIndex, rightIndex) directement (en court-circuit de saveAllPages, donc en court-circuit du guard). À chaque itération : 1 objet en moins sur le canvas → 1 objet en moins réécrit dans pages[leftIndex] et pages[rightIndex]. Le set d'objets rétrécit jusqu'à quasi-vidage. Quand renderAllPages reconstruit la grille, il lit ces pages quasi-vides → perte massive de contenu.
  • Triple fix défensif.
    1. renderAllPages() : _isRenderingAllPages = true est désormais posé avant la boucle deepCleanupCanvas.
    2. deepCleanupCanvas() : marque fabricCanvas._spDisposing = true avant toute suppression d'objet, comme signal explicite de teardown.
    3. saveSpreadContent() : 4 guards en tête de fonction — bail-out immédiat si _spDisposing, _isRenderingAllPages, _isRestoringState, ou _isLoading. Plus aucune écriture intempestive de pages[] pendant les phases sensibles.
  • Complémentaire. Cumulé avec _spStripOverflowDuplicatesAfterReorg() (v1.7.108) qui purge les duplicats _isOverflowFromLeft/Right stale après mutation de pages[], la réorganisation chemin de fer en mode spread est désormais robuste : drag-drop, ajout, suppression, déplacement multiple successifs.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.108

Released — May 8, 2026

📖 Chemin de fer + import PDF spread : stabilité totale fix

  • Symptômes utilisateur. Après import PDF en mode double page puis réorganisation des pages dans le chemin de fer (ajout de pages blanches, déplacement) : image PDF affichée à la mauvaise place, pages droites “vidées”, filets verticaux noirs/roses persistants à la place des marges et du plan de travail.
  • Cause racine #1 — duplicats overflow stale. saveSpreadContent stocke des copies d'objets chevauchant la reliure (flagées _isOverflowFromLeft / _isOverflowFromRight) sur la page voisine du primaire. Toute insertion/déplacement/suppression d'1 page bascule la parité → ces duplicats deviennent obsolètes et réapparaissent au mauvais endroit. Helper _spStripOverflowDuplicatesAfterReorg() ajouté et appelé après chaque mutation de pages[] (handleDrop, drop “en fin”, deletePageFromChemin, addPageFromChemin('simple')). Les originaux non-flaggés sont préservés ; les duplicats seront régénérés par le prochain saveSpreadContent selon le NOUVEAU pairage.
  • Cause racine #2 — guides non recréés. addSpreadGuides() court-circuitait la recréation si dimensions identiques, sans tenir compte du pairage de pages. Ajout d'un check samePairing (mémorisation de _guidesLeftIdx / _guidesRightIdx) → plus aucun trait fantôme du précédent spread.
  • Robustesse drag-drop. Tous les handlers du chemin de fer (handleDrop, addPageFromChemin, deletePageFromChemin, duplicatePageFromChemin) ont désormais le même retry _isLoading (40×50ms) que la duplication — plus aucune mutation de pages[] sur un canvas encore en cours de loadFromJSON après import PDF.

🔄 Curseurs de poignées typo qui suivent la rotation fix

  • Demande utilisateur. À 90° / -90°, gauche/droite doit devenir haut/bas (et réciproquement) pour les flèches/curseurs des poignées.
  • Fix. Les 8 poignées custom des Textbox utilisent désormais un cursorStyleHandler (au lieu d'un cursorStyle statique) qui calcule le bon curseur selon l'angle effectif (cycle ew → nwse → ns → nesw tous les 45°, avec offset selon l'axe d'origine). Tient compte de l'angle cumulé si l'objet est dans un activeSelection/group.

🛡️ Robustesse import/export & undo/redo fix

  • _spClone fallback robuste. Sur navigateurs sans structuredClone (Safari < 15.4), le fallback JSON.parse(JSON.stringify(obj)) crashait sur toute référence circulaire — cassait silencieusement tous les undo/redo. Désormais : try/catch + shallow copy de secours + log diagnostic.
  • FileReader.onerror par défaut. ~20 sites créaient un FileReader sans onerror → fichier corrompu / disque illisible / permission refusée = silence total, UI semble figée. Shim global readAsXxx() installe un onerror par défaut uniquement si absent → zéro changement de comportement pour les chemins existants, juste un console.warn diagnosable.

🌐 i18n

  • Clé alertCanvasLoading ajoutée en FR / EN / JA pour tout message « patientez : un chargement est en cours ».

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.107

Released — May 8, 2026

🔄 Inversion du sens de rotation visuelle des poignées fix

  • Demande utilisateur. Après validation que l'action des poignées suit bien la rotation (v1.7.104, repere local), un détail visuel restait : les bars/coins tournaient dans le même sens que l'objet, ce qui inversait la lecture intuitive haut↔bas et gauche↔droite par rapport à la position sur l'écran.
  • Fix appliqué. Dans __spWrapControlRender, la rotation du contexte canvas avant render() est désormais appliquée par -angle au lieu de +angle. À 90° / 180° / 270° cela permute visuellement haut↔bas et gauche↔droite des poignées ; à 0° rien ne change. L'action en repère local reste inchangée (les handlers actionHandlerML/MR/MT/MB et createCornerHandler sont calculés avec _spLocalAxes et setPositionByOrigin).

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.106

Released — May 8, 2026

✍️ Tracking per-char : espace VRAIMENT entre les lettres fix

  • Symptôme corrigé. Avec le tracking appliqué sur une sélection à l'intérieur d'un bloc texte, l'espace n'apparaissait pas entre les lettres mais cumulait à la fin du mot sélectionné — ex. : "hello" → rendu "helloXXXXX" (5 deltas concaténés en un seul gap après la dernière lettre).
  • Cause racine. Le rendu Fabric (_renderChars) batch les caractères consécutifs partageant le même style en un seul appel fillText(d, l, n)d = chars concaténés. Le critère de batch est _hasStyleChanged() qui compare fill / stroke / fontSize / fontFamily / fontWeight / fontStyle / deltaY mais pas charSpacing. Conséquence : tous les chars sélectionnés (qui partagent le même charSpacing per-char) étaient rendus en UN seul fillText sans espacement inter-lettre, et seule la position de fin de batch était avancée par la somme des deltas → le gap apparaissait après le mot.
  • Fix appliqué. Patch de fabric.Text.prototype._hasStyleChanged pour casser le batch dès que charSpacing diffère entre deux chars consécutifs OU diffère de obj.charSpacing (ce dernier cas force un flush par char, identique au comportement natif quand this.charSpacing !== 0). Résultat : chaque caractère trackté est rendu individuellement à sa position calculée dans __charBounds (qui inclut déjà le delta grâce au patch _measureChar v1.7.103) → espacement vraiment inter-lettre.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.105

Released — May 8, 2026

📄 Audit import / export après patch tracking + rotation handles fix

  • .sp / .json (round-trip). Audité OK : charSpacing est dans fabric.Text.prototype._styleProperties (patch v1.7.103) et 'styles' est inclus dans tous les propsToInclude (clone, transfer, save). Le tracking par-caractère est bien préservé à la sauvegarde et restauré au chargement — le patch _measureChar recalcule les advances après loadFromJSON.
  • .pdf raster. OK : le rendu canvas utilise _measureChar patché → __charBounds exact → raster reproduit fidèlement le tracking per-char.
  • .pdf vectoriel (HD). Régression détectée + corrigée : _drawTextViaOpentype vérifiait fontFamily / fontWeight / fontStyle / fontSize / fill pour détecter les blocs à styles mixtes (qui retombent en raster), mais pas charSpacing. Résultat : un textbox avec tracking sur sélection partait en vectoriel avec le seul obj.charSpacing global (via font.getAdvanceWidth(letterSpacing)) → espacement faux dans le PDF. Fix : ajout du test st.charSpacing !== blockCs dans la boucle des per-char styles → fallback raster automatique pour ces blocs (le raster utilise déjà le _measureChar patché et restitue le bon espacement).
  • Poignées rotées. Aucune incidence sur l'export : ML/MR/MT/MB/coins ne stockent rien dans le modèle, juste l'état live de drag (transformData._spLocal) qui est nettoyé dans commonMouseUpHandler. Round-trip propre.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.104

Released — May 8, 2026

🔄 Poignées de redimensionnement suivent la rotation (action locale) fix

  • Symptôme corrigé. Sur un bloc texte tourné (ex. 90°), tirer la poignée gauche/droite continuait à redimensionner sur l'axe X du canvas (largeur visuelle horizontale) au lieu de redimensionner la largeur de l'objet dans son repère local. Résultat : poignées "gauche/droite" et "haut/bas" échangées visuellement, action incohérente.
  • Cause racine. Les 5 actionHandlers personnalisés (ML/MR/MT/MB + coins) opéraient en coordonnées monde axes-alignées (getObjectBounds, setObjectFromBounds) en lisant pointer.x / pointer.y bruts — ce qui ignore target.angle.
  • Fix appliqué. Réécriture complète des 5 handlers en repère local : (a) au début du drag, capture du point d'ancrage opposite-edge en coords monde via translateToOriginPoint(getCenterPoint(), oppositeOriginX, oppositeOriginY) ; (b) projection du delta pointeur sur les axes locaux (cosθ, sinθ) / (-sinθ, cosθ) pour obtenir les nouveaux W/H locaux ; (c) setPositionByOrigin(anchorPoint, oppositeOriginX, oppositeOriginY) pour replacer l'objet de manière que le bord opposé reste fixe en monde. Résultat : les poignées agissent toujours dans l'axe local du bloc, quelle que soit sa rotation.
  • Bonus visuel. Le rendu (visuel) des poignées a aussi été patché (v1.7.102) via fabric.Object.prototype.drawControls pour pivoter le contexte de l'angle de l'objet — les poignées affichent maintenant l'orientation du bloc.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.103

Released — May 8, 2026

✏️ Tracking par caractère (per-char charSpacing) fix

  • Symptôme corrigé. Le champ Esp. lettres du sidebar de droite ne pouvait pas modifier l'espacement uniquement sur les caractères sélectionnés d'un bloc texte — la valeur était écrite dans les styles inline mais Fabric.js ne la lisait jamais.
  • Cause racine. Fabric.js 5.3 ne supporte pas nativement charSpacing par caractère. Cette propriété n'est pas dans _styleProperties, donc getCompleteStyleDeclaration ne la retourne pas, et _measureChar n'utilise que la valeur globale this.charSpacing du bloc. Résultat : setSelectionStyles({charSpacing: 50}) était silencieusement ignoré.
  • Fix appliqué. (a) Ajout de charSpacing à fabric.Text.prototype._styleProperties pour qu'il soit récupéré dans le style complet par caractère ; (b) patch de _measureChar qui calcule le delta entre charStyle.charSpacing et this.charSpacing et l'ajoute à width + kernedWidth ; (c) capture de la sélection sur mousedown/focus de l'input du sidebar (avant que le focus ne vole les selectionStart/selectionEnd) ; (d) appel à spForceInlineStyleRewrap après setSelectionStyles pour forcer la régénération de __charBounds.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.102

Released — May 8, 2026

✏️ Tracking (espace lettres) appliqué sur la sélection fix

  • Symptôme corrigé. Le champ Esp. lettres du panneau Typographie ne répondait plus : la valeur changeait dans l'input mais l'espacement des caractères restait inchangé sur le bloc texte.
  • Cause racine. Le handler n'était branché que sur l'événement change (déclenché au blur uniquement) et un return silencieux ignorait l'entrée en mode édition sans sélection. Le cache __charBounds n'était pas invalidé explicitement.
  • Fix appliqué. (a) Branchement sur input + change pour appliquer en live ; (b) la valeur s'applique uniquement aux caractères sélectionnés dans le bloc en mode édition (double-clic dans le bloc → sélectionner les glyphes → modifier l'espacement) ; (c) sanitisation Number.isFinite (évite NaN) ; (d) invalidation explicite de __charBounds + _clearCache avant initDimensions pour forcer la régénération des positions de caractères.

🔄 Poignées de sélection suivent la rotation fix

  • Symptôme corrigé. Lors de la rotation d'un bloc texte ou d'une image, les poignées de redimensionnement (cotés, coins, rotation) restaient alignées aux axes du canvas au lieu de suivre l'orientation du bloc.
  • Fix appliqué. Patch global de fabric.Object.prototype.drawControls qui enrobe une seule fois le render() de chaque control (textbox, image, rect, path, group…) pour pivoter localement le contexte de l'angle de l'objet avant de dessiner. Les poignées ml/mr/mt/mb/coins/mtr s'orientent désormais dans l'axe du bloc tourné, sans recréer les wrappers à chaque frame (flag __spRotatedRenderWrapped).

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.99

Released — May 7, 2026

📄 Export PDF avec gabarit — le texte du gabarit n'est plus perdu fix

  • Symptôme corrigé. Lorsqu'une page utilisait un gabarit contenant du texte (ex : titre courant, mention légale, pied de page), l'export PDF/JPG/PNG ressortait avec les images et formes du gabarit, mais le texte du gabarit était absent.
  • Cause racine. Dans injectMasterItemsForExport(), les textbox du gabarit étaient recréés manuellement sur le canvas d'export en copiant seulement ~20 propriétés. Plusieurs propriétés essentielles étaient omises : originX, originY, _fixedHeight, _fixedWidth, splitByGrapheme, breakWords, direction, enableHyphenation, minWidth, backgroundColor, skewX/Y, flipX/Y. Si l'utilisateur avait par exemple originX:'center' sur son texte master, la recréation avec 'left' par défaut le décalait de width/2, le faisait sortir de la zone page, et le filtre pasteboard de l'export le supprimait silencieusement. Les images et formes étaient épargnées car elles utilisent fabric.util.enlivenObjects() qui restaure fidèlement toutes les propriétés.
  • Fix appliqué. (a) Toutes les propriétés pertinentes sont maintenant copiées lors de la recréation du textbox master ; (b) initDimensions() est ré-appelé après injection des styles inline pour que la hauteur calculée reflète les fontSize overridés ; (c) _fixedHeight/_fixedWidth sont restaurés APRÈS initDimensions (sinon Fabric expand la hauteur pour contenir tout le texte) ; (d) la fonction restoreTextboxAfterLoad() (qui force un clipPath strict) n'est plus appelée sur les masters fraîchement injectés, qui n'en ont pas besoin et pouvaient être masqués par un clip mal calculé ; (e) un log [SP-export] master injected: visible dans la console (F12) confirme à chaque export combien d'items master texte/non-texte ont été injectés.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.98

Released — May 7, 2026

🔌 Collaboration P2P — stabilité réseau & avertissement invité UX fix

  • Disclaimer obligatoire pour l'invité. L'étape Rejoindre affiche désormais en haut un bandeau ambre clair prévenant que la connexion va écraser le document local de l'invité (l'hôte pousse son projet complet via doc:replace dès l'ouverture du DataChannel). Une case à cocher « Je comprends et j'accepte de perdre mon document local » gate le bouton Continuer pour éviter les pertes accidentelles. Bilingue FR/EN.
  • Keepalive ping/pong (3 s). Cause #1 des coupures P2P en réseau résidentiel/4G : les mappings NAT expirent après 30-60 s d'inactivité. Un ping minuscule est maintenant envoyé toutes les 3 s sur le DataChannel pour maintenir la session vivante même quand les deux utilisateurs sont en lecture passive.
  • Watchdog de reconnexion. Au-delà de 12 s sans trafic reçu, le badge collab passe en orange “Réseau instable — tentative de reconnexion…” et l'hôte déclenche automatiquement un RTCPeerConnection.restartIce() (négociation ICE fraîche sur la même session, sans renvoyer de lien). Si la connexion revient (typiquement 1-5 s sur un Wi-Fi qui roame), un toast “Connexion rétablie” confirme la reprise.
  • Plus de teardown intempestif. Avant, l'état ICE disconnected (transitoire, fréquent) coupait immédiatement la session. Désormais seuls failed et closed déclenchent une vraie déconnexion ; les drops courts (< 12 s) sont résorbés sans interrompre le travail.
  • Abandon propre après 45 s. Si la session reste muette plus de 45 s malgré les tentatives ICE, le client se déconnecte proprement et invite l'utilisateur à cliquer sur Collab puis Regénérer pour repartir, plutôt que de laisser une session zombie.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC (DataChannel keepalive + ICE restart) · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.97

Released — May 7, 2026

🤝 Collaboration P2P — modal redesign + WebRTC audit UX

  • Modal entirely redesigned. All decorative emojis (📋 ✍ 🔗 🚪 ⏳ ✓ ① ② ③) are gone. Two big tiles “Invite” / “Join”, numbered steps, larger fonts, more breathing room. The full base64 SDP is now hidden by default behind a “Show code” toggle so users only see a clean shareable URL.
  • Visible link preview field on the host side: a read-only input shows the absolute https://app.zigmoon.com/SUPERPRINT/#sp-collab=… URL the moment ICE gathering completes — selectable on click for trivial manual copy.
  • New “Regenerate” button on both host & join steps. Tears down the current RTCPeerConnection + DataChannel + ICE timer and creates a brand-new offer (or clears the join state) so a fresh URL/code is produced every time, eliminating the “my URL never changes between sessions” perception.
  • Robust paste handling on the join side. The textarea now has spellcheck="false" + autocomplete="off", auto-selects on focus, and a new “Clear” button sits between Paste and Continue. Pasting either the full URL or the raw base64 code both work — extractInviteCode() now feeds acceptAnswer and joinFromOffer too.
  • Validation before handshake. generateReply() now decodes & parses the SDP before creating the peer connection. If the user pasted random text or a truncated link, a clear bilingual toast fires (“Lien invalide — vérifiez que vous avez collé le lien complet”) instead of a silent console.error.
  • ICE-completion safety timeout (8s). On restrictive corporate networks where onicecandidate(null) never fires, the host now sees an orange status “ICE gathering is blocked by your network. Click Regenerate or check your connection.” instead of waiting forever.
  • Lifecycle leak fixes. Closing the modal mid-handshake now tears down the half-built peer connection (no more orphan RTCPeerConnections). disconnect() resets the wizard back to the choice step + clears all textareas (it used to leave the modal stuck on the “Connected” view). Peer name is cleared on teardown so the badge doesn’t keep a stale identity.
  • Absolute URL builder. makeInviteUrl() now always emits an explicit https:// + host + clean path (strips trailing index.html) and falls back to https://app.zigmoon.com/SUPERPRINT/ when the app is opened via file:// or a stale PWA cache where location.origin is empty — fixes the “copied link doesn’t start with app.zigmoon.com” bug.
  • Auto-join safety net. If a user opens the modal manually after clicking an invite link (or if checkAutoJoinHash() missed its timing), openModal() now re-reads location.hash and switches to the join step automatically.

📕 Chemin de fer — P1 duplication fix fix

  • P1 lost most of its elements when duplicated. Root cause was a race in saveAllPages(force=true): the force flag bypassed every guard, including the _isLoading check, so when the user clicked Duplicate while a canvas was still mid-loadFromJSON, getObjects() returned a partial list and pages[0].objects was overwritten truncated. P1 was the most exposed because it’s the first canvas reconstructed by renderAllPages. Two fixes: duplicatePageFromChemin now retries every 50 ms (max 2 s) while any canvas has _isLoading=true, and saveAllPages defensively refuses to read from a loading canvas even with force=true.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.96

Released — May 5, 2026

🩹 Version harmonization across all surfaces fix

  • Splash screen out of sync — the boot splash still displayed v1.7.79 while the in-app top-nav badge had moved on to v1.7.95. Two stale labels (.splash-version at L1052 and the secondary IBM Plex Mono mention at L3215) are now both bumped to v1.7.96 so every user-visible version string matches: splash ↔ top-nav badge ↔ documentation badge ↔ JSON-LD softwareVersion ↔ service-worker CACHE_NAME ↔ llms.txt ↔ llms-full.txt ↔ release.html. Single source of truth restored.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.95

Released — May 5, 2026

🤝 Real-time P2P collaboration — WebRTC new

  • 1-to-1 live co-design — a brand-new Collab button in the top toolbar opens a P2P session powered by WebRTC DataChannel. No server, no account, no cloud: invitation and reply are exchanged as base64 codes via your trusted channel (mail, chat, SMS). End-to-end encrypted by construction (DTLS), STUN public used only for NAT traversal. new
  • Live object sync — every object:added / object:modified / object:removed on any page is mirrored to the peer in real time, with the full SP_CUSTOM_PROPS whitelist preserved (image masks, text-link chains, master-page bindings, PDF-import flags, spread overflow markers, indents…). Each object gets a stable _collabId so add/move/delete remain consistent across peers.
  • Live cursors — each collaborator's mouse pointer is broadcast at ~20 Hz with their nickname + color badge, so you literally see your partner moving on the page.
  • Full .sp document broadcast — on connection, the host pushes the entire project (doc:replace message: pages, masters, text-links, numbering, format, margin, bleed) so the peer's editor mirrors the document 1:1. Auto re-broadcast after every host-side .sp import. Echo storm during reload is suppressed for 1.5 s to avoid duplicate object events.
  • Bilingual modal FR/EN — the entire P2P modal (title, description, tabs, buttons, instructions, placeholders, toasts) follows the global currentLanguage with data-i18n-fr / data-i18n-en attributes applied at open.
  • Round color swatches — replaces the OS-native <input type="color">: 5 carefully-picked accent colors (red, orange, green, blue, purple) for clear visual distinction between collaborators, plus a custom rainbow chip if you want a personal hue. Selection persists across sessions via localStorage.
  • Click-outside lockdown — the modal contains long base64 SDP codes you don't want to lose. The accidental "click backdrop = close" behavior was removed: the panel now only closes via the explicit ×, Close or Disconnect buttons.
  • Identity persistence — pseudo + color saved in localStorage.sp_collab_identity, restored on every reopen.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · WebRTC RTCPeerConnection + DataChannel · STUN Google + Cloudflare · DTLS · Vanilla JS

Honest scope: P2P 1↔1 today (no 3+ mesh, no CRDT, last-write-wins on simultaneous edits). Designed for client review, freelance pair-design, demo, BAT validation. For team co-edition with conflict-free merging, a future integration with Yjs is on the roadmap.

→ Open SUPER PRINT


SUPER PRINT v1.7.93

Released — May 5, 2026

🆕 Pageboard — Duplicate page & Save page as master new

  • Duplicate page — a new button appears on hover of every thumbnail in the pageboard. The duplicate is inserted right after the source page (i+1), preserving every object (text, images, shapes, user guides, grid markers), the page background, and the assigned master if any. Object identifiers (_spreadObjectId, textLinkId) are regenerated on the fly so spread mirroring and text chaining keep working independently on each copy new
  • Save page as master — a new ⊕G button creates a brand-new master page (auto-letter A → B → C…) from the current page content. Auto-generated print marks (margins / bleed / trim box) are filtered out (re-injected by the master renderer); user guides are kept. The new master is added to the masters panel without auto-assigning the source page — you can then assign it manually with the · button on any thumbnail. Double-click the master chip to edit it; close with the new × in the top-right of the master editor to return to the pageboard new

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v1.7.92

Released — May 5, 2026

🩹 Critical fixes — Memory leaks & auto-save reliability fix

  • IDML import — image blob URLs leaked — every .idml imported left N blob: URLs in memory until the next page reload. Bitmaps are already inlined as dataURL during parse, so the blob URLs were referenced nowhere. Now URL.revokeObjectURL() is called on every image right after parseIdmlAndBuild() resolves and in the catch path fix
  • IDML import — font blob URL leaked on error — when FontFace.load() rejected (corrupted / unsupported font), the blob URL created just before was never revoked. The variable now lives outside the try block so the catch branch can free it fix
  • Auto-save — silent skipped saves — the previous "cheap" hash compared pages.length + sum(objects.length). Add+delete operations producing the same total length collided silently, skipping the IndexedDB write. Replaced by a FNV-1a 32-bit content hash per page (~5–10 ms per 100 KB) — collisions effectively eliminated, no more lost work after a crash fix

⚡ Memory — Imposition VRAM released fix

  • Fabric dispose() + canvas zero-out — Fabric removes listeners but doesn't always reset the underlying <canvas> dimensions, which can pin GPU textures until the next garbage collection. The imposition export pipeline now grabs lowerCanvasEl / upperCanvasEl before dispose() and zeroes their width/height — large imposition sheets release several megabytes of VRAM immediately fix

� PDF import — micro white seam fixed fix

  • Imported PDF placed at 100,5 % instead of 100 % — sub-pixel rounding between the rasterised PDF page and the page background occasionally left a 1–2 px white antialiasing line at the edge. The placement scale in importPDFPagesV2 now applies a uniform ×1.005 overshoot, centred on the page (originX/originY = center), so the 0,5 % bleeds ~0,25 % each side and is clipped by the bleed/page bounds at export. Applies to all 3 recropping modes (support, page, custom) and to spread-split halves. The none mode (fit-inside) keeps a strict 100 % since the user expects the full PDF visible.

🎨 Export PDF HD CMYK — ICC profile order & default UX

  • “Aucun profil ICC” is now the default in both export panels (top-nav classic export and Imposition Calculator). Profiles are listed in priority order: Aucun (DeviceCMYK brut)Coated FOGRA39U.S. Web Coated SWOPJapan Color 2001 Coated. Custom .icc / .icm upload still available for shops that need to embed their own profile.

📝 Details

Fabric.js 5.3.0 · jsPDF 2.5.1 · pdf.js 3.11.174 · IndexedDB · FNV-1a 32-bit · Vanilla JS

→ Open SUPER PRINT


TYPO VIDEO v1.0.0

Released — April 28, 2026

New app — Animated typography studio new

  • Full-screen, single-page studio dedicated to kinetic typography: type your text, pick a mode, drive the FX with live sliders, hit REC.
  • 11 animation modes: Scroll, Pulse, Glitch, Marquee, Type, Stack, Kinetic, Rain, Edges, Frame and the new 3D (faux-extruded depth with rotation, highlight rim and floor reflection).
  • Animated grain slider — dual-pass film noise (overlay + soft-light) with a regenerated tile for true motion.
  • 12 curated Google Fonts (Bebas Neue, Anton, Archivo Black, Unbounded, Syne, Major Mono Display, Press Start 2P…) loaded on demand via document.fonts.load() so the canvas always renders the chosen face.
  • Live FX: glitch, blur, hue, trail, jitter, RGB-split, hue-cycle / strobe / RGB modes, custom letter-spacing, weight, speed.

Recording & export new

  • Live REC: one-click recording of the on-screen canvas at 60 fps via captureStream + MediaRecorder (VP9 / VP8 / AV1 fallback chain, 16 Mbps).
  • Offscreen export up to 4K (2160p) and 8K (4320p), aspect ratios 16:9, 9:16, 1:1, 4:5, frame-accurate via track.requestFrame() per rendered frame.
  • Auto-save to localStorage (debounced 250 ms) — your scene survives a refresh.

Installable PWA PWA

  • Standalone manifest scoped to /TYPOVIDEO/, display: standalone with window-controls-overlay override.
  • Service worker with versioned precache, network-first navigations (offline fallback to index.html) and stale-while-revalidate for Google Fonts.
  • Real INSTALL button in the top bar driven by beforeinstallprompt; iOS users get a Share-sheet hint.

UX UX

  • REC and EXPORT buttons promoted to the top-right nav; the footer HUD is now denser with wrapping mode segments and tighter sliders.
  • Hide / show the panel via the central grip handle, plus full-screen toggle.

Open TYPO VIDEO →

VIZION v0.2.0

Released — April 28, 2026

Performance overhaul perf

  • rAF-coalesced renderer (scheduleRender()): paint requests are merged into a single requestAnimationFrame tick, eliminating duplicate redraws during drag, resize and tool changes.
  • Per-layer render cache with stable hash key — masks, filters and transforms are only re-baked when something actually changes; otherwise a single drawImage() fast-path is used.
  • Debounced history (pushHistory() with 60 ms coalescing + flushPendingHistory()) — undo stack no longer explodes during continuous drags.
  • Viewport culling in render(): off-screen layers are skipped entirely.
  • Smart import downscale: huge photos are clamped to MAX_IMPORT_DIM=4096 on the way in, keeping memory and GPU usage sane.

Folder & multi-asset drop with layout chooser new

  • Drop a folder (or many files at once) of images, videos or 3D models — VIZION walks the directory via webkitGetAsEntry and groups assets by family.
  • New layout modal appears for each family with 6 layouts: Grid, Masonry, Row, Pile, Turntable and Original — placement is computed around the current board centre, respecting zoom and pan.
  • Works for images, videos and 3D models (.glb / .obj / .stl / .fbx) in a single drop.

Cover Flow 3D mode new

  • iTunes-style focus carousel: side cards rotate, scale and depth-shift, the focused card is centered and on top.
  • Floating HUD with prev / next / exit, plus / arrow-key navigation and click-on-side-card to refocus.
  • Driven by a new computeLayoutPlacements() with a coverflow branch and a transient _coverflow state object that restores the original layout on exit.

Arrange button + align / distribute new

  • The brush slot is replaced by an Arrange button (desktop + mobile) opening a submenu with the 6 layouts, 6 align actions (left, center-X, right, top, center-Y, bottom) and 2 distribute actions (horizontal, vertical).
  • Closes on outside click, Esc, and is opened/closed with the R shortcut.

3D boxed layers — usability UX

  • New top dragbar on each 3D embed lets you move the box without fighting the OrbitControls below.
  • The 3D canvas is now pointer-events: none outside the dragbar / resize ring, so neighbouring image layers stay clickable.
  • Resize ring widened to a 22 px inset hit area for easier grabbing.
  • Dragbar respects state.zoom in infinite-board mode for 1:1 cursor tracking.

Text tool fix in infinite-board mode fix

  • openTextEditor() now correctly converts world → screen coordinates using x*zoom + panX when body.is-no-frame is active.
  • Font-size is scaled by visualScale so the editable input matches the rendered glyph size on the canvas (true WYSIWYG at any zoom).

Single-click drag after multi-import UX

  • Freshly imported batches are now select-and-drag in a single click instead of requiring a select → release → drag sequence.

Open VIZION →

TRACE v1.0.0

Released — April 26, 2026

Initial release — Free IP lookup, privacy audit & network diagnostic major

  • Single-page, browser-native diagnostic that shows in real time what every website, your ISP and the network already know about your machine.
  • Public IP & geolocation: IPv4 + IPv6, reverse DNS (PTR), ISP, ASN, organisation, city, region, country, postal, timezone, currency — pinned on a Leaflet + OpenStreetMap map (no Google).
  • 4-API cascade with 6-second timeout: ipwho.is → ipapi.co → ipapi.is → ipify, with graceful fallback when blocked.
  • Local network: WebRTC STUN probe, RFC1918 LAN addresses and any leaked public IP behind a VPN.
  • Browser fingerprint: canvas hash, audio hash (OfflineAudioContext), font enumeration (20-font test set), GPU vendor + renderer, screen, viewport, DPR, languages, timezone.
  • Hardware: CPU cores, device memory, battery, storage quota, permissions inventory, media devices, plugins.
  • Speed test: live download (1/5/10 MB chunks against speed.cloudflare.com) with progressive bitrate display, 2 MB upload estimation, RTT.
  • DNS & reachability: DoH lookup of A, AAAA, MX, NS, TXT/SPF, Cloudflare PoP / colo / edge IP, latency probes against Cloudflare, Google, AWS, Azure, OVH, GitHub, 1.1.1.1.
  • Privacy posture: 32-bit fingerprint ID with entropy estimate (“1 in N visitors”), VPN / Tor / hosting heuristic on ISP keywords, prefers-* media queries, WebAuthn, Bluetooth, USB, Serial, HID API availability.
  • Live behaviour: dwell time, mouse moves, clicks, keystrokes, scroll, focus, fullscreen, idle, page visibility — plus opt-in probes (GPS, motion sensors, microphone level, gamepads) requiring an explicit user click.
  • JSON export: one-click download of the full diagnostic report.

Day / night theme new

  • CSS-variable theme toggle stored in localStorage.trace_theme, default following prefers-color-scheme.
  • SVG sun / moon icons (no emoji), top-nav button. All panels, the splash screen and the Leaflet map adapt.

Network-themed splash screen new

  • Three-panel splash inspired by CAMERRA: brand panel + animated rotating “network aperture” rings + info panel with version, features, brand.
  • Scanline animation, theme-aware colours (cyan accent in dark, blue accent in light).

PWA & PayPal support pop-in new

  • Installable Progressive Web App: manifest.webmanifest with id, scope, categories [utilities, security, productivity, developer], maskable icons and 2 shortcuts (Run speed test / Export JSON).
  • Offline-capable shell via service-worker.js.
  • Discreet PayPal “Support” button in the top nav, opens donate flow in a pop-in.

SEO 2026 — full search + AI discoverability new

  • 6-graph JSON-LD: Organization, WebSite, WebApplication (with full featureList), BreadcrumbList, FAQPage (7 Q/A), SoftwareApplication.
  • Open Graph + Twitter Card, canonical, hreflang (en, fr, x-default), dual theme-color for dark/light.
  • noscript fallback and hidden indexable <div id="seo-intro"> with H1, H2, FAQ and feature list.
  • robots.txt explicitly allows GPTBot, ChatGPT-User, OAI-SearchBot, ClaudeBot, anthropic-ai, PerplexityBot, Google-Extended, Applebot-Extended, CCBot, Bytespider, Meta-ExternalAgent, MistralAI-User and more.
  • sitemap.xml with hreflang and image:image, plus llms.txt, llms-full.txt, ai.txt and humans.txt.

Privacy by design privacy

  • No backend, no analytics, no advertising, no third-party tracker, no signup, no email collected.
  • Microphone, GPS and motion sensors are never auto-activated — only on an explicit user click.
  • Source is a single static HTML file for full transparency.

Open TRACE →

MAIL MAX v1.0.0

Released — April 25, 2026

✉️ Initial Release — King of Mailing List CSVs major

  • Convert any CSV mailing list to the exact import format expected by 19 newsletter providers: Mailchimp, Brevo (ex-Sendinblue), Mailjet, MailerLite, HubSpot, ActiveCampaign, ConvertKit (Kit), Klaviyo, Beehiiv, Substack, GetResponse, AWeber, Constant Contact, Omnisend, SendGrid, Loops, Resend, Campaign Monitor and Drip.
  • Custom RFC-4180 CSV parser with delimiter auto-detect (comma, semicolon, tab, pipe), quoted fields, embedded newlines and BOM stripping.
  • Header normalisation across English, French, Spanish and German aliases plus heuristic email-column detection when headers are missing.
  • Multi-file ingestion with cross-file deduplication by lowercased email, invalid-email filtering, optional UTF-8 BOM for Excel.
  • Live preview table (first 50 rows) with stats: total contacts, dropped invalids, removed duplicates.

📥 Import-mode pop-in new

  • When dropping new files on top of an existing list, choose Merge & add, Replace or Cancel. Esc / backdrop / close all cancel.

💳 PayPal one-shot credit packs new

  • 100 free email credits granted on first launch (1 credit = 1 exported email, stored locally).
  • Three credit packs via PayPal one-shot orders (intent=capture, EUR, no subscription, credits never expire):
  • · Starter — 1 000 emails for €5
  • · Pro — 10 000 emails for €50 (best value)
  • · Agency — 100 000 emails for €300 (€0.003/email, -40% volume discount)
  • Header pill shows credits remaining with .low / .zero color states; click to top up.

🔍 SEO / GEO / LLMs reinforcement new

  • 5-graph JSON-LD: SoftwareApplication, Organization, WebSite, BreadcrumbList, HowTo, FAQPage — with accurate one-shot credit-pack offers.
  • Open Graph, Twitter Card, hreflang, canonical, robots.txt opening 11 AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, etc.).
  • llms.txt, llms-full.txt and ai.txt with full pricing and provider matrix for ChatGPT / Claude / Perplexity / Gemini ingestion.
  • SEO footer: comparison table vs Excel/online tools, FAQ accordion, provider grid, use cases.

📱 PWA new

  • Installable PWA with offline-first service worker (cache mailmax-v1.2.0).
  • file_handlers for .csv, 4 PWA shortcuts (New / Mailchimp / Brevo / HubSpot), edge_side_panel, display_override with window-controls-overlay.
  • 3-second splash screen with streaming-CSV canvas animation, click / Esc / Enter / Space to skip.

📝 Details

Single-file vanilla JS PWA · RFC-4180 parser · PayPal JS SDK (intent=capture, EUR) · localStorage credit ledger · Service Worker cache mailmax-v1.2.0

→ Open MAIL MAX


PDF-YZ v0.2.0

Released — April 23, 2026

✏️ Genuine PDF text editing critical

  • Edited text now actually exports correctly — the export pipeline rewrites embedded fonts, masks the original glyphs and re-renders with the user's chosen font, size and color. Previously the new text was overlaid on top of the original, producing unreadable double-strikes fix
  • Auto-extending white mask — the masking rectangle now grows to max(originalWidth, newTextWidth) using font.widthOfTextAtSize(). If you replace "fox" with "elephant", the original is no longer visible past the mask fix
  • Multi-line edits supported — typing extra \n beyond the original line count now masks and renders each new line at the correct PDF Y at the chosen size new
  • Font size synchronization — changing size in the side panel now updates both el.fontSize (CSS) and el.pdfFontSize (export). Previously, size edits were silently lost on rebuild/zoom and ignored by the exporter fix
  • Deleted extracted text is now actually erased — emptying an extracted text block now writes the white mask to the export, removing the original from the PDF fix

⌨️ Full classic keyboard shortcuts new

  • App-level always-onCtrl+S Export · Ctrl+P Print · Ctrl+F Find · Ctrl+O Open · Ctrl+Shift+N New blank · Esc cascade new
  • Editor shortcutsCtrl+Z Undo · Ctrl+Y / Ctrl+Shift+Z Redo · Ctrl+D Duplicate · Ctrl+B Pages sidebar · Ctrl + + / − / 0 / 1 Zoom · PageUp/PageDown/Home/End Page navigation · Arrows nudge (Shift = 10 px) · Del / Backspace Delete new
  • ToolsV T I D H E select / text / image / draw / highlight / eraser new
  • Two real bugs fixedCtrl+S previously bypassed the export modal and exported with stale prefs; Ctrl+D and Ctrl+A previously called .closest() / .cloneNode() on S.selected, which is a data object, not a DOM node. Both reworked to operate on the data model + placeElement() fix
  • Form-field aware — when typing in an input, textarea or contentEditable, the browser keeps native Ctrl+Z/X/C/V/A. Editor shortcuts only fire outside form fields fix

🖼️ Top-right install button & splash resume gate new

  • Permanent install PWA button — fixed top-right (z-index: 1000000), visible at all times during pre-home, even with a document open. Hidden only when running as installed standalone PWA new
  • Splash resume gate — when reopening, a neutral resume banner shows the previous file (name, age, page count, size) above the drop zone with Resume / Discard. Inspired by SuperPrint's #sp-startup-* pattern new
  • Top-left Pages button on desktop — sidebar toggle moved out of the toolbar onto a corner-fixed control on desktop (mobile keeps the toolbar entry) new

💳 PayPal subscription gate new

  • Donation pop-in — first install attempt opens a dark-themed modal with PayPal vault subscription SDK (lazy-loaded) and a secret-code bypass. Web version stays 100% free; installable app runs on a small monthly subscription new
  • Persistence — donor flag stored in pdfz_donated_v1; subscription button hidden after first successful donation new

🌐 EN-only audit fix

  • French strings purged — crop overlay ("Toutes les pages / Page courante / Annuler / Appliquer"), btnNewDoc confirm, three toast messages, all translated fix
  • og:locale:alternate fr_FR removed — the app is now declared EN-only across meta and JSON-LD fix
  • Verified with grep — zero French accents remain in any PDF-YZ source file fix

🔍 SEO / GEO / LLMs reinforcement new

  • JSON-LD enriched — added SoftwareApplication, HowTo (4-step "how to edit a PDF online"), and aggregateRating on WebApplication. BreadcrumbList and FAQPage retained new
  • Sitemap upgraded — multi-namespace (xhtml + image), lastmod 2026-04-23, xhtml:link hreflang declarations, image:image entry for Google Images new
  • robots.txt opened to AI crawlers — explicit Allow for GPTBot, ChatGPT-User, OAI-SearchBot, ClaudeBot, Claude-Web, anthropic-ai, PerplexityBot, Perplexity-User, Google-Extended, CCBot, Bytespider, Applebot-Extended, cohere-ai, Mistral-AI new
  • Dedicated llms.txt — created at /PDF-YZ/llms.txt with positioning, features, shortcuts, stack and sister-app links. PDF-YZ entry also added to the root /llms.txt directory new

🐛 Other fixes

  • Capture-phase mousedown no longer destroys inline edits — the global text-click handler on #canvasArea now excludes .el-text, .pdfz-inline-textarea, .resize-h, .el-img, .el-sig, .el-note, .el-pdf-img, #btnPagesFixed and #btnInstallPwa. Text editing was silently broken before fix
  • Splash banner colors neutralized — replaced blue accents (#3b82f6, #2563eb) on the resume banner with neutral #111/#000 per request fix
  • Ctrl+D duplicate now works — uses JSON.parse(JSON.stringify(src)), fresh UUID, +15 px offset, clears the extracted flag, and pushes a real undo entry fix

📝 Details

pdf-lib 1.17.1 · pdf.js 4.9.155 · Vanilla JS / single-file · PWA (manifest + service-worker · file_handlers application/pdf · share_target POST) · Service Worker cache bumped to pdfz-v4 · softwareVersion 0.2.0 in JSON-LD, humans.txt and llms.txt

Known limitation — undo/redo currently only restores add-type actions. Drag, resize, font/size/color changes and content edits do not yet push to the undo stack. Tracked for next sprint.

→ Open PDF-YZ


KULT 2 v0.0.3

Released — April 21, 2026

🏙️ Urban Generator Update new

  • Adaptive live preview — Urban generator now uses a GPU-friendly instanced preview while dragging sliders, then automatically restores the full detailed district preview when you release controls fix
  • Detailed generation preserved — final generation path keeps full geometry/detail behavior (facades, rooftop props, accessories) fix

🧭 Ergonomics & UI polish new

  • Urban panel redesign — wider panel, improved spacing, clearer visual hierarchy and larger controls for faster tuning
  • Generate action improved — dedicated primary button styling with sticky action row for better accessibility while scrolling
  • Slider readability — labels, ranges and values are now easier to scan and compare during iterative adjustments

📝 Details

Three.js 0.179.1 · WebGLRenderer · InstancedMesh preview path · Urban Architecture Generator UX refresh · Vanilla JS

→ Open KULT 2


ZORD v0.0.5

Released — April 26, 2026

🛡️ Security-focused release security

  • Strict CORS allowlist on ai.php — replaced the Access-Control-Allow-Origin: * wildcard with an explicit whitelist (app.zigmoon.com, zigmoon.com, www.zigmoon.com + localhost for dev). Unlisted origins are rejected with HTTP 403 and a Vary: Origin header is emitted on every response. Non-POST/OPTIONS requests now return 405 fix
  • OAuth tokens moved out of localStorage — Google Drive, Dropbox and OneDrive access tokens are now stored in sessionStorage (cleared when the tab closes), reducing the XSS-token-theft window. A one-shot migration helper transparently moves any pre-existing token from localStorage to sessionStorage on first launch fix
  • Content Security Policy added — both index.html and index_FR.html now ship a strict <meta http-equiv="Content-Security-Policy">: default-src 'self', object-src 'none', frame-src 'none', base-uri 'self', form-action 'self', with explicit allowlists for Quill / Tailwind / cdnjs (scripts & styles), Google Fonts, and the AI / cloud APIs (Anthropic, OpenAI, Gemini, Mistral, LanguageTool, Pinata, Google & Microsoft & Dropbox OAuth) new
  • Service Worker cache bumped to zord-v8-0.0.5 — forces every installed PWA to fetch the new hardened HTML, JS and PHP shell on next launch new

📱 Mobile UX new

  • Voice / dictation button promoted in the mobile More (…) drawer — now the third button (after Bold & Underline) instead of being hidden at the bottom of the list. Faster reach for one-handed dictation on phones new

📝 Details

CORS allowlist · CSP meta · sessionStorage OAuth migration · Service Worker zord-v8-0.0.5 · softwareVersion 0.0.5 in JSON-LD, splash and preferences · No functional regression, no API change.

→ Open ZORD


ZORD v0.0.3

Released — April 19, 2026

🛡️ Security Hardening fix

  • CORS wildcard removedai.php used Access-Control-Allow-Origin: *; now restricted to an explicit whitelist of allowed origins fix
  • XSS via IPFS hash — an unsanitized IPFS hash was inserted via innerHTML in app.js; replaced with safe textContent fix
  • cURL timeout + payload limitsai.php and ai-proxy.php now enforce CURLOPT_TIMEOUT (30s) and reject payloads larger than 512 KB to prevent resource exhaustion fix
  • IPFS hash validation — hashes are now validated against a strict CID regex before any fetch request fix
  • test-php.php removed — was exposing phpversion() in production fix

📱 Android Chrome — Data Loss Fix critical

  • Page Lifecycle API implemented — added pagehide, freeze, resume and pageshow event listeners. On Android Chrome, when the phone goes to sleep, the browser freezes or discards the tab without firing beforeunload. Documents were lost on wake. Now all four lifecycle events trigger a synchronous emergency save to localStorage fix
  • visibilitychange guard removed — the handler was gated behind && __idbInitDone, which skipped the synchronous localStorage save if IndexedDB hadn't finished initializing. Condition removed — localStorage now always writes on visibility change fix
  • _emergencySaveSync() centralized — all lifecycle events (beforeunload, visibilitychange, pagehide, freeze) now call a single function that captures the editor snapshot + writes full localStorage + writes emergency backup in one synchronous pass new
  • BFCache restorepageshow with persisted=true (back-forward cache) now re-syncs data from IndexedDB instead of showing stale content new
  • Frozen tab recoveryresume event re-initializes IndexedDB when a previously frozen tab becomes active again new

🌐 Bilingual Audit (EN & FR) fix

  • English page had French text — sidebar stats showed "0 mots" / "0 signes" instead of "0 words" / "0 chars"; desktop tools trap had "Couleur", "Lien", "Nettoyer" instead of "Color", "Link", "Clean" fix
  • Broken Unicode characters in EN — sort filter arrows and tool icons displayed as ? instead of / / fix
  • French "Text break" untranslated — desktop tool label now reads "Saut de texte" in the FR version fix
  • Tu/Vous inconsistency in FR — 12 modals (export, print, rename, AI settings, cloud, save reminder, Web3) mixed formal vous and informal tu. Standardized to tu across the entire French interface fix
  • i18n.js accent & punctuation fixes — fixed missing accent on "Régénère", added French typographic spaces before ! and ? in confirm.newTopicDetected, standardized 8 translation keys from vous to tu fix

🧹 Cleanup & Meta

  • Version bumped to 0.0.3 — removed "alpha" designation. Updated in <meta generator>, JSON-LD softwareVersion, splash screen, preferences contact tab, humans.txt, llms.txt, llms-full.txt
  • Service Worker cache bumped to zord-v3 — forces fresh cache on all clients
  • Silent .catch(() => {}) patterns flagged — error swallowing in multiple async paths identified for future logging improvements
  • CSP headers recommended — Content Security Policy not yet present on HTML files; documented as next priority

📝 Details

Page Lifecycle API · pagehide · freeze · resume · pageshow · localStorage sync save · IndexedDB · Quill.js 1.3.6 · Tailwind CSS 3.x

→ Open ZORD


ZORD v0.0.2-alpha

Released — April 19, 2026

🤖 AI Assistant — Full Overhaul major

  • Models upgraded to latest generation — Claude Sonnet 4 & Haiku 4 (Anthropic), GPT-4.1 & 4.1-mini (OpenAI), Gemini 2.5 Pro & Flash (Google), Mistral Large Latest new
  • Proper system prompt — Anthropic now uses the dedicated system field instead of injecting into user message; Gemini uses system_instruction; unified sharedSystemPrompt across all 4 providers fix
  • Anthropic API version bumped from 2023-06-01 to 2023-10-01 in both ai.php and ai-proxy.php
  • Gemini body forwarding fixedai.php was stripping system_instruction and generationConfig; now correctly forwarded fix
  • Mistral support added to ai-proxy.php — was missing while supported in ai.php and the client fix
  • Max tokens raised from 1000 to 4096 for all providers — better for long-form writing
  • AI text insertion — removed aggressive heading auto-detection (short lines ending with : and numbered items were incorrectly formatted as H2/H3); now only Markdown # headings are parsed
  • Double .catch() removed — the AI prompt handler had two chained .catch() blocks (second never triggered); merged into one fix

🔧 Critical Bug Fixes fix

  • exportFilename undefined — email export crashed because the variable was block-scoped in a different if branch; now uses a dedicated emailFilename variable fix
  • getQuillForPage() undefined — Web3/IPFS load called a function that doesn't exist; replaced with getOrderedPageQuills() fix
  • Web3 load data format mismatch — was accessing pageData.content but buildExportData() stores Delta objects directly; now handles both formats fix
  • Web3 load missing sanitizeDeltaForLoad() — all other load paths normalize typography (non-breaking spaces, guillemets); IPFS path now does too fix
  • DOCX export half-point font sizesparseInt("10.5pt") truncated to 10; now uses parseFloat() for correct half-point conversion fix

🎤 Voice-to-Text & Shortcuts

  • Speech recognition language — now detects document.documentElement.lang instead of being hardcoded to fr-FR; English page gets en-US fix
  • Shortcut changed — voice recording moved from Ctrl+Shift+V to Ctrl+Shift+M to avoid conflict with browser "Paste without formatting" fix

🛡️ Security

  • Gemini URL injection$model parameter in ai.php was interpolated into the URL without sanitization; now filtered with preg_replace + rawurlencode fix
  • OPTIONS preflightai.php now returns proper 204 status on OPTIONS requests

🧹 Cleanup

  • Service Worker cache duplicatevendor/docx.umd.js was listed twice in PRE_CACHE; deduplicated
  • Nested vendor/vendor/ directory — duplicate files removed
  • Cache version bumped to zord-v2 to force SW update

📝 Details

Claude Sonnet 4 · GPT-4.1 · Gemini 2.5 · Mistral Large · Anthropic API 2023-10-01 · Quill.js 1.3.6 · Tailwind CSS 3.x · IndexedDB + localStorage

→ Open ZORD


MIAOU v1.0.0

Released — April 16, 2026

🐱 Initial Release — Anonymous Decentralized Chat

  • Anonymous messaging — join with a random animal avatar and username, no account or sign-up required. Messages are ephemeral and leave no trace new
  • Decentralized architecture — powered by BroadcastChannel API, all communication stays local in your browser. Zero server, zero cloud, zero tracking new
  • Rich media support — send text messages, capture photos and record videos directly from the chat. In-app camera with front/rear toggle new
  • Emoji picker — categorized emoji panel (Smileys, Animals, Food, Activities, Travel, Objects, Symbols, Flags) with search. Mobile-optimized bottom sheet new
  • Media gallery — browse all shared photos and videos in a dedicated gallery panel with fullscreen preview and download new
  • Glassmorphism UI — dark futuristic design with frosted glass surfaces, Inter + Space Mono + IBM Plex Mono typography, fluid animations new
  • Fully responsive — 6 breakpoints (768px, 600px, 380px, landscape, safe-area, touch devices), iOS keyboard handling via visualViewport API, no auto-zoom on inputs new
  • Splash screen & lobby — animated splash with cat ASCII art, lobby with room creation/join, custom username support new
  • PWA & offline — installable as Progressive Web App with service worker, manifest.json, and full offline support new
  • 100% browser-based — no installation, no cloud, no tracking. All processing stays on device. GDPR compliant by design new

📝 Details

BroadcastChannel API · MediaDevices API · visualViewport API · Inter + Space Mono + IBM Plex Mono · Vanilla JS · PWA

→ Open MIAOU


CAMERRA v1.0.0

Released — April 16, 2026

🎥 Initial Release — Multi-Camera Web Studio

  • Multi-camera monitoring — connect unlimited USB and IP cameras simultaneously, with real-time preview in 6 layout modes (Solo, Dual, Quad, 6-up, 9-up, Picture-in-Picture) new
  • Recording & snapshots — record individual or all cameras in adaptive-bitrate WebM (VP9 + Opus, 800 Kbps–8 Mbps), take instant PNG snapshots from any feed new
  • Live broadcast via WHIP — stream a composite feed to any WHIP-compatible endpoint (OBS WHIP, Cloudflare, Janus). Canvas compositor with Grid, PiP and Side-by-Side modes, configurable resolution up to 1080p new
  • Real-time audio monitoring — per-camera waveform and VU meter powered by Web Audio API (AnalyserNode), with automatic audio mixing during broadcast new
  • Dark / Light theme — pure monochrome interface with day/night toggle, persistent via localStorage new
  • Step-by-step tutorial — 11-slide interactive wizard shown on first visit, accessible anytime via the help button new
  • Fullscreen studio mode — immersive full-screen interface for production use new
  • 100% browser-based — no installation, no cloud, no tracking. All processing stays on device. GDPR compliant by design new

📝 Details

WebRTC · MediaRecorder · Canvas API · Web Audio API · WHIP protocol · Vanilla JS

→ Open CAMERRA


SUPER PRINT v0.0.5-alpha

Released — April 2, 2026

🐛 Critical Fix — Undo/Redo blocked after page restore fix

  • _isRestoringState stuck on empty canvases — when _fastRestoreCanvases() was called with zero canvases, pendingLoads never reached 0 and onCanvasLoaded() was never invoked. The internal restore guard _isRestoringState stayed true permanently, silently blocking all Ctrl+Z / Ctrl+Y until the next full page reload. Added an early-exit guard that resets the flag immediately when canvases.length === 0 fix

🐛 Fix — Text undo race condition fix

  • Ctrl+Z inside text block inconsistentspScheduleTextEditingUndoFallback() compared the text content before and after a 25 ms window to decide whether to fall back to global undo. On a loaded browser the timeout fired before the native textarea had processed the keystroke, causing the global undo to trigger when it shouldn't — or to not trigger when it should. Timeout increased from 25 ms → 60 ms to reliably wait for the native input event cycle fix

⚡ Performance — Auto-save pressure reduced fix

  • Debounce after saveState extended — the IndexedDB write was scheduled 12 s after every saveState() call (which fires on every user action). On intensive work sessions this created a continuous queue of serialization tasks. Debounce extended to 30 s; the requestIdleCallback timeout increased to 10 s so the write only happens when the browser is truly idle fix
  • Periodic auto-save interval reduced — the background setInterval safety timer was set to 60 s and ran redundantly alongside the debounce. Increased to 5 min — it now acts only as an inactivity safety net, not as a second write path fix
  • setTimeout fallback no longer fires inline — the non-requestIdleCallback fallback path now defers 200 ms instead of executing synchronously, preventing an IndexedDB write from landing in the same frame as a user interaction fix

🔤 UX — Auto-save wording clarified

  • All user-visible references to IndexedDB replaced with "Sauvegarde automatique dans le navigateur" — onboarding wizard, Ctrl+S mode dropdown, onboarding FAQ and schema.org metadata. The technical term was meaningless to end users fix

📝 Details

Fabric.js 5.3.0 · IndexedDB · requestIdleCallback · Vanilla JS

→ Open SUPER PRINT


KULT v0.3.1-alpha

Released — April 1, 2026

🐛 Critical Fixes

  • Fix deletion after autosave restore — objects loaded from autosave are nested inside a parent Group (GLB root) and not directly in the scene; scene.remove(obj) was a silent no-op. Replaced by obj.removeFromParent() in deleteSelection() and _removeObjFromScene() — deletion now works correctly regardless of object nesting depth fix
  • Quad view labels repositioned — the 4 view labels (Perspective / Top / Front / Right) are now placed precisely in the requested corner of each quadrant following the standard Blender / DCC convention fix

📝 Details

obj.removeFromParent() · quad-label CSS · Vanilla JS

→ Open KULT


KULT v0.2.0-alpha

Released — March 27, 2026

⚡ 100% GPU-Accelerated Sculpt & Rendering

  • Incremental vertex normals — normals are now recomputed only on affected vertices instead of the full mesh on every sculpt frame; eliminates 100–500 ms stalls on meshes with 10K+ vertices new
  • GPU memory leak fixed — undo stack now disposes geometries and materials when actions drop off the 50-step limit; prevents 10–100 MB VRAM accumulation over a session fix
  • Non-blocking autosave — GLB serialization moved off the main thread; eliminates the 200–500 ms freeze every 30 s fix
  • StaticDrawUsage by default — geometries now use StaticDrawUsage at rest and switch to DynamicDrawUsage only during active sculpting; +10–20 % GPU throughput on static meshes new
  • InstancedMesh for procedural layouts — grid, line, circle and scatter generators now render via THREE.InstancedMesh; reduces draw calls from 40–80 per asset down to 1 new
  • Indexed geometry preservedtoNonIndexed() is no longer applied globally; kept only during sculpt mode, ×3 VRAM savings and −30–50 ms at import fix

⚙️ Technical

  • Three.js v0.179.1 — WebGL 2.0, SRGB, PBR
  • All existing features preserved — sculpt, build, procedural, FX pipeline, multi-format import/export
  • Lazy-loaded post-processing passes unchanged (Bloom, FXAA, Vignette, Manga, Ink)

📝 Details

Three.js 0.179.1 · InstancedMesh · StaticDrawUsage · Incremental normals · Worker autosave · Vanilla JS

→ Open KULT


ZE(B)D ONE v1.0

Released — March 27, 2026

🥁 Jungle & DnB Drum Machine — First Release

  • 15-track step sequencer — Kick, Snare, Ghost, Clap, HH-C, HH-O, Ride, Crash, Rim, Perc, Sub, Reese, Stab, Chord, Amen Break new
  • 3 pattern lengths — 16, 32 or 64 steps per pattern, switchable per session
  • 8 patterns (A→H) — Copy, paste, clear; chainable in Song Mode for full arrangement
  • BPM 60–300 with ± buttons, direct input and Tap Tempo
  • Swing — 0–80% groove control with live preview
  • MPC-style pads — 15 velocity-sensitive pads, keyboard shortcuts (Q W E R · A S D F · Z X C V · B N G), punch-in recording mode
  • 7 sound kits — Jungle (default), 808 Trap, Techno, Garage, Ragga, Industrial, Minimal — all synthesized via Web Audio API, zero samples
  • 6 built-in presets — Amen Classic, DnB Stepper, Jungle Chopper, Half-Time DnB, Roller 32, Reese Roller
  • Per-track volume & mute — Individual gain sliders and mute buttons on each track row
  • Humanize — Randomizes velocity values for organic feel
  • Metronome — Click track toggle (M key)

🎛️ FX Module

  • Reverb — Convolution reverb with Mix and Size knobs
  • Delay — Tempo-synced delay with Mix, Time and Feedback controls
  • Phaser — 4-stage allpass phaser with Mix, Rate and Depth
  • Filter — Biquad LP/HP/BP with Frequency and Resonance
  • Drive — Waveshaper distortion
  • Bitcrusher — Sample-rate crush with Mix and Bits (2–16)
  • Compressor — Master bus dynamics with Threshold and Ratio
  • Stereo Width — Mid/side width control
  • FX preset save/load/delete — custom FX chains stored in localStorage

📊 Visualizer & MIDI

  • Waveform / Spectrum / Both — Real-time canvas visualizer with 3 display modes
  • Web MIDI — Full MIDI input/output, configurable channel and per-track note map (GM Drum Map inspired)
  • Undo / Redo — 50-step history (Ctrl+Z / Ctrl+Y)

💾 Save & Export

  • Save / Load — Full session saved as .zebd JSON (patterns, FX, BPM, swing, kit)
  • Export WAV — Offline bounce of the current pattern loop to stereo WAV
  • Import Sample — Drop any audio file onto a track slot for custom one-shot playback
  • Autosave — Continuous localStorage autosave, restores on page reload

⚙️ Technical

  • 100% Web Audio API synthesis — no external samples, no CDN dependencies
  • Vanilla JS ES6 · single app.js + style.css · zero build tools
  • Dark / Light theme toggle (T key)
  • Offline-first — works fully without network after first load

📝 Details

Web Audio API · Web MIDI API · Canvas 2D · Vanilla JS · ~2 800 lines

→ Open ZE(B)D ONE


TAGZ v1.0

Released — March 27, 2026

📡 Multi-Column Social Dashboard — First Release

  • Bluesky & Mastodon & Lemmy support — follow profiles, hashtags and communities in real time, side by side in resizable columns new
  • Multi-network splash — select one or more networks (Bluesky, Mastodon, Lemmy) before searching; launches one column per selected network simultaneously new
  • Media lightbox — click any photo or video to open full-screen; keyboard navigation (← →) across media in the same post new
  • Deduplicate by author — max 2 posts per author per feed; "Show all" banner to reveal hidden posts new
  • Load More pagination — all 6 feed types (Bluesky profile & search, Mastodon profile & hashtag, Lemmy community & search) new
  • Default hashtag mode — search defaults to hashtag; prefix @ to switch to user search
  • Adaptive logo — white logo in dark mode, black logo in light mode, no flash
  • Spray canvas animation — interactive ink-spray mouse effect on the splash screen new

🎨 UI & UX

  • Full neutral color system — all blue/violet accents replaced by pure black/white palette, light and dark theme
  • Transparent search box — no background fill, 2px white border on dark mode
  • Multi-select network buttons — toggleable pills; at least one always active; searches open in parallel columns
  • Responsive columns with drag-to-resize handles

🔍 SEO & PWA

  • Full <head> — title, description, canonical, hreflang, geo, OG, Twitter Card, JSON-LD WebApplication
  • PWA manifest — installable on desktop and mobile
  • Added to sitemap.xml at priority: 0.9

⚙️ Technical

  • Vanilla JS IIFE — zero build tools, zero dependencies
  • All 6 fetch functions return {html, nextCursor} for clean pagination
  • PAGE_STATE WeakMap — per-feed pagination state
  • 100% client-side — no account required, no tracking, no cloud

📝 Details

Bluesky AT Protocol · Mastodon API · Lemmy API · Canvas 2D · Vanilla JS · PWA

→ Open TAGZ


PDF-YZ v0.2.0-alpha

Released — March 23, 2026

✂️ Visual Crop & Major UX Overhaul

  • Visual crop tool — Full-screen Photoshop-style crop overlay with 8 draggable handles, real-time mm dimensions, per-page or all-pages scope new
  • ICC color profiles — Right-side sliding drawer with CMYK (FOGRA39/47/51/52, SWOP, GRACoL, Japan Color), RGB (sRGB, Adobe RGB, Display P3), Grayscale profiles + custom .icc/.icm upload new
  • Append PDF — Open a second PDF and its pages are appended to the current document new
  • Imposition expanded — 7 layouts: 4-up, 8-up, 16-up, 20-up (5×4), 24-up (6×4), 32-up (8×4), 64-up (8×8) with SVG icons new
  • Text edit background fix — Samples background color behind text, preserves it during editing with inline span styles fix
  • Text paragraph width fix — Lines split at large horizontal gaps, textarea width clamped to page edge, tighter paragraph grouping fix

🎨 UI & UX

  • Floating search — Find & Replace moved to a bottom-left floating button (desktop), panel opens above it
  • Toolbar reorder — Export button moved to the very end of the toolbar
  • ICC drawer — Replaced dropdown panel with a full-height right-side sliding drawer with smooth CSS transition
  • Splash screen redesign — Vertical card layout, loading spinner during PDF load, fixed blank PDF creation
  • Sidebar thumbnails — Fixed-height (180px) with centered canvas, consistent aspect ratios
  • New imposition icon — Asymmetric divided rectangle for better visual recognition

⚙️ Technical

  • Single-file architecture — one index.html, now ~4800 lines
  • pdf-lib setCropBox + setMediaBox for permanent page cropping
  • PDF.js canvas rendering for crop preview at adaptive scale
  • Font detection: strip trailing numbers & PSMT suffixes from font names

📝 Details

PDF.js 4.9.155 · pdf-lib 1.17.1 · Vanilla JS · ~4800 lines

→ Open PDF-YZ


PDF-YZ v0.1.0-alpha

Released — March 22, 2026

📄 Ergonomic PDF Editor — First Release

  • PDF rendering — PDF.js 4.9.155 with high-quality canvas rendering, multi-page view and smooth zoom new
  • Text editing — Edit extracted text from PDF pages in a right-side drawer panel
  • Annotations — Draw, highlight, eraser tools with undo/redo support
  • Digital signatures — Draw or import signature, place on any page
  • Image insertion — Add images via file picker or drag & drop
  • Find & Replace — Search through extracted text with replace functionality
  • Page management — Add, delete, reorder, rotate pages, merge another PDF
  • Professional imposition — 8 layouts (2-up, 4-up, 6-up, 8-up, 9-up, N-up, booklet, step & repeat) with 10 sheet sizes, custom margins, gutters, bleed, crop marks, auto-rotate, creep compensation, page range selection new
  • Crop marks & watermark — Configurable crop marks on export, text watermark overlay
  • Export — PDF export with quality settings, image export (PNG), print support
  • Font management — Custom font loading for text elements
  • Preferences drawer — Right-side drawer with DPI, quality, PDF standard, metadata, export options
  • Keyboard shortcuts — Full shortcut set (V/T/D/H/E tools, Ctrl+S/Z/Y/F/P)
  • Dark/light theme — Auto-detected from system preferences

⚙️ Technical

  • Single-file architecture — one index.html, zero build tools
  • PDF.js 4.9.155 (ESM) for rendering, pdf-lib 1.17.1 for manipulation
  • Tailwind CSS CDN + custom CSS
  • Offline-first, no cloud, no tracking

📝 Details

PDF.js 4.9.155 · pdf-lib 1.17.1 · Tailwind CSS · Vanilla JS · ~3200 lines

→ Open PDF-YZ


ZEMULE v0.1.0-alpha

Released — March 22, 2026

🎮 Retro Multi-Console Emulator — First Release

  • Multi-console support — SNES, Mega Drive, 3DO and Neo Geo emulation directly in the browser new
  • ROM loading — Drag & drop or file picker, supports .sfc, .smc, .md, .bin, .gen, .iso, .chd, .zip, .7z formats
  • Save/Load states — Save and restore game progress at any point
  • Virtual gamepad — Touch-friendly on-screen controller for mobile devices
  • Fullscreen mode — Immersive gameplay with one click
  • CRT scanlines effect — Optional retro visual filter

📝 Details

100% browser-based · No installation · No cloud · Offline-capable

→ Open ZEMULE


CUT THE FLOW v3.5 — Powerhouse Update

Released — April 21, 2026

⚡ Three Selectable Export Encoders new

  • WebCodecs (H.264 hardware) — true GPU-accelerated MP4 muxing via MP4Box.js, 90 kHz timescale, fps-aligned keyframes, aspect-ratio contain rendering, automatic proxy → original swap before encoding
  • Transmux (MP4 preferred) — honest MediaRecorder wrapper that picks the best H.264/MP4 codec the browser exposes, with graceful WebM fallback
  • MediaRecorder (WebM) — battle-tested universal path, now with deduplicated GPU attempt logic (5 → 4 tentatives) and the user's prefs.gpuExport honored in automatic mode

🏷️ Custom Export File Name new

  • New FILE NAME field directly in the Export Complete popin — type your own name before downloading
  • Extension auto-detected and locked (.mp4 / .webm / .mkv) based on the chosen encoder/format
  • Special characters sanitized to underscores; last name remembered for the next export

🛡️ Editor Hardening

  • cutAtPlayhead() — all split durations now wrapped in quantizeTime(), eliminating float drift across undo/redo cycles fix
  • handleFiles()URL.createObjectURL wrapped in try/catch with user-facing error (Quota / Security / corrupt file) instead of killing the import loop fix
  • getMediaMetadata() — hard 10 s timeout so a broken file never hangs the import pipeline fix
  • beforeunload cleanup — saveReminderInterval and autoSaveTimer properly cleared on tab close (no more BFCache leaks) fix
  • Removed ~10 hot-path console.log calls from the import loop — cleaner devtools, faster bulk imports

📱 PWA Polish

  • Brand new install icon (phone + arrow SVG), distinct from the export upload glyph
  • Splash screen now uses live picsum.photos imagery with smooth fade — web-only, no local fallback bloat
  • 4 PWA icons regenerated (192, 512, 512-maskable, 180) from the master CUT_THE_FLOW_b.svg on a #1a1a1a background
  • Mobile toolbar cleaned up — install & export buttons visible on both desktop and mobile, redundant media button removed
  • Service Worker bumped to cuttheflow-shell-v3.5.0, 16-asset shell + fonts precached for offline launch

📝 Details

Single-page editor · Vanilla JS class CutTheFlow · Helper modules: webcodecs-export.js, transmux-export.js, export-safeguards.js · Hash-busted asset versioning (?v=<sha256-10>) · 100% client-side, no backend

→ Open CUT THE FLOW


CUT THE FLOW v2.1

Released — March 6, 2026 · Updated March 7, 2026

📱 Mobile Responsive — Complete Redesign

  • Hamburger button — fat chunky 3-bar button (26×3px each), animates to × when drawer is open, appears only on mobile (≤768px) new
  • Slide-out drawer — left-to-right panel (285px, 88vw max) with 3 sections: Édition (Undo, Redo, Text, Color Block), Format (16:9, 9:16, 1:1, 4:5), Projet (Open, Save, AI Assistant, Export) new
  • Drawer closes on backdrop tap, on button action, and automatically on window resize to desktop
  • Bottom tab bar redesigned — 5 tabs: Média, Timeline, FX, Color, Export (previously 4 tabs without FX/Color) new
  • FX panel — now opens as a mobile bottom sheet from the FX tab instead of a top overlay; 4-column grid, touch-optimized button size fix
  • Color Grading panel — accessible from dedicated Color tab in bottom bar new
  • All bottom sheets (Media, FX, Color, Properties, AI) use background: #050505 with border-top: 1px solid #111

🖤 Pure Black Theme

  • Toolbar, body, container background: #000 (previously #0a0a0a / #1a1a1a)
  • Bottom tab bar: background: #000, border-top: 1px solid #111
  • Drawer interior: #000 background, cards #0c0c0c, dividers #111
  • theme-color meta tag updated to #000000

🔧 Mobile Toolbar

  • Toolbar height: 48px on mobile (was 40px)
  • Toolbar center (all tool buttons) hidden on mobile — replaced by drawer
  • Export button always visible in top-right on mobile: white background, black icon, 36×36px
  • App logo: margin-right: auto to push export flush right

⚙️ JavaScript

  • toggleMobileDrawer() — open/close drawer with burger animation, body scroll lock
  • closeMobileDrawer() — centralized close, resets burger aria-expanded
  • mobileTab() extended — now handles fx and color cases (show/hide panels + backdrop)
  • Window resize listener: auto-closes drawer when viewport exceeds 768px

📝 Details

Vanilla JS · toggleMobileDrawer / closeMobileDrawer added · CSS mobile section overhauled (@media max-width: 768px) · Zero dependencies

→ Open CUT THE FLOW

🎬 Fade In / Fade Out System new

  • Visual Fade Panel — dedicated toolbar button (SVG envelope icon), opens a floating panel with 4 one-click presets: No Fade, Fade In, Fade Out, In & Out
  • Live SVG envelope visualizer — updates in real time as sliders move, reflects the actual fade shape (ramp up / flat / ramp down)
  • Two sliders (0–5 s, step 0.1 s) for Fade In and Fade Out durations, synced bidirectionally with the Properties panel
  • _calcFadeOpacity(clip, t) — new helper computing 0–1 opacity from clip position in timeline
  • Live preview: _applyVideoTransform() now drives element opacity via _calcFadeOpacity()
  • Fade globalAlpha applied during export in all 7 export engines — image and video clips
  • fadeIn / fadeOut values persisted in .ctf, .json and Pinata saves — confirmed safe through spread-operator audit
  • New JS methods: toggleFadePanel(), updateFadePanel(), _drawFadeEnvelope(), applyFadePreset(), setFadePanelIn(), setFadePanelOut(), _syncFadePresetHighlight()

🖼️ Image Positioning Fix fix

  • Static images dropped on the timeline were clipped to the top-left corner of the preview — #previewImage was missing from the CSS position:absolute; top:50%; left:50% centering rule
  • Conflicting inline width:100%; height:100% style on <img id="previewImage"> removed

🎞️ Export Engines — Full Parity fix

  • All 7 export engines now apply contain-fit aspect-ratio preservation, videoScale / videoPosX / videoPosY spatial transform, and fadeIn / fadeOut opacity for both image and video clips
  • Engines fixed: webcodecs-export.js, modern-export-engine-v2.js, optimized-export.js, frame-by-frame-exporter.js, simplified-export-engine.js, modern-export-engine.js, app.js main loop
  • Previously images and videos were drawn with bare ctx.drawImage(el, 0, 0, w, h) — stretched, unpositioned, no fade

🎨 UI Design Harmonization fix

  • All sliders (Fade, FX intensity, Color Grading, Properties Scale/Position/Opacity) unified to the volume-control design: rectangular thumb 8×12px, grey #555, hover #888, track #333 — no colored glows anywhere
  • Fade panel preset buttons active state changed from cyan/blue border to white/grey — matching the Save dialog card design language
  • Fade envelope SVG recolored to grey palette (#888 stroke, #555 fill)

ZORD v0.0.1-alpha

Released — February 5, 2026 · Updated February 18, 2026

🆕 New Features

  • Multi-AI assistant: Claude 3 (Anthropic), GPT-4 (OpenAI), Gemini 1.5 (Google) — use your own API keys
  • Image upload for AI vision analysis (GPT-4 Vision, Claude Vision)
  • Web3 cloud storage via IPFS / Pinata — permanent decentralized backup
  • Real-time collaboration via WebRTC (peer-to-peer, no server)
  • Multi-document manager with sidebar navigation
  • Professional DOCX export (bold, italic, underline, headings, lists, colors, images)
  • ODT import (.odt) — full OpenDocument parsing with styles, bold, italic, underline, headings, lists new
  • RTF import (.rtf) — basic rich-text format support new
  • Digital signatures — insert pre-encoded or uploaded signatures
  • Glyph panel — special characters with favorites
  • Preferences pop-in with switch toggles (dark mode, spellcheck, invisible chars, typography corrections)
  • Progressive Web App — installable on desktop & mobile

🔧 Fixes critical

  • DOCX import crash fixed: activeDocId is not defined — corrected bare variable references to __activeDocId and __documents in _importHtmlIntoNewDoc()
  • ODT import returning “file appears empty”: XML namespace bug — <office:body> and <office:text> were looked up in the wrong namespace (text: instead of office:)
  • Pagination after import: handlePagination() now runs correctly with a two-pass approach (200ms + 600ms) for large documents
  • Save/autosave moved inside pagination callback — documents are persisted after reflow, not before
  • IndexedDB persistence: fixed unconditional overwrite, beforeunload skipping saves, emergency backup premature deletion, migration data loss
  • maybeInitializeDefaultDocument() no longer wipes editor content after loading saved documents
  • IDB fallback timestamp uses epoch instead of new Date() — prevents empty doc from appearing “newer” than real data
  • Dark mode switch toggles: knob now visible in dark mode (dark:bg-neutral-900)

🎨 UI & UX

  • Real A4 pagination (210×297mm) with live page thumbnails
  • Save pop-in reordered: .zord → JSON → Pinata → .docx → .doc
  • Open pop-in: all format buttons at full opacity — no format pre-selected on open
  • Save/Open modals: consistent icon styling, neutral gray icons, Word label .doc / .docx
  • Responsive mobile toolbar + swipeable drawer + floating zoom controls
  • Light/Dark theme with smooth transitions
  • user-select: none on all modals to prevent accidental drag/import
  • Apply button closes preferences pop-in with visual feedback (processing → success → close)

📝 Details

Quill.js 1.3.6 · Tailwind CSS 3.x · Vanilla JS · Mammoth.js · JSZip · IndexedDB + localStorage dual persistence · 30-step undo history

→ Open ZORD

SUPER PRINT v0.0.4-alpha

Released — March 29, 2026

⚡ GPU Hardware Acceleration new

  • GPU detection — on opening Preferences, SuperPrint queries WebGL (WEBGL_debug_renderer_info) and displays the exact graphics card name and vendor directly inside the settings panel (e.g. NVIDIA GeForce RTX 4090, Apple M3 GPU, Intel Iris Xe). If WebGL is unavailable the panel shows a clear ✗ notice
  • Toggle in Preferences — a single checkbox "Accélération GPU" enables or disables hardware acceleration; state is persisted in localStorage (sp_gpu_enabled) and restored automatically on every launch
  • CSS layer promotion — when enabled, will-change: transform + transform: translateZ(0) + backface-visibility: hidden are applied to every Fabric.js canvas container, promoting them to dedicated GPU compositor layers; GPU handles compositing instead of the CPU
  • Fabric.js object cache — shapes, images, paths and groups gain objectCaching = true so they are bitmapped in GPU memory and only repainted when modified; text objects stay at objectCaching = false to preserve typographic sharpness at all zoom levels
  • Startup restore — if GPU mode was previously enabled, applyGpuAcceleration() fires automatically 1.5 s after page load (after Fabric canvases are ready)
  • All canvas layers re-rendered with requestRenderAll() immediately after toggling — no page reload required

�️ Asset Templates — 3 Critical Fixes fix

  • Missing images & elements in multi-page templatesaddAssetObjects was wrapping all template objects in a fabric.Group, causing image masks (applyImagePatternToRect) to compute positions relative to group center instead of the canvas; images appeared at wrong coordinates or not at all. Objects are now added individually with canvas.add() fix
  • RAM freeze on 4/8/12/16-page templates — each page build triggered a full saveState() deep-clone of all canvas objects; for a 16-page template this meant 16× the full document state was serialized in a tight loop. A window._buildingMultiPage flag now suppresses per-page saves; a single saveState() fires at the end of the build fix
  • 40+ redundant canvas redraws per template — each async image load in applyImagePatternToRect was calling canvas.requestRenderAll() immediately, causing up to 40 redraws for one 16-page template. Replaced with an 80 ms per-canvas debounced timer (canvas._spImgRenderTimer) so the canvas redraws once after all images settle fix

🔍 Find & Replace new

  • Ctrl+F — opens Find panel; Ctrl+H — opens Find & Replace panel; Escape closes it
  • Searches all pages in real time as you type; live match counter (e.g. 3 / 12)
  • ← Prev / Next → navigation jumps to the exact match across any page, scrolls to the canvas and enters text editing mode with the match selected
  • Replace one occurrence or Replace all in one click with toast feedback
  • Case-insensitive regex search across all Fabric.js textboxes in the document

🖼️ PNG / JPG Export new

  • Two new buttons in the Export modal: ↓ PNG and ↓ JPG
  • Single-page documents download directly as one file; multi-page documents are packaged into a .zip via JSZip (export-page-1.pngexport-page-N.png)
  • Respects the existing quality / resolution multiplier setting from Preferences
  • Uses Fabric.js canvas.toDataURL({ format, multiplier, quality }) — no server-side processing

🎨 Typography Styles — Update All Instances new

  • Each saved style in the Styles widget now shows a button
  • Clicking it calls updateAllStyleInstances(styleId), which finds every textbox across all pages tagged with that style (obj._appliedStyleId) and re-applies the current style properties in one pass
  • Single saveState() at the end — not one per textbox; toast reports how many objects were updated
  • The existing style widget (create, edit, apply, delete) is fully preserved and unchanged

📝 Details

Fabric.js 5.3.0 · WebGL WEBGL_debug_renderer_info · CSS compositing layer promotion · objectCaching per object type · JSZip · canvas.toDataURL() · Vanilla JS

→ Open SUPER PRINT


SUPER PRINT v0.0.3-alpha

Released — February 10, 2026 · Updated February 18, 2026

🆕 New Features

  • Scribus .sla file import beta — text frames, shapes, polylines with automatic coordinate conversion and multi-page support
  • Chemin de fer (page sorter) with drag-and-drop reordering + “Apply and close” button
  • ODT import fully rewritten — structured parsing, list/table support, inline images extraction
  • Pen Tool (Bézier) — professional vector drawing, Illustrator/Figma-style handles

🔧 Fixes critical

  • Main JS crash fixed: TypeError: Cannot read properties of undefined (reading 'forEach') — ASI ambiguity caused ['blockFill',...].forEach() to chain onto previous statement. Added defensive semicolons and null guards on getElementById
  • Removed missing mask-handle-guard.js script tag — was causing 404 error on every page load
  • PWA service worker registration guarded for file:// protocol — no more console errors when opening locally
  • Manifest CORS error fixed: <link rel="manifest"> now conditional, only loads over HTTP/HTTPS
  • Spread → Single mode: objects no longer lost — synchronous handler rewrite with safety snapshot and anti-overwrite protection
  • Master page typography now applies correctly — exitEditing() before serialization, forced visibility on textbox objects
  • ODT/DOCX import crash fixed — newPage() now creates synchronous temporary canvases instead of relying on async rendering
  • IDML import: fallback selector for cross-browser compatibility + guard bypass fix for post-import save
  • Assets panel memory leak: applyCompFormat() now performs full document purge before applying new composition
  • deepCleanupCanvas(): no longer destroys image sources (_element.src = '' removed)
  • View mode (single/spread) now persisted across all 8 save/load points
  • Page numbering settings: proper defaults for legacy projects

🎨 UI & UX

  • A4, A5, Letter + custom dimensions with configurable margins and bleed
  • Single page & Spread (double-page) display modes
  • Pasteboard (extended work area) around pages
  • Drawing tools: text, image, rectangle, circle, star, freeform, SVG import
  • Object manipulation: transform panel, proportional lock, grouping, z-index layers

📝 Details

Fabric.js 5.3.0 · jsPDF · JSZip · PDF.js · Paper.js · Mammoth.js · Hypher · ~43,690 lines JS

→ Open SUPER PRINT