
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <! doctype html> < meta charset = utf8 > < script src = "require-pm.js" ></ script > < script src = "index.js" defer></ script > < style > .menubar { border-bottom: 1px solid rgba(0, 0, 0, 0.2); line-height: 0.1; } .menuicon { display: inline-block; border-right: 1px solid rgba(0, 0, 0, 0.2); color: #888; line-height: 1; padding: 0 7px; margin: 1px; cursor: pointer; text-align: center; min-width: 1.4em; } .strong, .heading { font-weight: bold; } .em { font-style: italic; } #editor { padding-top: 0 } </ style > < div id = editor ></ div > < div style = "display: none" id = content > < h3 >Simple editor</ h3 > < p >With a very crude menu bar. </ div > |
javascript prosemirror :
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | class MenuView { constructor(items, editorView) { this .items = items this .editorView = editorView this .dom = document.createElement( "div" ) this .dom.className = "menubar" items.forEach(({dom}) => this .dom.appendChild(dom)) this .update() this .dom.addEventListener( "mousedown" , e => { e.preventDefault() editorView.focus() items.forEach(({command, dom}) => { if (dom.contains(e.target)) command(editorView.state, editorView.dispatch, editorView) }) }) } update() { this .items.forEach(({command, dom}) => { let active = command( this .editorView.state, null , this .editorView) dom.style.display = active ? "" : "none" }) } destroy() { this .dom.remove() } } const {Plugin} = require( "prosemirror-state" ) function menuPlugin(items) { return new Plugin({ view(editorView) { let menuView = new MenuView(items, editorView) editorView.dom.parentNode.insertBefore(menuView.dom, editorView.dom) return menuView } }) } const {toggleMark, setBlockType, wrapIn} = require( "prosemirror-commands" ) const {schema} = require( "prosemirror-schema-basic" ) // Helper function to create menu icons function icon(text, name) { let span = document.createElement( "span" ) span.className = "menuicon " + name span.title = name span.textContent = text return span } // Create an icon for a heading at the given level function heading(level) { return { command: setBlockType(schema.nodes.heading, {level}), dom: icon( "H" + level, "heading" ) } } let menu = menuPlugin([ {command: toggleMark(schema.marks.strong), dom: icon( "B" , "strong" )}, {command: toggleMark(schema.marks.em), dom: icon( "i" , "em" )}, {command: setBlockType(schema.nodes.paragraph), dom: icon( "p" , "paragraph" )}, heading(1), heading(2), heading(3), {command: wrapIn(schema.nodes.blockquote), dom: icon( ">" , "blockquote" )} ]) const {EditorState} = require( "prosemirror-state" ) const {EditorView} = require( "prosemirror-view" ) const {baseKeymap} = require( "prosemirror-commands" ) const {keymap} = require( "prosemirror-keymap" ) const {DOMParser} = require( "prosemirror-model" ) window.view = new EditorView(document.querySelector( "#editor" ), { state: EditorState.create({ doc: DOMParser.fromSchema(schema).parse(document.querySelector( "#content" )), plugins: [keymap(baseKeymap), menu] }) }) |
require-pm.js
1 2 3 4 5 6 7 8 | // Kludge to make requiring prosemirror core libraries possible. The // PM global is defined by http://prosemirror.net/examples/prosemirror.js, // which bundles all the core libraries. function require(name) { let id = /^prosemirror-(.*)/.exec(name), mod = id && PM[id[1].replace(/-/g, "_" )] if (!mod) throw new Error(`Library menu isn't loaded`) return mod } |
Leave a Reply