From 7790d1821cba8ec5f2cf701cf3c520cef88f260a Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 30 Jan 2026 09:54:10 +0000 Subject: [PATCH] fix: restore syntax highlighting colors Revert the CSS class-based approach which was failing to classify tokens. Instead, keep Shiki's inline styles from the theme and only remove backgrounds to let CSS handle those. The theme colors now provide syntax highlighting directly. --- src/lib/shiki.ts | 52 ++++++++---------------------------------------- 1 file changed, 8 insertions(+), 44 deletions(-) diff --git a/src/lib/shiki.ts b/src/lib/shiki.ts index a044b0b..71d4969 100644 --- a/src/lib/shiki.ts +++ b/src/lib/shiki.ts @@ -12,48 +12,11 @@ const loadedLanguages = new Set(); const failedLanguages = new Set(); /** - * Transformer that adds CSS classes based on token scopes - * This allows us to style tokens with CSS variables instead of inline colors + * Transformer that cleans up Shiki output for our styling + * Keeps inline colors from the theme but removes backgrounds */ -const classTransformer: ShikiTransformer = { - name: "class-transformer", - span(node) { - // Map inline colors to semantic CSS classes - // This allows us to style tokens with CSS variables instead of hardcoded colors - const style = node.properties?.style as string | undefined; - if (!style) return; - - // Remove inline style and add class based on token type - delete node.properties.style; - - // Add base class - node.properties.className = node.properties.className || []; - const classes = node.properties.className as string[]; - classes.push("shiki-token"); - - // Detect token type from the original style color - // These colors come from our theme definitions - if (style.includes("#8b949e") || style.includes("comment")) { - classes.push("shiki-comment"); - } else if (style.includes("#a5d6ff") || style.includes("string")) { - classes.push("shiki-string"); - } else if (style.includes("#79c0ff") || style.includes("constant")) { - classes.push("shiki-constant"); - } else if (style.includes("#7ee787") || style.includes("tag")) { - classes.push("shiki-tag"); - } else if (style.includes("#ffa198") || style.includes("deleted")) { - classes.push("shiki-deleted"); - } else if ( - style.includes("#f0f0f0") || - style.includes("#e6edf3") || - style.includes("keyword") || - style.includes("function") - ) { - classes.push("shiki-keyword"); - } else if (style.includes("#c9d1d9") || style.includes("punctuation")) { - classes.push("shiki-punctuation"); - } - }, +const cleanupTransformer: ShikiTransformer = { + name: "cleanup-transformer", pre(node) { // Remove background color from pre, let CSS handle it if (node.properties?.style) { @@ -62,9 +25,10 @@ const classTransformer: ShikiTransformer = { } }, code(node) { - // Remove color from code element + // Remove background from code element, keep color if (node.properties?.style) { - delete node.properties.style; + const style = node.properties.style as string; + node.properties.style = style.replace(/background-color:[^;]+;?/g, ""); } }, }; @@ -408,7 +372,7 @@ export async function highlightCode( return hl.codeToHtml(code, { lang: effectiveLang, theme: "grimoire", - transformers: [classTransformer], + transformers: [cleanupTransformer], }); }