【发布时间】:2021-06-04 10:31:33
【问题描述】:
我正处于开发插件的初始阶段,该插件允许用户将占位符元素插入 HTML 内容中,这些内容将在服务器端进行处理,并用于将一些简单的逻辑合并到生成的 PDF 文档中。为此,我尝试插入一个使用 Web 组件 API 定义的自定义元素。
class NSLoop extends HTMLElement {
constructor() {
super();
}
get source() {
return this.getAttribute('source');
}
get as() {
return this.getAttribute('as');
}
}
window.customElements.define('ns-loop', NSLoop);
loopediting.js的内容:
import Plugin from "@ckeditor/ckeditor5-core/src/plugin";
import Widget from "@ckeditor/ckeditor5-widget/src/widget";
import {viewToModelPositionOutsideModelElement} from "@ckeditor/ckeditor5-widget/src/utils";
import LoopCommand from "./loopcommand";
export default class LoopEditing extends Plugin {
static get requires() {
return [Widget];
}
constructor(editor) {
super(editor);
}
init() {
this._defineSchema();
this._defineConverters();
this.editor.commands.add('loop', new LoopCommand(this.editor));
this.editor.editing.mapper.on('viewToModelPosition', viewToModelPositionOutsideModelElement(this.editor.model, viewElement => viewElement.is('element', 'ns-loop')));
}
_defineSchema() {
const schema = this.editor.model.schema;
schema.register('loop', {
isBlock: false,
isLimit: false,
isObject: false,
isInline: false,
isSelectable: false,
isContent: false,
allowWhere: '$block',
allowAttributes: ['for', 'as'],
});
schema.extend( '$text', {
allowIn: 'loop'
} );
schema.extend( '$block', {
allowIn: 'loop'
} );
}
_defineConverters() {
const conversion = this.editor.conversion;
conversion.for('upcast').elementToElement({
view: {
name: 'ns-loop',
},
model: (viewElement, {write: modelWriter}) => {
const source = viewElement.getAttribute('for');
const as = viewElement.getAttribute('as');
return modelWriter.createElement('loop', {source: source, as: as});
}
});
conversion.for('editingDowncast').elementToElement({
model: 'loop',
view: (modelItem, {writer: viewWriter}) => {
const widgetElement = createLoopView(modelItem, viewWriter);
return widgetElement;
}
});
function createLoopView(modelItem, viewWriter) {
const source = modelItem.getAttribute('source');
const as = modelItem.getAttribute('as');
const loopElement = viewWriter.createContainerElement('ns-loop', {'for': source, 'as': as});
return loopElement;
}
}
}
此代码有效,因为<ns-loop> 元素已成功插入到编辑器内容中;但是,我无法编辑此元素的内容。任何键盘输入都插入到<p> 元素之前的<ns-loop> 元素中,并且一旦鼠标停止移动,任何文本选择都会消失。此外,只能将光标放在元素的开头。
如果我只是将“ns-loop”替换为“div”或“p”的标记名称,我可以在元素内输入而不会出现问题,所以我怀疑我在架构定义中遗漏了一些东西让 CKEditor 意识到这个元素是“允许”输入的,但是我不知道我可能错过了什么——据我所知,这就是我应该通过schema.extend() 调用实现的目标。
我在架构定义中尝试了无数种 allowedIn、allowedWhere、inheritAllFrom、isBlock、isLimit 等,但行为没有明显变化。
谁能提供任何见解?
编辑: 我刚刚注意到的一些附加信息 - 当光标位于 <ns-loop> 元素内时,标题/段落下拉菜单为空。这可能是相关的。
编辑 2: 我发现罪魁祸首正盯着我的脸。
this.editor.editing.mapper.on('viewToModelPosition', viewToModelPositionOutsideModelElement(this.editor.model, viewElement => viewElement.is('element', 'ns-loop')));
我是 CKE5 插件领域的新手,并且正在使用其他插件作为参考点,我想我从另一个插件中复制了该代码。删除该代码可以解决问题。
【问题讨论】:
标签: javascript ckeditor ckeditor5 ckeditor5-plugin