CKEditor5自定义插件:dataDowncast无法同时使用markerToData与markerToHighlight
解决CKEditor5同一标记同时生成start/end标签和高亮span的问题
问题原因
CKEditor5的转换系统中,针对同一模型标记(这里是my-highlight),在同一转换阶段(dataDowncast)只会触发第一个匹配的转换器。你同时注册markerToData和markerToHighlight时,后注册的不会生效,只会执行第一个注册的转换器,因此出现二选一的情况。
解决方案
不能直接依赖两个内置转换器,需要自定义复合转换器,手动构建包含start/end标签和高亮span的视图结构。具体步骤如下:
1. 移除原有内置转换器配置
删除这段冲突的代码:
editor.conversion.for('dataDowncast') .markerToHighlight(data_markerToHighlightConfig) .markerToData(data_markerToDataConfig);
2. 注册自定义downcast转换器
通过监听downcastDispatcher的convertMarker:my-highlight事件,手动生成需要的视图元素:
editor.conversion.for('dataDowncast').dispatcher.on('convertMarker:my-highlight', (evt, data, conversionApi) => { // 从标记名称提取name参数(比如"my-highlight:1"中的"1") const markerNameParts = data.marker.name.split(':'); const highlightName = markerNameParts[1] || ''; const viewWriter = conversionApi.writer; // 将模型范围转为视图范围 const range = conversionApi.mapper.toViewRange(data.marker.getRange()); // 创建所需视图元素 const startElement = viewWriter.createEmptyElement('my-highlight-start', { name: highlightName }); const endElement = viewWriter.createEmptyElement('my-highlight-end', { name: highlightName }); const highlightSpan = viewWriter.createContainerElement('span', { class: 'my-highlight' }); // 包裹高亮内容并插入首尾标签 viewWriter.wrap(range, highlightSpan); viewWriter.insert(viewWriter.createPositionBefore(highlightSpan), startElement); viewWriter.insert(viewWriter.createPositionAfter(highlightSpan), endElement); // 阻止默认转换器执行,避免冲突 evt.stop(); });
3. 验证效果
此时调用editor.getData()会生成你期望的输出:
X<my-highlight-start name="1"></my-highlight-start><span class="my-highlight">Y</span><my-highlight-end name="1"></my-highlight-end>Z
关键说明
- 手动监听
convertMarker事件可完全控制视图结构生成,避开内置转换器的互斥限制。 - 通过解析
data.marker.name获取标记参数,确保start/end标签的name属性准确对应。 - 使用
viewWriter的wrap和insert方法构建视图层级,同时保留标记范围信息,兼容重叠标记场景。
内容的提问来源于stack exchange,提问作者PeterB
相关产品推荐
相关产品推荐

