Reuse preview sanitizer across client page bundles
This commit is contained in:
1 parent
646814d6df
commit
a023049431
4 files changed
+20
-5
No files matched your search
@@ -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": {
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import createDOMPurify from "dompurify";
|
||||
|
||||
const sanitizers = new WeakMap<object, ReturnType<typeof createDOMPurify>>();
|
||||
// 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<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);
|
||||
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,
|
||||
|
||||
@@ -11,3 +11,15 @@ test("preview sanitization preserves email layout and editor markers but removes
|
||||
expect(result).not.toMatch(/onerror|javascript:|<script|<iframe/);
|
||||
window.close();
|
||||
});
|
||||
|
||||
test("separately bundled preview modules reuse one realm sanitizer", async () => {
|
||||
const { window } = new JSDOM("");
|
||||
const doc = window.document as unknown as Document;
|
||||
builderPreviewHTML("<p>First page</p>", 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("<p>Second page</p>", doc))).toContain("Second page");
|
||||
expect((window as any)[key]).toBe(first);
|
||||
window.close();
|
||||
});
|
||||
Reference in new issue
Block a user