Code blocks

The code block plugin enables support for fenced code blocks, but does not include any code editing UI. The codeMirrorPlugin and the sandpackPlugin build on top of it to provide a code editing experience. The next example enables both plugins along with their respective toolbar components.

const defaultSnippetContent = `
export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}
`.trim()

const simpleSandpackConfig: SandpackConfig = {
  defaultPreset: 'react',
  presets: [
    {
      label: 'React',
      name: 'react',
      meta: 'live react',
      sandpackTemplate: 'react',
      sandpackTheme: 'light',
      snippetFileName: '/App.js',
      snippetLanguage: 'jsx',
      initialSnippetContent: defaultSnippetContent
    },
  ]
}

function App() {
  return (
    <MDXEditor 
      markdown='hello world'
      plugins={[
       // the default code block language to insert when the user clicks the "insert code block" button
        codeBlockPlugin({defaultCodeBlockLanguage: 'js'}),
        sandpackPlugin({ sandpackConfig: simpleSandpackConfig }),
        codeMirrorPlugin({ codeBlockLanguages: { js: 'JavaScript', css: 'CSS' } }),
        toolbarPlugin({toolbarContents: () => (
          <ConditionalContents
            options={[
                { when: (editor) => editor?.editorType === 'codeblock', contents: () => <ChangeCodeMirrorLanguage /> },
                { when: (editor) => editor?.editorType === 'sandpack', contents: () => <ShowSandpackInfo /> },
                { fallback: () => ( <> 
                <InsertCodeBlock />
                <InsertSandpack />
              </>) }
              ]}
            />)
        })
      ]
      } 
    />
  )
}
Blocks of code

JavaScript:

```js
export default function App() {
  return <h1>Hello world from a markdown</h1>
}
```

CSS:

```css
body {
    color: red;
}
```

React Sandpack:

```tsx live react
export default function App() {
  return <h1>Hello world from a markdown</h1>
}
```

Configuring the CodeMirror editor

The code mirror editor plugin enables editing of fenced code blocks with basic code editing features like syntax highlighting, indentation and bracket matching. A set of toolbar component utilities support the display of a language selector when the block is in focus, while hiding the rich text editor controls. The plugin accepts supported languages as a parameter option.

Configuring the Sandpack editor

Compared to the code mirror editor, the Sandpack one is a bit more complex, as Sandpack needs to know the context of the code block in order to execute it correctly. Before diving in, it's good to understand Sandpack configuration itself. MDXEditor supports multiple Sandpack configurations, based on the meta data of the code block. To configure the supported presets, pass a sandpackConfig option in the plugin initialization. For more details, refer to the SandpackConfig interface and the SandpackPreset interface.

Build a custom code block editor

You can implement your own stack of custom code editors by passing a code block editor descriptor to the codeBlockPlugin. The next example uses a plain text textarea to edit the code block content. More details about each of the constructs in the example can be found in the API reference.

const PlainTextCodeEditorDescriptor: CodeBlockEditorDescriptor = {
  // always use the editor, no matter the language or the meta of the code block
  match: (language, meta) => true,
  // You can have multiple editors with different priorities, so that there's a "catch-all" editor (with the lowest priority)
  priority: 0,
  // The Editor is a React component
  Editor: (props) => {
    const cb = useCodeBlockEditorContext()
   // stops the proppagation so that the parent lexical editor does not handle certain events.
    return (
      <div onKeyDown={(e) => e.nativeEvent.stopImmediatePropagation()}>
        <textarea rows={3} cols={20} defaultValue={props.code} onChange={(e) => cb.setCode(e.target.value)} />
      </div>
    )
  }
}

/** use markdown with some code blocks */
const codeBlocksMarkdown = ""

export function CodeBlock() {
  return (
    <MDXEditor
      onChange={console.log}
      markdown={codeBlocksMarkdown}
      plugins={[
        codeBlockPlugin({ codeBlockEditorDescriptors: [PlainTextCodeEditorDescriptor] }),
      ]}
    />
  )
}