Contribute to this guide

guide更新至 CKEditor 5 v33.x

更新 CKEditor 5 安装时,请确保**所有包的版本一致**,以避免错误。

对于自定义版本,您可能尝试删除package-lock.jsonyarn.lock文件(如果适用)并在重建编辑器之前重新安装所有包。为了获得最佳效果,请确保您使用最新的包版本。

# 更新至 CKEditor 5 v33.0.0

于 2022 年 3 月 9 日发布。

有关版本 33.0.0 中引入的全部变更列表,请参阅CKEditor 5 v33.0.0 的发行说明

以下是升级到 CKEditor 5 v33.0.0 时需要注意的最重要的更改。

# ckeditor5-list 包中的新导入路径

从 v33.0.0 开始,ckeditor5-list 包中的一些导入路径已更改。如果您的应用程序导入单个插件来集成或构建 CKEditor 5,则应相应地更新路径

// ❌ Old import paths:
import ListEditing from '@ckeditor/ckeditor5-list/src/listediting';
import ListUI from '@ckeditor/ckeditor5-list/src/listui';
import TodoListEditing from '@ckeditor/ckeditor5-list/src/todolistediting';
import ListPropertiesEditing from '@ckeditor/ckeditor5-list/src/listpropertiesediting';

// ✅ New import paths (with subdirectories):
import ListEditing from '@ckeditor/ckeditor5-list/src/list/listediting';
import ListUI from '@ckeditor/ckeditor5-list/src/list/listui';
import TodoListEditing from '@ckeditor/ckeditor5-list/src/todolist/todolistediting';
import ListPropertiesEditing from '@ckeditor/ckeditor5-list/src/listproperties/listpropertiesediting';

诸如ListListPropertiesTodoList等顶级插件的导入路径保持不变。如果您不确定应该使用哪种导入路径,您始终可以浏览与 npm 上的包内容相对应的 GitHub 源代码

# CKEditor 5 协作功能中的额外依赖项

引入了对DLL 版本的支持,用于协作功能。因此,一些导入、插件要求和跨包依赖关系已更改,以允许新的构建过程。

从现在开始,当您将以下 CKEditor 5 协作功能添加到编辑器时,将需要额外的插件

  • TrackChanges还需要将Comments添加到编辑器插件列表中

    // ❌ Old imports:
    import TrackChanges from '@ckeditor/ckeditor5-track-changes/src/trackchanges';
    // ✅ New imports:
    import TrackChanges from '@ckeditor/ckeditor5-track-changes/src/trackchanges';
    import Comments from '@ckeditor/ckeditor5-comments/src/comments';
    
  • RealTimeCollaborativeEditing还需要CloudServices

    // ❌ Old imports:
    import RealTimeCollaborativeEditing from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativeediting';
    // ✅ New imports:
    import RealTimeCollaborativeEditing from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativeediting';
    import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices';
    
  • RealTimeCollaborativeComments还需要CloudServicesComments

    // ❌ Old imports:
    import RealTimeCollaborativeComments from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativecomments';
    // ✅ New imports:
    import RealTimeCollaborativeComments from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativecomments';
    import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices';
    import Comments from '@ckeditor/ckeditor5-comments/src/comments';
    
  • RealTimeCollaborativeTrackChanges还需要CloudServicesCommentsTrackChanges

    // ❌ Old imports:
    import RealTimeCollaborativeTrackChanges from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativetrackchanges';
    // ✅ New imports:
    import RealTimeCollaborativeTrackChanges from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativetrackchanges';
    import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices';
    import Comments from '@ckeditor/ckeditor5-comments/src/comments';
    import TrackChanges from '@ckeditor/ckeditor5-track-changes/src/trackchanges';
    
  • RealTimeCollaborativeRevisionHistory还需要CloudServices

    // ❌ Old imports:
    import RealTimeCollaborativeRevisionHistory from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativerevisionhistory';
    // ✅ New imports:
    import RealTimeCollaborativeRevisionHistory from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativerevisionhistory';
    import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices';
    
  • CloudServicesCommentsAdapter还需要CloudServicesCommentsRepository

    // ❌ Old imports:
    import CloudServicesCommentsAdapter from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativecomments/cloudservicescommentsadapter';
    // ✅ New imports:
    import CloudServicesCommentsAdapter from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativecomments/cloudservicescommentsadapter';
    import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices';
    import CommentsRepository from '@ckeditor/ckeditor5-comments/src/comments/commentsrepository';
    
  • CloudServicesTrackChangesAdapter还需要CloudServicesCommentsRepositoryTrackChangesEditing

    // ❌ Old imports:
    import CloudServicesTrackChangesAdapter from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativetrackchanges/cloudservicestrackchangesadapter';
    
    // ✅ New imports:
    import CloudServicesTrackChangesAdapter from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativetrackchanges/cloudservicestrackchangesadapter';
    import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices';
    import CommentsRepository from '@ckeditor/ckeditor5-comments/src/comments/commentsrepository';
    import TrackChangesEditing from '@ckeditor/ckeditor5-track-changes/src/trackchangesediting';
    
  • CloudServicesRevisionHistoryAdapter还需要CloudServices

    // ❌ Old imports:
    import CloudServicesRevisionHistoryAdapter from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativerevisionhistory/cloudservicesrevisionhistoryadapter';
    
    // ✅ New imports:
    import CloudServicesRevisionHistoryAdapter from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativerevisionhistory/cloudservicesrevisionhistoryadapter';
    import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices';
    

# 向下转换转换管道中所有模型项的强制使用

