add tui.editor (#1374)

This commit is contained in:
花裤衩 2018-11-28 11:05:41 +08:00 committed by GitHub
parent 929a4fc0c8
commit a6c8e1a11a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 166 additions and 102 deletions

View File

@ -43,7 +43,6 @@
"echarts": "4.1.0", "echarts": "4.1.0",
"element-ui": "2.4.6", "element-ui": "2.4.6",
"file-saver": "1.3.8", "file-saver": "1.3.8",
"font-awesome": "4.7.0",
"js-cookie": "2.2.0", "js-cookie": "2.2.0",
"jsonlint": "1.6.3", "jsonlint": "1.6.3",
"jszip": "3.1.5", "jszip": "3.1.5",
@ -52,8 +51,8 @@
"path-to-regexp": "2.4.0", "path-to-regexp": "2.4.0",
"screenfull": "3.3.3", "screenfull": "3.3.3",
"showdown": "1.8.6", "showdown": "1.8.6",
"simplemde": "1.11.2",
"sortablejs": "1.7.0", "sortablejs": "1.7.0",
"tui-editor": "1.2.7",
"vue": "2.5.17", "vue": "2.5.17",
"vue-count-to": "1.0.13", "vue-count-to": "1.0.13",
"vue-i18n": "7.3.2", "vue-i18n": "7.3.2",

View File

@ -0,0 +1,31 @@
// doc: https://nhnent.github.io/tui.editor/api/latest/ToastUIEditor.html#ToastUIEditor
export default {
minHeight: '200px',
previewStyle: 'vertical',
useCommandShortcut: true,
useDefaultHTMLSanitizer: true,
usageStatistics: false,
hideModeSwitch: false,
toolbarItems: [
'heading',
'bold',
'italic',
'strike',
'divider',
'hr',
'quote',
'divider',
'ul',
'ol',
'task',
'indent',
'outdent',
'divider',
'table',
'image',
'link',
'divider',
'code',
'codeblock'
]
}

View File

@ -1,16 +1,18 @@
<template> <template>
<div :style="{height:height+'px',zIndex:zIndex}" class="simplemde-container"> <div :id="id"/>
<textarea :id="id"/>
</div>
</template> </template>
<script> <script>
import 'font-awesome/css/font-awesome.min.css' // deps for editor
import 'simplemde/dist/simplemde.min.css' import 'codemirror/lib/codemirror.css' // codemirror
import SimpleMDE from 'simplemde' import 'tui-editor/dist/tui-editor.css' // editor ui
import 'tui-editor/dist/tui-editor-contents.css' // editor content
import Editor from 'tui-editor'
import defaultOptions from './defaultOptions'
export default { export default {
name: 'SimplemdeMd', name: 'MarddownEditor',
props: { props: {
value: { value: {
type: String, type: String,
@ -19,105 +21,98 @@ export default {
id: { id: {
type: String, type: String,
required: false, required: false,
default: 'markdown-editor-' + +new Date() default() {
return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
}
}, },
autofocus: { options: {
type: Boolean, type: Object,
default: false default() {
return defaultOptions
}
}, },
placeholder: { mode: {
type: String, type: String,
default: '' default: 'markdown'
}, },
height: { height: {
type: Number, type: String,
default: 150 required: false,
default: '300px'
}, },
zIndex: { language: {
type: Number, type: String,
default: 10 required: false,
}, default: 'en_US' // https://github.com/nhnent/tui.editor/tree/master/src/js/langs
toolbar: {
type: Array,
default: function() {
return []
}
} }
}, },
data() { data() {
return { return {
simplemde: null, editor: null
hasChange: false }
},
computed: {
editorOptions() {
const options = Object.assign({}, defaultOptions, this.options)
options.initialEditType = this.mode
options.height = this.height
options.language = this.language
return options
} }
}, },
watch: { watch: {
value(val) { value(newValue, preValue) {
if (val === this.simplemde.value() && !this.hasChange) return if (newValue !== preValue && newValue !== this.editor.getValue()) {
this.simplemde.value(val) this.editor.setValue(newValue)
}
},
language(val) {
this.destroyEditor()
this.initEditor()
},
height(newValue) {
this.editor.height(newValue)
},
mode(newValue) {
this.editor.changeMode(newValue)
} }
}, },
mounted() { mounted() {
this.simplemde = new SimpleMDE({ this.initEditor()
element: document.getElementById(this.id),
autoDownloadFontAwesome: false,
autofocus: this.autofocus,
toolbar: this.toolbar.length > 0 ? this.toolbar : undefined,
spellChecker: false,
insertTexts: {
link: ['[', ']( )']
},
// hideIcons: ['guide', 'heading', 'quote', 'image', 'preview', 'side-by-side', 'fullscreen'],
placeholder: this.placeholder
})
if (this.value) {
this.simplemde.value(this.value)
}
this.simplemde.codemirror.on('change', () => {
if (this.hasChange) {
this.hasChange = true
}
this.$emit('input', this.simplemde.value())
})
}, },
destroyed() { destroyed() {
this.simplemde.toTextArea() this.destroyEditor()
this.simplemde = null },
methods: {
initEditor() {
this.editor = new Editor({
el: document.getElementById(this.id),
...this.editorOptions
})
if (this.value) {
this.editor.setValue(this.value)
}
this.editor.on('change', () => {
this.$emit('input', this.editor.getValue())
})
},
destroyEditor() {
if (!this.editor) return
this.editor.off('change')
this.editor.remove()
},
setValue(value) {
this.editor.setValue(value)
},
getValue() {
return this.editor.getValue()
},
setHtml(value) {
this.editor.setHtml(value)
},
getHtml() {
return this.editor.getHtml()
}
} }
} }
</script> </script>
<style scoped>
.simplemde-container>>>.CodeMirror {
min-height: 150px;
line-height: 20px;
}
.simplemde-container>>>.CodeMirror-scroll {
min-height: 150px;
}
.simplemde-container>>>.CodeMirror-code {
padding-bottom: 40px;
}
.simplemde-container>>>.editor-statusbar {
display: none;
}
.simplemde-container>>>.CodeMirror .CodeMirror-code .cm-link {
color: #1890ff;
}
.simplemde-container>>>.CodeMirror .CodeMirror-code .cm-string.cm-url {
color: #2d3b4d;
}
.simplemde-container>>>.CodeMirror .CodeMirror-code .cm-formatting-link-string.cm-url {
padding: 0 2px;
color: #E61E1E;
}
.simplemde-container >>> .editor-toolbar.fullscreen,
.simplemde-container >>> .CodeMirror-fullscreen {
z-index: 1003;
}
</style>

View File

@ -1,15 +1,40 @@
<template> <template>
<div class="components-container"> <div class="components-container">
<code>Markdown is based on <code>Markdown is based on
<a href="https://github.com/sparksuite/simplemde-markdown-editor" target="_blank">simplemde-markdown-editor</a> Simply encapsulated in Vue. <a href="https://github.com/nhnent/tui.editor" target="_blank">tui.editor</a> Simply encapsulated in Vue.
<a target="_blank" href="https://juejin.im/post/593121aa0ce4630057f70d35#heading-15"> <a target="_blank" href="https://juejin.im/post/593121aa0ce4630057f70d35#heading-15">
相关文章 </a> 相关文章 </a>
</code> </code>
<div class="editor-container"> <div class="editor-container">
<markdown-editor id="contentEditor" ref="contentEditor" v-model="content" :height="300" :z-index="20"/> <el-tag class="tag-title">Basic:</el-tag>
<markdown-editor v-model="content" height="300px"/>
</div> </div>
<el-button style="margin-top:80px;" type="primary" icon="el-icon-document" @click="markdown2Html">To HTML</el-button>
<div class="editor-container">
<el-tag class="tag-title">Markdown Mode:</el-tag>
<markdown-editor ref="markdownEditor" v-model="content" :options="{hideModeSwitch:true,previewStyle:'tab'}" height="200px"/>
</div>
<div class="editor-container">
<el-tag class="tag-title">Customize Toolbar:</el-tag>
<markdown-editor
ref="markdownEditor"
v-model="content"
:options="{ toolbarItems: ['heading','bold','italic']}"
/>
</div>
<div class="editor-container">
<el-tag class="tag-title">I18n:</el-tag>
<el-alert :closable="false" title="You can change the language of the admin system to see the effect" type="success"/>
<markdown-editor v-model="content" :language="language" height="300px"/>
</div>
<el-button style="margin-top:80px;" type="primary" icon="el-icon-document" @click="getHtml">Get HTML</el-button>
<div v-html="html"/> <div v-html="html"/>
</div> </div>
</template> </template>
@ -17,32 +42,46 @@
import MarkdownEditor from '@/components/MarkdownEditor' import MarkdownEditor from '@/components/MarkdownEditor'
const content = ` const content = `
**this is test** **This is test**
* vue * vue
* element * element
* webpack * webpack
## Simplemde
` `
export default { export default {
name: 'MarkdownDemo', name: 'MarkdownDemo',
components: { MarkdownEditor }, components: { MarkdownEditor },
data() { data() {
return { return {
content: content, content: content,
html: '' html: '',
languageTypeList: {
'en': 'en_US',
'zh': 'zh_CN',
'es': 'es_ES'
}
}
},
computed: {
language() {
return this.languageTypeList[this.$store.getters.language]
} }
}, },
methods: { methods: {
markdown2Html() { getHtml() {
import('showdown').then(showdown => { this.html = this.$refs.markdownEditor.getHtml()
const converter = new showdown.Converter() console.log(this.html)
this.html = converter.makeHtml(this.content)
})
} }
} }
} }
</script> </script>
<style scoped>
.editor-container{
margin-bottom: 30px;
}
.tag-title{
margin-bottom: 5px;
}
</style>