1

富文本编辑器

 1 year ago
source link: http://muyunyun.cn/blog/vk4ikovw/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

富文本编辑器的层级

  • L1: 兼容性层面的优化, 自行实现 undo/redo 栈;
  • L2: 移动端/国际化适配;

一个好的框架设计: 尽量少的提前做的假设限制!

  1. 给元素上加上 contenteditable 属性
  2. 给选中元素执行 document.execCommand()

另外一种方法是内嵌 iframe, 并将其 designmode 属性设置为 true。(有跨域问题, 日后填坑)

Slate 框架

可以使用 editor.value.toJSON() 打印 tree 结构, 便于调试;

slate 设计模式

  • 兜底原则
    • normalizeNode, 除指定节点外都走该 normalize 机制;

有序列表的设计

  1. 小圆点 + 数字作为一个结构;
  2. 点击有序列表, 当前节点的同级兄弟节点都会变为有序列表;
  3. 点击可以取消有序列表;
  4. 当在有序列表的节点建立兄弟节点或子节点时, 自动设置为有序列表;
  5. 子节点规则 1 —— 1.1 —— 1.1.1 —— 1.1.1.1;
  6. 当把某个子节点从有序节点变为无序节点时, 该节点的兄弟节点也变为无序; 该节点的子节点从 1 开始计数;
  7. 原则: 兄弟节点必须都为有序或无序, 子节点可以无序也可以有序;
  1. 因此对 selection 是不敏感的, 即操作一个都会同时对同层级所有节点生效;

slate 开发坑点

  • 一种方式开发完之后, 在某些情况下是不满足的, 因此需要返工。
    • example: 输入 @、# 进行筛选最初是使用 set 方式实现的, 一开始这样设计是没问题的, 但是考虑未来在多人协作过程中会造成一份数据的互相影响, 因此将其重构调整为将筛选的数据绕开 set 的方式, 取而代之的是外面传递进来。

small tip

small tip in slate editor

When input b after a in page #slate #editor.





console.log(editor.value.texts.get(0)) // 'a';
requestAnimationFrame(() => {
console.log(editor.value.texts.get(0)) // 'ab'

Web Excel

  • Google Sheets
  • Office 365
  • WPS Web
  • 钉钉表格
    • 可扩展的表格
      • 棋盘模型
        • Range 模型
    • 协同的表格
      • 名词
        • cp(Check Point): 全量表格数据
        • op(Operation): 单次操作的表达
      • OT(Operation Transform) 是协同算法的关键。
      • 上限更高的 COT 调度算法要求 OT 同时运行在服务端与客户端
      • Rust + WASM 实现 OT, 已验证最小闭环
    • 高性能的表格
      • 选择 canvas 渲染表格主界面, 不用 DOM 的原因是浪费在 DOM Pipeline 的开销很大
      • 分层渲染管线
      • 双缓冲画布, 支持流畅的滚动
      • 自研排版引擎
  • etherpad-lite

    • 基于 OT 开发的从底层支持协同编辑的框架。
    • 代表: 飞书、石墨
    • 问题: 十年前代码、技术栈陈旧
    • 核心方法:
      • apply
      • compose
      • follow: 解决两个 changeset 冲突问题
      • inverse: 反操作, undo
  • Changeset

    • 代表对文档的一次修改
    • eg: Z:4>1=1*0+1$2
      • Z: 代表是一个 Changeset
      • 4>1: 源文档 4 个字符长度, 本次修改增加一个字符
      • =1: 跳过第一个字符
      • *0+1: 插入一个字符, 并且带上属性 0
      • $2: 插入的具体字符
    • Changeset Iterator, 解析上述 Changeset 的库
    • 行属性: 标题
    • 块属性: 图片
  • 问题一: follow 为什么要对 A 与 B 都要处理, 可否只对一处进行处理?

  • 问题二: etherpad-lite 服务端与客户端协同的处理? (要有一个 master)

    1. 服务端设置为 true
    2. 客户端设置为 false
    • 弱网情况下, 如何优化协同问题? (比如输入拼音, 被截断, 无法删除)

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK