@ckeditor/ckeditor5-ai
Version:
AI features for CKEditor 5.
179 lines (178 loc) • 6.47 kB
TypeScript
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
/**
* @module ai/aireviewmode/aireviewmodeediting
*/
import { InsertOperation, MarkerOperation, ModelPosition, ModelRange, type Operation } from 'ckeditor5/src/engine.js';
import { type Emitter } from 'ckeditor5/src/utils.js';
import { type Context, ContextPlugin, type Editor } from 'ckeditor5/src/core.js';
import { DocumentCompare } from 'ckeditor5-collaboration/src/collaboration-core.js';
import { type AIReviewCheckResultChange } from './model/aireviewcheckresultchange.js';
import { AIEditing } from '../aicore/aiediting.js';
export declare class AIReviewModeEditing extends ContextPlugin {
/**
* @inheritDoc
*/
static get pluginName(): "AIReviewModeEditing";
/**
* @inheritDoc
*/
static get requires(): readonly [typeof DocumentCompare, typeof AIEditing];
/**
* @inheritDoc
*/
static get isOfficialPlugin(): true;
/**
* @inheritDoc
*/
static get isPremiumPlugin(): true;
/**
* @inheritDoc
*/
constructor(context: Context | Editor);
/**
* Exposes the event emitter to allow listening to specific events.
*/
get emitter(): Emitter;
/**
* @inheritDoc
*/
afterInit(): void;
/**
* Returns the data (as string and flat list of container elements) and version of the current document.
*
* This method also applied `data-id` attributes to all elements that are direct parents of text nodes.
* These attributes are used by AI API to determine that given element can be changed.
*
* Additionally, each element is converted from model to HTML string in the context of the entire structure
* to ensure that the conversion is accurate (e.g. table cells need to be inside a table row, which needs to be inside a table).
*/
getDocumentData(): AIDocumentData;
/**
* Compares two pieces of content, calculates operations, groups them and returns diffed content
* and additional data for each group.
*
* Each group contains:
* - `operations`: list of operations that are part of the group.
* - `operationsIsolated`: list of operations that are part of the group but with positions/ranges re-calculated
* to allow applying them in isolation (without other operations that would affect their positions).
* - `groupOffset`: how many characters were inserted in this group.
* - `content`: function that returns content (as HTML string) of the entire content with all changes applied and context marked.
* - `context`: function that returns part of the content (as HTML string) consider as group context, with all changes applied
* for this specific context.
*
* The `context` is a range within a block that includes operations from a specific group, starts after the previous change, and ends
* before the next change. If there is a single group, it spans over the entire block element contents.
*
* For example:
* Initial content: <p>Foo bar baz. 123 456 789.</p>
* New content: <p>Foo bax baz. 123 789.</p>
*
* This can be visualized as ('[]' shows removal, '{}' shows insertion):
* <p>Foo[ bar]{ bax} baz. 123[ 456] 789.</p>
*
* There are 2 separate operation groups:
* - " bar" -> " bax" (marker remove operation + insert operation)
* - " 456" removed (marker remove operation)
*
* The context of each group (marked with '()') is:
* Group 1: <p>(Foo[ bar]{ bax} baz. 123) 456 789.</p>
* Group 2: <p>Foo bar( baz. 123 456 789.)</p>
*
* Operations processing logic is simplified assuming only `Insert` and `Marker` operations. Other operations, even if present
* in the calculated operations, are ignored.
*/
diffContent(contentInitial: string, contentNew: string): Array<AIReviewModeChangeData>;
markChangePositionInEditorContent(changes: Array<AIReviewCheckResultChange>, documentData: AIDocumentData): void;
clearAllMarkers(): void;
switchToReadOnly(): void;
switchToEdit(): void;
applyChange(changeIds: Array<string>): void;
rejectChange(changeId: string): void;
getEditor(): Editor;
getMarkerElementForChange(changeId: string): {
modelRange: ModelRange;
domElement: HTMLElement;
} | null;
}
export type AIDocumentDataElement = {
path: Array<number>;
getContent: () => string;
};
export type AIDocumentData = {
content: string;
version: number;
elements: Map<string, AIDocumentDataElement>;
};
export type AIDiffResult = {
content: string;
operations: Array<Operation>;
};
export type AIReviewModeMarkerInsertData = {
start: ModelPosition;
end: ModelPosition;
type: AIReviewModeMarkerType;
groupId: string;
text?: string;
};
export type AIReviewModeMarkerData = {
id: string;
groupId: string;
type: AIReviewModeMarkerType;
text?: string;
};
export type AIReviewModeMarkerType = 'insert' | 'remove-text' | 'remove-only' | 'remove-context';
export type AIReviewModeChangeRange = {
operations: Array<InsertOperation | MarkerOperation>;
operationsIsolated: Array<InsertOperation | MarkerOperation>;
groupOffset: number;
};
export type AIReviewModeChangeData = AIReviewModeChangeRange & {
content: () => string;
context: () => string;
};
export type AIReviewModeChangeMarkerClickedEvent = {
name: 'changeMarkerClick';
args: [
{
markerId: string;
changeId: string;
markerElement: HTMLElement;
domEvent: MouseEvent;
}
];
};
export type AIReviewModeChangeMarkerRemovedEvent = {
name: 'changeMarkerRemoved';
args: [
{
markerId: string;
changeId: string;
}
];
};
export type AIReviewModeChangeMarkerRestoredEvent = {
name: 'changeMarkerRestored';
args: [
{
markerId: string;
changeId: string;
}
];
};
export type AIReviewModeChangeMarkerBlurredEvent = {
name: 'changeMarkerBlurred';
args: [];
};
export type AIReviewModeChangeMarkerHoveredEvent = {
name: 'changeMarkerHovered';
args: [
{
changeId: string;
markerElement: HTMLElement;
domEvent: MouseEvent;
}
];
};