富文本编辑器剪贴板模块,序列化与反序列化如何实现?
摘要:在富文本编辑器中,序列化与反序列化是非常重要的环节,其涉及到了编辑器的内容复制、粘贴、导入导出等模块。当用户在编辑器中进行复制操作时,富文本内容会被转换为标准的HTML格式,并存储在剪贴板中。而在粘贴操作中,编辑器则需要将这些HTML内容解
在富文本编辑器中,序列化与反序列化是非常重要的环节,其涉及到了编辑器的内容复制、粘贴、导入导出等模块。当用户在编辑器中进行复制操作时,富文本内容会被转换为标准的HTML格式,并存储在剪贴板中。而在粘贴操作中,编辑器则需要将这些HTML内容解析并转换为编辑器的私有JSON结构,以便于实现跨编辑器内容的统一管理。
描述
我们平时在使用一些在线文档编辑器的时候,可能会好奇一个问题,为什么我们能够直接把格式复制出来,而不仅仅是纯文本,甚至于说从浏览器中复制内容到Office Word都可以保留格式。这看起来是不是一件很神奇的事情,不过当我们了解到剪贴板的基本操作之后,就可以了解这其中的底层实现了。
说到剪贴板的操作,在执行复制行为的时候,我们可能会认为复制的就是纯文本,然而显然光靠复制纯文本我们是做不到上述的功能。所以实际上剪贴板是可以存储复杂内容的,那么在这里我们以Word为例,当我们从Word中复制文本时,其实际上是会在剪贴板中写入这么几个key值:
text/plain
text/html
text/rtf
image/png
看着text/plain是不是很眼熟,这显然就是我们常见的Content-Type或者称作MIME-Type,所以说我们是不是可以认为剪贴板是一个Record<string, string>的结构类型。但是别忽略了我们还有一个image/png类型,因为我们的剪贴板是可以直接复制文件的,所以我们常用的剪贴板类型就是Record<string, string | File>,例如此时复制这段文字在剪贴板中就是如下内容。
text/plain
例如此时复制这段文字在剪贴板中就是如下内容
text/html
<meta charset="utf-8"><strong style="...">例如此时复制这段文字</strong><em style="...">在剪贴板中就是如下内容</em>
那么我们执行粘贴操作的时候就很明显了,只需要从剪贴板里读取内容就可以。例如我们从语雀复制内容到飞书中时,在语雀复制的时候会将text/plain以及text/html写入剪贴板,在粘贴到飞书的时候就可以首先检查是否有text/html的key,如果有的话就可以读取出来,并且将其解析成为飞书自己的私有格式,就可以通过剪贴板来保持内容格式粘贴到飞书了。而如果没有text/html的话,就直接将text/plain的内容写到私有的JSON数据即可。
此外,我们还可以考虑到一个问题,在上边的例子中实际上我们是复制时需要将JSON转到HTML字符串,在粘贴时需要将HTML字符串转换为JSON,这都是需要进行序列化与反序列化的,是需要有性能消耗以及内容损失的,所以是不是能够减少这部分消耗。通常来说如果是在应用内直接直接粘贴的话,可以直接通过剪贴板的数据直接compose到当前的JSON即可,这样就可以更完整地保持内容以及减少对于HTML解析的消耗。例如在飞书中,会有docx/text的独立clipboard key以及data-lark-record-data作为独立JSON数据源。
那么至此我们已经了解到剪贴板的工作原理,紧接着我们就来聊一聊如何进行序列化的操作。说到复制我们可能通常会想到clipboard.js,如果需要兼容性比较高的话(IE)可以考虑,但是如果需要在现在浏览器中使用的话,则可以直接考虑使用HTML5规范的API完成,在浏览器中关于复制的API常用的有两种,分别是document.execCommand("copy")以及navigator.clipboard.write/writeText。
