diff --git a/src/blocks/GenericEmbed/Component.tsx b/src/blocks/GenericEmbed/Component.tsx index 83c315b1..0fe2d14d 100644 --- a/src/blocks/GenericEmbed/Component.tsx +++ b/src/blocks/GenericEmbed/Component.tsx @@ -20,7 +20,7 @@ export const GenericEmbedBlockComponent = ({ className, isLexical = true, }: Props) => { - const [sanitizedHtml, setSanitizedHtml] = useState(null) + const [blobUrl, setBlobUrl] = useState(null) const bgColorClass = `bg-${backgroundColor}` const textColor = getTextColorFromBgColor(backgroundColor) @@ -29,7 +29,7 @@ export const GenericEmbedBlockComponent = ({ if (typeof window === 'undefined' || !html) return // Normalize problematic quotes that are parsed incorrectly by DOMParser and DOMPurify - const normalizedHTML = html.replaceAll('"', '"').replaceAll('"', '"') + const normalizedHTML = html.replaceAll('\u201C', '"').replaceAll('\u201D', '"') const sanitized = DOMPurify.sanitize(normalizedHTML, { ADD_TAGS: ['iframe', 'script', 'style', 'dbox-widget'], @@ -67,10 +67,17 @@ export const GenericEmbedBlockComponent = ({ ` - setSanitizedHtml(sanitized + styleOverrides) + // Use a blob URL instead of srcDoc because Chromium doesn't re-execute + // scripts in srcDoc iframes after SPA client-side navigation. + const fullHtml = `${sanitized}${styleOverrides}` + const blob = new Blob([fullHtml], { type: 'text/html' }) + const url = URL.createObjectURL(blob) + setBlobUrl(url) + + return () => URL.revokeObjectURL(url) }, [html]) - if (sanitizedHtml === null) return null + if (blobUrl === null) return null return (
@@ -87,10 +94,10 @@ export const GenericEmbedBlockComponent = ({