4.13.5 • Published 2 days ago

md-editor-rt v4.13.5

Weekly downloads
-
License
MIT
Repository
github
Last release
2 days ago

md-editor-rt

npm.io npm.io npm.io npm.io npm.io

English | 中文

Markdown editor for react, developed in jsx and typescript.

  • Documentation and demo:Go

  • Use it online:Go

  • The same series editor for vue3:md-editor-v3

Features

  • Toolbar, screenfull or screenfull in web pages and so on.
  • Themes, Built-in default and dark themes.
  • Shortcut key for editor.
  • Beautify your content by prettier(only for markdown content, not the code and other text).
  • Multi-language, build-in Chinese and English(default: Chinese).
  • Upload picture, paste or clip the picture and upload it.
  • Render article directly(no editor, no event listener, only preview content).
  • Preview themes, defalut, vuepress, github, cyanosis, mk-cute, smart-blue styles(not identical). It can be customized also(Refer to example page).
  • mermaid(>=1.3.0), katex mathematical formula(>=1.4.0).
  • Customize the toolbar as you like.

Preview

Default themeDark themePreview only
npm.ionpm.ionpm.io

mark and emoji extensions

mark and emoji extension

Apis

Props

nametypedefaultdescription
modelValuestring''Markdown content
theme'light' | 'dark''light'Editor theme
classstring''
historyLengthnumber10The max length of history(if it is too big, editor will use more RAM)
pageFullScreenbooleanfalseScreenfull in web page
previewbooleantruePreview content in editor
htmlPreviewbooleanfalsePreview html in editor
previewOnlybooleanfalseOnly render article content, no toolbar, no edit area
languagestring'zh-CN'Build-in language('zh-CN','en-US')
toolbarsArraytoolbarsShow some item of toolbars, all keyssee toolbars below
toolbarsExcludeArray[]Don't show some item of toolbars, all keystoolbars
noPrettierbooleanfalseUse prettier to beautify content or not
editorIdstringmd-editor-rtEditor id, it is used when there are more than two editors in the same page.
tabWidthnumber2One tab eq some spaces
showCodeRowNumberbooleanfalseShow row number for code block or not
previewTheme'default' | 'github' | 'vuepress' | 'mk-cute' | 'smart-blue' | 'cyanosis''default'Preview theme, can be customized
styleCSSProperties{}Editor inline style
tableShapenumber, number6, 4Preset the size of the table, columns, rows
noMermaidbooleanfalseUse mermaid or not
placeholderstring''
noKatexbooleanfalseUse katex or not
defToolbarsArray<DropdownToolbar | NormalToolbar | ModalToolbar>nullCustom toolbar in DropdownToolbar, NormalToolbar or ModalToolbar
codeTheme'atom' | 'a11y' | 'github' | 'gradient' | 'kimbie' | 'paraiso' | 'qtcreator' | 'stackoverflow''atom'Highlight code style, can be customized also
markedHeadingId(text: string, level: number) => string(text) => textH1-H6 ID generator
sanitize(html: string) => string(html) => htmlSanitize the html, prevent XSS
[
  'bold',
  'underline',
  'italic',
  '-',
  'strikeThrough',
  'title',
  'sub',
  'sup',
  'quote',
  'unorderedList',
  'orderedList',
  '-',
  'codeRow',
  'code',
  'link',
  'image',
  'table',
  'mermaid',
  'katex',
  '-',
  'revoke',
  'next',
  'save',
  '=',
  'pageFullscreen',
  'fullscreen',
  'preview',
  'htmlPreview',
  'catalog',
  'github'
];

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

Expand language, you need to replace all the content here:

