Use it online: Go

πŸ”– MdPreview Props

This is the props of MdPreview, which is also part of MdEditor:

πŸ“ƒ value

  • type: string

  • default: ''

    Markdown content.

    jsx Copy
    <MdEditor value="xxx" />

πŸ“ƒ modelValue

  • type: string

  • default: ''

    Deprecated. Starting from version 5.x, Replace with value.


πŸ› theme

  • type: 'light' | 'dark'

  • default: 'light'

    Editor's theme.

    jsx Copy
    <MdEditor theme="dark" />

πŸŽ€ className

  • type: string

  • default: ''

    ...


πŸ”€ language

  • type: string

  • default: 'zh-CN'

    Build-in language('zh-CN', 'en-US').

    You can install the existing language also: md-editor-extension. Refer to extension library for the usage and the way to contribute~


🎲 editorId

  • type: string

  • default: 'md-editor-v-\d'

    Deprecated. Starting from version 5.x, Replace with id.

    Unique identifier of the editor, use the default prefix and useId for concatenation. When using server-side rendering, make sure to set this attribute to a constant value.,Starting from version 5.0, there is no such limitation.


🎲 id

  • type: string

  • default: 'md-editor-v-\d'

    Unique identifier of the editor, use the default prefix and useId for concatenation.


πŸ”’ showCodeRowNumber

  • type: boolean

  • default: true

    Show row number for code block or not.


πŸ”¦ previewTheme

  • type: 'default' | 'github' | 'vuepress' | 'mk-cute' | 'smart-blue' | 'cyanosis'

  • default: 'default'

    Preview themes.

    Custom:

    1. Write css
    css Copy
    .xxx-theme {
      color: red;
    }
    1. Set previewTheme
    jsx Copy
    <MdEditor previewTheme="xxx" />

    For more, refer to markdown-theme.


πŸŽ…πŸ» style

  • type: CSSProperties

  • default: {}

    Editor inline style.


☝️ noMermaid

  • type: boolean

  • default: false

    do not want to use mermaid, set it to true.

    jsx Copy
    <MdEditor noMermaid />

❌ noKatex

  • type: boolean

  • default: false

    Do not want to use katex, set it to true.


πŸ¦‰ codeTheme

  • type: 'atom'|'a11y'|'github'|'gradient'|'kimbie'|'paraiso'|'qtcreator'|'stackoverflow'

  • default: 'atom'

    Highlight code css name. Get Them from highlight.js.

    Custom:

    1. Config editorExtensions
    js Copy
    import { config } from 'md-editor-rt';
    
    config({
      editorExtensions: {
        highlight: {
          css: {
            atom: {
              light:
                'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/atom-one-light.min.css',
              dark: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/atom-one-dark.min.css',
            },
            xxx: {
              light:
                'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/xxx-light.css',
              dark: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/xxx-dark.css',
            },
          },
        },
      },
    });
    1. Set codeTheme
    jsx Copy
    <MdEditor codeTheme="xxx" />

🎱 mdHeadingId

  • type: (text: string, level: number, index: number) => string

  • default: (text) => text

    Title ID generator.

    jsx Copy
    import { MdEditor } from 'md-editor-rt';
    import 'md-editor-rt/lib/style.css';
    
    const mdHeadingId = (_text, _level, index) => `heading-${index}`;
    
    export default () => {
      return <MdEditor mdHeadingId={mdHeadingId} />;
    };

🐣 sanitize

  • type: (html: string) => string

  • default: (html) => html

    This attribute is used to alter the compiled HTML content.

    This is a reserved attribute.

    Basic solution for dangerous code has been built-in since version 3.x. eg: <script>alert(123)</script>. Prior to version 4.11.3, it was recommended to utilize this attribute for cleaning more complex content to prevent XSS attacks.

    A more comprehensive solution has been implemented since version 4.11.3. Refer to

    sanitize-html example:

    jsx Copy
    import sanitizeHtml from 'sanitize-html';
    import { MdEditor } from 'md-editor-rt';
    import 'md-editor-rt/lib/style.css';
    
    const sanitize = (html) => sanitizeHtml(html);
    
    export default () => {
      return <MdEditor sanitize={sanitize} />;
    };

πŸ’… formatCopiedText

  • type: (text: string) => string

  • default: (text) => text

    Format copied code

    jsx Copy
    import { MdEditor } from 'md-editor-rt';
    import 'md-editor-rt/lib/style.css';
    
    export default () => {
      const formatCopiedText = (text: string) => {
        return `${text}  - from md-editor-rt`;
      };
    
      return <MdEditor formatCopiedText={formatCopiedText} />;
    };

πŸ› codeStyleReverse

  • type: boolean

  • default: true

    Code style will be reversed to dark while code block of the theme has a dark background.


🧼 codeStyleReverseList

  • type: Array

  • default: ['default', 'mk-cute']

    Themes to be reversed.


πŸ•Š noHighlight

  • type: boolean

  • default: false

    never highlight code


πŸ•Š noImgZoomIn

  • type: boolean

  • default: false

    Enable the function of enlarging images.

    html Copy
    <MdEditor noImgZoomIn />

    After version 4.15.4, it is also possible to disable zooming by setting the class .not-zoom.

    markdown Copy
    <img class="not-zoom">

