-
Notifications
You must be signed in to change notification settings - Fork 0
/
Components.tsx
160 lines (134 loc) · 3.46 KB
/
Components.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/* eslint-disable react/prop-types */
/* eslint-disable react/display-name */
/**
*
* @fileoverview Markdown components
*
* Based on https://github.com/mustaphaturhan/chakra-ui-markdown-renderer/blob/master/src/index.tsx
*/
//Imports
import Code from '../Code/Code';
import {Components, ReactBaseProps, ReactMarkdownProps} from 'react-markdown/src/ast-to-react';
import {As, Checkbox, Code as ChakraCode, Divider, Heading, Image, Link, ListItem, OrderedList, Table, Tbody, Td, Text, Th, Thead, Tr, UnorderedList} from '@chakra-ui/react';
//Header component wrapper
type HeaderProps = ReactBaseProps &
ReactMarkdownProps & {
level: number
};
const header = (props: HeaderProps) =>
{
const sizes = ['2xl', 'xl', 'lg', 'md', 'sm', 'xs'];
return (
<Heading
my={4}
as={`h${props.level}` as As}
size={sizes[props.level - 1]}
>
{props.children}
</Heading>
);
};
/**
* Markdown component overrides
*/
const components = {
//Paragraphs
p: props => <Text mb={2}>{props.children}</Text>,
//Emphasized text
em: props => <Text as="em">{props.children}</Text>,
//Block quotes
blockquote: props => <ChakraCode as="blockquote" borderRadius='3px' padding='4px'>{props.children}</ChakraCode>,
//Code block
code: props =>
{
//Convert to text
const text = props.children.map(child => child?.toString()).join('\r');
//If inline or the class was not provided, treat as an inline code block
if (props.inline || props.className == null)
{
return (
<Code inline={true}>
{text}
</Code>
);
}
//Otherwise treat as a multiline code block
{
//Get the index of the prefix
const languagePrefix = 'language-';
const prefixIndex = props.className.indexOf(languagePrefix);
//Remove the prefix
const language = props.className.substring(prefixIndex + languagePrefix.length);
return (
<Code inline={false} language={language}>
{text}
</Code>
);
}
},
//Deleted text
del: props => <Text as="del">{props.children}</Text>,
//Thematic break
hr: () => <Divider borderBottomWidth='2px' />,
//Link
a: props => <Link textDecoration='underline'>{props.children}</Link>,
//Image
img: Image,
//Text
text: props => <Text as="span">{props.children}</Text>,
//Unordered list
ul: props => (
<UnorderedList
spacing={2}
as='ul'
marginLeft={0}
stylePosition='inside'
styleType={props.depth == 1 ? 'circle' : 'disc'}
>
{props.children}
</UnorderedList>)
,
//Ordered list
ol: props => (
<OrderedList
spacing={2}
as='ol'
marginLeft={0}
stylePosition='inside'
styleType='decimal'
>
{props.children}
</OrderedList>
),
//List item
li: props => (
<ListItem listStyleType={props.checked != null ? 'none' : 'inherit'}>
{props.checked != null ? (
<Checkbox isChecked={props.checked} isReadOnly>
{props.children}
</Checkbox>
) : props.children}
</ListItem>
),
//Heading
h1: header,
h2: header,
h3: header,
h4: header,
h5: header,
h6: header,
//Table
table: Table,
//Table header
thead: Thead,
//Table body
tbody: Tbody,
//Table row
tr: props => <Tr>{props.children}</Tr>,
//Table data cell
td: props => <Td>{props.children}</Td>,
//Table header cell
th: props => <Th>{props.children}</Th>
} as Components;
//Export
export default components;