From a023049431e76288e2426e6eafd6af83b3eb1829 Mon Sep 17 00:00:00 2001 From: Ajay Ghanwat Date: Thu, 1 Oct 2026 20:19:08 +0530 Subject: [PATCH] Reuse preview sanitizer across client page bundles --- bun.lock | 2 +- packages/block-editor/package.json | 2 +- packages/block-editor/src/preview-html.ts | 9 ++++++--- packages/block-editor/test/preview-html.test.ts | 12 ++++++++++++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/bun.lock b/bun.lock index 33ac0016..40981e57 100644 --- a/bun.lock +++ b/bun.lock @@ -272,7 +272,7 @@ }, "packages/block-editor": { "name": "@wrnexus/block-editor", - "version": "0.1.19", + "version": "0.1.20", "dependencies": { "@codemirror/lang-xml": "6.1.0", "@codemirror/language": "6.12.4", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 2fb0cf65..b3bf6abc 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/block-editor", - "version": "0.1.19", + "version": "0.1.20", "type": "module", "description": "Hydrated accessible editor runtime for WRNexus block documents.", "exports": { diff --git a/packages/block-editor/src/preview-html.ts b/packages/block-editor/src/preview-html.ts index e70dab1b..d382b643 100644 --- a/packages/block-editor/src/preview-html.ts +++ b/packages/block-editor/src/preview-html.ts @@ -1,14 +1,17 @@ import createDOMPurify from "dompurify"; -const sanitizers = new WeakMap>(); +// Page modules are bundled separately. Keep the sanitizer on the realm so SPA +// navigation reuses its Trusted Types policy instead of creating it twice. +const sanitizerKey = Symbol.for("wrnexus.block-editor.preview-sanitizer"); +type PreviewRealm = Window & { [sanitizerKey]?: ReturnType }; /** 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); + let sanitizer = (realm as PreviewRealm)[sanitizerKey]; if (!sanitizer) { sanitizer = createDOMPurify(realm); - sanitizers.set(realm, sanitizer); + Object.defineProperty(realm, sanitizerKey, { value: sanitizer }); } return sanitizer.sanitize(html, { WHOLE_DOCUMENT: true, diff --git a/packages/block-editor/test/preview-html.test.ts b/packages/block-editor/test/preview-html.test.ts index fe15f96b..a2dca771 100644 --- a/packages/block-editor/test/preview-html.test.ts +++ b/packages/block-editor/test/preview-html.test.ts @@ -11,3 +11,15 @@ test("preview sanitization preserves email layout and editor markers but removes expect(result).not.toMatch(/onerror|javascript:| { + const { window } = new JSDOM(""); + const doc = window.document as unknown as Document; + builderPreviewHTML("

First page

", doc); + const key = Symbol.for("wrnexus.block-editor.preview-sanitizer"); + const first = (window as any)[key]; + const secondModule = await import("../src/preview-html.ts?second-page"); + expect(String(secondModule.builderPreviewHTML("

Second page

", doc))).toContain("Second page"); + expect((window as any)[key]).toBe(first); + window.close(); +});