ProseMirror模块介绍

50 阅读8分钟

本文是ProseMirror系列的第一篇文章,主要是介绍ProseMirror的各个模块的作用,让大家对ProseMirror有一个初始的印象,方便后面开展开发的工作。

介绍

Prose是散文,Mirror是镜子,ProseMirror就是你输入进去的一堆字符,它会给你返回一篇排版美观的散文。ProseMirror是一个基于MIT开源协议的开源的富文本开发库。它是一个基于contentEditable,支持协作编辑和自定义文档结构的,表现良好的富文本编辑器开发库。

ProseMirror不是一个开箱即用的产品。用建房子来做比喻,我们之前常见的一些富文本编辑器,比如wangEditor、UEditor、TinyMCE、CKEditor等,是给你直接建好了装修完好的房子,你可以直接拎包入住,而ProseMirror给你提供的是地基、钢筋、水泥、砖头、建筑工具这些建房子用的材料和工具,你还需要自己设计房子的功能,以及学会使用这些材料和工具才能建造出属于你自己的房子。

ProseMirror拆分成了多个模块,每个模块是一个单独的包,要基于ProseMirror开发则要了解每个模块负责的一些主要功能。下面将会对ProseMirror的每个模块都进行一个简单的介绍。

ProseMirror主要模块

我们先理解下ProseMirror的几个主要模块,我们暂时先不管他们内部是什么构造,而是先看看他们都负责什么样的工作吧。

ProseMirror的每个模块的职责分得很清楚,先按层次来分配好各个独立的工作,然后让对应的模块来将该层的所有工作都实现出来,并且相互配合,完成复杂的富文本器编辑和展示功能。

🌄View层:该层位于最上面,是用户能直接看到也能摸得着的地方。用户在这一层不但看得到的文档,还可以对文档进行操作交互。View层对应的模块为prosemirror-view模块。

🦔Command层:该层对应的是用户的某个操作的逻辑,一般配合菜单按钮来使用,但是因为ProseMirror并不提供菜单的UI的实现,因此一般用户需要自己来实现对应的菜单,并且将菜单的事件绑定到对应Command函数调用。Command层对应的模块为prosemirror-command模块。

🛣️State层:该层是视图层的数据结构,其保存了文档的状态信息,包括文档的树结构,选区和插件等信息。State层对应的模块为prosemirror-state模块。

🚉Transform层:该层是定义了操作文档树结构的原子化操作,这些操作可以被保存下来,一般恢复和重做。有了该模块的存在,就能阻止开发者随意修改树结构,虽然增加开发的复杂度,但是对文档的树结构的完整性有了更好的保护,同时支持还能实现时间穿梭和协作等强大功能。Transform层对应的模块为prosemirror-transform模块。

💽Model层:该层位于ProseMirror的最底层,是文档的模型层,该层主要定义文档树结构的节点模型,以及节点相关规范。其为State层提供文档树提供节点类型和节点定义。Model层对应的模块为prosemirror-model模块。

👬协作层:该层是发送用户的操作的tr数据,以及接收其他用户操作的tr数据,并更新到当前文档的状态中。协作层对应的模块为prosemirror-collab模块。

以下就是各个模块的详细介绍:

prosemirror-view

该模块是视图模块,是最主要的一个入口模块,它的主要任务包括:

将富文本内容渲染到浏览器上,同时接收用户的操作事件包括键盘输入事件以及快捷键事件。同时它也是操作的入口,比如触发一个操作的事务去获取一个新的内部状态,进而通过新的内部状态重新渲染富文本内容。该模块有一个内部状态对象,该对象维护了富文本内容对应的数据结构、用户操作的选区和光标,该状态对象在视图模块对象初始化的时候传入,并且在每个有内容变更时,都会产生一个新的内部状态对象,并通过updateState来更新该状态。

prosemirror-state

该模块实现了富文本编辑器的状态信息的管理,它的主要任务就是管理操作事务、选区,还有编辑器的相关插件。ProseMirror将所有的编辑器状态保存到了一个对象中(state)。该状态可以应用事务(transactions)来创建一个新的state对象,并更新到编辑器视图对象中。该模块包含以下重要概念:

