-
-
Notifications
You must be signed in to change notification settings - Fork 40
/
ShikiMagicMove.tsx
64 lines (57 loc) · 1.87 KB
/
ShikiMagicMove.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import type { HighlighterCore } from 'shiki/core'
import type { KeyedTokensInfo, MagicMoveDifferOptions, MagicMoveRenderOptions } from '../types'
import * as React from 'react'
import { codeToKeyedTokens, createMagicMoveMachine } from '../core'
import { ShikiMagicMoveRenderer } from './ShikiMagicMoveRenderer'
export interface ShikiMagicMoveProps {
highlighter: HighlighterCore
lang: string
theme: string
code: string
options?: MagicMoveRenderOptions & MagicMoveDifferOptions
onStart?: () => void
onEnd?: () => void
className?: string
tabindex?: number
}
export function ShikiMagicMove(props: ShikiMagicMoveProps) {
const codeToTokens = React.useRef<(code: string, lineNumbers?: boolean) => KeyedTokensInfo>()
codeToTokens.current = (code, lineNumbers) => codeToKeyedTokens(
props.highlighter,
code,
{
lang: props.lang,
theme: props.theme,
},
lineNumbers,
)
const machine = React.useRef<ReturnType<typeof createMagicMoveMachine>>()
machine.current = machine.current || createMagicMoveMachine(
(code, lineNumbers) => codeToTokens.current!(code, lineNumbers),
)
const lineNumbers = props.options?.lineNumbers ?? false
const result = React.useMemo(
() => {
if (
props.code === machine.current!.current.code
&& props.theme === machine.current!.current.themeName
&& props.lang === machine.current!.current.lang
&& lineNumbers === machine.current!.current.lineNumbers
) {
return machine.current!
}
return machine.current!.commit(props.code, props.options)
},
[props.code, props.options, props.theme, props.lang, lineNumbers],
)
return (
<ShikiMagicMoveRenderer
tokens={result.current}
options={props.options}
previous={result.previous}
onStart={props.onStart}
onEnd={props.onEnd}
className={props.className}
/>
)
}