初探富文本之编辑器引擎

初探,文本,编辑器,引擎 · 浏览次数 : 407

小编点评

**quill 文档概述** quill 是一个现代富文本编辑器,它拥有良好的兼容性和强大的可扩展性,还提供了部分开箱即用的功能。 **架构原则** * API驱动设计:quill 所有功能都是通过 API 来实现的,并可以直观的通过 API 来获得数据的变化。 * 基础功能的支持很丰富:quill 提供许多基础功能,包括文本编辑、格式设置和协同支持。 * 视图层:quill 使用视图层实现数据结构的展示,与框架无关。 * Delta 设计:quill 使用 Delta 设计来描述数据结构,可以非常方便地实现协同。 **功能** * 语言支持:支持许多编程语言,包括 JavaScript、TypeScript、Java 和 Python。 * 编辑器模式:支持多种编辑器模式,包括单行、双行和多行模式。 * 协同支持:支持多种协同协议,包括 RichText、Draft 和 CRDT-yjs。 * 数据持久化:支持数据持久化,例如 HTML 存储。 **性能** * 性能非常出色,即使处理大量内容时也不会卡顿。 **生态** *quill提供了非常丰富的插件和设计方案,可以参考来扩展其功能。 * 许多框架支持quill,包括 React、Vue 和 Svelte。 **使用说明** * 访问 quill 官方网站(quilljs.com)获取更多信息和示例。 * 使用 draft.js 框架构建富文本编辑器。 * 使用 Daily 一题等资源来学习 quill。

正文

初探富文本之编辑器引擎

在前文中我们介绍了富文本的基础概念,以及富文本的基本发展历程,那么在本文中将会介绍当前主流开源的富文本编辑器引擎。当前使用最广泛的富文本编辑器是L1的富文本编辑器,其能满足绝大部份使用场景,由此也诞生了非常多优秀的开源富文本引擎,这其中有仅提供引擎的编辑器例如Slate.js,也有提供了部分开箱即用的功能的例如Quill.js,也有基于这些引擎二次开发的例如Plate.js,本文主要介绍了Slate.jsQuill.jsDraft.js三款编辑器引擎。

Slate.js

slate是一个仅仅提供引擎的富文本core,简单来说他本身并不提供各种富文本编辑功能,所有的富文本功能都需要自己来通过其提供的API来实现,甚至他的插件机制也需要通过自己来拓展,所以使用slate来构建富文本编辑器的话可定制度相当高。slate的文档虽然不是特别详细,但是他的示例是非常丰富的,在文档中也提供了一个演练作为上手的基础,对于新手还是比较友好的。话说回来如果只提供一个引擎的话,谁也不知道应该怎么用哈哈。

slate的文档中有对于框架的设计原则上的描述:

  • 插件是一等公民,slate最重要的部分就是插件是一等公民实体,这意味着你可以完全定制编辑体验,去建立像Medium或是Dropbox这样复杂的编辑器,而不必对库的预设作斗争。
  • 精简的schema核心,slate的核心逻辑对你编辑的数据结构进行的预设非常少,这意味着当你构建复杂用例时,不会被任何的预制内容所阻碍。
  • 嵌套文档模型,slate文档所使用的模型是一个嵌套的,递归的树,就像DOM一样,这意味着对于高级用例来说,构建像表格或是嵌套引用这样复杂的组件是可能的,当然你也可以使用单一层次的结构来保持简单性。
  • DOM相同,slate的数据模型基于DOM,文档是一个嵌套的树,其使用文本选区selections和范围ranges,并且公开所有的标准事件处理函数,这意味着像是表格或者是嵌套引用这样的高级特性是可能的,几乎所有你在DOM中可以做到的事情,都可以在slate中做到。
  • 直观的指令,slate文档执行命令commands来进行编辑,它被设计为高级并且非常直观地进行编辑和阅读,以便定制功能尽可能地具有表现力,这大大的提高了你理解代码的能力。
  • 可协作的数据模型,slate使用的数据模型特别是操作如何应用到文档上,被设计为允许协同编辑在最顶层,所以如果你决定要实现协同编辑,不必去考虑彻底重构。
  • 明确的核心划分,使用插件优先的结构和精简核心,使得核心和定制的边界非常清晰,这意味着核心的编辑体验不会被各种边缘情况所困扰。

