Search results

Markdown

When you format the word in Markdown format, you should add Markdown syntax to the word to indicate the words and phrases that looks different from each other.

RichTextEditor supports markdown editing when the editorMode set as markdown and using both keyboard interaction and toolbar action, you can apply the formatting to text.

To create RichTextEditor with Markdown editing feature, inject the MarkdownEditor module to the RTE using the RichTextEditor.Inject(MarkdownEditor) method.

Supported tools

The editor’s toolbar contains commands to format the markdown content. The toolbar consists of

Tools Description Syntax in MD
Lists Ordered and unordered list types. For unorder list, preceding one or more lines of text with - or *.

For order list, precede each line with a number.
Links A hyperlink can be inserted into the editor for quick access to related information. Create an inline link by wrapping link text in brackets [] and then wrapping the URL in parentheses ().
Image Inserts and manages images. Create an image by wrapping an alternative text in brackets [] and then link of the image source in parentheses ().

Example: [](image.png)
Format Formats the sentence in different ways such as heading level, quotation, and code snippet. For heading, Add one to six # symbols before your heading text.
Styles Allows you to apply inline styles to the selected content like bold, italic, and more. For bold, add ** or __ to front and back of the text.

For italic, add * or _ to front and back of the text.

Markdown to HTML

The rich text editor allows you to preview markdown changes immediately using preview. In this sample, the third-party library Marked is used to convert markdown into HTML content.

This sample demonstrates how to preview markdown changes in rich text editor. Type or edit the display text, and apply format to view the preview of markdown. The actionComplete event can be used to convert Markdown to HTML.

Source
Preview
index.tsx
index.html
/**
 * RichTextEditor - Markdown to HTML Sample
 */
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { createElement, KeyboardEventArgs } from '@syncfusion/ej2-base';
import { RichTextEditor, Toolbar, Image, Link, MarkdownEditor, Inject, IToolbarItems, QuickToolbar  } from '@syncfusion/ej2-react-richtexteditor';
RichTextEditor.Inject(MarkdownEditor, Image, Link, Toolbar);

export class RTE extends React.Component<{}, {}> {
  private mdSource: HTMLElement;
  private mdSplit: HTMLElement;
  private htmlPreview: HTMLElement;
  private defaultRTE: RichTextEditor;
  private textArea: HTMLTextAreaElement;

  private value: string = `***Overview***
  The rich text editor component is WYSIWYG ("what you see is what you get") editor used to create and edit the content and return valid HTML markup or markdown (MD) of the content. The editor provides a standard toolbar to format content using its commands. Modular library features to load the necessary functionality on demand. The toolbar contains commands to align the text, insert link, insert image, insert list, undo/redo operation, HTML view, and more.

  ***Key features***
  - *Mode*: Provides IFRAME and DIV mode.
  - *Module*: Modular library to load the necessary functionality on demand.
  - *Toolbar*: Provide a fully customizable toolbar.
  - *Editing*: HTML view to edit the source directly for developers.
  - *Third-party Integration*: Supports to integrate third-party library.
  - *Preview*: Preview the modified content before saving it.
  - *Tools*: Handling images, hyperlinks, video, uploads and more.
  - *Undo and Redo*: Undo/redo manager.
  - *Lists*: Creates bulleted and numbered list.`;

