Angular 13 ckedor5自定义构建,使用自定义插件plugincollection-plugin-not-f



我在我的angular应用程序中使用ckedor5。我已经生成了一个自定义构建,并将ckeditor.js文件保存在我的项目目录中。一切正常。我能够渲染编辑器,并在一个角组件中使用它没有问题,通过将这一行添加到顶部:import * as customBuild from 'src/ckCustomBuild/ckeditor';

现在我正在浏览他们的示例文档"占位符"插件,我似乎不能让它在angular中工作。我从他们的网站上添加了相同的代码到一个名为placeholder.plugin.js的新文件中,该文件与上面的ckeditor.js位于同一文件夹中。

然后我将它也导入到我的组件中,并按照如下方式构建配置:

import * as customBuild from 'src/ckCustomBuild/ckeditor';
import * as Placeholder from 'src/ckCustomBuild/placeholder.plugin';
...component boilerplate code....
htmlEditorConfig = {
plugins: [Placeholder],
toolbar: {
items: ['bold', 'italic', 'underline', 'link', 'alignment', 'bulletedList', 'numberedList', '|', 'fontFamily', 'fontSize', 'fontColor', 'fontBackgroundColor', '|', 'Paceholder'],
shouldNotGroupWhenFull: false,
},
// placeholderConfig: {
//   types: ['date', 'color', 'first name', 'surname'],
// },
fontSize: {
options: [9, 11, 13, 'default', 17, 19, 21],
},
mediaEmbed: {
previewsInData: true,
},
};

当我运行应用程序时,我得到以下运行时错误:

core.mjs:6494 ERROR Error: Uncaught (in promise): CKEditorError: plugincollection-plugin-not-found {"plugin":{}}
Read more: https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html#error-plugincollection-plugin-not-found
CKEditorError: plugincollection-plugin-not-found {"plugin":{}}
Read more: https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html#error-plugincollection-plugin-not-found
at p (ckeditor.js:5:432588)
at ckeditor.js:5:432433
at Array.forEach (<anonymous>)
at f (ckeditor.js:5:432420)
at wa.init (ckeditor.js:5:431516)
at bq.initPlugins (ckeditor.js:5:703694)
at ckeditor.js:5:831531
at new ZoneAwarePromise (zone.js:1351:1)
at bq.create (ckeditor.js:5:831488)
at CKEditorComponent.<anonymous> (ckeditor-ckeditor5-angular.js:235:1)
at resolvePromise (zone.js:1262:1)
at resolvePromise (zone.js:1216:1)
at zone.js:1329:1
at push.46026._ZoneDelegate.invokeTask (zone.js:443:1)
at Object.onInvokeTask (core.mjs:25595:1)
at push.46026._ZoneDelegate.invokeTask (zone.js:442:1)
at push.46026.Zone.runTask (zone.js:214:1)
at drainMicroTaskQueue (zone.js:632:1)
at push.46026.ZoneTask.invokeTask [as invoke] (zone.js:529:1)
at invokeTask (zone.js:1727:1)

这是我的2个文件的内容:placeholder.plugin.js

