/** * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options */ import { type Locale, type PriorityString } from '@ckeditor/ckeditor5-utils'; import type { ModelSchema, ModelElement } from '@ckeditor/ckeditor5-engine'; import { type Suggestion } from './suggestion.js'; /** * Creates descriptions for suggestions and suggestions chains. * * The class manages everything related to generating descriptions for suggestions. Here, you register labels for elements, * attributes, or custom callback for non-regular cases. * * One or more suggestions that are grouped together (based ond various conditions) create "suggestion chain". * In such chain one suggestion may impact other suggestion when it comes to the description of the whole chain. * For example, insertion next to deletion results in "Replaced" description. */ export declare class SuggestionDescriptionFactory { constructor(schema: ModelSchema, locale: Locale); /** * Returns descriptions for given suggestion chain. * * The structure of the descriptions array is as follows (explained on an example): * * ```ts * [ * { type: 'insertion', content: '*Insert:* 2 paragraphs' }, * { type: 'insertion', content: '*Insert:* image }, * { type: 'replace', content: '*Replace:* "Foo" *with* "Bar"' } * ] * ``` * * In above example there are three description instances (or lines). Two new (empty) paragraphs were added, * an image was added and then "Foo" text was removed and "Bar" text was added. For example, above structure could be rendered as: * * ```html *

Insert: 2 paragraphs

*

Insert: image

*

Replace: "Foo" with "Bar"

* ``` */ getDescriptions(suggestions: Array): Array; /** * Registers a callback function that returns a custom description for a suggestion. * * Registered callback is fired for a suggestion whenever there is a need to generate a description for that suggestion. * * The callback takes the suggestion instance as a parameter and should return * {@link module:track-changes/suggestiondescriptionfactory~SuggestionDescription description object} or a falsy value * if the suggestion was not handled by the callback. * * Example of a description callback for the bold style: * * ```ts * suggestionDescriptionFactory.registerDescriptionCallback( suggestion => { * const { data } = suggestion; * * // Omit suggestions that are not bold style suggestions. * if ( !data || data.commandName !== 'bold' ) { * return; * } * * const isSet = !!data.commandParams[ 0 ].forceValue; * const content = isSet ? '*Set format:* bold' : '*Remove format:* bold'; * * return { * type: 'format', * content * }; * } ); * ``` */ registerDescriptionCallback(callback: SuggestionDescriptionCallback): void; /** * For given `elementName` registers how this element will be labeled in a description (for example when it is added * or removed). * * Instead of a string name you may provide a matching function that takes item {@link module:engine/model/item~ModelItem} as an input * and should return boolean value. * * Provided label callback takes one parameter, `quantity`, and is expected to return the label for the element as a string. * * A simple use case without using internationalization: * * ```ts * suggestionDescriptionFactory.registerElementLabel( * 'paragraph', * quantity => quantity == 1 ? 'paragraph' : quantity + ' paragraphs' * ); * ``` * * If you want your feature to be localized to other languages, use localization service: * * ```ts * const t = editor.locale.t; // Remember that you have to use function named `t`. * * suggestionDescriptionFactory.registerElementLabel( * 'paragraph', * quantity => t( { string: 'paragraph', plural: '%0 paragraphs', id: 'ELEMENT_PARAGRAPH' }, quantity ) * ); * ``` */ registerElementLabel(elementNameOrCallback: string | Function, labelCallback: SuggestionLabelCallback, priority?: PriorityString): void; /** * For given `attributeName` registers how this attribute will be labeled in a description (for example when it is added * or removed). * * Example usage with internationalization: * * ```ts * const t = editor.locale.t; // Remember that you have to use function named `t`. * * suggestionDescriptionFactory.registerAttributeLabel( * 'bold', * t( 'bold' ) * ); * ``` */ registerAttributeLabel(attributeName: string, attributeLabel: string): void; /** * Returns label registered for given element or the element name if there is no label registered for it. */ getItemLabel(element: ModelElement, quantity?: number): string; } /** * A description for the suggestion. * * ```ts * { * type: 'format', * label: '*Set format:* bold' * } * ``` * * A description for the color-related suggestions like font color may specify the `color` property that will provide a better UX * by displaying a color box next to the suggestion. * * ```ts * { * type: 'format', * label: '*Set font color:*', * color: { * value: 'hsl( 60, 60%, 60% )', * title: 'yellow' * } * } * ``` */ export interface SuggestionDescription { type: 'insertion' | 'deletion' | 'replace' | 'format'; /** * Description label. You may use `*` to bold part of the label. */ content: string; /** * The optional `color` property used for color-related suggestions. * The object should provide the `value` (for displaying the color) and `title` (for describing the color) fields. */ color?: { value: string; title: string; }; } export type SuggestionDescriptionCallback = (suggestion: Suggestion) => SuggestionDescription | SuggestionDescriptionItem | undefined; export type SuggestionLabelCallback = (quantity: number) => string; /** * An intermediate state which is easier to operate on when consecutive suggestion * ranges are traversed. */ export interface SuggestionDescriptionItem { type: 'text' | 'addEmptyContainer' | 'addObject' | 'removeEmptyContainer' | 'removeObject' | 'addContainer' | 'removeContainer' | 'addFormat' | 'removeFormat'; add?: string; remove?: string; element?: ModelElement; quantity?: number; key?: string; }