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<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<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:
- Write css
css.xxx-theme { color: red; }
- Set
previewTheme
jsx<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 totrue
.jsx<MdEditor noMermaid />
β noKatex
-
type:
boolean
-
default:
false
Do not want to use
katex
, set it totrue
.
π¦ codeTheme
-
type:
'atom'|'a11y'|'github'|'gradient'|'kimbie'|'paraiso'|'qtcreator'|'stackoverflow'
-
default:
'atom'
Highlight code css name. Get Them from
highlight.js
.Custom:
- Config
editorExtensions
jsimport { 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', }, }, }, }, });
- Set
codeTheme
jsx<MdEditor codeTheme="xxx" />
- Config
π± mdHeadingId
-
type:
(text: string, level: number, index: number) => string
-
default:
(text) => text
Title
ID
generator.jsximport { 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:jsximport 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
jsximport { 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<MdEditor noImgZoomIn />
After version
4.15.4
, it is also possible to disable zooming by setting the class.not-zoom
.markdown<img class="not-zoom">
π¬ customIcon
-
type:
CustomIcon
-
default:
{}
Customized icons
Type Warning
The icon corresponding to
copy
andcollapse-tips
can only be a string, while others can be components or stringstsximport 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
tstype 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
tofalse
whenhtmlPreview
istrue
.
𧱠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[ '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
orModalToolbar
. To display them, put index ofdefToolbars
intotoolbars
(this is not standard).jsximport { 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} /> ); };
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]
jsxconst tableShape = [8, 4]; () => <MdEditor tableShape={tableShape}>
πͺ§ 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
jsximport { 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.
tsximport { 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
oftextarea
).
πΎ onSave
-
type:
(v: string, h: Promise<string>) => void
Saving content event,
ctrl+s
and clicking button will trigger it.jsximport { 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.
jsximport 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.jsxconst onError = (err) => { alert(err.message); }; export default () => <MdEditor onError={onError} />;
πΎ onBlur
-
type:
(event: FocusEvent<HTMLTextAreaElement, Element>) => void
Textarea has lost focus.
jsxconst 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.
jsximport { 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
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
jseditorRef.current?.on('pageFullscreen', (status) => console.log(status));
-
fullscreen
jseditorRef.current?.on('fullscreen', (status) => console.log(status));
-
preview
jseditorRef.current?.on('preview', (status) => console.log(status));
-
previewOnly
jseditorRef.current?.on('previewOnly', (status) => console.log(status));
-
htmlPreview
jseditorRef.current?.on('htmlPreview', (status) => console.log(status));
-
catalog
jseditorRef.current?.on('catalog', (status) => console.log(status));
π» togglePageFullscreen
Toggle status of fullscreen within the page.
js
editorRef.current?.togglePageFullscreen(true);
Switched to the opposite status, without input parameter.
π₯ toggleFullscreen
Toggle status of fullscreen widthin browser.
js
editorRef.current?.toggleFullscreen(true);
Switched to the opposite status, without input parameter.
π togglePreview
Toggle status of preview.
js
editorRef.current?.togglePreview(true);
Switched to the opposite status, without input parameter.
π togglePreviewOnly
Toggle into Preview Only Mode.
js
editorRef.current?.togglePreviewOnly(true);
Switched to the opposite status, without input parameter.
πΌ toggleHtmlPreview
Toggle status of htmlPreview.
js
editorRef.current?.toggleHtmlPreview(true);
Switched to the opposite status, without input parameter.
𧬠toggleCatalog
Toggle status of catalog.
js
editorRef.current?.toggleCatalog(true);
Switched to the opposite status, without input parameter.
πΎ triggerSave
js
editorRef.current?.triggerSave();
π insert
Manually insert content into textarea.
js
/**
* @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
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
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
editorRef.current?.rerender();
π getSelectedText
Get the currently selected text.
js
console.log(editorRef.current?.getSelectedText());
π resetHistory
Clear current history.
π domEventHandlers
Supports listening to all DOM events.
js
editorRef.current?.domEventHandlers({
compositionstart: () => {
console.log('compositionstart');
},
});
π execCommand
Insert content into the editor via trigger.
js
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
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
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
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
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
type MarkdownItPlugins = (
plugins: Array<MarkdownItConfigPlugin>,
options: {
editorId: string;
}
) => Array<MarkdownItConfigPlugin>;
Example: Modify the class name of the image.
js
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
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
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
import { config } from 'md-editor-rt';
config({
editorConfig: {
// delay rendering time(ms)
renderDelay: 0,
},
});
π₯ zIndex
js
import { config } from 'md-editor-rt';
config({
editorConfig: {
// for modal component
zIndex: 2000,
},
});
π₯ editorExtensions
Config some dependency libraries, like highlight..
typescript
import { config } from 'md-editor-rt';
config({
editorExtensions: { highlight: { js: 'https://xxx.cc' } },
});
ts
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
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
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
import { config } from 'md-editor-rt';
config({
mermaidConfig(base: any) {
return {
...base,
logLevel: 'error',
};
},
});
π§ katexConfig
Configure katex
, Details
js
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
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}
/>
);
};
πΌ DropdownToolbar
-
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
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}
/>
);
};
π¦ 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, defaultauto
.height
:string
, same aswidth
.showAdjust
:boolean
, not required, visibility of fullscreen button.isFullscreen
:boolean
, required whenshowAdjust = 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, defaulttrue
.
-
events
onClick
:() => void
, required.onClose
:() => void
, required, close event.onAdjust
:(val: boolean) => void
, fullscreen button click event.
jsx
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}
/>
);
};
π» MdCatalog
-
props
editorId
:string
, required, editor'sid
, 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 usingMdPreview
, it is usually set todocument.documentElement
.theme
: 'light' | 'dark', not required, provide it when you want to change theme online, it is the same as Editortheme
.offsetTop
:number
, not required, highlight current item of catalogs when title isoffsetTop
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
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, defaultauto
.height
:string
, same aswidth
.showAdjust
:boolean
, not required, visibility of fullscreen button.isFullscreen
:boolean
, required whenshowAdjust = 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, defaulttrue
.
-
events
onClose
:() => void
, required, close event.onAdjust
:(val: boolean) => void
, fullscreen button click event.
jsx
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
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
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