Skip to content

Instantly share code, notes, and snippets.

@johno
Created April 16, 2018 21:15
Show Gist options
  • Save johno/811676fe3e6643b49dbe3fa94450338a to your computer and use it in GitHub Desktop.
Save johno/811676fe3e6643b49dbe3fa94450338a to your computer and use it in GitHub Desktop.
Dynamic MDX rendering
import React from 'react'
import Markdown from './Markdown'
const components = {
h1: props => <h1 style={{ color: 'tomato' }} {...props} />
}
const scope = {
name: 'world!',
Box: props => <div style={{border: 'thin solid tomato'}} {...props} />
}
const mdx = `
# Hello, <span>{name}</span>
<Box>
<h4>!!!!!</h4>
</Box>
`
export default () => (
<Markdown
components={components}
children={mdx}
{...scope}
/>
)
import React, { Component } from 'react'
import mdx from '@mdx-js/mdx'
import { MDXTag } from '@mdx-js/tag'
import * as babel from 'babel-standalone'
const parse = raw => babel.transform(raw, {
plugins: [
require('babel-plugin-transform-react-jsx')
],
presets: [
'react',
'stage-0'
]
}).code
export default class Markdown extends Component {
state = {
Component: null
}
mdxify = async () => {
const { children, components, ...props } = this.props
const scope = { components, ...props, MDXTag }
const jsx = await mdx(children, { components })
// Hacky workaround
const code = jsx.replace(/^(\s)*export default/, '')
const keys = Object.keys(scope)
const values = keys.map(k => scope[k])
const fn = new Function('React', ...keys, `return ${parse(code)}`)
const Component = fn(React, ...values)
this.setState({ Component })
}
// Should prolly recreate on props change
componentWillMount () {
this.mdxify()
}
render () {
const { Component } = this.state
return Component ? <Component /> : null
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment