101 lines
2.8 KiB
JavaScript
101 lines
2.8 KiB
JavaScript
import {EditorState, Plugin} from 'prosemirror-state'
|
|
import {EditorView} from 'prosemirror-view'
|
|
import {history} from 'prosemirror-history'
|
|
import {keymap} from 'prosemirror-keymap'
|
|
import {baseKeymap} from 'prosemirror-commands'
|
|
import {DOMParser, DOMSerializer} from 'prosemirror-model'
|
|
|
|
import {buildKeymap} from './godo-additional-keymap.mjs'
|
|
import {basicSchema, headersSchema, listSchema, fullSchema} from './godo-schemas.mjs'
|
|
import {Menu, blocks, marks} from './godo-menus.mjs'
|
|
|
|
function menuPlugin (menu) {
|
|
return new Plugin({
|
|
view (editorView) {
|
|
let menuView = new Menu(menu, editorView)
|
|
editorView.dom.parentNode.insertBefore(menuView.el, editorView.dom)
|
|
return menuView
|
|
},
|
|
})
|
|
}
|
|
|
|
export default class Godo {
|
|
constructor (textarea, options) {
|
|
this.textarea = textarea
|
|
this.textarea.hidden = true
|
|
this.textarea.style.display = 'none'
|
|
let displayBlocksMenu = true
|
|
|
|
this.defaultOptions = {
|
|
schema: 'full',
|
|
headingLevels: [3, 4],
|
|
}
|
|
this.options = Object.assign(this.defaultOptions, options)
|
|
this.options.headingLevels = this.options.headingLevels.slice(0, 3)
|
|
|
|
this.schema = (() => {
|
|
switch (this.options.schema) {
|
|
case 'basic':
|
|
displayBlocksMenu = false
|
|
return basicSchema
|
|
case 'headers':
|
|
return headersSchema
|
|
case 'list':
|
|
return listSchema
|
|
case 'full':
|
|
default:
|
|
return fullSchema
|
|
}
|
|
})()
|
|
|
|
this.editorWrapper = document.createElement('div')
|
|
this.editorWrapper.className = 'godo'
|
|
textarea.insertAdjacentElement('afterend', this.editorWrapper)
|
|
|
|
this.marksMenu = menuPlugin(marks(this.schema))
|
|
this.blocksMenu = menuPlugin(blocks(this.schema, this.options.headingLevels))
|
|
|
|
let pluginsList = [
|
|
history(),
|
|
keymap(buildKeymap(this.schema, null, this.options)),
|
|
keymap(baseKeymap),
|
|
this.marksMenu,
|
|
]
|
|
|
|
if (displayBlocksMenu && !textarea.readOnly) pluginsList.push(this.blocksMenu)
|
|
|
|
this.state = EditorState.create({
|
|
schema: this.schema,
|
|
doc: DOMParser.fromSchema(this.schema).parse(this.getTextAreaContent()),
|
|
plugins: pluginsList,
|
|
})
|
|
|
|
this.view = new EditorView(this.editorWrapper, {
|
|
state: this.state,
|
|
editable: () => !textarea.readOnly,
|
|
attributes: {
|
|
class: 'godo--editor',
|
|
},
|
|
})
|
|
|
|
this.textarea.form.addEventListener('submit', () => {
|
|
textarea.value = this.getHTML()
|
|
})
|
|
}
|
|
|
|
getTextAreaContent () {
|
|
const w = document.createElement('div')
|
|
w.innerHTML = this.textarea.value
|
|
return w
|
|
}
|
|
|
|
getHTML () {
|
|
const div = document.createElement('div')
|
|
const fragment = DOMSerializer
|
|
.fromSchema(this.schema)
|
|
.serializeFragment(this.view.state.doc.content)
|
|
div.appendChild(fragment)
|
|
return div.innerHTML
|
|
}
|
|
}
|