自定义元素Web 组件在由 CKEditor 5 插件插入时不接受键盘输入

问题描述

我正处于开发插件的初始阶段,该插件将允许用户将占位符元素插入到 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','ns-loop')));

我是 CKE5 插件间的新手,并使用其他插件作为参考点,我想我从另一个插件复制了该代码删除代码可以解决问题。

解决方法

正如第二次编辑中所指出的,罪魁祸首是代码,

this.editor.editing.mapper.on('viewToModelPosition',viewToModelPositionOutsideModelElement(this.editor.model,viewElement => viewElement.is('element','ns-loop')));

我显然是从我正在使用的另一个插件中复制的以供参考。删除此代码已解决了当前的问题。

我会接受这个答案并在 2 天计时器结束后关闭问题。