# Table of Contents - [MDXEditor - the Rich Text Markdown Editor React Component](#mdxeditor-the-rich-text-markdown-editor-react-component) - [Content styling | MDXEditor](#content-styling-mdxeditor) - [Getting started | MDXEditor](#getting-started-mdxeditor) - [Code blocks | MDXEditor](#code-blocks-mdxeditor) - [API Reference | MDXEditor](#api-reference-mdxeditor) - [Links | MDXEditor](#links-mdxeditor) - [404: This page could not be found.](#404-this-page-could-not-be-found-) - [Tables | MDXEditor](#tables-mdxeditor) - [Basic Formatting | MDXEditor](#basic-formatting-mdxeditor) - [Images | MDXEditor](#images-mdxeditor) - [Overview | MDXEditor](#overview-mdxeditor) - [Front-matter | MDXEditor](#front-matter-mdxeditor) - [Diff/source mode | MDXEditor](#diff-source-mode-mdxeditor) - [Markdown shortcuts | MDXEditor](#markdown-shortcuts-mdxeditor) - [Directives | MDXEditor](#directives-mdxeditor) - [Admonitions | MDXEditor](#admonitions-mdxeditor) - [JSX | MDXEditor](#jsx-mdxeditor) - [HTML support | MDXEditor](#html-support-mdxeditor) - [Toolbar | MDXEditor](#toolbar-mdxeditor) - [Extending the editor | MDXEditor](#extending-the-editor-mdxeditor) - [Theming | MDXEditor](#theming-mdxeditor) - [Error handling | MDXEditor](#error-handling-mdxeditor) - [MDXEditorMethods | MDXEditor](#mdxeditormethods-mdxeditor) - [Upgrading to v2 | MDXEditor](#upgrading-to-v2-mdxeditor) - [404: This page could not be found.](#404-this-page-could-not-be-found-) - [i18n | MDXEditor](#i18n-mdxeditor) - [MDXEditorProps | MDXEditor](#mdxeditorprops-mdxeditor) - [MDXEditor | MDXEditor](#mdxeditor-mdxeditor) - [ALL_HEADING_LEVELS | MDXEditor](#all-heading-levels-mdxeditor) - [HEADING_LEVEL | MDXEditor](#heading-level-mdxeditor) - [allowedHeadingLevels%24 | MDXEditor](#allowedheadinglevels-24-mdxeditor) - [404: This page could not be found.](#404-this-page-could-not-be-found-) - [404: This page could not be found.](#404-this-page-could-not-be-found-) - [headingsPlugin | MDXEditor](#headingsplugin-mdxeditor) - [quotePlugin | MDXEditor](#quoteplugin-mdxeditor) - [disableAutoLink%24 | MDXEditor](#disableautolink-24-mdxeditor) - [linkPlugin | MDXEditor](#linkplugin-mdxeditor) - [EditLinkDialog | MDXEditor](#editlinkdialog-mdxeditor) - [InactiveLinkDialog | MDXEditor](#inactivelinkdialog-mdxeditor) - [RectData | MDXEditor](#rectdata-mdxeditor) - [PreviewLinkDialog | MDXEditor](#previewlinkdialog-mdxeditor) - [applyLinkChanges%24 | MDXEditor](#applylinkchanges-24-mdxeditor) - [linkDialogState%24 | MDXEditor](#linkdialogstate-24-mdxeditor) - [openLinkEditDialog%24 | MDXEditor](#openlinkeditdialog-24-mdxeditor) - [removeLink%24 | MDXEditor](#removelink-24-mdxeditor) - [cancelLinkEdit%24 | MDXEditor](#cancellinkedit-24-mdxeditor) - [linkDialogPlugin | MDXEditor](#linkdialogplugin-mdxeditor) - [updateLink%24 | MDXEditor](#updatelink-24-mdxeditor) - [switchFromPreviewToLinkEdit%24 | MDXEditor](#switchfrompreviewtolinkedit-24-mdxeditor) - [applyListType%24 | MDXEditor](#applylisttype-24-mdxeditor) - [currentListType%24 | MDXEditor](#currentlisttype-24-mdxeditor) - [ImageNode | MDXEditor](#imagenode-mdxeditor) - [CreateImageNodeParameters | MDXEditor](#createimagenodeparameters-mdxeditor) - [listsPlugin | MDXEditor](#listsplugin-mdxeditor) - [EditingImageDialogState | MDXEditor](#editingimagedialogstate-mdxeditor) - [FileImageParameters | MDXEditor](#fileimageparameters-mdxeditor) - [NewImageDialogState | MDXEditor](#newimagedialogstate-mdxeditor) - [InactiveImageDialogState | MDXEditor](#inactiveimagedialogstate-mdxeditor) - [SrcImageParameters | MDXEditor](#srcimageparameters-mdxeditor) - [SaveImageParameters | MDXEditor](#saveimageparameters-mdxeditor) - [ImagePreviewHandler | MDXEditor](#imagepreviewhandler-mdxeditor) - [ImageUploadHandler | MDXEditor](#imageuploadhandler-mdxeditor) - [InsertImageParameters | MDXEditor](#insertimageparameters-mdxeditor) - [SerializedImageNode | MDXEditor](#serializedimagenode-mdxeditor) - [closeImageDialog%24 | MDXEditor](#closeimagedialog-24-mdxeditor) - [disableImageResize%24 | MDXEditor](#disableimageresize-24-mdxeditor) - [imageAutocompleteSuggestions%24 | MDXEditor](#imageautocompletesuggestions-24-mdxeditor) - [imageDialogState%24 | MDXEditor](#imagedialogstate-24-mdxeditor) - [imagePreviewHandler%24 | MDXEditor](#imagepreviewhandler-24-mdxeditor) - [imageUploadHandler%24 | MDXEditor](#imageuploadhandler-24-mdxeditor) - [openEditImageDialog%24 | MDXEditor](#openeditimagedialog-24-mdxeditor) - [openNewImageDialog%24 | MDXEditor](#opennewimagedialog-24-mdxeditor) - [insertImage%24 | MDXEditor](#insertimage-24-mdxeditor) - [saveImage%24 | MDXEditor](#saveimage-24-mdxeditor) - [%24createImageNode | MDXEditor](#-24createimagenode-mdxeditor) - [%24isImageNode | MDXEditor](#-24isimagenode-mdxeditor) - [imagePlugin | MDXEditor](#imageplugin-mdxeditor) - [TableNode | MDXEditor](#tablenode-mdxeditor) - [SerializedTableNode | MDXEditor](#serializedtablenode-mdxeditor) - [insertTable%24 | MDXEditor](#inserttable-24-mdxeditor) - [%24createTableNode | MDXEditor](#-24createtablenode-mdxeditor) - [%24isTableNode | MDXEditor](#-24istablenode-mdxeditor) - [tablePlugin | MDXEditor](#tableplugin-mdxeditor) - [insertThematicBreak%24 | MDXEditor](#insertthematicbreak-24-mdxeditor) - [thematicBreakPlugin | MDXEditor](#thematicbreakplugin-mdxeditor) - [toolbarContents%24 | MDXEditor](#toolbarcontents-24-mdxeditor) - [BlockTypeSelect | MDXEditor](#blocktypeselect-mdxeditor) - [toolbarPlugin | MDXEditor](#toolbarplugin-mdxeditor) - [BoldItalicUnderlineToggles | MDXEditor](#bolditalicunderlinetoggles-mdxeditor) - [ChangeAdmonitionType | MDXEditor](#changeadmonitiontype-mdxeditor) - [ChangeCodeMirrorLanguage | MDXEditor](#changecodemirrorlanguage-mdxeditor) - [CodeToggle | MDXEditor](#codetoggle-mdxeditor) - [CreateLink | MDXEditor](#createlink-mdxeditor) - [DiffSourceToggleWrapper | MDXEditor](#diffsourcetogglewrapper-mdxeditor) - [InsertAdmonition | MDXEditor](#insertadmonition-mdxeditor) - [InsertCodeBlock | MDXEditor](#insertcodeblock-mdxeditor) - [InsertFrontmatter | MDXEditor](#insertfrontmatter-mdxeditor) - [InsertImage | MDXEditor](#insertimage-mdxeditor) - [InsertSandpack | MDXEditor](#insertsandpack-mdxeditor) - [InsertTable | MDXEditor](#inserttable-mdxeditor) - [InsertThematicBreak | MDXEditor](#insertthematicbreak-mdxeditor) - [KitchenSinkToolbar | MDXEditor](#kitchensinktoolbar-mdxeditor) - [ListsToggle | MDXEditor](#liststoggle-mdxeditor) - [ShowSandpackInfo | MDXEditor](#showsandpackinfo-mdxeditor) - [StrikeThroughSupSubToggles | MDXEditor](#strikethroughsupsubtoggles-mdxeditor) - [UndoRedo | MDXEditor](#undoredo-mdxeditor) - [ConditionalContentsOption | MDXEditor](#conditionalcontentsoption-mdxeditor) - [FallbackOption | MDXEditor](#fallbackoption-mdxeditor) - [Button | MDXEditor](#button-mdxeditor) - [ButtonOrDropdownButton | MDXEditor](#buttonordropdownbutton-mdxeditor) - [ButtonWithTooltip | MDXEditor](#buttonwithtooltip-mdxeditor) - [MultipleChoiceToggleGroup | MDXEditor](#multiplechoicetogglegroup-mdxeditor) - [ConditionalContents | MDXEditor](#conditionalcontents-mdxeditor) - [DialogButton | MDXEditor](#dialogbutton-mdxeditor) - [Separator | MDXEditor](#separator-mdxeditor) - [SingleChoiceToggleGroup | MDXEditor](#singlechoicetogglegroup-mdxeditor) --- # MDXEditor - the Rich Text Markdown Editor React Component Markdown editing can be even more delightful. ----------------------------------------------- MDXEditor is an open-source React component that allows users to author markdown documents naturally. Just like in Google docs or Notion. [Try it live](/editor/demo) [Get started](/editor/docs/getting-started) Style the content editable area with your content CSS class ----------------------------------------------------------- No more need for edit ↔ preview. ----------------------------------- What you see is what you get. Style the rich text with the same styles as your actual page. [Read more about content styling](editor/docs/content-styling) Code blocks with syntax highlighting, auto-complete, and live preview --------------------------------------------------------------------- No more code samples with sneaky syntax errors. Live preview of the snippet result, powered by Sandpack. [Code blocks docs](editor/docs/code-blocks) ![Sandpack screenshot](/_next/static/media/sandpack-screenshot.a5974dbb.png) Use \`+\` as a bullet sign, \`\_\` as emphasis ---------------------------------------------- Consistent, configurable markdown output ---------------------------------------- The component exposes properties that allow you to tune how the editor content gets converted to markdown. This lets you adjust formatting like the bullet style, the whitespace settings, the emphasis markers. [Markdown processing explained](editor/docs/markdown-processing) Feature overview ---------------- * [Table editor](editor/docs/tables) * [Link dialog](editor/docs/links) * [Image support](editor/docs/images) * [Front-matter editor](editor/docs/front-matter) * [Markdown shortcuts](editor/docs/markdown-shortcuts) * [Diff/source view](editor/docs/diff-source) * [Directives](editor/docs/custom-directive-editors) * [MarkdownX Components](editor/docs/jsx) * [Customizable toolbar](editor/docs/customizing-toolbar) --- # Content styling | MDXEditor Content styling =============== The MDXEditor component exposes a property called `contentEditableClassName` that you can use to style the content of the editor. This is useful if you want to use a different font family, or change the contents of the various blocks inside. For best results, ensure that you style the editor using the same CSS classes that you use in your application. .prose { font-family: "Inter", sans-serif; } .prose strong { font-weight: 600; } Avoiding collisions with the editor UI -------------------------------------- In addition to the content itself, the content editable editor area can include editor elements like the table editor dialog cells and buttons, the frontmatter editor, and the code block editor. To avoid breaking the look of those, ensure that your selectors are conservative and don't target generic elements like `div`, for example. * [Avoiding collisions with the editor UI](#avoiding-collisions-with-the-editor-ui) --- # Getting started | MDXEditor Getting started =============== You've decided to give MDXEditor a try? That's great, because it does not take a lot of effort. While powerful, the component needs little to boot. In this article, we will go through the necessary steps to reach the "Hello world" state. Installation ------------ To use MDXEditor in your project, install the `@mdxeditor/editor` NPM package in your React project: npm install --save @mdxeditor/editor Afterwards, you can import the React component and use it in your project. You need to include the CSS file as well, either as an import in React or in your project stylesheet. Follow the instructions below for your framework of choice. import { MDXEditor } from '@mdxeditor/editor' import '@mdxeditor/editor/style.css' ### Next.js (App router) MDXEditor does not support server rendering, so we need to ensure that the editor component is rendered only on client-side. To do so, we can use the [`dynamic` utility](https://nextjs.org/docs/pages/building-your-application/optimizing/lazy-loading) with `{ssr: false}`. **NOTE:** Make sure that the editor plugins are initialized client-side only, too. Using some plugins will cause hydration errors if imported during SSR. 'use client' // InitializedMDXEditor.tsx import type { ForwardedRef } from 'react' import { headingsPlugin, listsPlugin, quotePlugin, thematicBreakPlugin, markdownShortcutPlugin, MDXEditor, type MDXEditorMethods, type MDXEditorProps } from '@mdxeditor/editor' // Only import this to the next file export default function InitializedMDXEditor({ editorRef, ...props }: { editorRef: ForwardedRef | null } & MDXEditorProps) { return ( ) } 'use client' // ForwardRefEditor.tsx import dynamic from 'next/dynamic' import { forwardRef } from "react" import { type MDXEditorMethods, type MDXEditorProps} from '@mdxeditor/editor' // This is the only place InitializedMDXEditor is imported directly. const Editor = dynamic(() => import('./InitializedMDXEditor'), { // Make sure we turn SSR off ssr: false }) // This is what is imported by other components. Pre-initialized with plugins, and ready // to accept other props, including a ref. export const ForwardRefEditor = forwardRef((props, ref) => ) // TS complains without the following line ForwardRefEditor.displayName = 'ForwardRefEditor' If you get stuck, check the [MDX editor in Next.js GitHub sample repository for a working example](https://github.com/mdx-editor/mdx-editor-in-next) . ### Next.js (Pages router) Next.js in pages mode seems to choke on the ESM format of the editor and one of its dependencies. To work around that, include the following packages in your transpilation list in next.config.js: /** @type {import('next').NextConfig} */ const nextConfig = { transpilePackages: ['@mdxeditor/editor'], reactStrictMode: true, webpack: (config) => { // this will override the experiments config.experiments = { ...config.experiments, topLevelAwait: true } // this will just update topLevelAwait property of config.experiments // config.experiments.topLevelAwait = true return config } } module.exports = nextConfig Check the [MDX editor in Next.js (pages) GitHub sample repository for a working example](https://github.com/mdx-editor/mdx-editor-in-next-pages) for a working example. ### Vite MDXEditor "just works" in Vite, assuming that you use a recent version of it. Here's a minimal example for App.tsx: import { MDXEditor } from '@mdxeditor/editor' import { headingsPlugin } from '@mdxeditor/editor' import '@mdxeditor/editor/style.css' function App() { return } export default App If you get stuck, check the [MDX editor in Vite GitHub sample repository for a working example](https://github.com/mdx-editor/mdx-editor-in-vite) . ### Remix The component works well with the [ClientOnly remix utility](https://github.com/sergiodxa/remix-utils/tree/main?tab=readme-ov-file#clientonly) . Check the working example in the [MDX editor in the Remix GitHub sample repository](https://github.com/mdx-editor/mdx-editor-in-remix) . ### Create React App Here's a minimal example for App.tsx: import '@mdxeditor/editor/style.css' import { MDXEditor, headingsPlugin } from '@mdxeditor/editor' function App() { return } export default App See the [MDX editor in CRA GitHub sample repository for a working example](https://github.com/mdx-editor/mdx-editor-in-cra) . Basic usage ----------- The MDXEditor component accepts its initial value through the `markdown` property. Notice that the property works like the [textarea `defaultValue`](https://react.dev/reference/react-dom/components/textarea#providing-an-initial-value-for-a-text-area) . To change the value dynamically, you should use the `setMarkdown` ref method. To listen for changes of the value of the editor, use the `onChange` callback property. The event is triggered continuously as the user types, so you can use it to update your state. Alternatively, to obtain the value of the editor, use the `getMarkdown` ref method. // create a ref to the editor component const ref = React.useRef(null) return ( <> ) If you want to insert markdown content after the editor is initialized, you can use `insertMarkdown` ref method to insert markdown content to the current cursor position of the active editor. // create a ref to the editor component const ref = React.useRef(null) return ( <> ) Next steps ---------- Hopefully, at this point, the editor component is installed and working in your setup, but it's not very useful. Depending on your use case, you will need some additional features. To ensure that the bundle size stays small, MDXEditor uses a plugin system. Below is an example of a few basic plugins being enabled for the editor. import { MDXEditor, headingsPlugin, listsPlugin, quotePlugin, thematicBreakPlugin } from '@mdxeditor/editor' function App() { return } Follow the links in the sidebar to learn more about each respective capability and the way to enable it. * [Installation](#installation) * [Next.js (App router)](#nextjs-app-router) * [Next.js (Pages router)](#nextjs-pages-router) * [Vite](#vite) * [Remix](#remix) * [Create React App](#create-react-app) * [Basic usage](#basic-usage) * [Next steps](#next-steps) --- # Code blocks | MDXEditor 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 (

Hello CodeSandbox

Start editing to see some magic happen!

); } `.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 ( (\ editor?.editorType === 'codeblock', contents: () => },\ { when: (editor) => editor?.editorType === 'sandpack', contents: () => },\ {\ fallback: () => (\ <>\ \ \ \ )\ }\ ]}\ />\ )\ })\ ]} /> ) } Blocks of code JavaScript: ```js export default function App() { return

Hello world from a markdown

} ``` CSS: ```css body { color: red; } ``` React Sandpack: ```tsx live react export default function App() { return

Hello world from a markdown

} ``` 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](https://sandpack.codesandbox.io/) 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](../api/editor.sandpackconfig) and the [SandpackPreset interface](../api/editor.sandpackpreset) . 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 propagation so that the parent lexical editor does not handle certain events. return (
e.nativeEvent.stopImmediatePropagation()}>