2 Commits

Author SHA1 Message Date
fb70b39173 Open embed route to all origins, add embed snippet UI, enable LTspice
frame-ancestors * for /embed/* routes so any site can iframe notebooks.
Remove postMessage origin allowlist (theme toggle is cosmetic-only).
Add EmbedDialog popover with copy-paste iframe snippet and theme picker.
Enable ltspice in the engine dropdown now that the backend supports it.
2026-03-05 15:41:51 -07:00
3f3ca58521 Add embeddable notebook viewer for Mims library integration
New /embed/[id] route renders notebooks in a read-only, chromeless
layout for iframe embedding. Supports light/dark themes via URL
param and postMessage from the parent window.

- EmbedLayout: minimal HTML shell, no navbar/footer
- EmbedViewer: fetches notebook, runs simulations, syncs theme
- EmbedCell: read-only markdown + SPICE cell renderer
- SpiceEditor: added readOnly prop (EditorState.readOnly + editable.of)
- embed-theme.css: light mode CSS variable overrides
- Astro middleware: CSP frame-ancestors on /embed/* routes
- Backend: env-configurable CORS origins, CSP header middleware

Security hardening from review:
- postMessage origin validation (ALLOWED_MESSAGE_ORIGINS)
- markdown XSS fix: isSafeUrl() blocks javascript: URIs in links
- escapeHtml now covers single quotes
- Notebook ID validated against /^[a-zA-Z0-9_-]+$/
- Theme param normalized at Astro boundary
- classList.remove/add instead of className stomping
2026-02-13 15:46:37 -07:00