资讯动态

CKEditor 4 pastefromword:IE 环境下 Word 列表粘贴回归(Trac 16826)复现、修复原理与验证机制

发布时间:2026/10/17 2:33:53 来源:尧图企业网站定制
前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载本文围绕 CKEditor 4 仓库中针对 Trac 16826 缺陷的回归测试文档展开在 IE 浏览器中从 Microsoft Word 粘贴多行列表时列表项li内部被错误地嵌套了段落p元素。读完后你将掌握该缺陷的完整复现步骤、pastefromword过滤链中针对 IE 嵌套段落的具体修复实现以及仓库中配套的 bender 回归测试与 fixture 组织方式。一、缺陷复现步骤原回归测试文档内容仓库中 tests/tickets/16826/ielists.md 是一份典型的 CKEditor 4 ticket 回归测试描述文档其 bender 标签声明了缺陷属性与所需插件bender-tags: bug, 4.7.0, trac16826, pastefromword bender-ui: collapsed bender-ckeditor-plugins: wysiwygarea, toolbar, undo, pastefromword, sourcearea, elementspath, list复现步骤原文如下使用 Microsoft Word 打开或创建一个包含列表的文档仓库提供的样例文档为 Ordered_list_multiple.docx这是一个多级有序列表1. this/2. is/3. a/a. multi/i. level/b. ordered/4. list。全选整个列表。将其粘贴进 CKEditor 实例。期望结果Expected列表项内部不包含段落元素List items doesnt have paragraphs in it。非期望结果Unexpectedli元素内存在段落Paragraphs are present inlielements。配套的测试页面 tests/tickets/16826/ielists.html 中有一个关键守卫if ( !CKEDITOR.env.ie ) { bender.ignore(); }也就是说该用例只在 IE 浏览器中执行——这正是缺陷只与 IE 的粘贴行为相关的原因。二、为什么只有 IE 会在li内嵌套p对比 fixture 目录下不同浏览器的原始粘贴数据即可看出差异。以 word2013 的 IE11 原始数据 为例其结构为ol stylelist-style-type: decimal; direction: ltr; li stylefont-style: normal; font-weight: normal; p style... mso-list: l0 level1 lfo1;This/p /li li style... p style... mso-list: l0 level1 lfo1;Is/p /li li style... p style... mso-list: l0 level1 lfo1;A/p ol stylelist-style-type: lower-alpha; li style...p style... mso-list: l0 level2 lfo1; ...Multi/p.../li /ol /li ... /ol每个li内都包着一层带mso-list: l0 levelN lfo1样式的p而同一 Word 版本下 Chrome/Firefox 的 fixture如 word2013/chrome.html中li直接包含内联内容没有这层段落包裹。源码注释也直接点明了这一点见 plugins/pastefromword/filter/default.js#L160-L162IE pastes nested paragraphs in list items, which is different from other browsers. (https://dev.ckeditor.com/ticket/16826)这带来两个具体问题一是语义上不干净的lip…/p/li结构二是 IE 把列表层级信息写在li内部p的mso-list样式上过滤器需要到嵌套段落中才能取到层级数据。三、过滤链中的 IE 专门修复修复逻辑位于 Word 粘贴过滤器的段落处理规则中见 plugins/pastefromword/filter/default.js#L146-L201 的p元素规则。处理流程分两支分支一该段落本身是一个列表项List.thisIsAListItem判定为真见 L484-L502执行 16826 的核心修复// IE pastes nested paragraphs in list items, which is different from other browsers. (https://dev.ckeditor.com/ticket/16826) // Theres a possibility that list item will contain multiple paragraphs, in that case we want // to split them with BR. tools.array.reduce( element.children, function( paragraphsReplaced, node ) { if ( node.name p ) { // If there were already paragraphs replaced, put a br before this paragraph, so that // its inline children are displayed in a next line. if ( paragraphsReplaced 0 ) { var br new CKEDITOR.htmlParser.element( br ); br.insertBefore( node ); } node.replaceWithChildren(); paragraphsReplaced 1; } return paragraphsReplaced; }, 0 );要点逐个检查列表项此处已被List.convertToFakeListItem转换为cke:li的伪列表项的子节点发现内嵌p时调用replaceWithChildren()将段落展开为其内联子节点消除li内的段落层如果一个列表项包含多个段落则从第二个段落起在其前插入br保证原有换行呈现不被丢失。分支二该段落不是列表项但其祖先ul/ol尚未携带层级信息L179-L189。注释写道In IE list level information is stored inpelements insidelielements因此从p的mso-list: l0 level2 lfo1样式中解析出level数字写入祖先列表容器的cke-list-level属性供后续createLists构建嵌套结构使用。此外ul/ol规则L262-L301还处理了 IE11 下列表跳级时ol被隐式包进li的边界情况给外层li打上list-style-type: none随后统一走List.dissolveList溶解。四、列表重建流水线修复所处位置理解上述修复需要看它在整条过滤流水线中的位置。过滤规则入口plug.rules中根节点规则先完成全部过滤再把所有伪列表项重建成真实列表树L72-L76root: function( element ) { element.filterChildren( filter ); CKEDITOR.plugins.pastefromword.lists.cleanup( List.createLists( element, editor ) ); }从源码结构看完整链路为Word 识别msoListsDetected通过正则mso-list:\s*l\d\slevel\d\slfo\d确认粘贴内容确属 WordL69避免把普通 HTML 列表误当 Word 列表处理溶解现有列表ul/ol规则调用 List.dissolveList按list-style-type为每个li计算符号cke-symbol与层级cke-list-level并把li改名为p打cke-dissolved标记伪列表项转换thisIsAListItem→convertToFakeListItemL513-L577元素改名为cke:li同时处理margin-left缩进校正16826 的嵌套段落剥离就发生在这一阶段之内层级信息解析List.getListItemInfo 从mso-list属性解析出列表id与level重建嵌套树List.createListsL865先将cke:li批量转回真实liconvertToRealListItems再按cke-list-level用容器栈生成ol li ol li之类的嵌套结构设置list-style-type、start、li[value]等清理临时属性List.cleanupL1051-L1067删除cke-list-level、cke-symbol、cke-dissolved等辅助属性。16826 的修复正是第 3 步中针对 IE 粘贴特征li内嵌p的归一化使 IE 的数据与 Chrome/Firefox 的扁平结构对齐后再进入统一的重建逻辑。五、期望输出对照与自动化回归fixture 目录 tests/plugins/pastefromword/generated/_fixtures/Ordered_list_multiple/ 按 Word 版本与浏览器组织数据word2007/、word2013/、word2016/各自存放原始粘贴 HTML 与expected_*.html期望输出根目录另有 expected.html 作为基线。修复后的目标输出是一个无段落嵌套的干净有序列表ol lithis/li liis/li lia ol stylelist-style-type:lower-alpha limulti ol stylelist-style-type:lower-roman lilevel/li /ol /li liordered/li /ol /li lilist/li /ol而 IE11 专属期望 expected_ie11.html 保留了 IE 粘贴的字体样式信息但同样验证了li内不再有p、且lower-alpha/lower-roman嵌套层级正确。自动化回归则由生成式测试套件驱动tests/plugins/pastefromword/generated/tickets6.js在 chrome/edge word2016 组合下将Ordered_list_multiple等 fixture 纳入测试集compareRawData: true做原始数据比对并注明ignoreAll: ( CKEDITOR.env.ie CKEDITOR.env.version 11 ) || bender.tools.env.mobile即 IE 场景交给人工/环境限定用例tests/plugins/pastefromword/generated/tickets7.js在pasteFromWord_heuristicsEdgeList false配置下验证No_heuristics/Ordered_list_multiple变体tests/plugins/pastefromword/generated/generic.js通用套件中同样启用Ordered_list_multiple与Ordered_list_multiple_edgy。结合 ielists.html 中仅 IE 生效的守卫形成了自动生成套件覆盖主流浏览器 独立 ticket 用例钉死 IE 行为的双层回归保障。六、运行与验证方式本仓库测试基于 bender 框架入口配置见 bender.js 与 bender-runner.config.json。验证该缺陷修复时在支持的环境中安装依赖并启动 bender runner以仓库根目录的package.json脚本与 bender 配置为准定位到tests/tickets/16826/对应用例ielists在 IE 环境或具备 IE 的 CI 矩阵中执行从 Word 打开样例Ordered_list_multiple.docx→ 全选列表 → 粘贴 → 检查源码视图中li内是否还有p交叉运行tests/plugins/pastefromword/generated/下的tickets6.js、tickets7.js、generic.js确认Ordered_list_multiple各变体在 word2007/2013/2016 × 多浏览器矩阵下均通过。适用前提与限制该用例依赖真实 IE 浏览器环境ielists.html在非 IE 环境会自动bender.ignore()fixture 的期望输出与具体 Word 版本强绑定目录中按word2007/word2013/word2016分列更换 Word 版本重新生成粘贴数据时需同步更新对应expected_*.html。七、小结要素位置回归测试描述与复现步骤tests/tickets/16826/ielists.mdIE 限定测试页tests/tickets/16826/ielists.html样例 Word 文档Ordered_list_multiple.docxIE 修复核心代码嵌套p剥离 br拆分plugins/pastefromword/filter/default.js#L160-L177IE 层级信息回写cke-list-levelplugins/pastefromword/filter/default.js#L179-L189列表重建与清理plugins/pastefromword/filter/default.js#L865、#L1051-L1067自动化回归套件tickets6.js、tickets7.js、generic.js16826 虽然只是一个列表项内不应出现段落的小缺陷但它暴露了跨浏览器粘贴 HTML 结构差异这一普遍问题pastefromword过滤器通过识别来源 → 溶解归一 → 伪列表项 → 重建嵌套树 → 清理临时属性的流水线把 IE 特有的嵌套段落归一化后汇入统一重建逻辑并以 fixture 期望文件 自动生成测试套件的方式把回归钉死在 CI 可复验的形态上。赞分享前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载相关推荐Respect Validation Extension 验证器实战指南PHP 文件扩展名校验原理、模板定制与测试用例解析Respect Validation Extension 验证器实战指南PHP 文件扩展名校验原理、模板定制与测试用例解析 本文是 Respect\Valid前端UI组件CKEditor 4 粘贴部分列表项失败的修复原理与手动回归测试指南CKEditor 4 粘贴部分列表项失败的修复原理与手动回归测试指南 导读 本文以 CKEditor 4 仓库中的手动回归测试 pastepartiallist前端UI组件CKEditor 4 从 Word 粘贴“特殊字符项目符号”无序列表崩溃877问题复现、修复原理与回归测试指南CKEditor 4 从 Word 粘贴“特殊字符项目符号”无序列表崩溃 877问题复现、修复原理与回归测试指南 本文围绕 CKEditor 4 仓库中前端UI组件上一篇Kener 状态页监控嵌入完全指南JavaScript 脚本与 iframe 两种方案的实战手册下一篇OpenOcta八爪鱼完全指南中国首个开源桌面级AI智能体双击安装30秒上手创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