From faf129c50923f5a7918ea14b7a17aa51503992e1 Mon Sep 17 00:00:00 2001 From: Josh Knapp Date: Wed, 7 Oct 2026 13:35:15 -0700 Subject: [PATCH] fix(preview): gate head animation CSS/noscript on composed header+body+footer Preview (TopBar handlePreview + history snapshot preview) gated the animation CSS and no-JS fallback on the page body only, while the published head (generateCompiledHTML) gates on the composed header+body+footer. Add exportComposedPreviewHtml (head scanned over composed content for fonts and animation; body replaced with composed HTML + one reveal script) and use it from both Preview paths. Co-Authored-By: Claude Opus 5.5 --- craft/src/panels/topbar/TopBar.tsx | 33 ++++--------------- craft/src/utils/history-restore.test.ts | 14 ++++++++ craft/src/utils/history-restore.ts | 15 +++------ .../src/utils/html-export.head-parity.test.ts | 33 +++++++++++++++++++ craft/src/utils/html-export.ts | 28 +++++++++++++++- 5 files changed, 86 insertions(+), 37 deletions(-) diff --git a/craft/src/panels/topbar/TopBar.tsx b/craft/src/panels/topbar/TopBar.tsx index 11a11a3..9a3d5e0 100644 --- a/craft/src/panels/topbar/TopBar.tsx +++ b/craft/src/panels/topbar/TopBar.tsx @@ -274,7 +274,7 @@ export const TopBar: React.FC = ({ showGuides, onToggleGuides }) => const win = window.open('', '_blank'); try { const serialized = query.serialize(); - Promise.all([import('../../utils/html-export'), import('../../utils/sandboxed-preview')]).then(([{ exportToHtml, exportBodyHtml, buildAnimationScript }, { openSandboxedPreview }]) => { + Promise.all([import('../../utils/html-export'), import('../../utils/sandboxed-preview')]).then(([{ exportComposedPreviewHtml, exportBodyHtml }, { openSandboxedPreview }]) => { // Get header HTML let headerHtml = ''; try { @@ -295,18 +295,11 @@ export const TopBar: React.FC = ({ showGuides, onToggleGuides }) => } } catch (e) { console.warn('Footer export failed:', e); } - // Compose full page: header + body + footer. `handlePreview` below - // replaces the ENTIRE wrapped-doc `` inner (including the - // in-body reveal `