feat(f7): sealed webview asset + esbuild preview bundle (#21)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* F7 preview webview client (sealed sandbox, INV-21). Receives annotated HTML
|
||||
* from the extension host and swaps it in; runs mermaid over `.mermaid` blocks
|
||||
* (mermaid needs a DOM, so it runs here, not in the host). Bundled by esbuild as
|
||||
* a standalone IIFE → out/media/preview.js, so mermaid never enters the host
|
||||
* bundle. No network, no LLM.
|
||||
*/
|
||||
import mermaid from "mermaid";
|
||||
// Imported so esbuild emits the sibling out/media/preview.css (the controller
|
||||
// links it into the sealed shell via asWebviewUri).
|
||||
import "./preview.css";
|
||||
|
||||
interface RenderMessage {
|
||||
type: "render";
|
||||
html: string;
|
||||
epoch: string;
|
||||
summary: { added: number; removed: number; changed: number };
|
||||
}
|
||||
|
||||
const body = document.getElementById("cw-body")!;
|
||||
const header = document.getElementById("cw-epoch")!;
|
||||
const summary = document.getElementById("cw-summary")!;
|
||||
|
||||
function themeFor(): "dark" | "default" {
|
||||
return document.body.classList.contains("vscode-dark") ||
|
||||
document.body.classList.contains("vscode-high-contrast")
|
||||
? "dark"
|
||||
: "default";
|
||||
}
|
||||
|
||||
async function renderMermaid(): Promise<void> {
|
||||
const nodes = Array.from(body.querySelectorAll<HTMLElement>("pre.mermaid"));
|
||||
if (nodes.length === 0) return;
|
||||
mermaid.initialize({ startOnLoad: false, theme: themeFor(), securityLevel: "strict" });
|
||||
try {
|
||||
await mermaid.run({ nodes });
|
||||
} catch {
|
||||
// mermaid.run already marks failed nodes; ensure a visible chip per failure.
|
||||
for (const n of nodes) {
|
||||
if (!n.querySelector("svg")) n.setAttribute("data-cw-error", "true");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("message", (event: MessageEvent<RenderMessage>) => {
|
||||
const msg = event.data;
|
||||
if (msg?.type !== "render") return;
|
||||
body.innerHTML = msg.html;
|
||||
header.textContent = `Track changes since ${msg.epoch}`;
|
||||
summary.innerHTML =
|
||||
`<span class="cw-add">+${msg.summary.added + msg.summary.changed}</span> ` +
|
||||
`<span class="cw-del">−${msg.summary.removed + msg.summary.changed}</span>`;
|
||||
void renderMermaid();
|
||||
});
|
||||
Reference in New Issue
Block a user