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 };
}
}