1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-06-29 04:01:49 +03:00

Started playing with prosemirror

- Got base setup together with WYSIWYG/Markdown switching, where HTML is
  the base content format.
- Added some testing routes/views for initial development.
- Added some dev npm tasks to support editor-specific actions.
This commit is contained in:
Dan Brown
2021-11-26 15:05:06 +00:00
parent c3f7b39a0f
commit 27f9e8e4bd
6 changed files with 551 additions and 0 deletions

74
resources/js/editor.js Normal file
View File

@ -0,0 +1,74 @@
import {EditorState} from "prosemirror-state";
import {EditorView} from "prosemirror-view";
import {exampleSetup} from "prosemirror-example-setup";
import {defaultMarkdownParser,
defaultMarkdownSerializer} from "prosemirror-markdown";
import {DOMParser, DOMSerializer} from "prosemirror-model";
import {schema} from "./editor/schema";
class MarkdownView {
constructor(target, content) {
// Build DOM from content
const renderDoc = document.implementation.createHTMLDocument();
renderDoc.body.innerHTML = content;
const htmlDoc = DOMParser.fromSchema(schema).parse(renderDoc.body);
const markdown = defaultMarkdownSerializer.serialize(htmlDoc);
this.textarea = target.appendChild(document.createElement("textarea"))
this.textarea.value = markdown;
}
get content() {
const markdown = this.textarea.value;
const doc = defaultMarkdownParser.parse(markdown);
const fragment = DOMSerializer.fromSchema(schema).serializeFragment(doc.content);
const renderDoc = document.implementation.createHTMLDocument();
renderDoc.body.appendChild(fragment);
return renderDoc.body.innerHTML;
}
focus() { this.textarea.focus() }
destroy() { this.textarea.remove() }
}
class ProseMirrorView {
constructor(target, content) {
// Build DOM from content
const renderDoc = document.implementation.createHTMLDocument();
renderDoc.body.innerHTML = content;
this.view = new EditorView(target, {
state: EditorState.create({
doc: DOMParser.fromSchema(schema).parse(renderDoc.body),
plugins: exampleSetup({schema})
})
});
}
get content() {
const fragment = DOMSerializer.fromSchema(schema).serializeFragment(this.view.state.doc.content);
const renderDoc = document.implementation.createHTMLDocument();
renderDoc.body.appendChild(fragment);
return renderDoc.body.innerHTML;
}
focus() { this.view.focus() }
destroy() { this.view.destroy() }
}
const place = document.querySelector("#editor");
let view = new ProseMirrorView(place, document.getElementById('content').innerHTML);
const markdownToggle = document.getElementById('markdown-toggle');
markdownToggle.addEventListener('change', event => {
const View = markdownToggle.checked ? MarkdownView : ProseMirrorView;
if (view instanceof View) return
const content = view.content
console.log(content);
view.destroy()
view = new View(place, content)
view.focus()
});