Files
FastGPT/client/src/components/Markdown/codeLight.tsx
2023-06-11 16:32:06 +08:00

333 lines
6.4 KiB
TypeScript

import React from 'react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { Box, Flex, useColorModeValue } from '@chakra-ui/react';
import Icon from '@/components/Icon';
import { useCopyData } from '@/utils/tools';
const codeLight: { [key: string]: React.CSSProperties } = {
'code[class*=language-]': {
color: '#d4d4d4',
textShadow: 'none',
direction: 'ltr',
textAlign: 'left',
whiteSpace: 'pre',
wordSpacing: 'normal',
wordBreak: 'normal',
lineHeight: '1.5',
MozTabSize: '4',
OTabSize: '4',
tabSize: '4',
WebkitHyphens: 'none',
MozHyphens: 'none',
msHyphens: 'none',
hyphens: 'none'
},
'pre[class*=language-]': {
color: '#d4d4d4',
textShadow: 'none',
direction: 'ltr',
textAlign: 'left',
whiteSpace: 'pre',
wordSpacing: 'normal',
wordBreak: 'normal',
lineHeight: '1.5',
MozTabSize: '4',
OTabSize: '4',
tabSize: '4',
WebkitHyphens: 'none',
MozHyphens: 'none',
msHyphens: 'none',
hyphens: 'none',
padding: '1em',
margin: '.5em 0',
overflow: 'auto',
background: '#1e1e1e'
},
'code[class*=language-] ::selection': {
textShadow: 'none',
background: '#264f78'
},
'code[class*=language-]::selection': {
textShadow: 'none',
background: '#264f78'
},
'pre[class*=language-] ::selection': {
textShadow: 'none',
background: '#264f78'
},
'pre[class*=language-]::selection': {
textShadow: 'none',
background: '#264f78'
},
':not(pre)>code[class*=language-]': {
padding: '.1em .3em',
borderRadius: '.3em',
color: '#db4c69',
background: '#1e1e1e'
},
'.namespace': {
opacity: '0.7'
},
'doctype.doctype-tag': {
color: '#569cd6'
},
'doctype.name': {
color: '#9cdcfe'
},
comment: {
color: '#6a9955'
},
prolog: {
color: '#6a9955'
},
'.language-html .language-css .token.punctuation': {
color: '#d4d4d4'
},
'.language-html .language-javascript .token.punctuation': {
color: '#d4d4d4'
},
punctuation: {
color: '#d4d4d4'
},
boolean: {
color: '#569cd6'
},
constant: {
color: '#9cdcfe'
},
inserted: {
color: '#b5cea8'
},
number: {
color: '#b5cea8'
},
property: {
color: '#9cdcfe'
},
symbol: {
color: '#b5cea8'
},
tag: {
color: '#569cd6'
},
unit: {
color: '#b5cea8'
},
'attr-name': {
color: '#9cdcfe'
},
builtin: {
color: '#ce9178'
},
char: {
color: '#ce9178'
},
deleted: {
color: '#ce9178'
},
selector: {
color: '#d7ba7d'
},
string: {
color: '#ce9178'
},
'.language-css .token.string.url': {
textDecoration: 'underline'
},
entity: {
color: '#569cd6'
},
operator: {
color: '#d4d4d4'
},
'operator.arrow': {
color: '#569cd6'
},
atrule: {
color: '#ce9178'
},
'atrule.rule': {
color: '#c586c0'
},
'atrule.url': {
color: '#9cdcfe'
},
'atrule.url.function': {
color: '#dcdcaa'
},
'atrule.url.punctuation': {
color: '#d4d4d4'
},
keyword: {
color: '#569cd6'
},
'keyword.control-flow': {
color: '#c586c0'
},
'keyword.module': {
color: '#c586c0'
},
function: {
color: '#dcdcaa'
},
'function.maybe-class-name': {
color: '#dcdcaa'
},
regex: {
color: '#d16969'
},
important: {
color: '#569cd6'
},
italic: {
fontStyle: 'italic'
},
'class-name': {
color: '#4ec9b0'
},
'maybe-class-name': {
color: '#4ec9b0'
},
console: {
color: '#9cdcfe'
},
parameter: {
color: '#9cdcfe'
},
interpolation: {
color: '#9cdcfe'
},
'punctuation.interpolation-punctuation': {
color: '#569cd6'
},
'exports.maybe-class-name': {
color: '#9cdcfe'
},
'imports.maybe-class-name': {
color: '#9cdcfe'
},
variable: {
color: '#9cdcfe'
},
escape: {
color: '#d7ba7d'
},
'tag.punctuation': {
color: 'grey'
},
cdata: {
color: 'grey'
},
'attr-value': {
color: '#ce9178'
},
'attr-value.punctuation': {
color: '#ce9178'
},
'attr-value.punctuation.attr-equals': {
color: '#d4d4d4'
},
namespace: {
color: '#4ec9b0'
},
'code[class*=language-javascript]': {
color: '#9cdcfe'
},
'code[class*=language-jsx]': {
color: '#9cdcfe'
},
'code[class*=language-tsx]': {
color: '#9cdcfe'
},
'code[class*=language-typescript]': {
color: '#9cdcfe'
},
'pre[class*=language-javascript]': {
color: '#9cdcfe'
},
'pre[class*=language-jsx]': {
color: '#9cdcfe'
},
'pre[class*=language-tsx]': {
color: '#9cdcfe'
},
'pre[class*=language-typescript]': {
color: '#9cdcfe'
},
'code[class*=language-css]': {
color: '#ce9178'
},
'pre[class*=language-css]': {
color: '#ce9178'
},
'code[class*=language-html]': {
color: '#d4d4d4'
},
'pre[class*=language-html]': {
color: '#d4d4d4'
},
'.language-regex .token.anchor': {
color: '#dcdcaa'
},
'.language-html .token.punctuation': {
color: 'grey'
},
'pre[class*=language-]>code[class*=language-]': {
position: 'relative',
zIndex: '1'
},
'.line-highlight.line-highlight': {
background: '#f7ebc6',
boxShadow: 'inset 5px 0 0 #f7d87c',
zIndex: '0'
}
};
const CodeLight = ({
children,
className,
inline,
match,
...props
}: {
children: React.ReactNode & React.ReactNode[];
className?: string;
inline?: boolean;
match: RegExpExecArray | null;
}) => {
const { copyData } = useCopyData();
if (!inline && match) {
return (
<Box my={3} borderRadius={'md'} overflow={'overlay'} backgroundColor={'#222'}>
<Flex
className="code-header"
py={2}
px={5}
backgroundColor={useColorModeValue('#323641', 'gray.600')}
color={'#fff'}
fontSize={'sm'}
userSelect={'none'}
>
<Box flex={1}>{match?.[1]}</Box>
<Flex cursor={'pointer'} onClick={() => copyData(String(children))} alignItems={'center'}>
<Icon name={'copy'} width={15} height={15} fill={'#fff'}></Icon>
<Box ml={1}></Box>
</Flex>
</Flex>
<SyntaxHighlighter style={codeLight as any} language={match?.[1]} PreTag="pre" {...props}>
{String(children)}
</SyntaxHighlighter>
</Box>
);
}
return (
<code className={className} {...props}>
{children}
</code>
);
};
export default React.memo(CodeLight);