wangEditor 5 富文本编辑器质量保障指南:300+ 测试用例与多浏览器兼容实现拆解
wangEditor 5 富文本编辑器质量保障指南:300+ 测试用例与多浏览器兼容实现拆解
【免费下载链接】wangEditorwangEditor, open-source Web rich text editor 开源 Web 富文本编辑器项目地址: https://gitcode.com/gh_mirrors/wa/wangEditor
wangEditor 是一款开源 Web 富文本编辑器,支持 JS、Vue、React 集成。仓库当前@wangeditor/editor主包版本为 5.1.23,整体采用 lerna + yarn workspaces 管理 8 个包。对富文本编辑器来说,真正难写的部分往往不在工具栏,而在于不同浏览器、不同输入法下的输入行为差异。这篇文章基于仓库真实代码路径,讲清楚三件事:兼容层是如何吸收浏览器差异的、300+ 条测试用例如何覆盖这些行为、以及如何在本地跑起来复现和定位问题。
🧩 项目结构:8 个包组成的 lerna monorepo
wangEditor 5 的packages/目录把编辑器拆成职责清晰的包:
| 包 | 路径 | 职责 |
|---|---|---|
| core | packages/core/ | 核心能力:slate 数据模型 + snabbdom 渲染、编辑区事件处理、菜单框架、HTML 解析与生成 |
| editor | packages/editor/ | 主入口,createEditor/createToolbar,注册默认菜单与配置 |
| basic-modules | packages/basic-modules/ | 标题、引用、代码块、颜色、图片、链接、缩进、待办、撤销重做等基础模块 |
| list-module | packages/list-module/ | 有序列表 / 无序列表 |
| table-module | packages/table-module/ | 表格及增删行列操作 |
| code-highlight | packages/code-highlight/ | 代码块语法高亮装饰 |
| upload-image-module | packages/upload-image-module/ | 图片上传 |
| video-module | packages/video-module/ | 视频插入与上传 |
本地跑起来的流程在 docs/dev.md 中有说明:yarn bootstrap安装依赖,yarn dev打包全部模块,然后进入packages/editor执行yarn example,浏览器打开http://localhost:8881/examples/即可看到效果(注意:改完代码重新打包后要强制刷新浏览器)。
🔍 兼容层设计:从 UA 检测到处方药式处理
集中式浏览器能力检测
所有"这个浏览器能不能做某事"的判断都收敛在 packages/core/src/utils/ua.ts 中,导出一组布尔常量:
// packages/core/src/utils/ua.ts(节选) export const IS_IOS = typeof globalThis.navigator !== 'undefined' && typeof globalThis.window !== 'undefined' && /iPad|iPhone|iPod/.test(navigator.userAgent) && !globalThis.window.MSStream // Firefox / Edge 旧版不支持 beforeinput 事件, // Chrome 75 及以下对 beforeinput 支持不完整 export const HAS_BEFORE_INPUT_SUPPORT = !IS_CHROME_LEGACY && !IS_EDGE_LEGACY && typeof globalThis !== 'undefined' && globalThis.InputEvent && typeof globalThis.InputEvent.prototype.getTargetRanges === 'function'同一个文件里还有IS_SAFARI、IS_FIREFOX、IS_CHROME、IS_QQBROWSER等常量。把检测集中在一处的好处是:后续任何浏览器差异处理都引用这些常量,而不是散落的 UA 字符串匹配。
事件处理层的 COMPAT 分支
核心编辑区的事件处理器位于 packages/core/src/text-area/event-handlers/,每一处为特定浏览器"开的小灶"都带有COMPAT:注释,可以直接全文检索定位。几个典型例子:
| 文件 | 处理的浏览器差异 |
|---|---|
| focus.ts | Firefox 下焦点可能落入嵌套的可编辑元素,导致键盘导航异常,需要强制把焦点拉回编辑器根节点 |
| blur.ts | Safari 在 contenteditable 失焦后不总是清除选区,需要手动removeAllRanges() |
| syncSelection.ts | Firefox 中创建 range 后还必须 focus 元素;表格前后光标位置需要特殊重置,避免选区"贴"在 table 上 |
| composition.ts | Chrome/Firefox 拼音输入会暴露多余 text 节点;Safari/Firefox 在链接后输入会造成不可逆的 DOM 结构变化,用setNewKey强刷整行 |
输入法(IME)的兼容逻辑集中在composition.ts:composition 开始时记录当前 text 内容,composition 结束时统一通过 slate 的insertText落库,顺带完成maxLength对拼音输入的长度校验;如果拼音输入跨越了 DOM 文本节点(对应 issue wangEditor-v5#47),还会把起始节点还原,保证选区不错位。
输入与粘贴的降级链路
输入主链路是 beforeInput.ts:先preventDefault()劫持全部富文本输入,再按inputType分派到Editor的各种原子操作。对不支持 beforeInput 的浏览器(由HAS_BEFORE_INPUT_SUPPORT判定),直接跳过该处理器,退回 keypress/keydown 路径处理。
粘贴链路在 paste.ts 中,逻辑很短:
// 先给用户配置钩子拦截机会 const { customPaste } = editor.getConfig() if (customPaste) { const res = customPaste(editor, event) if (res === false) return // 自行实现粘贴 } // 支持 beforeInput 且非纯文本粘贴(html、图片等)时,交给 beforeInput 处理 if (HAS_BEFORE_INPUT_SUPPORT && !isPlainTextOnlyPaste(event)) returncustomPaste是暴露给使用者的配置项(定义见 packages/core/src/config/interface.ts),返回false即可完全接管粘贴行为,做内容净化或格式转换都从这里入手。
▶️ 质量保障:Jest 单元测试 + Cypress E2E 两层验证
测试体系在 docs/test.md 中有完整说明,当前仓库实际包含 133 个测试文件、300+ 条it()用例:
- 单元测试(Jest):从底层 API 角度验证功能,各包的
__tests__/目录按模块组织(如basic-modules/__tests__/header/、table-module/__tests__/menu/),覆盖 parse-html、render-elem、elem-to-html、menu 等维度。运行命令:yarn run test,带覆盖率用yarn run test-c。 - E2E 测试(Cypress):针对编辑器这类强交互产品做集成验证。用例集中在 cypress/integration/,现有 editor.spec.ts 访问 examples 页面、点击创建按钮后,断言工具栏和编辑区 DOM 属性正确生成。开发模式运行
yarn e2e:dev(会先起 example 服务再打开 Cypress UI),纯跑用例用yarn e2e。
🛠 本地排障:用 examples 页面复现问题
packages/editor/examples/ 下有一组独立页面,每个页面聚焦一个场景,适合按症状对号入座:default-mode.html(默认完整形态)、huge-doc.html(大文档性能)、shadow-dom.html、theme.html、i18n.html、maxlength.html、multi-editors.html、parse-html.html、upload-image.html等。定位某个浏览器下的输入或粘贴异常时,先在对应 example 页面复现,再对照上一节的事件处理器文件断点排查,比直接在业务项目里调试高效得多。
两个可操作的下一步:
- 本地先跑
yarn run test和yarn e2e确认基线全绿,再开始改代码,避免把历史问题当成自己的问题。 - 遇到具体浏览器行为异常时,先
grep -r "COMPAT" packages/core/src确认是否已有针对性处理,未覆盖的场景可按 docs/test.md 的目录规范补充测试用例;想深入参与开发可参考 docs/join.md。
【免费下载链接】wangEditorwangEditor, open-source Web rich text editor 开源 Web 富文本编辑器项目地址: https://gitcode.com/gh_mirrors/wa/wangEditor
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考