基于Chrome扩展的浏览器可信事件与网页离线PDF导出
Chrome
扩展是一种可以在浏览器中添加新功能和修改浏览器行为的软件程序,我们可以基于Manifest
规范的API
实现对于浏览器和Web
页面在一定程度上的修改,例如广告拦截、代理控制等。Chrome DevTools Protocol
则是Chrome
浏览器提供的一套与浏览器进行交互的API
,我们可以基于DevTools
协议控制Chromium
内核的浏览器进行各种操作,例如操作页面元素、模拟用户交互等。
描述
前段时间我们需要实现一个比较复杂的需求,经常做需求的同学都知道,很多功能并不是可以按步就班地实现的,在某些情况下例如要跨部门甚至无法联系合作的情况下,单方面跨系统完成一些事情就可能需要动用不同寻常的方法。当然具体需求的内容不是很方便表达,所以在这里我们就替代为其他方面的需求展开文章的叙述,虽然实现的目的不一样,但是最终想要表达的技术方案是类似的。
因此在这里假设我们的背景变成了另一个故事,前段时间语雀进行了商业化,对于用户文章的数量和分享都做了一些限制,那么此时我们可能希望将现在已经写过的文档内容抽离出来,将其放在GitHub
或者其他软件中作备份或分享等。那么此时问题来了,熟悉富文本的同学都知道,我们在语雀上存储的文档都是JSON
文件而不是MarkDown
等,会存在固定的私有格式,因此我们可能需要对其先进行一遍解析,而调用语雀的OpenAPI
所需要的Personal Token
是需要超级会员的,因此我们可能只能走比较常用的Cookie
以及私有格式的解析方案,或者自动化操作Puppeteer
模拟导出文档也是可行的。
那么有没有更加通用的方案可以参考,熟悉富文本的同学还知道,由于富文本需要实现DOM
与选区MODEL
的映射,因此生成的DOM
结构通常会比较复杂,而当我们从文档中复制内容到剪贴板时,我们会希望这个结构是更规范化的,以便粘贴到其他平台例如飞书、Word
等时会有更好的解析。因此我们便可以借助这一点来获取更加通用的方案,毕竟通过HTML
解析成MarkDown
等格式社区有很多完善的方法而不需要我们自行解析了,此外由于我们是通过HTML
来描述内容,对于文档的内容完整性保持的会更好一些,自行解析的情况下可能会由于复杂的嵌套内容需要不断完善解析程序。
当然在这里只是平替了一下需求,前边我们也提到了背景是假设出来的,而由这个背景则延伸出了我们文章要聊的解决方案,如果真的是针对于语雀的这个迁移问题,在批量处理内容的情况下还是自行解析JSON
会更方便一些。那么我们可以继续沿着提取HTML
内容的思路处理数据,首先我们需要考虑如何获取这个HTML
内容,最简单的方案就是我们通过读取Node.innerHTML
属性来获取DOM
结构,那么问题来了,在语雀当中有大量的ne
开头的标签,以及大量的ne
属性值来表达样式,以简单的文本与加粗为例,其HTML
内容是这样的,其实语雀还算比较简单的结构,如果是飞书的表达则更加复杂。
<!-- 语雀 -->
<ne-p id="u5aec73be" data-lake-id="u5aec73be">
<ne-text id="u1e4a00ce">123</ne-text>
<ne-text id="ucc026ff4" ne-bold="true">123</ne-text>
<span class="ne-viewer-b-filler" ne-filler="block"><br></span>
</ne-p>
<!-- 飞书 -->
<div class="block docx-text-block" data-block-type="text" data-block-id="2" data-record-id="doxcns7E9SHaX2Xft1XweL0Mqwth">
<div class="text-block-wrapper">
<div class="text-block">
<div class="zone-container text-editor non-empty" data-zone-id="2" data-zone-container="*" data-slate-editor="true" contenteditable="true">
<div class="ace-line" data-node="true" dir="auto">
<span data-string="true" class=" author-0087753711195911211" data-leaf="true">123</span>
<span data-string="true" style="font-weight:bold;" class=" author-0087753711195911211" data-leaf="true">123</span>
<span data-string="true" data-enter="true" data-leaf="true">​</span>
</div>
</div>
</div>
</div>
</div>
可以看出来,我们取得这样的HTML
解析起来相对成本还是比较高的,而如果我们以上述的剪贴板思路,也就是富文本通常会对复制的内容作Normalize
处理,那么我们可以通过剪贴板事件来获取这个规范化的内容,然后再进行处理HTML
,这里的HTML
内容就会规范很多,那么同样也会便于我们处理数据。在这里实际上通常还会有私有类型的数据,这里就是我们选中部分取得的渲染Fragment
,通常是用来在编辑器内部粘贴处理数据无损化还原使用的,如果对于数据格式非常熟悉的话解析这部分内容也是可以的,只是并没有比较高的通用性。
<!-- 语雀 -->
<div class="lake-content" typography="classic">
<p id="u5aec73be" class="ne-p" style