在angular应用程序中为CKEDITOR 5创建自定义插件时,抛出TypeError:无法读取属性';0';未定义的

在angular应用程序中为CKEDITOR 5创建自定义插件时,抛出TypeError:无法读取属性';0';未定义的,ckeditor,angular7,ckeditor5,Ckeditor,Angular7,Ckeditor5,我正在尝试添加一个自定义插件以添加到ckeditor5构建解耦文档编辑器。 当我将自定义插件添加到ckeditor5构建解耦文档构建代码中,然后运行npm run build。但是我得到了错误TypeError:当我将ckeditor.js构建文件添加到我的angular项目时,无法读取undefined的属性“0” 编辑器工具栏不再显示在屏幕上,我无法编辑文本,但是,该插件似乎正在执行其允许在编辑器中使用内联样式的目的 我有两个问题: 我是否正确创建了插件 在我的Angular项目中,我的配

我正在尝试添加一个自定义插件以添加到ckeditor5构建解耦文档编辑器。 当我将自定义插件添加到ckeditor5构建解耦文档构建代码中,然后运行
npm run build
。但是我得到了错误TypeError:当我将ckeditor.js构建文件添加到我的angular项目时,无法读取undefined的属性“0”

编辑器工具栏不再显示在屏幕上,我无法编辑文本,但是,该插件似乎正在执行其允许在编辑器中使用内联样式的目的