😬 customIcon

  • type: CustomIcon

  • default: {}

    Customized icons

    Type Warning

    The icon corresponding to copy and collapse-tips can only be a string, while others can be components or strings

    tsx Copy
    import React from 'react';
    import type { CustomIcon } from 'md-editor-rt';
    import { MdEditor, StrIcon } from 'md-editor-rt';
    // Assuming you have installed an icon library or customized icon components
    import { IconFont } from 'tdesign-icons-react';
    import 'md-editor-rt/lib/style.css';
    
    const customIcon: CustomIcon = {
      bold: {
        component: 'A',
      },
      // Demonstrating the use of default icons
      copy: StrIcon('copy', {}),
      // copy: '<i class="fa fa-car"></i>',
      // 'collapse-tips': '<i class="fa fa-car"></i>',
      preview: {
        component: '<i class="fa fa-car"></i>',
      },
      github: {
        component: IconFont,
        props: {
          name: 'sneer',
        },
      },
    };
    
    export default () => {
      return <MdEditor modelValue="" customIcon={customIcon} />;
    };

    Type CustomIcon

    ts Copy
    type IconName =
      | 'bold'
      | 'underline'
      | 'italic'
      | 'strike-through'
      | 'title'
      | 'sub'
      | 'sup'
      | 'quote'
      | 'unordered-list'
      | 'ordered-list'
      | 'task'
      | 'code-row'
      | 'code'
      | 'link'
      | 'image'
      | 'table'
      | 'revoke'
      | 'next'
      | 'save'
      | 'prettier'
      | 'minimize'
      | 'maximize'
      | 'fullscreen-exit'
      | 'fullscreen'
      | 'preview-only'
      | 'preview'
      | 'preview-html'
      | 'catalog'
      | 'github'
      | 'mermaid'
      | 'formula'
      | 'close'
      | 'delete'
      | 'upload'
      | 'collapse-tips';
    
    type CustomIcon = {
      [key in IconName]?: {
        component: Component | JSX.Element | string;
        props: {
          [key: string | number | symbol]: any;
        };
      };
    } & {
      copy?: string;
    };

πŸ•Š sanitizeMermaid

  • type: (h: string) => Promise<string>

  • default: (h: string) => Promise.resolve(h)

    Convert the generated mermaid code


πŸ•Ή codeFoldable

  • type: boolean

  • default: true

    Whether to enable code folding feature


⏲ autoFoldThreshold

  • type: number

  • default: 30

    Threshold for triggering automatic code folding by line count


πŸ”© MdEditor Props

Except for the same as MdPreview:

πŸ’» pageFullscreen

  • type: boolean

  • default: false

    Screenfull in web page.


πŸ“± preview

  • type: boolean

  • default: true

    Preview content in editor.


πŸ“€ htmlPreview

  • type: boolean

  • default: false

    Preview html in editor. Set preview to false when htmlPreview is true.


🧱 toolbars

  • type: Array

  • default: [all]

    Show contents of toolbar.

    You can sort the toolbar as you like, split tools by '-', the left and right toolbars are divided by '='!

    [all]

    js Copy
    [
      'bold',
      'underline',
      'italic',
      '-',
      'strikeThrough',
      'sub',
      'sup',
      'quote',
      'unorderedList',
      'orderedList',
      'task',
      '-',
      'codeRow',
      'code',
      'link',
      'image',
      'table',
      'mermaid',
      'katex',
      '-',
      'revoke',
      'next',
      'save',
      '=',
      'pageFullscreen',
      'fullscreen',
      'preview',
      'previewOnly',
      'htmlPreview',
      'catalog',
      'github',
    ];

🧱 toolbarsExclude

  • type: Array

  • default: []

    Don't show some item of toolbars, all keys.


πŸ’ͺ defToolbars

  • type: Array<VNode>

  • default: []

    Custom toolbar in DropdownToolbar, NormalToolbar or ModalToolbar. To display them, put index of defToolbars into toolbars(this is not standard).

    jsx Copy
    import { MdEditor, NormalToolbar } from 'md-editor-rt';
    import 'md-editor-rt/lib/style.css';
    
    const handler = () => {
      console.log('NormalToolbar clicked!');
    };
    
    const toolbars = ['github', '=', 0];
    
    const defToolbars = [
      <NormalToolbar
        title="mark"
        onClick={handler}
        trigger={
          <svg className="md-editor-icon" aria-hidden="true">
            <use xlinkHref="#icon-mark"></use>
          </svg>
        }
      />,
    ];
    
    export default () => {
      return (
        <MdEditor modelValue="" toolbars={toolbars} defToolbars={defToolbars} />
      );
    };
    NormalToolbar
    DropdownToolbar

    For more info, Get Internal Components heading. Get source code of mark, emoji and modal preview at docs branch.


πŸͺ’ noPrettier

  • type: boolean

  • default: true

    Use prettier to beautify content or not.


🀏 tabWidth

  • type: number

  • default: 2

    One tab eq some space.


