TYPO3 v12 CKEditor5分页插件报错:commandcollection-command-not-found
我正在为TYPO3 v12开发扩展,给CKEditor5添加分页(Page Break)功能,希望用户只需安装我的扩展就能使用,无需自行通过Node安装分页依赖。但点击分页按钮时出现错误:
"ckeditor5-utils.js?bust=1712928953:47 Uncaught CKEditorError: commandcollection-command-not-found {"commandName":"pageBreak"}"
我的扩展结构及代码如下:
1. rte_ckeditor_pagebreak/Configuration/JavaScriptModules.php
<?php return [ 'dependencies' => [ 'backend' ], 'tags' => [ 'backend.form', ], 'imports' => [ '@test/typo3-rte-ckeditor-page-break/plugin.js' => 'EXT:rte_ckeditor_pagebreak/Resources/Public/JavaScript/CkeditorPlugins/PageBreak/plugin.js', '@ckeditor/page-break.js' => 'EXT:rte_ckeditor_pagebreak/Resources/Public/Contrib/ckeditor/ckeditor5-page-break/src/index.js', '@ckeditor/page-break-core.js' => 'EXT:rte_ckeditor_pagebreak/Resources/Public/Contrib/ckeditor/ckeditor5/src/core.js', '@ckeditor/page-break-widget.js' => 'EXT:rte_ckeditor_pagebreak/Resources/Public/Contrib/ckeditor/ckeditor5/src/widget.js', '@ckeditor/page-break-ui.js' => 'EXT:rte_ckeditor_pagebreak/Resources/Public/Contrib/ckeditor/ckeditor5-ui/src/index.js', ], ];
2. rte_ckeditor_pagebreak/Configuration/RTE/PluginPageBreak.yaml
editor: config: importModules: - '@test/typo3-rte-ckeditor-page-break/plugin.js'
3. rte_ckeditor_pagebreak/Resources/Public/JavaScript/CkeditorPlugins/PageBreak.plugin.js
import * as Core from '@ckeditor/ckeditor5-core'; import * as UI from '@ckeditor/ckeditor5-ui'; import { PageBreak } from "@ckeditor/page-break.js" export default class PageBreakPlugin extends Core.Plugin { static pluginName = 'PageBreakPlugin'; init() { const editor = this.editor; editor.config._config.plugins.push(PageBreak); // The button must be registered among the UI components of the editor // to be displayed in the toolbar. editor.ui.componentFactory.add(PageBreakPlugin.pluginName, () => { // The button will be an instance of ButtonView. const button = new UI.ButtonView(); button.set({ label: 'Page Break', withText: true }); // Execute a callback function when the button is clicked button.on('execute', () => { editor.execute( 'pageBreak' ); }); return button; }); } }
问题原因及修复方案
核心问题
直接修改editor.config._config.plugins添加PageBreak插件的方式不符合CKEditor5的插件加载规范,会绕过编辑器的插件初始化流程,导致PageBreak插件没有正确注册对应的pageBreak命令。同时手动引入的CKEditor5核心模块可能存在路径错误或依赖缺失,进一步加剧了初始化问题。
修复步骤
1. 调整JavaScriptModules.php的依赖映射
移除多余的核心模块引入,添加rte_ckeditor依赖,确保和TYPO3内置的CKEditor5集成兼容:
<?php return [ 'dependencies' => [ 'backend', 'rte_ckeditor' ], 'tags' => [ 'backend.form', ], 'imports' => [ '@test/rte-pagebreak/plugin' => 'EXT:rte_ckeditor_pagebreak/Resources/Public/JavaScript/Plugin.js', '@ckeditor/ckeditor5-page-break' => 'EXT:rte_ckeditor_pagebreak/Resources/Public/Contrib/ckeditor/ckeditor5-page-break/src/index.js', ], ];
2. 重写插件代码,正确注册PageBreak
使用CKEditor5标准的插件依赖声明方式,让编辑器自动处理插件初始化:
import { Plugin } from '@ckeditor/ckeditor5-core'; import { ButtonView } from '@ckeditor/ckeditor5-ui'; import { PageBreak } from '@ckeditor/ckeditor5-page-break'; export default class PageBreakPlugin extends Plugin { static get requires() { // 声明依赖PageBreak插件,编辑器会自动加载并初始化它 return [PageBreak]; } static get pluginName() { return 'PageBreakPlugin'; } init() { const editor = this.editor; // 注册工具栏按钮 editor.ui.componentFactory.add('pageBreak', () => { const button = new ButtonView(); button.set({ label: '分页符', withText: true, tooltip: true }); // 绑定按钮状态到命令状态 button.bind('isOn', 'isEnabled').to(editor.commands.get('pageBreak')); button.on('execute', () => { editor.execute('pageBreak'); editor.editing.view.focus(); }); return button; }); } }
3. 更新RTE配置,添加按钮到工具栏
修改PluginPageBreak.yaml,确保按钮被添加到编辑器工具栏:
editor: config: importModules: - '@test/rte-pagebreak/plugin' toolbar: items: - pageBreak
4. 确保PageBreak插件文件完整
从官方npm包@ckeditor/ckeditor5-page-break中复制全部源码到Resources/Public/Contrib/ckeditor/ckeditor5-page-break目录,不要只复制index.js——必须包含src/pagebreak.js、src/pagebreakcommand.js等核心文件,否则命令无法被定义。
关键说明
- TYPO3的CKEditor5集成要求插件通过
requires属性声明依赖,编辑器会自动处理加载顺序和初始化逻辑,避免手动修改配置导致的流程绕过。 - 直接修改
editor.config._config.plugins会跳过插件的初始化钩子,导致命令、视图等功能无法注册。 - 必须保证引入的PageBreak插件完整,缺少命令定义文件是触发
command-not-found错误的直接原因。
内容的提问来源于stack exchange,提问作者flo1999

