If you haven’t read the syntax highlighting guide it’s recommended start there.
Read syntax highlighting guide
Live code
An increasingly common approach for live code editors is to overload the code block. This is often done so that the code shows up nicely when rendered to GitHub and it’s a nice usage of meta strings.
Code block meta string
After the language in code fences you can add key=value
pairs which will
be automatically passed as props to your code block.
```js live=true
Component
If live
isn’t passed to the code component you can render syntax highlighting.
If live
is present you can return react-live.
// src/components/CodeBlock.jsimport React from 'react'import Highlight, {defaultProps} from 'prism-react-renderer'import {LiveProvider, LiveEditor, LiveError, LivePreview} from 'react-live'export default ({children, className, live}) => {const language = className.replace(/language-/, '')if (live) {return (<div style={{marginTop: '40px'}}><LiveProvider code={children}><LivePreview /><LiveEditor /><LiveError /></LiveProvider></div>)}return (<Highlight {...defaultProps} code={children} language={language}>{({className, style, tokens, getLineProps, getTokenProps}) => (<pre className={className} style={{...style, padding: '20px'}}>{tokens.map((line, i) => (<div key={i} {...getLineProps({line, key: i})}>{line.map((token, key) => (<span key={key} {...getTokenProps({token, key})} />))}</div>))}</pre>)}</Highlight>)}
Passing to the MDXProvider
Now that you have a code block component you need to pass it to MDXProvider in the components object so that it is rendered.
// src/App.jsimport React from 'react'import {MDXProvider} from '@mdx-js/tag'import CodeBlock from './components/CodeBlock'const components = {pre: props => <div {...props} />,code: CodeBlock}export default props => (<MDXProvider components={components}><main {...props}></main></MDXProvider>)
Using the MDXProvider context for rendering
With the react-live editor you can ensure that your MDX components in context are rendered in the preview. In order to do this you can use the MDX custom pragma.
To achieve this, import the pragma:
import {mdx} from '@mdx-js/react'
Then apply a code transformation for the pragma and add it to scope:
<LiveProvidercode={children.trim()}transformCode={code => '/** @jsx mdx */' + code}scope={{ mdx }}>
All together
/* eslint react/jsx-key: 0 */import React from 'react'import Highlight, {defaultProps} from 'prism-react-renderer'import {LiveProvider, LiveEditor, LiveError, LivePreview} from 'react-live'import {mdx} from '@mdx-js/react'export default ({children, className, live, render}) => {const language = className.replace(/language-/, '')if (live) {return (<div style={{marginTop: '40px', backgroundColor: 'black'}}><LiveProvidercode={children.trim()}transformCode={code => '/** @jsx mdx */' + code}scope={{ mdx }}><LivePreview /><LiveEditor /><LiveError /></LiveProvider></div>)}if (render) {return (<div style={{marginTop: '40px'}}><LiveProvider code={children}><LivePreview /></LiveProvider></div>)}return (<Highlight {...defaultProps} code={children.trim()} language={language}>{({className, style, tokens, getLineProps, getTokenProps}) => (<pre className={className} style={{...style, padding: '20px'}}>{tokens.map((line, i) => (<div key={i} {...getLineProps({line, key: i})}>{line.map((token, key) => (<span key={key} {...getTokenProps({token, key})} />))}</div>))}</pre>)}</Highlight>)}