File size: 1,308 Bytes
03d9a71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { Icon } from '@lobehub/ui';
import { useThemeMode } from 'antd-style';
import { Loader2 } from 'lucide-react';
import { memo, useEffect } from 'react';
import { Center } from 'react-layout-kit';
import { type HighlighterOptions } from 'shiki-es';

import { useStyles } from './style';
import { useHighlight } from './useHighlight';

export interface SyntaxHighlighterProps {
  children: string;
  language: string;
  options?: HighlighterOptions;
}

const SyntaxHighlighter = memo<SyntaxHighlighterProps>(({ children, language, options }) => {
  const { styles } = useStyles();
  const { isDarkMode } = useThemeMode();
  const [codeToHtml, isLoading] = useHighlight((s) => [s.codeToHtml, !s.highlighter]);

  useEffect(() => {
    useHighlight.getState().initHighlighter(options);
  }, [options]);

  return (
    <>
      {isLoading ? (
        <code>{children}</code>
      ) : (
        <div
          className={styles.shiki}
          dangerouslySetInnerHTML={{
            __html: codeToHtml(children, language, isDarkMode) || '',
          }}
        />
      )}

      {isLoading && (
        <Center className={styles.loading} gap={8} horizontal>
          <Icon icon={Loader2} spin />
          Highlighting...
        </Center>
      )}
    </>
  );
});

export default SyntaxHighlighter;