1- import Prism from 'prismjs' ;
2- import { forwardRef , useEffect } from 'react' ;
3-
4- import 'prismjs/components/prism-diff' ;
5- import 'prismjs/components/prism-javascript' ;
6- import 'prismjs/components/prism-sql' ;
7- import 'prismjs/components/prism-yaml' ;
8- import 'prismjs/plugins/diff-highlight/prism-diff-highlight' ;
1+ // prism-react-renderer
2+ import { Highlight , Prism as RendererPrism } from 'prism-react-renderer' ;
3+ import { forwardRef } from 'react' ;
94
105import {
116 BaseProps ,
@@ -15,6 +10,21 @@ import {
1510 tasty ,
1611} from '../../../tasty' ;
1712
13+ // Bridge the Prism instance used by `prism-react-renderer` **before** we load
14+ // any additional grammars so that those grammars augment this exact object.
15+ ( globalThis as any ) . Prism = RendererPrism ;
16+
17+ // Vite will pre-bundle these. The `@vite-ignore` keeps it from trying to
18+ // statically analyze the variable `path`.
19+ await Promise . all ( [
20+ import ( 'prismjs/components/prism-diff' ) ,
21+ import ( 'prismjs/components/prism-sql' ) ,
22+ import ( 'prismjs/plugins/diff-highlight/prism-diff-highlight' ) ,
23+ // already bundled in most cases, but kept for completeness
24+ import ( 'prismjs/components/prism-javascript' ) ,
25+ import ( 'prismjs/components/prism-yaml' ) ,
26+ ] ) ;
27+
1828const PreElement = tasty ( {
1929 as : 'pre' ,
2030 qa : 'CodeBlock' ,
@@ -79,7 +89,7 @@ export interface CubePrismCodeProps extends ContainerStyleProps {
7989}
8090
8191function PrismCode ( props : CubePrismCodeProps , ref ) {
82- let { code, language = 'javascript' , ...otherProps } = props ;
92+ const { code = '' , language = 'javascript' , ...otherProps } = props ;
8393
8494 if ( typeof code !== 'string' && code ) {
8595 throw new Error (
@@ -89,18 +99,51 @@ function PrismCode(props: CubePrismCodeProps, ref) {
8999
90100 const isDiff = isDiffCode ( code || '' ) ;
91101
92- useEffect ( ( ) => {
93- Prism . highlightAll ( ) ;
94- } ) ;
102+ // For diff snippets we rely on the `diff` grammar. We still keep the
103+ // original language as a suffix (e.g. diff-javascript) so that the diff
104+ // plugin can colour the inserted / deleted signs while the inner tokens are
105+ // still highlighted correctly.
106+ const grammarLang = isDiff ? `diff-${ language } ` : language ;
95107
96108 return (
97109 < PreElement ref = { ref } { ...otherProps } >
98- < code
99- data-element = "Code"
100- className = { `language${ isDiff ? '-diff' : '' } -${ language } ${ isDiff ? ' diff-highlight' : '' } ` }
110+ < Highlight
111+ prism = { RendererPrism }
112+ code = { code }
113+ language = { grammarLang as any }
101114 >
102- { code }
103- </ code >
115+ { ( { className, tokens, getLineProps, getTokenProps } ) => (
116+ < code
117+ data-element = "Code"
118+ className = { `${ className } ${ isDiff ? ' diff-highlight' : '' } ` }
119+ >
120+ { tokens . map ( ( line , i ) => (
121+ < span
122+ key = { i }
123+ { ...getLineProps ( { line, key : i } ) }
124+ style = { undefined }
125+ >
126+ { line . map ( ( token , key ) => {
127+ const props = getTokenProps ( { token, key } ) ;
128+
129+ return (
130+ < span
131+ key = { key }
132+ { ...props }
133+ style = { {
134+ ...props . style ,
135+ color : undefined ,
136+ backgroundColor : undefined ,
137+ } }
138+ />
139+ ) ;
140+ } ) }
141+ { '\n' }
142+ </ span >
143+ ) ) }
144+ </ code >
145+ ) }
146+ </ Highlight >
104147 </ PreElement >
105148 ) ;
106149}
0 commit comments