react-shiki 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,22 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
> This package is still a work in progress, fully functional but not extensively tested.
|
|
1
|
+
# 🎨 [react-shiki](https://npmjs.com/react-shiki)
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
> [!NOTE]
|
|
4
|
+
> This package is still a work in progress, fully functional but not
|
|
5
|
+
> extensively tested.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
Performant server and client side syntax highlighting component + hook
|
|
8
|
+
for react using [Shiki](https://shiki.matsu.io/)
|
|
7
9
|
|
|
8
10
|
[See the demo page with highlighted code blocks showcasing several Shiki themes!](https://react-shiki.vercel.app/)
|
|
9
11
|
|
|
12
|
+
<!--toc:start-->
|
|
13
|
+
|
|
14
|
+
- 🎨 [react-shiki](https://npmjs.com/react-shiki)
|
|
15
|
+
- [Features](#features)
|
|
16
|
+
- [Installation](#installation)
|
|
17
|
+
- [Usage](#usage)
|
|
18
|
+
- [`react-markdown`](#react-markdown)
|
|
19
|
+
- [Custom themes](#custom-themes)
|
|
20
|
+
- [Client-side highlighting](#client-side-highlighting)
|
|
21
|
+
- [Throttling real-time highlighting](#throttling-real-time-highlighting)
|
|
22
|
+
- [Streaming and LLM chat UI](#streaming-and-llm-chat-ui)
|
|
23
|
+
<!--toc:end-->
|
|
24
|
+
|
|
10
25
|
## Features
|
|
11
26
|
|
|
12
|
-
- 🖼️ Provides a `ShikiHighlighter` component for highlighting code as children,
|
|
27
|
+
- 🖼️ Provides a `ShikiHighlighter` component for highlighting code as children,
|
|
28
|
+
as well as a `useShikiHighlighter` hook for more flexibility
|
|
13
29
|
- 🔐 No `dangerouslySetInnerHTML`, output from Shiki is parsed using `html-react-parser`
|
|
14
|
-
- 📦 Supports all Shiki languages and themes
|
|
15
|
-
-
|
|
30
|
+
- 📦 Supports all Shiki languages and themes in addition to
|
|
31
|
+
- 🖌️ Full support for custom TextMate themes in a JavaScript object format
|
|
32
|
+
- 🚰 Performant highlighting of streamed code on the client, with optional throttling
|
|
16
33
|
- 📚 Includes minimal default styles for code blocks
|
|
17
|
-
- 🚀 Shiki dynamically imports only the languages and themes used on a page,
|
|
18
|
-
|
|
19
|
-
-
|
|
34
|
+
- 🚀 Shiki dynamically imports only the languages and themes used on a page,
|
|
35
|
+
optimizing for performance
|
|
36
|
+
- 🖥️ `ShikiHighlighter` component displays a language label for each code block
|
|
37
|
+
when `showLanguage` is set to `true` (default)
|
|
38
|
+
- 🎨 Users can customize the styling of the generated code blocks by passing
|
|
39
|
+
a `style` object or a `className`
|
|
20
40
|
|
|
21
41
|
## Installation
|
|
22
42
|
|
|
@@ -26,17 +46,23 @@ Syntax highlighting component and hook for react using [Shiki](https://shiki.mat
|
|
|
26
46
|
|
|
27
47
|
## Usage
|
|
28
48
|
|
|
29
|
-
You can use the `ShikiHighlighter` component, or the `useShikiHighlighter` hook
|
|
49
|
+
You can use the `ShikiHighlighter` component, or the `useShikiHighlighter` hook
|
|
50
|
+
to highlight code.
|
|
30
51
|
|
|
31
|
-
`useShikiHighlighter` is a hook that takes in the code to be highlighted, the
|
|
52
|
+
`useShikiHighlighter` is a hook that takes in the code to be highlighted, the
|
|
53
|
+
language, and the theme, and returns the highlighted code as React elements.
|
|
54
|
+
It's useful for users who want full control over the rendering of highlighted
|
|
55
|
+
code.
|
|
32
56
|
|
|
33
57
|
```tsx
|
|
34
|
-
const highlightedCode = useShikiHighlighter(code, language, theme);
|
|
58
|
+
const highlightedCode = useShikiHighlighter(code, language, theme, options);
|
|
35
59
|
```
|
|
36
60
|
|
|
37
|
-
The `ShikiHighlighter` component is imported in your project, with the code to
|
|
61
|
+
The `ShikiHighlighter` component is imported in your project, with the code to
|
|
62
|
+
be highlighted passed as it's children.
|
|
38
63
|
|
|
39
|
-
Shiki automatically handles dynamically importing only the languages and themes
|
|
64
|
+
Shiki automatically handles dynamically importing only the languages and themes
|
|
65
|
+
used on the page.
|
|
40
66
|
|
|
41
67
|
```tsx
|
|
42
68
|
function CodeBlock() {
|
|
@@ -50,11 +76,15 @@ function CodeBlock() {
|
|
|
50
76
|
|
|
51
77
|
The component accepts several props in addition to language and theme:
|
|
52
78
|
|
|
53
|
-
- `showLanguage: boolean` - Shows the language name in the top right corner of
|
|
54
|
-
|
|
55
|
-
- `
|
|
56
|
-
|
|
57
|
-
- `
|
|
79
|
+
- `showLanguage: boolean` - Shows the language name in the top right corner of
|
|
80
|
+
the code block
|
|
81
|
+
- `addDefaultStyles`: boolean - Adds default styles (padding, overflow handling,
|
|
82
|
+
and border-radius) to the code block
|
|
83
|
+
- `as: string` - The component to be rendered. Defaults to 'pre'
|
|
84
|
+
- `delay: number` - Delay between highlights in milliseconds, useful for throttling
|
|
85
|
+
rapid highlighting on the client
|
|
86
|
+
- `className: string` - Class name to be passed to the component
|
|
87
|
+
- `style: object` - Style object to be passed to the component
|
|
58
88
|
|
|
59
89
|
```tsx
|
|
60
90
|
function Houston() {
|
|
@@ -75,7 +105,7 @@ function Houston() {
|
|
|
75
105
|
}
|
|
76
106
|
```
|
|
77
107
|
|
|
78
|
-
react-shiki exports `isInlineCode` to check if a code block is inline
|
|
108
|
+
**react-shiki** exports `isInlineCode` to check if a code block is inline:
|
|
79
109
|
|
|
80
110
|
```tsx
|
|
81
111
|
const isInline: boolean | undefined = node ? isInlineCode(node) : undefined;
|
|
@@ -91,7 +121,7 @@ return !isInline ? (
|
|
|
91
121
|
);
|
|
92
122
|
```
|
|
93
123
|
|
|
94
|
-
|
|
124
|
+
### `react-markdown`
|
|
95
125
|
|
|
96
126
|
```tsx
|
|
97
127
|
import type { ReactNode } from "react";
|
|
@@ -118,7 +148,7 @@ export const CodeHighlight = ({
|
|
|
118
148
|
};
|
|
119
149
|
```
|
|
120
150
|
|
|
121
|
-
Pass CodeHighlight to `react-markdown` as a code component:
|
|
151
|
+
Pass `CodeHighlight` to `react-markdown` as a code component:
|
|
122
152
|
|
|
123
153
|
```tsx
|
|
124
154
|
import ReactMarkdown from "react-markdown";
|
|
@@ -145,7 +175,25 @@ import tokyoNight from '@styles/tokyo-night.mjs';
|
|
|
145
175
|
|
|
146
176
|
## Client-side highlighting
|
|
147
177
|
|
|
148
|
-
|
|
178
|
+
react-shiki supports performance-optimized highlighting on the client.
|
|
179
|
+
|
|
180
|
+
### Throttling real-time highlighting
|
|
181
|
+
|
|
182
|
+
Throttling real-time highlighting on the client is possible with the
|
|
183
|
+
`delay` option.
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
const highlightedCode = useShikiHighlighter(code, language, theme, {
|
|
187
|
+
delay: 150,
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Streaming and LLM chat UI
|
|
192
|
+
|
|
193
|
+
react-shiki can be used to highlight streamed code from LLM responses in real-time.
|
|
194
|
+
|
|
195
|
+
I use it for an
|
|
196
|
+
LLM chatbot UI, it renders markdown and highlights code in memoized chat messages.
|
|
149
197
|
|
|
150
198
|
Using `useShikiHighlighter` hook:
|
|
151
199
|
|
|
@@ -176,9 +224,15 @@ export const CodeHighlight = ({
|
|
|
176
224
|
});
|
|
177
225
|
|
|
178
226
|
return !isInline ? (
|
|
179
|
-
<div
|
|
227
|
+
<div
|
|
228
|
+
className="shiki not-prose relative [&_pre]:overflow-auto
|
|
229
|
+
[&_pre]:rounded-lg [&_pre]:px-6 [&_pre]:py-5"
|
|
230
|
+
>
|
|
180
231
|
{language ? (
|
|
181
|
-
<span
|
|
232
|
+
<span
|
|
233
|
+
className="absolute right-3 top-2 text-xs tracking-tighter
|
|
234
|
+
text-muted-foreground/85"
|
|
235
|
+
>
|
|
182
236
|
{language}
|
|
183
237
|
</span>
|
|
184
238
|
) : null}
|
|
@@ -216,7 +270,12 @@ export const CodeHighlight = ({
|
|
|
216
270
|
const isInline: boolean | undefined = node ? isInlineCode(node) : undefined;
|
|
217
271
|
|
|
218
272
|
return !isInline ? (
|
|
219
|
-
<ShikiHighlighter
|
|
273
|
+
<ShikiHighlighter
|
|
274
|
+
language={language}
|
|
275
|
+
theme={"houston"}
|
|
276
|
+
delay={150}
|
|
277
|
+
{...props}
|
|
278
|
+
>
|
|
220
279
|
{String(children)}
|
|
221
280
|
</ShikiHighlighter>
|
|
222
281
|
) : (
|
|
@@ -227,7 +286,7 @@ export const CodeHighlight = ({
|
|
|
227
286
|
};
|
|
228
287
|
```
|
|
229
288
|
|
|
230
|
-
Passed to `react-markdown` as a code component in
|
|
289
|
+
Passed to `react-markdown` as a `code` component in memo-ized chat messages:
|
|
231
290
|
|
|
232
291
|
```tsx title=ChatMessages.tsx
|
|
233
292
|
const RenderedMessage = React.memo(({ message }: { message: Message }) => (
|