import { sanitizeHtml } from "../parse/html.ts"; import { elementFactory, requireFile, setButtonLabel } from "./dom.ts"; import { sandboxFrame } from "./frame.ts"; import type { ViewerMount } from "../types.ts"; export const mountHtml: ViewerMount = async ({ parent, file, source, button, signal }) => { const text = await requireFile(file).text(); if (signal.aborted) return; const view = parent.ownerDocument.defaultView; if (!view) throw new Error("HTML preview requires a document"); const frame = sandboxFrame(parent, { title: source.name || "HTML preview", policy: "default-src 'none'; base-uri 'none'; form-action 'none'; style-src 'unsafe-inline'; img-src data:", body: sanitizeHtml(text, view), css: "body{padding:1rem;box-sizing:border-box;font:16px/1.5 system-ui}img{max-width:100%}", }); const raw = elementFactory(parent.ownerDocument)("pre", text); let sourceView = false; const toggle = button("Source", () => { sourceView = !sourceView; setButtonLabel(toggle, sourceView ? "Preview" : "Source"); toggle.setAttribute("aria-pressed", String(sourceView)); parent.replaceChildren(sourceView ? raw : frame); }); toggle.setAttribute("aria-pressed", "false"); parent.append(frame); };