示例

这样一段文本数据结构如下所示。

[
  {
    children: [
      { text: "这样" },
      { text: "一段文本", italic: true },
      { text: "的" },
      { text: "数据结构", bold: true },
      { text: "如下所示。" },
    ],
  },
];

优势

  • 可定制化程度非常高,几乎所有富文本表现层的功能都需要自行实现。
  • 非常轻量,本体只有一个内核,需要什么就做什么功能,体积可控。
  • 在设计架构时就针对协同提供了OP化的差量变更操作。
  • 数据结构是类似于DOM的嵌套JSON结构,比较直观容易理解。

不足

  • 依旧处于Beta阶段,可能会有重大API变化,例如0.50版本就是全新重构的。
  • 虽然有协同的设计,但没有转换操作的OT算法或CRDT算法的直接支持。
  • 仅有内核的架构同样也是不足,所有的功能都需要自行实现,成本比较高。
  • 新版slate是无schema的,这也就意味着Normalize需要自行实现。

参考

  • slate官方文档https://docs.slatejs.org/
  • slate官方示例https://www.slatejs.org/examples/richtext
  • 个人基于slate实现的富文本编辑器https://github.com/WindrunnerMax/DocEditor
  • 基于slate的开箱即用富文本编辑器https://plate.udecode.io/docs/playground
  • slateOT协同实现参考https://github.com/solidoc/slate-ot
  • slate协同的OTTypes参考https://github.com/pubuzhixing8/ottype-slate
  • slateCRDT协同实现参考https://github.com/humandx/slate-automerge
  • slateYJS协同结合的参考https://github.com/BitPhinix/slate-yjs
  • 关于slate非常不错的文章https://github.com/yoyoyohamapi/book-slate-editor-design

Quill.js

quill是一个现代富文本编辑器,具备良好的兼容性及强大的可扩展性,还提供了部分开箱即用的功能。quill是在2012年开源的,quill的出现给富文本编辑器带了很多新的东西,也是目前开源编辑器里面受众非常大的一款编辑器,至今为止的生态已经非常的丰富,可以在Github等找到大量的示例,包括比较完善的协同实例。

quill的文档中有对于框架的设计原则上的描述:

  • API驱动设计,quill所有的功能都是通过API来实现的并且可以直观的通过API来获得数据的变化,以文本为中心的基础上构建的API,不需要解析HTML或者DIFF DOM树,这样的设计可以让quill的功能更加的灵活与更高的可拓展性。
  • 自定义内容和格式,quill公开了自己的文档模型,这是对DOM的强大抽象,允许扩展和定制,由此数据结构的主角变成了BlotsParchmentDelta
  • 跨平台,quill有着比较良好的兼容性,在旧版本的浏览器中也可以相同的方式运行,在用户体验上不同浏览器中也可以有着相同的视图与交互效果,并且可以在桌面和移动设备上使用。
  • 易于使用,quill携带了部分开箱即用的功能,如果不需要定制的话,这些功能已经足够了,同时quill又有着非常高的可拓展性,用来自定义各种功能。

示例

这样一段文本数据结构如下所示。

{
  ops: [
    { insert: "这样" },
    { insert: "一段文本", attributes: { italic: true } },
    { insert: "的" },
    { insert: "数据结构", attributes: { bold: true } },
    { insert: "如下所示。\\n" },
  ],
};

优势

  • API驱动设计,基础功能的支持很丰富,并且支持拓展。
  • 实现了视图层,实现上与框架无关,无论是Vue还是React都可以轻松使用。
  • 使用了更加直观的Delta来描述数据结构,本身实现了操作转换的逻辑,可以非常方便地实现协同。
  • 生态非常丰富,有着非常多的插件与设计方案可以参考,特别是对于协同的支持可参考的地方非常多。