πŸ“… tableShape

  • type: [number, number] \| [number, number, number, number]

  • default: [6, 4]

    Preset the size of the table, [columns, rows, Maximum number of columns, Maximum number of rows]

    jsx Copy
    const tableShape = [8, 4];
    
    () => <MdEditor tableShape={tableShape}>
    Preview

πŸͺ§ placeholder

  • type: string

  • default: ''

    em-_-!


🦢 footers

  • type: Array<'markdownTotal' \| '=' \| 'scrollSwitch' \| number>

  • default: ['markdownTotal', '=', 'scrollSwitch']

    Show contents of footer, they are divided by '='. Set it to [] to hidden footer.


🦿 defFooters

  • type: Array<ReactNode>

  • default: []

    Custom footer.

    Get example code.


⛡️ scrollAuto

  • type: boolean

  • default: true

    Scroll default setting.


πŸ₯Ή noUploadImg

  • type: boolean

  • default: false

    Not show the entrance to upload pictures

    jsx Copy
    import { MdEditor } from 'md-editor-rt';
    import 'md-editor-rt/lib/style.css';
    
    export default () => {
      return <MdEditor noUploadImg />;
    };

πŸ”¬ autoFocus

  • type: boolean

  • default: false

    Same as autofocus in native textarea.


πŸ”© disabled

  • type: boolean

  • default: false

    Same as disabled in native textarea.


πŸ”’ readOnly

  • type: boolean

  • default: false

    Same as readonly in native textarea.


πŸ“ maxLength

  • type: number

  • default: ``

    Same as maxlength in native textarea.


πŸ“₯ autoDetectCode

  • type: boolean

  • default: false

    Auto detect the type of pasted code, only support that copied from vscode.


πŸ“ completions

  • type: Array<CompletionSource>

  • default: []

    Additional completion sources.

    tsx Copy
    import { useMemo, useState } from 'react';
    import { CompletionSource } from '@codemirror/autocomplete';
    import { MdEditor } from 'md-editor-rt';
    import 'md-editor-rt/lib/style.css';
    
    export default () => {
      const [t, s] = useState('');
    
      const completions = useMemo<Array<CompletionSource>>(() => {
        return [
          (context) => {
            const word = context.matchBefore(/@\w*/);
    
            if (word === null || (word.from == word.to && context.explicit)) {
              return null;
            }
    
            return {
              from: word.from,
              options: [
                {
                  label: '@imzbf',
                  type: 'text',
                },
              ],
            };
          },
        ];
      }, []);
    
      return <MdEditor modelValue={t} onChange={s} completions={completions} />;
    };

πŸ“₯ showToolbarName

  • type: boolean

  • default: false

    Show toolbar name or not


πŸ“₯ inputBoxWidth

  • type: string

  • default: 50%

    Default width of input box


πŸ“₯ transformImgUrl

  • type: (imgUrl: string) => string | Promise<string>

  • default: t => t

    Transform image links


🧡 MdPreview Events

🚁 onHtmlChanged

  • type: (h: string) => void

    Compile markdown successful event, you can use it to get the html code.


πŸ—’ onGetCatalog

  • type: (list: HeadList[]) => void

    Get catalogue of article.


πŸͺ’ MdEditor Events

Except for the same as MdPreview:

πŸ“ž onChange

  • type: (v: string) => void

    Content changed event(bind to oninput of textarea).


πŸ’Ύ onSave

  • type: (v: string, h: Promise<string>) => void

    Saving content event, ctrl+s and clicking button will trigger it.

    jsx Copy
    import { MdEditor } from 'md-editor-rt';
    import 'md-editor-rt/lib/style.css';
    
    const onSave = (v, h) => {
      console.log(v);
    
      h.then((html) => {
        console.log(html);
      });
    };
    
    export default () => <MdEditor onSave={onSave} />;

πŸ“Έ onUploadImg

  • type: files: Array<File>, callback: (urls: string[] | { url: string; alt: string; title: string }[]) => void

    Uploading picture event, when picture is uploading the modal will not close, please provide right urls to the callback function.

    jsx Copy
    import React, { useState } from 'react';
    import { MdEditor } from 'md-editor-rt';
    import 'md-editor-rt/lib/style.css';
    
    const onUploadImg = async (files, callback) => {
      const res = await Promise.all(
        files.map((file) => {
          return new Promise((rev, rej) => {
            const form = new FormData();
            form.append('file', file);
    
            axios
              .post('/api/img/upload', form, {
                headers: {
                  'Content-Type': 'multipart/form-data',
                },
              })
              .then((res) => rev(res))
              .catch((error) => rej(error));
          });
        })
      );
    
      // Approach 1
      callback(res.map((item) => item.data.url));
      // Approach 2
      // callback(
      //   res.map((item: any) => ({
      //     url: item.data.url,
      //     alt: 'alt',
      //     title: 'title'
      //   }))
      // );
    };
    
    export default () => {
      const [text, setText] = useState('# Hello Editor');
    
      return (
        <MdEditor
          modelValue={text}
          onChange={setText}
          onUploadImg={onUploadImg}
        />
      );
    };

πŸ’€ onError

  • type: (err: { name: 'Cropper' \| 'fullscreen' \| 'prettier' \| 'overlength'; message: string }) => void

    Run-Time error event, only be called when Cropper, fullscreen, prettier is not loaded. And content exceeds the length limit error.

    jsx Copy
    const onError = (err) => {
      alert(err.message);
    };
    
    export default () => <MdEditor onError={onError} />;

