如何保留CKEditor5中图片元素的原有class属性?当前其被移至包裹span
解决CKEditor5中inline图片class属性被转移到外层span的问题
背景
用CKEditor5非侵入式替换自研编辑器,要求不修改原有编辑内容及类定义,保留WYSIWYG功能。基于django_ckeditor_5构建了自定义CKEditor5,已集成ckeditor5-inspector、自定义插件和CSS,基础功能正常。
问题现象
加载以下HTML到ClassicEditor时:
<p>Text with inline image: <img class="someclass" src="/media/uploads/some.jpeg"></p>
编辑器视图DOM中,<img>的someclass被移到了外层包裹的<span>上:
... <p>Text with an inline image: <span class="image-inline ck-widget someclass ck-widget_with-resizer" contenteditable="false"> <img src="/media/uploads/some.jpeg"> <div class="ck ck-reset_all ck-widget__resizer ck-hidden"> <div ...></div></span></p> ...
导致原有样式表无法正常调整图片尺寸。手动给<img>加回class后,样式和编辑工具恢复正常;切换源代码视图再返回,<img>的class也能保留。
已启用GeneralHtmlSupport插件,且编写了自定义Extend插件扩展imageInline模型:
export default class Extend extends Plugin { static get pluginName() { return 'Extend'; } #updateSchema() { const schema = this.editor.model.schema; schema.extend('imageInline', { allowAttributes: ['class'] }); } init() { const editor = this.editor; this.#updateSchema(); } }
解决方案
核心是调整CKEditor5的数据视图转换规则——你已经允许模型存储class属性,但需要确保视图渲染时将class绑定到<img>而非外层<span>。
1. 修改自定义Extend插件,添加视图转换器
更新插件代码,补充模型与视图之间的属性映射逻辑:
export default class Extend extends Plugin { static get pluginName() { return 'Extend'; } #updateSchema() { const schema = this.editor.model.schema; schema.extend('imageInline', { allowAttributes: ['class'] }); } #updateConverters() { const editor = this.editor; const conversion = editor.conversion; // 向下转换:模型imageInline的class属性映射到视图<img> conversion.for('downcast').add(dispatcher => { dispatcher.on('attribute:class:imageInline', (evt, data, conversionApi) => { if (!conversionApi.consumable.consume(data.item, evt.name)) return; const viewWriter = conversionApi.writer; const figureElement = conversionApi.mapper.toViewElement(data.item); const imgElement = figureElement.getChild(0); if (imgElement) { data.attributeNewValue ? viewWriter.setAttribute('class', data.attributeNewValue, imgElement) : viewWriter.removeAttribute('class', imgElement); } }); }); // 向上转换:视图<img>的class属性读取到模型imageInline conversion.for('upcast').add(dispatcher => { dispatcher.on('element:img', (evt, data, conversionApi) => { const viewItem = data.viewItem; const modelItem = data.modelItem; if (!modelItem || !conversionApi.schema.checkAttribute(modelItem, 'class')) return; const classAttr = viewItem.getAttribute('class'); if (classAttr) { conversionApi.writer.setAttribute('class', classAttr, modelItem); } }); }); } init() { const editor = this.editor; this.#updateSchema(); this.#updateConverters(); } }
2. 确认GeneralHtmlSupport配置
在CKEditor初始化配置中,明确允许<img>的class属性:
ClassicEditor.create(document.querySelector('#editor'), { // 其他配置项... htmlSupport: { allow: [ { name: 'img', attributes: ['class', 'src'] } ] }, plugins: [ // 已加载的其他插件... Extend, GeneralHtmlSupport ] });
3. 验证效果
重新加载编辑器后,带class的<img>会将class保留在自身元素上,外层<span>不会继承该class,原有样式表即可正常作用于图片,实现WYSIWYG的预期效果。
内容的提问来源于stack exchange,提问作者zoltan
相关产品推荐
相关产品推荐

