// Vue composable that keeps every markdown viewer in sync with the // mermaid runner. The viewer passes its `
` // container ref and the reactive source; this hook schedules a // `nextTick` → `renderMermaidNodes` on mount and whenever the source // changes, so newly-injected placeholders become SVG diagrams without // each viewer re-implementing the plumbing. import { onMounted, watch, nextTick, type Ref } from "vue"; import { useI18n } from "vue-i18n"; import { renderMermaidNodes, type MermaidRenderLabels } from "@mulmoclaude/markdown-utils/markdown/mermaidRender"; export function useMermaidRenderer(containerRef: Ref, sourceRef: Ref): void { const { t } = useI18n(); // Resolve the two error-surface keys through the live i18n // instance so the messages track locale changes. `t` is stable // across the composable's lifetime, so building the labels once // here (rather than re-building on every render) is safe. const labels: MermaidRenderLabels = { loadFailed: (error) => t("markdownMermaid.loadFailed", { error }), renderFailed: (error) => t("markdownMermaid.renderFailed", { error }), }; const run = async (): Promise => { await nextTick(); await renderMermaidNodes(containerRef.value ?? null, labels); }; onMounted(() => { void run(); }); // `immediate: false` — `onMounted` already covers the initial // render. `flush: "post"` fires after Vue applies the DOM patch that // v-html triggers, so placeholder nodes exist when we scan for them. watch(sourceRef, () => void run(), { flush: "post" }); }