UNPKG

@ckeditor/ckeditor5-collaboration-core

Version:

Base utilities used by CKEditor 5 collaboration features to support multiple users working together in a rich text editor.

170 lines (169 loc) 5.59 kB
/** * @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 */ /** * @module collaboration-core/documentcompare */ import { ContextPlugin, Editor } from "@ckeditor/ckeditor5-core"; import { ModelPosition, type ModelWriter, type ModelDocumentFragment, type ModelElement, type Operation } from "@ckeditor/ckeditor5-engine"; export declare const DATA_ID_MODEL_ATTRIBUTE = "$elementId"; export declare const DATA_ID_VIEW_ATTRIBUTE = "data-id"; /** * The `DocumentCompare` plugin provides utilities to compare two documents or documents fragments, and provide set of operations * which need to be executed to transform one document into the other. */ export declare class DocumentCompare extends ContextPlugin { /** * @inheritDoc */ static get pluginName(): "DocumentCompare"; /** * @inheritDoc */ static override get isOfficialPlugin(): true; /** * @inheritDoc */ static override get isPremiumPlugin(): true; init(): Promise<void>; get editor(): Editor; getDiff(dataBefore: string, dataAfter: string, options?: DocumentCompareOptions): DocumentDiff; /** * Returns `true` if given `operation` is an operation that marks a content to be removed. This kind of operations can be * returned by {@link module:collaboration-core/documentcompare~DocumentCompare#getOperations} if `markedDeletions` mode is enabled. * * @param operation */ isMarkedRemoveOperation(operation: Operation): boolean; /** * Applies the given operations (for example, the result of comparing two documents) to the model. * * Beyond applying the operations, this method reproduces the marker bookkeeping that the editing pipeline normally * performs, so that existing markers behave the same as during regular editing: * * * markers affected by a move or merge are anchored, so they can be restored on undo; * * marker operations have their `oldRange` reconciled with the live marker, as operations coming from a comparison * have it set to `null`. * * Must be called inside a model change block; the operations are added to the given `writer`'s batch. * * @param writer Writer of the change block the operations are applied within. * @param operations Operations to apply, in order. */ applyOperations(writer: ModelWriter, operations: Array<Operation>): void; } export interface DocumentCompareOptions { anchor?: string | ModelPosition; markDeletions: boolean; /** * When `DocumentCompare` runs on a context with several editors, `DocumentCompare#editor` is the first editor in the context. * Pass the editor whose model/schema should be used for parsing and for resolving a string `anchor` (e.g. multi-root root names). */ targetEditor?: Editor; } export declare class DocumentDiff { constructor({ editor, before, after, options }: { editor: Editor; before: ModelDocumentFragment; after: ModelDocumentFragment; options: { markDeletions: boolean; anchor: ModelPosition; }; }); getOperationsData(): Array<OperationData>; getOperations(): Array<Operation>; } export interface InsertOperationData { type: "insert"; path: Path; tokens: Array<ModelToken>; } export interface RemoveOperationData { type: "remove"; path: Path; howMany: number; } export interface SplitOperationData { type: "split"; path: Path; } export interface MergeOperationData { type: "merge"; path: Path; } export interface RenameOperationData { type: "rename"; path: Path; oldName: string; newName: string; } export interface AttributeOperationData { type: "attribute"; path: Path; howMany: number; key: string; oldValue: string; newValue: string; } export interface MarkerOperationData { type: "marker"; name: string; range: null | { start: Path; end: Path; }; } export interface UnwrapOperationData { type: "unwrap"; path: Path; howMany: number; } export interface WrapOperationData { type: "wrap"; token: ModelElementToken; range: { start: Path; end: Path; }; } export interface MarkedRemoveData { type: "markedRemove"; range: { start: Path; end: Path; }; } export type OperationData = InsertOperationData | RemoveOperationData | SplitOperationData | MergeOperationData | RenameOperationData | AttributeOperationData | MarkerOperationData | UnwrapOperationData | WrapOperationData | MarkedRemoveData; export type ModelToken = ModelElementToken | ModelTextToken; export interface ModelElementToken { type: "element"; element: ModelElement; elementId: string; /** * Elements category. * * Describes how the element behaves and how it can change. It is used when comparing lists of model tokens to create a better diff. * * * `block` - elements like paragraphs, lists, or headings. Can be renamed. Can be created by splitting. Can be removed by merging. * Its contents can be "moved around" by splitting or merging. * * * `container` - elements like blockquote. Cannot be renamed. Can be created by wrapping. Can be removed by unwrapping. Can be * "resized" by having other elements be moved into or out of them. * * * `solid` - limit-like elements like table or image. Cannot be renamed, split or merged. Can be added by insertion and removed by * deletion. If added or removed, all their content also should be treated as added or removed. */ category: "block" | "container" | "solid"; isStart: boolean; limitId: string; } export interface ModelTextToken { type: "text"; data: string; parent: ModelElement | ModelDocumentFragment; offset: number; limitId: string; } export type Path = Array<number>;