  public componentDidMount(): void {
    this.defaultRTE = new RichTextEditor({
      height: '300px',
      valueTemplate: this.value,
      editorMode: 'Markdown',
      toolbarSettings: {
        items: [
          'Bold', 'Italic', 'StrikeThrough', '|', 'Formats', 'OrderedList', 'UnorderedList', '|',
          'CreateLink', 'Image', '|',
          {
            tooltipText: 'Preview',
            template: '<button id="preview-code" class="e-tbar-btn e-control e-btn e-icon-btn">' +
            '<span class="e-btn-icon e-md-preview e-preview e-icons"></span></button>'
          },
          {
            tooltipText: 'Split Editor',
            template: '<button id="MD_Preview" class="e-tbar-btn e-control e-btn e-icon-btn">' +
                      '<span class="e-btn-icon e-view-side e-icons"></span></button>'
          },
          'FullScreen', '|', 'Undo', 'Redo']
        },
        created: () => {
          this.textArea = this.defaultRTE.contentModule.getEditPanel() as HTMLTextAreaElement;
          this.textArea.addEventListener('keyup', (e: KeyboardEventArgs) => {
            this.markDownConversion();
          });
          let rteObj: RichTextEditor = this.defaultRTE;
          this.mdSource = document.getElementById('preview-code');
          this.mdSource.addEventListener('click', (e: MouseEvent) => {
          this.fullPreview({ mode: true, type: 'preview' });
          if ((e.currentTarget as HTMLElement).classList.contains('e-active')) {
            this.defaultRTE.disableToolbarItem(['Bold', 'Italic', 'StrikeThrough', '|',
              'Formats', 'OrderedList', 'UnorderedList', '|',
              'CreateLink', 'Image', 'Undo', 'Redo']);
            (e.currentTarget as HTMLElement).parentElement.previousElementSibling.classList.add('e-overlay');
          } else {
            this.defaultRTE.enableToolbarItem(['Bold', 'Italic', 'StrikeThrough', '|',
              'Formats', 'OrderedList', 'UnorderedList', '|',
              'CreateLink', 'Image', 'Undo', 'Redo']);
            (e.currentTarget as HTMLElement).parentElement.previousElementSibling.classList.remove('e-overlay');
          }
        });
        this.mdSplit = document.getElementById('MD_Preview');
        this.mdSplit.addEventListener('click', (e: MouseEvent) => {
          if (this.defaultRTE.element.classList.contains('e-rte-full-screen')) {
            this.fullPreview({ mode: true, type: '' });
          }
          this.mdSource.classList.remove('e-active');
          if (!this.defaultRTE.element.classList.contains('e-rte-full-screen')) {
            this.defaultRTE.showFullScreen();
          }
        });
      },
      actionComplete: (e: any) => {
        if (e.targetItem === 'Maximize' && isNullOrUndefined(e.args)) {
          this.fullPreview({ mode: true, type: '' });
        } else if (!this.mdSplit.parentElement.classList.contains('e-overlay')) {
          if (e.targetItem === 'Minimize') {
            this.textArea.style.display = 'block';
            this.textArea.style.width = '100%';
            if (this.htmlPreview) { this.htmlPreview.style.display = 'none'; }
              this.mdSplit.classList.remove('e-active');
              this.mdSource.classList.remove('e-active');
          }
          this.markDownConversion();
        }
        setTimeout(() => {
          this.defaultRTE.toolbarModule.refreshToolbarOverflow();
        }, 400);
      }
    });
    this.defaultRTE.appendTo('#markdownPreview');
  }

  private markDownConversion(): void {
    if (this.mdSplit.classList.contains('e-active')) {
      let id: string = this.defaultRTE.getID() + 'html-preview';
      let htmlPreview: HTMLElement = this.defaultRTE.element.querySelector('#' + id);
      htmlPreview.innerHTML = marked((this.defaultRTE.contentModule.getEditPanel() as HTMLTextAreaElement).value);
    }
  }

  private fullPreview(e: { [key: string]: string | boolean }): void {
    let id: string = this.defaultRTE.getID() + 'html-preview';
    this.htmlPreview = this.defaultRTE.element.querySelector('#' + id);
    if ((this.mdSource.classList.contains('e-active') || this.mdSplit.classList.contains('e-active')) && e.mode) {
      this.mdSource.classList.remove('e-active');
      this.mdSplit.classList.remove('e-active');
      this.mdSource.parentElement.title = 'Preview';
      this.textArea.style.display = 'block';
      this.textArea.style.width = '100%';
      this.htmlPreview.style.display = 'none';
    } else {
      this.mdSource.classList.add('e-active');
      this.mdSplit.classList.add('e-active');
      if (!this.htmlPreview) {
        this.htmlPreview = createElement('div', { className: 'e-content' });
        this.htmlPreview.id = id;
        this.textArea.parentNode.appendChild(this.htmlPreview);
      }
      if (e.type === 'preview') {
        this.textArea.style.display = 'none'; this.htmlPreview.classList.add('e-pre-source');
      } else {
        this.htmlPreview.classList.remove('e-pre-source');
        this.textArea.style.width = '50%';
      }
      this.htmlPreview.style.display = 'block';
      this.htmlPreview.innerHTML = marked((this.defaultRTE.contentModule.getEditPanel() as HTMLTextAreaElement).value);
      this.mdSource.parentElement.title = 'Code View';
    }
  }

  render() {
    return (
      <div id="rte-default" className='control-pane'>
        <div className='control-section' id="rtePreview">
          <div className="content-wrapper">
            <div id="markdownPreview"></div>
          </div>
        </div>
      </div>
    );
  }
}
ReactDOM.render(<RTE />, document.getElementById('sample'));
<!DOCTYPE html>
<html lang="en">

