Render Mermaid diagrams and worktree images in agent Markdown
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import { errorText, h } from "./dom.js";
|
||||
|
||||
type Mermaid = {
|
||||
initialize(config: Record<string, unknown>): void;
|
||||
render(id: string, text: string): Promise<{ svg: string }>;
|
||||
};
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
mermaid?: Mermaid;
|
||||
}
|
||||
}
|
||||
|
||||
let loading: Promise<Mermaid> | undefined;
|
||||
let next = 0;
|
||||
|
||||
function load(): Promise<Mermaid> {
|
||||
loading ??= new Promise((resolve, reject) => {
|
||||
const script = h("script", { src: "/vendor/mermaid.min.js" });
|
||||
script.onload = () => {
|
||||
const m = window.mermaid!;
|
||||
const css = getComputedStyle(document.documentElement);
|
||||
const v = (name: string) => css.getPropertyValue(name).trim();
|
||||
m.initialize({
|
||||
startOnLoad: false,
|
||||
securityLevel: "strict",
|
||||
suppressErrorRendering: true,
|
||||
theme: "base",
|
||||
fontFamily: v("--font"),
|
||||
themeVariables: {
|
||||
fontFamily: v("--font"),
|
||||
fontSize: "13px",
|
||||
background: v("--bg"),
|
||||
primaryColor: v("--surface"),
|
||||
primaryTextColor: v("--text"),
|
||||
primaryBorderColor: v("--border"),
|
||||
secondaryColor: v("--accent-tint"),
|
||||
tertiaryColor: v("--raised"),
|
||||
lineColor: v("--muted"),
|
||||
textColor: v("--text"),
|
||||
noteBkgColor: v("--warn-tint"),
|
||||
noteTextColor: v("--text"),
|
||||
noteBorderColor: v("--border"),
|
||||
},
|
||||
});
|
||||
resolve(m);
|
||||
};
|
||||
script.onerror = () => reject(new Error("couldn't load /vendor/mermaid.min.js"));
|
||||
document.head.append(script);
|
||||
});
|
||||
return loading;
|
||||
}
|
||||
|
||||
export function diagram(src: string): HTMLElement {
|
||||
const el = h("div", { class: "mermaid-diagram" }, h("pre", { class: "mermaid-source" }, src));
|
||||
void render(el, src);
|
||||
return el;
|
||||
}
|
||||
|
||||
async function render(el: HTMLElement, src: string) {
|
||||
try {
|
||||
const m = await load();
|
||||
const { svg } = await m.render(`mermaid-${next++}`, src);
|
||||
el.innerHTML = svg;
|
||||
} catch (err) {
|
||||
el.append(h("div", { class: "mermaid-error" }, `diagram not rendered: ${errorText(err)}`));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user