Friendly Markdown
想象一下,你有一个允许用户输入评论的网站,并且你决定使用Markdown作为评论输入。你的目标群体大多知道如何使用Markdown,并且觉得它很方便。但是你可能也有一些非技术用户,对于他们来说,学习神秘的语法规则并不容易。
在不更改后端的情况下,您可以将ProseMirror作为替代输入编辑器。人们甚至可以在编辑时在两种视图之间切换!
prosemirror-markdown
包定义了一个ProseMirrorschema,可以准确表达Markdown中可以表达的内容。它还带有一个解析器和序列化器,可以在此schema和Markdown文本之间转换文档。
为了抽象出实际的编辑器,我们首先在文本区域周围创建一个简单的接口:
class MarkdownView {
constructor(target, content) {
this.textarea = target.appendChild(document.createElement("textarea"))
this.textarea.value = content
}
get content() { return this.textarea.value }
focus() { this.textarea.focus() }
destroy() { this.textarea.remove() }
}
然后为支持 Markdown 的 ProseMirror 实例实现相同的接口。此接口的输入和输出仍然是 Markdown 文本,它在内部将其转换为 ProseMirror 文档。
import {EditorView} from "prosemirror-view"
import {EditorState} from "prosemirror-state"
import {schema, defaultMarkdownParser,
defaultMarkdownSerializer} from "prosemirror-markdown"
import {exampleSetup} from "prosemirror-example-setup"
class ProseMirrorView {
constructor(target, content) {
this.view = new EditorView(target, {
state: EditorState.create({
doc: defaultMarkdownParser.parse(content),
plugins: exampleSetup({schema})
})
})
}
get content() {
return defaultMarkdownSerializer.serialize(this.view.state.doc)
}
focus() { this.view.focus() }
destroy() { this.view.destroy() }
}
最后,我们可以连接一些单选按钮,以允许用户在这两种表示之间切换。
let place = document.querySelector("#editor")
let view = new MarkdownView(place, document.querySelector("#content").value)
document.querySelectorAll("input[type=radio]").forEach(button => {
button.addEventListener("change", () => {
if (!button.checked) return
let View = button.value == "markdown" ? MarkdownView : ProseMirrorView
if (view instanceof View) return
let content = view.content
view.destroy()
view = new View(place, content)
view.focus()
})
})