前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载导读CKEditor 4 的表格插件table在生成 HTML 时必须保证caption是table的第一个直接子元素、thead紧随其后这与 HTML 规范中表格内容模型的定义一致。本文以仓库内手动测试文档 tests/plugins/table/manual/tagsorder.md 为主线完整还原其测试步骤并结合对话框源码、DTD 定义与自动化测试深入讲解 CKEditor 4 是如何在表头 标题场景下保证元素顺序的帮助读者理解表格生成的底层逻辑并掌握用 Bender 手动测试回归该行为的方法。一、测试背景HTML 规范对表格子元素顺序的要求HTML 规范对table的直接子元素顺序有明确约束caption、colgroup、thead、tfoot、tbody依次排列。在 CKEditor 4 中这一约束被直接编码在 DTD文档类型定义中见 core/dtd.jstable: { caption: 1, colgroup: 1, thead: 1, tfoot: 1, tbody: 1, tr: 1 },该行表明table允许且仅允许包含上述子元素caption排在第一位。历史缺陷 ticket #12707#12707: Fixed: The order of table elements does not comply with the HTML specification.tagsorder.md这份手动测试文档就是为回归验证该修复而编写的。二、手动测试文档解读元数据与测试目的tagsorder.md开头是 Bender 手动测试的元数据标记定义了测试的适用版本、类型和插件依赖bender-tags: 4.5.8, bug, trac12707 bender-ui: collapsed bender-ckeditor-plugins: wysiwygarea,toolbar,table,sourceareabender-tags标记该测试从 CKEditor 4.5.8 起有效属于bug回归测试对应票据编号trac12707bender-ui: collapsedBender 手动测试模式下界面折叠展示bender-ckeditor-plugins指定运行环境加载wysiwygarea可见编辑区、toolbar工具栏、table被测插件、sourcearea源码视图用于检查生成的 HTML。对应的测试页面 tests/plugins/table/manual/tagsorder.html 内容极简——一个textarea ideditor1加一行CKEDITOR.replace( editor1 )即创建一个实例化后的编辑器供人工操作。三、测试步骤详解继承原文档操作流程原文档给出 6 个操作步骤全部在编辑器界面内完成最终通过源码视图验证生成的 HTML 结构点击工具栏上的Table表格按钮弹出表格插入对话框在Headers表头下拉框中选择Both两者皆有即行表头 列表头在Caption标题字段中输入文本foo点击Ok按钮确认此时编辑区应生成一张3 行 2 列的表格这是表格对话框的行、列默认值见下文源码分析点击Source源码工具栏按钮切换到源码视图查看生成的 HTML校验点 1caption元素必须是table元素的第一个直接子元素校验点 2caption元素包含文本foo校验点 3thead是table元素的第二个子元素。预期最终生成的 HTML 结构如下table captionfoo/caption thead tr th scopecol.../th th scopecol.../th /tr /thead tbody tr td.../td td.../td /tr tr td.../td td.../td /tr /tbody /table说明scopecol是 Both 表头模式下首行th的语义属性标记为列方向表头其赋值逻辑在源码中有专门处理详见下文。四、源码实现元素顺序是如何保证的4.1 对话框字段定义表格插入/属性对话框由 plugins/table/dialogs/table.js 定义其中与本测试直接相关的两个字段txtCaptionCaption 输入框table.js#L499-L540requiredContent: caption其commit回调负责把输入的文本写入captionselHeaders表头下拉框table.js#L319-L329四个选项分别为无、行row、列col、两者both本测试选择both。另外行数与列数输入框的默认值分别为3与2见 table.js#L289-L313这正是测试步骤 4 中3 行 2 列的来源。4.2 caption 被插入到表格最前面对话框确认onOk时先执行this.commitContent( data, table )table.js#L150其中txtCaption的commit逻辑table.js#L521-L540如下commit: function( data, table ) { if ( !this.isEnabled() ) return; var caption this.getValue(), captionElement table.getElementsByTag( caption ); if ( caption ) { if ( captionElement.count() 0 ) { captionElement captionElement.getItem( 0 ); captionElement.setHtml( ); } else { captionElement new CKEDITOR.dom.element( caption, editor.document ); table.append( captionElement, true ); } captionElement.append( new CKEDITOR.dom.text( caption, editor.document ) ); } else if ( captionElement.count() 0 ) { for ( var i captionElement.count() - 1; i 0; i-- ) captionElement.getItem( i ).remove(); } }关键点在table.append( captionElement, true )第二个参数toStart true表示插入到子节点列表的最前面。对应底层实现见 core/dom/element.jsappend: function( node, toStart ) { if ( typeof node string ) node this.getDocument().createElement( node ); if ( toStart ) this.$.insertBefore( node.$, this.$.firstChild ); else this.$.appendChild( node.$ ); return node; },即toStart为真时走insertBefore把 caption 放到 table 首个子节点的位置。由于 caption 提交发生在表体生成之前后续生成的tbody会排在 caption 之后从而保证 caption 是第一个直接子元素——对应校验点 1、2。4.3 thead 紧随 caption 之后表头处理逻辑位于 table.js#L170-L195当headers row || headers both且表格尚无thead时新建thead并insertBefore( tbody )随后把tbody首行的单元格renameNode( th )并设置scopecol// Should we make a thead? var headers info.selHeaders; if ( !table.$.tHead ( headers row || headers both ) ) { var thead table.getElementsByTag( thead ).getItem( 0 ); tbody table.getElementsByTag( tbody ).getItem( 0 ); var theRow tbody.getElementsByTag( tr ).getItem( 0 ); if ( !thead ) { thead new CKEDITOR.dom.element( thead ); thead.insertBefore( tbody ); } // Change TD to TH: for ( i 0; i theRow.getChildCount(); i ) { var th theRow.getChild( i ); if ( th.type CKEDITOR.NODE_ELEMENT !th.data( cke-bookmark ) ) { th.renameNode( th ); th.setAttribute( scope, col ); } } thead.append( theRow.remove() ); }thead被插在tbody之前而tbody又在 caption 之后最终顺序为caption → thead → tbody与 HTML 规范及校验点 3 完全一致。此外Both 模式下scope属性的细节处理也见 table.js#L228-L233首行单元格使用scopecol其余行首单元格使用scoperow相关行为另有独立的手动测试 tests/plugins/table/manual/scopeattribute.md 与 changescopeattribute.md 覆盖。4.4 内容过滤规则中的元素允许性plugins/table/plugin.js 在注册table命令时声明了allowedContentallowedContent: table{width,height,border-collapse}[align,border,cellpadding,cellspacing,summary]; caption tbody thead tfoot; th td tr[scope]; td{border*,background-color,vertical-align,width,height}[colspan,rowspan]; ...其中caption tbody thead tfoot;允许这些结构元素存在th td tr[scope];允许th/td/tr及scope属性。也就是说只有内容过滤规则放行插入对话框生成的caption、thead、th[scope]才会被编辑器保留——这是生成合法结构之外的另一道保障。五、自动化测试佐证除了手动测试仓库还提供了对应的自动化用例 tests/plugins/table/caption.js用 Bender 的editorBot直接驱动对话框覆盖四种表头配置下 caption 的位置test caption index in table without headers无表头test caption index in table with headers row行表头test caption index in table with headers col列表头test caption index in table with both headersBoth 表头每个用例都通过以下断言验证caption 是 table 的第一个子元素assert.areSame( table.getItem( 0 ).getChild( 0 ).getName(), caption, Caption element is first child of table. );其中both用例与本手动测试场景完全一致设置selHeaders both并填写 caption见 caption.js#L52-L63。手动测试与自动化测试互补自动化测试快速回归元素顺序手动测试则在真实编辑器中验证源码视图下生成的 HTML 是否符合规范。六、如何在本地运行该手动测试该测试属于 Bender 手动测试体系本仓库根目录的 bender.js、bender.ci.js、bender-runner.config.json 定义了运行环境。常规做法是在仓库根目录安装依赖并启动 Bender 服务器bender server run在浏览器中打开 Bender 测试页面进入tests/plugins/table/manual目录打开tagsorder.html按上文第三节的步骤逐一操作核对三个校验点是否全部通过。说明tagsorder.html通过CKEDITOR.replace( editor1 )实例化编辑器页面本身不携带额外配置插件集合由 Bender 元数据bender-ckeditor-plugins指定。七、总结tagsorder.md看似只是一份简短的验收清单实则承载了 CKEditor 4 对表格结构合规性的一次关键回归从 core/dtd.js 中table的内容模型定义到对话框commit中table.append( captionElement, true )的置顶插入再到thead.insertBefore( tbody )的顺序编排最终由 CHANGES.md 确认的 4.5.8 修复落地。理解这条从规范 → 源码 → 测试的链路有助于你在集成 CKEditor 4 时正确预期表格的 HTML 输出也能为后续自定义表格功能或编写类似回归测试提供范本。赞分享前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载相关推荐CKEditor 4 表格元素识别边界修复CKEDITOR.dom.range_getTableElement() 原理与手动测试指南CKEditor 4 表格元素识别边界修复CKEDITOR.dom.range _getTableElement 原理与手动测试指南 本文围绕 CKEdito前端UI组件CKEditor 4 Autolink 插件自定义正则配置实战从手动测试规范到源码级原理CKEditor 4 Autolink 插件自定义正则配置实战从手动测试规范到源码级原理 本文围绕 CKEditor 4 仓库中 Autolink 插件的手动前端UI组件CKEditor 4 justify 插件 useComputedState 配置实战从手动测试到源码原理CKEditor 4 justify 插件 useComputedState 配置实战从手动测试到源码原理 useComputedState 是 CKEdit前端UI组件上一篇AFNetworking 4.x 完整使用指南安装集成、核心 API 与源码级原理解析iOS/macOS/watchOS/tvOS下一篇解决Laravel订阅系统常见问题Soulbscription实用技巧与最佳实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考