-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathCodeExample.js
81 lines (72 loc) · 2.28 KB
/
CodeExample.js
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
import React from 'react'
import HTMLtoJSX from 'html-2-jsx'
import {Absolute, BorderBox, Box, StyledOcticon as Octicon, Relative, Text} from '@primer/components'
import {LiveEditor, LiveError, LivePreview, LiveProvider} from 'react-live'
import {getIconByName} from '@githubprimer/octicons-react'
import ClipboardCopy from './ClipboardCopy'
import Frame from './Frame'
import 'prism-github/prism-github.scss'
const LANG_PATTERN = /\blanguage-\.?(jsx|html)\b/
const converter = new HTMLtoJSX({
indent: ' ',
createClass: false
})
const defaultTransform = code => `<React.Fragment>${code}</React.Fragment>`
const languageTransforms = {
html: html => defaultTransform(converter.convert(html)),
jsx: defaultTransform
}
export default function CodeExample(props) {
const {children, dangerouslySetInnerHTML, inert, source, ...rest} = props
const lang = getLanguage(props.className)
if (lang && !inert) {
const liveProps = {
code: source,
scope: {Octicon, getIconByName},
transformCode: getTransformForLanguage(lang),
mountStylesheet: false
}
return (
<LiveProvider {...liveProps}>
<BorderBox {...rest}>
<BorderBox bg="white" border={0} borderBottom={1} borderRadius={0}>
<Frame>
<LivePreview />
</Frame>
</BorderBox>
<Box is={Relative} bg="gray.1" p={3}>
<LiveEditor style={{margin: 0, padding: 0}} />
<Absolute right={0} top={0} m={3}>
<ClipboardCopy value={source} />
</Absolute>
<Text
is={LiveError}
fontFamily="mono"
style={{
overflow: 'auto',
whiteSpace: 'pre'
}}
/>
</Box>
</BorderBox>
</LiveProvider>
)
} else {
const rest = {
children,
dangerouslySetInnerHTML
}
// eslint-disable-next-line react/no-danger-with-children
return <BorderBox data-source={source} is="pre" {...rest} />
}
}
CodeExample.defaultProps = {
my: 4
}
function getLanguage(className) {
const match = className && className.match(LANG_PATTERN)
return match ? match[1] : undefined
}
function getTransformForLanguage(lang) {
return lang in languageTransforms ? languageTransforms[lang] : null
}