import * as Plugin from 'src/ckCustomBuild/ckeditor';
import * as Widget from 'src/ckCustomBuild/ckeditor';
import * as Command from 'src/ckCustomBuild/ckeditor';
import * as Collection from 'src/ckCustomBuild/ckeditor';
import * as Model from 'src/ckCustomBuild/ckeditor';
import * as toWidget from 'src/ckCustomBuild/ckeditor';
import * as viewToModelPositionOutsideModelElement from 'src/ckCustomBuild/ckeditor';
import * as addListToDropdown from 'src/ckCustomBuild/ckeditor';
import * as createDropdown from 'src/ckCustomBuild/ckeditor';
class Placeholder extends Plugin {
static get requires() {
return [PlaceholderEditing, PlaceholderUI];
}
}
class PlaceholderCommand extends Command {
execute({ value }) {
const editor = this.editor;
const selection = editor.model.document.selection;
editor.model.change((writer) => {
// Create a <placeholder> elment with the "name" attribute (and all the selection attributes)...
const placeholder = writer.createElement('placeholder', {
...Object.fromEntries(selection.getAttributes()),
name: value,
});
// ... and insert it into the document.
editor.model.insertContent(placeholder);
// Put the selection on the inserted element.
writer.setSelection(placeholder, 'on');
});
}
refresh() {
const model = this.editor.model;
const selection = model.document.selection;
const isAllowed = model.schema.checkChild(selection.focus.parent, 'placeholder');
this.isEnabled = isAllowed;
}
}
class PlaceholderUI extends Plugin {
init() {
const editor = this.editor;
const t = editor.t;
const placeholderNames = editor.config.get('placeholderConfig.types');
// The "placeholder" dropdown must be registered among the UI components of the editor
// to be displayed in the toolbar.
editor.ui.componentFactory.add('placeholder', (locale) => {
const dropdownView = createDropdown(locale);
// Populate the list in the dropdown with items.
addListToDropdown(dropdownView, getDropdownItemsDefinitions(placeholderNames));
dropdownView.buttonView.set({
// The t() function helps localize the editor. All strings enclosed in t() can be
// translated and change when the language of the editor changes.
label: t('Placeholder'),
tooltip: true,
withText: true,
});
// Disable the placeholder button when the command is disabled.
const command = editor.commands.get('placeholder');
dropdownView.bind('isEnabled').to(command);
// Execute the command when the dropdown item is clicked (executed).
this.listenTo(dropdownView, 'execute', (evt) => {
editor.execute('placeholder', { value: evt.source.commandParam });
editor.editing.view.focus();
});
return dropdownView;
});
}
}
function getDropdownItemsDefinitions(placeholderNames) {
const itemDefinitions = new Collection();
for (const name of placeholderNames) {
const definition = {
type: 'button',
model: new Model({
commandParam: name,
label: name,
withText: true,
}),
};
// Add the item definition to the collection.
itemDefinitions.add(definition);
}
return itemDefinitions;
}
class PlaceholderEditing extends Plugin {
static get requires() {
return [Widget];
}
init() {
console.log('PlaceholderEditing#init() got called');
this._defineSchema();
this._defineConverters();
this.editor.commands.add('placeholder', new PlaceholderCommand(this.editor));
this.editor.editing.mapper.on(
'viewToModelPosition',
viewToModelPositionOutsideModelElement(this.editor.model, (viewElement) => viewElement.hasClass('placeholder'))
);
this.editor.config.define('placeholderConfig', {
types: ['date', 'first name', 'surname'],
});
}
_defineSchema() {
const schema = this.editor.model.schema;
schema.register('placeholder', {
// Allow wherever text is allowed:
allowWhere: '$text',
// The placeholder will act as an inline node:
isInline: true,
// The inline widget is self-contained so it cannot be split by the caret and it can be selected:
isObject: true,
// The inline widget can have the same attributes as text (for example linkHref, bold).
allowAttributesOf: '$text',
// The placeholder can have many types, like date, name, surname, etc:
allowAttributes: ['name'],
});
}
_defineConverters() {
const conversion = this.editor.conversion;
conversion.for('upcast').elementToElement({
view: {
name: 'span',
classes: ['placeholder'],
},
model: (viewElement, { writer: modelWriter }) => {
// Extract the "name" from "{name}".
const name = viewElement.getChild(0).data.slice(1, -1);
return modelWriter.createElement('placeholder', { name });
},
});
conversion.for('editingDowncast').elementToElement({
model: 'placeholder',
view: (modelItem, { writer: viewWriter }) => {
const widgetElement = createPlaceholderView(modelItem, viewWriter);
// Enable widget handling on a placeholder element inside the editing view.
return toWidget(widgetElement, viewWriter);
},
});
conversion.for('dataDowncast').elementToElement({
model: 'placeholder',
view: (modelItem, { writer: viewWriter }) => createPlaceholderView(modelItem, viewWriter),
});
// Helper method for both downcast converters.
function createPlaceholderView(modelItem, viewWriter) {
const name = modelItem.getAttribute('name');
const placeholderView = viewWriter.createContainerElement('span', {
class: 'placeholder',
});
// Insert the placeholder name (as a text).
const innerText = viewWriter.createText('{' + name + '}');
viewWriter.insert(viewWriter.createPositionAt(placeholderView, 0), innerText);
return placeholderView;
}
}
}

