Prosemirror核心概念
Nov. 26 · 3min
个人觉得prosemirror的概念还是比较难理解的,在深入源码之前,有必要对这些概念有一个大致的了解。
schema
shema用于定义编辑器的文档模型,一个基本的schema定义如下:
import { Schema } from "prosemirror-model";
// schema由nodes和marks组成
const exampleSchema = new Schema({
nodes: {
// doc必须定义
doc: {
content: "paragraph+"
},
paragraph: {
content: "text*",
group: "block",
// DOM的解析规则。
// 这条规则的意思是:如果遇到p标签,就解析为paragraph节点
parseDOM: [{ tag: "p" }],
// 转换为DOM的规则。
// 这条规则的意思是:如果遇到paragraph节点,就转换为p标签,0叫做“洞”(hole),表示可以插入内容
toDOM(node) { return ["p", 0] },
},
text: {}
},
marks: {
strong: {
parseDOM: [{ tag: "strong" }],
toDOM() { return ["strong"] }
}
}
});
selection
prosemirror的选区系统。
new Selection(
$anchor: ResolvedPos,
$head: ResolvedPos,
ranges: readonly SelectionRange[]
)
slice
new Slice(
content: Fragment,
openStart: number, // slice开头未闭合的标签深度
openEnd: number // slice结尾未闭合的标签深度
)
transactions
prosemirror借鉴了redux的思想,不直接修改state,而是在旧的state的基础上,通过dispatch(transaction)生成新的state。
steps
step是文档修改的最小单位,一个tranaction可以包含多个steps,保存在transaction的steps属性中。
mapping
文档经过一系列steps修改后,可以通过mapping将旧的位置映射到新的位置。
commands
编辑器命令,可以通过keymap建立键盘快捷键与命令之间的映射。Command函数接收state和可选的dispatch作为参数,返回boolean。
plugins
插件系统用于为编辑器添加额外的功能,一个简单的插件定义如下:
const myPlugin = new Plugin({
// 插件名称
name: "myPlugin",
// 插件初始化函数
init() {
// 插件初始化时,将插件的state初始化为一个空对象
this.state = {};
},
// 插件的状态更新函数
apply(tr, state) {
// 根据tr和state更新插件state
if (tr.docChanged) {
this.state = {...this.state,...state.toJSON() };
} else {
this.state = {...this.state };
}
}
> cd ..