<head>
    <title> Syncfusion React RichTextEditor </title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Essential JS 2 for React Components" />
    <meta name="author" content="Syncfusion" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-richtexteditor/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-lists/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-popups/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-navigations/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-dropdowns/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.19/marked.js" type="text/javascript"></script>
    <script src="systemjs.config.js"></script>
    <style>
        #loader {
            color: #008cff;
            height: 40px;
            left: 45%;
            position: absolute;
            top: 45%;
            width: 30%;
        }

        #rteMarkdown .e-richtexteditor textarea.e-content#markdownPreview_editable-content {
            float: left;
            border-right: 1px solid rgba(0, 0, 0, 0.12);
        }

        #rteMarkdown #markdownPreview .e-richtexteditor .e-rte-content .e-content {
            min-height: 150px;
        }

        #rteMarkdown #markdownPreview .e-richtexteditor .e-rte-content {
            overflow: hidden;
        }

        #rteMarkdown .e-icon-btn.e-active .e-md-preview::before {
            content: '\e350';
        }

        #rteMarkdown .e-icon-btn .e-md-preview::before {
            content: '\e345';
        }

        #rteMarkdown .e-rte-content #markdownPreviewhtml-preview.e-content {
            float: right;
            width: 50%;
            overflow: auto;
            height: inherit;
            padding: 8px;
            height: 100%;
        }

        #rteMarkdown #markdownPreview .e-rte-content .e-content.e-pre-source {
            width: 100%;
        }

        .sb-header {
            z-index: 100 !important;
        }

        #rteMarkdown {
            overflow: hidden;
        }

        #rteMarkdown .content-wrapper {
            width: auto;
            margin: 0;
        }
    </style>
</head>

<body>
    <div id='sample' style="margin: 20px auto 0;">
        <div id='loader'>Loading....</div>
    </div>
</body>

</html>

Table

Rich Text Editor allows to insert Markdown table in edit panel with 2 X 2 rows and columns along with the heading. To use table tool, add the CreateTable item in toolbar items.

Insert table

To insert the table in RichTextEditor, click the table toolbar option to insert the table into rich text editor content and this is the default way in all the devices. Please refer the below sample and code snippets to add the table in Markdown editor

Source
Preview
index.tsx
index.html
/**
 * RichTextEditor - Markdown to HTML Sample
 */
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { createElement, KeyboardEventArgs } from '@syncfusion/ej2-base';
import { RichTextEditor, Toolbar, Image, Link, MarkdownEditor, Inject, IToolbarItems, QuickToolbar  } from '@syncfusion/ej2-react-richtexteditor';
RichTextEditor.Inject(MarkdownEditor, Image, Link, Toolbar);

export class RTE extends React.Component<{}, {}> {
  private mdSource: HTMLElement;
  private mdSplit: HTMLElement;
  private htmlPreview: HTMLElement;
  private defaultRTE: RichTextEditor;
  private textArea: HTMLTextAreaElement;

  private value: string = `***Overview***
  The rich text editor component is WYSIWYG ("what you see is what you get") editor used to create and edit the content and return valid HTML markup or markdown (MD) of the content. The editor provides a standard toolbar to format content using its commands. Modular library features to load the necessary functionality on demand. The toolbar contains commands to align the text, insert link, insert image, insert list, undo/redo operation, HTML view, and more.

  ***Key features***
  - *Mode*: Provides IFRAME and DIV mode.
  - *Module*: Modular library to load the necessary functionality on demand.
  - *Toolbar*: Provide a fully customizable toolbar.
  - *Editing*: HTML view to edit the source directly for developers.
  - *Third-party Integration*: Supports to integrate third-party library.
  - *Preview*: Preview the modified content before saving it.
  - *Tools*: Handling images, hyperlinks, video, uploads and more.
  - *Undo and Redo*: Undo/redo manager.
  - *Lists*: Creates bulleted and numbered list.`;