我有两个问题:

  • 我是否正确创建了插件
  • 在我的Angular项目中,我的配置是否缺少一些内容
  • 以下是我遵循的步骤和使用的代码

    创建插件

    import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
    
    
    export default class Extension extends Plugin {
        constructor( editor ) {
            super( editor );
        }
    
        init() {
            const editor = this.editor;
    
            let allowedAttributes = [
                'width', 'height', 'style', 'stylex', 'target', 'class', 'id', 'name', 'title', 'type', 'olddisplay', 'text-align', 'align',
                'border', 'cellspacing','padding', 'cellpadding', 'color', 'valign', 'clear', 'src',  'shapes', '&amp',
                'prefix', 'tagtype', 'datetime', 'cite',  'cols', 'colspan', 'noshade', 'text-decoration',
                'shape', 'start',  'alt', 'strong', 'files', 'hr', 'font-size',
                'com',  'background-color', 'rowspan', 'span', 'page', 'content',
                'action', 'value', 'autofocus', 'maxlength', 'rows', 'for', 'aria-label', 'checked', 'selected',
                'rel', 'scope', 'location', 'cellpacing', 'block-id', 'lang',
                'original-style', 'datatype', 'property', 'controls', 'controlslist', 'data-attr', 'poster', 'preload',
                'tabindex', 'role', 'aria-describedby', 'aria-disabled','aria-haspopup', 
                'href', 'col', 'doc', 'attach', 'pls', 'vspace', 'hspace', 'slatepath'];
    
             //creates a new schema to to keep preexisting styles
             editor.model.schema.extend('$root', { allowAttributes: allowedAttributes });
             editor.model.schema.extend('$block', { allowAttributes: allowedAttributes });
             editor.model.schema.extend('$text', { allowAttributes: allowedAttributes });
    
             for (var i = 0; i < allowedAttributes.length; i++) {
                 editor.conversion.attributeToAttribute({ model: this.allowedAttributes[i], view: this.allowedAttributes[i] });
             }
    
             editor.model.schema.extend('paragraph', { allowAttributes: '__style' });
    
             editor.conversion.for('upcast').attributeToAttribute({
                 model: {
                     key: '__style',
                     name: 'paragraph'
                 },
                 view: 'style'
             });
    
             editor.conversion.for('downcast').add(dispatcher => {
                 dispatcher.on('attribute:__style:paragraph', (evt, data, conversionApi) => {
                     conversionApi.consumable.consume(data.item, evt.name);
    
                     const viewElement = conversionApi.mapper.toViewElement(data.item);
    
                     conversionApi.writer.setAttribute('style', data.attributeNewValue, viewElement);
                 });
             });
        } 
    }
    
    "compilerOptions": {
        "baseUrl": "./",
        "outDir": "./dist/out-tsc",
        "sourceMap": true,
        "declaration": false,
        "module": "es2015",
        "moduleResolution": "node",
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "allowJs": true,
        "importHelpers": true,
        "target": "es2015",
        "typeRoots": [
          "node_modules/@types"
        ],
        "lib": [
          "es2018",
          "dom"
        ]
      }
    
    editor.conversion.attributeToAttribute({ model: allowedAttributes[i], view: allowedAttributes[i] });
    
    接下来,我运行
    npm run build
    ,它在build文件夹中生成ckeditor.js。 接下来,我将ckeditor.js(以及相应的翻译文件)从build文件夹复制到angular项目的assets文件夹中

    然后将我的自定义编辑器添加到我的文件中

    import * as CustomEditor from 'src/assets/ckeditor.js';
    public Editor = CustomEditor;
    
    在tsconfig.json中

    import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
    
    
    export default class Extension extends Plugin {
        constructor( editor ) {
            super( editor );
        }
    
        init() {
            const editor = this.editor;
    
            let allowedAttributes = [
                'width', 'height', 'style', 'stylex', 'target', 'class', 'id', 'name', 'title', 'type', 'olddisplay', 'text-align', 'align',
                'border', 'cellspacing','padding', 'cellpadding', 'color', 'valign', 'clear', 'src',  'shapes', '&amp',
                'prefix', 'tagtype', 'datetime', 'cite',  'cols', 'colspan', 'noshade', 'text-decoration',
                'shape', 'start',  'alt', 'strong', 'files', 'hr', 'font-size',
                'com',  'background-color', 'rowspan', 'span', 'page', 'content',
                'action', 'value', 'autofocus', 'maxlength', 'rows', 'for', 'aria-label', 'checked', 'selected',
                'rel', 'scope', 'location', 'cellpacing', 'block-id', 'lang',
                'original-style', 'datatype', 'property', 'controls', 'controlslist', 'data-attr', 'poster', 'preload',
                'tabindex', 'role', 'aria-describedby', 'aria-disabled','aria-haspopup', 
                'href', 'col', 'doc', 'attach', 'pls', 'vspace', 'hspace', 'slatepath'];
    
             //creates a new schema to to keep preexisting styles
             editor.model.schema.extend('$root', { allowAttributes: allowedAttributes });
             editor.model.schema.extend('$block', { allowAttributes: allowedAttributes });
             editor.model.schema.extend('$text', { allowAttributes: allowedAttributes });
    
             for (var i = 0; i < allowedAttributes.length; i++) {
                 editor.conversion.attributeToAttribute({ model: this.allowedAttributes[i], view: this.allowedAttributes[i] });
             }
    
             editor.model.schema.extend('paragraph', { allowAttributes: '__style' });
    
             editor.conversion.for('upcast').attributeToAttribute({
                 model: {
                     key: '__style',
                     name: 'paragraph'
                 },
                 view: 'style'
             });
    
             editor.conversion.for('downcast').add(dispatcher => {
                 dispatcher.on('attribute:__style:paragraph', (evt, data, conversionApi) => {
                     conversionApi.consumable.consume(data.item, evt.name);
    
                     const viewElement = conversionApi.mapper.toViewElement(data.item);
    
                     conversionApi.writer.setAttribute('style', data.attributeNewValue, viewElement);
                 });
             });
        } 
    }
    
    "compilerOptions": {
        "baseUrl": "./",
        "outDir": "./dist/out-tsc",
        "sourceMap": true,
        "declaration": false,
        "module": "es2015",
        "moduleResolution": "node",
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "allowJs": true,
        "importHelpers": true,
        "target": "es2015",
        "typeRoots": [
          "node_modules/@types"
        ],
        "lib": [
          "es2018",
          "dom"
        ]
      }
    
    editor.conversion.attributeToAttribute({ model: allowedAttributes[i], view: allowedAttributes[i] });
    
    在控制台中,当我打印编辑器的插件时,我的自定义插件显示为未定义

    ["Essentials", "Alignment", "FontSize", "FontFamily", "Highlight", "CKFinderUploadAdapter", "Autoformat", "Bold", "Italic", "Strikethrough", "Underline", "BlockQuote", "CKFinder", "EasyImage", "Heading", "Image", "ImageCaption", "ImageStyle", "ImageToolbar", "ImageUpload", "Link", "List", "MediaEmbed", "Paragraph", "PasteFromOffice", "Table", "TableToolbar", undefined]
    

    我认为您需要添加
    pluginName

    export default class Extension extends Plugin {
        constructor( editor ) {
            super( editor );
        }
    
        static get pluginName() {
            return 'Extension';
        }
    
        init() { ...
    

    因此,问题不是由任何角度/Ckeditor5积分引起的,而是代码中的一个简单错误

    我最初是在Angular中构建代码的,当时我正在熟悉创建插件的过程,并将代码从Angular应用程序转移到克隆的repo中,以创建自定义插件

    该错误是一个简单的引用错误

    该行

    import Extension from "../ckeditor5-extension/src/extension.js";
    
    DecoupledEditor.builtinPlugins = [
        *
        *
        PasteFromOffice,
        Table,
        TableToolbar,
        Extension
    ];
    
    editor.conversion.attributeToAttribute({ model: this.allowedAttributes[i], view: this.allowedAttributes[i] });
    
    应该是

    import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
    
    
    export default class Extension extends Plugin {
        constructor( editor ) {
            super( editor );
        }
    
        init() {
            const editor = this.editor;
    
            let allowedAttributes = [
                'width', 'height', 'style', 'stylex', 'target', 'class', 'id', 'name', 'title', 'type', 'olddisplay', 'text-align', 'align',
                'border', 'cellspacing','padding', 'cellpadding', 'color', 'valign', 'clear', 'src',  'shapes', '&amp',
                'prefix', 'tagtype', 'datetime', 'cite',  'cols', 'colspan', 'noshade', 'text-decoration',
                'shape', 'start',  'alt', 'strong', 'files', 'hr', 'font-size',
                'com',  'background-color', 'rowspan', 'span', 'page', 'content',
                'action', 'value', 'autofocus', 'maxlength', 'rows', 'for', 'aria-label', 'checked', 'selected',
                'rel', 'scope', 'location', 'cellpacing', 'block-id', 'lang',
                'original-style', 'datatype', 'property', 'controls', 'controlslist', 'data-attr', 'poster', 'preload',
                'tabindex', 'role', 'aria-describedby', 'aria-disabled','aria-haspopup', 
                'href', 'col', 'doc', 'attach', 'pls', 'vspace', 'hspace', 'slatepath'];
    
             //creates a new schema to to keep preexisting styles
             editor.model.schema.extend('$root', { allowAttributes: allowedAttributes });
             editor.model.schema.extend('$block', { allowAttributes: allowedAttributes });
             editor.model.schema.extend('$text', { allowAttributes: allowedAttributes });
    
             for (var i = 0; i < allowedAttributes.length; i++) {
                 editor.conversion.attributeToAttribute({ model: this.allowedAttributes[i], view: this.allowedAttributes[i] });
             }
    
             editor.model.schema.extend('paragraph', { allowAttributes: '__style' });
    
             editor.conversion.for('upcast').attributeToAttribute({
                 model: {
                     key: '__style',
                     name: 'paragraph'
                 },
                 view: 'style'
             });
    
             editor.conversion.for('downcast').add(dispatcher => {
                 dispatcher.on('attribute:__style:paragraph', (evt, data, conversionApi) => {
                     conversionApi.consumable.consume(data.item, evt.name);
    
                     const viewElement = conversionApi.mapper.toViewElement(data.item);
    
                     conversionApi.writer.setAttribute('style', data.attributeNewValue, viewElement);
                 });
             });
        } 
    }
    
    "compilerOptions": {
        "baseUrl": "./",
        "outDir": "./dist/out-tsc",
        "sourceMap": true,
        "declaration": false,
        "module": "es2015",
        "moduleResolution": "node",
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "allowJs": true,
        "importHelpers": true,
        "target": "es2015",
        "typeRoots": [
          "node_modules/@types"
        ],
        "lib": [
          "es2018",
          "dom"
        ]
      }
    
    editor.conversion.attributeToAttribute({ model: allowedAttributes[i], view: allowedAttributes[i] });
    
    减去这个。参考资料

    对于任何创建自定义插件的人,当您构建插件时,repo中有一个示例编辑器,允许您使用最新的更改测试代码。您可以确保代码在传输到Angular应用程序之前工作正常,从而排除自定义插件和Angular应用程序的任何集成问题