godo.js/src-js/godo.js

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 {basic_schema, headers_schema, full_schema} 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.default_options = {
schema: "full",
heading_levels: [3, 4]
}
this.options = Object.assign(this.default_options, options);
this.options.heading_levels = this.options.heading_levels.slice(0, 3);
this.schema = (() => {
switch(this.options.schema) {
case 'basic':
displayBlocksMenu = false;
return basic_schema;
break;
case 'headers':
return headers_schema;
break;
case 'full':
default:
return full_schema
};
})();
this.editor_wrapper = document.createElement('div');
this.editor_wrapper.className = "godo";
textarea.insertAdjacentElement('afterend', this.editor_wrapper);
this.marksMenu = menuPlugin(marks(this.schema));
this.blocksMenu = menuPlugin(blocks(this.schema, this.options.heading_levels));
let plugins_list = [
history(),
keymap(baseKeymap),
keymap(buildKeymap(this.schema, null, this.options)),
this.marksMenu
];
if (displayBlocksMenu) plugins_list.push(this.blocksMenu);
this.state = EditorState.create({
schema: this.schema,
doc: DOMParser.fromSchema(this.schema).parse(this.get_textarea_content()),
plugins: plugins_list
});
this.view = new EditorView(this.editor_wrapper, {
state: this.state,
attributes: {
class: "godo--editor"
}
});
this.textarea.form.addEventListener('submit', e => {
textarea.value = this.getHTML();
});
}
get_textarea_content() {
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;
}
}