Files
remanso/src/hooks/useMarkdownPostRender.hook.ts
Julien Calixte 9d1b6552cb feat(markdown): add hover download buttons on rendered SVGs
Attach SVG and PNG (×2) download buttons to every rendered SVG (TikZ,
Mermaid, …) once post-render finishes. Exports always use the original
colors with a white background baked in, regardless of theme.
2026-05-16 12:17:04 +02:00

65 lines
1.5 KiB
TypeScript

import { nextTick, type Ref, toValue, watch } from "vue"
import { useImages } from "@/hooks/useImages.hook"
import {
runMermaid,
runTikz,
useShikiji
} from "@/hooks/useMarkdown.hook"
import { attachSvgDownloads } from "@/utils/svgDownload"
interface MarkdownPostRenderOptions {
onReady?: () => void
tikz?: boolean
mermaid?: () => boolean
shikiji?: () => boolean
images?: () => string | null | undefined
triggers?: Ref<unknown>[]
}
export const useMarkdownPostRender = (
contentRef: Ref<unknown>,
scopeSelector: () => string,
options: MarkdownPostRenderOptions = {}
) => {
const sources = [contentRef, ...(options.triggers ?? [])]
watch(
sources,
async () => {
if (!toValue(contentRef)) return
await nextTick()
options.onReady?.()
const scope = scopeSelector()
const wantsTikz = !!options.tikz
const wantsMermaid = !!options.mermaid?.()
const renderJobs: Promise<unknown>[] = []
if (wantsTikz) {
renderJobs.push(runTikz(`${scope} .tikz`))
}
if (wantsMermaid) {
renderJobs.push(runMermaid(`${scope} .mermaid`))
}
if (options.shikiji?.()) {
void useShikiji()
}
const imagesSha = options.images?.()
if (imagesSha) {
useImages(imagesSha)
}
if (wantsTikz || wantsMermaid) {
await Promise.allSettled(renderJobs)
await nextTick()
attachSvgDownloads(document.querySelector(scope))
}
},
{ immediate: true }
)
}