Skip to content

Commit 2fb2120

Browse files
committed
feat(PrismCode): react renderer
1 parent 4c704ca commit 2fb2120

File tree

4 files changed

+85
-17
lines changed

4 files changed

+85
-17
lines changed

.changeset/fair-turtles-switch.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@cube-dev/ui-kit": patch
3+
---
4+
5+
Use react renderer for PrismCode.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
"diff": "^7.0.0",
8080
"email-validator": "^2.0.4",
8181
"globals": "^16.0.0",
82+
"prism-react-renderer": "^2.4.1",
8283
"prismjs": "^1.30.0",
8384
"react-aria": "^3.37.0",
8485
"react-focus-lock": "^2.13.5",

pnpm-lock.yaml

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/content/PrismCode/PrismCode.tsx

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
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

105
import {
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+
1828
const PreElement = tasty({
1929
as: 'pre',
2030
qa: 'CodeBlock',
@@ -79,7 +89,7 @@ export interface CubePrismCodeProps extends ContainerStyleProps {
7989
}
8090

8191
function 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

Comments
 (0)