export interface ToolbarTips {
  bold?: string;
  underline?: string;
  italic?: string;
  strikeThrough?: string;
  title?: string;
  sub?: string;
  sup?: string;
  quote?: string;
  unorderedList?: string;
  orderedList?: string;
  codeRow?: string;
  code?: string;
  link?: string;
  image?: string;
  table?: string;
  mermaid?: string;
  katex?: string;
  revoke?: string;
  next?: string;
  save?: string;
  prettier?: string;
  pageFullscreen?: string;
  fullscreen?: string;
  catalog?: string;
  preview?: string;
  htmlPreview?: string;
  github?: string;
  '-'?: string;
  '='?: string;
}

export interface StaticTextDefaultValue {
  // Toolbar hover tips(html title)
  toolbarTips?: ToolbarTips;
  // h1-h6 dropdown menu item
  titleItem?: {
    h1?: string;
    h2?: string;
    h3?: string;
    h4?: string;
    h5?: string;
    h6?: string;
  };
  // v1.6.0
  imgTitleItem?: {
    link: string;
    upload: string;
    clip2upload: string;
  };
  // The modal tips of add link or upload picture
  linkModalTips?: {
    title?: string;
    descLable?: string;
    descLablePlaceHolder?: string;
    urlLable?: string;
    UrlLablePlaceHolder?: string;
    buttonOK?: string;
  };
  // The modal tips of clip the picture, v1.2.0
  clipModalTips?: {
    title?: string;
    buttonUpload?: string;
  };
  // Copy code tips, v1.1.4
  copyCode?: {
    text?: string;
    successTips?: string;
    failTips?: string;
  };
  // 1.8.0
  mermaid?: {
    flow?: string;
    sequence?: string;
    gantt?: string;
    class?: string;
    state?: string;
    pie?: string;
    relationship?: string;
    journey?: string;
  };
  // 1.9.0
  katex?: {
    // formula inline
    inline: string;
    // formula block
    block: string;
  };
}

Event

nameparamdescription
onChangev:stringContent changed event(bind to oninput of textarea)
onSavev:stringSave content event, ctrl+s and click button will be triggered also
onUploadImgfiles:Array, callback:FunctionUpload picture event, when picture is uploading the modal will not close, please provide right urls to the callback function
onHtmlChangedh:stringCompile markdown successful event, you can use it to get the html code
onGetCataloglist: HeadList[]Get catalog of article
onErrorerr: { name: string; message: string }Catch run-time error, Cropper,fullScreen and prettier are used when they are not loaded

Config

Use MdEditor.config(option: ConfigOption) to reconfigure renderer.

  • markedRenderer: (renderer: Renderer) => Renderer

    Open target page in a new browser window:

    MdEditor.config({
      markedRenderer(renderer) {
        renderer.link = (href, title, text) => {
          return `<a href="${href}" title="${title}" target="_blank">${text}</a>`;
        };
    
        return renderer;
      }
    });

    Reference: https://marked.js.org/using_pro#renderer

  • markedExtensions: Array<marked.TokenizerExtension & marked.RendererExtension>

    import MdEditor from 'md-editor-rt';
    
    MdEditor.config({
      markedExtensions: [your extension]
    });

    Reference: https://marked.js.org/using_pro#extensions

  • markedOptions: marked.MarkedOptions

    Do not render <br> on a single line break:

    import MdEditor from 'md-editor-rt';
    
    MdEditor.config({
      markedOptions: { breaks: false }
    });

    Reference: https://marked.js.org/using_advanced#options

  • editorConfig: Add more languages, reset mermaid template or delay rendering time:

    import MdEditor from 'md-editor-rt';
    
    MdEditor.config({
      editorConfig: {
        languageUserDefined: { lang: StaticTextDefaultValue },
        mermaidTemplate: {
          flow: `flow tempalte`,
          ...more
        },
        // ms
        renderDelay: 500
      }
    });
  • editorExtensions: Config some dependency libraries, like highlight..

    import MdEditor from 'md-editor-rt';
    
    MdEditor.config({
      editorExtensions: { iconfont: 'https://xxx.cc' }
    });
    import MdEditor from 'md-editor-rt';
    
    interface EditorExtensions {
      highlight?: {
        instance?: any;
        js?: string;
        css?: {
          [key: string]: {
            light: string;
            dark: string;
          };
        };
      };
      prettier?: {
        standaloneJs?: string;
        parserMarkdownJs?: string;
      };
      cropper?: {
        instance?: any;
        js?: string;
        css?: string;
      };
      iconfont?: string;
      screenfull?: {
        instance?: any;
        js?: string;
      };
      mermaid?: {
        instance?: any;
        js?: string;
      };
      katex?: {
        instance?: any;
        js?: string;
        css?: string;
      };
    }

