mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-11 21:57:14 +03:00
CSP meta-tag auto-patch (live-inject.mjs) When the user's HTML carries <meta http-equiv="Content-Security-Policy">, the cross-origin load of /live.js and the SSE/POST stream back to localhost:PORT are both blocked. Insert: append http://localhost:PORT to script-src and connect-src, plus blob: to img-src (the shader overlay), stash the original content value as a base64 data-impeccable-csp-original attribute. Remove: decode the marker and restore the original verbatim. Header-based CSP (Next/Nuxt/SvelteKit configs) intentionally untouched — those flow through the existing detect-csp.mjs reference path. JSX-aware accept (live-accept.mjs) - Carbonize stash now emits style={{ display: 'contents' }} for JSX targets instead of style="display: contents" (HTML form). React 19 was throwing "Failed to set indexed property [0] on CSSStyleDeclaration" on the string form because it iterated chars onto the style object. - extractCss now matches </style> anywhere on a line, not just at line start. Previously a JSX template-literal close like `}</style> would leak the backtick + brace into the carbonize stash, breaking JSX. - Carbonize stash wraps the CSS body in {` … `} for JSX targets so curly braces in CSS rules don't get parsed as JSX expressions. Conditional-render UX (live-browser.js) - Drop the 2s-then-window.location.reload() fallback in the SSE 'done' handler. That reload was masking a real failure mode: when the picked element lives inside conditional render (closed modal, hidden tab, other-route), Fast Refresh remounts the parent and state resets, so the variants land in source but never reach the DOM. Reload also reset state to default, leaving the user stuck. - Replace with a 6s contextual toast: "Variants ready. If the picked element isn't visible, retrace the path that revealed it — they'll appear automatically." The MutationObserver stays armed and auto-transitions to CYCLING once the variants finally mount. - Pick-time heads-up: when the picked element is inside [role="dialog"], [data-state="open"], a multi-tab tabpanel, or an aria-expanded collapsible, fire a brief upfront toast so the user knows what to expect if state resets during generation. Hydration race (live-browser.js) - SvelteKit (and any framework that hydrates after HTML parse) was failing post-Vite-page-reload because init() ran resumeSession() before the variant wrapper hydrated into the DOM. The OLD reload fallback masked this by triggering a second reload whose hydration benefited from warm cache. Without that, fix it properly: install a scout MutationObserver in init() that retries resumeSession() once [data-impeccable-variants] lands in the DOM. Shader overlay (live-browser.js) - WebGL fallback in showShaderOverlay used Object.assign(img.style, canvas.style, …), which throws on modern Chromium because CSSStyleDeclaration's indexed properties are not writable. Use cssText to copy positioning instead. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>