File tree Expand file tree Collapse file tree 2 files changed +61
-15
lines changed Expand file tree Collapse file tree 2 files changed +61
-15
lines changed Original file line number Diff line number Diff line change 1
- import { codeToHtml } from '@/lib/shiki' ;
1
+ 'use client' ;
2
+ import { useEffect , useState } from 'react' ;
3
+ import { codeToHtml , disposeHighlighter } from '@/lib/shiki' ;
2
4
3
- type CodeRenderer = {
5
+ type CodeRendererProps = {
4
6
code : string ;
5
7
lang : string ;
6
8
} ;
7
9
8
- export default async function CodeRenderer ( { code, lang } : CodeRenderer ) {
9
- const html = await codeToHtml ( {
10
- code,
11
- lang,
12
- } ) ;
10
+ export default function CodeRenderer ( { code, lang } : CodeRendererProps ) {
11
+ const [ html , setHtml ] = useState < string | null > ( null ) ;
12
+
13
+ useEffect ( ( ) => {
14
+ const fetchHtml = async ( ) => {
15
+ try {
16
+ const generatedHtml = await codeToHtml ( { code, lang } ) ;
17
+ setHtml ( generatedHtml ) ;
18
+ } catch ( error ) {
19
+ console . error ( 'Error generating HTML:' , error ) ;
20
+ }
21
+ } ;
22
+
23
+ fetchHtml ( ) ;
24
+
25
+ return ( ) => {
26
+ // Avoid disposing if the highlighter might still be needed
27
+ // Consider removing or commenting out this line if it's causing issues
28
+ // disposeHighlighter();
29
+ } ;
30
+ } , [ code , lang ] ) ;
13
31
14
32
return (
15
33
< div >
16
- < div dangerouslySetInnerHTML = { { __html : html } } />
34
+ < div dangerouslySetInnerHTML = { { __html : html || '' } } />
17
35
</ div >
18
36
) ;
19
37
}
Original file line number Diff line number Diff line change 1
- import { bundledLanguages , createHighlighter } from 'shiki/bundle/web' ;
1
+ import {
2
+ bundledLanguages ,
3
+ createHighlighter ,
4
+ Highlighter ,
5
+ } from 'shiki/bundle/web' ;
2
6
import { noir } from './custom-theme' ;
3
7
8
+ // This variable will hold the cached highlighter instance
9
+ let highlighter : Highlighter | null = null ;
10
+
11
+ const getHighlighter = async ( ) : Promise < Highlighter > => {
12
+ if ( ! highlighter ) {
13
+ // Create it only once
14
+ highlighter = await createHighlighter ( {
15
+ themes : [ noir ] ,
16
+ langs : [ ...Object . keys ( bundledLanguages ) ] ,
17
+ } ) ;
18
+ }
19
+ return highlighter ;
20
+ } ;
21
+
4
22
export const codeToHtml = async ( {
5
23
code,
6
24
lang,
7
25
} : {
8
26
code : string ;
9
27
lang : string ;
10
- } ) => {
11
- const highlighter = await createHighlighter ( {
12
- themes : [ noir ] ,
13
- langs : [ ...Object . keys ( bundledLanguages ) ] ,
14
- } ) ;
28
+ } ) : Promise < string > => {
29
+ const highlighterInstance = await getHighlighter ( ) ;
15
30
16
- return highlighter . codeToHtml ( code , {
31
+ // Ensure highlighterInstance is not null
32
+ if ( ! highlighterInstance ) {
33
+ throw new Error ( 'Highlighter instance is null' ) ;
34
+ }
35
+
36
+ return highlighterInstance . codeToHtml ( code , {
17
37
lang : lang ,
18
38
theme : 'noir' ,
19
39
} ) ;
20
40
} ;
41
+
42
+ // Function to dispose of the highlighter when done (e.g., server-side cleanup)
43
+ export const disposeHighlighter = async ( ) : Promise < void > => {
44
+ if ( highlighter ) {
45
+ highlighter . dispose ( ) ;
46
+ highlighter = null ; // Reset the cached instance
47
+ }
48
+ } ;
You can’t perform that action at this time.
0 commit comments