1
1
mirror of https://github.com/primer/css.git synced 2024-11-30 19:53:11 +03:00

convert HTML to JSX transparently 😎

This commit is contained in:
Shawn Allen 2018-12-14 01:25:38 -05:00
parent 2626cf574f
commit 919d48747e

View File

@ -1,25 +1,58 @@
import React from 'react' import React from 'react'
import {BorderBox, theme} from '@primer/components'
import {withMDXLive} from 'mdx-live' import {withMDXLive} from 'mdx-live'
import HTMLtoJSX from 'html-2-jsx' import HTMLtoJSX from 'html-2-jsx'
const LANG_PATTERN = /\blanguage-\.?(erb|jsx|html)\b/
const converter = new HTMLtoJSX({ const converter = new HTMLtoJSX({
indent: ' ', indent: ' ',
createClass: false createClass: false
}) })
const defaultTransform = code => `<React.Fragment>${code}</React.Fragment>`
const LiveEditor = withMDXLive('pre') const LiveEditor = withMDXLive('pre')
LiveEditor.defaultProps = { LiveEditor.defaultProps = {
// match ```html and ```jsx fenced code blocks, with or without "." // match ```html and ```jsx fenced code blocks, with or without "."
match: /\blanguage-\.?(html|jsx)\b/ match: LANG_PATTERN,
style: {
padding: 0
},
previewStyle: {
backgroundColor: theme.colors.white,
padding: theme.space[3]
},
editorStyle: {
fontFamily: theme.fonts.mono,
fontSize: theme.fontSizes[1],
padding: theme.space[3]
}
} }
export default function CodeExample(props) { export default function CodeExample(props) {
// for some reason, some fenced code blocks get unsafeInnerHTML and others
// get children; we need to handle both and convert them to a single string
// that we can sanitize
const {unsafeInnerHTML, children, ...rest} = props const {unsafeInnerHTML, children, ...rest} = props
const html = unsafeInnerHTML ? unsafeInnerHTML.__html : React.Children.toArray(children).join('\n') const lang = getLanguage(props.className)
const jsx = converter.convert(html) rest.transformCode = getTransformForLanguage(lang)
return <LiveEditor {...rest}>{jsx}</LiveEditor> const code = unsafeInnerHTML
? unsafeInnerHTML.__html
: React.Children.toArray(children).join('\n')
rest.children = code
return (
<BorderBox bg="gray.1" my={4}>
<LiveEditor {...rest} />
</BorderBox>
)
}
function getLanguage(className) {
const match = className.match(LANG_PATTERN)
return match ? match[1] : undefined
}
function getTransformForLanguage(lang) {
return lang === 'jsx'
? defaultTransform
: html => defaultTransform(converter.convert(html))
} }