-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathindex.tsx
More file actions
103 lines (97 loc) · 3.56 KB
/
index.tsx
File metadata and controls
103 lines (97 loc) · 3.56 KB
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import React, { useMemo } from 'react';
import { Prism as SyntaxHighlighter, SyntaxHighlighterProps } from 'react-syntax-highlighter';
import { oneLight } from 'react-syntax-highlighter/dist/cjs/styles/prism';
import classNames from 'classnames';
import Copy from '../../copy';
import { Message as MessageEntity } from '../entity';
import { CopyOptions } from '../useContext';
import './index.scss';
export interface ICodeBlockProps<M extends MessageEntity = MessageEntity> {
copy?: boolean | CopyOptions;
className?: string;
style?: React.CSSProperties;
message?: M;
convert?: boolean;
toolbars?: React.ReactNode | ((code: string, message?: M) => React.ReactNode);
options?: Partial<SyntaxHighlighterProps>;
children: React.ReactNode & React.ReactNode[];
}
export default function CodeBlock<M extends MessageEntity = MessageEntity>({
className,
style,
toolbars,
message,
copy: rawCopy,
convert,
children,
options: { lineNumberStyle = {}, ...rest } = {},
}: ICodeBlockProps<M>) {
const { value, language } = useMemo(() => {
const child = children[0] as React.ReactElement;
const match = /language-(\w+)/.exec(child.props.className || '');
const language = match ? match[1] : 'SQL';
const value = String(child.props.children).replace(/\n$/, '');
return { value, language };
}, [children]);
const copy = useMemo<{ disabled: boolean; options: CopyOptions }>(() => {
if (typeof rawCopy === 'boolean') {
return {
disabled: !rawCopy,
options: {},
};
}
return {
disabled: false,
options: { ...(rawCopy || {}) },
};
}, [rawCopy]);
const text = value || '';
return (
<div
className={classNames(
'dtc__aigc__codeblock',
convert && 'dtc__aigc__codeblock--convert',
className
)}
style={style}
>
<div className="dtc__aigc__codeblock__header">
<span className="dtc__aigc__codeblock__language">
{language.toLocaleLowerCase()}
</span>
<div className="dtc__aigc__codeblock__tool">
{typeof toolbars === 'function' ? toolbars(text, message) : toolbars}
{/* FIXME:Copy 组件后续可以支持一下 disabled 属性 */}
{!copy.disabled && <Copy text={text} {...copy.options} />}
</div>
</div>
<SyntaxHighlighter
language={language.toLocaleLowerCase()}
wrapLines
style={{
...oneLight,
'code[class*="language-"]': {
...oneLight['code[class*="language-"]'],
background: convert ? '#F9F9FA' : '#fff',
},
'pre[class*="language-"]': {
...oneLight['pre[class*="language-"]'],
background: convert ? '#F9F9FA' : '#fff',
margin: 0,
overflow: 'auto',
maxHeight: 270,
borderRadius: '0 0 4px 4px',
},
}}
lineNumberStyle={{
fontStyle: 'normal',
...lineNumberStyle,
}}
showLineNumbers
{...rest}
>
{text}
</SyntaxHighlighter>
</div>
);
}