从 v33.0.0 开始,向下转换转换管道中的所有项都必须在模型中被使用,以防止编辑器功能出现错误和不可预测的行为。如果模型项未被使用,则将抛出conversion-model-consumable-not-consumed错误。要了解有关此错误原因和可能解决方案的更多信息,请参阅API 文档

# 向下转换管道中的 triggerBy 选项现在已过时

v33.0.0 版本对转换系统进行了重大升级。您可以在GitHub 开发人员说明中找到所有这些更改的详细摘要。

如果您的某些向下转换管道转换器使用实验性的triggerBy属性来触发在属性或子级更改时进行(重新)转换,则需要更新它们。例如

// ❌ The old conversion using obsolete "triggerBy":
editor.conversion.for( 'downcast' ).elementToElement( {
    model: 'myElement',
    view: ( modelElement, { writer } ) => {
        return writer.createContainerElement( 'div', {
            'data-owner-id': modelElement.getAttribute( 'ownerId' ),
            class: `my-element my-element-${ modelElement.getAttribute( 'type' ) }`
        } );
    },
    triggerBy: {
        attributes: [ 'ownerId', 'type' ],
        children: 'childModelElement'
    }
} );

// ✅ The new conversion syntax:
editor.conversion.for( 'downcast' ).elementToElement( {
    model: {
        name: 'myElement',
        attributes: [ 'ownerId', 'type' ],
        children: true
    },
    view: ( modelElement, { writer } ) => {
        // The same converter code.
    }
} );

新语法在elementToElementelementToStructure助手两者中都可用。

TableEditing插件带来的转换在此版本中得到了改进,现在严重依赖于elementToStructure向下转换转换助手。

如果您的集成扩展或覆盖了该转换(tabletableRowtableCell模型元素和/或它们的属性),您可能需要采取一些措施来使您的自定义功能与最新的编辑器 API 保持一致。必要的更改程度可能因您的自定义程度而异。

# 低级别向下转换转换器中的职责转移

向下转换调度程序现在将为模型项触发事件,无论它们是否已被使用。这意味着监听这些事件的低级别(事件驱动)向下转换转换器必须首先测试该项是否已被使用,以防止双重转换和错误

editor.conversion.for( 'downcast' ).add( dispatcher => {
    dispatcher.on( '...', ( evt, data, conversionApi ) => {
        // Before converting, check whether the change has not been consumed yet.
        if ( !conversionApi.consumable.test( data.item, evt.name ) ) {
            return;
        }

        // Converter code...
    } );
} );

此外,从 CKEditor 5 v33.0.0 开始,您的自定义转换器必须使用所有模型项,以防止进一步的错误。

# Differ#refreshItem() 方法现在已过时

Differ#refreshItem()已过时,并被reconvertItem替换

// ❌ Old API:
editor.model.document.differ.refreshItem( ... );

// ✅ New API:
editor.editing.reconvertItem( ... );

# 现在需要注释编辑器配置

由于我们删除了项目内部的跨包依赖关系,因此注释编辑器的配置变得必需。注释部分中使用的编辑器也是一个 CKEditor 5 实例。它的配置方式与常规编辑器相同。

更新后,您应该使用config.comments.editorConfig选项配置注释编辑器

import Autoformat from '@ckeditor/ckeditor5-autoformat/src/autoformat';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
import List from '@ckeditor/ckeditor5-list/src/list';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        // ...

        comments: {
            editorConfig: {
                extraPlugins: [ Autoformat, Bold, Italic, List ]
            }
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

在更改之前,注释编辑器包含BoldItalicAutoformatList插件。

如果您希望在更新编辑器后保持相同的用户体验,则需要按上述示例配置注释编辑器。

如果未提供此配置,则会在控制台中记录警告,并且注释编辑器将使用最基本的功能初始化:键入、段落和撤销。

要隐藏警告(并使用基本配置),请为注释编辑器提供空配置

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        // ...

        comments: {
            editorConfig: {}
        }
    } );

# 新 API

# 新的 elementToStructure() 向下转换助手

引入了新的elementToStructure助手,以简化向下转换到复杂视图结构的转换。与elementToElement不同,它允许将元素的子级放置在视图结构中的可配置插槽中,而无需使用低级别事件驱动 API 开发复杂的转换器。

要详细了解此新助手,请参阅API 文档或查看官方转换指南,其中包含大量示例和详细信息。

# 触发向下转换(重新)转换的新 API

triggerBy属性已过时,并创建了一个新 API 来在模型元素的属性或子级发生更改时触发该模型元素的向下转换转换(也称为重新转换)。

editor.conversion.for( 'downcast' ).elementToElement( {
    model: {
        name: 'myElement',

        // Changes to these attributes will (re)convert myElement.
        attributes: [ 'ownerId', 'type' ],

        // If some children are added or removed, myElement will be (re)converted.
        children: true
    },
    view: ( modelElement, { writer } ) => {
        // ...
    }
} );

model属性的新语法在elementToElementelementToStructure助手两者中都可用。有关更多详细信息,请参阅相应的 API 文档。

# DowncastWriter#createContainerElement() API 的改进

从 v33.0.0 开始,您可以在 createContainerElement 方法中直接指定容器元素的子元素。

// ❌ Old API:
const element = writer.createContainerElement( 'p', { id: '1234' } );

writer.insert( writer.createPositionAt( element, 0 ), childElementA );
writer.insert( writer.createPositionAt( element, 1 ), childElementB );
// ...

// ✅ New API:
writer.createContainerElement( 'p', { id: '1234' }, [
    childElementA,
    childElementB,

    // ...
] );