友好的 markdown
想象一下你有一个允许用户输入评论的网站,同时你决定让用户在评论输入的时候使用 Markdown。
你的大部分用户都知道如何使用 Markdown,并且觉得它很方便。但是你可能还要面对一些非技术的用户,
他们对学习 Markdown 的晦涩难懂的语法规则并不感冒。
不用修改你后端服务的任何东西,你可以将 ProseMirror 作为你的编辑器。
人们在编辑的时候可以随时切换到正常编辑模式和 Markdown 编辑模式!
prosemirror-markdown
库定义了
一个 ProseMirror 的 schema ,它支持了 Markdown 的语法及元素。
它也提供了一个 parser 和 serializer 来将普通文档和 Markdown 文档相互转化。
为了抽象这个实际的编辑器,我们首先在 textarea 中创建了一个 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()
})
})