UNPKG

@ckeditor/ckeditor5-engine

Version:

The editing engine of CKEditor 5 – the best browser-based rich text editor.

79 lines (78 loc) 3.85 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 */ import { ModelRange } from '../range.js'; import { type Model } from '../model.js'; import { type ModelSchema } from '../schema.js'; /** * Injects selection post-fixer to the model. * * The role of the selection post-fixer is to ensure that the selection is in a correct place * after a {@link module:engine/model/model~Model#change `change()`} block was executed. * * The correct position means that: * * * All collapsed selection ranges are in a place where the {@link module:engine/model/schema~ModelSchema} * allows a `$text`. * * None of the selection's non-collapsed ranges crosses a {@link module:engine/model/schema~ModelSchema#isLimit limit element} * boundary (a range must be rooted within one limit element). * * Only {@link module:engine/model/schema~ModelSchema#isSelectable selectable elements} can be selected from the outside * (e.g. `[<paragraph>foo</paragraph>]` is invalid). This rule applies independently to both selection ends, so this * selection is correct: `<paragraph>f[oo</paragraph><imageBlock></imageBlock>]`. * * If the position is not correct, the post-fixer will automatically correct it. * * ## Fixing a non-collapsed selection * * See as an example a selection that starts in a P1 element and ends inside the text of a TD element * (`[` and `]` are range boundaries and `(l)` denotes an element defined as `isLimit=true`): * * ``` * root * |- element P1 * | |- "foo" root * |- element TABLE (l) P1 TABLE P2 * | |- element TR (l) f o[o TR TR b a r * | | |- element TD (l) TD TD * | | |- "aaa" a]a a b b b * | |- element TR (l) * | | |- element TD (l) || * | | |- "bbb" || * |- element P2 VV * | |- "bar" * root * P1 TABLE] P2 * f o[o TR TR b a r * TD TD * a a a b b b * ``` * * In the example above, the TABLE, TR and TD are defined as `isLimit=true` in the schema. The range which is not contained within * a single limit element must be expanded to select the outermost limit element. The range end is inside the text node of the TD element. * As the TD element is a child of the TR and TABLE elements, where both are defined as `isLimit=true` in the schema, the range must be * expanded to select the whole TABLE element. * * **Note** If the selection contains multiple ranges, the method returns a minimal set of ranges that are not intersecting after expanding * them to select `isLimit=true` elements. * * @internal */ export declare function injectSelectionPostFixer(model: Model): void; /** * Tries fixing a range if it's incorrect. * * **Note:** This helper is used by the selection post-fixer and to fix the `beforeinput` target ranges. * * @returns Returns fixed range or null if range is valid. * @internal */ export declare function tryFixingRange(range: ModelRange, schema: ModelSchema): ModelRange | null; /** * Returns a minimal non-intersecting array of ranges without duplicates. * * @param ranges Ranges to merge. * @returns Array of unique and non-intersecting ranges. * @internal */ export declare function mergeIntersectingRanges(ranges: Array<ModelRange>): Array<ModelRange>;