Fix production dynamic-page modules and trusted email previews
This commit is contained in:
1 parent
bccbf1f4c9
commit
646814d6df
9 files changed
+149
-9
No files matched your search
@@ -10,3 +10,4 @@ export * from "./image-preview.ts";
|
||||
export * from "./announcements.ts";
|
||||
export * from "./kit.ts";
|
||||
export * from "./source-editor.ts";
|
||||
export { setBuilderPreview, builderPreviewHTML } from "./preview-html.ts";
|
||||
@@ -1,8 +1,9 @@
|
||||
import { builderPreviewHTML } from "./preview-html.ts";
|
||||
/** Updates the existing sandbox document without navigating/reloading its iframe. */
|
||||
export function updateBuilderCanvas(frame: HTMLIFrameElement, html: string): void {
|
||||
const canvas = frame.contentDocument;
|
||||
if (!canvas?.body) return;
|
||||
const parsed = new DOMParser().parseFromString(html, "text/html");
|
||||
const parsed = new DOMParser().parseFromString(builderPreviewHTML(html, frame.ownerDocument), "text/html");
|
||||
const scrolling = canvas.scrollingElement;
|
||||
const top = scrolling?.scrollTop ?? 0, left = scrolling?.scrollLeft ?? 0;
|
||||
canvas.head.replaceChildren(...Array.from(parsed.head.childNodes).map(node => canvas.importNode(node, true)));
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import createDOMPurify from "dompurify";
|
||||
|
||||
const sanitizers = new WeakMap<object, ReturnType<typeof createDOMPurify>>();
|
||||
/** Sanitize generated previews in the sink's realm, including Trusted Types. */
|
||||
export function builderPreviewHTML(html: string, doc: Document = document): string {
|
||||
const realm = doc.defaultView;
|
||||
if (!realm) throw new Error("Preview document has no browser realm");
|
||||
let sanitizer = sanitizers.get(realm);
|
||||
if (!sanitizer) {
|
||||
sanitizer = createDOMPurify(realm);
|
||||
sanitizers.set(realm, sanitizer);
|
||||
}
|
||||
return sanitizer.sanitize(html, {
|
||||
WHOLE_DOCUMENT: true,
|
||||
RETURN_TRUSTED_TYPE: true,
|
||||
FORBID_TAGS: ["script", "iframe", "object", "embed", "form", "base"],
|
||||
}) as unknown as string;
|
||||
}
|
||||
|
||||
/** Only script-free sandboxed frames may receive generated email previews. */
|
||||
export function setBuilderPreview(frame: HTMLIFrameElement, html: string): void {
|
||||
if (!frame.hasAttribute("sandbox") || frame.sandbox.contains("allow-scripts"))
|
||||
throw new Error("Email previews require a script-free sandbox");
|
||||
frame.srcdoc = builderPreviewHTML(html, frame.ownerDocument);
|
||||
}
|
||||
Reference in new issue
Block a user