{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/model/liverange.js","webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/model/history.js","webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/model/document.js","webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/model/markercollection.js","webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/model/liveposition.js","webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/model/element.js","webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/model/documentselection.js","webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/model/documentfragment.js"],"names":["LiveRange","start","end","bindWithDocument","call","this","stopListening","type","Range","range","listenTo","root","document","model","event","args","operation","isDocumentOperation","transform","priority","ranges","getTransformedByOperation","result","_createFromRanges","boundariesChanged","isEqual","contentChanged","doesOperationChangeRangeContent","deletionPosition","rootName","sourcePosition","oldRange","toRange","fire","containsPosition","position","targetPosition","splitPosition","insertionPosition","mix","EmitterMixin","History","_operations","_undoPairs","Map","_undoneOperations","Set","includes","push","from","Number","NEGATIVE_INFINITY","to","POSITIVE_INFINITY","operations","baseVersion","undoneOperation","undoingOperation","set","add","has","get","graveyardName","Document","version","history","selection","DocumentSelection","roots","Collection","idProperty","differ","Differ","markers","_postFixers","_hasSelectionChangedFromTheLastChangeBlock","createRoot","evt","CKEditorError","bufferOperation","addOperation","marker","newRange","bufferMarkerChange","name","affectsData","on","getRange","elementName","RootElement","destroy","Array","filter","postFixer","json","clone","writer","_hasDocumentChangedFromTheLastChangeBlock","_callPostFixers","refresh","hasDataChanges","batch","reset","isEmpty","graveyard","defaultRoot","_getDefaultRoot","schema","createPositionFromPath","nearestRange","getNearestSelectionRange","createRange","validateTextNodePosition","wasFixed","callback","getRoot","rangeBoundary","textNode","data","offset","startOffset","isInsideSurrogatePair","isInsideCombinedSymbol","MarkerCollection","_markers","Symbol","iterator","values","markerName","markerOrName","managedUsingOperations","Marker","oldMarker","hasChanged","_attachLiveRange","fromRange","_managedUsingOperations","_affectsData","liveRange","delete","_destroyMarker","getIntersection","prefix","startsWith","_detachLiveRange","_liveRange","delegate","stopDelegating","detach","LivePosition","path","stickiness","is","Position","slice","oldPosition","toPosition","Element","attrs","children","_children","NodeList","_insertChild","index","getNode","node","getNodeIndex","getNodeStartOffset","offsetToIndex","relativePath","getChild","parentName","options","includeSelf","parent","length","toJSON","deep","map","_clone","getAttributes","nodes","childCount","items","normalize","_remove","_insertNodes","howMany","_removeNodes","maxOffset","child","fromJSON","Text","attributes","Node","isIterable","TextProxy","storePrefix","doc","_selection","LiveSelection","getRanges","getFirstPosition","getLastPosition","getFirstRange","getLastRange","getSelectedBlocks","getSelectedElement","element","containsEntireContent","getAttributeKeys","key","getAttribute","hasAttribute","_updateMarkers","_updateAttributes","prefixOrName","observeMarkers","itemOrPosition","setFocus","selectable","placeOrOffset","setTo","value","setAttribute","removeAttribute","_getStoredAttributes","overrideGravity","uid","restoreGravity","isCollapsed","anchor","focus","rangeCount","hasOwnRange","isBackward","isGravityOverridden","_ranges","_model","_document","_attributePriority","_selectionRestorePosition","_hasChangedRange","_overriddenGravityRegister","_observedMarkers","_fixGraveyardSelection","directChange","_validateSelectionRange","_updateMarker","clearAttributesStoredInElement","i","_getDefaultRange","optionsOrPlaceOrOffset","_setAttribute","attributeKeys","_removeAttribute","overrideUid","size","pop","_prepareRange","_checkRange","indexOf","splice","changed","markerGroup","split","markerRange","selectionRange","containsRange","oldMarkers","remove","hasMarker","contained","clearAll","newAttributes","toMap","_getSurroundingAttributes","oldAttributes","_attrs","_setAttributesTo","newKey","newValue","oldKey","oldValue","gotAdded","selectionParent","realKey","substr","nodeBefore","nodeAfter","getAttrsIfCharacter","isInline","previousSibling","nextSibling","item","isObject","_pushRange","Selection","entry","changeParent","isNoLongerEmpty","enqueueChange","storedAttributes","getChanges","DocumentFragment","getChildren"],"mappings":"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","file":"js/chunk-vendors~4c5fa93d.fcc98c30.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/liverange\n */\n\nimport Range from './range';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * `LiveRange` is a type of {@link module:engine/model/range~Range Range}\n * that updates itself as {@link module:engine/model/document~Document document}\n * is changed through operations. It may be used as a bookmark.\n *\n * **Note:** Be very careful when dealing with `LiveRange`. Each `LiveRange` instance bind events that might\n * have to be unbound. Use {@link module:engine/model/liverange~LiveRange#detach detach} whenever you don't need `LiveRange` anymore.\n */\nexport default class LiveRange extends Range {\n\t/**\n\t * Creates a live range.\n\t *\n\t * @see module:engine/model/range~Range\n\t */\n\tconstructor( start, end ) {\n\t\tsuper( start, end );\n\n\t\tbindWithDocument.call( this );\n\t}\n\n\t/**\n\t * Unbinds all events previously bound by `LiveRange`. Use it whenever you don't need `LiveRange` instance\n\t * anymore (i.e. when leaving scope in which it was declared or before re-assigning variable that was\n\t * referring to it).\n\t */\n\tdetach() {\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\tliveRange.is( 'range' ); // -> true\n\t *\t\tliveRange.is( 'model:range' ); // -> true\n\t *\t\tliveRange.is( 'liveRange' ); // -> true\n\t *\t\tliveRange.is( 'model:liveRange' ); // -> true\n\t *\n\t *\t\tliveRange.is( 'view:range' ); // -> false\n\t *\t\tliveRange.is( 'documentSelection' ); // -> 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 === 'liveRange' || type === 'model:liveRange' ||\n\t\t\t// From super.is(). This is highly utilised method and cannot call super. See ckeditor/ckeditor5#6529.\n\t\t\ttype == 'range' || type === 'model:range';\n\t}\n\n\t/**\n\t * Creates a {@link module:engine/model/range~Range range instance} that is equal to this live range.\n\t *\n\t * @returns {module:engine/model/range~Range}\n\t */\n\ttoRange() {\n\t\treturn new Range( this.start, this.end );\n\t}\n\n\t/**\n\t * Creates a `LiveRange` instance that is equal to the given range.\n\t *\n\t * @param {module:engine/model/range~Range} range\n\t * @returns {module:engine/model/liverange~LiveRange}\n\t */\n\tstatic fromRange( range ) {\n\t\treturn new LiveRange( range.start, range.end );\n\t}\n\n\t/**\n\t * @see module:engine/model/range~Range._createIn\n\t * @static\n\t * @protected\n\t * @method module:engine/model/liverange~LiveRange._createIn\n\t * @param {module:engine/model/element~Element} element\n\t * @returns {module:engine/model/liverange~LiveRange}\n\t */\n\n\t/**\n\t * @see module:engine/model/range~Range._createOn\n\t * @static\n\t * @protected\n\t * @method module:engine/model/liverange~LiveRange._createOn\n\t * @param {module:engine/model/element~Element} element\n\t * @returns {module:engine/model/liverange~LiveRange}\n\t */\n\n\t/**\n\t * @see module:engine/model/range~Range._createFromPositionAndShift\n\t * @static\n\t * @protected\n\t * @method module:engine/model/liverange~LiveRange._createFromPositionAndShift\n\t * @param {module:engine/model/position~Position} position\n\t * @param {Number} shift\n\t * @returns {module:engine/model/liverange~LiveRange}\n\t */\n\n\t/**\n\t * Fired when `LiveRange` instance boundaries have changed due to changes in the\n\t * {@link module:engine/model/document~Document document}.\n\t *\n\t * @event change:range\n\t * @param {module:engine/model/range~Range} oldRange Range with start and end position equal to start and end position of this live\n\t * range before it got changed.\n\t * @param {Object} data Object with additional information about the change.\n\t * @param {module:engine/model/position~Position|null} data.deletionPosition Source position for remove and merge changes.\n\t * Available if the range was moved to the graveyard root, `null` otherwise.\n\t */\n\n\t/**\n\t * Fired when `LiveRange` instance boundaries have not changed after a change in {@link module:engine/model/document~Document document}\n\t * but the change took place inside the range, effectively changing its content.\n\t *\n\t * @event change:content\n\t * @param {module:engine/model/range~Range} range Range with start and end position equal to start and end position of\n\t * change range.\n\t * @param {Object} data Object with additional information about the change.\n\t * @param {null} data.deletionPosition Due to the nature of this event, this property is always set to `null`. It is passed\n\t * for compatibility with the {@link module:engine/model/liverange~LiveRange#event:change:range} event.\n\t */\n}\n\n// Binds this `LiveRange` to the {@link module:engine/model/document~Document document}\n// that owns this range's {@link module:engine/model/range~Range#root root}.\n//\n// @private\nfunction bindWithDocument() {\n\tthis.listenTo(\n\t\tthis.root.document.model,\n\t\t'applyOperation',\n\t\t( event, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( !operation.isDocumentOperation ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttransform.call( this, operation );\n\t\t},\n\t\t{ priority: 'low' }\n\t);\n}\n\n// Updates this range accordingly to the updates applied to the model. Bases on change events.\n//\n// @private\n// @param {module:engine/model/operation/operation~Operation} operation Executed operation.\nfunction transform( operation ) {\n\t// Transform the range by the operation. Join the result ranges if needed.\n\tconst ranges = this.getTransformedByOperation( operation );\n\tconst result = Range._createFromRanges( ranges );\n\n\tconst boundariesChanged = !result.isEqual( this );\n\tconst contentChanged = doesOperationChangeRangeContent( this, operation );\n\n\tlet deletionPosition = null;\n\n\tif ( boundariesChanged ) {\n\t\t// If range boundaries have changed, fire `change:range` event.\n\t\t//\n\t\tif ( result.root.rootName == '$graveyard' ) {\n\t\t\t// If the range was moved to the graveyard root, set `deletionPosition`.\n\t\t\tif ( operation.type == 'remove' ) {\n\t\t\t\tdeletionPosition = operation.sourcePosition;\n\t\t\t} else {\n\t\t\t\t// Merge operation.\n\t\t\t\tdeletionPosition = operation.deletionPosition;\n\t\t\t}\n\t\t}\n\n\t\tconst oldRange = this.toRange();\n\n\t\tthis.start = result.start;\n\t\tthis.end = result.end;\n\n\t\tthis.fire( 'change:range', oldRange, { deletionPosition } );\n\t} else if ( contentChanged ) {\n\t\t// If range boundaries have not changed, but there was change inside the range, fire `change:content` event.\n\t\tthis.fire( 'change:content', this.toRange(), { deletionPosition } );\n\t}\n}\n\n// Checks whether given operation changes something inside the range (even if it does not change boundaries).\n//\n// @private\n// @param {module:engine/model/range~Range} range Range to check.\n// @param {module:engine/model/operation/operation~Operation} operation Executed operation.\n// @returns {Boolean}\nfunction doesOperationChangeRangeContent( range, operation ) {\n\tswitch ( operation.type ) {\n\t\tcase 'insert':\n\t\t\treturn range.containsPosition( operation.position );\n\t\tcase 'move':\n\t\tcase 'remove':\n\t\tcase 'reinsert':\n\t\tcase 'merge':\n\t\t\treturn range.containsPosition( operation.sourcePosition ) ||\n\t\t\t\trange.start.isEqual( operation.sourcePosition ) ||\n\t\t\t\trange.containsPosition( operation.targetPosition );\n\t\tcase 'split':\n\t\t\treturn range.containsPosition( operation.splitPosition ) || range.containsPosition( operation.insertionPosition );\n\t}\n\n\treturn false;\n}\n\nmix( LiveRange, EmitterMixin );\n","/**\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/history\n */\n\n/**\n * `History` keeps the track of all the operations applied to the {@link module:engine/model/document~Document document}.\n */\nexport default class History {\n\t/**\n\t * Creates an empty History instance.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Operations added to the history.\n\t\t *\n\t\t * @protected\n\t\t * @member {Array.} module:engine/model/history~History#_operations\n\t\t */\n\t\tthis._operations = [];\n\n\t\t/**\n\t\t * Holds an information which {@link module:engine/model/operation/operation~Operation operation} undoes which\n\t\t * {@link module:engine/model/operation/operation~Operation operation}.\n\t\t *\n\t\t * Keys of the map are \"undoing operations\", that is operations that undone some other operations. For each key, the\n\t\t * value is an operation that has been undone by the \"undoing operation\".\n\t\t *\n\t\t * @private\n\t\t * @member {Map} module:engine/model/history~History#_undoPairs\n\t\t */\n\t\tthis._undoPairs = new Map();\n\n\t\t/**\n\t\t * Holds all undone operations.\n\t\t *\n\t\t * @private\n\t\t * @member {Set.} module:engine/model/history~History#_undoneOperations\n\t\t */\n\t\tthis._undoneOperations = new Set();\n\t}\n\n\t/**\n\t * Adds an operation to the history.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} operation Operation to add.\n\t */\n\taddOperation( operation ) {\n\t\tif ( this._operations.includes( operation ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._operations.push( operation );\n\t}\n\n\t/**\n\t * Returns operations added to the history.\n\t *\n\t * @param {Number} [from=Number.NEGATIVE_INFINITY] Base version from which operations should be returned (inclusive).\n\t * Defaults to `Number.NEGATIVE_INFINITY`, which means that operations from the first one will be returned.\n\t * @param {Number} [to=Number.POSITIVE_INFINITY] Base version up to which operations should be returned (exclusive).\n\t * Defaults to `Number.POSITIVE_INFINITY` which means that operations up to the last one will be returned.\n\t * @returns {Array.} Operations added to the history.\n\t */\n\tgetOperations( from = Number.NEGATIVE_INFINITY, to = Number.POSITIVE_INFINITY ) {\n\t\tconst operations = [];\n\n\t\tfor ( const operation of this._operations ) {\n\t\t\tif ( operation.baseVersion >= from && operation.baseVersion < to ) {\n\t\t\t\toperations.push( operation );\n\t\t\t}\n\t\t}\n\n\t\treturn operations;\n\t}\n\n\t/**\n\t * Returns operation from the history that bases on given `baseVersion`.\n\t *\n\t * @param {Number} baseVersion Base version of the operation to get.\n\t * @returns {module:engine/model/operation/operation~Operation|undefined} Operation with given base version or `undefined` if\n\t * there is no such operation in history.\n\t */\n\tgetOperation( baseVersion ) {\n\t\tfor ( const operation of this._operations ) {\n\t\t\tif ( operation.baseVersion == baseVersion ) {\n\t\t\t\treturn operation;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Marks in history that one operation is an operation that is undoing the other operation. By marking operation this way,\n\t * history is keeping more context information about operations, which helps in operational transformation.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} undoneOperation Operation which is undone by `undoingOperation`.\n\t * @param {module:engine/model/operation/operation~Operation} undoingOperation Operation which undoes `undoneOperation`.\n\t */\n\tsetOperationAsUndone( undoneOperation, undoingOperation ) {\n\t\tthis._undoPairs.set( undoingOperation, undoneOperation );\n\t\tthis._undoneOperations.add( undoneOperation );\n\t}\n\n\t/**\n\t * Checks whether given `operation` is undoing any other operation.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} operation Operation to check.\n\t * @returns {Boolean} `true` if given `operation` is undoing any other operation, `false` otherwise.\n\t */\n\tisUndoingOperation( operation ) {\n\t\treturn this._undoPairs.has( operation );\n\t}\n\n\t/**\n\t * Checks whether given `operation` has been undone by any other operation.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} operation Operation to check.\n\t * @returns {Boolean} `true` if given `operation` has been undone any other operation, `false` otherwise.\n\t */\n\tisUndoneOperation( operation ) {\n\t\treturn this._undoneOperations.has( operation );\n\t}\n\n\t/**\n\t * For given `undoingOperation`, returns the operation which has been undone by it.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} undoingOperation\n\t * @returns {module:engine/model/operation/operation~Operation|undefined} Operation that has been undone by given\n\t * `undoingOperation` or `undefined` if given `undoingOperation` is not undoing any other operation.\n\t */\n\tgetUndoneOperation( undoingOperation ) {\n\t\treturn this._undoPairs.get( undoingOperation );\n\t}\n}\n","/**\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/document\n */\n\nimport Differ from './differ';\nimport RootElement from './rootelement';\nimport History from './history';\nimport DocumentSelection from './documentselection';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport { isInsideSurrogatePair, isInsideCombinedSymbol } from '@ckeditor/ckeditor5-utils/src/unicode';\nimport { clone } from 'lodash-es';\n\n// @if CK_DEBUG_ENGINE // const { logDocument } = require( '../dev-utils/utils' );\n\nconst graveyardName = '$graveyard';\n\n/**\n * Data model's document. It contains the model's structure, its selection and the history of changes.\n *\n * Read more about working with the model in\n * {@glink framework/guides/architecture/editing-engine#model introduction to the the editing engine's architecture}.\n *\n * Usually, the document contains just one {@link module:engine/model/document~Document#roots root element}, so\n * you can retrieve it by just calling {@link module:engine/model/document~Document#getRoot} without specifying its name:\n *\n *\t\tmodel.document.getRoot(); // -> returns the main root\n *\n * However, the document may contain multiple roots – e.g. when the editor has multiple editable areas\n * (e.g. a title and a body of a message).\n *\n * @mixes module:utils/emittermixin~EmitterMixin\n */\nexport default class Document {\n\t/**\n\t * Creates an empty document instance with no {@link #roots} (other than\n\t * the {@link #graveyard graveyard root}).\n\t */\n\tconstructor( model ) {\n\t\t/**\n\t\t * The {@link module:engine/model/model~Model model} that the document is a part of.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/model~Model}\n\t\t */\n\t\tthis.model = model;\n\n\t\t/**\n\t\t * The document version. It starts from `0` and every operation increases the version number. It is used to ensure that\n\t\t * operations are applied on a proper document version.\n\t\t *\n\t\t * If the {@link module:engine/model/operation/operation~Operation#baseVersion base version} does not match the document version,\n\t\t * a {@link module:utils/ckeditorerror~CKEditorError model-document-applyoperation-wrong-version} error is thrown.\n\t\t *\n\t\t * @type {Number}\n\t\t */\n\t\tthis.version = 0;\n\n\t\t/**\n\t\t * The document's history.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/history~History}\n\t\t */\n\t\tthis.history = new History( this );\n\n\t\t/**\n\t\t * The selection in this document.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/documentselection~DocumentSelection}\n\t\t */\n\t\tthis.selection = new DocumentSelection( this );\n\n\t\t/**\n\t\t * A list of roots that are owned and managed by this document. Use {@link #createRoot} and\n\t\t * {@link #getRoot} to manipulate it.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:utils/collection~Collection}\n\t\t */\n\t\tthis.roots = new Collection( { idProperty: 'rootName' } );\n\n\t\t/**\n\t\t * The model differ object. Its role is to buffer changes done on the model document and then calculate a diff of those changes.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/differ~Differ}\n\t\t */\n\t\tthis.differ = new Differ( model.markers );\n\n\t\t/**\n\t\t * Post-fixer callbacks registered to the model document.\n\t\t *\n\t\t * @private\n\t\t * @type {Set.}\n\t\t */\n\t\tthis._postFixers = new Set();\n\n\t\t/**\n\t\t * A boolean indicates whether the selection has changed until\n\t\t *\n\t\t * @private\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis._hasSelectionChangedFromTheLastChangeBlock = false;\n\n\t\t// Graveyard tree root. Document always have a graveyard root, which stores removed nodes.\n\t\tthis.createRoot( '$root', graveyardName );\n\n\t\t// First, if the operation is a document operation check if it's base version is correct.\n\t\tthis.listenTo( model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( operation.isDocumentOperation && operation.baseVersion !== this.version ) {\n\t\t\t\t/**\n\t\t\t\t * Only operations with matching versions can be applied.\n\t\t\t\t *\n\t\t\t\t * @error model-document-applyoperation-wrong-version\n\t\t\t\t * @param {module:engine/model/operation/operation~Operation} operation\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError( 'model-document-applyoperation-wrong-version', this, { operation } );\n\t\t\t}\n\t\t}, { priority: 'highest' } );\n\n\t\t// Then, still before an operation is applied on model, buffer the change in differ.\n\t\tthis.listenTo( model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( operation.isDocumentOperation ) {\n\t\t\t\tthis.differ.bufferOperation( operation );\n\t\t\t}\n\t\t}, { priority: 'high' } );\n\n\t\t// After the operation is applied, bump document's version and add the operation to the history.\n\t\tthis.listenTo( model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( operation.isDocumentOperation ) {\n\t\t\t\tthis.version++;\n\t\t\t\tthis.history.addOperation( operation );\n\t\t\t}\n\t\t}, { priority: 'low' } );\n\n\t\t// Listen to selection changes. If selection changed, mark it.\n\t\tthis.listenTo( this.selection, 'change', () => {\n\t\t\tthis._hasSelectionChangedFromTheLastChangeBlock = true;\n\t\t} );\n\n\t\t// Buffer marker changes.\n\t\t// This is not covered in buffering operations because markers may change outside of them (when they\n\t\t// are modified using `model.markers` collection, not through `MarkerOperation`).\n\t\tthis.listenTo( model.markers, 'update', ( evt, marker, oldRange, newRange ) => {\n\t\t\t// Whenever marker is updated, buffer that change.\n\t\t\tthis.differ.bufferMarkerChange( marker.name, oldRange, newRange, marker.affectsData );\n\n\t\t\tif ( oldRange === null ) {\n\t\t\t\t// If this is a new marker, add a listener that will buffer change whenever marker changes.\n\t\t\t\tmarker.on( 'change', ( evt, oldRange ) => {\n\t\t\t\t\tthis.differ.bufferMarkerChange( marker.name, oldRange, marker.getRange(), marker.affectsData );\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * The graveyard tree root. A document always has a graveyard root that stores removed nodes.\n\t *\n\t * @readonly\n\t * @member {module:engine/model/rootelement~RootElement}\n\t */\n\tget graveyard() {\n\t\treturn this.getRoot( graveyardName );\n\t}\n\n\t/**\n\t * Creates a new root.\n\t *\n\t * @param {String} [elementName='$root'] The element name. Defaults to `'$root'` which also has some basic schema defined\n\t * (`$block`s are allowed inside the `$root`). Make sure to define a proper schema if you use a different name.\n\t * @param {String} [rootName='main'] A unique root name.\n\t * @returns {module:engine/model/rootelement~RootElement} The created root.\n\t */\n\tcreateRoot( elementName = '$root', rootName = 'main' ) {\n\t\tif ( this.roots.get( rootName ) ) {\n\t\t\t/**\n\t\t\t * A root with the specified name already exists.\n\t\t\t *\n\t\t\t * @error model-document-createroot-name-exists\n\t\t\t * @param {module:engine/model/document~Document} doc\n\t\t\t * @param {String} name\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'model-document-createroot-name-exists', this, { name: rootName } );\n\t\t}\n\n\t\tconst root = new RootElement( this, elementName, rootName );\n\t\tthis.roots.add( root );\n\n\t\treturn root;\n\t}\n\n\t/**\n\t * Removes all event listeners set by the document instance.\n\t */\n\tdestroy() {\n\t\tthis.selection.destroy();\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Returns a root by its name.\n\t *\n\t * @param {String} [name='main'] A unique root name.\n\t * @returns {module:engine/model/rootelement~RootElement|null} The root registered under a given name or `null` when\n\t * there is no root with the given name.\n\t */\n\tgetRoot( name = 'main' ) {\n\t\treturn this.roots.get( name );\n\t}\n\n\t/**\n\t * Returns an array with names of all roots (without the {@link #graveyard}) added to the document.\n\t *\n\t * @returns {Array.} Roots names.\n\t */\n\tgetRootNames() {\n\t\treturn Array.from( this.roots, root => root.rootName ).filter( name => name != graveyardName );\n\t}\n\n\t/**\n\t * Used to register a post-fixer callback. A post-fixer mechanism guarantees that the features\n\t * will operate on a correct model state.\n\t *\n\t * An execution of a feature may lead to an incorrect document tree state. The callbacks are used to fix the document tree after\n\t * it has changed. Post-fixers are fired just after all changes from the outermost change block were applied but\n\t * before the {@link module:engine/model/document~Document#event:change change event} is fired. If a post-fixer callback made\n\t * a change, it should return `true`. When this happens, all post-fixers are fired again to check if something else should\n\t * not be fixed in the new document tree state.\n\t *\n\t * As a parameter, a post-fixer callback receives a {@link module:engine/model/writer~Writer writer} instance connected with the\n\t * executed changes block. Thanks to that, all changes done by the callback will be added to the same\n\t * {@link module:engine/model/batch~Batch batch} (and undo step) as the original changes. This makes post-fixer changes transparent\n\t * for the user.\n\t *\n\t * An example of a post-fixer is a callback that checks if all the data were removed from the editor. If so, the\n\t * callback should add an empty paragraph so that the editor is never empty:\n\t *\n\t *\t\tdocument.registerPostFixer( writer => {\n\t *\t\t\tconst changes = document.differ.getChanges();\n\t *\n\t *\t\t\t// Check if the changes lead to an empty root in the editor.\n\t *\t\t\tfor ( const entry of changes ) {\n\t *\t\t\t\tif ( entry.type == 'remove' && entry.position.root.isEmpty ) {\n\t *\t\t\t\t\twriter.insertElement( 'paragraph', entry.position.root, 0 );\n\t *\n\t *\t\t\t\t\t// It is fine to return early, even if multiple roots would need to be fixed.\n\t *\t\t\t\t\t// All post-fixers will be fired again, so if there are more empty roots, those will be fixed, too.\n\t *\t\t\t\t\treturn true;\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * @param {Function} postFixer\n\t */\n\tregisterPostFixer( postFixer ) {\n\t\tthis._postFixers.add( postFixer );\n\t}\n\n\t/**\n\t * A custom `toJSON()` method to solve child-parent circular dependencies.\n\t *\n\t * @returns {Object} A clone of this object with the document property changed to a string.\n\t */\n\ttoJSON() {\n\t\tconst json = clone( this );\n\n\t\t// Due to circular references we need to remove parent reference.\n\t\tjson.selection = '[engine.model.DocumentSelection]';\n\t\tjson.model = '[engine.model.Model]';\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * Check if there were any changes done on document, and if so, call post-fixers,\n\t * fire `change` event for features and conversion and then reset the differ.\n\t * Fire `change:data` event when at least one operation or buffered marker changes the data.\n\t *\n\t * @protected\n\t * @fires change\n\t * @fires change:data\n\t * @param {module:engine/model/writer~Writer} writer The writer on which post-fixers will be called.\n\t */\n\t_handleChangeBlock( writer ) {\n\t\tif ( this._hasDocumentChangedFromTheLastChangeBlock() ) {\n\t\t\tthis._callPostFixers( writer );\n\n\t\t\t// Refresh selection attributes according to the final position in the model after the change.\n\t\t\tthis.selection.refresh();\n\n\t\t\tif ( this.differ.hasDataChanges() ) {\n\t\t\t\tthis.fire( 'change:data', writer.batch );\n\t\t\t} else {\n\t\t\t\tthis.fire( 'change', writer.batch );\n\t\t\t}\n\n\t\t\t// Theoretically, it is not necessary to refresh selection after change event because\n\t\t\t// post-fixers are the last who should change the model, but just in case...\n\t\t\tthis.selection.refresh();\n\n\t\t\tthis.differ.reset();\n\t\t}\n\n\t\tthis._hasSelectionChangedFromTheLastChangeBlock = false;\n\t}\n\n\t/**\n\t * Returns whether there is a buffered change or if the selection has changed from the last\n\t * {@link module:engine/model/model~Model#enqueueChange `enqueueChange()` block}\n\t * or {@link module:engine/model/model~Model#change `change()` block}.\n\t *\n\t * @protected\n\t * @returns {Boolean} Returns `true` if document has changed from the last `change()` or `enqueueChange()` block.\n\t */\n\t_hasDocumentChangedFromTheLastChangeBlock() {\n\t\treturn !this.differ.isEmpty || this._hasSelectionChangedFromTheLastChangeBlock;\n\t}\n\n\t/**\n\t * Returns the default root for this document which is either the first root that was added to the document using\n\t * {@link #createRoot} or the {@link #graveyard graveyard root} if no other roots were created.\n\t *\n\t * @protected\n\t * @returns {module:engine/model/rootelement~RootElement} The default root for this document.\n\t */\n\t_getDefaultRoot() {\n\t\tfor ( const root of this.roots ) {\n\t\t\tif ( root !== this.graveyard ) {\n\t\t\t\treturn root;\n\t\t\t}\n\t\t}\n\n\t\treturn this.graveyard;\n\t}\n\n\t/**\n\t * Returns the default range for this selection. The default range is a collapsed range that starts and ends\n\t * at the beginning of this selection's document {@link #_getDefaultRoot default root}.\n\t *\n\t * @protected\n\t * @returns {module:engine/model/range~Range}\n\t */\n\t_getDefaultRange() {\n\t\tconst defaultRoot = this._getDefaultRoot();\n\t\tconst model = this.model;\n\t\tconst schema = model.schema;\n\n\t\t// Find the first position where the selection can be put.\n\t\tconst position = model.createPositionFromPath( defaultRoot, [ 0 ] );\n\t\tconst nearestRange = schema.getNearestSelectionRange( position );\n\n\t\t// If valid selection range is not found - return range collapsed at the beginning of the root.\n\t\treturn nearestRange || model.createRange( position );\n\t}\n\n\t/**\n\t * Checks whether a given {@link module:engine/model/range~Range range} is a valid range for\n\t * the {@link #selection document's selection}.\n\t *\n\t * @private\n\t * @param {module:engine/model/range~Range} range A range to check.\n\t * @returns {Boolean} `true` if `range` is valid, `false` otherwise.\n\t */\n\t_validateSelectionRange( range ) {\n\t\treturn validateTextNodePosition( range.start ) && validateTextNodePosition( range.end );\n\t}\n\n\t/**\n\t * Performs post-fixer loops. Executes post-fixer callbacks as long as none of them has done any changes to the model.\n\t *\n\t * @private\n\t * @param {module:engine/model/writer~Writer} writer The writer on which post-fixer callbacks will be called.\n\t */\n\t_callPostFixers( writer ) {\n\t\tlet wasFixed = false;\n\n\t\tdo {\n\t\t\tfor ( const callback of this._postFixers ) {\n\t\t\t\t// Ensure selection attributes are up to date before each post-fixer.\n\t\t\t\t// https://github.com/ckeditor/ckeditor5-engine/issues/1673.\n\t\t\t\t//\n\t\t\t\t// It might be good to refresh the selection after each operation but at the moment it leads\n\t\t\t\t// to losing attributes for composition or and spell checking\n\t\t\t\t// https://github.com/ckeditor/ckeditor5-typing/issues/188\n\t\t\t\tthis.selection.refresh();\n\n\t\t\t\twasFixed = callback( writer );\n\n\t\t\t\tif ( wasFixed ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} while ( wasFixed );\n\t}\n\n\t/**\n\t * Fired after each {@link module:engine/model/model~Model#enqueueChange `enqueueChange()` block} or the outermost\n\t * {@link module:engine/model/model~Model#change `change()` block} was executed and the document was changed\n\t * during that block's execution.\n\t *\n\t * The changes which this event will cover include:\n\t *\n\t * * document structure changes,\n\t * * selection changes,\n\t * * marker changes.\n\t *\n\t * If you want to be notified about all these changes, then simply listen to this event like this:\n\t *\n\t *\t\tmodel.document.on( 'change', () => {\n\t *\t\t\tconsole.log( 'The document has changed!' );\n\t *\t\t} );\n\t *\n\t * If, however, you only want to be notified about the data changes, then use the\n\t * {@link module:engine/model/document~Document#event:change:data change:data} event,\n\t * which is fired for document structure changes and marker changes (which affects the data).\n\t *\n\t *\t\tmodel.document.on( 'change:data', () => {\n\t *\t\t\tconsole.log( 'The data has changed!' );\n\t *\t\t} );\n\t *\n\t * @event change\n\t * @param {module:engine/model/batch~Batch} batch The batch that was used in the executed changes block.\n\t */\n\n\t/**\n\t * It is a narrower version of the {@link #event:change} event. It is fired for changes which\n\t * affect the editor data. This is:\n\t *\n\t * * document structure changes,\n\t * * marker changes (which affects the data).\n\t *\n\t * If you want to be notified about the data changes, then listen to this event:\n\t *\n\t *\t\tmodel.document.on( 'change:data', () => {\n\t *\t\t\tconsole.log( 'The data has changed!' );\n\t *\t\t} );\n\t *\n\t * If you would like to listen to all document changes, then check out the\n\t * {@link module:engine/model/document~Document#event:change change} event.\n\t *\n\t * @event change:data\n\t * @param {module:engine/model/batch~Batch} batch The batch that was used in the executed changes block.\n\t */\n\n\t// @if CK_DEBUG_ENGINE // log( version = null ) {\n\t// @if CK_DEBUG_ENGINE // \tversion = version === null ? this.version : version;\n\t// @if CK_DEBUG_ENGINE // \tlogDocument( this, version );\n\t// @if CK_DEBUG_ENGINE // }\n}\n\nmix( Document, EmitterMixin );\n\n// Checks whether given range boundary position is valid for document selection, meaning that is not between\n// unicode surrogate pairs or base character and combining marks.\nfunction validateTextNodePosition( rangeBoundary ) {\n\tconst textNode = rangeBoundary.textNode;\n\n\tif ( textNode ) {\n\t\tconst data = textNode.data;\n\t\tconst offset = rangeBoundary.offset - textNode.startOffset;\n\n\t\treturn !isInsideSurrogatePair( data, offset ) && !isInsideCombinedSymbol( data, offset );\n\t}\n\n\treturn true;\n}\n","/**\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/markercollection\n */\n\nimport LiveRange from './liverange';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * The collection of all {@link module:engine/model/markercollection~Marker markers} attached to the document.\n * It lets you {@link module:engine/model/markercollection~MarkerCollection#get get} markers or track them using\n * {@link module:engine/model/markercollection~MarkerCollection#event:update} event.\n *\n * To create, change or remove makers use {@link module:engine/model/writer~Writer model writers'} methods:\n * {@link module:engine/model/writer~Writer#addMarker} or {@link module:engine/model/writer~Writer#removeMarker}. Since\n * the writer is the only proper way to change the data model it is not possible to change markers directly using this\n * collection. All markers created by the writer will be automatically added to this collection.\n *\n * By default there is one marker collection available as {@link module:engine/model/model~Model#markers model property}.\n *\n * @see module:engine/model/markercollection~Marker\n */\nexport default class MarkerCollection {\n\t/**\n\t * Creates a markers collection.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Stores {@link ~Marker markers} added to the collection.\n\t\t *\n\t\t * @private\n\t\t * @member {Map} #_markers\n\t\t */\n\t\tthis._markers = new Map();\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * Iterates over all {@link ~Marker markers} added to the collection.\n\t *\n\t * @returns {Iterable}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this._markers.values();\n\t}\n\n\t/**\n\t * Checks if marker with given `markerName` is in the collection.\n\t *\n\t * @param {String} markerName Marker name.\n\t * @returns {Boolean} `true` if marker with given `markerName` is in the collection, `false` otherwise.\n\t */\n\thas( markerName ) {\n\t\treturn this._markers.has( markerName );\n\t}\n\n\t/**\n\t * Returns {@link ~Marker marker} with given `markerName`.\n\t *\n\t * @param {String} markerName Name of marker to get.\n\t * @returns {module:engine/model/markercollection~Marker|null} Marker with given name or `null` if such marker was\n\t * not added to the collection.\n\t */\n\tget( markerName ) {\n\t\treturn this._markers.get( markerName ) || null;\n\t}\n\n\t/**\n\t * Creates and adds a {@link ~Marker marker} to the `MarkerCollection` with given name on given\n\t * {@link module:engine/model/range~Range range}.\n\t *\n\t * If `MarkerCollection` already had a marker with given name (or {@link ~Marker marker} was passed), the marker in\n\t * collection is updated and {@link module:engine/model/markercollection~MarkerCollection#event:update} event is fired\n\t * but only if there was a change (marker range or {@link module:engine/model/markercollection~Marker#managedUsingOperations}\n\t * flag has changed.\n\t *\n\t * @protected\n\t * @fires module:engine/model/markercollection~MarkerCollection#event:update\n\t * @param {String|module:engine/model/markercollection~Marker} markerOrName Name of marker to set or marker instance to update.\n\t * @param {module:engine/model/range~Range} range Marker range.\n\t * @param {Boolean} [managedUsingOperations=false] Specifies whether the marker is managed using operations.\n\t * @param {Boolean} [affectsData=false] Specifies whether the marker affects the data produced by the data pipeline\n\t * (is persisted in the editor's data).\n\t * @returns {module:engine/model/markercollection~Marker} `Marker` instance which was added or updated.\n\t */\n\t_set( markerOrName, range, managedUsingOperations = false, affectsData = false ) {\n\t\tconst markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;\n\n\t\tif ( markerName.includes( ',' ) ) {\n\t\t\t/**\n\t\t\t * Marker name cannot contain the \",\" character.\n\t\t\t *\n\t\t\t * @error markercollection-incorrect-marker-name\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'markercollection-incorrect-marker-name', this );\n\t\t}\n\n\t\tconst oldMarker = this._markers.get( markerName );\n\n\t\tif ( oldMarker ) {\n\t\t\tconst oldRange = oldMarker.getRange();\n\t\t\tlet hasChanged = false;\n\n\t\t\tif ( !oldRange.isEqual( range ) ) {\n\t\t\t\toldMarker._attachLiveRange( LiveRange.fromRange( range ) );\n\t\t\t\thasChanged = true;\n\t\t\t}\n\n\t\t\tif ( managedUsingOperations != oldMarker.managedUsingOperations ) {\n\t\t\t\toldMarker._managedUsingOperations = managedUsingOperations;\n\t\t\t\thasChanged = true;\n\t\t\t}\n\n\t\t\tif ( typeof affectsData === 'boolean' && affectsData != oldMarker.affectsData ) {\n\t\t\t\toldMarker._affectsData = affectsData;\n\t\t\t\thasChanged = true;\n\t\t\t}\n\n\t\t\tif ( hasChanged ) {\n\t\t\t\tthis.fire( 'update:' + markerName, oldMarker, oldRange, range );\n\t\t\t}\n\n\t\t\treturn oldMarker;\n\t\t}\n\n\t\tconst liveRange = LiveRange.fromRange( range );\n\t\tconst marker = new Marker( markerName, liveRange, managedUsingOperations, affectsData );\n\n\t\tthis._markers.set( markerName, marker );\n\t\tthis.fire( 'update:' + markerName, marker, null, range );\n\n\t\treturn marker;\n\t}\n\n\t/**\n\t * Removes given {@link ~Marker marker} or a marker with given name from the `MarkerCollection`.\n\t *\n\t * @protected\n\t * @fires module:engine/model/markercollection~MarkerCollection#event:update\n\t * @param {String} markerOrName Marker or name of a marker to remove.\n\t * @returns {Boolean} `true` if marker was found and removed, `false` otherwise.\n\t */\n\t_remove( markerOrName ) {\n\t\tconst markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;\n\t\tconst oldMarker = this._markers.get( markerName );\n\n\t\tif ( oldMarker ) {\n\t\t\tthis._markers.delete( markerName );\n\t\t\tthis.fire( 'update:' + markerName, oldMarker, oldMarker.getRange(), null );\n\n\t\t\tthis._destroyMarker( oldMarker );\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Fires an {@link module:engine/model/markercollection~MarkerCollection#event:update} event for the given {@link ~Marker marker}\n\t * but does not change the marker. Useful to force {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher downcast\n\t * conversion} for the marker.\n\t *\n\t * @protected\n\t * @fires module:engine/model/markercollection~MarkerCollection#event:update\n\t * @param {String} markerOrName Marker or name of a marker to refresh.\n\t */\n\t_refresh( markerOrName ) {\n\t\tconst markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;\n\t\tconst marker = this._markers.get( markerName );\n\n\t\tif ( !marker ) {\n\t\t\t/**\n\t\t\t * Marker with provided name does not exists.\n\t\t\t *\n\t\t\t * @error markercollection-refresh-marker-not-exists\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'markercollection-refresh-marker-not-exists', this );\n\t\t}\n\n\t\tconst range = marker.getRange();\n\n\t\tthis.fire( 'update:' + markerName, marker, range, range, marker.managedUsingOperations, marker.affectsData );\n\t}\n\n\t/**\n\t * Returns iterator that iterates over all markers, which ranges contain given {@link module:engine/model/position~Position position}.\n\t *\n\t * @param {module:engine/model/position~Position} position\n\t * @returns {Iterable.}\n\t */\n\t* getMarkersAtPosition( position ) {\n\t\tfor ( const marker of this ) {\n\t\t\tif ( marker.getRange().containsPosition( position ) ) {\n\t\t\t\tyield marker;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns iterator that iterates over all markers, which intersects with given {@link module:engine/model/range~Range range}.\n\t *\n\t * @param {module:engine/model/range~Range} range\n\t * @returns {Iterable.}\n\t */\n\t* getMarkersIntersectingRange( range ) {\n\t\tfor ( const marker of this ) {\n\t\t\tif ( marker.getRange().getIntersection( range ) !== null ) {\n\t\t\t\tyield marker;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Destroys marker collection and all markers inside it.\n\t */\n\tdestroy() {\n\t\tfor ( const marker of this._markers.values() ) {\n\t\t\tthis._destroyMarker( marker );\n\t\t}\n\n\t\tthis._markers = null;\n\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Iterates over all markers that starts with given `prefix`.\n\t *\n\t *\t\tconst markerFooA = markersCollection.set( 'foo:a', rangeFooA );\n\t *\t\tconst markerFooB = markersCollection.set( 'foo:b', rangeFooB );\n\t *\t\tconst markerBarA = markersCollection.set( 'bar:a', rangeBarA );\n\t *\t\tconst markerFooBarA = markersCollection.set( 'foobar:a', rangeFooBarA );\n\t *\t\tArray.from( markersCollection.getMarkersGroup( 'foo' ) ); // [ markerFooA, markerFooB ]\n\t *\t\tArray.from( markersCollection.getMarkersGroup( 'a' ) ); // []\n\t *\n\t * @param prefix\n\t * @returns {Iterable.}\n\t */\n\t* getMarkersGroup( prefix ) {\n\t\tfor ( const marker of this._markers.values() ) {\n\t\t\tif ( marker.name.startsWith( prefix + ':' ) ) {\n\t\t\t\tyield marker;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Destroys the marker.\n\t *\n\t * @private\n\t * @param {module:engine/model/markercollection~Marker} marker Marker to destroy.\n\t */\n\t_destroyMarker( marker ) {\n\t\tmarker.stopListening();\n\t\tmarker._detachLiveRange();\n\t}\n\n\t/**\n\t * Fired whenever marker is added, updated or removed from `MarkerCollection`.\n\t *\n\t * @event update\n\t * @param {module:engine/model/markercollection~Marker} marker Updated Marker.\n\t * @param {module:engine/model/range~Range|null} oldRange Marker range before the update. When is not defined it\n\t * means that marker is just added.\n\t * @param {module:engine/model/range~Range|null} newRange Marker range after update. When is not defined it\n\t * means that marker is just removed.\n\t */\n}\n\nmix( MarkerCollection, EmitterMixin );\n\n/**\n * `Marker` is a continuous parts of model (like a range), is named and represent some kind of information about marked\n * part of model document. In contrary to {@link module:engine/model/node~Node nodes}, which are building blocks of\n * model document tree, markers are not stored directly in document tree but in\n * {@link module:engine/model/model~Model#markers model markers' collection}. Still, they are document data, by giving\n * additional meaning to the part of a model document between marker start and marker end.\n *\n * In this sense, markers are similar to adding and converting attributes on nodes. The difference is that attribute is\n * connected with a given node (e.g. a character is bold no matter if it gets moved or content around it changes).\n * Markers on the other hand are continuous ranges and are characterized by their start and end position. This means that\n * any character in the marker is marked by the marker. For example, if a character is moved outside of marker it stops being\n * \"special\" and the marker is shrunk. Similarly, when a character is moved into the marker from other place in document\n * model, it starts being \"special\" and the marker is enlarged.\n *\n * Another upside of markers is that finding marked part of document is fast and easy. Using attributes to mark some nodes\n * and then trying to find that part of document would require traversing whole document tree. Marker gives instant access\n * to the range which it is marking at the moment.\n *\n * Markers are built from a name and a range.\n *\n * Range of the marker is updated automatically when document changes, using\n * {@link module:engine/model/liverange~LiveRange live range} mechanism.\n *\n * Name is used to group and identify markers. Names have to be unique, but markers can be grouped by\n * using common prefixes, separated with `:`, for example: `user:john` or `search:3`. That's useful in term of creating\n * namespaces for custom elements (e.g. comments, highlights). You can use this prefixes in\n * {@link module:engine/model/markercollection~MarkerCollection#event:update} listeners to listen on changes in a group of markers.\n * For instance: `model.markers.on( 'update:user', callback );` will be called whenever any `user:*` markers changes.\n *\n * There are two types of markers.\n *\n * 1. Markers managed directly, without using operations. They are added directly by {@link module:engine/model/writer~Writer}\n * to the {@link module:engine/model/markercollection~MarkerCollection} without any additional mechanism. They can be used\n * as bookmarks or visual markers. They are great for showing results of the find, or select link when the focus is in the input.\n *\n * 1. Markers managed using operations. These markers are also stored in {@link module:engine/model/markercollection~MarkerCollection}\n * but changes in these markers is managed the same way all other changes in the model structure - using operations.\n * Therefore, they are handled in the undo stack and synchronized between clients if the collaboration plugin is enabled.\n * This type of markers is useful for solutions like spell checking or comments.\n *\n * Both type of them should be added / updated by {@link module:engine/model/writer~Writer#addMarker}\n * and removed by {@link module:engine/model/writer~Writer#removeMarker} methods.\n *\n *\t\tmodel.change( ( writer ) => {\n * \t\t\tconst marker = writer.addMarker( name, { range, usingOperation: true } );\n *\n * \t\t\t// ...\n *\n * \t\t\twriter.removeMarker( marker );\n *\t\t} );\n *\n * See {@link module:engine/model/writer~Writer} to find more examples.\n *\n * Since markers need to track change in the document, for efficiency reasons, it is best to create and keep as little\n * markers as possible and remove them as soon as they are not needed anymore.\n *\n * Markers can be downcasted and upcasted.\n *\n * Markers downcast happens on {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:addMarker} and\n * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:removeMarker} events.\n * Use {@link module:engine/conversion/downcasthelpers downcast converters} or attach a custom converter to mentioned events.\n * For {@link module:engine/controller/datacontroller~DataController data pipeline}, marker should be downcasted to an element.\n * Then, it can be upcasted back to a marker. Again, use {@link module:engine/conversion/upcasthelpers upcast converters} or\n * attach a custom converter to {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element}.\n *\n * `Marker` instances are created and destroyed only by {@link ~MarkerCollection MarkerCollection}.\n */\nclass Marker {\n\t/**\n\t * Creates a marker instance.\n\t *\n\t * @param {String} name Marker name.\n\t * @param {module:engine/model/liverange~LiveRange} liveRange Range marked by the marker.\n\t * @param {Boolean} managedUsingOperations Specifies whether the marker is managed using operations.\n\t * @param {Boolean} affectsData Specifies whether the marker affects the data produced by the data pipeline\n\t * (is persisted in the editor's data).\n\t */\n\tconstructor( name, liveRange, managedUsingOperations, affectsData ) {\n\t\t/**\n\t\t * Marker's name.\n\t\t *\n\t\t * @readonly\n\t\t * @type {String}\n\t\t */\n\t\tthis.name = name;\n\n\t\t/**\n\t\t * Range marked by the marker.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:engine/model/liverange~LiveRange}\n\t\t */\n\t\tthis._liveRange = this._attachLiveRange( liveRange );\n\n\t\t/**\n\t\t * Flag indicates if the marker is managed using operations or not.\n\t\t *\n\t\t * @private\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis._managedUsingOperations = managedUsingOperations;\n\n\t\t/**\n\t\t * Specifies whether the marker affects the data produced by the data pipeline\n\t\t * (is persisted in the editor's data).\n\t\t *\n\t\t * @private\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis._affectsData = affectsData;\n\t}\n\n\t/**\n\t * A value indicating if the marker is managed using operations.\n\t * See {@link ~Marker marker class description} to learn more about marker types.\n\t * See {@link module:engine/model/writer~Writer#addMarker}.\n\t *\n\t * @returns {Boolean}\n\t */\n\tget managedUsingOperations() {\n\t\tif ( !this._liveRange ) {\n\t\t\tthrow new CKEditorError( 'marker-destroyed', this );\n\t\t}\n\n\t\treturn this._managedUsingOperations;\n\t}\n\n\t/**\n\t * A value indicating if the marker changes the data.\n\t *\n\t * @returns {Boolean}\n\t */\n\tget affectsData() {\n\t\tif ( !this._liveRange ) {\n\t\t\tthrow new CKEditorError( 'marker-destroyed', this );\n\t\t}\n\n\t\treturn this._affectsData;\n\t}\n\n\t/**\n\t * Returns current marker start position.\n\t *\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tgetStart() {\n\t\tif ( !this._liveRange ) {\n\t\t\tthrow new CKEditorError( 'marker-destroyed', this );\n\t\t}\n\n\t\treturn this._liveRange.start.clone();\n\t}\n\n\t/**\n\t * Returns current marker end position.\n\t *\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tgetEnd() {\n\t\tif ( !this._liveRange ) {\n\t\t\tthrow new CKEditorError( 'marker-destroyed', this );\n\t\t}\n\n\t\treturn this._liveRange.end.clone();\n\t}\n\n\t/**\n\t * Returns a range that represents the current state of the marker.\n\t *\n\t * Keep in mind that returned value is a {@link module:engine/model/range~Range Range}, not a\n\t * {@link module:engine/model/liverange~LiveRange LiveRange}. This means that it is up-to-date and relevant only\n\t * until next model document change. Do not store values returned by this method. Instead, store {@link ~Marker#name}\n\t * and get `Marker` instance from {@link module:engine/model/markercollection~MarkerCollection MarkerCollection} every\n\t * time there is a need to read marker properties. This will guarantee that the marker has not been removed and\n\t * that it's data is up-to-date.\n\t *\n\t * @returns {module:engine/model/range~Range}\n\t */\n\tgetRange() {\n\t\tif ( !this._liveRange ) {\n\t\t\tthrow new CKEditorError( 'marker-destroyed', this );\n\t\t}\n\n\t\treturn this._liveRange.toRange();\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\tmarker.is( 'marker' ); // -> true\n\t *\t\tmarker.is( 'model:marker' ); // -> true\n\t *\n\t *\t\tmarker.is( 'view:element' ); // -> false\n\t *\t\tmarker.is( 'documentSelection' ); // -> 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 === 'marker' || type === 'model:marker';\n\t}\n\n\t/**\n\t * Binds new live range to the marker and detach the old one if is attached.\n\t *\n\t * @protected\n\t * @param {module:engine/model/liverange~LiveRange} liveRange Live range to attach\n\t * @returns {module:engine/model/liverange~LiveRange} Attached live range.\n\t */\n\t_attachLiveRange( liveRange ) {\n\t\tif ( this._liveRange ) {\n\t\t\tthis._detachLiveRange();\n\t\t}\n\n\t\t// Delegating does not work with namespaces. Alternatively, we could delegate all events (using `*`).\n\t\tliveRange.delegate( 'change:range' ).to( this );\n\t\tliveRange.delegate( 'change:content' ).to( this );\n\n\t\tthis._liveRange = liveRange;\n\n\t\treturn liveRange;\n\t}\n\n\t/**\n\t * Unbinds and destroys currently attached live range.\n\t *\n\t * @protected\n\t */\n\t_detachLiveRange() {\n\t\tthis._liveRange.stopDelegating( 'change:range', this );\n\t\tthis._liveRange.stopDelegating( 'change:content', this );\n\t\tthis._liveRange.detach();\n\t\tthis._liveRange = null;\n\t}\n\n\t/**\n\t * Fired whenever {@link ~Marker#_liveRange marker range} is changed due to changes on {@link module:engine/model/document~Document}.\n\t * This is a delegated {@link module:engine/model/liverange~LiveRange#event:change:range LiveRange change:range event}.\n\t *\n\t * When marker is removed from {@link module:engine/model/markercollection~MarkerCollection MarkerCollection},\n\t * all event listeners listening to it should be removed. It is best to do it on\n\t * {@link module:engine/model/markercollection~MarkerCollection#event:update MarkerCollection update event}.\n\t *\n\t * @see module:engine/model/liverange~LiveRange#event:change:range\n\t * @event change:range\n\t * @param {module:engine/model/range~Range} oldRange\n\t * @param {Object} data\n\t */\n\n\t/**\n\t * Fired whenever change on {@link module:engine/model/document~Document} is done inside {@link ~Marker#_liveRange marker range}.\n\t * This is a delegated {@link module:engine/model/liverange~LiveRange#event:change:content LiveRange change:content event}.\n\t *\n\t * When marker is removed from {@link module:engine/model/markercollection~MarkerCollection MarkerCollection},\n\t * all event listeners listening to it should be removed. It is best to do it on\n\t * {@link module:engine/model/markercollection~MarkerCollection#event:update MarkerCollection update event}.\n\t *\n\t * @see module:engine/model/liverange~LiveRange#event:change:content\n\t * @event change:content\n\t * @param {module:engine/model/range~Range} oldRange\n\t * @param {Object} data\n\t */\n}\n\nmix( Marker, EmitterMixin );\n\n/**\n * Cannot use a {@link module:engine/model/markercollection~MarkerCollection#destroy destroyed marker} instance.\n *\n * @error marker-destroyed\n */\n","/**\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/liveposition\n */\n\nimport Position from './position';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * `LivePosition` is a type of {@link module:engine/model/position~Position Position}\n * that updates itself as {@link module:engine/model/document~Document document}\n * is changed through operations. It may be used as a bookmark.\n *\n * **Note:** Contrary to {@link module:engine/model/position~Position}, `LivePosition` works only in roots that are\n * {@link module:engine/model/rootelement~RootElement}.\n * If {@link module:engine/model/documentfragment~DocumentFragment} is passed, error will be thrown.\n *\n * **Note:** Be very careful when dealing with `LivePosition`. Each `LivePosition` instance bind events that might\n * have to be unbound.\n * Use {@link module:engine/model/liveposition~LivePosition#detach} whenever you don't need `LivePosition` anymore.\n *\n * @extends module:engine/model/position~Position\n */\nexport default class LivePosition extends Position {\n\t/**\n\t * Creates a live position.\n\t *\n\t * @see module:engine/model/position~Position\n\t * @param {module:engine/model/rootelement~RootElement} root\n\t * @param {Array.} path\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness]\n\t */\n\tconstructor( root, path, stickiness = 'toNone' ) {\n\t\tsuper( root, path, stickiness );\n\n\t\tif ( !this.root.is( 'rootElement' ) ) {\n\t\t\t/**\n\t\t\t * LivePosition's root has to be an instance of RootElement.\n\t\t\t *\n\t\t\t * @error model-liveposition-root-not-rootelement\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'model-liveposition-root-not-rootelement', root );\n\t\t}\n\n\t\tbindWithDocument.call( this );\n\t}\n\n\t/**\n\t * Unbinds all events previously bound by `LivePosition`. Use it whenever you don't need `LivePosition` instance\n\t * anymore (i.e. when leaving scope in which it was declared or before re-assigning variable that was\n\t * referring to it).\n\t */\n\tdetach() {\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\tlivePosition.is( 'position' ); // -> true\n\t *\t\tlivePosition.is( 'model:position' ); // -> true\n\t *\t\tlivePosition.is( 'liveposition' ); // -> true\n\t *\t\tlivePosition.is( 'model:livePosition' ); // -> true\n\t *\n\t *\t\tlivePosition.is( 'view:position' ); // -> false\n\t *\t\tlivePosition.is( 'documentSelection' ); // -> 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 === 'livePosition' || type === 'model:livePosition' ||\n\t\t\t// From super.is(). This is highly utilised method and cannot call super. See ckeditor/ckeditor5#6529.\n\t\t\ttype == 'position' || type === 'model:position';\n\t}\n\n\t/**\n\t * Creates a {@link module:engine/model/position~Position position instance}, which is equal to this live position.\n\t *\n\t * @returns {module:engine/model/position~Position}\n\t */\n\ttoPosition() {\n\t\treturn new Position( this.root, this.path.slice(), this.stickiness );\n\t}\n\n\t/**\n\t * Creates a `LivePosition` instance that is equal to position.\n\t *\n\t * @param {module:engine/model/position~Position} position\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness]\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tstatic fromPosition( position, stickiness ) {\n\t\treturn new this( position.root, position.path.slice(), stickiness ? stickiness : position.stickiness );\n\t}\n\n\t/**\n\t * @static\n\t * @protected\n\t * @method module:engine/model/liveposition~LivePosition._createAfter\n\t * @see module:engine/model/position~Position._createAfter\n\t * @param {module:engine/model/node~Node} node\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone']\n\t * @returns {module:engine/model/liveposition~LivePosition}\n\t */\n\n\t/**\n\t * @static\n\t * @protected\n\t * @method module:engine/model/liveposition~LivePosition._createBefore\n\t * @see module:engine/model/position~Position._createBefore\n\t * @param {module:engine/model/node~Node} node\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone']\n\t * @returns {module:engine/model/liveposition~LivePosition}\n\t */\n\n\t/**\n\t * @static\n\t * @protected\n\t * @method module:engine/model/liveposition~LivePosition._createAt\n\t * @see module:engine/model/position~Position._createAt\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset]\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone']\n\t * @returns {module:engine/model/liveposition~LivePosition}\n\t */\n\n\t/**\n\t * Fired when `LivePosition` instance is changed due to changes on {@link module:engine/model/document~Document}.\n\t *\n\t * @event module:engine/model/liveposition~LivePosition#change\n\t * @param {module:engine/model/position~Position} oldPosition Position equal to this live position before it got changed.\n\t */\n}\n\n// Binds this `LivePosition` to the {@link module:engine/model/document~Document document} that owns\n// this position's {@link module:engine/model/position~Position#root root}.\n//\n// @private\nfunction bindWithDocument() {\n\tthis.listenTo(\n\t\tthis.root.document.model,\n\t\t'applyOperation',\n\t\t( event, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( !operation.isDocumentOperation ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttransform.call( this, operation );\n\t\t},\n\t\t{ priority: 'low' }\n\t);\n}\n\n// Updates this position accordingly to the updates applied to the model. Bases on change events.\n//\n// @private\n// @param {module:engine/model/operation/operation~Operation} operation Executed operation.\nfunction transform( operation ) {\n\tconst result = this.getTransformedByOperation( operation );\n\n\tif ( !this.isEqual( result ) ) {\n\t\tconst oldPosition = this.toPosition();\n\n\t\tthis.path = result.path;\n\t\tthis.root = result.root;\n\n\t\tthis.fire( 'change', oldPosition );\n\t}\n}\n\nmix( LivePosition, EmitterMixin );\n","/**\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/element\n */\n\nimport Node from './node';\nimport NodeList from './nodelist';\nimport Text from './text';\nimport TextProxy from './textproxy';\nimport isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';\n\n// @if CK_DEBUG_ENGINE // const { stringifyMap, convertMapToStringifiedObject, convertMapToTags } = require( '../dev-utils/utils' );\n\n/**\n * Model element. Type of {@link module:engine/model/node~Node node} that has a {@link module:engine/model/element~Element#name name} and\n * {@link module:engine/model/element~Element#getChildren child nodes}.\n *\n * **Important**: see {@link module:engine/model/node~Node} to read about restrictions using `Element` and `Node` API.\n *\n * @extends module:engine/model/node~Node\n */\nexport default class Element extends Node {\n\t/**\n\t * Creates a model element.\n\t *\n\t * **Note:** Constructor of this class shouldn't be used directly in the code.\n\t * Use the {@link module:engine/model/writer~Writer#createElement} method instead.\n\t *\n\t * @protected\n\t * @param {String} name Element's name.\n\t * @param {Object} [attrs] Element's attributes. See {@link module:utils/tomap~toMap} for a list of accepted values.\n\t * @param {module:engine/model/node~Node|Iterable.} [children]\n\t * One or more nodes to be inserted as children of created element.\n\t */\n\tconstructor( name, attrs, children ) {\n\t\tsuper( attrs );\n\n\t\t/**\n\t\t * Element name.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String} module:engine/model/element~Element#name\n\t\t */\n\t\tthis.name = name;\n\n\t\t/**\n\t\t * List of children nodes.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/nodelist~NodeList} module:engine/model/element~Element#_children\n\t\t */\n\t\tthis._children = new NodeList();\n\n\t\tif ( children ) {\n\t\t\tthis._insertChild( 0, children );\n\t\t}\n\t}\n\n\t/**\n\t * Number of this element's children.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget childCount() {\n\t\treturn this._children.length;\n\t}\n\n\t/**\n\t * Sum of {@link module:engine/model/node~Node#offsetSize offset sizes} of all of this element's children.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget maxOffset() {\n\t\treturn this._children.maxOffset;\n\t}\n\n\t/**\n\t * Is `true` if there are no nodes inside this element, `false` otherwise.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isEmpty() {\n\t\treturn this.childCount === 0;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\telement.is( 'element' ); // -> true\n\t *\t\telement.is( 'node' ); // -> true\n\t *\t\telement.is( 'model:element' ); // -> true\n\t *\t\telement.is( 'model:node' ); // -> true\n\t *\n\t *\t\telement.is( 'view:element' ); // -> false\n\t *\t\telement.is( 'documentSelection' ); // -> false\n\t *\n\t * Assuming that the object being checked is an element, you can also check its\n\t * {@link module:engine/model/element~Element#name name}:\n\t *\n\t *\t\telement.is( 'element', 'image' ); // -> true if this is an element\n\t *\t\telement.is( 'element', 'image' ); // -> same as above\n\t *\t\ttext.is( 'element', 'image' ); -> 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 Type to check.\n\t * @param {String} [name] Element name.\n\t * @returns {Boolean}\n\t */\n\tis( type, name = null ) {\n\t\tif ( !name ) {\n\t\t\treturn type === 'element' || type === 'model:element' ||\n\t\t\t\t// From super.is(). This is highly utilised method and cannot call super. See ckeditor/ckeditor5#6529.\n\t\t\t\ttype === 'node' || type === 'model:node';\n\t\t}\n\n\t\treturn name === this.name && ( type === 'element' || type === 'model:element' );\n\t}\n\n\t/**\n\t * Gets the child at the given index.\n\t *\n\t * @param {Number} index Index of child.\n\t * @returns {module:engine/model/node~Node} Child node.\n\t */\n\tgetChild( index ) {\n\t\treturn this._children.getNode( index );\n\t}\n\n\t/**\n\t * Returns an iterator that iterates over all of this element's children.\n\t *\n\t * @returns {Iterable.}\n\t */\n\tgetChildren() {\n\t\treturn this._children[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Returns an index of the given child node. Returns `null` if given node is not a child of this element.\n\t *\n\t * @param {module:engine/model/node~Node} node Child node to look for.\n\t * @returns {Number} Child node's index in this element.\n\t */\n\tgetChildIndex( node ) {\n\t\treturn this._children.getNodeIndex( node );\n\t}\n\n\t/**\n\t * Returns the starting offset of given child. Starting offset is equal to the sum of\n\t * {@link module:engine/model/node~Node#offsetSize offset sizes} of all node's siblings that are before it. Returns `null` if\n\t * given node is not a child of this element.\n\t *\n\t * @param {module:engine/model/node~Node} node Child node to look for.\n\t * @returns {Number} Child node's starting offset.\n\t */\n\tgetChildStartOffset( node ) {\n\t\treturn this._children.getNodeStartOffset( node );\n\t}\n\n\t/**\n\t * Returns index of a node that occupies given offset. If given offset is too low, returns `0`. If given offset is\n\t * too high, returns {@link module:engine/model/element~Element#getChildIndex index after last child}.\n\t *\n\t *\t\tconst textNode = new Text( 'foo' );\n\t *\t\tconst pElement = new Element( 'p' );\n\t *\t\tconst divElement = new Element( [ textNode, pElement ] );\n\t *\t\tdivElement.offsetToIndex( -1 ); // Returns 0, because offset is too low.\n\t *\t\tdivElement.offsetToIndex( 0 ); // Returns 0, because offset 0 is taken by `textNode` which is at index 0.\n\t *\t\tdivElement.offsetToIndex( 1 ); // Returns 0, because `textNode` has `offsetSize` equal to 3, so it occupies offset 1 too.\n\t *\t\tdivElement.offsetToIndex( 2 ); // Returns 0.\n\t *\t\tdivElement.offsetToIndex( 3 ); // Returns 1.\n\t *\t\tdivElement.offsetToIndex( 4 ); // Returns 2. There are no nodes at offset 4, so last available index is returned.\n\t *\n\t * @param {Number} offset Offset to look for.\n\t * @returns {Number}\n\t */\n\toffsetToIndex( offset ) {\n\t\treturn this._children.offsetToIndex( offset );\n\t}\n\n\t/**\n\t * Returns a descendant node by its path relative to this element.\n\t *\n\t *\t\t// ac\n\t *\t\tthis.getNodeByPath( [ 0 ] ); // -> \"a\"\n\t *\t\tthis.getNodeByPath( [ 1 ] ); // -> \n\t *\t\tthis.getNodeByPath( [ 1, 0 ] ); // -> \"c\"\n\t *\n\t * @param {Array.} relativePath Path of the node to find, relative to this element.\n\t * @returns {module:engine/model/node~Node}\n\t */\n\tgetNodeByPath( relativePath ) {\n\t\tlet node = this; // eslint-disable-line consistent-this\n\n\t\tfor ( const index of relativePath ) {\n\t\t\tnode = node.getChild( node.offsetToIndex( index ) );\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Returns the parent element of the given name. Returns null if the element is not inside the desired parent.\n\t *\n\t * @param {String} parentName The name of the parent element to find.\n\t * @param {Object} [options] Options object.\n\t * @param {Boolean} [options.includeSelf=false] When set to `true` this node will be also included while searching.\n\t * @returns {module:engine/model/element~Element|null}\n\t */\n\tfindAncestor( parentName, options = { includeSelf: false } ) {\n\t\tlet parent = options.includeSelf ? this : this.parent;\n\n\t\twhile ( parent ) {\n\t\t\tif ( parent.name === parentName ) {\n\t\t\t\treturn parent;\n\t\t\t}\n\n\t\t\tparent = parent.parent;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Converts `Element` instance to plain object and returns it. Takes care of converting all of this element's children.\n\t *\n\t * @returns {Object} `Element` instance converted to plain object.\n\t */\n\ttoJSON() {\n\t\tconst json = super.toJSON();\n\n\t\tjson.name = this.name;\n\n\t\tif ( this._children.length > 0 ) {\n\t\t\tjson.children = [];\n\n\t\t\tfor ( const node of this._children ) {\n\t\t\t\tjson.children.push( node.toJSON() );\n\t\t\t}\n\t\t}\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * Creates a copy of this element and returns it. Created element has the same name and attributes as the original element.\n\t * If clone is deep, the original element's children are also cloned. If not, then empty element is returned.\n\t *\n\t * @protected\n\t * @param {Boolean} [deep=false] If set to `true` clones element and all its children recursively. When set to `false`,\n\t * element will be cloned without any child.\n\t */\n\t_clone( deep = false ) {\n\t\tconst children = deep ? Array.from( this._children ).map( node => node._clone( true ) ) : null;\n\n\t\treturn new Element( this.name, this.getAttributes(), children );\n\t}\n\n\t/**\n\t * {@link module:engine/model/element~Element#_insertChild Inserts} one or more nodes at the end of this element.\n\t *\n\t * @see module:engine/model/writer~Writer#append\n\t * @protected\n\t * @param {module:engine/model/item~Item|Iterable.} nodes Nodes to be inserted.\n\t */\n\t_appendChild( nodes ) {\n\t\tthis._insertChild( this.childCount, nodes );\n\t}\n\n\t/**\n\t * Inserts one or more nodes at the given index and sets {@link module:engine/model/node~Node#parent parent} of these nodes\n\t * to this element.\n\t *\n\t * @see module:engine/model/writer~Writer#insert\n\t * @protected\n\t * @param {Number} index Index at which nodes should be inserted.\n\t * @param {module:engine/model/item~Item|Iterable.} items Items to be inserted.\n\t */\n\t_insertChild( index, items ) {\n\t\tconst nodes = normalize( items );\n\n\t\tfor ( const node of nodes ) {\n\t\t\t// If node that is being added to this element is already inside another element, first remove it from the old parent.\n\t\t\tif ( node.parent !== null ) {\n\t\t\t\tnode._remove();\n\t\t\t}\n\n\t\t\tnode.parent = this;\n\t\t}\n\n\t\tthis._children._insertNodes( index, nodes );\n\t}\n\n\t/**\n\t * Removes one or more nodes starting at the given index and sets\n\t * {@link module:engine/model/node~Node#parent parent} of these nodes to `null`.\n\t *\n\t * @see module:engine/model/writer~Writer#remove\n\t * @protected\n\t * @param {Number} index Index of the first node to remove.\n\t * @param {Number} [howMany=1] Number of nodes to remove.\n\t * @returns {Array.} Array containing removed nodes.\n\t */\n\t_removeChildren( index, howMany = 1 ) {\n\t\tconst nodes = this._children._removeNodes( index, howMany );\n\n\t\tfor ( const node of nodes ) {\n\t\t\tnode.parent = null;\n\t\t}\n\n\t\treturn nodes;\n\t}\n\n\t/**\n\t * Creates an `Element` instance from given plain object (i.e. parsed JSON string).\n\t * Converts `Element` children to proper nodes.\n\t *\n\t * @param {Object} json Plain object to be converted to `Element`.\n\t * @returns {module:engine/model/element~Element} `Element` instance created using given plain object.\n\t */\n\tstatic fromJSON( json ) {\n\t\tlet children = null;\n\n\t\tif ( json.children ) {\n\t\t\tchildren = [];\n\n\t\t\tfor ( const child of json.children ) {\n\t\t\t\tif ( child.name ) {\n\t\t\t\t\t// If child has name property, it is an Element.\n\t\t\t\t\tchildren.push( Element.fromJSON( child ) );\n\t\t\t\t} else {\n\t\t\t\t\t// Otherwise, it is a Text node.\n\t\t\t\t\tchildren.push( Text.fromJSON( child ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn new Element( json.name, json.attributes, children );\n\t}\n\n\t// @if CK_DEBUG_ENGINE // toString() {\n\t// @if CK_DEBUG_ENGINE // \treturn `<${ this.rootName || this.name }>`;\n\t// @if CK_DEBUG_ENGINE // }\n\n\t// @if CK_DEBUG_ENGINE // log() {\n\t// @if CK_DEBUG_ENGINE // \tconsole.log( 'ModelElement: ' + this );\n\t// @if CK_DEBUG_ENGINE // }\n\n\t// @if CK_DEBUG_ENGINE // logExtended() {\n\t// @if CK_DEBUG_ENGINE // \tconsole.log( `ModelElement: ${ this }, ${ this.childCount } children,\n\t// @if CK_DEBUG_ENGINE //\t\tattrs: ${ convertMapToStringifiedObject( this.getAttributes() ) }` );\n\t// @if CK_DEBUG_ENGINE // }\n\n\t// @if CK_DEBUG_ENGINE // logAll() {\n\t// @if CK_DEBUG_ENGINE // \tconsole.log( '--------------------' );\n\t// @if CK_DEBUG_ENGINE //\n\t// @if CK_DEBUG_ENGINE // \tthis.logExtended();\n\t// @if CK_DEBUG_ENGINE //\tconsole.log( 'List of children:' );\n\t// @if CK_DEBUG_ENGINE //\n\t// @if CK_DEBUG_ENGINE // \tfor ( const child of this.getChildren() ) {\n\t// @if CK_DEBUG_ENGINE // \t\tchild.log();\n\t// @if CK_DEBUG_ENGINE // \t}\n\t// @if CK_DEBUG_ENGINE // }\n\n\t// @if CK_DEBUG_ENGINE // printTree( level = 0) {\n\t// @if CK_DEBUG_ENGINE // \tlet string = '';\n\n\t// @if CK_DEBUG_ENGINE // \tstring += '\\t'.repeat( level );\n\t// @if CK_DEBUG_ENGINE // \tstring += `<${ this.rootName || this.name }${ convertMapToTags( this.getAttributes() ) }>`;\n\n\t// @if CK_DEBUG_ENGINE // \tfor ( const child of this.getChildren() ) {\n\t// @if CK_DEBUG_ENGINE // \t\tstring += '\\n';\n\n\t// @if CK_DEBUG_ENGINE // \t\tif ( child.is( '$text' ) ) {\n\t// @if CK_DEBUG_ENGINE // \t\t\tconst textAttrs = convertMapToTags( child._attrs );\n\n\t// @if CK_DEBUG_ENGINE // \t\t\tstring += '\\t'.repeat( level + 1 );\n\n\t// @if CK_DEBUG_ENGINE // \t\t\tif ( textAttrs !== '' ) {\n\t// @if CK_DEBUG_ENGINE // \t\t\t\tstring += `<$text${ textAttrs }>` + child.data + '';\n\t// @if CK_DEBUG_ENGINE // \t\t\t} else {\n\t// @if CK_DEBUG_ENGINE // \t\t\t\tstring += child.data;\n\t// @if CK_DEBUG_ENGINE // \t\t\t}\n\t// @if CK_DEBUG_ENGINE // \t\t} else {\n\t// @if CK_DEBUG_ENGINE // \t\t\tstring += child.printTree( level + 1 );\n\t// @if CK_DEBUG_ENGINE // \t\t}\n\t// @if CK_DEBUG_ENGINE // \t}\n\n\t// @if CK_DEBUG_ENGINE // \tif ( this.childCount ) {\n\t// @if CK_DEBUG_ENGINE // \t\tstring += '\\n' + '\\t'.repeat( level );\n\t// @if CK_DEBUG_ENGINE // \t}\n\n\t// @if CK_DEBUG_ENGINE // \tstring += ``;\n\n\t// @if CK_DEBUG_ENGINE // \treturn string;\n\t// @if CK_DEBUG_ENGINE // }\n\n\t// @if CK_DEBUG_ENGINE // logTree() {\n\t// @if CK_DEBUG_ENGINE // \tconsole.log( this.printTree() );\n\t// @if CK_DEBUG_ENGINE // }\n}\n\n// Converts strings to Text and non-iterables to arrays.\n//\n// @param {String|module:engine/model/item~Item|Iterable.}\n// @returns {Iterable.}\nfunction normalize( nodes ) {\n\t// Separate condition because string is iterable.\n\tif ( typeof nodes == 'string' ) {\n\t\treturn [ new Text( nodes ) ];\n\t}\n\n\tif ( !isIterable( nodes ) ) {\n\t\tnodes = [ nodes ];\n\t}\n\n\t// Array.from to enable .map() on non-arrays.\n\treturn Array.from( nodes )\n\t\t.map( node => {\n\t\t\tif ( typeof node == 'string' ) {\n\t\t\t\treturn new Text( node );\n\t\t\t}\n\n\t\t\tif ( node instanceof TextProxy ) {\n\t\t\t\treturn new Text( node.data, node.getAttributes() );\n\t\t\t}\n\n\t\t\treturn node;\n\t\t} );\n}\n","/**\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","/**\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 module:engine/model/documentfragment\n */\n\nimport NodeList from './nodelist';\nimport Element from './element';\nimport Text from './text';\nimport TextProxy from './textproxy';\nimport isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';\n\n// @if CK_DEBUG_ENGINE // const { stringifyMap } = require( '../dev-utils/utils' );\n\n/**\n * DocumentFragment represents a part of model which does not have a common root but its top-level nodes\n * can be seen as siblings. In other words, it is a detached part of model tree, without a root.\n *\n * DocumentFragment has own {@link module:engine/model/markercollection~MarkerCollection}. Markers from this collection\n * will be set to the {@link module:engine/model/model~Model#markers model markers} by a\n * {@link module:engine/model/writer~Writer#insert} function.\n */\nexport default class DocumentFragment {\n\t/**\n\t * Creates an empty `DocumentFragment`.\n\t *\n\t * **Note:** Constructor of this class shouldn't be used directly in the code.\n\t * Use the {@link module:engine/model/writer~Writer#createDocumentFragment} method instead.\n\t *\n\t * @protected\n\t * @param {module:engine/model/node~Node|Iterable.} [children]\n\t * Nodes to be contained inside the `DocumentFragment`.\n\t */\n\tconstructor( children ) {\n\t\t/**\n\t\t * DocumentFragment static markers map. This is a list of names and {@link module:engine/model/range~Range ranges}\n\t\t * which will be set as Markers to {@link module:engine/model/model~Model#markers model markers collection}\n\t\t * when DocumentFragment will be inserted to the document.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Map} module:engine/model/documentfragment~DocumentFragment#markers\n\t\t */\n\t\tthis.markers = new Map();\n\n\t\t/**\n\t\t * List of nodes contained inside the document fragment.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/nodelist~NodeList} module:engine/model/documentfragment~DocumentFragment#_children\n\t\t */\n\t\tthis._children = new NodeList();\n\n\t\tif ( children ) {\n\t\t\tthis._insertChild( 0, children );\n\t\t}\n\t}\n\n\t/**\n\t * Returns an iterator that iterates over all nodes contained inside this document fragment.\n\t *\n\t * @returns {Iterable.}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this.getChildren();\n\t}\n\n\t/**\n\t * Number of this document fragment's children.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget childCount() {\n\t\treturn this._children.length;\n\t}\n\n\t/**\n\t * Sum of {@link module:engine/model/node~Node#offsetSize offset sizes} of all of this document fragment's children.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget maxOffset() {\n\t\treturn this._children.maxOffset;\n\t}\n\n\t/**\n\t * Is `true` if there are no nodes inside this document fragment, `false` otherwise.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isEmpty() {\n\t\treturn this.childCount === 0;\n\t}\n\n\t/**\n\t * Artificial root of `DocumentFragment`. Returns itself. Added for compatibility reasons.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/documentfragment~DocumentFragment}\n\t */\n\tget root() {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Artificial parent of `DocumentFragment`. Returns `null`. Added for compatibility reasons.\n\t *\n\t * @readonly\n\t * @type {null}\n\t */\n\tget parent() {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t *\t\tdocFrag.is( 'documentFragment' ); // -> true\n\t *\t\tdocFrag.is( 'model:documentFragment' ); // -> true\n\t *\n\t *\t\tdocFrag.is( 'view:documentFragment' ); // -> false\n\t *\t\tdocFrag.is( 'element' ); // -> false\n\t *\t\tdocFrag.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 === 'documentFragment' || type === 'model:documentFragment';\n\t}\n\n\t/**\n\t * Gets the child at the given index. Returns `null` if incorrect index was passed.\n\t *\n\t * @param {Number} index Index of child.\n\t * @returns {module:engine/model/node~Node|null} Child node.\n\t */\n\tgetChild( index ) {\n\t\treturn this._children.getNode( index );\n\t}\n\n\t/**\n\t * Returns an iterator that iterates over all of this document fragment's children.\n\t *\n\t * @returns {Iterable.}\n\t */\n\tgetChildren() {\n\t\treturn this._children[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Returns an index of the given child node. Returns `null` if given node is not a child of this document fragment.\n\t *\n\t * @param {module:engine/model/node~Node} node Child node to look for.\n\t * @returns {Number|null} Child node's index.\n\t */\n\tgetChildIndex( node ) {\n\t\treturn this._children.getNodeIndex( node );\n\t}\n\n\t/**\n\t * Returns the starting offset of given child. Starting offset is equal to the sum of\n\t * {@link module:engine/model/node~Node#offsetSize offset sizes} of all node's siblings that are before it. Returns `null` if\n\t * given node is not a child of this document fragment.\n\t *\n\t * @param {module:engine/model/node~Node} node Child node to look for.\n\t * @returns {Number|null} Child node's starting offset.\n\t */\n\tgetChildStartOffset( node ) {\n\t\treturn this._children.getNodeStartOffset( node );\n\t}\n\n\t/**\n\t * Returns path to a `DocumentFragment`, which is an empty array. Added for compatibility reasons.\n\t *\n\t * @returns {Array}\n\t */\n\tgetPath() {\n\t\treturn [];\n\t}\n\n\t/**\n\t * Returns a descendant node by its path relative to this element.\n\t *\n\t *\t\t// ac\n\t *\t\tthis.getNodeByPath( [ 0 ] ); // -> \"a\"\n\t *\t\tthis.getNodeByPath( [ 1 ] ); // -> \n\t *\t\tthis.getNodeByPath( [ 1, 0 ] ); // -> \"c\"\n\t *\n\t * @param {Array.} relativePath Path of the node to find, relative to this element.\n\t * @returns {module:engine/model/node~Node|module:engine/model/documentfragment~DocumentFragment}\n\t */\n\tgetNodeByPath( relativePath ) {\n\t\tlet node = this; // eslint-disable-line consistent-this\n\n\t\tfor ( const index of relativePath ) {\n\t\t\tnode = node.getChild( node.offsetToIndex( index ) );\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Converts offset \"position\" to index \"position\".\n\t *\n\t * Returns index of a node that occupies given offset. If given offset is too low, returns `0`. If given offset is\n\t * too high, returns index after last child}.\n\t *\n\t *\t\tconst textNode = new Text( 'foo' );\n\t *\t\tconst pElement = new Element( 'p' );\n\t *\t\tconst docFrag = new DocumentFragment( [ textNode, pElement ] );\n\t *\t\tdocFrag.offsetToIndex( -1 ); // Returns 0, because offset is too low.\n\t *\t\tdocFrag.offsetToIndex( 0 ); // Returns 0, because offset 0 is taken by `textNode` which is at index 0.\n\t *\t\tdocFrag.offsetToIndex( 1 ); // Returns 0, because `textNode` has `offsetSize` equal to 3, so it occupies offset 1 too.\n\t *\t\tdocFrag.offsetToIndex( 2 ); // Returns 0.\n\t *\t\tdocFrag.offsetToIndex( 3 ); // Returns 1.\n\t *\t\tdocFrag.offsetToIndex( 4 ); // Returns 2. There are no nodes at offset 4, so last available index is returned.\n\t *\n\t * @param {Number} offset Offset to look for.\n\t * @returns {Number} Index of a node that occupies given offset.\n\t */\n\toffsetToIndex( offset ) {\n\t\treturn this._children.offsetToIndex( offset );\n\t}\n\n\t/**\n\t * Converts `DocumentFragment` instance to plain object and returns it.\n\t * Takes care of converting all of this document fragment's children.\n\t *\n\t * @returns {Object} `DocumentFragment` instance converted to plain object.\n\t */\n\ttoJSON() {\n\t\tconst json = [];\n\n\t\tfor ( const node of this._children ) {\n\t\t\tjson.push( node.toJSON() );\n\t\t}\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * Creates a `DocumentFragment` instance from given plain object (i.e. parsed JSON string).\n\t * Converts `DocumentFragment` children to proper nodes.\n\t *\n\t * @param {Object} json Plain object to be converted to `DocumentFragment`.\n\t * @returns {module:engine/model/documentfragment~DocumentFragment} `DocumentFragment` instance created using given plain object.\n\t */\n\tstatic fromJSON( json ) {\n\t\tconst children = [];\n\n\t\tfor ( const child of json ) {\n\t\t\tif ( child.name ) {\n\t\t\t\t// If child has name property, it is an Element.\n\t\t\t\tchildren.push( Element.fromJSON( child ) );\n\t\t\t} else {\n\t\t\t\t// Otherwise, it is a Text node.\n\t\t\t\tchildren.push( Text.fromJSON( child ) );\n\t\t\t}\n\t\t}\n\n\t\treturn new DocumentFragment( children );\n\t}\n\n\t/**\n\t * {@link #_insertChild Inserts} one or more nodes at the end of this document fragment.\n\t *\n\t * @protected\n\t * @param {module:engine/model/item~Item|Iterable.} items Items to be inserted.\n\t */\n\t_appendChild( items ) {\n\t\tthis._insertChild( this.childCount, items );\n\t}\n\n\t/**\n\t * Inserts one or more nodes at the given index and sets {@link module:engine/model/node~Node#parent parent} of these nodes\n\t * to this document fragment.\n\t *\n\t * @protected\n\t * @param {Number} index Index at which nodes should be inserted.\n\t * @param {module:engine/model/item~Item|Iterable.} items Items to be inserted.\n\t */\n\t_insertChild( index, items ) {\n\t\tconst nodes = normalize( items );\n\n\t\tfor ( const node of nodes ) {\n\t\t\t// If node that is being added to this element is already inside another element, first remove it from the old parent.\n\t\t\tif ( node.parent !== null ) {\n\t\t\t\tnode._remove();\n\t\t\t}\n\n\t\t\tnode.parent = this;\n\t\t}\n\n\t\tthis._children._insertNodes( index, nodes );\n\t}\n\n\t/**\n\t * Removes one or more nodes starting at the given index\n\t * and sets {@link module:engine/model/node~Node#parent parent} of these nodes to `null`.\n\t *\n\t * @protected\n\t * @param {Number} index Index of the first node to remove.\n\t * @param {Number} [howMany=1] Number of nodes to remove.\n\t * @returns {Array.} Array containing removed nodes.\n\t */\n\t_removeChildren( index, howMany = 1 ) {\n\t\tconst nodes = this._children._removeNodes( index, howMany );\n\n\t\tfor ( const node of nodes ) {\n\t\t\tnode.parent = null;\n\t\t}\n\n\t\treturn nodes;\n\t}\n\n\t// @if CK_DEBUG_ENGINE // toString() {\n\t// @if CK_DEBUG_ENGINE // \treturn 'documentFragment';\n\t// @if CK_DEBUG_ENGINE // }\n\n\t// @if CK_DEBUG_ENGINE // log() {\n\t// @if CK_DEBUG_ENGINE // \tconsole.log( 'ModelDocumentFragment: ' + this );\n\t// @if CK_DEBUG_ENGINE // }\n\n\t// @if CK_DEBUG_ENGINE // printTree() {\n\t// @if CK_DEBUG_ENGINE //\tlet string = 'ModelDocumentFragment: [';\n\n\t// @if CK_DEBUG_ENGINE //\tfor ( const child of this.getChildren() ) {\n\t// @if CK_DEBUG_ENGINE //\t\tstring += '\\n';\n\n\t// @if CK_DEBUG_ENGINE //\t\tif ( child.is( '$text' ) ) {\n\t// @if CK_DEBUG_ENGINE //\t\t\tconst textAttrs = stringifyMap( child._attrs );\n\n\t// @if CK_DEBUG_ENGINE //\t\t\tstring += '\\t'.repeat( 1 );\n\n\t// @if CK_DEBUG_ENGINE //\t\t\tif ( textAttrs !== '' ) {\n\t// @if CK_DEBUG_ENGINE //\t\t\t\tstring += `<$text${ textAttrs }>` + child.data + '';\n\t// @if CK_DEBUG_ENGINE //\t\t\t} else {\n\t// @if CK_DEBUG_ENGINE //\t\t\t\tstring += child.data;\n\t// @if CK_DEBUG_ENGINE //\t\t\t}\n\t// @if CK_DEBUG_ENGINE //\t\t} else {\n\t// @if CK_DEBUG_ENGINE //\t\t\tstring += child.printTree( 1 );\n\t// @if CK_DEBUG_ENGINE //\t\t}\n\t// @if CK_DEBUG_ENGINE //\t}\n\n\t// @if CK_DEBUG_ENGINE //\tstring += '\\n]';\n\n\t// @if CK_DEBUG_ENGINE //\treturn string;\n\t// @if CK_DEBUG_ENGINE // }\n\n\t// @if CK_DEBUG_ENGINE // logTree() {\n\t// @if CK_DEBUG_ENGINE // \tconsole.log( this.printTree() );\n\t// @if CK_DEBUG_ENGINE // }\n}\n\n// Converts strings to Text and non-iterables to arrays.\n//\n// @param {String|module:engine/model/item~Item|Iterable.}\n// @returns {Iterable.}\nfunction normalize( nodes ) {\n\t// Separate condition because string is iterable.\n\tif ( typeof nodes == 'string' ) {\n\t\treturn [ new Text( nodes ) ];\n\t}\n\n\tif ( !isIterable( nodes ) ) {\n\t\tnodes = [ nodes ];\n\t}\n\n\t// Array.from to enable .map() on non-arrays.\n\treturn Array.from( nodes )\n\t\t.map( node => {\n\t\t\tif ( typeof node == 'string' ) {\n\t\t\t\treturn new Text( node );\n\t\t\t}\n\n\t\t\tif ( node instanceof TextProxy ) {\n\t\t\t\treturn new Text( node.data, node.getAttributes() );\n\t\t\t}\n\n\t\t\treturn node;\n\t\t} );\n}\n"],"sourceRoot":""}