Component.ts

import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { CKEditorUploadAdapter } from 'src/app/_helpers/ckeditor-upload-adapter';
import { ConferenceViewModelWithDetails, PaperAcknowledgementViewModel, PaperConfigurationViewModel } from 'src/app/_models/generatedModels';
import { AuthenticationService } from 'src/app/_services/authentication.service';
import { AdminCallForPapersService, OrganizationService } from 'src/app/_services/generatedServices';
import { ToasterService } from 'src/app/_services/toaster.service';
import * as customBuild from 'src/ckCustomBuild/ckeditor';
//import * as Placeholder from 'src/ckCustomBuild/ckeditor';
import * as Placeholder from 'src/ckCustomBuild/placeholder.plugin';

@Component({
selector: 'bxl-abstract-management-configuration',
templateUrl: 'abstract-management-configuration.component.html',
})
export class AbstractManagementConfigurationComponent implements OnInit {
initialized = false;
public Editor = customBuild;
htmlEditorConfig = {
plugins: [Placeholder],
toolbar: {
items: ['bold', 'italic', 'underline', 'link', 'alignment', 'bulletedList', 'numberedList', '|', 'fontFamily', 'fontSize', 'fontColor', 'fontBackgroundColor', '|', 'Paceholder'],
shouldNotGroupWhenFull: false,
},
// placeholderConfig: {
//   types: ['date', 'color', 'first name', 'surname'],
// },
fontSize: {
options: [9, 11, 13, 'default', 17, 19, 21],
},
mediaEmbed: {
previewsInData: true,
},
};
organizationId: string;
conferenceId: any;
configuration: PaperConfigurationViewModel;
constructor(private auth: AuthenticationService, private orgService: OrganizationService, private router: Router, private route: ActivatedRoute, private cfpService: AdminCallForPapersService, private toaster: ToasterService) {}
ngOnInit(): void {
this.route.paramMap.subscribe((params) => {
this.organizationId = params.get('organizationId');
this.conferenceId = params.get('conferenceId');
this.cfpService.getPaperConfiguration(this.organizationId, this.conferenceId).subscribe((result) => {
this.configuration = result;
this.initialized = true;
});
});
}

在您的placeholder.plugin.js中放入以下内容,

import * as Plugin from 'src/app/ckeditor/ckeditor';
import * as Widget from 'src/app/ckeditor/ckeditor';
import * as Command from 'src/app/ckeditor/ckeditor';
import * as Collection from 'src/app/ckeditor/ckeditor';
import * as Model from 'src/app/ckeditor/ckeditor';
import * as toWidget from 'src/app/ckeditor/ckeditor';
import * as viewToModelPositionOutsideModelElement from 'src/app/ckeditor/ckeditor';
import * as addListToDropdown from 'src/app/ckeditor/ckeditor';
import * as createDropdown from 'src/app/ckeditor/ckeditor';

代替这些行,

import * as Plugin from 'src/ckCustomBuild/ckeditor';
import * as Widget from 'src/ckCustomBuild/ckeditor';
import * as Command from 'src/ckCustomBuild/ckeditor';
import * as Collection from 'src/ckCustomBuild/ckeditor';
import * as Model from 'src/ckCustomBuild/ckeditor';
import * as toWidget from 'src/ckCustomBuild/ckeditor';
import * as viewToModelPositionOutsideModelElement from 'src/ckCustomBuild/ckeditor';
import * as addListToDropdown from 'src/ckCustomBuild/ckeditor';
import * as createDropdown from 'src/ckCustomBuild/ckeditor';

指向错误的路径,它一定是指向ckeditor.js的路径。通过这种方式,您可以消除该文件中的模块加载错误。

最新更新