/**
 * @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 Element, type Document } from '../utils/htmlparser.js';
declare const AIResponseApplier_base: {
    new (): import("@ckeditor/ckeditor5-utils").Observable;
    prototype: import("@ckeditor/ckeditor5-utils").Observable;
};
/**
 * AIResponseApplier is a part of the AI API response processing pipeline.
 *
 * The main purpose of this class is to merge HTML suggestions (modified content chunks) returned
 * from the AI API into the existing editor content. This is "black box" processing, which means that
 * the class does not know anything about the editor content structure, it just merges the content
 * based on provided HTML data (part/suggestion and content) and 'data-id' attributes.
 */
export declare class AIResponseApplier extends /* #__PURE__ -- @preserve */ AIResponseApplier_base {
    constructor(generateUid?: () => string);
    /**
     * Merges the given content part (AI suggestion) with the provided editor content.
     *
     * The main purpose of this function is to merge a piece of AI modified content (`contentPart`)
     * into the given content (editor content, `content`).
     *
     * This is done based on a few rules:
     *
     * 1. Any removed element is not present in the `contentPart` itself but is represented by a special
     * "removed comment" node: `<!-- removed data-id="some_id" -->`. This comment node is located
     * in the same position (relative position to other present nodes) as the element in the original
     * content.
     * 2. Any newly added element is presented in the `contentPart` with a special `data-id="new-element"`
     * attribute.
     * 3. Any existing (from the original `content`) and modified element is presented in the `contentPart`
     * with the same `data-id` value as in the original `content`. Its contents may be different (tag,
     * attributes, entire subtree may change). Also modified elements don't have to be a top level elements
     * from the original `content`, which means the `contentPart` may not keep the original structure
     * or nesting order of the elements.
     *
     * Each type of modification is handled differently when merged into the `content`:
     *
     * 1. Modified elements (with `data-id` attribute with a value which exists in the `content`) replaces
     * the existing element with the same `data-id`, without changing its position in the `content`.
     * 2. Removed elements (marked with a special "removed comment") are removed from the `content` based
     * on the `data-id` comment value.
     * 3. New elements (marked with `data-id="new-element"`) are inserted into the `content` based on their
     * relative position to other nodes in the `contentPart`. The detailed rules for inserting new elements are
     * described in the next section.
     * 4. Invalid elements (elements with `data-id` attribute which value is not present in the `content`,
     * or without `data-id` attribute at all) are ignored and not inserted into the `content`.
     *
     * The position on which new elements from the `contentPart` are inserted into the `content`
     * is determined based on the reference nodes. The reference node is:
     *
     * - A node in the `contentPart` which also exists in the `content` with the same `data-id` attribute value.
     * - A special "removed comment" node which points to the existing element in the `content`.
     * - A special "existing document" comment node which implicates that there should be any content
     * before/after the new element position on which it is inserted into the `content`.
     *
     * The algorithm operates on the top level nodes of the `contentPart` which means only direct root children
     * of the `contentPart` are processed. Nested elements are not processed directly, but as a children
     * of the top level nodes they are included in the merge process.
     *
     * Note: "existing document" comments and "removed" comments are only meaningful at the top level of the `contentPart`.
     * If an existing (kept) element contains such comments inside its children, they are ignored (stripped) — the entire
     * element is replaced with the `contentPart` version as-is. This means that partial replacement inside a kept parent
     * is not supported: the LLM must provide the full content of any existing element it returns.
     *
     * The algorithm iterates over the `contentPart` top level nodes and tries to find a position (directly or via reference node)
     * for any element which should be merged into the `content`.
     *
     * Example 1: Modified element.
     *
     * ```html
     * // content:
     * <p data-id="1">Foo</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     *
     * // contentPart:
     * <p data-id="1">New content</p>
     *
     * // merge result:
     * <p data-id="1">New content</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     * ```
     *
     * Example 2: Multiple modified element.
     *
     * ```html
     * // content:
     * <p data-id="1">Foo</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     *
     * // contentPart:
     * <p data-id="1">New content</p>
     * <!-- existing document !-->
     * <p data-id="3">Another <strong>change</strong></p>
     *
     * // merge result:
     * <p data-id="1">New content</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Another <strong>change</strong></p>
     * ```
     *
     * Example 3: Removed element.
     *
     * ```html
     * // content:
     * <p data-id="1">Foo</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     *
     * // contentPart:
     * <!-- removed data-id="1" !-->
     *
     * // merge result:
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     * ```
     *
     * Example 4: New element with reference node before.
     *
     * ```html
     * // content:
     * <p data-id="1">Foo</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     *
     * // contentPart:
     * <p data-id="1">Foo</p>
     * <p data-id="new-element">New element</p>
     * <!-- existing document !-->
     *
     * // merge result:
     * <p data-id="1">Foo</p>
     * <p data-id="new-id">New element</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     * ```
     *
     * Example 5: New element with reference node after.
     *
     * ```html
     * // content:
     * <p data-id="1">Foo</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     *
     * // contentPart:
     * <!-- existing document !-->
     * <p data-id="new-element">New element</p>
     * <p data-id="3">Cup</p>
     *
     * // merge result:
     * <p data-id="1">Foo</p>
     * <p data-id="2">Bar</p>
     * <p data-id="new-id">New element</p>
     * <p data-id="3">Cup</p>
     * ```
     *
     * Example 6: New element at the start of the content.
     *
     * ```html
     * // content:
     * <p data-id="1">Foo</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     *
     * // contentPart:
     * <p data-id="new-element">New element</p>
     * <!-- existing document !-->
     *
     * // merge result:
     * <p data-id="new-id">New element</p>
     * <p data-id="1">Foo</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     * ```
     *
     * Example 7: New element at the end of the content.
     *
     * ```html
     * // content:
     * <p data-id="1">Foo</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     *
     * // contentPart:
     * <!-- existing document !-->
     * <p data-id="new-element">New element</p>
     *
     * // merge result:
     * <p data-id="1">Foo</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     * <p data-id="new-id">New element</p>
     * ```
     *
     * Example 8: New element after removed element.
     *
     * ```html
     * // content:
     * <p data-id="1">Foo</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     *
     * // contentPart:
     * <!-- removed data-id="2" !-->
     * <p data-id="new-element">New element</p>
     *
     * // merge result:
     * <p data-id="1">Foo</p>
     * <p data-id="new-id">New element</p>
     * <p data-id="3">Cup</p>
     * ```
     *
     * Example 9: Wrapped element.
     *
     * ```html
     * // content:
     * <p data-id="1">Foo</p>
     * <p data-id="2">Bar</p>
     * <p data-id="3">Cup</p>
     *
     * // contentPart:
     * <p data-id="1">Foo</p>
     * <div data-id="new-element">
     *   <p data-id="2">Bar</p>
     * </div>
     *
     * // merge result:
     * <p data-id="1">Foo</p>
     * <div data-id="new-id">
     *   <p data-id="2">Bar</p>
     * </div>
     * <p data-id="3">Cup</p>
     * ```
     *
     * Example 10: Modification of nested elements.
     *
     * ```html
     * // content:
     * <table data-id="1">
     *   <tr data-id="11">
     *     <td data-id="111">Foo</td>
     *   </tr>
     *   <tr data-id="12">
     *     <td data-id="121">Bar</td>
     *     <td data-id="122">Cup</td>
     *   </tr>
     * </table>
     *
     * // contentPart:
     * <tr data-id="12">
     *   <td data-id="new-element">New content</td>
     * </tr>
     *
     * // merge result:
     * <table data-id="1">
     *   <tr data-id="11">
     *     <td data-id="111">Foo</td>
     *   </tr>
     *   <tr data-id="12">
     *     <td data-id="new-id">New content</td>
     *   </tr>
     * </table>
     * ```
     *
     * Since existing elements are either modifications or only reference nodes in the `contentPart`, there is an additional logic
     * for checking if such elements are identical to the existing ones in the `content`. This way the algorithm can correctly detect
     * if an existing element was modified or not.
     *
     * Additionally, this method supports the following options:
     * - `cutAfterLastChange`: if set to `true`, the content will be cut after the last modified element.
     * - `markUnstableElements`: if set to `true`, the function will mark all elements starting from the last tag element
     * as unstable by adding a special 'data-unstable' attribute to them.
     * - `markUnstableElementsDepth`: if set, it will determine how deep the unstable marking should go.
     */
    merge(contentPart: Document, parsedContent: Document, options?: MergeOptions): MergeResult;
}
export type MergeResult = {
    parsedContent: Document;
    newNodeIds: Array<string>;
    modifiedNodeIds: Array<string>;
    removedNodeIds: Array<string>;
    /**
     * Maps each newly-inserted top-level node id to the `data-id` of the existing element the merger picked as its anchor (the
     * preceding or following existing element the AI's stream attached the new node to). Lets consumers route a new node to the
     * correct source document when neighbour positions in the merged tree are ambiguous — e.g. "prepend at the start of doc B"
     * produces the same merged tree as "append at the end of doc A", but only the AI's anchor disambiguates which doc owns the new
     * node.
     */
    newAnchorIds: ReadonlyMap<string, string>;
};
export type MergeOptions = {
    cutAfterLastChange?: boolean;
    markUnstableElements?: boolean;
    markUnstableElementsDepth?: number;
    replaceRemovedWith?: Element;
};
export {};