  public componentDidMount(): void {
    this.defaultRTE = new RichTextEditor({
      height: '300px',
      valueTemplate: this.value,
      editorMode: 'Markdown',
      toolbarSettings: {
        items: [
          'Bold', 'Italic', 'StrikeThrough', '|', 'Formats', 'OrderedList', 'UnorderedList', '|',
          'CreateLink', 'Image', 'CreateTable', '|',
          {
            tooltipText: 'Preview',
            template: '<button id="preview-code" class="e-tbar-btn e-control e-btn e-icon-btn">' +
            '<span class="e-btn-icon e-md-preview e-preview e-icons"></span></button>'
          },
          {
            tooltipText: 'Split Editor',
            template: '<button id="MD_Preview" class="e-tbar-btn e-control e-btn e-icon-btn">' +
                      '<span class="e-btn-icon e-view-side e-icons"></span></button>'
          },
          'FullScreen', '|', 'Undo', 'Redo']
        },
        created: () => {
          this.textArea = this.defaultRTE.contentModule.getEditPanel() as HTMLTextAreaElement;
          this.textArea.addEventListener('keyup', (e: KeyboardEventArgs) => {
            this.markDownConversion();
          });
          let rteObj: RichTextEditor = this.defaultRTE;
          this.mdSource = document.getElementById('preview-code');
          this.mdSource.addEventListener('click', (e: MouseEvent) => {
          this.fullPreview({ mode: true, type: 'preview' });
          if ((e.currentTarget as HTMLElement).classList.contains('e-active')) {
            this.defaultRTE.disableToolbarItem(['Bold', 'Italic', 'StrikeThrough', '|',
              'Formats', 'OrderedList', 'UnorderedList', '|',
              'CreateLink', 'Image', 'Undo', 'Redo', 'CreateTable']);
            (e.currentTarget as HTMLElement).parentElement.previousElementSibling.classList.add('e-overlay');
          } else {
            this.defaultRTE.enableToolbarItem(['Bold', 'Italic', 'StrikeThrough', '|',
              'Formats', 'OrderedList', 'UnorderedList', '|',
              'CreateLink', 'Image', 'Undo', 'Redo', 'CreateTable']);
            (e.currentTarget as HTMLElement).parentElement.previousElementSibling.classList.remove('e-overlay');
          }
        });
        this.mdSplit = document.getElementById('MD_Preview');
        this.mdSplit.addEventListener('click', (e: MouseEvent) => {
          if (this.defaultRTE.element.classList.contains('e-rte-full-screen')) {
            this.fullPreview({ mode: true, type: '' });
          }
          this.mdSource.classList.remove('e-active');
          if (!this.defaultRTE.element.classList.contains('e-rte-full-screen')) {
            this.defaultRTE.showFullScreen();
          }
        });
      },
      actionComplete: (e: any) => {
        if (e.targetItem === 'Maximize' && isNullOrUndefined(e.args)) {
          this.fullPreview({ mode: true, type: '' });
        } else if (!this.mdSplit.parentElement.classList.contains('e-overlay')) {
          if (e.targetItem === 'Minimize') {
            this.textArea.style.display = 'block';
            this.textArea.style.width = '100%';
            if (this.htmlPreview) { this.htmlPreview.style.display = 'none'; }
              this.mdSplit.classList.remove('e-active');
              this.mdSource.classList.remove('e-active');
          }
          this.markDownConversion();
        }
        setTimeout(() => {
          this.defaultRTE.toolbarModule.refreshToolbarOverflow();
        }, 400);
      }
    });
    this.defaultRTE.appendTo('#markdownPreview');
  }

  private markDownConversion(): void {
    if (this.mdSplit.classList.contains('e-active')) {
      let id: string = this.defaultRTE.getID() + 'html-preview';
      let htmlPreview: HTMLElement = this.defaultRTE.element.querySelector('#' + id);
      htmlPreview.innerHTML = marked((this.defaultRTE.contentModule.getEditPanel() as HTMLTextAreaElement).value);
    }
  }

  private fullPreview(e: { [key: string]: string | boolean }): void {
    let id: string = this.defaultRTE.getID() + 'html-preview';
    this.htmlPreview = this.defaultRTE.element.querySelector('#' + id);
    if ((this.mdSource.classList.contains('e-active') || this.mdSplit.classList.contains('e-active')) && e.mode) {
      this.mdSource.classList.remove('e-active');
      this.mdSplit.classList.remove('e-active');
      this.mdSource.parentElement.title = 'Preview';
      this.textArea.style.display = 'block';
      this.textArea.style.width = '100%';
      this.htmlPreview.style.display = 'none';
    } else {
      this.mdSource.classList.add('e-active');
      this.mdSplit.classList.add('e-active');
      if (!this.htmlPreview) {
        this.htmlPreview = createElement('div', { className: 'e-content' });
        this.htmlPreview.id = id;
        this.textArea.parentNode.appendChild(this.htmlPreview);
      }
      if (e.type === 'preview') {
        this.textArea.style.display = 'none'; this.htmlPreview.classList.add('e-pre-source');
      } else {
        this.htmlPreview.classList.remove('e-pre-source');
        this.textArea.style.width = '50%';
      }
      this.htmlPreview.style.display = 'block';
      this.htmlPreview.innerHTML = marked((this.defaultRTE.contentModule.getEditPanel() as HTMLTextAreaElement).value);
      this.mdSource.parentElement.title = 'Code View';
    }
  }