🐾 onBlur

  • type: (event: FocusEvent<HTMLTextAreaElement, Element>) => void

    Textarea has lost focus.

    jsx Copy
    const onBlur = (err) => {
      console.log('onBlur', e);
    };
    
    export default () => <MdEditor onBlur={onBlur} />;

πŸ”– onFocus

  • type: (event: FocusEvent<HTMLTextAreaElement, Element>) => void

    Textarea has received focus.


πŸ”– onInput

  • type: (event: Event) => void

    Element gets input.


πŸ”– onDrop

  • type: (event: DragEvent) => void

    The event occurs when a selection is being dragged.

    jsx Copy
    import { useState } from 'react';
    import { MdEditor } from 'md-editor-rt';
    import 'md-editor-rt/lib/style.css';
    
    const onDrop = (e) => {
      e.preventDefault();
      console.log(e.dataTransfer?.files[0]);
    };
    
    export default () => {
      const [text, setText] = useState('');
      return <MdEditor modelValue={text} onChange={setText} onDrop={onDrop} />;
    };

πŸ”– onInputBoxWidthChange

  • type: (width: string) => void

    Event occurs when width of input box has been changed


🀱🏼 Expose

After 2.5.0, Editor exposes several methods on the instance, used to get or change the internal status of the editor.

jsx Copy
import React, { useState, useEffect, useRef } from 'react';
import { MdEditor, ExposeParam } from 'md-editor-rt';
//
// import type { ExposePreviewParam } from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';

export default () => {
  const [text, setText] = useState('#Hello Editor');

  const editorRef = useRef<ExposeParam>();

  useEffect(() => {
    editorRef.current?.on('catalog', console.log);
  }, []);

  return <MdEditor ref={editorRef} modelValue={text} onChange={setText} />;
};
Name MdEditor MdPreview
on √ Γ—
togglePageFullscreen √ Γ—
toggleFullscreen √ Γ—
togglePreview √ Γ—
togglePreviewOnly √ Γ—
toggleHtmlPreview √ Γ—
toggleCatalog √ Γ—
triggerSave √ Γ—
insert √ Γ—
focus √ Γ—
rerender √ √
getSelectedText √ Γ—
resetHistory √ Γ—

πŸ‘‚πŸΌ on

Get the internal state of the editor, including pageFullscreen, fullscreen, preview, htmlPreview, catalog, etc.

  • pageFullscreen

    js Copy
    editorRef.current?.on('pageFullscreen', (status) => console.log(status));
  • fullscreen

    js Copy
    editorRef.current?.on('fullscreen', (status) => console.log(status));
  • preview

    js Copy
    editorRef.current?.on('preview', (status) => console.log(status));
  • previewOnly

    js Copy
    editorRef.current?.on('previewOnly', (status) => console.log(status));
  • htmlPreview

    js Copy
    editorRef.current?.on('htmlPreview', (status) => console.log(status));
  • catalog

    js Copy
    editorRef.current?.on('catalog', (status) => console.log(status));

πŸ’» togglePageFullscreen

Toggle status of fullscreen within the page.

js Copy
editorRef.current?.togglePageFullscreen(true);

Switched to the opposite status, without input parameter.


πŸ–₯ toggleFullscreen

Toggle status of fullscreen widthin browser.

js Copy
editorRef.current?.toggleFullscreen(true);

Switched to the opposite status, without input parameter.


πŸ“– togglePreview

Toggle status of preview.

js Copy
editorRef.current?.togglePreview(true);

Switched to the opposite status, without input parameter.


πŸ“– togglePreviewOnly

Toggle into Preview Only Mode.

js Copy
editorRef.current?.togglePreviewOnly(true);

Switched to the opposite status, without input parameter.


πŸ“Ό toggleHtmlPreview

Toggle status of htmlPreview.

js Copy
editorRef.current?.toggleHtmlPreview(true);

Switched to the opposite status, without input parameter.


🧬 toggleCatalog

Toggle status of catalog.

js Copy
editorRef.current?.toggleCatalog(true);

Switched to the opposite status, without input parameter.


πŸ’Ύ triggerSave

js Copy
editorRef.current?.triggerSave();

πŸ’‰ insert

Manually insert content into textarea.

js Copy
/**
 * @params selectedText
 */
editorRef.current?.insert((selectedText) => {
  /**
   * @return targetValue    Content to be inserted
   * @return select         Automatically select content, default: true
   * @return deviationStart Start position of the selected content, default: 0
   * @return deviationEnd   End position of the selected content, default: 0
   */
  return {
    targetValue: `${selectedText}`,
    select: true,
    deviationStart: 0,
    deviationEnd: 0,
  };
});

🎯 focus

Focus on the textarea.

ts Copy
import type { FocusOption } from 'md-editor-rt';

const option: FocusOption | undefined = 'start';

