]> BookStack Code Mirror - bookstack/blob - resources/js/editor.js
Started playing with prosemirror
[bookstack] / resources / js / editor.js
1 import {EditorState} from "prosemirror-state";
2 import {EditorView} from "prosemirror-view";
3 import {exampleSetup} from "prosemirror-example-setup";
4 import {defaultMarkdownParser,
5     defaultMarkdownSerializer} from "prosemirror-markdown";
6 import {DOMParser, DOMSerializer} from "prosemirror-model";
7
8 import {schema} from "./editor/schema";
9
10 class MarkdownView {
11     constructor(target, content) {
12
13         // Build DOM from content
14         const renderDoc = document.implementation.createHTMLDocument();
15         renderDoc.body.innerHTML = content;
16
17         const htmlDoc = DOMParser.fromSchema(schema).parse(renderDoc.body);
18         const markdown = defaultMarkdownSerializer.serialize(htmlDoc);
19
20         this.textarea = target.appendChild(document.createElement("textarea"))
21         this.textarea.value = markdown;
22     }
23
24     get content() {
25         const markdown = this.textarea.value;
26         const doc = defaultMarkdownParser.parse(markdown);
27         const fragment = DOMSerializer.fromSchema(schema).serializeFragment(doc.content);
28         const renderDoc = document.implementation.createHTMLDocument();
29         renderDoc.body.appendChild(fragment);
30         return renderDoc.body.innerHTML;
31     }
32
33     focus() { this.textarea.focus() }
34     destroy() { this.textarea.remove() }
35 }
36
37 class ProseMirrorView {
38     constructor(target, content) {
39
40         // Build DOM from content
41         const renderDoc = document.implementation.createHTMLDocument();
42         renderDoc.body.innerHTML = content;
43
44         this.view = new EditorView(target, {
45             state: EditorState.create({
46                 doc: DOMParser.fromSchema(schema).parse(renderDoc.body),
47                 plugins: exampleSetup({schema})
48             })
49         });
50     }
51
52     get content() {
53         const fragment = DOMSerializer.fromSchema(schema).serializeFragment(this.view.state.doc.content);
54         const renderDoc = document.implementation.createHTMLDocument();
55         renderDoc.body.appendChild(fragment);
56         return renderDoc.body.innerHTML;
57     }
58     focus() { this.view.focus() }
59     destroy() { this.view.destroy() }
60 }
61
62 const place = document.querySelector("#editor");
63 let view = new ProseMirrorView(place, document.getElementById('content').innerHTML);
64
65 const markdownToggle = document.getElementById('markdown-toggle');
66 markdownToggle.addEventListener('change', event => {
67     const View = markdownToggle.checked ? MarkdownView : ProseMirrorView;
68     if (view instanceof View) return
69     const content = view.content
70     console.log(content);
71     view.destroy()
72     view = new View(place, content)
73     view.focus()
74 });