11import type * as React from "react" ;
2- import { cache } from "react" ;
3- import { createHighlighter } from "shiki" ;
2+ import { createHighlighterCoreSync } from "shiki/core" ;
3+ import { createJavaScriptRegexEngine } from "shiki/engine/javascript" ;
4+ import css from "shiki/langs/css.mjs" ;
5+ import html from "shiki/langs/html.mjs" ;
6+ import json from "shiki/langs/json.mjs" ;
7+ import jsx from "shiki/langs/jsx.mjs" ;
8+ import markdown from "shiki/langs/markdown.mjs" ;
9+ import tsx from "shiki/langs/tsx.mjs" ;
10+ import githubLight from "shiki/themes/github-light.mjs" ;
11+ import vesper from "shiki/themes/vesper.mjs" ;
412import { SciFiCard } from "@/components/scifi-card" ;
513import { cn } from "@/lib/utils" ;
614import { CopyButton } from "./copy-button" ;
@@ -12,50 +20,27 @@ interface CodeBlockProps extends React.ComponentProps<"div"> {
1220 children ?: React . ReactNode ;
1321}
1422
15- const getShikiHighlighter = cache (
16- async ( ) =>
17- await createHighlighter ( {
18- themes : [ "vesper" , "github-light" ] ,
19- langs : [
20- "typescript" ,
21- "javascript" ,
22- "tsx" ,
23- "jsx" ,
24- "bash" ,
25- "shell" ,
26- "sh" ,
27- "html" ,
28- "css" ,
29- "json" ,
30- "python" ,
31- "go" ,
32- "rust" ,
33- "sql" ,
34- "yaml" ,
35- "xml" ,
36- "markdown" ,
37- "plaintext" ,
38- ] ,
39- } )
40- ) ;
23+ const highlighter = createHighlighterCoreSync ( {
24+ themes : [ vesper , githubLight ] ,
25+ langs : [ tsx , jsx , html , css , json , markdown ] ,
26+ engine : createJavaScriptRegexEngine ( ) ,
27+ } ) ;
4128
42- async function CodeBlock ( {
29+ function CodeBlock ( {
4330 children,
4431 className,
4532 language = "text" ,
4633 filename,
4734 code,
4835} : CodeBlockProps ) {
49- const content = ( code || children ) as string ;
36+ const content = ( code ?? children ) as string ;
5037
5138 if ( ! content || typeof content !== "string" ) {
5239 return null ;
5340 }
5441
55- const highlighter = await getShikiHighlighter ( ) ;
5642 let highlightedCode : string | null = null ;
5743
58- // Only attempt syntax highlighting for supported languages
5944 if ( language !== "text" && language !== "plaintext" ) {
6045 try {
6146 highlightedCode = highlighter . codeToHtml ( content , {
@@ -68,7 +53,6 @@ async function CodeBlock({
6853 transformers : [
6954 {
7055 pre ( node ) {
71- // Remove default styling to use our own
7256 node . properties . style = "" ;
7357 node . properties . tabindex = "-1" ;
7458 } ,
@@ -79,10 +63,6 @@ async function CodeBlock({
7963 ] ,
8064 } ) ;
8165 } catch {
82- // Fallback to plain text if language is not supported
83- console . warn (
84- `Shiki: Language "${ language } " not supported, falling back to plain text`
85- ) ;
8666 highlightedCode = null ;
8767 }
8868 }
@@ -93,7 +73,6 @@ async function CodeBlock({
9373 cornerOpacity = "opacity-0 group-hover/code:opacity-100"
9474 variant = "primary"
9575 >
96- { /* Header */ }
9776 { ( language !== "text" || filename ) && (
9877 < div className = "flex items-center justify-between border-white/5 border-b bg-white/5 px-4 py-2.5" >
9978 < div className = "flex items-center gap-3" >
@@ -108,9 +87,7 @@ async function CodeBlock({
10887 </ span >
10988 ) }
11089 </ div >
111- < div className = "flex items-center gap-2" >
112- < CopyButton className = "h-6 w-6" value = { content } />
113- </ div >
90+ < CopyButton className = "h-6 w-6" value = { content } />
11491 </ div >
11592 ) }
11693
@@ -123,43 +100,40 @@ async function CodeBlock({
123100 </ div >
124101 ) }
125102
126- { /* Code content */ }
127103 < div className = "relative" >
128104 { highlightedCode ? (
129105 < div
130106 className = { cn (
131- "overflow-x-auto font-geist- mono text-[13px] leading-relaxed" ,
132- "[&>pre]:m-0 [&>pre]:overflow-visible [&>pre]:p-4 [&>pre]:font-geist-mono [&>pre]: leading-relaxed" ,
133- "[&>pre>code]:block [&>pre>code]:w-full [&>pre>code]:font-geist-mono [&>pre>code]:leading-relaxed " ,
134- "[&_.line]:min-h-[1.25rem] [&_.line]:px-0 " ,
107+ "overflow-x-auto font-mono text-[13px] leading-relaxed" ,
108+ "[&>pre]:m-0 [&>pre]:overflow-visible [&>pre]:p-4 [&>pre]:leading-relaxed" ,
109+ "[&>pre>code]:block [&>pre>code]:w-full" ,
110+ "[&_.line]:min-h-5 " ,
135111 className
136112 ) }
137113 dangerouslySetInnerHTML = { { __html : highlightedCode } }
138114 />
139115 ) : (
140116 < pre
141117 className = { cn (
142- "overflow-x-auto p-4 font-geist- mono text-foreground text-sm leading-relaxed" ,
118+ "overflow-x-auto p-4 font-mono text-foreground text-sm leading-relaxed" ,
143119 "[&>code]:block [&>code]:w-full [&>code]:p-0 [&>code]:text-inherit" ,
144120 className
145121 ) }
146122 tabIndex = { - 1 }
147123 >
148- < code className = "font-geist-mono" > { content } </ code >
124+ < code > { content } </ code >
149125 </ pre >
150126 ) }
151127 </ div >
152128 </ SciFiCard >
153129 ) ;
154130}
155131
156- interface InlineCodeProps extends React . ComponentProps < "code" > { }
157-
158- function InlineCode ( { className, ...props } : InlineCodeProps ) {
132+ function InlineCode ( { className, ...props } : React . ComponentProps < "code" > ) {
159133 return (
160134 < code
161135 className = { cn (
162- "relative rounded border border-primary/20 bg-primary/10 px-1.5 py-0.5 font-geist-mono font-medium text-primary text-sm" ,
136+ "rounded border border-primary/20 bg-primary/10 px-1.5 py-0.5 font-medium font-mono text-primary text-sm" ,
163137 className
164138 ) }
165139 { ...props }
0 commit comments