2019-01-11: codemirror1和6有各自的问题, 因此, 我用prosemirror试一试.
2019-01-11: 这个有空再搞, marijn对应editable的文档和代码都比较难搞. 我自己先写写看, 实在不行再来读他的.

时隔半年, 认真的写一篇吧, cm1已经阅读了源码, 并且看了所有的文档. 现在看看prosemirror.

参考两份文档
  • http://marijnhaverbeke.nl/blog/prosemirror.html
  • http://marijnhaverbeke.nl/blog/collaborative-editing.html

下面我们逐段来看

起源和缘起
  • 作者睡不着觉, 想着再开一个开源项目.
  • 于是又一个web editor诞生了.
一个编辑器

marijn认为, 现在有几百个基于editable的编辑器了. 但是, 他们没有实现marijn的想法, 其中一些基于老旧的写法, 导致我们很难控制在浏览器的作用下的文档.

那么, 我们需要控制什么呢? 文档的一个清晰的状态, 如果文档只由我们的editor控制, 那么我们可以保证文档处在一个很简明的状态. 任何一串操作导致的都是同样的结果.

更重要的是, 完全的单一控制, 可以让你对[修改]进行抽象, 不仅仅是因为用户做了啥, 我们就生成对应的状态, 这样太琐碎了, 对导致我们无法对协同操作做处理. 对[修改]做了抽象之后, 非常利于多个用户同时编辑的协同处理, 尤其是处理编辑冲突.

处理概要

prosemirror使用了editable的element. 这样的优势: 获得焦点和光标处理简单, 非常易于支持屏幕阅读和双向文字.

所有的实质性修改都被完全控制, 通过捕获对应的浏览器时间来实现. 然后, 我们把这些时间转化为我们对应的处理, 在现代浏览器中, 这些文档修改操作大部分都非常好处理. 我们可以捕获, 键盘事件, 尤其是删除和回车. 我们可以捕获剪贴板事件来处理copy和粘贴. 拖动也可以同样处理, 甚至于输入法事件也可以通过composition实现.

不幸的是有一些情况下浏览器没有触发任何事件, 我们只能得到一个滞后的input事件, 比如用户从拼写检查的菜单拿到一个候选项, 或者用户使用了组合键输入, 比如. 幸运的是这种情况我们可以检测dom, 定时比较dom, 然后决定做什么.

当一个修改导致文档的描述发生变化后, 展示会随之修改. 这个策略通过维护一个持续的数据结构, 每次修改都是建一个新的文档对象, 而不是维护一个修改的文档. 我们实现了一个非常快速的dom比较算法, 在更新的dom的时候只更新需要更新的部分, 类似react. 为此prosemirror独自实现了一个文档结构, 并没有像react一样使用了一个类似dom的文档结构.

文档结构

文档结构使用了markdown. 段落, 标题, 列表. 维护成了树, 因为儿子可以包含儿子. 所有的块级元素比如段落或者标题, 他们的内部是平的inline元素构成, 每一种inline元素都有对应的style. 这个比树结构(例如原生dom)好. 原因是: 这种方式非常适合做各种格式化的处理, 并且也非常适合做位置和光标处理, 就像再纯文本中的处理一样. 直接用offest就可以了.

段落这样的块级之外, 我们用的是tree. 所以位置由树的path决定. 这个路径头部是一个深度描述, 可以顺着路径找到合适的节点. 路径的尾部是节点的offset, 可以找到具体的位置. 由此可以用路径描述光标.

prosemirror的文档模型就是markdown, 未来可以扩展.

界面

当前有两个风格的界面. 一个是顶部的正常的按钮. 然后还有一个根据上下文弹出的菜单. 根据选择的内容弹出块级和行内的对应操作菜单.

这个界面是模块化的, 并且独立于编辑器核心, 因此, 可以做定制化和扩展.

快捷键也是可以配置的, 遵从codemirror模式. 一般情况下用execcommand实现.

有一个模块: 输入规则, 这个模块解决的是匹配输入模式, 比如自动化引号, 或者有序列表[1.] 加空格之后触发的规则.

协同

支持实时协同工作. 这是一个大课题, 不过也可以简略的描述一下:

一个修改发生时, 我们做一个新的doc并且关联一个位置map. 因为这个位置map导致有rebase的可能性. marijn费了很大劲才实现这个rebase特性.

简单的说就是强制rebase, 强制同步处理文档, 尤其是有多个端同时修改同一份文档的时候.

目标
  • 易用的markdown编辑器.
  • 让大家从富文本迁移出来, 迁移到清除了无用复杂的html的编辑器.
  • 提供一个真正的协同工作的编辑器. 超越google docs的体验的编辑器.
官方的有意义的文档
  • https://prosemirror.net/docs/guide/
  • https://prosemirror.net/docs/ref/