  render() {
    return (
      <div id="rte-default" className='control-pane'>
        <div className='control-section' id="rtePreview">
          <div className="content-wrapper">
            <div id="markdownPreview"></div>
          </div>
        </div>
      </div>
    );
  }
}
ReactDOM.render(<RTE />, document.getElementById('sample'));
<!DOCTYPE html>
<html lang="en">

<head>
    <title> Syncfusion React RichTextEditor </title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Essential JS 2 for React Components" />
    <meta name="author" content="Syncfusion" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-richtexteditor/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-lists/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-popups/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-navigations/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-dropdowns/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.19/marked.js" type="text/javascript"></script>
    <script src="systemjs.config.js"></script>
    <style>
        #loader {
            color: #008cff;
            height: 40px;
            left: 45%;
            position: absolute;
            top: 45%;
            width: 30%;
        }

        #rteMarkdown .e-richtexteditor textarea.e-content#markdownPreview_editable-content {
            float: left;
            border-right: 1px solid rgba(0, 0, 0, 0.12);
        }

        #rteMarkdown #markdownPreview .e-richtexteditor .e-rte-content .e-content {
            min-height: 150px;
        }

        #rteMarkdown #markdownPreview .e-richtexteditor .e-rte-content {
            overflow: hidden;
        }

        #rteMarkdown .e-icon-btn.e-active .e-md-preview::before {
            content: '\e350';
        }

        #rteMarkdown .e-icon-btn .e-md-preview::before {
            content: '\e345';
        }

        #rteMarkdown .e-rte-content #markdownPreviewhtml-preview.e-content {
            float: right;
            width: 50%;
            overflow: auto;
            height: inherit;
            padding: 8px;
            height: 100%;
        }

        #rteMarkdown #markdownPreview .e-rte-content .e-content.e-pre-source {
            width: 100%;
        }

        .sb-header {
            z-index: 100 !important;
        }

        #rteMarkdown {
            overflow: hidden;
        }

        #rteMarkdown .content-wrapper {
            width: auto;
            margin: 0;
        }
    </style>
</head>

<body>
    <div id='sample' style="margin: 20px auto 0;">
        <div id='loader'>Loading....</div>
    </div>
</body>

</html>

Changing table constants

The Markdown table constants can be changed for the table heading and the column names.

Source
Preview
index.tsx
index.html
/**
 * RichTextEditor - Markdown to HTML Sample
 */
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { createElement, KeyboardEventArgs } from '@syncfusion/ej2-base';
import { RichTextEditor, Toolbar, Image, Link, MarkdownEditor, Inject, IToolbarItems, QuickToolbar  } from '@syncfusion/ej2-react-richtexteditor';
import { L10n } from '@syncfusion/ej2-base';
L10n.load({
    'en-US': {
        'richtexteditor': {
            'TableHeadingText': 'Header',
            'TableColText': 'Cell'
         }
     }
});
RichTextEditor.Inject(MarkdownEditor, Image, Link, Toolbar);

export class RTE extends React.Component<{}, {}> {
  private mdSource: HTMLElement;
  private mdSplit: HTMLElement;
  private htmlPreview: HTMLElement;
  private defaultRTE: RichTextEditor;
  private textArea: HTMLTextAreaElement;

  private value: string = `***Overview***
  The rich text editor component is WYSIWYG ("what you see is what you get") editor used to create and edit the content and return valid HTML markup or markdown (MD) of the content. The editor provides a standard toolbar to format content using its commands. Modular library features to load the necessary functionality on demand. The toolbar contains commands to align the text, insert link, insert image, insert list, undo/redo operation, HTML view, and more.

  ***Key features***
  - *Mode*: Provides IFRAME and DIV mode.
  - *Module*: Modular library to load the necessary functionality on demand.
  - *Toolbar*: Provide a fully customizable toolbar.
  - *Editing*: HTML view to edit the source directly for developers.
  - *Third-party Integration*: Supports to integrate third-party library.
  - *Preview*: Preview the modified content before saving it.
  - *Tools*: Handling images, hyperlinks, video, uploads and more.
  - *Undo and Redo*: Undo/redo manager.
  - *Lists*: Creates bulleted and numbered list.`;

