From ac3a641b22656f5dcf7a17bb65573e83deaa403c Mon Sep 17 00:00:00 2001 From: Julien Calixte Date: Tue, 9 Jun 2026 14:38:40 +0200 Subject: [PATCH] fix(markdown): re-render code blocks after Shikiji loads The singleton `md` instance is mutated by `useShikiji()` asynchronously, but `content` computeds had no reactive dep on that loading, so the initial render on page reload never picked up syntax highlighting. Link-click navigation appeared to work only because Shikiji was already installed in `md` by an earlier render. --- src/hooks/useMarkdown.hook.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/hooks/useMarkdown.hook.ts b/src/hooks/useMarkdown.hook.ts index ff1b88e..223e9ac 100644 --- a/src/hooks/useMarkdown.hook.ts +++ b/src/hooks/useMarkdown.hook.ts @@ -13,7 +13,7 @@ import markdownItIframe from "markdown-it-iframe" import Shikiji from "markdown-it-shikiji" import mermaid from "mermaid" import type { LanguageRegistration } from "shikiji-core" -import { Ref, toValue } from "vue" +import { Ref, ref, toValue } from "vue" import { data } from "@/data/data" import { DataType } from "@/data/DataType.enum" @@ -142,6 +142,7 @@ const md = new MarkdownIt({ }) let shikijiPromise: Promise | null = null +const shikijiReady = ref(false) export const useShikiji = (): Promise => { if (!shikijiPromise) { @@ -168,6 +169,7 @@ export const useShikiji = (): Promise => { ] }).then((plugin) => { md.use(plugin) + shikijiReady.value = true }) } return shikijiPromise @@ -391,6 +393,11 @@ const stripFrontmatter = (content: string): string => { } const renderMarkdown = (content: string, env?: Record) => { + // Track Shikiji readiness so reactive consumers (e.g. the `content` + // computed in useFile) re-render once `useShikiji()` mutates the + // singleton `md` — otherwise the first render on page load stays + // unhighlighted because nothing else invalidates the computed. + if (content.includes("```")) void shikijiReady.value slugger.reset() return env ? md.render(content, env) : md.render(content) }