Skip to content
MDX logo
v1.5.2GitHub logo

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.js
import 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.js
import 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:

<LiveProvider
code={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'}}>
<LiveProvider
code={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>
)
}

See the full example

Edit this page on GitHub
Previous:
Syntax highlighting
Next:
Math blocks