// Cursor position when focusing on textarea, default: position when it last lost focus
editorRef.current?.focus(option);
ts Copy
type FocusOption =
  | 'start'
  | 'end'
  | {
      // Start position, default cursor position
      rangeAnchor?: number;
      // End position, default cursor position
      rangeHead?: number;
      // Cursor position
      cursorPos: number;
    };

βœ’οΈ rerender

Re render the content.

js Copy
editorRef.current?.rerender();

πŸ” getSelectedText

Get the currently selected text.

js Copy
console.log(editorRef.current?.getSelectedText());

πŸ—‘ resetHistory

Clear current history.


πŸŽ› domEventHandlers

Supports listening to all DOM events.

js Copy
editorRef.current?.domEventHandlers({
  compositionstart: () => {
    console.log('compositionstart');
  },
});

πŸŽ› execCommand

Insert content into the editor via trigger.

js Copy
editorRef.current?.execCommand('bold');

πŸ”– getEditorView

Get codemirror instance.


πŸ’΄ Config Editor

Use config(option: ConfigOption) to reconfigure markdown-it and so on.

We recommend configuring it at the project entry point, such as in main.js for projects created with Vite. Avoid calling config within components!

πŸ¦ͺ codeMirrorExtensions

Customize new extensions based on theme and default extensions f codeMirror.

ts Copy
type CodeMirrorExtensions = (
  theme: Themes,
  extensions: Array<Extension>,
  keyBindings: Array<KeyBinding>,
  options: {
    editorId: string;
  }
) => Array<Extension>;

Example: Editor does not render the line number of textarea by default, this extension needs to be manually added

js Copy
import { config } from 'md-editor-rt';
import { lineNumbers } from '@codemirror/view';

config({
  codeMirrorExtensions(_theme, extensions) {
    return [...extensions, lineNumbers()];
  },
});

🍀 markdownItConfig

Customize extensions, attributes of markdown-it, etc.

ts Copy
type MarkdownItConfig = (
  md: markdownit,
  options: {
    editorId: string;
  }
) => void;

Example: Use markdown-it-anchor to render a hyperlink symbol to the right of the title

js Copy
import { config } from 'md-editor-rt';
import ancher from 'markdown-it-anchor';

config({
  markdownItConfig(mdit) {
    mdit.use(ancher, {
      permalink: true,
    });
  },
});

🍀 markdownItPlugins

Select and add built-in plugins to markdown-it.

ts Copy
type MarkdownItPlugins = (
  plugins: Array<MarkdownItConfigPlugin>,
  options: {
    editorId: string;
  }
) => Array<MarkdownItConfigPlugin>;

Example: Modify the class name of the image.

js Copy
import { config } from 'md-editor-rt';

config({
  markdownItPlugins(plugins) {
    return plugins.map((p) => {
      if (p.type === 'image') {
        return {
          ...p,
          options: {
            ...p.options,
            classes: 'my-class',
          },
        };
      }

      return p;
    });
  },
});

πŸ™ editorConfig

Add more languages, reset mermaid template or delay rendering time

🍚 languageUserDefined

js Copy
import { config } from 'md-editor-rt';

config({
  editorConfig: {
    languageUserDefined: {
      'en-US': {
        toolbarTips: {
          bold: 'bold',
          underline: 'underline',
          italic: 'italic',
          strikeThrough: 'strikeThrough',
          title: 'title',
          sub: 'subscript',
          sup: 'superscript',
          quote: 'quote',
          unorderedList: 'unordered list',
          orderedList: 'ordered list',
          codeRow: 'inline code',
          code: 'block-level code',
          link: 'link',
          image: 'image',
          table: 'table',
          mermaid: 'mermaid',
          katex: 'formula',
          revoke: 'revoke',
          next: 'undo revoke',
          save: 'save',
          prettier: 'prettier',
          pageFullscreen: 'fullscreen in page',
          fullscreen: 'fullscreen',
          preview: 'preview',
          previewOnly: 'previewOnly',
          htmlPreview: 'html preview',
          catalog: 'catalog',
          github: 'source code',
        },
        titleItem: {
          h1: 'Lv1 Heading',
          h2: 'Lv2 Heading',
          h3: 'Lv3 Heading',
          h4: 'Lv4 Heading',
          h5: 'Lv5 Heading',
          h6: 'Lv6 Heading',
        },
        imgTitleItem: {
          link: 'Add Img Link',
          upload: 'Upload Img',
          clip2upload: 'Clip Upload',
        },
        linkModalTips: {
          linkTitle: 'Add Link',
          imageTitle: 'Add Image',
          descLabel: 'Desc:',
          descLabelPlaceHolder: 'Enter a description...',
          urlLabel: 'Link:',
          urlLabelPlaceHolder: 'Enter a link...',
          buttonOK: 'OK',
        },
        clipModalTips: {
          title: 'Crop Image',
          buttonUpload: 'Upload',
        },
        copyCode: {
          text: 'Copy',
          successTips: 'Copied!',
          failTips: 'Copy failed!',
        },
        mermaid: {
          flow: 'flow',
          sequence: 'sequence',
          gantt: 'gantt',
          class: 'class',
          state: 'state',
          pie: 'pie',
          relationship: 'relationship',
          journey: 'journey',
        },
        katex: {
          inline: 'inline',
          block: 'block',
        },
        footer: {
          markdownTotal: 'Word Count',
          scrollAuto: 'Scroll Auto',
        },
      },
    },
  },
});

