ProseMirror是著名的在线代码编辑器CodeMirror的作者Marijn Haverbeke开发的一款开源(MIT)的富文本编辑器。使用JavaScript开发,可在浏览器中使用。

又一款富文本编辑器?

使用JavaScript开发的富文本编辑器已经有数十种之多,为何还要开发一款新的?作者在其博客中做了一些解释。

基于ContentEditable的传统编辑器

传统的编辑器大都是基于HTML的ContentEditable特性做成的。简单介绍下ContentEditable。ContentEditable其实是HTML元素的属性,若ContentEditable为真,那么浏览器会在相应的HTML元素所述内容区域内显示光标(Caret),允许用户使用鼠标和键盘对这些内容进行修改。同时,对于用户在ContentEditable区域内选中的内容,可以使用Document.execCommand()函数对选中的部分执行一揽子操作,比如把字体改成粗体,改变对齐方向等等。

由于ContentEditable的存在,导致使用JavaScript写一个富文本编辑器变得十分简单。但是,由于ContentEditable存在的缺陷,要让这些富文本编辑器在不同浏览器下变现得一致,则十分困难。核心问题在于ContentEditable只定义了操作,而没有定义操作的效果。比如对于字体加粗这个操作,一些浏览器会在需要加粗的字体上加上<strong>标签,而另外一些浏览器可能会采取另辟蹊径的做法。其次,Document.execCommand()支持的命令,大部分都是基于鼠标选取的。鼠标选取(也就是Selection API)在各个平台的表现也不一致。要知道HTML的DOM是树形结构,在网页上选取一些内容,就相当于选取了DOM树的一部分子树。表面上看起来同样的选取操作,在不同的浏览器下可能会选中不同的DOM子树,造成处理上的麻烦。

传统的编辑器为了应付ContentEditable操作结果不一致的问题伤透了脑筋,常常需要重新调整编辑后的HTML内容,才能使ContentEditable的显示效果在各个浏览器中比较一致。

基于ContentEditable的新式编辑器

可能是受ReactJS的启发,一些新式的编辑器采用与以往不同的方式来应对ContentEditable的问题,这个新的方式是像ReactJS那样,在DOM之上加一层类似VirtualDOM的抽象层。这个新方式的好处在于,把一部分编辑职能从DOM移到了抽象层。这样ContentEditable可以只负责在各个平台表现一致的操作,其他操作则由抽象层代劳。

基于这种新方式的编辑器除了ProseMirror之外,还包括Medium.com的编辑器、Slate、CKEditor5等等。

熟悉ReactJS的都知道,采用VirtualDOM有一个大前提,那就是所有需要更改DOM的操作,都需要经过VirtualDOM来协调。换句话说,所有DOM的状态变化都要经由VirtualDOM统筹协调。这为一些更高级的特性打开了大门,协同编辑是其中一个例子。

有句话说得好:

上帝的归上帝,凯撒的归凯撒。

其他

逸闻趣事

ProseMirror最早是通过众筹来获取资金,以资助作者开发的。

参考链接

(未完待续)

2022-04-16更新

感悟:在ProseMirror响应完DOM,生成transaction的时候,已经生成了对文档的变更,有了新的编辑器状态,然后再告诉给用户或者插件。

相关工具

(更新完)