Shortcut key

keyfunctiondescription
TABinsert spaceInsert space, the length eq tabWidth, default: 2, support multiline
SHIFT + TABdelete space, setting is the same as Tab
CTRL + CcopyWhen selected, copy the selected content. When not selected, copy the content of the current line
CTRL + XshearWhen selected, cut the selected content. When not selected, cut the current line
CTRL + DdeleteWhen selected, delete the selected content. When not selected, delete the current line
CTRL + SsaveTrigger onSave event
CTRL + Bbold text**bold**
CTRL + Uunderline<u>underline</u>
CTRL + Iitalic*italic*
CTRL + 1-6h1-h6# title
CTRL + ↑superscript<sup>superscript</sup>
CTRL + ↓subscript<sub>subscript</sub>
CTRL + Qquote> quote
CTRL + Oordered list1. ordered list
CTRL + Llink[link](https://github.com/imzbf/md-editor-rt)
CTRL + ZwithdrawWithdraw history in editor, not the function of system
CTRL + SHIFT + Sline-through~line-through~
CTRL + SHIFT + Uunordered list- unordered list
CTRL + SHIFT + Ccode block
CTRL + SHIFT + Ipicture![picture](https://imbf.cc)
CTRL + SHIFT + ZforwardForward history in editor, not the function of system
CTRL + SHIFT + FBeautify
CTRL + ALT + Ccode row
CTRL + SHIFT + ALT + Ttable\|table\|

Components

They are used as attributes of the editor component, eg: Editor.DropdownToolbar. For more examples, refer to document.

NormalToolbar

Editor.NormalToolbar

  • props

    • title: string, not necessary, title of toolbar.
  • events

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

    • trigger: string | JSX.Element, necessary, it is usually an icon, which is displayed on the toolbar.

DropdownToolbar

Editor.DropdownToolbar

  • props

    • title: string, not necessary, title of toolbar.
    • visible: boolean, necessary.
  • events

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

    • trigger: string | JSX.Element, necessary, it is usually an icon, which is displayed on the toolbar.
    • overlay: string | JSX.Element, necessary, content of dropdown box.

ModalToolbar

Editor.ModalToolbar

  • props

    • title: string, not necessary, title of toolbar.
    • modalTitle: string, not necessary, title of the Modal.
    • visible: boolean, necessary, visibility of Modal.
    • width: string, not necessary, width of Modal, default auto.
    • height: string, same as width.
    • showAdjust: boolean, not necessary, visibility of fullscreen button.
    • isFullscreen: boolean, necessary when showAdjust = true, status of fullscreen.
  • events

    • onClick: () => void, necessary.
    • onClose: () => void, necessary, close event.
    • onAdjust: (val: boolean) => void, fullscreen button click event.
  • slots

    • trigger: string | JSX.Element, necessary, it is usually an icon, which is displayed on the toolbar.
    • overlay: string | JSX.Element, necessary, content of Modal.

MdCatalog

Editor.MdCatalog

  • props

    • editorId: string, necessary, same as editor's editorId, used to register listening events.
    • class: string, not necessary.
    • markedHeadingId: MarkedHeadingId, not necessary, same as editor.
    • scrollElement: string | HTMLElement, not necessary, it is an element selector when its type is string. When previewOnly eq true, it is usually set to document.documentElement.
    • theme: 'light' | 'dark', not necessary, provide it when you want to change theme online, it is the same as Editor theme.

Examples

Jsx module

import React, { useState } from 'react';
import MdEditor from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';

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

  return <Editor modelValue={text} onChange={setText} />;
}

Upload picture

Tips: When you paste and upload GIF, it will upload a static picture. So you should upload it by file system!

import React, { useState } from 'react';
import MdEditor from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';

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

  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));
        });
      })
    );

    callback(res.map((item) => item.data.url));
  };

  return <Editor modelValue={text} onChange={setText} onUploadImg={onUploadImg} />;
}