🍘 mermaidTemplate

js Copy
import { config } from 'md-editor-rt';

config({
  editorConfig: {
    // mermaid template
    mermaidTemplate: {
      flow: `flow tempalte`,
      sequence: `sequence template`,
      gantt: `gantt template`,
      class: `class template`,
      state: `state template`,
      pie: `pie template`,
      relationship: `relationship template`,
      journey: `journey template`,
    },
  },
});

πŸ₯ renderDelay

js Copy
import { config } from 'md-editor-rt';

config({
  editorConfig: {
    // delay rendering time(ms)
    renderDelay: 0,
  },
});

πŸ₯ zIndex

js Copy
import { config } from 'md-editor-rt';

config({
  editorConfig: {
    // for modal component
    zIndex: 2000,
  },
});

πŸ₯  editorExtensions

Config some dependency libraries, like highlight..

typescript Copy
import { config } from 'md-editor-rt';

config({
  editorExtensions: { highlight: { js: 'https://xxx.cc' } },
});
ts Copy
export interface EditorExtensions {
  highlight?: {
    instance?: any;
    js?: string;
    css?: {
      [key: string]: {
        light: string;
        dark: string;
      };
    };
  };
  prettier?: {
    // >= 2.2.0
    prettierInstance?: any;
    parserMarkdownInstance?: any;

    standaloneJs?: string;
    parserMarkdownJs?: string;
  };
  cropper?: {
    instance?: any;
    js?: string;
    css?: string;
  };
  screenfull?: {
    instance?: any;
    js?: string;
  };
  mermaid?: {
    instance?: any;
    js?: string;
  };
  katex?: {
    instance?: any;
    js?: string;
    css?: string;
  };
}

πŸ₯  editorExtensionsAttrs

Synchronously add attributes to the CDN link tags, consistent with the type of editorExtensions, with a value type of HTMLElementTagNameMap['tagName'].

js Copy
import { config } from 'md-editor-rt';

config({
  editorExtensionsAttrs: {
    highlight: {
      js: {
        className: 'hglh-js',
      },
      css: {
        atom: {
          light: {
            className: 'atom-light-css',
          },
          dark: {
            className: 'atom-dark-css',
          },
        },
      },
    },
  },
});

Example of using built-in basic configuration:

js Copy
import { config, editorExtensionsAttrs } from 'md-editor-rt';

config({
  editorExtensionsAttrs,
});

Warning

Do not attempt to define the src \ onload \ id of the script and rel \ href \ id of the link in editorExtensionsAttrs, as they will be overwritten by default values


🎨 mermaidConfig

Configure mermaid, Details

js Copy
import { config } from 'md-editor-rt';
config({
  mermaidConfig(base: any) {
    return {
      ...base,
      logLevel: 'error',
    };
  },
});

πŸ”§ katexConfig

Configure katex, Details

js Copy
import { config } from 'md-editor-rt';

config({
  katexConfig(base: any) {
    return {
      ...base,
      strict: false,
    };
  },
});

πŸͺ‘ Shortcut Keys

Pay attention

Shortcut keys are only available when the textarea has received focus!

