Report an issue

guide将跟踪更改与自定义功能集成

跟踪更改功能专为自定义功能而设计。在本指南中,您将学习如何将您的插件与跟踪更改功能集成。

# 启用命令

CKEditor 5 使用 命令 来更改编辑器内容。大多数对编辑器内容的修改都是通过命令执行完成的。此外,命令通常与代表其状态的工具栏按钮相连接。例如,如果某个命令在当前时刻被禁用,工具栏按钮也会被禁用。

默认情况下,当启用跟踪更改时,命令会被禁用。这是为了防止错误和未准备好在建议模式下工作的命令的错误行为。集成您的命令的第一步是启用它

const trackChangesEditing = editor.plugins.get( 'TrackChangesEditing' );

trackChangesEditing.enableCommand( 'commandName' );

现在,该命令将在跟踪更改模式下启用。但是,这本身并不会引入任何与跟踪更改功能集成相关的额外功能。该命令将像跟踪更改被关闭一样工作。

如果您的命令没有对文档模型进行任何更改(例如,它显示一个 UI 组件),那么可能只需简单地启用它就足够了。

进一步的集成步骤将取决于您的命令执行的是哪种更改。

# 插入和删除

许多自定义功能侧重于引入一种新的元素或一个部件。建议使用 model.insertContent() 将此类对象插入文档内容中。此方法除了负责维护适当的文档结构外,还与跟踪更改功能集成。使用此方法插入的任何内容都会自动标记为插入建议。

类似地,删除也通过与 model.deleteContent() 的集成与跟踪更改相集成。在建议模式下调用此方法将创建一个删除建议。对于删除内容的操作也是如此,例如使用 BackspaceDelete 键、在选定内容上键入或在选定内容上粘贴。

总之,如果您的命令插入或删除一个部件,则很有可能它会在建议模式下开箱即用。

可能仍然需要您注意的一点是建议描述。为了生成适当的建议描述,您需要 注册所引入元素的标签。描述机制支持翻译以及单个和多个添加/删除元素的不同标签。

分页符集成示例

const t = editor.t;

trackChangesEditing.descriptionFactory.registerElementLabel(
    'pageBreak',

    quantity => t( {
        string: 'page break',
        plural: '%0 page breaks',
        id: 'ELEMENT_PAGE_BREAK'
    }, quantity )
);

注册元素标签后,它将用于建议描述中。对于上面的示例,描述可能是“**移除:** 分页符”或例如“**插入:** 3 个分页符”。使用翻译系统并添加自定义功能的翻译将在本地化指南中介绍。

如果您不需要支持多种语言,则可以跳过使用翻译系统

trackChangesEditing.descriptionFactory.registerElementLabel(
    'customElement',

    quantity => quantity == 1 ? 'custom element' : quantity + ' custom elements'
);

如果您没有指定标签,则默认情况下将使用模型元素。

如果由于某些原因您的功能无法使用model.insertContent()model.deleteContent(),或者您需要更高级的集成,您可以分配一个自定义回调,该回调将在建议模式打开时执行命令时被调用

trackChangesEditing.enableCommand( 'commandName', ( executeCommand, options ) => {
    // Here you can overwrite what happens when the command is executed in the suggestion mode.
    // See the API documentation to learn more about the parameters passed to the callback.
    // ...
} );

然后您需要使用跟踪更改 API 中的以下方法之一

# 属性更改

另一类更改是属性更改。如果您的自定义功能引入了应用于文本或可以由用户更改的属性,您可能希望实现这种类型的集成。

要启用跟踪属性更改,请使用enableDefaultAttributesIntegration()方法。它是一个简单的助手,旨在处理与属性更改相关的多数场景。它将启用命令,因此您无需另外使用enableCommand()

此外,您需要注册要跟踪的每个属性键。这是使用registerInlineAttribute()registerBlockAttribute()方法完成的。

例如,如果您有一个更改customAttribute值(在文本上设置)的customCommand,请使用以下代码片段

