UNPKG

@ckeditor/ckeditor5-ai

Version:

AI features for CKEditor 5.

179 lines (178 loc) • 6.47 kB
/** * @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; } ]; };