2

在我尝试在 CKEditor5 中创建自定义插件后,我收到以下错误(“model-nodelist-offset-out-of-bounds”)。该插件采用三个用户输入值并创建一系列具有三个文本节点的嵌套元素。我的自定义向下转换功能包含...

    const testimonial = data.item;

    // Retrieves attributes from custom 'testimonial' element
    let body = testimonial.getAttribute( 'testimonialBody' );
    let author = testimonial.getAttribute( 'testimonialAuthor' );
    let about = testimonial.getAttribute( 'testimonialAbout' );

    // Element creation
    const testWrapperElement = conversionApi.writer.createContainerElement( 'div', { class: 'callout__interbodyquote' } );
    const testBodyElement = conversionApi.writer.createContainerElement( 'p', { class: 'body_testimonial' } );
    const testSubBodyElement = conversionApi.writer.createContainerElement( 'div' );
    const testIconElement = conversionApi.writer.createContainerElement( 'image', { class: 'icon__testimonial', src: testimonialIcon } );
    const testFooterWrapperElement = conversionApi.writer.createContainerElement( 'div' );
    const testAuthorElement = conversionApi.writer.createContainerElement( 'p', { class: 'author_testimonial' } );
    const testAboutElement = conversionApi.writer.createContainerElement( 'p', { class: 'about_testimonial' } );

    // Text element creation
    const bodyText = conversionApi.writer.createText( body );
    const authorText = conversionApi.writer.createText( author );
    const aboutText = conversionApi.writer.createText( about );   

    // Combining/nesting elements
    let insertPosition = ViewPosition.createAt( testWrapperElement, 'end' );
    conversionApi.writer.insert( insertPosition, testBodyElement );
    insertPosition = ViewPosition.createAt( testWrapperElement, 'end' );
    conversionApi.writer.insert( insertPosition, testSubBodyElement );
    insertPosition = ViewPosition.createAt( testBodyElement, 'end' );
    conversionApi.writer.insert( insertPosition, bodyText );
    insertPosition = ViewPosition.createAt( testSubBodyElement, 'end' );
    conversionApi.writer.insert( insertPosition, testFooterWrapperElement );
    insertPosition = ViewPosition.createAt( testSubBodyElement, 'end' );
    conversionApi.writer.insert( insertPosition, testIconElement );
    insertPosition = ViewPosition.createAt( testFooterWrapperElement, 'end' );
    conversionApi.writer.insert( insertPosition, testAuthorElement );
    insertPosition = ViewPosition.createAt( testFooterWrapperElement, 'end' );
    conversionApi.writer.insert( insertPosition, testAboutElement );
    insertPosition = ViewPosition.createAt( testAboutElement, 'end' );
    conversionApi.writer.insert( insertPosition, aboutText );
    insertPosition = ViewPosition.createAt( testAuthorElement, 'end' );
    conversionApi.writer.insert( insertPosition, authorText );

    const viewPosition = conversionApi.mapper.toViewPosition( data.range.start );
    conversionApi.mapper.bindElements( testimonial, testWrapperElement );
    conversionApi.writer.insert( viewPosition, testWrapperElement );

我的命令如下...

    export default class TestimonialCommand extends Command {
        refresh() {
            const model = this.editor.model;
            const selection = model.document.selection;
            const schema = model.schema;

            const validParent = getInsertTestimonialParent( selection.getFirstPosition() );

            // Check if custom testimonial element is allowed within the current parent (based on cursor location)
            this.isEnabled = schema.checkChild( validParent, 'testimonial' );
        }

        execute(body, author, about) {
            const model = this.editor.model;
            const selection = model.document.selection;

            model.change(writer => {
                const firstPosition = selection.getFirstPosition();
                const isRoot = firstPosition.parent === firstPosition.root;
                const insertPosition = isRoot ? Position.createAt( firstPosition ) : Position.createAfter( firstPosition.parent );

                // Creates custom testimonial element with user input as custom attributes.
                // These attributes will be pulled off the element during the downcasting and converted into 
                // text within a testimonial block of HTML. 
                const testimonial = writer.createElement( 'testimonial', { 'testimonialBody': body, 'testimonialAuthor': author, 'testimonialAbout': about } );

                writer.insert( testimonial, insertPosition );
            })
        }
    }

    // Retrieves parent element 
    function getInsertTestimonialParent( position ) {
        const parent = position.parent;

        return parent === parent.root ? parent : parent.parent;
    }

我收到的完整错误是......

Uncaught CKEditorError: model-nodelist-offset-out-of-bounds: Given offset cannot be found in the node list.

诸如此类的错误的可能原因是什么?

预先感谢您的帮助!

4

1 回答 1

0

我在开发自己的小部件时遇到了同样的错误,并用viewToModelPositionOutsideModelElement实用程序解决了这个问题。

抛出此错误是因为由于结构不同,模型和视图之间的文本节点映射存在差异

您可以在此处阅读 CKEditor 文档:Fixing position mapping

于 2019-11-12T12:20:20.027 回答