add some old functions

This commit is contained in:
Philipp Kühn 2018-10-21 21:55:24 +02:00
parent d5e25de018
commit 3d866d9c1c
7 changed files with 283 additions and 67 deletions

View File

@ -147,24 +147,24 @@
<script> <script>
import Icon from 'Components/Icon' import Icon from 'Components/Icon'
import { Editor, EditorContent } from 'tiptap' import { Editor, EditorContent } from 'tiptap'
// import { import {
// BlockquoteNode, BlockquoteNode,
// BulletListNode, BulletListNode,
// CodeBlockNode, CodeBlockNode,
// HardBreakNode, HardBreakNode,
// HeadingNode, HeadingNode,
// ListItemNode, ListItemNode,
// OrderedListNode, OrderedListNode,
// TodoItemNode, TodoItemNode,
// TodoListNode, TodoListNode,
// BoldMark, BoldMark,
// CodeMark, CodeMark,
// ItalicMark, ItalicMark,
// LinkMark, LinkMark,
// StrikeMark, StrikeMark,
// UnderlineMark, UnderlineMark,
// HistoryExtension, HistoryExtension,
// } from 'tiptap-extensions' } from 'tiptap-extensions'
export default { export default {
components: { components: {
@ -174,23 +174,24 @@ export default {
data() { data() {
return { return {
editor: new Editor({ editor: new Editor({
editable: true,
extensions: [ extensions: [
// new BlockquoteNode(), new BlockquoteNode(),
// new BulletListNode(), new BulletListNode(),
// new CodeBlockNode(), new CodeBlockNode(),
// new HardBreakNode(), new HardBreakNode(),
// new HeadingNode({ maxLevel: 3 }), new HeadingNode({ maxLevel: 3 }),
// new ListItemNode(), new ListItemNode(),
// new OrderedListNode(), new OrderedListNode(),
// new TodoItemNode(), new TodoItemNode(),
// new TodoListNode(), new TodoListNode(),
// new BoldMark(), new BoldMark(),
// new CodeMark(), new CodeMark(),
// new ItalicMark(), new ItalicMark(),
// new LinkMark(), new LinkMark(),
// new StrikeMark(), new StrikeMark(),
// new UnderlineMark(), new UnderlineMark(),
// new HistoryExtension(), new HistoryExtension(),
], ],
content: { content: {
type: 'doc', type: 'doc',

View File

@ -6,12 +6,6 @@ export default {
}, },
}, },
render(createElement) { render(createElement) {
// console.log('createElement', this.editor)
// if (this.editor) {
// console.log('create element', this.editor.element)
// return this.editor.element
// // return createElement('div', {}, this.editor.element.innerHTML)
// }
return createElement('div') return createElement('div')
}, },
watch: { watch: {
@ -26,14 +20,4 @@ export default {
}, },
} }
}, },
created() {
// console.log('on init')
// this.editor.on('init', () => {
// console.log('iniiiitttt!!!')
// })
// setTimeout(() => {
// // this.$el.innerHTML = this.editor.element.innerHTML
// this.$el.append(this.editor.element)
// }, 1000);
},
} }

View File

@ -0,0 +1,89 @@
import Vue from 'vue'
export default class ComponentView {
constructor(component, {
node,
view,
getPos,
decorations,
editable,
}) {
this.component = component
this.node = node
this.view = view
this.getPos = getPos
this.decorations = decorations
this.editable = editable
this.dom = this.createDOM()
this.contentDOM = this.vm.$refs.content
}
createDOM() {
const Component = Vue.extend(this.component)
this.vm = new Component({
propsData: {
node: this.node,
view: this.view,
getPos: this.getPos,
decorations: this.decorations,
editable: this.editable,
updateAttrs: attrs => this.updateAttrs(attrs),
updateContent: content => this.updateContent(content),
},
}).$mount()
return this.vm.$el
}
updateAttrs(attrs) {
if (!this.editable) {
return
}
const transaction = this.view.state.tr.setNodeMarkup(this.getPos(), null, {
...this.node.attrs,
...attrs,
})
this.view.dispatch(transaction)
}
updateContent(content) {
if (!this.editable) {
return
}
const transaction = this.view.state.tr.setNodeMarkup(this.getPos(), this.node.type, { content })
this.view.dispatch(transaction)
}
ignoreMutation() {
return true
}
stopEvent(event) {
// TODO: find a way to pass full extensions to ComponentView
// so we could check for schema.draggable
// for now we're allowing all drag events for node views
return !/drag/.test(event.type)
}
update(node, decorations) {
if (node.type !== this.node.type) {
return false
}
if (node === this.node && this.decorations === decorations) {
return true
}
this.node = node
this.decorations = decorations
this.vm._props.node = node
this.vm._props.decorations = decorations
return true
}
destroy() {
this.vm.$destroy()
}
}

View File

@ -10,10 +10,10 @@ import { inputRules } from 'prosemirror-inputrules'
import { import {
// buildMenuActions, // buildMenuActions,
ExtensionManager, ExtensionManager,
// initNodeViews, initNodeViews,
// menuBubble, // menuBubble,
// floatingMenu, // floatingMenu,
// builtInKeymap, builtInKeymap,
} from '../Utils' } from '../Utils'
import builtInNodes from '../Nodes' import builtInNodes from '../Nodes'
@ -21,8 +21,6 @@ import builtInNodes from '../Nodes'
export default class Editor { export default class Editor {
constructor(options = {}) { constructor(options = {}) {
console.log('construct editor')
this.element = document.createElement('div') this.element = document.createElement('div')
this.bus = new Vue() this.bus = new Vue()
@ -30,14 +28,16 @@ export default class Editor {
this.extensions = this.createExtensions() this.extensions = this.createExtensions()
this.nodes = this.createNodes() this.nodes = this.createNodes()
this.marks = this.createMarks() this.marks = this.createMarks()
this.views = this.createViews()
this.schema = this.createSchema() this.schema = this.createSchema()
this.plugins = this.createPlugins()
this.keymaps = this.createKeymaps()
this.inputRules = this.createInputRules()
this.state = this.createState() this.state = this.createState()
this.view = this.createView() this.view = this.createView()
this.commands = this.createCommands()
console.log('emit init')
this.emit('init') this.emit('init')
console.log(this.view)
} }
createExtensions() { createExtensions() {
@ -47,13 +47,39 @@ export default class Editor {
]) ])
} }
createPlugins() {
return this.extensions.plugins
}
createKeymaps() {
return this.extensions.keymaps({
schema: this.schema,
})
}
createInputRules() {
return this.extensions.inputRules({
schema: this.schema,
})
}
createCommands() {
return this.extensions.commands({
schema: this.schema,
view: this.view,
})
}
createNodes() { createNodes() {
const { nodes } = this.extensions return this.extensions.nodes
return nodes
} }
createMarks() { createMarks() {
return [] return this.extensions.marks
}
createViews() {
return this.extensions.views
} }
createSchema() { createSchema() {
@ -67,9 +93,40 @@ export default class Editor {
return EditorState.create({ return EditorState.create({
schema: this.schema, schema: this.schema,
doc: this.createDocument(this.options.content), doc: this.createDocument(this.options.content),
plugins: [
...this.plugins,
...this.getPlugins(),
],
}) })
} }
getPlugins() {
const plugins = [
inputRules({
rules: this.inputRules,
}),
...this.keymaps,
keymap(builtInKeymap),
keymap(baseKeymap),
gapCursor(),
new Plugin({
props: {
editable: () => this.options.editable,
},
}),
]
// if (this.menububbleNode) {
// plugins.push(menuBubble(this.menububbleNode))
// }
// if (this.floatingMenuNode) {
// plugins.push(floatingMenu(this.floatingMenuNode))
// }
return plugins
}
createDocument(content) { createDocument(content) {
if (typeof content === 'object') { if (typeof content === 'object') {
return this.schema.nodeFromJSON(content) return this.schema.nodeFromJSON(content)
@ -84,10 +141,10 @@ export default class Editor {
return new EditorView(this.element, { return new EditorView(this.element, {
state: this.state, state: this.state,
dispatchTransaction: this.dispatchTransaction.bind(this), dispatchTransaction: this.dispatchTransaction.bind(this),
// nodeViews: initNodeViews({ nodeViews: initNodeViews({
// nodes: this.views, nodes: this.views,
// editable: this.editable, editable: this.options.editable,
// }), }),
}) })
} }
@ -123,6 +180,52 @@ export default class Editor {
return div.innerHTML return div.innerHTML
} }
getJSON() {
return this.state.doc.toJSON()
}
getDocFromContent(content) {
if (typeof content === 'object') {
return this.schema.nodeFromJSON(content)
}
if (typeof content === 'string') {
const element = document.createElement('div')
element.innerHTML = content.trim()
return DOMParser.fromSchema(this.schema).parse(element)
}
return false
}
setContent(content = {}, emitUpdate = false) {
this.state = EditorState.create({
schema: this.state.schema,
doc: this.getDocFromContent(content),
plugins: this.state.plugins,
})
this.view.updateState(this.state)
if (emitUpdate) {
this.emitUpdate()
}
}
clearContent(emitUpdate = false) {
this.setContent({
type: 'doc',
content: [{
type: 'paragraph',
}],
}, emitUpdate)
}
focus() {
this.view.focus()
}
emit(event, ...data) { emit(event, ...data) {
this.bus.$emit(event, ...data) this.bus.$emit(event, ...data)
} }
@ -131,4 +234,12 @@ export default class Editor {
this.bus.$on(event, callback) this.bus.$on(event, callback)
} }
destroy() {
this.emit('destroy')
if (this.view) {
this.view.destroy()
}
}
} }

View File

@ -0,0 +1,10 @@
import { lift, selectParentNode } from 'prosemirror-commands'
import { undoInputRule } from 'prosemirror-inputrules'
const keymap = {
'Mod-BracketLeft': lift,
Backspace: undoInputRule,
Escape: selectParentNode,
}
export default keymap

View File

@ -1,7 +1,7 @@
// export { default as buildMenuActions } from './buildMenuActions' // export { default as buildMenuActions } from './buildMenuActions'
// export { default as builtInKeymap } from './builtInKeymap' export { default as builtInKeymap } from './builtInKeymap'
// export { default as ComponentView } from './ComponentView' export { default as ComponentView } from './ComponentView'
// export { default as initNodeViews } from './initNodeViews' export { default as initNodeViews } from './initNodeViews'
// export { default as floatingMenu } from './floatingMenu' // export { default as floatingMenu } from './floatingMenu'
// export { default as menuBubble } from './menuBubble' // export { default as menuBubble } from './menuBubble'
export { default as ExtensionManager } from './ExtensionManager' export { default as ExtensionManager } from './ExtensionManager'

View File

@ -0,0 +1,21 @@
import ComponentView from './ComponentView'
export default function initNodeViews({ nodes, editable }) {
const nodeViews = {}
Object.keys(nodes).forEach(nodeName => {
nodeViews[nodeName] = (node, view, getPos, decorations) => {
const component = nodes[nodeName]
return new ComponentView(component, {
node,
view,
getPos,
decorations,
editable,
})
}
})
return nodeViews
}