Change Styles

.css-vars(@isDark) {
  --md-color: if(@isDark, #999, #222);
  --md-hover-color: if(@isDark, #bbb, #000);
  --md-bk-color: if(@isDark, #000, #fff);
  --md-bk-color-outstand: if(@isDark, #111, #f6f6f6);
  --md-bk-hover-color: if(@isDark, #1b1a1a, #f5f7fa);
  --md-border-color: if(@isDark, #2d2d2d, #e6e6e6);
  --md-border-hover-color: if(@isDark, #636262, #b9b9b9);
  --md-border-active-color: if(@isDark, #777, #999);
  --md-modal-mask: #00000073;
  --md-scrollbar-bg-color: if(@isDark, #0f0f0f, #e2e2e2);
  --md-scrollbar-thumb-color: if(@isDark, #2d2d2d, #0000004d);
  --md-scrollbar-thumb-hover-color: if(@isDark, #3a3a3a, #00000059);
  --md-scrollbar-thumb-avtive-color: if(@isDark, #3a3a3a, #00000061);
}

.md {
  .css-vars(false);
}

.md-dark {
  .css-vars(true);
}

Change background color in dark mode:

.md-dark {
  --md-bk-color: #333 !important;
}
4.14.0-0

2 days ago

4.13.4

6 days ago

4.13.5

6 days ago

4.13.3

10 days ago

4.13.3-beta.0

10 days ago

4.13.2

15 days ago

4.13.1

17 days ago

4.13.0

25 days ago

4.13.0-beta.0

26 days ago

4.12.4

29 days ago

4.12.3

1 month ago

4.12.2

1 month ago

4.12.0

2 months ago

4.12.1

2 months ago

4.12.0-beta.0

2 months ago

4.12.0-beta.2

2 months ago

4.11.3

2 months ago

4.11.1

3 months ago

4.11.2

3 months ago

4.11.0

3 months ago

4.11.0-beta.1

4 months ago

4.11.0-beta.2

4 months ago

4.11.0-beta.0

4 months ago

4.10.0

4 months ago

4.10.0-beta.0

4 months ago

4.9.0

5 months ago

4.8.3

6 months ago

4.9.0-beta.0

5 months ago

4.8.0-beta.0

7 months ago

4.8.0-beta.1

7 months ago

4.8.1

7 months ago

4.8.0

7 months ago

4.8.2

6 months ago

4.7.0

7 months ago

4.7.0-beta.1

7 months ago

4.7.0-beta.0

7 months ago

4.6.2

8 months ago

4.5.0-beta.0

8 months ago

4.5.0-beta.1

8 months ago

4.5.0-beta.2

8 months ago

4.6.1

8 months ago

4.6.0

8 months ago

4.6.2-beta.0

8 months ago

4.5.0

8 months ago

4.6.0-beta.0

8 months ago

4.4.0

8 months ago

4.0.4

11 months ago

4.0.1

12 months ago

4.0.3

11 months ago

4.0.2

11 months ago

4.2.0-beta.0

11 months ago

4.2.0-beta.1

11 months ago

4.3.1-beta.0

9 months ago

4.3.0-beta.3

9 months ago

4.3.0-beta.2

9 months ago

4.3.0

9 months ago

4.3.0-beta.1

9 months ago

4.3.0-beta.0

9 months ago

4.3.0-beta.7

9 months ago

4.3.0-beta.6

9 months ago

4.3.0-beta.4

9 months ago

4.2.1-beta.0

10 months ago

4.2.2

10 months ago

4.2.1

10 months ago

4.2.0

11 months ago

4.1.0-beta.0

11 months ago

4.1.0-beta.1

11 months ago

4.0.4-beta.0

11 months ago

4.1.0

11 months ago

4.1.1

11 months ago

2.11.1

1 year ago

2.11.2

1 year ago

2.11.3

1 year ago

4.0.0

12 months ago

3.0.0-beta.0

1 year ago

3.0.0-beta.3

1 year ago

3.0.0-beta.5

1 year ago

3.0.0-beta.4

1 year ago

3.0.1

12 months ago

3.0.0

1 year ago

4.0.0-beta.0

12 months ago

2.8.0-beta.0

1 year ago

2.11.0

1 year ago

2.8.1

1 year ago

2.8.0

1 year ago

2.9.0-beta.4

1 year ago

2.9.0-beta.5

1 year ago

2.9.0-beta.2

1 year ago

2.9.0-beta.3

1 year ago

2.9.0-beta.0

1 year ago

2.9.0-beta.1

1 year ago

2.9.2

1 year ago

2.9.1

1 year ago

2.9.3

1 year ago

2.10.1

1 year ago

2.10.0-beta.2

1 year ago

2.10.0

1 year ago

2.9.0

1 year ago

2.10.0-beta.1

1 year ago

2.4.1

1 year ago

2.4.0

1 year ago

2.6.0

1 year ago

2.4.2

1 year ago

2.5.0-beta.0

1 year ago

2.5.0-beta.1

1 year ago

2.5.0

1 year ago

2.7.0

1 year ago

2.7.2

1 year ago

2.7.1

1 year ago

2.6.0-beta.0

1 year ago

2.4.0-beta.0

1 year ago

2.4.0-beta.2

1 year ago

2.4.0-beta.1

1 year ago

2.7.0-beta.1

1 year ago

2.7.0-beta.0

1 year ago

2.3.0-beta.0

2 years ago

2.3.0-beta.1

2 years ago

2.3.0

2 years ago

2.2.0-beta.0

2 years ago

2.2.0-beta.1

2 years ago

2.2.0-beta.2

2 years ago

2.2.1

2 years ago

2.2.0

2 years ago

2.0.1

2 years ago

2.0.0

2 years ago

1.6.13

2 years ago

2.2.1-beta.1

2 years ago

2.2.1-beta.0

2 years ago

2.1.2

2 years ago

2.1.1

2 years ago

2.0.0-beta.0

2 years ago

2.1.0

2 years ago

2.1.2-beta.1

2 years ago

2.1.1-beta.1

2 years ago

2.1.2-beta.0

2 years ago

2.1.1-beta.2

2 years ago

2.1.0-beta.0

2 years ago

2.1.2-beta.2

2 years ago

2.1.1-beta.0

2 years ago

1.6.11

2 years ago

1.6.10

2 years ago

1.6.12

2 years ago

1.6.4

2 years ago

1.6.3

2 years ago

1.6.2

2 years ago

1.6.1

2 years ago

1.6.0

2 years ago

1.6.9

2 years ago

1.6.8

2 years ago

1.6.7

2 years ago

1.6.6

2 years ago

1.6.5

2 years ago

1.5.1

2 years ago

1.4.2

2 years ago

1.5.0

2 years ago

1.4.1

2 years ago

1.2.3

2 years ago

1.4.0

2 years ago

1.3.0

2 years ago

1.2.0

2 years ago

1.2.2

2 years ago

1.2.1

2 years ago

1.1.1

3 years ago

1.1.0

3 years ago

1.1.2

3 years ago

1.0.0

3 years ago