不足

  • Delta数据结构是扁平的,也就是一维的数据结构,这样在实现例如表格的功能时就比较麻烦。
  • quill 2.0已经开发了很久了,但是还没有正式发布,目前的1.3.7版本已经有很多年没有更新了。
  • quill自带的功能很丰富,但这也就意味着其包的大小会比较大一些。

参考

  • quill官方文档https://quilljs.com/docs/quickstart/
  • quill官方示例https://quilljs.com/standalone/full/
  • quillDelta设计与实现https://quilljs.com/docs/delta/
  • quill协同的OTTypes参考https://github.com/ottypes/rich-text
  • quillOT协同实现参考https://github.com/share/sharedb/tree/master/examples/rich-text
  • quillCRDT-yjs的协同实现参考https://github.com/yjs/y-quill

Draft.js

draft是用于在React中构建富文本编辑器的框架,其为创建和自定义文本编辑器提供了强大的API,并且旨在易于扩展和与其他库集成,与React结合可以使开发者在进行编辑器开发时既不用操作DOM、也不用单独学习一套构建UI的范式,而是可以直接编写React组件实现编辑器的UIdraft整体理念与React非常的吻合,例如使用状态管理保存数据结构、使用immutable.js库、数据结构的修改基本全部代理了浏览器的默认行为、通过状态管理的方式修改富文本数据等。

draftREADME中有对于框架的设计原则上的描述:

  • 可扩展和可定制,提供了构建块来创建各种丰富的文本组合体验,从基本文本样式到嵌入式媒体的支持。
  • 声明式富文本,draft无缝融入React,使用React用户熟悉的声明式的API抽象出渲染、选择和输入行为的细节。
  • 不可变的编辑器状态,draft模型是使用immutable.js构建的,提供具有功能状态更新的API,并积极利用数据持久性来实现可扩展的内存使用。

示例

这样一段文本数据结构如下所示。

{
  blocks: [
    {
      key: "3eesq",
      text: "这样一段文本的数据结构如下所示。",
      type: "unstyled",
      depth: 0,
      inlineStyleRanges: [
        { offset: 2, length: 4, style: "ITALIC" },
        { offset: 7, length: 4, style: "BOLD" },
      ],
      entityRanges: [],
      data: {},
    },
  ],
  entityMap: {},
};

优势

  • 具有灵活的API,可以轻松地扩展和自定义块和内联元素等。
  • 使用React作为UI层以及数据管理,可以充分利用React生态,对React用户友好。
  • 没有过重大的Breaking Change,在稳定性与细节的处理上比较具有优势。

不足

  • 完全依赖于React作为UI层,与React深度绑定,在其他UI框架上很难使用。
  • 数据结构模型的设计上不是很灵活,在实现表格等嵌套结构时比较受限。
  • draft针对性能进行了大量优化,但是在呈现大量内容时还是会感受到卡顿。

参考

  • draft官方文档https://draftjs.org/docs/overview
  • draft官方示例https://draftjs.org/
  • draftcodesandbox示例https://codesandbox.io/s/github/gupta-piyush19/Draft-JS-Editor

每日一题

https://github.com/WindrunnerMax/EveryDay

参考

https://github.com/hzjswlgbsj/blog
https://zhuanlan.zhihu.com/p/425265438
https://jkrsp.com/slate-js-vs-draft-js/
https://www.zhihu.com/question/404836496
https://www.zhihu.com/question/449541344
https://juejin.cn/post/6844903838982340622
https://juejin.cn/post/7034480408888770567
https://juejin.cn/post/6974609015602937870
https://github.com/cudr/slate-collaborative
https://blog.logrocket.com/what-is-slate-js-replace-quill-draft-js/
https://dev.to/charrondev/getting-to-know-quilljs---part-1-parchment-blots-and-lifecycle--3e76

与初探富文本之编辑器引擎相似的内容:

初探富文本之编辑器引擎