  public componentDidMount(): void {
    this.defaultRTE = new RichTextEditor({
      height: '300px',
      valueTemplate: this.value,
      editorMode: 'Markdown',
      toolbarSettings: {
        items: [
          'Bold', 'Italic', 'StrikeThrough', '|', 'Formats', 'OrderedList', 'UnorderedList', '|',
          'CreateLink', 'Image', 'CreateTable', '|',
          {
            tooltipText: 'Preview',
            template: '<button id="preview-code" class="e-tbar-btn e-control e-btn e-icon-btn">' +
            '<span class="e-btn-icon e-md-preview e-preview e-icons"></span></button>'
          },
          {
            tooltipText: 'Split Editor',
            template: '<button id="MD_Preview" class="e-tbar-btn e-control e-btn e-icon-btn">' +
                      '<span class="e-btn-icon e-view-side e-icons"></span></button>'
          },
          'FullScreen', '|', 'Undo', 'Redo']
        },
        created: () => {
          this.textArea = this.defaultRTE.contentModule.getEditPanel() as HTMLTextAreaElement;
          this.textArea.addEventListener('keyup', (e: KeyboardEventArgs) => {
            this.markDownConversion();
          });
          let rteObj: RichTextEditor = this.defaultRTE;
          this.mdSource = document.getElementById('preview-code');
          this.mdSource.addEventListener('click', (e: MouseEvent) => {
          this.fullPreview({ mode: true, type: 'preview' });
          if ((e.currentTarget as HTMLElement).classList.contains('e-active')) {
            this.defaultRTE.disableToolbarItem(['Bold', 'Italic', 'StrikeThrough', '|',
              'Formats', 'OrderedList', 'UnorderedList', '|',
              'CreateLink', 'Image', 'Undo', 'Redo', 'CreateTable']);
            (e.currentTarget as HTMLElement).parentElement.previousElementSibling.classList.add('e-overlay');
          } else {
            this.defaultRTE.enableToolbarItem(['Bold', 'Italic', 'StrikeThrough', '|',
              'Formats', 'OrderedList', 'UnorderedList', '|',
              'CreateLink', 'Image', 'Undo', 'Redo', 'CreateTable']);
            (e.currentTarget as HTMLElement).parentElement.previousElementSibling.classList.remove('e-overlay');
          }
        });
        this.mdSplit = document.getElementById('MD_Preview');
        this.mdSplit.addEventListener('click', (e: MouseEvent) => {
          if (this.defaultRTE.element.classList.contains('e-rte-full-screen')) {
            this.fullPreview({ mode: true, type: '' });
          }
          this.mdSource.classList.remove('e-active');
          if (!this.defaultRTE.element.classList.contains('e-rte-full-screen')) {
            this.defaultRTE.showFullScreen();
          }
        });
      },
      actionComplete: (e: any) => {
        if (e.targetItem === 'Maximize' && isNullOrUndefined(e.args)) {
          this.fullPreview({ mode: true, type: '' });
        } else if (!this.mdSplit.parentElement.classList.contains('e-overlay')) {
          if (e.targetItem === 'Minimize') {
            this.textArea.style.display = 'block';
            this.textArea.style.width = '100%';
            if (this.htmlPreview) { this.htmlPreview.style.display = 'none'; }
              this.mdSplit.classList.remove('e-active');
              this.mdSource.classList.remove('e-active');
          }
          this.markDownConversion();
        }
        setTimeout(() => {
          this.defaultRTE.toolbarModule.refreshToolbarOverflow();
        }, 400);
      }
    });
    this.defaultRTE.appendTo('#markdownPreview');
  }

  private markDownConversion(): void {
    if (this.mdSplit.classList.contains('e-active')) {
      let id: string = this.defaultRTE.getID() + 'html-preview';
      let htmlPreview: HTMLElement = this.defaultRTE.element.querySelector('#' + id);
      htmlPreview.innerHTML = marked((this.defaultRTE.contentModule.getEditPanel() as HTMLTextAreaElement).value);
    }
  }

  private fullPreview(e: { [key: string]: string | boolean }): void {
    let id: string = this.defaultRTE.getID() + 'html-preview';
    this.htmlPreview = this.defaultRTE.element.querySelector('#' + id);
    if ((this.mdSource.classList.contains('e-active') || this.mdSplit.classList.contains('e-active')) && e.mode) {
      this.mdSource.classList.remove('e-active');
      this.mdSplit.classList.remove('e-active');
      this.mdSource.parentElement.title = 'Preview';
      this.textArea.style.display = 'block';
      this.textArea.style.width = '100%';
      this.htmlPreview.style.display = 'none';
    } else {
      this.mdSource.classList.add('e-active');
      this.mdSplit.classList.add('e-active');
      if (!this.htmlPreview) {
        this.htmlPreview = createElement('div', { className: 'e-content' });
        this.htmlPreview.id = id;
        this.textArea.parentNode.appendChild(this.htmlPreview);
      }
      if (e.type === 'preview') {
        this.textArea.style.display = 'none'; this.htmlPreview.classList.add('e-pre-source');
      } else {
        this.htmlPreview.classList.remove('e-pre-source');
        this.textArea.style.width = '50%';
      }
      this.htmlPreview.style.display = 'block';
      this.htmlPreview.innerHTML = marked((this.defaultRTE.contentModule.getEditPanel() as HTMLTextAreaElement).value);
      this.mdSource.parentElement.title = 'Code View';
    }
  }

