/**
* @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;
}