Zigmoon Apps

Releases & Changelog

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