From 3a415cc5e82ff966dc0c890a25819318faf34b5a Mon Sep 17 00:00:00 2001 From: WolfieLeader Date: Tue, 17 Mar 2026 14:21:14 +0200 Subject: [PATCH 1/4] fix: code blocks invisible in dark mode due to CSS/class mismatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The initial render used className "shiki github-light dark:aurora-x". In dark mode, `html.dark .shiki.github-light { display: none }` hid the element. Since dark:aurora-x is not a valid Tailwind utility, the aurora-x class was never applied — leaving code blocks permanently hidden when Shiki's async highlighting failed to replace them. - Use Tailwind dark: variants for proper light/dark initial render - Add try/catch to Shiki effect to prevent silent failures - Add cleanup flag to prevent state updates after unmount Fixes #761, fixes #760, fixes #759 --- src/components/markdown/CodeBlock.tsx | 83 ++++++++++++++++----------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/src/components/markdown/CodeBlock.tsx b/src/components/markdown/CodeBlock.tsx index db753985..87797e9d 100644 --- a/src/components/markdown/CodeBlock.tsx +++ b/src/components/markdown/CodeBlock.tsx @@ -155,7 +155,10 @@ export function CodeBlock({ const code = children?.props.children const [codeElement, setCodeElement] = React.useState( -
+    
       {lang === 'mermaid' ?  : code}
     
, ) @@ -163,48 +166,58 @@ export function CodeBlock({ React[ typeof document !== 'undefined' ? 'useLayoutEffect' : 'useEffect' ](() => { + let cancelled = false ;(async () => { - const themes = ['github-light', 'aurora-x'] - const langStr = lang || 'plaintext' + try { + const themes = ['github-light', 'aurora-x'] + const langStr = lang || 'plaintext' - const { highlighter, effectiveLang } = await getHighlighter(langStr) - // Trim trailing newlines to prevent empty lines at end of code block - const trimmedCode = (code || '').trimEnd() + const { highlighter, effectiveLang } = await getHighlighter(langStr) + // Trim trailing newlines to prevent empty lines at end of code block + const trimmedCode = (code || '').trimEnd() - const htmls = await Promise.all( - themes.map(async (theme) => { - const output = highlighter.codeToHtml(trimmedCode, { - lang: effectiveLang, - theme, - transformers: [transformerNotationDiff()], - }) + const htmls = await Promise.all( + themes.map(async (theme) => { + const output = highlighter.codeToHtml(trimmedCode, { + lang: effectiveLang, + theme, + transformers: [transformerNotationDiff()], + }) - if (lang === 'mermaid') { - const preAttributes = extractPreAttributes(output) - let svgHtml = genSvgMap.get(trimmedCode) - if (!svgHtml) { - const mermaid = await getMermaid() - const { svg } = await mermaid.render('foo', trimmedCode) - genSvgMap.set(trimmedCode, svg) - svgHtml = svg + if (lang === 'mermaid') { + const preAttributes = extractPreAttributes(output) + let svgHtml = genSvgMap.get(trimmedCode) + if (!svgHtml) { + const mermaid = await getMermaid() + const { svg } = await mermaid.render('foo', trimmedCode) + genSvgMap.set(trimmedCode, svg) + svgHtml = svg + } + return `
${svgHtml}
` } - return `
${svgHtml}
` - } - return output - }), - ) + return output + }), + ) - setCodeElement( -
pre]:h-full [&>pre]:rounded-none' : '', - )} - dangerouslySetInnerHTML={{ __html: htmls.join('') }} - ref={ref} - />, - ) + if (!cancelled) { + setCodeElement( +
pre]:h-full [&>pre]:rounded-none' : '', + )} + dangerouslySetInnerHTML={{ __html: htmls.join('') }} + ref={ref} + />, + ) + } + } catch (err) { + console.warn('Shiki highlighting failed:', err) + } })() + return () => { + cancelled = true + } }, [code, lang]) return ( From 072f8dcc06409498a29e2ab4bb8b71f8d0f1eaf0 Mon Sep 17 00:00:00 2001 From: WolfieLeader Date: Tue, 17 Mar 2026 14:21:22 +0200 Subject: [PATCH 2/4] chore: remove unused PACKAGE_MANAGERS import --- src/components/CopyPageDropdown.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/CopyPageDropdown.tsx b/src/components/CopyPageDropdown.tsx index b9e5e0c4..8f4cdf73 100644 --- a/src/components/CopyPageDropdown.tsx +++ b/src/components/CopyPageDropdown.tsx @@ -10,10 +10,7 @@ import { DropdownContent, DropdownItem, } from './Dropdown' -import { - getPackageManager, - PACKAGE_MANAGERS, -} from '~/utils/markdown/installCommand' +import { getPackageManager } from '~/utils/markdown/installCommand' // Markdown icon component matching the screenshot function MarkdownIcon({ className }: { className?: string }) { From 55a2054f2ae60c48c70acd253f73ebd4ed0f138c Mon Sep 17 00:00:00 2001 From: WolfieLeader Date: Tue, 17 Mar 2026 14:31:49 +0200 Subject: [PATCH 3/4] fix: address review feedback in CodeBlock - Add null safety for preAttributes.class in mermaid rendering - Add isEmbedded to effect dependency array --- src/components/markdown/CodeBlock.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/markdown/CodeBlock.tsx b/src/components/markdown/CodeBlock.tsx index 87797e9d..db3a67bf 100644 --- a/src/components/markdown/CodeBlock.tsx +++ b/src/components/markdown/CodeBlock.tsx @@ -193,7 +193,7 @@ export function CodeBlock({ genSvgMap.set(trimmedCode, svg) svgHtml = svg } - return `
${svgHtml}
` + return `
${svgHtml}
` } return output @@ -218,7 +218,7 @@ export function CodeBlock({ return () => { cancelled = true } - }, [code, lang]) + }, [code, lang, isEmbedded]) return (
Date: Tue, 17 Mar 2026 14:32:32 +0200 Subject: [PATCH 4/4] refactor: use twMerge for mermaid div class composition --- src/components/markdown/CodeBlock.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/markdown/CodeBlock.tsx b/src/components/markdown/CodeBlock.tsx index db3a67bf..2bbaba8c 100644 --- a/src/components/markdown/CodeBlock.tsx +++ b/src/components/markdown/CodeBlock.tsx @@ -193,7 +193,8 @@ export function CodeBlock({ genSvgMap.set(trimmedCode, svg) svgHtml = svg } - return `
${svgHtml}
` + const cls = twMerge(preAttributes.class, 'py-4 bg-neutral-50') + return `
${svgHtml}
` } return output