  render() {
    return (
      <div id="rte-default" className='control-pane'>
        <div className='control-section' id="rtePreview">
          <div className="content-wrapper">
            <div id="markdownPreview"></div>
          </div>
        </div>
      </div>
    );
  }
}
ReactDOM.render(<RTE />, document.getElementById('sample'));
<!DOCTYPE html>
<html lang="en">

<head>
    <title> Syncfusion React RichTextEditor </title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Essential JS 2 for React Components" />
    <meta name="author" content="Syncfusion" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-richtexteditor/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-lists/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-popups/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-navigations/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-dropdowns/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.19/marked.js" type="text/javascript"></script>
    <script src="systemjs.config.js"></script>
    <style>
        #loader {
            color: #008cff;
            height: 40px;
            left: 45%;
            position: absolute;
            top: 45%;
            width: 30%;
        }

        #rteMarkdown .e-richtexteditor textarea.e-content#markdownPreview_editable-content {
            float: left;
            border-right: 1px solid rgba(0, 0, 0, 0.12);
        }

        #rteMarkdown #markdownPreview .e-richtexteditor .e-rte-content .e-content {
            min-height: 150px;
        }

        #rteMarkdown #markdownPreview .e-richtexteditor .e-rte-content {
            overflow: hidden;
        }

        #rteMarkdown .e-icon-btn.e-active .e-md-preview::before {
            content: '\e350';
        }

        #rteMarkdown .e-icon-btn .e-md-preview::before {
            content: '\e345';
        }

        #rteMarkdown .e-rte-content #markdownPreviewhtml-preview.e-content {
            float: right;
            width: 50%;
            overflow: auto;
            height: inherit;
            padding: 8px;
            height: 100%;
        }

        #rteMarkdown #markdownPreview .e-rte-content .e-content.e-pre-source {
            width: 100%;
        }

        .sb-header {
            z-index: 100 !important;
        }

        #rteMarkdown {
            overflow: hidden;
        }

        #rteMarkdown .content-wrapper {
            width: auto;
            margin: 0;
        }
    </style>
</head>

<body>
    <div id='sample' style="margin: 20px auto 0;">
        <div id='loader'>Loading....</div>
    </div>
</body>

</html>

Custom format

The rich text editor allows you to customize the markdown syntax by overriding its default syntax. Configure the customized markdown syntax using the formatter property.

This sample demonstrates how to customize tags of markdown formatting.

For example, apply + to Unordered list, apply 2 to Ordered list, for bold, __, and for italic _.

Source
Preview
index.tsx
index.html
/**
 * RichTextEditor - Markdown - Custom Format Sample
 */
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { createElement, KeyboardEventArgs } from '@syncfusion/ej2-base';
import { RichTextEditorComponent, Toolbar, Inject, Image, Link, MarkdownEditor, MarkdownFormatter,QuickToolbar } from '@syncfusion/ej2-react-richtexteditor';

export class DefaultRTE extends React.Component<{}, {}> {
private rteObj: RichTextEditorComponent;

    // set the value to RichTextEditor
    private template: string = `The sample is configured with customized markdown syntax using the __formatter__ property. Type the content and click the toolbar item to view customized markdown syntax. For unordered list, you need to add a plus sign before the word (e.g., + list1). Or To make a phrase bold, you need to add two underscores before and after the phrase (e.g., __this text is bold__).`;

    // RichTextEditor items list
    private items: (string | IToolbarItems)[] = ['Bold', 'Italic', 'StrikeThrough', '|',
    'Formats', 'OrderedList', 'UnorderedList', '|',
    'CreateLink', 'Image', '|',
    {
        tooltipText: 'Preview',
        template: '<button id="preview-code" class="e-tbar-btn e-control e-btn e-icon-btn">' +
            '<span class="e-btn-icon e-icons e-md-preview"></span></button>'
    }, 'Undo', 'Redo'];

    private textArea: HTMLTextAreaElement;
    private mdsource: HTMLElement;
    private mdPreview: HTMLElement;

    //RichTextEditor ToolbarSettings
    private toolbarSettings: object = {
        items: this.items
    };

