{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/model/documentselection.js"],"names":["storePrefix","DocumentSelection","doc","Object","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_classCallCheck_js__WEBPACK_IMPORTED_MODULE_21__","this","_selection","LiveSelection","delegate","to","isCollapsed","anchor","focus","rangeCount","hasOwnRange","isBackward","isGravityOverridden","markers","_ranges","getRanges","getFirstPosition","getLastPosition","getFirstRange","getLastRange","getSelectedBlocks","getSelectedElement","element","containsEntireContent","destroy","getAttributeKeys","getAttributes","key","getAttribute","hasAttribute","_updateMarkers","_updateAttributes","prefixOrName","observeMarkers","type","itemOrPosition","offset","setFocus","selectable","placeOrOffset","options","setTo","value","setAttribute","removeAttribute","_getStoredAttributes","overrideGravity","uid","restoreGravity","startsWith","mix","EmitterMixin","_this","_super","call","Collection","idProperty","_model","model","_document","_attributePriority","Map","_selectionRestorePosition","_hasChangedRange","_overriddenGravityRegister","Set","_observedMarkers","listenTo","evt","args","operation","isDocumentOperation","length","_fixGraveyardSelection","fire","directChange","priority","on","_step","_iterator","_createForOfIteratorHelper","s","n","done","range","_validateSelectionRange","CKEditorError","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_assertThisInitialized_js__WEBPACK_IMPORTED_MODULE_14__","err","e","f","marker","oldRange","newRange","_updateMarker","batch","clearAttributesStoredInElement","_getDefaultRange","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_get_js__WEBPACK_IMPORTED_MODULE_15__","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_getPrototypeOf_js__WEBPACK_IMPORTED_MODULE_18__","prototype","start","end","size","i","detach","stopListening","regeneratorRuntime","wrap","_context","prev","next","delegateYield","stop","optionsOrPlaceOrOffset","_setAttribute","attributeKeys","_removeAttribute","overrideUid","add","has","delete","pop","liveRange","_prepareRange","push","_this2","_checkRange","root","graveyard","LiveRange","fromRange","data","deletionPosition","index","indexOf","splice","_step2","changed","_iterator2","markerGroup","name","split","_step3","markerRange","getRange","_iterator3","selectionRange","containsRange","oldMarkers","Array","from","_i","_markers","_i2","_Array$from","includes","remove","hasMarker","_step4","contained","_iterator4","clearAll","newAttributes","toMap","_getSurroundingAttributes","oldAttributes","_attrs","_step5","_iterator5","_step5$value","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_slicedToArray_js__WEBPACK_IMPORTED_MODULE_4__","_setAttributesTo","_step6","_iterator6","_step6$value","newKey","newValue","get","_step7","_iterator7","_step7$value","oldKey","arguments","undefined","oldValue","set","attrs","_step8","_iterator8","_step8$value","_step9","_iterator9","_step9$value","gotAdded","selectionParent","_iterator10","_step10","realKey","_context2","parent","isEmpty","substr","t0","finish","position","schema","nodeBefore","textNode","nodeAfter","getAttrsIfCharacter","node","isInline","previousSibling","nextSibling","_step11","_iterator11","item","is","isObject","getNearestSelectionRange","_pushRange","Selection","TextProxy","Text","_step12","differ","document","_iterator12","getChanges","_loop","entry","changeParent","isNoLongerEmpty","maxOffset","enqueueChange","writer","_step13","storedAttributes","filter","_iterator13"],"mappings":"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","file":"js/chunk-2d216c02.bff1afa2.js","sourcesContent":["/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module engine/model/documentselection\n */\n\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\n\nimport Selection from './selection';\nimport LiveRange from './liverange';\nimport Text from './text';\nimport TextProxy from './textproxy';\nimport toMap from '@ckeditor/ckeditor5-utils/src/tomap';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport uid from '@ckeditor/ckeditor5-utils/src/uid';\n\nconst storePrefix = 'selection:';\n\n/**\n * `DocumentSelection` is a special selection which is used as the\n * {@link module:engine/model/document~Document#selection document's selection}.\n * There can be only one instance of `DocumentSelection` per document.\n *\n * Document selection can only be changed by using the {@link module:engine/model/writer~Writer} instance\n * inside the {@link module:engine/model/model~Model#change `change()`} block, as it provides a secure way to modify model.\n *\n * `DocumentSelection` is automatically updated upon changes in the {@link module:engine/model/document~Document document}\n * to always contain valid ranges. Its attributes are inherited from the text unless set explicitly.\n *\n * Differences between {@link module:engine/model/selection~Selection} and `DocumentSelection` are:\n * * there is always a range in `DocumentSelection` - even if no ranges were added there is a \"default range\"\n * present in the selection,\n * * ranges added to this selection updates automatically when the document changes,\n * * attributes of `DocumentSelection` are updated automatically according to selection ranges.\n *\n * Since `DocumentSelection` uses {@link module:engine/model/liverange~LiveRange live ranges}\n * and is updated when {@link module:engine/model/document~Document document}\n * changes, it cannot be set on {@link module:engine/model/node~Node nodes}\n * that are inside {@link module:engine/model/documentfragment~DocumentFragment document fragment}.\n * If you need to represent a selection in document fragment,\n * use {@link module:engine/model/selection~Selection Selection class} instead.\n *\n * @mixes module:utils/emittermixin~EmitterMixin\n */\nexport default class DocumentSelection {\n\t/**\n\t * Creates an empty live selection for given {@link module:engine/model/document~Document}.\n\t *\n\t * @param {module:engine/model/document~Document} doc Document which owns this selection.\n\t */\n\tconstructor( doc ) {\n\t\t/**\n\t\t * Selection used internally by that class (`DocumentSelection` is a proxy to that selection).\n\t\t *\n\t\t * @protected\n\t\t */\n\t\tthis._selection = new LiveSelection( doc );\n\n\t\tthis._selection.delegate( 'change:range' ).to( this );\n\t\tthis._selection.delegate( 'change:attribute' ).to( this );\n\t\tthis._selection.delegate( 'change:marker' ).to( this );\n\t}\n\n\t/**\n\t * Returns whether the selection is collapsed. Selection is collapsed when there is exactly one range which is\n\t * collapsed.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isCollapsed() {\n\t\treturn this._selection.isCollapsed;\n\t}\n\n\t/**\n\t * Selection anchor. Anchor may be described as a position where the most recent part of the selection starts.\n\t * Together with {@link #focus} they define the direction of selection, which is important\n\t * when expanding/shrinking selection. Anchor is always {@link module:engine/model/range~Range#start start} or\n\t * {@link module:engine/model/range~Range#end end} position of the most recently added range.\n\t *\n\t * Is set to `null` if there are no ranges in selection.\n\t *\n\t * @see #focus\n\t * @readonly\n\t * @type {module:engine/model/position~Position|null}\n\t */\n\tget anchor() {\n\t\treturn this._selection.anchor;\n\t}\n\n\t/**\n\t * Selection focus. Focus is a position where the selection ends.\n\t *\n\t * Is set to `null` if there are no ranges in selection.\n\t *\n\t * @see #anchor\n\t * @readonly\n\t * @type {module:engine/model/position~Position|null}\n\t */\n\tget focus() {\n\t\treturn this._selection.focus;\n\t}\n\n\t/**\n\t * Returns number of ranges in selection.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget rangeCount() {\n\t\treturn this._selection.rangeCount;\n\t}\n\n\t/**\n\t * Describes whether `Documentselection` has own range(s) set, or if it is defaulted to\n\t * {@link module:engine/model/document~Document#_getDefaultRange document's default range}.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget hasOwnRange() {\n\t\treturn this._selection.hasOwnRange;\n\t}\n\n\t/**\n\t * Specifies whether the {@link #focus}\n\t * precedes {@link #anchor}.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isBackward() {\n\t\treturn this._selection.isBackward;\n\t}\n\n\t/**\n\t * Describes whether the gravity is overridden (using {@link module:engine/model/writer~Writer#overrideSelectionGravity}) or not.\n\t *\n\t * Note that the gravity remains overridden as long as will not be restored the same number of times as it was overridden.\n\t *\n\t * @readonly\n\t * @returns {Boolean}\n\t */\n\tget isGravityOverridden() {\n\t\treturn this._selection.isGravityOverridden;\n\t}\n\n\t/**\n\t * A collection of selection {@link module:engine/model/markercollection~Marker markers}.\n\t * Marker is a selection marker when selection range is inside the marker range.\n\t *\n\t * **Note**: Only markers from {@link ~DocumentSelection#observeMarkers observed markers groups} are collected.\n\t *\n\t * @readonly\n\t * @type {module:utils/collection~Collection}\n\t */\n\tget markers() {\n\t\treturn this._selection.markers;\n\t}\n\n\t/**\n\t * Used for the compatibility with the {@link module:engine/model/selection~Selection#isEqual} method.\n\t *\n\t * @protected\n\t */\n\tget _ranges() {\n\t\treturn this._selection._ranges;\n\t}\n\n\t/**\n\t * Returns an iterable that iterates over copies of selection ranges.\n\t *\n\t * @returns {Iterable.}\n\t */\n\tgetRanges() {\n\t\treturn this._selection.getRanges();\n\t}\n\n\t/**\n\t * Returns the first position in the selection.\n\t * First position is the position that {@link module:engine/model/position~Position#isBefore is before}\n\t * any other position in the selection.\n\t *\n\t * Returns `null` if there are no ranges in selection.\n\t *\n\t * @returns {module:engine/model/position~Position|null}\n\t */\n\tgetFirstPosition() {\n\t\treturn this._selection.getFirstPosition();\n\t}\n\n\t/**\n\t * Returns the last position in the selection.\n\t * Last position is the position that {@link module:engine/model/position~Position#isAfter is after}\n\t * any other position in the selection.\n\t *\n\t * Returns `null` if there are no ranges in selection.\n\t *\n\t * @returns {module:engine/model/position~Position|null}\n\t */\n\tgetLastPosition() {\n\t\treturn this._selection.getLastPosition();\n\t}\n\n\t/**\n\t * Returns a copy of the first range in the selection.\n\t * First range is the one which {@link module:engine/model/range~Range#start start} position\n\t * {@link module:engine/model/position~Position#isBefore is before} start position of all other ranges\n\t * (not to confuse with the first range added to the selection).\n\t *\n\t * Returns `null` if there are no ranges in selection.\n\t *\n\t * @returns {module:engine/model/range~Range|null}\n\t */\n\tgetFirstRange() {\n\t\treturn this._selection.getFirstRange();\n\t}\n\n\t/**\n\t * Returns a copy of the last range in the selection.\n\t * Last range is the one which {@link module:engine/model/range~Range#end end} position\n\t * {@link module:engine/model/position~Position#isAfter is after} end position of all other ranges (not to confuse with the range most\n\t * recently added to the selection).\n\t *\n\t * Returns `null` if there are no ranges in selection.\n\t *\n\t * @returns {module:engine/model/range~Range|null}\n\t */\n\tgetLastRange() {\n\t\treturn this._selection.getLastRange();\n\t}\n\n\t/**\n\t * Gets elements of type {@link module:engine/model/schema~Schema#isBlock \"block\"} touched by the selection.\n\t *\n\t * This method's result can be used for example to apply block styling to all blocks covered by this selection.\n\t *\n\t * **Note:** `getSelectedBlocks()` returns blocks that are nested in other non-block elements\n\t * but will not return blocks nested in other blocks.\n\t *\n\t * In this case the function will return exactly all 3 paragraphs (note: `
` is not a block itself):\n\t *\n\t *\t\t[a\n\t *\t\t
\n\t *\t\t\tb\n\t *\t\t
\n\t *\t\tc]d\n\t *\n\t * In this case the paragraph will also be returned, despite the collapsed selection:\n\t *\n\t *\t\t[]a\n\t *\n\t * In such a scenario, however, only blocks A, B & E will be returned as blocks C & D are nested in block B:\n\t *\n\t *\t\t[\n\t *\t\t\n\t *\t\t\t\n\t *\t\t\t\n\t *\t\t\n\t *\t\t]\n\t *\n\t * If the selection is inside a block all the inner blocks (A & B) are returned:\n\t *\n\t * \t\t\n\t *\t\t\t[a\n\t * \t\t\tb]\n\t * \t\t\n\t *\n\t * **Special case**: If a selection ends at the beginning of a block, that block is not returned as from user perspective\n\t * this block wasn't selected. See [#984](https://github.com/ckeditor/ckeditor5-engine/issues/984) for more details.\n\t *\n\t *\t\t[a\n\t *\t\tb\n\t *\t\t]c // this block will not be returned\n\t *\n\t * @returns {Iterable.}\n\t */\n\tgetSelectedBlocks() {\n\t\treturn this._selection.getSelectedBlocks();\n\t}\n\n\t/**\n\t * Returns the selected element. {@link module:engine/model/element~Element Element} is considered as selected if there is only\n\t * one range in the selection, and that range contains exactly one element.\n\t * Returns `null` if there is no selected element.\n\t *\n\t * @returns {module:engine/model/element~Element|null}\n\t */\n\tgetSelectedElement() {\n\t\treturn this._selection.getSelectedElement();\n\t}\n\n\t/**\n\t * Checks whether the selection contains the entire content of the given element. This means that selection must start\n\t * at a position {@link module:engine/model/position~Position#isTouching touching} the element's start and ends at position\n\t * touching the element's end.\n\t *\n\t * By default, this method will check whether the entire content of the selection's current root is selected.\n\t * Useful to check if e.g. the user has just pressed Ctrl + A.\n\t *\n\t * @param {module:engine/model/element~Element} [element=this.anchor.root]\n\t * @returns {Boolean}\n\t */\n\tcontainsEntireContent( element ) {\n\t\treturn this._selection.containsEntireContent( element );\n\t}\n\n\t/**\n\t * Unbinds all events previously bound by document selection.\n\t */\n\tdestroy() {\n\t\tthis._selection.destroy();\n\t}\n\n\t/**\n\t * Returns iterable that iterates over this selection's attribute keys.\n\t *\n\t * @returns {Iterable.}\n\t */\n\tgetAttributeKeys() {\n\t\treturn this._selection.getAttributeKeys();\n\t}\n\n\t/**\n\t * Returns iterable that iterates over this selection's attributes.\n\t *\n\t * Attributes are returned as arrays containing two items. First one is attribute key and second is attribute value.\n\t * This format is accepted by native `Map` object and also can be passed in `Node` constructor.\n\t *\n\t * @returns {Iterable.<*>}\n\t */\n\tgetAttributes() {\n\t\treturn this._selection.getAttributes();\n\t}\n\n\t/**\n\t * Gets an attribute value for given key or `undefined` if that attribute is not set on the selection.\n\t *\n\t * @param {String} key Key of attribute to look for.\n\t * @returns {*} Attribute value or `undefined`.\n\t */\n\tgetAttribute( key ) {\n\t\treturn this._selection.getAttribute( key );\n\t}\n\n\t/**\n\t * Checks if the selection has an attribute for given key.\n\t *\n\t * @param {String} key Key of attribute to check.\n\t * @returns {Boolean} `true` if attribute with given key is set on selection, `false` otherwise.\n\t */\n\thasAttribute( key ) {\n\t\treturn this._selection.hasAttribute( key );\n\t}\n\n\t/**\n\t * Refreshes selection attributes and markers according to the current position in the model.\n\t */\n\trefresh() {\n\t\tthis._selection._updateMarkers();\n\t\tthis._selection._updateAttributes( false );\n\t}\n\n\t/**\n\t * Registers a marker group prefix or a marker name to be collected in the\n\t * {@link ~DocumentSelection#markers selection markers collection}.\n\t *\n\t * See also {@link module:engine/model/markercollection~MarkerCollection#getMarkersGroup `MarkerCollection#getMarkersGroup()`}.\n\t *\n\t * @param {String} prefixOrName The marker group prefix or marker name.\n\t */\n\tobserveMarkers( prefixOrName ) {\n\t\tthis._selection.observeMarkers( prefixOrName );\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t *\t\tselection.is( 'selection' ); // -> true\n\t *\t\tselection.is( 'documentSelection' ); // -> true\n\t *\t\tselection.is( 'model:selection' ); // -> true\n\t *\t\tselection.is( 'model:documentSelection' ); // -> true\n\t *\n\t *\t\tselection.is( 'view:selection' ); // -> false\n\t *\t\tselection.is( 'element' ); // -> false\n\t *\t\tselection.is( 'node' ); // -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type === 'selection' ||\n\t\t\ttype == 'model:selection' ||\n\t\t\ttype == 'documentSelection' ||\n\t\t\ttype == 'model:documentSelection';\n\t}\n\n\t/**\n\t * Moves {@link module:engine/model/documentselection~DocumentSelection#focus} to the specified location.\n\t * Should be used only within the {@link module:engine/model/writer~Writer#setSelectionFocus} method.\n\t *\n\t * The location can be specified in the same form as\n\t * {@link module:engine/model/writer~Writer#createPositionAt writer.createPositionAt()} parameters.\n\t *\n\t * @see module:engine/model/writer~Writer#setSelectionFocus\n\t * @protected\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/model/item~Item model item}.\n\t */\n\t_setFocus( itemOrPosition, offset ) {\n\t\tthis._selection.setFocus( itemOrPosition, offset );\n\t}\n\n\t/**\n\t * Sets this selection's ranges and direction to the specified location based on the given\n\t * {@link module:engine/model/selection~Selectable selectable}.\n\t * Should be used only within the {@link module:engine/model/writer~Writer#setSelection} method.\n\t *\n\t * @see module:engine/model/writer~Writer#setSelection\n\t * @protected\n\t * @param {module:engine/model/selection~Selectable} selectable\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t */\n\t_setTo( selectable, placeOrOffset, options ) {\n\t\tthis._selection.setTo( selectable, placeOrOffset, options );\n\t}\n\n\t/**\n\t * Sets attribute on the selection. If attribute with the same key already is set, it's value is overwritten.\n\t * Should be used only within the {@link module:engine/model/writer~Writer#setSelectionAttribute} method.\n\t *\n\t * @see module:engine/model/writer~Writer#setSelectionAttribute\n\t * @protected\n\t * @param {String} key Key of the attribute to set.\n\t * @param {*} value Attribute value.\n\t */\n\t_setAttribute( key, value ) {\n\t\tthis._selection.setAttribute( key, value );\n\t}\n\n\t/**\n\t * Removes an attribute with given key from the selection.\n\t * If the given attribute was set on the selection, fires the {@link module:engine/model/selection~Selection#event:change:range}\n\t * event with removed attribute key.\n\t * Should be used only within the {@link module:engine/model/writer~Writer#removeSelectionAttribute} method.\n\t *\n\t * @see module:engine/model/writer~Writer#removeSelectionAttribute\n\t * @protected\n\t * @param {String} key Key of the attribute to remove.\n\t */\n\t_removeAttribute( key ) {\n\t\tthis._selection.removeAttribute( key );\n\t}\n\n\t/**\n\t * Returns an iterable that iterates through all selection attributes stored in current selection's parent.\n\t *\n\t * @protected\n\t * @returns {Iterable.<*>}\n\t */\n\t_getStoredAttributes() {\n\t\treturn this._selection._getStoredAttributes();\n\t}\n\n\t/**\n\t * Temporarily changes the gravity of the selection from the left to the right.\n\t *\n\t * The gravity defines from which direction the selection inherits its attributes. If it's the default left\n\t * gravity, the selection (after being moved by the the user) inherits attributes from its left hand side.\n\t * This method allows to temporarily override this behavior by forcing the gravity to the right.\n\t *\n\t * It returns an unique identifier which is required to restore the gravity. It guarantees the symmetry\n\t * of the process.\n\t *\n\t * @see module:engine/model/writer~Writer#overrideSelectionGravity\n\t * @protected\n\t * @returns {String} The unique id which allows restoring the gravity.\n\t */\n\t_overrideGravity() {\n\t\treturn this._selection.overrideGravity();\n\t}\n\n\t/**\n\t * Restores the {@link ~DocumentSelection#_overrideGravity overridden gravity}.\n\t *\n\t * Restoring the gravity is only possible using the unique identifier returned by\n\t * {@link ~DocumentSelection#_overrideGravity}. Note that the gravity remains overridden as long as won't be restored\n\t * the same number of times it was overridden.\n\t *\n\t * @see module:engine/model/writer~Writer#restoreSelectionGravity\n\t * @protected\n\t * @param {String} uid The unique id returned by {@link #_overrideGravity}.\n\t */\n\t_restoreGravity( uid ) {\n\t\tthis._selection.restoreGravity( uid );\n\t}\n\n\t/**\n\t * Generates and returns an attribute key for selection attributes store, basing on original attribute key.\n\t *\n\t * @protected\n\t * @param {String} key Attribute key to convert.\n\t * @returns {String} Converted attribute key, applicable for selection store.\n\t */\n\tstatic _getStoreAttributeKey( key ) {\n\t\treturn storePrefix + key;\n\t}\n\n\t/**\n\t * Checks whether the given attribute key is an attribute stored on an element.\n\t *\n\t * @protected\n\t * @param {String} key\n\t * @returns {Boolean}\n\t */\n\tstatic _isStoreAttributeKey( key ) {\n\t\treturn key.startsWith( storePrefix );\n\t}\n}\n\nmix( DocumentSelection, EmitterMixin );\n\n/**\n * Fired when selection range(s) changed.\n *\n * @event change:range\n * @param {Boolean} directChange In case of {@link module:engine/model/selection~Selection} class it is always set\n * to `true` which indicates that the selection change was caused by a direct use of selection's API.\n * The {@link module:engine/model/documentselection~DocumentSelection}, however, may change because its position\n * was directly changed through the {@link module:engine/model/writer~Writer writer} or because its position was\n * changed because the structure of the model has been changed (which means an indirect change).\n * The indirect change does not occur in case of normal (detached) selections because they are \"static\" (as \"not live\")\n * which mean that they are not updated once the document changes.\n */\n\n/**\n * Fired when selection attribute changed.\n *\n * @event change:attribute\n * @param {Boolean} directChange In case of {@link module:engine/model/selection~Selection} class it is always set\n * to `true` which indicates that the selection change was caused by a direct use of selection's API.\n * The {@link module:engine/model/documentselection~DocumentSelection}, however, may change because its attributes\n * were directly changed through the {@link module:engine/model/writer~Writer writer} or because its position was\n * changed in the model and its attributes were refreshed (which means an indirect change).\n * The indirect change does not occur in case of normal (detached) selections because they are \"static\" (as \"not live\")\n * which mean that they are not updated once the document changes.\n * @param {Array.} attributeKeys Array containing keys of attributes that changed.\n */\n\n/**\n * Fired when selection marker(s) changed.\n *\n * @event change:marker\n * @param {Boolean} directChange This is always set to `false` in case of `change:marker` event as there is no possibility\n * to change markers directly through {@link module:engine/model/documentselection~DocumentSelection} API.\n * See also {@link module:engine/model/documentselection~DocumentSelection#event:change:range} and\n * {@link module:engine/model/documentselection~DocumentSelection#event:change:attribute}.\n * @param {Array.} oldMarkers Markers in which the selection was before the change.\n */\n\n// `LiveSelection` is used internally by {@link module:engine/model/documentselection~DocumentSelection} and shouldn't be used directly.\n//\n// LiveSelection` is automatically updated upon changes in the {@link module:engine/model/document~Document document}\n// to always contain valid ranges. Its attributes are inherited from the text unless set explicitly.\n//\n// Differences between {@link module:engine/model/selection~Selection} and `LiveSelection` are:\n// * there is always a range in `LiveSelection` - even if no ranges were added there is a \"default range\"\n// present in the selection,\n// * ranges added to this selection updates automatically when the document changes,\n// * attributes of `LiveSelection` are updated automatically according to selection ranges.\n//\n// @extends module:engine/model/selection~Selection\n//\nclass LiveSelection extends Selection {\n\t// Creates an empty live selection for given {@link module:engine/model/document~Document}.\n\t// @param {module:engine/model/document~Document} doc Document which owns this selection.\n\tconstructor( doc ) {\n\t\tsuper();\n\n\t\t// List of selection markers.\n\t\t// Marker is a selection marker when selection range is inside the marker range.\n\t\t//\n\t\t// @type {module:utils/collection~Collection}\n\t\tthis.markers = new Collection( { idProperty: 'name' } );\n\n\t\t// Document which owns this selection.\n\t\t//\n\t\t// @protected\n\t\t// @member {module:engine/model/model~Model}\n\t\tthis._model = doc.model;\n\n\t\t// Document which owns this selection.\n\t\t//\n\t\t// @protected\n\t\t// @member {module:engine/model/document~Document}\n\t\tthis._document = doc;\n\n\t\t// Keeps mapping of attribute name to priority with which the attribute got modified (added/changed/removed)\n\t\t// last time. Possible values of priority are: `'low'` and `'normal'`.\n\t\t//\n\t\t// Priorities are used by internal `LiveSelection` mechanisms. All attributes set using `LiveSelection`\n\t\t// attributes API are set with `'normal'` priority.\n\t\t//\n\t\t// @private\n\t\t// @member {Map} module:engine/model/liveselection~LiveSelection#_attributePriority\n\t\tthis._attributePriority = new Map();\n\n\t\t// Position to which the selection should be set if the last selection range was moved to the graveyard.\n\t\t// @private\n\t\t// @member {module:engine/model/position~Position} module:engine/model/liveselection~LiveSelection#_selectionRestorePosition\n\t\tthis._selectionRestorePosition = null;\n\n\t\t// Flag that informs whether the selection ranges have changed. It is changed on true when `LiveRange#change:range` event is fired.\n\t\t// @private\n\t\t// @member {Array} module:engine/model/liveselection~LiveSelection#_hasChangedRange\n\t\tthis._hasChangedRange = false;\n\n\t\t// Each overriding gravity adds an UID to the set and each removal removes it.\n\t\t// Gravity is overridden when there's at least one UID in the set.\n\t\t// Gravity is restored when the set is empty.\n\t\t// This is to prevent conflicts when gravity is overridden by more than one feature at the same time.\n\t\t// @private\n\t\t// @type {Set}\n\t\tthis._overriddenGravityRegister = new Set();\n\n\t\t// Prefixes of marker names that should affect `LiveSelection#markers` collection.\n\t\t// @private\n\t\t// @type {Set}\n\t\tthis._observedMarkers = new Set();\n\n\t\t// Ensure selection is correct after each operation.\n\t\tthis.listenTo( this._model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( !operation.isDocumentOperation || operation.type == 'marker' || operation.type == 'rename' || operation.type == 'noop' ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Fix selection if the last range was removed from it and we have a position to which we can restore the selection.\n\t\t\tif ( this._ranges.length == 0 && this._selectionRestorePosition ) {\n\t\t\t\tthis._fixGraveyardSelection( this._selectionRestorePosition );\n\t\t\t}\n\n\t\t\t// \"Forget\" the restore position even if it was not \"used\".\n\t\t\tthis._selectionRestorePosition = null;\n\n\t\t\tif ( this._hasChangedRange ) {\n\t\t\t\tthis._hasChangedRange = false;\n\t\t\t\tthis.fire( 'change:range', { directChange: false } );\n\t\t\t}\n\t\t}, { priority: 'lowest' } );\n\n\t\t// Ensure selection is correct and up to date after each range change.\n\t\tthis.on( 'change:range', () => {\n\t\t\tfor ( const range of this.getRanges() ) {\n\t\t\t\tif ( !this._document._validateSelectionRange( range ) ) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Range from {@link module:engine/model/documentselection~DocumentSelection document selection}\n\t\t\t\t\t * starts or ends at incorrect position.\n\t\t\t\t\t *\n\t\t\t\t\t * @error document-selection-wrong-position\n\t\t\t\t\t * @param {module:engine/model/range~Range} range\n\t\t\t\t\t */\n\t\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t\t'document-selection-wrong-position',\n\t\t\t\t\t\tthis,\n\t\t\t\t\t\t{ range }\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\t// Update markers data stored by the selection after each marker change.\n\t\t// This handles only marker changes done through marker operations (not model tree changes).\n\t\tthis.listenTo( this._model.markers, 'update', ( evt, marker, oldRange, newRange ) => {\n\t\t\tthis._updateMarker( marker, newRange );\n\t\t} );\n\n\t\t// Ensure selection is up to date after each change block.\n\t\tthis.listenTo( this._document, 'change', ( evt, batch ) => {\n\t\t\tclearAttributesStoredInElement( this._model, batch );\n\t\t} );\n\t}\n\n\tget isCollapsed() {\n\t\tconst length = this._ranges.length;\n\n\t\treturn length === 0 ? this._document._getDefaultRange().isCollapsed : super.isCollapsed;\n\t}\n\n\tget anchor() {\n\t\treturn super.anchor || this._document._getDefaultRange().start;\n\t}\n\n\tget focus() {\n\t\treturn super.focus || this._document._getDefaultRange().end;\n\t}\n\n\tget rangeCount() {\n\t\treturn this._ranges.length ? this._ranges.length : 1;\n\t}\n\n\t// Describes whether `LiveSelection` has own range(s) set, or if it is defaulted to\n\t// {@link module:engine/model/document~Document#_getDefaultRange document's default range}.\n\t//\n\t// @readonly\n\t// @type {Boolean}\n\tget hasOwnRange() {\n\t\treturn this._ranges.length > 0;\n\t}\n\n\t// When set to `true` then selection attributes on node before the caret won't be taken\n\t// into consideration while updating selection attributes.\n\t//\n\t// @protected\n\t// @type {Boolean}\n\tget isGravityOverridden() {\n\t\treturn !!this._overriddenGravityRegister.size;\n\t}\n\n\t// Unbinds all events previously bound by live selection.\n\tdestroy() {\n\t\tfor ( let i = 0; i < this._ranges.length; i++ ) {\n\t\t\tthis._ranges[ i ].detach();\n\t\t}\n\n\t\tthis.stopListening();\n\t}\n\n\t* getRanges() {\n\t\tif ( this._ranges.length ) {\n\t\t\tyield* super.getRanges();\n\t\t} else {\n\t\t\tyield this._document._getDefaultRange();\n\t\t}\n\t}\n\n\tgetFirstRange() {\n\t\treturn super.getFirstRange() || this._document._getDefaultRange();\n\t}\n\n\tgetLastRange() {\n\t\treturn super.getLastRange() || this._document._getDefaultRange();\n\t}\n\n\tsetTo( selectable, optionsOrPlaceOrOffset, options ) {\n\t\tsuper.setTo( selectable, optionsOrPlaceOrOffset, options );\n\t\tthis._updateAttributes( true );\n\t\tthis._updateMarkers();\n\t}\n\n\tsetFocus( itemOrPosition, offset ) {\n\t\tsuper.setFocus( itemOrPosition, offset );\n\t\tthis._updateAttributes( true );\n\t\tthis._updateMarkers();\n\t}\n\n\tsetAttribute( key, value ) {\n\t\tif ( this._setAttribute( key, value ) ) {\n\t\t\t// Fire event with exact data.\n\t\t\tconst attributeKeys = [ key ];\n\t\t\tthis.fire( 'change:attribute', { attributeKeys, directChange: true } );\n\t\t}\n\t}\n\n\tremoveAttribute( key ) {\n\t\tif ( this._removeAttribute( key ) ) {\n\t\t\t// Fire event with exact data.\n\t\t\tconst attributeKeys = [ key ];\n\t\t\tthis.fire( 'change:attribute', { attributeKeys, directChange: true } );\n\t\t}\n\t}\n\n\toverrideGravity() {\n\t\tconst overrideUid = uid();\n\n\t\t// Remember that another overriding has been requested. It will need to be removed\n\t\t// before the gravity is to be restored.\n\t\tthis._overriddenGravityRegister.add( overrideUid );\n\n\t\tif ( this._overriddenGravityRegister.size === 1 ) {\n\t\t\tthis._updateAttributes( true );\n\t\t}\n\n\t\treturn overrideUid;\n\t}\n\n\trestoreGravity( uid ) {\n\t\tif ( !this._overriddenGravityRegister.has( uid ) ) {\n\t\t\t/**\n\t\t\t * Restoring gravity for an unknown UID is not possible. Make sure you are using a correct\n\t\t\t * UID obtained from the {@link module:engine/model/writer~Writer#overrideSelectionGravity} to restore.\n\t\t\t *\n\t\t\t * @error document-selection-gravity-wrong-restore\n\t\t\t * @param {String} uid The unique identifier returned by\n\t\t\t * {@link module:engine/model/documentselection~DocumentSelection#_overrideGravity}.\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'document-selection-gravity-wrong-restore',\n\t\t\t\tthis,\n\t\t\t\t{ uid }\n\t\t\t);\n\t\t}\n\n\t\tthis._overriddenGravityRegister.delete( uid );\n\n\t\t// Restore gravity only when all overriding have been restored.\n\t\tif ( !this.isGravityOverridden ) {\n\t\t\tthis._updateAttributes( true );\n\t\t}\n\t}\n\n\tobserveMarkers( prefixOrName ) {\n\t\tthis._observedMarkers.add( prefixOrName );\n\t\tthis._updateMarkers();\n\t}\n\n\t_popRange() {\n\t\tthis._ranges.pop().detach();\n\t}\n\n\t_pushRange( range ) {\n\t\tconst liveRange = this._prepareRange( range );\n\n\t\t// `undefined` is returned when given `range` is in graveyard root.\n\t\tif ( liveRange ) {\n\t\t\tthis._ranges.push( liveRange );\n\t\t}\n\t}\n\n\t// Prepares given range to be added to selection. Checks if it is correct,\n\t// converts it to {@link module:engine/model/liverange~LiveRange LiveRange}\n\t// and sets listeners listening to the range's change event.\n\t//\n\t// @private\n\t// @param {module:engine/model/range~Range} range\n\t_prepareRange( range ) {\n\t\tthis._checkRange( range );\n\n\t\tif ( range.root == this._document.graveyard ) {\n\t\t\t// @if CK_DEBUG // console.warn( 'Trying to add a Range that is in the graveyard root. Range rejected.' );\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst liveRange = LiveRange.fromRange( range );\n\n\t\t// If selection range is moved to the graveyard remove it from the selection object.\n\t\t// Also, save some data that can be used to restore selection later, on `Model#applyOperation` event.\n\t\tliveRange.on( 'change:range', ( evt, oldRange, data ) => {\n\t\t\tthis._hasChangedRange = true;\n\n\t\t\tif ( liveRange.root == this._document.graveyard ) {\n\t\t\t\tthis._selectionRestorePosition = data.deletionPosition;\n\n\t\t\t\tconst index = this._ranges.indexOf( liveRange );\n\t\t\t\tthis._ranges.splice( index, 1 );\n\t\t\t\tliveRange.detach();\n\t\t\t}\n\t\t} );\n\n\t\treturn liveRange;\n\t}\n\n\t_updateMarkers() {\n\t\tif ( !this._observedMarkers.size ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst markers = [];\n\t\tlet changed = false;\n\n\t\tfor ( const marker of this._model.markers ) {\n\t\t\tconst markerGroup = marker.name.split( ':', 1 )[ 0 ];\n\n\t\t\tif ( !this._observedMarkers.has( markerGroup ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst markerRange = marker.getRange();\n\n\t\t\tfor ( const selectionRange of this.getRanges() ) {\n\t\t\t\tif ( markerRange.containsRange( selectionRange, !selectionRange.isCollapsed ) ) {\n\t\t\t\t\tmarkers.push( marker );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst oldMarkers = Array.from( this.markers );\n\n\t\tfor ( const marker of markers ) {\n\t\t\tif ( !this.markers.has( marker ) ) {\n\t\t\t\tthis.markers.add( marker );\n\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\n\t\tfor ( const marker of Array.from( this.markers ) ) {\n\t\t\tif ( !markers.includes( marker ) ) {\n\t\t\t\tthis.markers.remove( marker );\n\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\n\t\tif ( changed ) {\n\t\t\tthis.fire( 'change:marker', { oldMarkers, directChange: false } );\n\t\t}\n\t}\n\n\t_updateMarker( marker, markerRange ) {\n\t\tconst markerGroup = marker.name.split( ':', 1 )[ 0 ];\n\n\t\tif ( !this._observedMarkers.has( markerGroup ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet changed = false;\n\n\t\tconst oldMarkers = Array.from( this.markers );\n\t\tconst hasMarker = this.markers.has( marker );\n\n\t\tif ( !markerRange ) {\n\t\t\tif ( hasMarker ) {\n\t\t\t\tthis.markers.remove( marker );\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t} else {\n\t\t\tlet contained = false;\n\n\t\t\tfor ( const selectionRange of this.getRanges() ) {\n\t\t\t\tif ( markerRange.containsRange( selectionRange, !selectionRange.isCollapsed ) ) {\n\t\t\t\t\tcontained = true;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( contained && !hasMarker ) {\n\t\t\t\tthis.markers.add( marker );\n\n\t\t\t\tchanged = true;\n\t\t\t} else if ( !contained && hasMarker ) {\n\t\t\t\tthis.markers.remove( marker );\n\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\n\t\tif ( changed ) {\n\t\t\tthis.fire( 'change:marker', { oldMarkers, directChange: false } );\n\t\t}\n\t}\n\n\t// Updates this selection attributes according to its ranges and the {@link module:engine/model/document~Document model document}.\n\t//\n\t// @protected\n\t// @param {Boolean} clearAll\n\t// @fires change:attribute\n\t_updateAttributes( clearAll ) {\n\t\tconst newAttributes = toMap( this._getSurroundingAttributes() );\n\t\tconst oldAttributes = toMap( this.getAttributes() );\n\n\t\tif ( clearAll ) {\n\t\t\t// If `clearAll` remove all attributes and reset priorities.\n\t\t\tthis._attributePriority = new Map();\n\t\t\tthis._attrs = new Map();\n\t\t} else {\n\t\t\t// If not, remove only attributes added with `low` priority.\n\t\t\tfor ( const [ key, priority ] of this._attributePriority ) {\n\t\t\t\tif ( priority == 'low' ) {\n\t\t\t\t\tthis._attrs.delete( key );\n\t\t\t\t\tthis._attributePriority.delete( key );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._setAttributesTo( newAttributes );\n\n\t\t// Let's evaluate which attributes really changed.\n\t\tconst changed = [];\n\n\t\t// First, loop through all attributes that are set on selection right now.\n\t\t// Check which of them are different than old attributes.\n\t\tfor ( const [ newKey, newValue ] of this.getAttributes() ) {\n\t\t\tif ( !oldAttributes.has( newKey ) || oldAttributes.get( newKey ) !== newValue ) {\n\t\t\t\tchanged.push( newKey );\n\t\t\t}\n\t\t}\n\n\t\t// Then, check which of old attributes got removed.\n\t\tfor ( const [ oldKey ] of oldAttributes ) {\n\t\t\tif ( !this.hasAttribute( oldKey ) ) {\n\t\t\t\tchanged.push( oldKey );\n\t\t\t}\n\t\t}\n\n\t\t// Fire event with exact data (fire only if anything changed).\n\t\tif ( changed.length > 0 ) {\n\t\t\tthis.fire( 'change:attribute', { attributeKeys: changed, directChange: false } );\n\t\t}\n\t}\n\n\t// Internal method for setting `LiveSelection` attribute. Supports attribute priorities (through `directChange`\n\t// parameter).\n\t//\n\t// @private\n\t// @param {String} key Attribute key.\n\t// @param {*} value Attribute value.\n\t// @param {Boolean} [directChange=true] `true` if the change is caused by `Selection` API, `false` if change\n\t// is caused by `Batch` API.\n\t// @returns {Boolean} Whether value has changed.\n\t_setAttribute( key, value, directChange = true ) {\n\t\tconst priority = directChange ? 'normal' : 'low';\n\n\t\tif ( priority == 'low' && this._attributePriority.get( key ) == 'normal' ) {\n\t\t\t// Priority too low.\n\t\t\treturn false;\n\t\t}\n\n\t\tconst oldValue = super.getAttribute( key );\n\n\t\t// Don't do anything if value has not changed.\n\t\tif ( oldValue === value ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis._attrs.set( key, value );\n\n\t\t// Update priorities map.\n\t\tthis._attributePriority.set( key, priority );\n\n\t\treturn true;\n\t}\n\n\t// Internal method for removing `LiveSelection` attribute. Supports attribute priorities (through `directChange`\n\t// parameter).\n\t//\n\t// NOTE: Even if attribute is not present in the selection but is provided to this method, it's priority will\n\t// be changed according to `directChange` parameter.\n\t//\n\t// @private\n\t// @param {String} key Attribute key.\n\t// @param {Boolean} [directChange=true] `true` if the change is caused by `Selection` API, `false` if change\n\t// is caused by `Batch` API.\n\t// @returns {Boolean} Whether attribute was removed. May not be true if such attributes didn't exist or the\n\t// existing attribute had higher priority.\n\t_removeAttribute( key, directChange = true ) {\n\t\tconst priority = directChange ? 'normal' : 'low';\n\n\t\tif ( priority == 'low' && this._attributePriority.get( key ) == 'normal' ) {\n\t\t\t// Priority too low.\n\t\t\treturn false;\n\t\t}\n\n\t\t// Update priorities map.\n\t\tthis._attributePriority.set( key, priority );\n\n\t\t// Don't do anything if value has not changed.\n\t\tif ( !super.hasAttribute( key ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis._attrs.delete( key );\n\n\t\treturn true;\n\t}\n\n\t// Internal method for setting multiple `LiveSelection` attributes. Supports attribute priorities (through\n\t// `directChange` parameter).\n\t//\n\t// @private\n\t// @param {Map.} attrs Iterable object containing attributes to be set.\n\t// @returns {Set.} Changed attribute keys.\n\t_setAttributesTo( attrs ) {\n\t\tconst changed = new Set();\n\n\t\tfor ( const [ oldKey, oldValue ] of this.getAttributes() ) {\n\t\t\t// Do not remove attribute if attribute with same key and value is about to be set.\n\t\t\tif ( attrs.get( oldKey ) === oldValue ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// All rest attributes will be removed so changed attributes won't change .\n\t\t\tthis._removeAttribute( oldKey, false );\n\t\t}\n\n\t\tfor ( const [ key, value ] of attrs ) {\n\t\t\t// Attribute may not be set because of attributes or because same key/value is already added.\n\t\t\tconst gotAdded = this._setAttribute( key, value, false );\n\n\t\t\tif ( gotAdded ) {\n\t\t\t\tchanged.add( key );\n\t\t\t}\n\t\t}\n\n\t\treturn changed;\n\t}\n\n\t// Returns an iterable that iterates through all selection attributes stored in current selection's parent.\n\t//\n\t// @protected\n\t// @returns {Iterable.<*>}\n\t* _getStoredAttributes() {\n\t\tconst selectionParent = this.getFirstPosition().parent;\n\n\t\tif ( this.isCollapsed && selectionParent.isEmpty ) {\n\t\t\tfor ( const key of selectionParent.getAttributeKeys() ) {\n\t\t\t\tif ( key.startsWith( storePrefix ) ) {\n\t\t\t\t\tconst realKey = key.substr( storePrefix.length );\n\n\t\t\t\t\tyield [ realKey, selectionParent.getAttribute( key ) ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Checks model text nodes that are closest to the selection's first position and returns attributes of first\n\t// found element. If there are no text nodes in selection's first position parent, it returns selection\n\t// attributes stored in that parent.\n\t//\n\t// @private\n\t// @returns {Iterable.<*>} Collection of attributes.\n\t_getSurroundingAttributes() {\n\t\tconst position = this.getFirstPosition();\n\t\tconst schema = this._model.schema;\n\n\t\tlet attrs = null;\n\n\t\tif ( !this.isCollapsed ) {\n\t\t\t// 1. If selection is a range...\n\t\t\tconst range = this.getFirstRange();\n\n\t\t\t// ...look for a first character node in that range and take attributes from it.\n\t\t\tfor ( const value of range ) {\n\t\t\t\t// If the item is an object, we don't want to get attributes from its children.\n\t\t\t\tif ( value.item.is( 'element' ) && schema.isObject( value.item ) ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( value.type == 'text' ) {\n\t\t\t\t\tattrs = value.item.getAttributes();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// 2. If the selection is a caret or the range does not contain a character node...\n\n\t\t\tconst nodeBefore = position.textNode ? position.textNode : position.nodeBefore;\n\t\t\tconst nodeAfter = position.textNode ? position.textNode : position.nodeAfter;\n\n\t\t\t// When gravity is overridden then don't take node before into consideration.\n\t\t\tif ( !this.isGravityOverridden ) {\n\t\t\t\t// ...look at the node before caret and take attributes from it if it is a character node.\n\t\t\t\tattrs = getAttrsIfCharacter( nodeBefore );\n\t\t\t}\n\n\t\t\t// 3. If not, look at the node after caret...\n\t\t\tif ( !attrs ) {\n\t\t\t\tattrs = getAttrsIfCharacter( nodeAfter );\n\t\t\t}\n\n\t\t\t// 4. If not, try to find the first character on the left, that is in the same node.\n\t\t\t// When gravity is overridden then don't take node before into consideration.\n\t\t\tif ( !this.isGravityOverridden && !attrs ) {\n\t\t\t\tlet node = nodeBefore;\n\n\t\t\t\twhile ( node && !schema.isInline( node ) && !attrs ) {\n\t\t\t\t\tnode = node.previousSibling;\n\t\t\t\t\tattrs = getAttrsIfCharacter( node );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 5. If not found, try to find the first character on the right, that is in the same node.\n\t\t\tif ( !attrs ) {\n\t\t\t\tlet node = nodeAfter;\n\n\t\t\t\twhile ( node && !schema.isInline( node ) && !attrs ) {\n\t\t\t\t\tnode = node.nextSibling;\n\t\t\t\t\tattrs = getAttrsIfCharacter( node );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 6. If not found, selection should retrieve attributes from parent.\n\t\t\tif ( !attrs ) {\n\t\t\t\tattrs = this._getStoredAttributes();\n\t\t\t}\n\t\t}\n\n\t\treturn attrs;\n\t}\n\n\t// Fixes the selection after all its ranges got removed.\n\t//\n\t// @private\n\t// @param {module:engine/model/position~Position} deletionPosition Position where the deletion happened.\n\t_fixGraveyardSelection( deletionPosition ) {\n\t\t// Find a range that is a correct selection range and is closest to the position where the deletion happened.\n\t\tconst selectionRange = this._model.schema.getNearestSelectionRange( deletionPosition );\n\n\t\t// If nearest valid selection range has been found - add it in the place of old range.\n\t\tif ( selectionRange ) {\n\t\t\t// Check the range, convert it to live range, bind events, etc.\n\t\t\tthis._pushRange( selectionRange );\n\t\t}\n\t\t// If nearest valid selection range cannot be found don't add any range. Selection will be set to the default range.\n\t}\n}\n\n// Helper function for {@link module:engine/model/liveselection~LiveSelection#_updateAttributes}.\n//\n// It takes model item, checks whether it is a text node (or text proxy) and, if so, returns it's attributes. If not, returns `null`.\n//\n// @param {module:engine/model/item~Item|null} node\n// @returns {Boolean}\nfunction getAttrsIfCharacter( node ) {\n\tif ( node instanceof TextProxy || node instanceof Text ) {\n\t\treturn node.getAttributes();\n\t}\n\n\treturn null;\n}\n\n// Removes selection attributes from element which is not empty anymore.\n//\n// @param {module:engine/model/model~Model} model\n// @param {module:engine/model/batch~Batch} batch\nfunction clearAttributesStoredInElement( model, batch ) {\n\tconst differ = model.document.differ;\n\n\tfor ( const entry of differ.getChanges() ) {\n\t\tif ( entry.type != 'insert' ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst changeParent = entry.position.parent;\n\t\tconst isNoLongerEmpty = entry.length === changeParent.maxOffset;\n\n\t\tif ( isNoLongerEmpty ) {\n\t\t\tmodel.enqueueChange( batch, writer => {\n\t\t\t\tconst storedAttributes = Array.from( changeParent.getAttributeKeys() )\n\t\t\t\t\t.filter( key => key.startsWith( storePrefix ) );\n\n\t\t\t\tfor ( const key of storedAttributes ) {\n\t\t\t\t\twriter.removeAttribute( key, changeParent );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n}\n"],"sourceRoot":""}