初探富文本之编辑器引擎 在前文中我们介绍了富文本的基础概念,以及富文本的基本发展历程,那么在本文中将会介绍当前主流开源的富文本编辑器引擎。当前使用最广泛的富文本编辑器是L1的富文本编辑器,其能满足绝大部份使用场景,由此也诞生了非常多优秀的开源富文本引擎,这其中有仅提供引擎的编辑器例如Slate.js

初探富文本之React实时预览

初探富文本之React实时预览 在前文中我们探讨了很多关于富文本引擎和协同的能力,在本文中我们更偏向具体的应用组件实现。在一些场景中比如组件库的文档编写时,我们希望能够有实时预览的能力,也就是用户可以在文档中直接编写代码,然后在页面中实时预览,这样可以让用户更加直观的了解组件的使用方式,这也是很多组

初探富文本之OT协同算法

初探富文本之OT协同算法 OT的英文全称是Operational Transformation,是一种处理协同编辑的算法。当前OT算法用的比较多的地方就是富文本编辑器领域了,常用于作为实现文档协同的底层算法,支持多个用户同时编辑文档,不会因为用户并发修改导致冲突,而导致结果不一致甚至数据丢失的问题。

初探富文本之富文本概述

初探富文本之富文本概述 富文本编辑器通常指的是可以对文字、图片等进行编辑的产品,具有所见即所得的能力。对于Input、Textarea之类标签,他们是支持内容编辑的,但并不支持带格式的文本或者是图片的插入等功能,所以对于这类的需求就需要富文本编辑器来实现。现在的富文本编辑器也已经不仅限于文字和图片,

初探富文本之基于虚拟滚动的大型文档性能优化方案

初探富文本之基于虚拟滚动的大型文档性能优化方案 虚拟滚动是一种优化长列表性能的技术,其通过按需渲染列表项来提高浏览器运行效率。具体来说,虚拟滚动只渲染用户浏览器视口部分的文档数据,而不是整个文档结构,其核心实现根据可见区域高度和容器的滚动位置计算出需要渲染的列表项,同时不渲染额外的视图内容。虚拟滚动

初探富文本之OT协同实例

初探富文本之OT协同实例 在前边初探富文本之OT协同算法一文中我们探讨了为什么需要协同、为什么仅有原子化的操作并不能实现协同、为什么要有操作变换、如何进行操作变换、什么时候能够应用操作、服务端如何进行协同调度等等,这些属于完成协同所需要了解的基础知识,实际上当前有很多成熟的协同实现,例如ot.js、

初探富文本之CRDT协同算法

初探富文本之CRDT协同算法 CRDT的英文全称是Conflict-free Replicated Data Type,最初是由协同文本编辑和移动计算而发展的,现在还被用作在线聊天系统、音频分发平台等等。当前CRDT算法在富文本编辑器领域的协同依旧是典型的场景,常用于作为实现文档协同的底层算法,支持

初探富文本之CRDT协同实例

初探富文本之CRDT协同实例 在前边初探富文本之CRDT协同算法一文中我们探讨了为什么需要协同、分布式的最终一致性理论、偏序集与半格的概念、为什么需要有偏序关系、如何通过数据结构避免冲突、分布式系统如何进行同步调度等等,这些属于完成协同所需要了解的基础知识,实际上当前有很多成熟的协同实现,例如aut

应用部署初探:微服务的3大部署模式

在之前的文章中,我们已经充分了解了应用部署的4种常见模式(金丝雀部署、蓝绿部署、滚动部署及影子部署)。随着云原生技术逐步成熟,企业追求更为灵活和可扩展的系统,微服务架构大行其道。 微服务固然有诸多优点,但也给架构及运维工程师带来了新的挑战。在单体架构中,应用的设计、部署以及扩展都是作为一个单元进行,

应用部署初探:6个保障安全的最佳实践

在之前的文章中,我们了解了应用部署的阶段以及常见的部署模式,包括微服务架构的应用应该如何部署等基本内容。本篇文章将介绍如何安全地部署应用程序。 安全是软件开发生命周期(SDLC)中的关键部分,同时也需要成为 SDLC 中每个环节的一部分,尤其是部署。因此,保障应用部署安全并不是开始于部署阶段,而是从