trackChangesEditing.enableDefaultAttributesIntegration( 'customCommand' );
trackChangesEditing.registerInlineAttribute( 'customAttribute' );

属性分为两类:内联(用于在文本上设置的属性)和块(用于在模型元素上设置的属性)。这种区分对于处理对不同类型内容进行的建议的不同逻辑是必要的。

以这种方式集成的每个命令都会跟踪所有已注册的属性,并为其更改创建建议。每个属性应仅注册一次。

对于属性格式化,每个在跟踪更改中注册的属性也应该有其标签注册

const t = editor.t;

plugin.descriptionFactory.registerAttributeLabel( 'bold', t( 'bold' ) );

如果您在评估建议描述时需要更复杂的逻辑,请参阅下面的设置自定义建议描述部分。

# 其他格式更改

以上部分涵盖了典型的自定义插件和命令,这些插件和命令只是添加新元素或更改某些属性。

如果您的功能更复杂,例如,它引入了多个属性,这些属性的值相互依赖,或者您的命令一次执行多个相关的更改,那么您可能需要使用不同的方法。

在这种情况下,您需要将一个自定义回调传递给enableCommand(),该回调将覆盖跟踪更改打开时的默认命令行为。在回调中,您需要使用跟踪更改 API

请参阅这些方法的 API 文档以了解更多信息。

格式建议与命令严格相关。这些建议数据包括:触发命令的范围、命令名称和命令选项。当建议被接受时,指定的命令将在建议范围内使用指定的选项执行。换句话说,原始命令执行被“重播”。

处理自定义功能的格式建议的一般方法是使用与自定义功能类似的逻辑,但不是将更改应用于内容,而是使用跟踪更改 API 创建建议

  1. 覆盖命令回调(使用enableCommand()),这样就不会执行命令。
  2. 使用与自定义命令相同的逻辑来确定命令是否应该执行任何操作。
  3. 使用与自定义命令相同的逻辑来评估所有未设置的命令参数(如果执行命令的原始代码,将使用默认值)。这一点很重要:建议必须设置所有参数,因此其执行不依赖于当前内容状态,而是依赖于创建建议时的内容状态。
  4. 使用选择范围或评估一个或多个更精确的范围用于建议。
  5. 使用markInlineFormat()markBlockFormat()使用先前评估的变量创建一个或多个建议。

请注意,如果以这种方式集成命令,则命令更改将不会真正执行(换句话说,操作不会反映在内容中)。命令只有在建议最终被接受后才会执行。

imageTypeInline命令集成的示例

plugin.enableCommand( 'imageTypeInline', ( executeCommand, options ) => {
    // Commands work on the current selection, so the track
    // changes integration also works on the current selection.
    // Find element that will be affected.
    const image = imageUtils.getClosestSelectedImageElement( editor.model.document.selection );

    editor.model.change( () => {
        plugin.markBlockFormat(
            image,
            {
                // The command to be executed when the suggestion is accepted.
                commandName: 'imageTypeInline',
                // Parameters for the command.
                commandParams: [ options ]
            },
            [],
            'convertBlockImageToInline' );
    } );
} );

请参阅下一部分以了解如何为格式化建议生成标签。

# 设置自定义建议描述

要完成使用格式建议或更复杂的属性建议逻辑的命令集成,您需要提供一个回调,该回调将为这样的建议生成描述。这不同于为插入/删除建议注册标签,因为格式建议更加多样化和复杂。

块引用命令的描述回调示例

plugin.descriptionFactory.registerDescriptionCallback( suggestion => {
    const { data } = suggestion;

    if ( !data || data.commandName != 'blockQuote' ) {
        return;
    }

    if ( data.commandParams[ 0 ].forceValue ) {
        return {
            type: 'format',
            content: '*Set format:* block quote'
        };
    }

    return {
        type: 'format',
        content: '*Remove format:* block quote'
    };
} );

请注意,如果您想覆盖默认描述,描述回调也可以用于插入和删除建议。