key function description
TAB insert space Insert space, the length eq tabWidth, default: 2, support multiline
SHIFT + TAB delete space, setting is the same as Tab
CTRL + C copy When selected, copy the selected content. When not selected, copy the content of the current line
CTRL + X shear When selected, cut the selected content. When not selected, cut the current line
CTRL + D delete When selected, delete the selected content. When not selected, delete the current line
CTRL + S save Trigger onSave event
CTRL + B bold text **bold**
CTRL + U underline <u>underline</u>
CTRL + I italic *italic*
CTRL + 1-6 h1-h6 # title
CTRL + ↑ superscript <sup>superscript</sup>
CTRL + ↓ subscript <sub>subscript</sub>
CTRL + O ordered list 1. ordered list
CTRL + L link [link](https://github.com/imzbf/md-editor-rt)
CTRL + Z withdraw Withdraw history in editor, not the function of system
CTRL + F find and replace
CTRL + SHIFT + S line-through ~line-through~
CTRL + SHIFT + U unordered list - unordered list
CTRL + SHIFT + C code block
CTRL + SHIFT + I picture ![picture](https://github.com/imzbf)
CTRL + SHIFT + Z forward Forward history in editor, not the function of system
CTRL + SHIFT + F Beautify
CTRL + ALT + C code row
CTRL + SHIFT + ALT + T table |table|

πŸͺ€ Internal components

On-demand import, eg: import { DropdownToolbar } from 'md-editor-rt'.

Built-in attribute

To help developers quickly insert content and use editor attributes, the editor component has added the following attribute values to the written extension component by default:

name example
insert Refer to the DropdownToolbar component example below
theme Refer to the extension components in the ExportPDF
previewtheme Same as above
language Same as above

🐣 NormalToolbar

  • props

    • title: string, not required, title of toolbar.
    • trigger: ReactNode, required, it is usually an icon, which is displayed on the toolbar.
  • events

    • onClick: (e: MouseEvent) => void, required.

usage:

jsx Copy
import { useCallback, useState } from 'react';
import { MdEditor, NormalToolbar } from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';

/**
 * `insert` will be automatically injected into the component by the editor
 */
const MyToolbar = ({ insert = () => {} }) => {
  const onClick = useCallback(() => {
    insert((selectedText) => {
      /**
       * @return targetValue    Content to be inserted
       * @return select         Automatically select content, default: true
       * @return deviationStart Start position of the selected content, default: 0
       * @return deviationEnd   End position of the selected content, default: 0
       */
      return {
        targetValue: `==${selectedText}==`,
        select: true,
        deviationStart: 0,
        deviationEnd: 0,
      };
    });
  }, [insert]);

  return (
    <NormalToolbar
      title="mark"
      trigger={
        <svg className="md-editor-icon" aria-hidden="true">
          <use xlinkHref="#icon-mark"></use>
        </svg>
      }
      onClick={onClick}
      key="mark-toolbar"
    />
  );
};

const toolbars = ['bold', 0, '=', 'github'];
const defToolbars = [<MyToolbar />];

export default () => {
  const [value, setValue] = useState('');

  return (
    <MdEditor
      modelValue={value}
      id="md-prev"
      toolbars={toolbars}
      defToolbars={defToolbars}
      onChange={setValue}
    />
  );
};

MarkExtension Source Code


  • props

    • title: string, not required, title of toolbar.
    • visible: boolean, required.
    • trigger: ReactNode, required, it is usually an icon, which is displayed on the toolbar.
    • overlay: ReactNode, required, content of dropdown box.
  • events

    • onChange: (visible: boolean) => void, required.

usage:

jsx Copy
import { useCallback, useState } from 'react';
import { MdEditor, DropdownToolbar } from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';

/**
 * `insert` will be automatically injected into the component by the editor
 */
const MyToolbar = ({ insert = () => {} }) => {
  const [visible, setVisible] = useState(false);

  const onClick = useCallback(() => {
    insert((selectedText) => {
      /**
       * @return targetValue    Content to be inserted
       * @return select         Automatically select content, default: true
       * @return deviationStart Start position of the selected content, default: 0
       * @return deviationEnd   End position of the selected content, default: 0
       */
      return {
        targetValue: `==${selectedText}==`,
        select: true,
        deviationStart: 0,
        deviationEnd: 0,
      };
    });
  }, [insert]);

  return (
    <DropdownToolbar
      visible={visible}
      onChange={setVisible}
      overlay={
        <ul>
          <li onClick={onClick}>option 1</li>
          <li>option 2</li>
        </ul>
      }
      trigger={
        <svg className="md-editor-icon" aria-hidden="true">
          <use xlinkHref="#icon-emoji"></use>
        </svg>
      }
      key="emoji-toolbar"
    />
  );
};

const toolbars = ['bold', 0, '=', 'github'];
const defToolbars = [<MyToolbar key="key" />];

export default () => {
  const [value, setValue] = useState('');

  return (
    <MdEditor
      modelValue={value}
      id="md-prev"
      toolbars={toolbars}
      defToolbars={defToolbars}
      onChange={setValue}
    />
  );
};

EmojiExtension Source Code


πŸ¦‰ ModalToolbar

  • props

    • title: string, not required, title of toolbar.
    • modalTitle: ReactNode, not required, title of the Modal.
    • visible: boolean, required, visibility of Modal.
    • width: string, not required, width of Modal, default auto.
    • height: string, same as width.
    • showAdjust: boolean, not required, visibility of fullscreen button.
    • isFullscreen: boolean, required when showAdjust = true, status of fullscreen.
    • trigger: ReactNode, required, it is usually an icon, which is displayed on the toolbar.
    • children: ReactNode, required, content of Modal.
    • className: string, ^4.16.8, not required.
    • style: CSSProperties, ^4.16.8, not required.
    • showMask: boolean, ^4.16.8, not required, whether to display the mask layer, default true.
  • events

    • onClick: () => void, required.
    • onClose: () => void, required, close event.
    • onAdjust: (val: boolean) => void, fullscreen button click event.
jsx Copy
import { useState } from 'react';
import { MdEditor, ModalToolbar } from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';

/**
 * `insert` will be automatically injected into the component by the editor
 */
const MyToolbar = ({ insert = () => {} }) => {
  const [visible, setVisible] = useState(false);
  const [isFullscreen, setIsFullscreen] = useState(false);

  const onClick = useCallback(() => {
    setVisible(true);
  }, []);

  const onClose = useCallback(() => {
    setVisible(false);
  }, []);

  const onAdjust = useCallback(() => {
    setIsFullscreen((i) => !i);
  }, []);

  const insertHandler = useCallback(() => {
    insert((selectedText) => {
      /**
       * @return targetValue    Content to be inserted
       * @return select         Automatically select content, default: true
       * @return deviationStart Start position of the selected content, default: 0
       * @return deviationEnd   End position of the selected content, default: 0
       */
      return {
        targetValue: `==${selectedText}==`,
        select: true,
        deviationStart: 0,
        deviationEnd: 0,
      };
    });
  }, [insert]);

  return (
    <ModalToolbar
      visible={visible}
      isFullscreen={isFullscreen}
      showAdjust
      title="hover-title"
      modalTitle="modalTitle"
      width="870px"
      height="600px"
      onClick={onClick}
      onClose={onClose}
      onAdjust={onAdjust}
      trigger={
        <svg className="md-editor-icon" aria-hidden="true">
          <use xlinkHref="#icon-read"></use>
        </svg>
      }
    >
      <div
        style={{
          height: '100%',
          padding: '20px',
          overflow: 'auto',
        }}
      >
        <button onClick={insertHandler}>click me</button>
      </div>
    </ModalToolbar>
  );
};

const toolbars = ['bold', 0, '=', 'github'];
const defToolbars = [<MyToolbar key="key" />];

export default () => {
  const [value, setValue] = useState('');
  return (
    <MdEditor
      modelValue={value}
      id="md-prev"
      toolbars={toolbars}
      defToolbars={defToolbars}
      onChange={setValue}
    />
  );
};

ReadExtension Source Code


🐻 MdCatalog

  • props

    • editorId: string, required, editor's id, used to register listening events.
    • className: string, not required.
    • mdHeadingId: mdHeadingId, not required, same as editor.
    • scrollElement: string | HTMLElement, not required, it is an element selector when its type is string. When using MdPreview, it is usually set to document.documentElement.
    • theme: 'light' | 'dark', not required, provide it when you want to change theme online, it is the same as Editor theme.
    • offsetTop: number, not required, highlight current item of catalogs when title is offsetTop pixels from the top, default 20.
    • scrollElementOffsetTop: number, not required, offsetTop of the scroll container,default 0.
  • events

    • onClick: (e: MouseEvent, t: TocItem) => void, not required.
    • onActive: (heading: HeadList | undefined) => void, not required, heading was highlighted.

usage:

jsx Copy
import { MdPreview, MdCatalog } from 'md-editor-rt';
import 'md-editor-rt/lib/preview.css';

const editorId = 'my-editor';

export default () => {
  const [state] = useState({
    text: '# heading',
    scrollElement: document.documentElement,
  });

  return (
    <>
      {/* Ensure that the editorId is the same */}
      <MdPreview id={editorId} modelValue={state.text} />
      <MdCatalog editorId={editorId} scrollElement={state.scrollElement} />
    </>
  );
};

πŸ›Έ MdModal

It is usually used in conjunction with DropdownToolbar.

  • props

    • title: ReactNode, not required, title of Modal.
    • visible: boolean, required, visibility of Modal.
    • width: string, not required, width of Modal, default auto.
    • height: string, same as width.
    • showAdjust: boolean, not required, visibility of fullscreen button.
    • isFullscreen: boolean, required when showAdjust = true, status of fullscreen.
    • children: ReactNode, required, content of Modal.
    • className: string, not required.
    • style: CSSProperties, not required.
    • showMask: boolean, ^4.16.8, not required, whether to display the mask layer, default true.
  • events

    • onClose: () => void, required, close event.
    • onAdjust: (val: boolean) => void, fullscreen button click event.
jsx Copy
import { useState } from 'react';
import { MdEditor, DropdownToolbar, MdModal } from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';

/**
 * `insert` will be automatically injected into the component by the editor
 */
const MyToolbar = () => {
  const [visible, setVisible] = useState(false);
  const [mVisible, setMvisible] = useState(false);

  const onClick = useCallback(() => {
    setMvisible(true);
  }, []);

  const onClose = useCallback(() => {
    setMvisible(false);
  }, []);

  return (
    <DropdownToolbar
      visible={visible}
      onChange={setVisible}
      overlay={
        <ul>
          <li onClick={onClick}>option 1</li>
          <li>option 2</li>
        </ul>
      }
      trigger={
        <svg className="md-editor-icon" aria-hidden="true">
          <use xlinkHref="#icon-emoji"></use>
        </svg>
      }
      key="emoji-toolbar"
    >
      <MdModal title={'title'} visible={mVisible} onClose={onClose}>
        Content, Content
      </MdModal>
    </DropdownToolbar>
  );
};

const defToolbars = [<MyToolbar key="key" />];

export default () => {
  const [value, setValue] = useState('');

  return (
    <MdEditor
      modelValue={value}
      id="md-prev"
      toolbars={['bold', 0, '=', 'github']}
      defToolbars={defToolbars}
      onChange={setValue}
    />
  );
};

πŸͺ€ Internal Configuration

js Copy
import {
  allToolbar,
  allFooter,
  zh_CN,
  en_US,
  editorExtensionsAttrs,
} from 'md-editor-rt';

console.log(allToolbar, allFooter, zh_CN, en_US, editorExtensionsAttrs);

πŸ“¦ Internal Tools

🧹 clearSideEffects

>=5.0.0

Clear the side effects brought by the component, for example: links embedded using CDN. To ensure that multiple components can run correctly., the component will not actively remove these when it is unmounted.

js Copy
import { clearSideEffects } from 'md-editor-rt';

clearSideEffects();

It will remove the CDN references in the page. If the component instance still exists on the current page, do not call it!

XSSPlugin

>=5.0.0

Example: Add XSS extension

✍️ Edit This Page

doc-en-US

Copy