-
-
Notifications
You must be signed in to change notification settings - Fork 74
/
Copy pathCodeBlock.tsx
79 lines (74 loc) · 2.1 KB
/
CodeBlock.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import { CodeHighlight, CodeHighlightTabs } from '@mantine/code-highlight';
import { IconBrandCss3, IconBrandTypescript, IconFileTypeTsx, IconJson, IconTerminal } from '@tabler/icons-react';
const ICON_PROPS = { size: 16 };
const ICONS = {
tsx: <IconFileTypeTsx {...ICON_PROPS} />,
ts: <IconBrandTypescript {...ICON_PROPS} />,
css: <IconBrandCss3 {...ICON_PROPS} />,
shell: <IconTerminal {...ICON_PROPS} />,
json: <IconJson {...ICON_PROPS} />,
};
function getLanguage(fileName: string) {
return fileName.split('.').pop() as keyof typeof ICONS;
}
export type CodeBlockProps<T extends Record<string, string>> =
| {
language?: keyof typeof ICONS;
fileName?: never;
code: string;
tabs?: never;
}
| {
language?: never;
fileName: string;
code: string;
tabs?: never;
}
| {
language?: never;
fileName?: never;
code?: never;
tabs:
| {
language?: keyof typeof ICONS;
fileName: string;
code: string;
}[]
| { code: T; keys: (keyof T)[] };
};
export function CodeBlock<T extends Record<string, string>>({ fileName, language, code, tabs }: CodeBlockProps<T>) {
if (tabs) {
if (Array.isArray(tabs)) {
return (
<CodeHighlightTabs
code={tabs.map(({ language, fileName, code }) => {
language = language || getLanguage(fileName);
return {
language,
fileName,
code,
icon: ICONS[language] || undefined,
};
})}
/>
);
} else {
const { code, keys } = tabs;
return (
<CodeHighlightTabs
code={keys.map((key) => {
const language = getLanguage(key as string);
return {
language,
fileName: key as string,
code: code[key] as string,
icon: ICONS[language] || undefined,
};
})}
/>
);
}
} else {
return <CodeHighlight language={fileName ? getLanguage(fileName) : language || 'tsx'} code={code} />;
}
}