nginx-ui/frontend/src/components/RichText/RichTextEditor.vue
2022-02-19 09:52:59 +08:00

151 lines
3.4 KiB
Vue

<template>
<div class="editor" v-if="editor">
<menu-bar class="editor__header" :editor="editor"/>
<editor-content :editor="editor"/>
</div>
</template>
<script>
import {Editor, EditorContent, VueNodeViewRenderer} from '@tiptap/vue-2'
import StarterKit from '@tiptap/starter-kit'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Highlight from '@tiptap/extension-highlight'
import Text from '@tiptap/extension-text'
import TaskList from '@tiptap/extension-task-list'
import TaskItem from '@tiptap/extension-task-item'
import CharacterCount from '@tiptap/extension-character-count'
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'
import CodeBlockComponent from './CodeBlockComponent'
import MenuBar from './MenuBar.vue'
import lowlight from 'lowlight'
export default {
components: {
EditorContent,
MenuBar,
},
data() {
return {
editor: null,
}
},
props: {
value: {
type: String,
default: '',
},
},
model: {
prop: 'value',
event: 'changeValue'
},
watch: {
value(value) {
// HTML
const isSame = this.editor.getHTML() === value
// JSON
// const isSame = this.editor.getJSON().toString() === value.toString()
if (isSame) {
return
}
this.editor.commands.setContent(this.value, false)
},
},
created() {
const that = this
this.editor = new Editor({
onUpdate({editor}) {
that.$emit('changeValue', editor.getHTML())
},
content: '',
extensions: [
StarterKit,
Document,
Paragraph,
Text,
TaskList,
TaskItem,
CharacterCount,
Highlight,
CodeBlockLowlight
.extend({
addNodeView() {
return VueNodeViewRenderer(CodeBlockComponent)
},
}).configure({lowlight}),
],
})
},
mounted() {
this.editor.commands.setContent(this.value, false)
},
beforeDestroy() {
this.editor.destroy()
},
}
</script>
<style lang="less">
.ant-affix {
z-index: 8 !important;
}
</style>
<style lang="less" scoped>
.editor {
display: flex;
flex-direction: column;
border-radius: 0.75rem;
@gray: rgba(0, 0, 0, 0.2);
background-color: #FFFFFF;
@media (prefers-color-scheme: dark) {
@gray: #666666;
border: 1px solid @gray;
background-color: #28292c;
&__header {
border-bottom: 1px solid @gray;
}
}
border: 1px solid @gray;
line-height: 1.5 !important;
&__header {
display: flex;
align-items: center;
flex: 0 0 auto;
flex-wrap: wrap;
padding: 0.25rem;
border-bottom: 1px solid @gray;
}
&__content {
padding: 1.25rem 1rem;
flex: 1 1 auto;
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
}
</style>
<style lang="less">
@import "style";
</style>
<style lang="less">
.editor .ProseMirror {
height: 500px;
overflow: scroll;
padding: 15px;
}
</style>