Each component defined a .craft.related.settings panel that was never
rendered -- the right panel renders only GuidedStyles (per-type
*StylePanel components), never .related.settings. Removed all dead
settings components across every component, their settings-only helpers
(including the dead uploadToWhp/showBrowser/handleBrowse asset-browse
blocks in Logo/Navbar/VideoBlock/FeaturesGrid, and CtasEditor in
_cta-helpers), and dropped the now-empty related keys. Render output,
.craft props/rules, and toHtml statics are unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Every user-controlled URL emitted by a component's static toHtml (href,
src, action, and CSS url()) now runs through escapeAttr(safeUrl(...))
before hitting the exported HTML string, closing the XSS gaps flagged
in the A2 review (PricingTable buttonHref was fully unescaped, Gallery/
HeroSimple/ImageBlock/VideoBlock/etc. lacked scheme filtering) plus a
few more found via a grep sweep of href=/src=/action=/url( inside
toHtml template strings: MapEmbed's iframe src and the shared
form-relay-wiring fallback form action (a javascript: form action
executes on submit).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rebuilt the visual site builder from scratch using Craft.js, React 18,
and TypeScript. The new editor renders directly in the DOM (no iframe),
supports 40+ components, multi-page with shared header/footer, 16
templates, full-spectrum color/gradient controls, custom head code
injection, save/publish workflow, and auto-save.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>