    private formatter =new MarkdownFormatter({
        listTags: { 'OL': '2. ', 'UL': '+ ' },
        formatTags: {
            'Blockquote': '> '
        },
        selectionTags: {'Bold': '__',  'Italic': '_'}
    });

    public markDownConversion(): void {
        if (this.mdsource.classList.contains('e-active')) {
            let id: string = (this.rteObj as any).getID() + 'html-view';
            let htmlPreview: HTMLElement = (this.rteObj as any).element.querySelector('#' + id);
            htmlPreview.innerHTML = Marked(((this.rteObj as any).contentModule.getEditPanel() as HTMLTextAreaElement).value);
        }
    }
    public fullPreview(): void {
        let id: string = this.rteObj.getID() + 'html-preview';
        let htmlPreview: HTMLElement = this.rteObj.element.querySelector('#' + id);
        if (this.mdsource.classList.contains('e-active')) {
            this.mdsource.classList.remove('e-active');
            this.mdsource.parentElement.title = 'Preview';
            this.rteObj.enableToolbarItem(this.rteObj.toolbarSettings.items as string[]);
            this.textArea.style.display = 'block';
            htmlPreview.style.display = 'none';
        } else {
            this.mdsource.classList.add('e-active');
            this.rteObj.disableToolbarItem(this.rteObj.toolbarSettings.items as string[]);
            if (!htmlPreview) {
                htmlPreview = createElement('div', { className: 'e-content e-pre-source' });
                htmlPreview.id = id;
                this.textArea.parentNode.appendChild(htmlPreview);
            }
            this.textArea.style.display = 'none';
            htmlPreview.style.display = 'block';
            htmlPreview.innerHTML = Marked((this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement).value);
            this.mdsource.parentElement.title = 'Code View';
        }
    }
    public rendereComplete(): void {
        this.mdPreview = document.getElementById('MD_Preview');
        this.textArea = this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement;
        this.textArea.addEventListener('keyup', (e: KeyboardEventArgs) => {
            this.markDownConversion();
        });
        this.mdsource = document.getElementById('preview-code');
        this.mdsource.addEventListener('click', (e: MouseEvent) => {
            this.fullPreview();
        });
    }
    render() {
        return (
                            <RichTextEditorComponent id="markdownRTE"
                                ref={(richtexteditor) => { this.rteObj = richtexteditor }}
                                height='260px' editorMode='Markdown'
                                formatter= {this.formatter}
                                valueTemplate={this.template} toolbarSettings={this.toolbarSettings} >
                                <Inject services={[MarkdownEditor, Toolbar, Image, Link, QuickToolbar]} />
                            </RichTextEditorComponent>
        );
    }
}

ReactDOM.render(<DefaultRTE />, document.getElementById('sample'));
<!DOCTYPE html>
<html lang="en">

<head>
    <title> Syncfusion React RichTextEditor </title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Essential JS 2 for React Components" />
    <meta name="author" content="Syncfusion" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-richtexteditor/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-lists/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-popups/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-navigations/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-react-dropdowns/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.19/marked.js" type="text/javascript"></script>
    <script src="systemjs.config.js"></script>
    <style>
        #loader {
            color: #008cff;
            height: 40px;
            left: 45%;
            position: absolute;
            top: 45%;
            width: 30%;
        }

        #rteMarkdown .e-richtexteditor textarea.e-content#markdownPreview_editable-content {
            float: left;
            border-right: 1px solid rgba(0, 0, 0, 0.12);
        }

        #rteMarkdown #markdownPreview .e-richtexteditor .e-rte-content .e-content {
            min-height: 150px;
        }

        #rteMarkdown #markdownPreview .e-richtexteditor .e-rte-content {
            overflow: hidden;
        }

        #rteMarkdown .e-icon-btn.e-active .e-md-preview::before {
            content: '\e350';
        }

        #rteMarkdown .e-icon-btn .e-md-preview::before {
            content: '\e345';
        }

        #rteMarkdown .e-rte-content #markdownPreviewhtml-preview.e-content {
            float: right;
            width: 50%;
            overflow: auto;
            height: inherit;
            padding: 8px;
            height: 100%;
        }

        #rteMarkdown #markdownPreview .e-rte-content .e-content.e-pre-source {
            width: 100%;
        }

        .sb-header {
            z-index: 100 !important;
        }

        #rteMarkdown {
            overflow: hidden;
        }

        #rteMarkdown .content-wrapper {
            width: auto;
            margin: 0;
        }
    </style>
</head>

<body>
    <div id='sample' style="margin: 20px auto 0;">
        <div id='loader'>Loading....</div>
    </div>
</body>

</html>