Serializing Markdown
components/demo.tsx
'use client';
import React from 'react';
import { Plate } from '@udecode/plate/react';
import { editorPlugins } from '@/components/editor/plugins/editor-plugins';
import { useCreateEditor } from '@/components/editor/use-create-editor';
import { Editor, EditorContainer } from '@/components/plate-ui/editor';
import { DEMO_VALUES } from './values/demo-values';
export default function Demo({ id }: { id: string }) {
  const editor = useCreateEditor({
    plugins: [...editorPlugins],
    value: DEMO_VALUES[id],
  });
  return (
    <Plate editor={editor}>
      <EditorContainer variant="demo">
        <Editor />
      </EditorContainer>
    </Plate>
  );
}
Installation
npm install @udecode/plate-markdownUsage
Markdown to Slate
import { MarkdownPlugin } from '@udecode/plate-markdown';
 
const editor = createPlateEditor({ 
  plugins: [
    // ...otherPlugins,
    MarkdownPlugin,
  ],
});
 
const value = editor.api.markdown.deserialize('**Hello world!**');components/markdown-to-slate-demo.tsx
'use client';
import React, { useState } from 'react';
import type { Value } from '@udecode/plate';
import { withProps } from '@udecode/cn';
import {
  type PlateEditor,
  ParagraphPlugin,
  Plate,
  PlateLeaf,
  usePlateEditor,
} from '@udecode/plate/react';
import {
  BoldPlugin,
  CodePlugin,
  ItalicPlugin,
  StrikethroughPlugin,
  SubscriptPlugin,
  SuperscriptPlugin,
  UnderlinePlugin,
} from '@udecode/plate-basic-marks/react';
import { BlockquotePlugin } from '@udecode/plate-block-quote/react';
import {
  CodeBlockPlugin,
  CodeLinePlugin,
  CodeSyntaxPlugin,
} from '@udecode/plate-code-block/react';
import { HEADING_KEYS } from '@udecode/plate-heading';
import { HighlightPlugin } from '@udecode/plate-highlight/react';
import { HorizontalRulePlugin } from '@udecode/plate-horizontal-rule/react';
import { KbdPlugin } from '@udecode/plate-kbd/react';
import { LinkPlugin } from '@udecode/plate-link/react';
import { MarkdownPlugin, deserializeMd } from '@udecode/plate-markdown';
import { InlineEquationPlugin } from '@udecode/plate-math/react';
import { ImagePlugin } from '@udecode/plate-media/react';
import {
  TableCellHeaderPlugin,
  TableCellPlugin,
  TablePlugin,
  TableRowPlugin,
} from '@udecode/plate-table/react';
import { cloneDeep } from 'lodash';
import remarkEmoji from 'remark-emoji';
import { autoformatPlugin } from '@/components/editor/plugins/autoformat-plugin';
import { basicNodesPlugins } from '@/components/editor/plugins/basic-nodes-plugins';
import { indentListPlugins } from '@/components/editor/plugins/indent-list-plugins';
import { linkPlugin } from '@/components/editor/plugins/link-plugin';
import { mediaPlugins } from '@/components/editor/plugins/media-plugins';
import { tablePlugin } from '@/components/editor/plugins/table-plugin';
import { BlockquoteElement } from '@/components/plate-ui/blockquote-element';
import { CodeBlockElement } from '@/components/plate-ui/code-block-element';
import { CodeLeaf } from '@/components/plate-ui/code-leaf';
import { CodeLineElement } from '@/components/plate-ui/code-line-element';
import { CodeSyntaxLeaf } from '@/components/plate-ui/code-syntax-leaf';
import { Editor, EditorContainer } from '@/components/plate-ui/editor';
import { HeadingElement } from '@/components/plate-ui/heading-element';
import { HighlightLeaf } from '@/components/plate-ui/highlight-leaf';
import { HrElement } from '@/components/plate-ui/hr-element';
import { ImageElement } from '@/components/plate-ui/image-element';
import { KbdLeaf } from '@/components/plate-ui/kbd-leaf';
import { LinkElement } from '@/components/plate-ui/link-element';
import { ParagraphElement } from '@/components/plate-ui/paragraph-element';
import {
  TableCellElement,
  TableCellHeaderElement,
} from '@/components/plate-ui/table-cell-element';
import { TableElement } from '@/components/plate-ui/table-element';
import { TableRowElement } from '@/components/plate-ui/table-row-element';
const initialMarkdown = `# Markdown syntax guide
## Headers
# This is a Heading h1
## This is a Heading h2
###### This is a Heading h6
## Emphasis
*This text will be italic*  
_This will also be italic_
**This text will be bold**  
__This will also be bold__
_You **can** combine them_
## Lists
### Unordered
* Item 1
* Item 2
* Item 2a
* Item 2b
### Ordered
1. Item 1
2. Item 2
3. Item 3
    1. Item 3a
    2. Item 3b
## Images

## Links
You may be using [Markdown Live Preview](https://markdownlivepreview.com/).
## Blockquotes
> Markdown is a lightweight markup language with plain-text-formatting syntax, created in 2004 by John Gruber with Aaron Swartz.
## Tables
| Left columns  | Right columns |
| ------------- |:-------------:|
| left foo      | right foo     |
| left bar      | right bar     |
| left baz      | right baz     |
## Blocks of code
\`\`\`js
let message = 'Hello world';
alert(message);
\`\`\`
## Inline code
This web site is using \`plate\`.
## GitHub Flavored Markdown
### Task Lists
- [x] Completed task
- [ ] Incomplete task
- [x] @mentions, #refs, [links](), **formatting**, and <del>tags</del> supported
- [ ] list syntax required (any unordered or ordered list supported)
### Strikethrough
~~This text is strikethrough~~
### Autolinks
Visit https://github.com automatically converts to a link
Email example@example.com also converts automatically
### Emoji
:smile: :heart:
`;
const markdownPlugin = MarkdownPlugin.configure({
  options: { indentList: true },
});
export default function MarkdownDemo() {
  const markdownEditor = usePlateEditor({
    plugins: [markdownPlugin],
    value: [{ children: [{ text: initialMarkdown }], type: 'p' }],
  });
  const [value, setValue] = useState<Value>([]);
  const editor = usePlateEditor(
    {
      override: {
        components: {
          [BlockquotePlugin.key]: BlockquoteElement,
          [BoldPlugin.key]: withProps(PlateLeaf, { as: 'strong' }),
          [CodeBlockPlugin.key]: CodeBlockElement,
          [CodeLinePlugin.key]: CodeLineElement,
          [CodePlugin.key]: CodeLeaf,
          [CodeSyntaxPlugin.key]: CodeSyntaxLeaf,
          [HEADING_KEYS.h1]: withProps(HeadingElement, { variant: 'h1' }),
          [HEADING_KEYS.h2]: withProps(HeadingElement, { variant: 'h2' }),
          [HEADING_KEYS.h3]: withProps(HeadingElement, { variant: 'h3' }),
          [HEADING_KEYS.h4]: withProps(HeadingElement, { variant: 'h4' }),
          [HEADING_KEYS.h5]: withProps(HeadingElement, { variant: 'h5' }),
          [HEADING_KEYS.h6]: withProps(HeadingElement, { variant: 'h6' }),
          [HighlightPlugin.key]: HighlightLeaf,
          [HorizontalRulePlugin.key]: HrElement,
          [ImagePlugin.key]: ImageElement,
          [ItalicPlugin.key]: withProps(PlateLeaf, { as: 'em' }),
          [KbdPlugin.key]: KbdLeaf,
          [LinkPlugin.key]: LinkElement,
          [ParagraphPlugin.key]: ParagraphElement,
          [StrikethroughPlugin.key]: withProps(PlateLeaf, { as: 's' }),
          [SubscriptPlugin.key]: withProps(PlateLeaf, { as: 'sub' }),
          [SuperscriptPlugin.key]: withProps(PlateLeaf, { as: 'sup' }),
          [TableCellHeaderPlugin.key]: TableCellHeaderElement,
          [TableCellPlugin.key]: TableCellElement,
          [TablePlugin.key]: TableElement,
          [TableRowPlugin.key]: TableRowElement,
          [UnderlinePlugin.key]: withProps(PlateLeaf, { as: 'u' }),
        },
      },
      plugins: [
        ...basicNodesPlugins,
        HorizontalRulePlugin,
        linkPlugin,
        tablePlugin,
        ...mediaPlugins,
        InlineEquationPlugin,
        HighlightPlugin,
        KbdPlugin,
        ImagePlugin,
        ...indentListPlugins,
        autoformatPlugin,
        markdownPlugin,
      ],
      value: (editor) =>
        deserializeMd(editor, initialMarkdown, {
          processor(processor) {
            return processor.use(remarkEmoji) as any;
          },
        }),
    },
    []
  );
  useResetEditorOnChange({ editor, value: value }, [value]);
  return (
    <div className="grid grid-cols-2 overflow-y-auto">
      <Plate
        onValueChange={() => {
          setValue(
            editor.api.markdown.deserialize(
              markdownEditor.api.markdown.serialize()
            )
          );
        }}
        editor={markdownEditor}
      >
        <EditorContainer>
          <Editor variant="none" className="p-2 font-mono text-sm" />
        </EditorContainer>
      </Plate>
      <Plate editor={editor}>
        <EditorContainer className="bg-muted/50">
          <Editor variant="none" className="p-2" />
        </EditorContainer>
      </Plate>
    </div>
  );
}
function useResetEditorOnChange(
  { editor, value }: { editor: PlateEditor; value: Value },
  deps: any[]
) {
  React.useEffect(() => {
    if (value.length > 0) {
      editor.tf.replaceNodes(cloneDeep(value), {
        at: [],
        children: true,
      });
      editor.history.undos = [];
      editor.history.redos = [];
      editor.operations = [];
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [...deps]);
}
Slate to Markdown
Currently supported plugins: paragraph, link, list, heading, italic, bold and code. List indentation uses 3 spaces instead of 2.
const editor = createPlateEditor({ 
  value,
  plugins: [
    // ...otherPlugins,
    MarkdownPlugin,
  ],
});
 
const content = editor.api.markdown.serialize();API
MarkdownPlugin
editor.api.markdown.deserialize
Converts a Markdown string to a Slate value.
editor.api.markdown.serialize
Converts the current Slate value to a Markdown string.
parseMarkdownBlocks
Extracts and filters markdown tokens using marked lexer.