Selection:选区有多种类型,包括文本选区(TextSelection)、节点选区(NodeSelection)和全选选区(AllSelection)。选区还包含选区的范围(SelectionRange)和选区的书签(SelectionBookmark)等信息。

Transaction:Transaction继承了Transform类,是一个操作事务,就是对富文本信息的操作的Transform转换,以及选区的转换信息。事务包含一系列的原子操作,以及每个原子操作前后的doc文档对象。

Plugin System:插件系统主要用于方便地管理和启用额外的编辑器功能。每个插件都可以拥有自己的状态,并附着在编辑器的state上面。

prosemirror-transform

该模块也是一个核心模块,它的主要任务是定义如何修改文档模型的结构的。它定义了一个原子操作步骤Step,并将将一系列原子操作包装成一个Transform对象,让对文档的撤销恢复操作、以及多人协作成为可能。该模块定义了修改文档的一系列步骤,每个Step(步骤)都是一个针对文档原子操作,其中每个Step都有一个对应的反向操作,用于恢复操作。一个Transform对象包含了以下属性类型:

steps:原子性的文档变更的操作步骤,有三个类,分别是AttrStep、MarkStep和ReplaceStep。

docs:对应每个操作步骤前的文档。

doc:应用所有的步骤后的文档。

Position Mapping:对应每个操作前后的位置关联信息

用户对文档的操作往往会产生一系列的操作步骤Steps,而Transform对象可以用来方便管理一系列操作步骤。虽然开发过程中基本很少会直接操作Transform,但可以看下其操作,以便方便理解该模块。

prosemirror-model

该模块是数据模型模块,它的主要任务就是定义一套既适合进行文档操作,也适合文档展示渲染的文档s数据模型,以及规范文档结构的文档模式规范。该模块是最底层的一个模块,我们一般不会直接操作该模块的数据模块,而是通过Transaction去操作。该模块定义了Node数据节点,Node里面有一个Fagment类型的content属性,表示其子节点,而Fagment的content属性则是一个Node数组。还定义了Mark标记节点,用来表示加粗、斜体等标记内容。除此之外,还有一个Schema数据的模式,用于定义文档的每个节点的类型、属性、DOM结构等信息。

prosemirror-commands

该模块主要任务是定义了一系列的用于构建块的封装编辑动作的命令函数。命令可以简单地理解为一系列的Transaction操作。一个命令函数接收一个编辑器的状态(state),以及可选的事务派发器(dispatch)和 编辑器视图(editor view),返回值为布尔值。

prosemirror-collab

该模块主要任务是监听用户的操作,即transaction修改事件,并将该transaction发送同步给其他的协作方。同时也接收来自其他协作方的transaction数据,并及时更新到当前的文档的状态中去。该模块需要协作后台服务来共同完成协作的任务。(目前暂时不涉及)

prosemirror-keymap

该模块主要的任务是定义快捷键,并做快捷键操作事件的统一分发。它是定义了快捷键操作绑定信息的编辑器插件。该模块的核心是keymap方法,参数为bindings(快捷键名与命令的对应关系),返回一个监听keydown事件的并将对应的键盘事件与命令进行调用的插件。比如Enter后的行为,就是通过keymap就是绑定的。

prosemirror-history

该模块的主要任务是做历史记录,它是一个记录用户的操作历史插件,同时也包括了撤销、恢复命令。

prosemirror-schema-basic

该模块主要负责提供一个基本的文档节点结构定义,该结构支持了大部分Markdown文档对应的节点,让你可以快速开发一个Markdown编辑器。该模块虽然不能直接用于项目开发上,但是它给项目开发提供了一个可参考的文档节点定义的示例,富文本开发项目都可以参考这个项目来定义适合自己的文档节点结构。

prosemirror-dev-tools

该模块主要是负责提供一个可视化的State、Schema、History、Plugins的开发工具,让你开发过程可以方便地查看对应的数据。

参考文档

prosemirror.net/docs/guide/