
前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载导读本文以 continoustyping.md 这一手动测试用例为入口深入剖析 CKEditor 4 的Auto Linkautolink插件在“URL 空格 普通文本”连续输入场景下如何做到只将链接部分转换为a锚点、同时保留其余文本为纯文本。文章将完整继承该用例的步骤与预期/非预期判定标准并结合 autolink 插件源码、textmatch 插件 与 link 插件 展开底层实现原理最后给出autolink_commitKeystrokes、autolink_urlRegex、autolink_emailRegex三个配置项的完整说明以及同目录手动测试矩阵与自动化测试佐证帮助读者既能复现验证也能读懂实现。一、用例原文与验证目标continoustyping.md是 autolink 插件manual/目录下的一份手动测试manual test规格文档全文以 Bender 测试元数据 操作步骤 期望/非期望结果的形式组织bender-ui: collapsed bender-tags: 4.11.0, feature, 1815 bender-ckeditor-plugins: clipboard, toolbar, wysiwygarea, autolink 1. Focus the editor. 1. Type http://example.com example. **Expected** * Typed link text is turned into an anchor. The rest of the text i.e. example is preserved as a plain text. **Unexpected** * The whole typed text is turned into an anchor.元数据逐项解读bender-ui: collapsed手动测试页面以折叠 UI 模式呈现方便在浏览器中直接操作编辑器bender-tags: 4.11.0, feature, 1815该场景对应4.11.0 版本引入的 typing link completion 功能issue 编号为 1815。对照 CHANGES.md 第 794 行可确认#1815 “The Auto Link plugin supports typing link completion” 是 4.11.0 的新特性bender-ckeditor-plugins: clipboard, toolbar, wysiwygarea, autolink测试页面加载的最小插件集合。autolink 插件自身的requires: clipboard,textmatch,link见 plugin.js会自动补齐依赖。配套的 continoustyping.html 只是创建一个标准编辑器实例先调用bender.tools.ignoreUnsupportedEnvironment( autolink )在不支持 autolink 的环境中跳过用例再CKEDITOR.replace( editor )完成实例化。整个用例的核心验证点只有一个连续输入http://example.com example中间以空格分隔后只有http://example.com被转换为锚点example必须保持为普通文本如果整段文本都被包进a即视为回归缺陷。二、为什么“连续输入”是链接自动化的关键场景从功能边界看autolink 需要同时支持两种输入路径粘贴paste路径从剪贴板粘贴一段 URL / 邮箱paste事件处理器将其整体转为链接键入typing路径用户像写普通文本一样直接敲入 URL在按下提交键默认Enter或Space的瞬间完成链接化。continoustyping验证的是第 2 条路径中最容易出错的组合URL 之后紧跟空格和普通文本。因为空格本身既是分隔符又是默认的提交键keyCode 32用户输入http://example.com example时第一个空格按下后 URL 应当被立即“提交”为链接而后面的example属于链接之外的独立文本。如果实现简单粗暴地“把光标左侧整段文本都当作候选链接”就会出现用例所禁止的Unexpected结果——http://example.com example整段被包进锚点产生a href...http://example.com example/a这种错误输出。因此这个用例本质上是在验证链接候选的匹配边界必须精确到“最后一个空白分隔的 token”而不是光标前的整段文本。三、源码级实现原理下面沿着一次真实的连续输入过程逐层拆解 plugins/autolink/plugin.js 的实现。3.1 提交键commit keystroke监听插件在init中注册了key事件监听plugin.jseditor.on( key, function( evt ) { if ( editor.mode ! wysiwyg || CKEDITOR.tools.indexOf( editor.config.autolink_commitKeystrokes, evt.data.keyCode ) -1 ) { return; } var matched CKEDITOR.plugins.textMatch.match( editor.getSelection().getRanges()[ 0 ], matchCallback ); if ( matched ) { insertLink( matched ); } } );要点只有editor.mode wysiwyg时才参与这也是 #2756 修复的一部分避免在源码模式下手动测试 sourcemode.md 中描述的报错按下键的 keyCode 必须命中config.autolink_commitKeystrokes数组否则直接忽略匹配工作委托给textmatch 插件的CKEDITOR.plugins.textMatch.match()它以当前光标折叠 range为起点扫描相邻文本节点生成“完整文本 光标偏移”再交给matchCallback判断。3.2 matchCallback按空白切分只取最后一个词连续输入能“只链接 URL、保留后续文本”的关键就在matchCallbackplugin.jsfunction matchCallback( text, offset ) { var parts text.slice( 0, offset ) .split( /\s/ ), query parts[ parts.length - 1 ]; if ( !query ) { return null; } if ( !matchLink( query ) ) { return null; } return { start: text.lastIndexOf( query ), end: offset }; }流程解读取光标之前的文本text.slice( 0, offset )按/\s/任意空白切分取最后一个分段query作为候选链接用matchLink( query )同时匹配 URL 正则与邮箱正则plugin.js命中则返回{ start, end }区间由 textmatch 换算回 DOM range。以用例输入http://example.com example为例当用户敲下第一个空格keyCode 32恰为提交键时光标前文本是http://example.com切分后最后一个 token 正是http://example.com匹配 URL 正则成功 → 只把这个区间转成链接空格本身作为提交键被消费随后敲入的example不再触发匹配后续字符键入时光标前的最后一个 token 是example不匹配任何正则自然保持纯文本。这也解释了为什么连续输入两个 URL同样成立手动测试 fillingcharsequence.md 要求输入http://example.com example http://example.com后“Links are turned into anchors. Typed text structure is preserved.”即两个 URL 各自被独立匹配并转链接中间的example与整体结构不被破坏。同时 textmatch 的match()在匹配前会移除浏览器插入的FILLING_CHAR_SEQUENCE见 textmatch/plugin.js对应 #2038保证查询文本干净避免“ehttp://example.com”这种结构被错误拼接fillingcharsequence.md 的 Unexpected 项。3.3 insertLink防嵌套、插 HTML、移光标命中后进入insertLinkplugin.jsfunction insertLink( match ) { var selection editor.getSelection(); // We dont want to insert a link if selection is already inside another link. if ( selection.getRanges()[ 0 ].startContainer.getAscendant( a, true ) ) { return; } selection.selectRanges( [ match.range ] ); editor.insertHtml( getHtmlToInsert( match.text ), text ); if ( !CKEDITOR.env.webkit ) { // Make sure that link cannot be modified right after insertion // by moving selection at the end of inserted node. var insertionRange selection.getRanges()[ 0 ], newRange editor.createRange(); newRange.setStartAfter( insertionRange.startContainer ); selection.selectRanges( [ newRange ] ); } }三个值得注意的实现细节防嵌套若光标起点位于某个a内部getAscendant( a, true )命中直接放弃插入——避免在已有链接里再生成链接插入方式先选中匹配区间再以text类型插入getHtmlToInsert()生成的 HTMLWebkit 例外非 Webkit 浏览器会把光标移动到新插入节点的末尾防止用户紧接着修改链接Webkit 则跳过这一步。这与自动化用例 typing.js 中test typing after autolinked text对 Webkit 使用assert.ignore()的处理typing.js完全对应。3.4 链接生成与 link 插件协同getHtmlToInsertplugin.js负责把匹配文本变成合法的a元素function getHtmlToInsert( text ) { // URL will be encoded later on with link.setAttribute method. Avoid // double encoding of special characters (#4858). text CKEDITOR.tools.htmlDecodeAttr( text ); var link new CKEDITOR.dom.element( a ), value text.replace( //g, %22 ); value value.match( editor.config.autolink_urlRegex ) ? value : mailto: value; link.setText( text ); link.setAttribute( href, value ); // (#1824) var linkData CKEDITOR.plugins.link.parseLinkAttributes( editor, link ), attributes CKEDITOR.plugins.link.getLinkAttributes( editor, linkData ); if ( !CKEDITOR.tools.isEmpty( attributes.set ) ) { link.setAttributes( attributes.set ); } if ( attributes.removed.length ) { link.removeAttributes( attributes.removed ); } link.removeAttribute( data-cke-saved-href ); return link.getOuterHtml(); }实现要点协议判定命中autolink_urlRegex的按 URL 处理否则一律加mailto:前缀邮箱场景见 mail.md对应 4.10.0 的 #1761 特性双引号编码replace( //g, %22 )对应 #13419 的修复URL 中的双引号需编码CHANGES.md 第 1498 行防双重编码先用CKEDITOR.tools.htmlDecodeAttr解码避免被二次转义成amp;amp;这正是 #4858 修复CHANGES.md 第 350 行手动测试 encoding.md 验证了“Editor 中原样、源码区单层amp;编码”的预期与 link 插件协同autolink 依赖 link 插件requires: clipboard,textmatch,link通过parseLinkAttributes/getLinkAttributes见 link/plugin.js 与 L626 附近的实现复用 link 插件的属性处理管线保证生成的链接在双击打开 Link 对话框时类型正确URL/E-mail并清理data-cke-saved-href。手动测试 link.md#18244.16.0专门验证工具栏会出现 link 插件的按钮。四、三个核心配置项continoustyping场景用到的全部行为都由以下三个配置项驱动它们在 plugin.js 末尾以默认值形式注册到CKEDITOR.config。4.1autolink_commitKeystrokes提交键数组默认值为[ 13, 32 ]即Enter与Spaceplugin.js// 默认配置13 Enter32 Space config.autolink_commitKeystrokes [ 13, 32 ];传入单个数字或数字数组均可设为空数组[]可完全禁用键入时的自动链接仅保留粘贴路径可自定义为任意键码例如方向键。自动化测试 typing.js 用 ArrowLeft/Up/Right/Down37/38/39/40验证自定义提交键同样生效手动测试 typing.md 要求分别用Enter与Space提交并双击生成的链接确认 Link Type 为URL/E-mail同时验证 Undo 分两步回退先撤销链接、再撤销键入文本。4.2autolink_urlRegexURL 匹配正则plugin.jsconfig.autolink_urlRegex /^(https?|ftp):\/\/(-\.)?([^\s\/?\.#]\.?)(\/[^\s]*)?[^\s\.,]$/i;默认只识别http://、https://、ftp://协议的地址域名部分支持连字符http://a.b-c.de这类用例对应 #14769 修复CHANGES.md 第 1175 行末尾的[^\s\.,]$保证了 URL 后跟句点/逗号/空格时不会吞掉标点该配置从 4.14.1 起可通过编辑器实例配置自定义#3156手动测试 customregex.md 与 autolink.js 中的optionalParameters用例配置autolink_urlRegex: /^url:xxx.xxx$/、autolink_emailRegex: /^mail:xxx$/验证了自定义正则的生效与不匹配时保持纯文本。4.3autolink_emailRegex邮箱匹配正则plugin.jsconfig.autolink_emailRegex /^[a-zA-Z0-9.!#$%*\/?^_{|}~-]a-zA-Z0-9?(?:\.a-zA-Z0-9?)*$/;采用 HTML 规范中 email state 的字符集命中后生成mailto:链接支持通过config.emailProtectionencode或mt(NAME,DOMAIN,SUBJECT,BODY)输出混淆/加密形式的mailto:链接——autolink.js 与 typing.js 分别验证了粘贴与键入两条路径下的受保护邮箱链接。说明上述默认正则均在 4.11.0 起提供配置入口更早版本如 4.10.0 的 #1761 邮箱支持使用内置正则无法通过配置覆盖这一限制在 #3156 中才被解除。五、同目录手动测试矩阵tests/plugins/autolink/manual/下的用例共同构成 autolink 的功能验证矩阵与continoustyping互补用例文件版本/标签验证主题autolink.md4.7.0, bug, trac14769粘贴各类 URL含连字符域名、锚点、查询串自动转链接mail.md4.10.0, feature, 1761粘贴邮箱自动转mailto:链接typing.md4.11.0, feature, 1815键入后按 Enter/Space 提交、链接类型、两步撤销continoustyping.md4.11.0, feature, 1815连续输入“URL 空格 文本”仅 URL 转链接本文主题fillingcharsequence.md4.11.0, feature, 1815多个链接与文本交错键入文本结构不被破坏sourcemode.md4.11.3, bug, 2756源码模式下按 Enter 不抛错customregex.md4.14.1, bug, 3156自定义 URL 正则生效link.md4.16.0, bug, 1824工具栏出现 link 插件按钮依赖加载encoding.md4.17.0, bug, 4858字符不被双重编码六、自动化测试佐证除手动测试外仓库还提供两套自动化测试直接覆盖continoustyping的底层逻辑typing.js模拟键入提交。test press commit keystroke to finish link completion用 13Enter和 32Space分别提交http://example.com^与mailexample.com^^表示光标位置断言结果为pa hrefhttp://example.comhttp://example.com/a/ptest link completion with invalid commit keystroke验证非提交键如 93不会触发链接化test typing after autolinked text验证链接插入后继续输入文本得到a ...http://example.com/anbsp;test的结构autolink.js覆盖粘贴路径与配置项包括“URL/邮箱后跟文本不整体转链接”test URL link with text after、test mail link with text after、含 HTML 标签的文本不转链接、内部粘贴DATA_TRANSFER_INTERNAL不转链接、自定义正则、emailProtection以及 link 插件依赖test link plugin is loaded等与 plugin.js 的 paste 处理器跳过内部传输、跳过含的片段一一对应。七、如何运行这些手动测试手动测试依赖仓库的 Bender 测试框架运行测试配置见仓库根目录 bender.jstests分组中的Plugins组basePathtests/paths 含plugins/**会收录tests/plugins/autolink/manual/下的用例框架为yui并启用了 coverage 与 ckeditor 测试插件runner 配置见 bender-runner.config.jsonbender 服务端口 9001、runner 端口 9002Linux 默认浏览器为 Chrome/FirefoxmacOS 为 Safari运行方式按 package.json 的devDependencies安装benderjs系列依赖后启动 Bender 服务并在浏览器中打开对应手动测试页面即可按用例文档中的步骤逐条操作验证。bender-ui: collapsed会折叠测试 UI让操作聚焦在编辑器本体。八、常见坑与注意事项浏览器前提autolink 通过isSupportedEnvironment()plugin.js判定!CKEDITOR.env.ie || CKEDITOR.env.edge即经典 IE 不支持#2208IE 原生行为与插件冲突CHANGES.md 第 441 行Edge 可用。手动/自动化用例均通过bender.tools.ignoreUnsupportedEnvironment( autolink )在不支持环境中跳过空格的双重身份Space 既是分隔符又是提交键。输入 URL 后立刻按空格链接在空格键事件中被提交若希望键入时完全不自动链接将autolink_commitKeystrokes设为[]即可粘贴路径不受影响链接内部继续键入insertLink的getAscendant( a, true )检查保证已处于链接内时不重复嵌套非 Webkit 下插入后光标被移到链接末尾避免用户无意中改坏链接撤销粒度按 typing.md 的预期Undo 需分两步——先撤销链接、再撤销键入文本两步顺序不可颠倒编码陷阱粘贴含的 URL 时若发现源码区出现amp;amp;双重编码即为 #4858 的回归表现可对照 encoding.md 与 autolink.js 验证修复是否生效。小结continoustyping.md表面上是三行步骤的手动测试背后却锁定了 autolink 插件最核心的边界行为以空白为界、按最后一个 token 精确匹配、以提交键为触发时机。通过matchCallback的切分逻辑与autolink_commitKeystrokes的键码配置CKEditor 4 实现了“URL 立即转链接、后续文本安然无恙”的连续输入体验。读者在集成或排查 autolink 问题时可优先对照本文第五节的手动测试矩阵定位功能维度再进入 plugins/autolink/plugin.js 与对应自动化测试核实实现细节。赞分享前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载相关推荐CKEditor 4 Auto Link 插件连续输入场景下的链接自动补全与 Filling Character Sequence 机制解析CKEditor 4 Auto Link 插件连续输入场景下的链接自动补全与 Filling Character Sequence 机制解析 导读 本文围绕前端UI组件番茄小说下载器使用指南10分钟免费把整本小说离线保存到本地番茄小说下载器使用指南10分钟免费把整本小说离线保存到本地 你以为把一整本番茄小说存下来得自己写爬虫、懂网络请求其实不用。 番茄小说下载器 全程复制粘贴命前端UI组件CKEditor 4 extraPlugins 配置深入解析从手动测试用例到插件加载机制CKEditor 4 extraPlugins 配置深入解析从手动测试用例到插件加载机制 本文以 CKEditor 4 仓库中的手动测试用例 tests/co前端UI组件上一篇mobx-state-tree 快照处理器详解ISnapshotProcessor 接口与 types.snapshotProcessor 实战指南下一篇OpenCore Legacy Patcher终极指南让老款Mac重获新生创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考