md-editor-v3
English | 中文
Markdown editor for vue3, developed by jsx
and typescript
.
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, support
defalut
、vuepress
、github
styles(not identical).
More features are developing, if you have some ideas or find issues, please tell it to me~
Preview
Default theme | Dark theme | Preview only |
---|
| | |
Apis
Props
name | type | default | description |
---|
modelValue | String | '' | Markdown content,use v-model in vue template |
theme | 'light' | 'dark' | 'light' | Change editor theme |
editorClass | String | '' | |
hljs | Object | null | Highlight instance, editor will not insert script of it, but you need to import highlight code style by yourself |
highlightJs | String | highlight.js@11.2.0 | HighlightJs url |
highlightCss | String | atom-one-dark@11.2.0 | Highlight code style |
historyLength | Number | 10 | The max length of history(if it is too big, editor will use more RAM ) |
pageFullScreen | Boolean | false | Screenfull in web page |
preview | Boolean | true | Preview content in editor |
htmlPreview | Boolean | false | Preview html in editor |
previewOnlyv1.3.0 | Boolean | false | Only render article content, no toolbar, no edit area |
language | String | 'zh-CN' | Build-in language('zh-CN','en-US') |
languageUserDefinedv1.5.0 changed | Object | {key: StaticTextDefaultValue} | Expand language,update language api to your key |
toolbars | Array | [toolbars] | Show some item of toolbars,all keyssee toolbars below |
toolbarsExcludev1.1.4 | Array | [] | Don't show some item of toolbars,all keystoolbars |
prettier | Boolean | true | Use prettier to beautify content or not |
prettierCDN | String | standalone@2.4.0 | |
prettierMDCDN | String | parser-markdown@2.4.0 | |
cropperCssv1.2.0 | String | cropper.min.css@1.5.12 | Cropper css url |
cropperJsv1.2.0 | String | cropper.min.js@1.5.12 | Cropper js url |
iconfontJsv1.3.2 | String | iconfont | Icon url |
editorIdv1.6.4 updated | String | md-editor-v3 | Editor id, also the html id, it is used when there are more than two editors |
tabWidthv1.4.0 | Number | 2 | One tab eq some space |
showCodeRowNumberv1.4.3 | Boolean | false | Show row number for code block or not |
screenfullv1.4.3 | Object | null | Screenfull instance, editor will not insert script of it |
screenfullJs<v1.4.3 | String | screenfull@5.1.0 | Screenfull js url |
previewThemev1.4.3 | 'default' | 'github' | 'vuepress' | 'default' | Preview themes |
stylev1.7.0 | CSSProperties | {} | Editor's inline style |
[toolbars]
[
'bold',
'underline',
'italic',
'-',
'strikeThrough',
'title',
'sub',
'sup',
'quote',
'unorderedList',
'orderedList',
'-',
'codeRow',
'code',
'link',
'image',
'table',
'-',
'revoke',
'next',
'save',
'=',
'pageFullscreen',
'fullscreen',
'preview',
'htmlPreview',
'catalog',
'github'
];
after v1.6.0, 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:
[StaticTextDefaultValue]
export interface StaticTextDefaultValue {
toolbarTips?: ToolbarTips;
titleItem?: {
h1?: string;
h2?: string;
h3?: string;
h4?: string;
h5?: string;
h6?: string;
};
imgTitleItem?: {
link: string;
upload: string;
clip2upload: string;
};
linkModalTips?: {
title?: string;
descLable?: string;
descLablePlaceHolder?: string;
urlLable?: string;
UrlLablePlaceHolder?: string;
buttonOK?: string;
};
clipModalTips?: {
title?: string;
buttonUpload?: string;
};
copyCode?: {
text?: string;
tips?: string;
};
}
Event
name | params | description |
---|
onChange | v:String | Content changed event(bind to oninput of textarea ) |
onSave | v:String | Save Content event,ctrl+s and click button will trigger |
onUploadImg | files:FileList, callback:Function | Upload picture event,when picture is uploading the modal will not close,please provide right urls to the callback function |
onHtmlChanged | h:String | Compile markdown successful event,you can use it to get the html code |
onGetCatalogv1.4.0 | list: HeadList[] | Get catalogue of article |
markedHeadingv1.6.0 | text: string,level: 1-6,raw: string, slugger: Slugger | marked head renderer methods |
markedHeadingIdv1.7.0 | (text: string, level: number) => string | title ID generator |
If markedHeading
is overridden, be sure to tell the editor the algorithm for generating the title ID by marketheadingid
.
Shortcut key
key | function | description | support |
---|
TAB | insert space | Insert space, the length eq tabWidth , default: 2, support multiline | v1.4.0 |
SHIFT + TAB | delete space, setting is the same as Tab | | v1.4.0 |
CTRL + C | copy | When selected, copy the selected content. When not selected, copy the content of the current line | v1.4.0 |
CTRL + X | shear | When selected, cut the selected content. When not selected, cut the current line | v1.4.0 |
CTRL + D | delete | When selected, delete the selected content. When not selected, delete the current line | v1.4.0 |
CTRL + S | save | Trigger onSave event | v1.0.0 |
CTRL + B | bold text | **bold** | v1.0.0 |
CTRL + U | underline | <u>underline</u> | v1.0.0 |
CTRL + I | italic | *italic* | v1.0.0 |
CTRL + 1-6 | h1-h6 | # title | v1.0.0 |
CTRL + ↑ | superscript | <sup>superscript</sup> | v1.0.0 |
CTRL + ↓ | subscript | <sub>subscript</sub> | v1.0.0 |
CTRL + Q | quote | > quote | v1.0.0 |
CTRL + O | ordered list | 1. ordered list | v1.0.0 |
CTRL + L | link | [link](https://github.com/imzbf/md-editor-v3) | v1.0.0 |
CTRL + Z | withdraw | Withdraw history in editor, not the function of system | v1.0.0 |
CTRL + SHIFT + S | line-through | ~line-through~ | v1.0.0 |
CTRL + SHIFT + U | unordered list | - unordered list | v1.0.0 |
CTRL + SHIFT + C | code block | | v1.0.0 |
CTRL + SHIFT + I | picture | ![picture](https://imbf.cc) | v1.0.0 |
CTRL + SHIFT + Z | forward | Forward history in editor, not the function of system | v1.0.0 |
CTRL + SHIFT + F | Beautify | | v1.0.0 |
CTRL + ALT + C | code row | | v1.0.0 |
CTRL + SHIFT + ALT + T | table | |table| | v1.4.0 |
Simple demo
Jsx module
import { defineComponent, reactive } from 'vue';
import Editor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-dark.css';
export default defineComponent({
setup() {
const md = reactive({
text: 'default markdown content'
});
return () => (
<Editor hljs={hljs} modelValue={md.text} onChange={(value) => (md.text = value)} />
);
}
});
Vue template
<template>
<editor v-model="text" pageFullScreen></editor>
</template>
<script>
import { defineComponent } from 'vue';
import Editor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
export default defineComponent({
name: 'VueTemplateDemo',
components: { Editor },
data() {
return {
text: '# md-editor-v3'
};
}
});
</script>
Upload picture
Tips:When you paste and upload GIF,it will upload a static picture. So you should upload it by file system!
async onUploadImg(files: FileList, callback: (urls: string[]) => void) {
const res = await Promise.all(
Array.from(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: any) => item.data.url));
}