{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/view/rooteditableelement.js","webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/view/rawelement.js","webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/view/renderer.js"],"names":["rootNameSymbol","Symbol","RootEditableElement","document","name","_this","Object","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_classCallCheck_js__WEBPACK_IMPORTED_MODULE_2__","this","_super","call","rootName","type","arguments","length","undefined","getCustomProperty","_setCustomProperty","EditableElement","RawElement","attrs","children","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_classCallCheck_js__WEBPACK_IMPORTED_MODULE_4__","_isAllowedInsideAttributeElement","getFillerOffset","index","nodes","Node","Array","from","CKEditorError","Element","Renderer","domConverter","selection","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_classCallCheck_js__WEBPACK_IMPORTED_MODULE_9__","domDocuments","Set","markedAttributes","markedChildren","markedTexts","isFocused","_inlineFiller","_fakeSelectionContainer","node","mapViewToDom","parent","add","inlineFillerPosition","_step","_iterator","_createForOfIteratorHelper","s","n","done","element","value","_updateChildrenMappings","err","e","f","_isSelectionInInlineFiller","_removeInlineFiller","_getInlineFillerPosition","_needsInlineFillerAtSelection","getFirstPosition","_step2","_iterator2","_updateAttrs","_step3","_iterator3","_updateChildren","_step4","_iterator4","has","_updateText","fillerDomPosition","viewPositionToDom","domDocument","ownerDocument","startsWithFiller","addInlineFiller","offset","_updateFocus","_updateSelection","clear","viewElement","domElement","actualDomChildren","childNodes","expectedDomChildren","viewChildrenToDom","withChildren","diff","_diffNodeLists","actions","_findReplaceActions","indexOf","_step5","counter","equal","insert","delete","_iterator5","action","insertIndex","deleteIndex","viewChild","getChild","is","_updateElementMappings","remove","unbindDomElement","bindElements","firstPos","ViewPosition","_createBefore","rangeCount","isCollapsed","selectionPosition","position","isText","domFillerNode","isInlineFiller","parentNode","removeChild","data","substr","INLINE_FILLER_LENGTH","selectionParent","selectionOffset","root","isEditable","nodeBefore","nodeAfter","ViewText","viewText","options","domText","findCorrespondingDomText","newDomText","viewToDom","actualText","expectedText","filler","INLINE_FILLER","_step6","fastDiff","_iterator6","insertData","values","join","deleteData","howMany","_step7","domAttrKeys","attributes","map","attr","viewAttrKeys","getAttributeKeys","_iterator7","key","setAttribute","getAttribute","_step8","_iterator8","hasAttribute","removeAttribute","bind","_step9","i","nodesToUnbind","_iterator9","_step10","_iterator10","insertAt","_markDescendantTextToSync","domToView","_step11","_iterator11","filterOutFakeSelectionContainer","sameNodes","actualDom","expectedDom","_step12","newActions","actualSlice","expectedSlice","_iterator12","push","concat","areSimilar","x","viewNode","_step13","_iterator13","getChildren","child","_removeDomSelection","_removeFakeSelection","domRoot","editableElement","isFake","_updateFakeSelection","_updateDomSelection","createFakeSelectionContainer","container","bindFakeSelection","_fakeSelectionNeedsUpdate","parentElement","appendChild","textContent","fakeSelectionLabel","domSelection","getSelection","domRange","createRange","removeAllRanges","selectNodeContents","addRange","defaultView","_domSelectionNeedsUpdate","anchor","focus","collapse","extend","env","isGecko","fixGeckoSelectionAfterBr","isDomSelectionCorrect","oldViewSelection","domSelectionToView","isEqual","isSimilar","anchorNode","contains","_step14","_iterator14","doc","activeDomElement","activeElement","mapDomToView","editable","findAncestor","domParentOrArray","nodeAfterFiller","fillerNode","createTextNode","isArray","splice","node1","node2","isNode","nodeType","COMMENT_NODE","tagName","toLowerCase","actualDomChild","expectedDomChild","isBlockFiller","ELEMENT_NODE","childAtOffset","getRangeAt","domChildList","fakeSelectionContainer","childList","last","pop","createElement","className","assign","style","top","left","width","mix","ObservableMixin"],"mappings":"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","file":"js/chunk-5b1b3063.63626c23.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/view/rooteditableelement\n */\n\nimport EditableElement from './editableelement';\n\nconst rootNameSymbol = Symbol( 'rootName' );\n\n/**\n * Class representing a single root in the data view. A root can be either {@link ~RootEditableElement#isReadOnly editable or read-only},\n * but in both cases it is called \"an editable\". Roots can contain other {@link module:engine/view/editableelement~EditableElement\n * editable elements} making them \"nested editables\".\n *\n * @extends module:engine/view/editableelement~EditableElement\n */\nexport default class RootEditableElement extends EditableElement {\n\t/**\n\t * Creates root editable element.\n\t *\n\t * @param {module:engine/view/document~Document} document The document instance to which this element belongs.\n\t * @param {String} name Node name.\n\t */\n\tconstructor( document, name ) {\n\t\tsuper( document, name );\n\n\t\t/**\n\t\t * Name of this root inside {@link module:engine/view/document~Document} that is an owner of this root. If no\n\t\t * other name is set, `main` name is used.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.rootName = 'main';\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\trootEditableElement.is( 'rootElement' ); // -> true\n\t *\t\trootEditableElement.is( 'editableElement' ); // -> true\n\t *\t\trootEditableElement.is( 'element' ); // -> true\n\t *\t\trootEditableElement.is( 'node' ); // -> true\n\t *\t\trootEditableElement.is( 'view:editableElement' ); // -> true\n\t *\t\trootEditableElement.is( 'view:element' ); // -> true\n\t *\t\trootEditableElement.is( 'view:node' ); // -> true\n\t *\n\t *\t\trootEditableElement.is( 'model:element' ); // -> false\n\t *\t\trootEditableElement.is( 'documentFragment' ); // -> false\n\t *\n\t * Assuming that the object being checked is a root editable element, you can also check its\n\t * {@link module:engine/view/rooteditableelement~RootEditableElement#name name}:\n\t *\n\t *\t\trootEditableElement.is( 'element', 'div' ); // -> true if this is a div root editable element\n\t *\t\trootEditableElement.is( 'rootElement', 'div' ); // -> same as above\n\t *\t\ttext.is( 'element', 'div' ); -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view 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 === 'rootElement' || type === 'view:rootElement' ||\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 === 'editableElement' || type === 'view:editableElement' ||\n\t\t\t\ttype === 'containerElement' || type === 'view:containerElement' ||\n\t\t\t\ttype === 'element' || type === 'view:element' ||\n\t\t\t\ttype === 'node' || type === 'view:node';\n\t\t} else {\n\t\t\treturn name === this.name && (\n\t\t\t\ttype === 'rootElement' || type === 'view:rootElement' ||\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 === 'editableElement' || type === 'view:editableElement' ||\n\t\t\t\ttype === 'containerElement' || type === 'view:containerElement' ||\n\t\t\t\ttype === 'element' || type === 'view:element'\n\t\t\t);\n\t\t}\n\t}\n\n\tget rootName() {\n\t\treturn this.getCustomProperty( rootNameSymbol );\n\t}\n\n\tset rootName( rootName ) {\n\t\tthis._setCustomProperty( rootNameSymbol, rootName );\n\t}\n\n\t/**\n\t * Overrides old element name and sets new one.\n\t * This is needed because view roots are created before they are attached to the DOM.\n\t * The name of the root element is temporary at this stage. It has to be changed when the\n\t * view root element is attached to the DOM element.\n\t *\n\t * @protected\n\t * @param {String} name The new name of element.\n\t */\n\tset _name( name ) {\n\t\tthis.name = name;\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/view/rawelement\n */\n\nimport Element from './element';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport Node from './node';\n\n/**\n * The raw element class.\n *\n * The raw elements work as data containers (\"wrappers\", \"sandboxes\") but their children are not managed or\n * even recognized by the editor. This encapsulation allows integrations to maintain custom DOM structures\n * in the editor content without, for instance, worrying about compatibility with other editor features.\n * Raw elements are a perfect tool for integration with external frameworks and data sources.\n *\n * Unlike {@link module:engine/view/uielement~UIElement UI elements}, raw elements act like real editor\n * content (similar to {@link module:engine/view/containerelement~ContainerElement} or\n * {@link module:engine/view/emptyelement~EmptyElement}), they are considered by the editor selection and\n * {@link module:widget/utils~toWidget they can work as widgets}.\n *\n * To create a new raw element, use the\n * {@link module:engine/view/downcastwriter~DowncastWriter#createRawElement `downcastWriter#createRawElement()`} method.\n *\n * @extends module:engine/view/element~Element\n */\nexport default class RawElement extends Element {\n\t/**\n\t * Creates a new instance of a raw element.\n\t *\n\t * Throws the `view-rawelement-cannot-add` {@link module:utils/ckeditorerror~CKEditorError CKEditorError} when the `children`\n\t * parameter is passed to inform that the usage of `RawElement` is incorrect (adding child nodes to `RawElement` is forbidden).\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#createRawElement\n\t * @protected\n\t * @param {module:engine/view/document~Document} document The document instance to which this element belongs.\n\t * @param {String} name A node name.\n\t * @param {Object|Iterable} [attrs] The collection of attributes.\n\t * @param {module:engine/view/node~Node|Iterable.} [children]\n\t * A list of nodes to be inserted into the created element.\n\t */\n\tconstructor( document, name, attrs, children ) {\n\t\tsuper( document, name, attrs, children );\n\n\t\t// Override the default of the base class.\n\t\tthis._isAllowedInsideAttributeElement = true;\n\n\t\t/**\n\t\t * Returns `null` because filler is not needed for raw elements.\n\t\t *\n\t\t * @method #getFillerOffset\n\t\t * @returns {null} Always returns null.\n\t\t */\n\t\tthis.getFillerOffset = getFillerOffset;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type or name.\n\t *\n\t *\t\trawElement.is( 'rawElement' ); // -> true\n\t *\t\trawElement.is( 'element' ); // -> true\n\t *\t\trawElement.is( 'node' ); // -> true\n\t *\t\trawElement.is( 'view:rawElement' ); // -> true\n\t *\t\trawElement.is( 'view:element' ); // -> true\n\t *\t\trawElement.is( 'view:node' ); // -> true\n\t *\n\t *\t\trawElement.is( 'model:element' ); // -> false\n\t *\t\trawElement.is( 'documentFragment' ); // -> false\n\t *\n\t * Assuming that the object being checked is a raw element, you can also check its\n\t * {@link module:engine/view/rawelement~RawElement#name name}:\n\t *\n\t *\t\trawElement.is( 'img' ); // -> true if this is an img element\n\t *\t\trawElement.is( 'rawElement', 'img' ); // -> same as above\n\t *\t\ttext.is( 'img' ); -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type The type to check when the `name` parameter is present.\n\t * Otherwise, it acts like the `name` parameter.\n\t * @param {String} [name] The element name.\n\t * @returns {Boolean}\n\t */\n\tis( type, name = null ) {\n\t\tif ( !name ) {\n\t\t\treturn type === 'rawElement' || type === 'view:rawElement' ||\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 === this.name || type === 'view:' + this.name ||\n\t\t\t\ttype === 'element' || type === 'view:element' ||\n\t\t\t\ttype === 'node' || type === 'view:node';\n\t\t} else {\n\t\t\treturn name === this.name && (\n\t\t\t\ttype === 'rawElement' || type === 'view:rawElement' ||\n\t\t\t\ttype === 'element' || type === 'view:element'\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Overrides the {@link module:engine/view/element~Element#_insertChild} method.\n\t * Throws the `view-rawelement-cannot-add` {@link module:utils/ckeditorerror~CKEditorError CKEditorError} to prevent\n\t * adding any child nodes to a raw element.\n\t *\n\t * @protected\n\t */\n\t_insertChild( index, nodes ) {\n\t\tif ( nodes && ( nodes instanceof Node || Array.from( nodes ).length > 0 ) ) {\n\t\t\t/**\n\t\t\t * Cannot add children to a {@link module:engine/view/rawelement~RawElement} instance.\n\t\t\t *\n\t\t\t * @error view-rawelement-cannot-add\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'view-rawelement-cannot-add',\n\t\t\t\t[ this, nodes ]\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * This allows rendering the children of a {@link module:engine/view/rawelement~RawElement} on the DOM level.\n\t * This method is called by the {@link module:engine/view/domconverter~DomConverter} with the raw DOM element\n\t * passed as an argument, leaving the number and shape of the children up to the integrator.\n\t *\n\t * This method **must be defined** for the raw element to work:\n\t *\n\t *\t\tconst myRawElement = downcastWriter.createRawElement( 'div' );\n\t *\n\t *\t\tmyRawElement.render = function( domElement ) {\n\t *\t\t\tdomElement.innerHTML = 'This is the raw content of myRawElement.';\n\t *\t\t};\n\t *\n\t * @method #render\n\t * @param {HTMLElement} domElement The native DOM element representing the raw view element.\n\t */\n}\n\n// Returns `null` because block filler is not needed for raw elements.\n//\n// @returns {null}\nfunction getFillerOffset() {\n\treturn null;\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/* globals Node */\n\n/**\n * @module engine/view/renderer\n */\n\nimport ViewText from './text';\nimport ViewPosition from './position';\nimport { INLINE_FILLER, INLINE_FILLER_LENGTH, startsWithFiller, isInlineFiller } from './filler';\n\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport diff from '@ckeditor/ckeditor5-utils/src/diff';\nimport insertAt from '@ckeditor/ckeditor5-utils/src/dom/insertat';\nimport remove from '@ckeditor/ckeditor5-utils/src/dom/remove';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport isText from '@ckeditor/ckeditor5-utils/src/dom/istext';\nimport isNode from '@ckeditor/ckeditor5-utils/src/dom/isnode';\nimport fastDiff from '@ckeditor/ckeditor5-utils/src/fastdiff';\nimport env from '@ckeditor/ckeditor5-utils/src/env';\n\n/**\n * Renderer is responsible for updating the DOM structure and the DOM selection based on\n * the {@link module:engine/view/renderer~Renderer#markToSync information about updated view nodes}.\n * In other words, it renders the view to the DOM.\n *\n * Its main responsibility is to make only the necessary, minimal changes to the DOM. However, unlike in many\n * virtual DOM implementations, the primary reason for doing minimal changes is not the performance but ensuring\n * that native editing features such as text composition, autocompletion, spell checking, selection's x-index are\n * affected as little as possible.\n *\n * Renderer uses {@link module:engine/view/domconverter~DomConverter} to transform view nodes and positions\n * to and from the DOM.\n */\nexport default class Renderer {\n\t/**\n\t * Creates a renderer instance.\n\t *\n\t * @param {module:engine/view/domconverter~DomConverter} domConverter Converter instance.\n\t * @param {module:engine/view/documentselection~DocumentSelection} selection View selection.\n\t */\n\tconstructor( domConverter, selection ) {\n\t\t/**\n\t\t * Set of DOM Documents instances.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Set.}\n\t\t */\n\t\tthis.domDocuments = new Set();\n\n\t\t/**\n\t\t * Converter instance.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/domconverter~DomConverter}\n\t\t */\n\t\tthis.domConverter = domConverter;\n\n\t\t/**\n\t\t * Set of nodes which attributes changed and may need to be rendered.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Set.}\n\t\t */\n\t\tthis.markedAttributes = new Set();\n\n\t\t/**\n\t\t * Set of elements which child lists changed and may need to be rendered.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Set.}\n\t\t */\n\t\tthis.markedChildren = new Set();\n\n\t\t/**\n\t\t * Set of text nodes which text data changed and may need to be rendered.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Set.}\n\t\t */\n\t\tthis.markedTexts = new Set();\n\n\t\t/**\n\t\t * View selection. Renderer updates DOM selection based on the view selection.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/documentselection~DocumentSelection}\n\t\t */\n\t\tthis.selection = selection;\n\n\t\t/**\n\t\t * Indicates if the view document is focused and selection can be rendered. Selection will not be rendered if\n\t\t * this is set to `false`.\n\t\t *\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis.isFocused = false;\n\n\t\t/**\n\t\t * The text node in which the inline filler was rendered.\n\t\t *\n\t\t * @private\n\t\t * @member {Text}\n\t\t */\n\t\tthis._inlineFiller = null;\n\n\t\t/**\n\t\t * DOM element containing fake selection.\n\t\t *\n\t\t * @private\n\t\t * @type {null|HTMLElement}\n\t\t */\n\t\tthis._fakeSelectionContainer = null;\n\t}\n\n\t/**\n\t * Marks a view node to be updated in the DOM by {@link #render `render()`}.\n\t *\n\t * Note that only view nodes whose parents have corresponding DOM elements need to be marked to be synchronized.\n\t *\n\t * @see #markedAttributes\n\t * @see #markedChildren\n\t * @see #markedTexts\n\t *\n\t * @param {module:engine/view/document~ChangeType} type Type of the change.\n\t * @param {module:engine/view/node~Node} node Node to be marked.\n\t */\n\tmarkToSync( type, node ) {\n\t\tif ( type === 'text' ) {\n\t\t\tif ( this.domConverter.mapViewToDom( node.parent ) ) {\n\t\t\t\tthis.markedTexts.add( node );\n\t\t\t}\n\t\t} else {\n\t\t\t// If the node has no DOM element it is not rendered yet,\n\t\t\t// its children/attributes do not need to be marked to be sync.\n\t\t\tif ( !this.domConverter.mapViewToDom( node ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( type === 'attributes' ) {\n\t\t\t\tthis.markedAttributes.add( node );\n\t\t\t} else if ( type === 'children' ) {\n\t\t\t\tthis.markedChildren.add( node );\n\t\t\t} else {\n\t\t\t\t/**\n\t\t\t\t * Unknown type passed to Renderer.markToSync.\n\t\t\t\t *\n\t\t\t\t * @error view-renderer-unknown-type\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError( 'view-renderer-unknown-type', this );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Renders all buffered changes ({@link #markedAttributes}, {@link #markedChildren} and {@link #markedTexts}) and\n\t * the current view selection (if needed) to the DOM by applying a minimal set of changes to it.\n\t *\n\t * Renderer tries not to break the text composition (e.g. IME) and x-index of the selection,\n\t * so it does as little as it is needed to update the DOM.\n\t *\n\t * Renderer also handles {@link module:engine/view/filler fillers}. Especially, it checks if the inline filler is needed\n\t * at the selection position and adds or removes it. To prevent breaking text composition inline filler will not be\n\t * removed as long as the selection is in the text node which needed it at first.\n\t */\n\trender() {\n\t\tlet inlineFillerPosition;\n\n\t\t// Refresh mappings.\n\t\tfor ( const element of this.markedChildren ) {\n\t\t\tthis._updateChildrenMappings( element );\n\t\t}\n\n\t\t// There was inline filler rendered in the DOM but it's not\n\t\t// at the selection position any more, so we can remove it\n\t\t// (cause even if it's needed, it must be placed in another location).\n\t\tif ( this._inlineFiller && !this._isSelectionInInlineFiller() ) {\n\t\t\tthis._removeInlineFiller();\n\t\t}\n\n\t\t// If we've got the filler, let's try to guess its position in the view.\n\t\tif ( this._inlineFiller ) {\n\t\t\tinlineFillerPosition = this._getInlineFillerPosition();\n\t\t}\n\t\t// Otherwise, if it's needed, create it at the selection position.\n\t\telse if ( this._needsInlineFillerAtSelection() ) {\n\t\t\tinlineFillerPosition = this.selection.getFirstPosition();\n\n\t\t\t// Do not use `markToSync` so it will be added even if the parent is already added.\n\t\t\tthis.markedChildren.add( inlineFillerPosition.parent );\n\t\t}\n\n\t\tfor ( const element of this.markedAttributes ) {\n\t\t\tthis._updateAttrs( element );\n\t\t}\n\n\t\tfor ( const element of this.markedChildren ) {\n\t\t\tthis._updateChildren( element, { inlineFillerPosition } );\n\t\t}\n\n\t\tfor ( const node of this.markedTexts ) {\n\t\t\tif ( !this.markedChildren.has( node.parent ) && this.domConverter.mapViewToDom( node.parent ) ) {\n\t\t\t\tthis._updateText( node, { inlineFillerPosition } );\n\t\t\t}\n\t\t}\n\n\t\t// Check whether the inline filler is required and where it really is in the DOM.\n\t\t// At this point in most cases it will be in the DOM, but there are exceptions.\n\t\t// For example, if the inline filler was deep in the created DOM structure, it will not be created.\n\t\t// Similarly, if it was removed at the beginning of this function and then neither text nor children were updated,\n\t\t// it will not be present.\n\t\t// Fix those and similar scenarios.\n\t\tif ( inlineFillerPosition ) {\n\t\t\tconst fillerDomPosition = this.domConverter.viewPositionToDom( inlineFillerPosition );\n\t\t\tconst domDocument = fillerDomPosition.parent.ownerDocument;\n\n\t\t\tif ( !startsWithFiller( fillerDomPosition.parent ) ) {\n\t\t\t\t// Filler has not been created at filler position. Create it now.\n\t\t\t\tthis._inlineFiller = addInlineFiller( domDocument, fillerDomPosition.parent, fillerDomPosition.offset );\n\t\t\t} else {\n\t\t\t\t// Filler has been found, save it.\n\t\t\t\tthis._inlineFiller = fillerDomPosition.parent;\n\t\t\t}\n\t\t} else {\n\t\t\t// There is no filler needed.\n\t\t\tthis._inlineFiller = null;\n\t\t}\n\n\t\t// First focus the new editing host, then update the selection.\n\t\t// Otherwise, FF may throw an error (https://github.com/ckeditor/ckeditor5/issues/721).\n\t\tthis._updateFocus();\n\t\tthis._updateSelection();\n\n\t\tthis.markedTexts.clear();\n\t\tthis.markedAttributes.clear();\n\t\tthis.markedChildren.clear();\n\t}\n\n\t/**\n\t * Updates mappings of view element's children.\n\t *\n\t * Children that were replaced in the view structure by similar elements (same tag name) are treated as 'replaced'.\n\t * This means that their mappings can be updated so the new view elements are mapped to the existing DOM elements.\n\t * Thanks to that these elements do not need to be re-rendered completely.\n\t *\n\t * @private\n\t * @param {module:engine/view/node~Node} viewElement The view element whose children mappings will be updated.\n\t */\n\t_updateChildrenMappings( viewElement ) {\n\t\tconst domElement = this.domConverter.mapViewToDom( viewElement );\n\n\t\tif ( !domElement ) {\n\t\t\t// If there is no `domElement` it means that it was already removed from DOM and there is no need to process it.\n\t\t\treturn;\n\t\t}\n\n\t\t// Removing nodes from the DOM as we iterate can cause `actualDomChildren`\n\t\t// (which is a live-updating `NodeList`) to get out of sync with the\n\t\t// indices that we compute as we iterate over `actions`.\n\t\t// This would produce incorrect element mappings.\n\t\t//\n\t\t// Converting live list to an array to make the list static.\n\t\tconst actualDomChildren = Array.from(\n\t\t\tthis.domConverter.mapViewToDom( viewElement ).childNodes\n\t\t);\n\t\tconst expectedDomChildren = Array.from(\n\t\t\tthis.domConverter.viewChildrenToDom( viewElement, domElement.ownerDocument, { withChildren: false } )\n\t\t);\n\t\tconst diff = this._diffNodeLists( actualDomChildren, expectedDomChildren );\n\t\tconst actions = this._findReplaceActions( diff, actualDomChildren, expectedDomChildren );\n\n\t\tif ( actions.indexOf( 'replace' ) !== -1 ) {\n\t\t\tconst counter = { equal: 0, insert: 0, delete: 0 };\n\n\t\t\tfor ( const action of actions ) {\n\t\t\t\tif ( action === 'replace' ) {\n\t\t\t\t\tconst insertIndex = counter.equal + counter.insert;\n\t\t\t\t\tconst deleteIndex = counter.equal + counter.delete;\n\t\t\t\t\tconst viewChild = viewElement.getChild( insertIndex );\n\n\t\t\t\t\t// UIElement and RawElement are special cases. Their children are not stored in a view (#799)\n\t\t\t\t\t// so we cannot use them with replacing flow (since they use view children during rendering\n\t\t\t\t\t// which will always result in rendering empty elements).\n\t\t\t\t\tif ( viewChild && !( viewChild.is( 'uiElement' ) || viewChild.is( 'rawElement' ) ) ) {\n\t\t\t\t\t\tthis._updateElementMappings( viewChild, actualDomChildren[ deleteIndex ] );\n\t\t\t\t\t}\n\n\t\t\t\t\tremove( expectedDomChildren[ insertIndex ] );\n\t\t\t\t\tcounter.equal++;\n\t\t\t\t} else {\n\t\t\t\t\tcounter[ action ]++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Updates mappings of a given view element.\n\t *\n\t * @private\n\t * @param {module:engine/view/node~Node} viewElement The view element whose mappings will be updated.\n\t * @param {Node} domElement The DOM element representing the given view element.\n\t */\n\t_updateElementMappings( viewElement, domElement ) {\n\t\t// Remap 'DomConverter' bindings.\n\t\tthis.domConverter.unbindDomElement( domElement );\n\t\tthis.domConverter.bindElements( domElement, viewElement );\n\n\t\t// View element may have children which needs to be updated, but are not marked, mark them to update.\n\t\tthis.markedChildren.add( viewElement );\n\n\t\t// Because we replace new view element mapping with the existing one, the corresponding DOM element\n\t\t// will not be rerendered. The new view element may have different attributes than the previous one.\n\t\t// Since its corresponding DOM element will not be rerendered, new attributes will not be added\n\t\t// to the DOM, so we need to mark it here to make sure its attributes gets updated. See #1427 for more\n\t\t// detailed case study.\n\t\t// Also there are cases where replaced element is removed from the view structure and then has\n\t\t// its attributes changed or removed. In such cases the element will not be present in `markedAttributes`\n\t\t// and also may be the same (`element.isSimilar()`) as the reused element not having its attributes updated.\n\t\t// To prevent such situations we always mark reused element to have its attributes rerenderd (#1560).\n\t\tthis.markedAttributes.add( viewElement );\n\t}\n\n\t/**\n\t * Gets the position of the inline filler based on the current selection.\n\t * Here, we assume that we know that the filler is needed and\n\t * {@link #_isSelectionInInlineFiller is at the selection position}, and, since it is needed,\n\t * it is somewhere at the selection position.\n\t *\n\t * Note: The filler position cannot be restored based on the filler's DOM text node, because\n\t * when this method is called (before rendering), the bindings will often be broken. View-to-DOM\n\t * bindings are only dependable after rendering.\n\t *\n\t * @private\n\t * @returns {module:engine/view/position~Position}\n\t */\n\t_getInlineFillerPosition() {\n\t\tconst firstPos = this.selection.getFirstPosition();\n\n\t\tif ( firstPos.parent.is( '$text' ) ) {\n\t\t\treturn ViewPosition._createBefore( this.selection.getFirstPosition().parent );\n\t\t} else {\n\t\t\treturn firstPos;\n\t\t}\n\t}\n\n\t/**\n\t * Returns `true` if the selection has not left the inline filler's text node.\n\t * If it is `true`, it means that the filler had been added for a reason and the selection did not\n\t * leave the filler's text node. For example, the user can be in the middle of a composition so it should not be touched.\n\t *\n\t * @private\n\t * @returns {Boolean} `true` if the inline filler and selection are in the same place.\n\t */\n\t_isSelectionInInlineFiller() {\n\t\tif ( this.selection.rangeCount != 1 || !this.selection.isCollapsed ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Note, we can't check if selection's position equals position of the\n\t\t// this._inlineFiller node, because of #663. We may not be able to calculate\n\t\t// the filler's position in the view at this stage.\n\t\t// Instead, we check it the other way – whether selection is anchored in\n\t\t// that text node or next to it.\n\n\t\t// Possible options are:\n\t\t// \"FILLER{}\"\n\t\t// \"FILLERadded-text{}\"\n\t\tconst selectionPosition = this.selection.getFirstPosition();\n\t\tconst position = this.domConverter.viewPositionToDom( selectionPosition );\n\n\t\tif ( position && isText( position.parent ) && startsWithFiller( position.parent ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Removes the inline filler.\n\t *\n\t * @private\n\t */\n\t_removeInlineFiller() {\n\t\tconst domFillerNode = this._inlineFiller;\n\n\t\t// Something weird happened and the stored node doesn't contain the filler's text.\n\t\tif ( !startsWithFiller( domFillerNode ) ) {\n\t\t\t/**\n\t\t\t * The inline filler node was lost. Most likely, something overwrote the filler text node\n\t\t\t * in the DOM.\n\t\t\t *\n\t\t\t * @error view-renderer-filler-was-lost\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-renderer-filler-was-lost', this );\n\t\t}\n\n\t\tif ( isInlineFiller( domFillerNode ) ) {\n\t\t\tdomFillerNode.parentNode.removeChild( domFillerNode );\n\t\t} else {\n\t\t\tdomFillerNode.data = domFillerNode.data.substr( INLINE_FILLER_LENGTH );\n\t\t}\n\n\t\tthis._inlineFiller = null;\n\t}\n\n\t/**\n\t * Checks if the inline {@link module:engine/view/filler filler} should be added.\n\t *\n\t * @private\n\t * @returns {Boolean} `true` if the inline filler should be added.\n\t */\n\t_needsInlineFillerAtSelection() {\n\t\tif ( this.selection.rangeCount != 1 || !this.selection.isCollapsed ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst selectionPosition = this.selection.getFirstPosition();\n\t\tconst selectionParent = selectionPosition.parent;\n\t\tconst selectionOffset = selectionPosition.offset;\n\n\t\t// If there is no DOM root we do not care about fillers.\n\t\tif ( !this.domConverter.mapViewToDom( selectionParent.root ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( !( selectionParent.is( 'element' ) ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Prevent adding inline filler inside elements with contenteditable=false.\n\t\t// https://github.com/ckeditor/ckeditor5-engine/issues/1170\n\t\tif ( !isEditable( selectionParent ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We have block filler, we do not need inline one.\n\t\tif ( selectionOffset === selectionParent.getFillerOffset() ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst nodeBefore = selectionPosition.nodeBefore;\n\t\tconst nodeAfter = selectionPosition.nodeAfter;\n\n\t\tif ( nodeBefore instanceof ViewText || nodeAfter instanceof ViewText ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Checks if text needs to be updated and possibly updates it.\n\t *\n\t * @private\n\t * @param {module:engine/view/text~Text} viewText View text to update.\n\t * @param {Object} options\n\t * @param {module:engine/view/position~Position} options.inlineFillerPosition The position where the inline\n\t * filler should be rendered.\n\t */\n\t_updateText( viewText, options ) {\n\t\tconst domText = this.domConverter.findCorrespondingDomText( viewText );\n\t\tconst newDomText = this.domConverter.viewToDom( viewText, domText.ownerDocument );\n\n\t\tconst actualText = domText.data;\n\t\tlet expectedText = newDomText.data;\n\n\t\tconst filler = options.inlineFillerPosition;\n\n\t\tif ( filler && filler.parent == viewText.parent && filler.offset == viewText.index ) {\n\t\t\texpectedText = INLINE_FILLER + expectedText;\n\t\t}\n\n\t\tif ( actualText != expectedText ) {\n\t\t\tconst actions = fastDiff( actualText, expectedText );\n\n\t\t\tfor ( const action of actions ) {\n\t\t\t\tif ( action.type === 'insert' ) {\n\t\t\t\t\tdomText.insertData( action.index, action.values.join( '' ) );\n\t\t\t\t} else { // 'delete'\n\t\t\t\t\tdomText.deleteData( action.index, action.howMany );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if attribute list needs to be updated and possibly updates it.\n\t *\n\t * @private\n\t * @param {module:engine/view/element~Element} viewElement The view element to update.\n\t */\n\t_updateAttrs( viewElement ) {\n\t\tconst domElement = this.domConverter.mapViewToDom( viewElement );\n\n\t\tif ( !domElement ) {\n\t\t\t// If there is no `domElement` it means that 'viewElement' is outdated as its mapping was updated\n\t\t\t// in 'this._updateChildrenMappings()'. There is no need to process it as new view element which\n\t\t\t// replaced old 'viewElement' mapping was also added to 'this.markedAttributes'\n\t\t\t// in 'this._updateChildrenMappings()' so it will be processed separately.\n\t\t\treturn;\n\t\t}\n\n\t\tconst domAttrKeys = Array.from( domElement.attributes ).map( attr => attr.name );\n\t\tconst viewAttrKeys = viewElement.getAttributeKeys();\n\n\t\t// Add or overwrite attributes.\n\t\tfor ( const key of viewAttrKeys ) {\n\t\t\tdomElement.setAttribute( key, viewElement.getAttribute( key ) );\n\t\t}\n\n\t\t// Remove from DOM attributes which do not exists in the view.\n\t\tfor ( const key of domAttrKeys ) {\n\t\t\tif ( !viewElement.hasAttribute( key ) ) {\n\t\t\t\tdomElement.removeAttribute( key );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if elements child list needs to be updated and possibly updates it.\n\t *\n\t * @private\n\t * @param {module:engine/view/element~Element} viewElement View element to update.\n\t * @param {Object} options\n\t * @param {module:engine/view/position~Position} options.inlineFillerPosition The position where the inline\n\t * filler should be rendered.\n\t */\n\t_updateChildren( viewElement, options ) {\n\t\tconst domElement = this.domConverter.mapViewToDom( viewElement );\n\n\t\tif ( !domElement ) {\n\t\t\t// If there is no `domElement` it means that it was already removed from DOM.\n\t\t\t// There is no need to process it. It will be processed when re-inserted.\n\t\t\treturn;\n\t\t}\n\n\t\tconst inlineFillerPosition = options.inlineFillerPosition;\n\t\tconst actualDomChildren = this.domConverter.mapViewToDom( viewElement ).childNodes;\n\t\tconst expectedDomChildren = Array.from(\n\t\t\tthis.domConverter.viewChildrenToDom( viewElement, domElement.ownerDocument, { bind: true, inlineFillerPosition } )\n\t\t);\n\n\t\t// Inline filler element has to be created as it is present in the DOM, but not in the view. It is required\n\t\t// during diffing so text nodes could be compared correctly and also during rendering to maintain\n\t\t// proper order and indexes while updating the DOM.\n\t\tif ( inlineFillerPosition && inlineFillerPosition.parent === viewElement ) {\n\t\t\taddInlineFiller( domElement.ownerDocument, expectedDomChildren, inlineFillerPosition.offset );\n\t\t}\n\n\t\tconst diff = this._diffNodeLists( actualDomChildren, expectedDomChildren );\n\n\t\tlet i = 0;\n\t\tconst nodesToUnbind = new Set();\n\n\t\t// Handle deletions first.\n\t\t// This is to prevent a situation where an element that already exists in `actualDomChildren` is inserted at a different\n\t\t// index in `actualDomChildren`. Since `actualDomChildren` is a `NodeList`, this works like move, not like an insert,\n\t\t// and it disrupts the whole algorithm. See https://github.com/ckeditor/ckeditor5/issues/6367.\n\t\t//\n\t\t// It doesn't matter in what order we remove or add nodes, as long as we remove and add correct nodes at correct indexes.\n\t\tfor ( const action of diff ) {\n\t\t\tif ( action === 'delete' ) {\n\t\t\t\tnodesToUnbind.add( actualDomChildren[ i ] );\n\t\t\t\tremove( actualDomChildren[ i ] );\n\t\t\t} else if ( action === 'equal' ) {\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\n\t\ti = 0;\n\n\t\tfor ( const action of diff ) {\n\t\t\tif ( action === 'insert' ) {\n\t\t\t\tinsertAt( domElement, i, expectedDomChildren[ i ] );\n\t\t\t\ti++;\n\t\t\t} else if ( action === 'equal' ) {\n\t\t\t\t// Force updating text nodes inside elements which did not change and do not need to be re-rendered (#1125).\n\t\t\t\t// Do it here (not in the loop above) because only after insertions the `i` index is correct.\n\t\t\t\tthis._markDescendantTextToSync( this.domConverter.domToView( expectedDomChildren[ i ] ) );\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\n\t\t// Unbind removed nodes. When node does not have a parent it means that it was removed from DOM tree during\n\t\t// comparison with the expected DOM. We don't need to check child nodes, because if child node was reinserted,\n\t\t// it was moved to DOM tree out of the removed node.\n\t\tfor ( const node of nodesToUnbind ) {\n\t\t\tif ( !node.parentNode ) {\n\t\t\t\tthis.domConverter.unbindDomElement( node );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Shorthand for diffing two arrays or node lists of DOM nodes.\n\t *\n\t * @private\n\t * @param {Array.|NodeList} actualDomChildren Actual DOM children\n\t * @param {Array.|NodeList} expectedDomChildren Expected DOM children.\n\t * @returns {Array.} The list of actions based on the {@link module:utils/diff~diff} function.\n\t */\n\t_diffNodeLists( actualDomChildren, expectedDomChildren ) {\n\t\tactualDomChildren = filterOutFakeSelectionContainer( actualDomChildren, this._fakeSelectionContainer );\n\n\t\treturn diff( actualDomChildren, expectedDomChildren, sameNodes.bind( null, this.domConverter ) );\n\t}\n\n\t/**\n\t * Finds DOM nodes that were replaced with the similar nodes (same tag name) in the view. All nodes are compared\n\t * within one `insert`/`delete` action group, for example:\n\t *\n\t * \t\tActual DOM:\t\t

FooBarBazBax

\n\t * \t\tExpected DOM:\t

Bar123Baz456

\n\t * \t\tInput actions:\t[ insert, insert, delete, delete, equal, insert, delete ]\n\t * \t\tOutput actions:\t[ insert, replace, delete, equal, replace ]\n\t *\n\t * @private\n\t * @param {Array.} actions Actions array which is a result of the {@link module:utils/diff~diff} function.\n\t * @param {Array.|NodeList} actualDom Actual DOM children\n\t * @param {Array.} expectedDom Expected DOM children.\n\t * @returns {Array.} Actions array modified with the `replace` actions.\n\t */\n\t_findReplaceActions( actions, actualDom, expectedDom ) {\n\t\t// If there is no both 'insert' and 'delete' actions, no need to check for replaced elements.\n\t\tif ( actions.indexOf( 'insert' ) === -1 || actions.indexOf( 'delete' ) === -1 ) {\n\t\t\treturn actions;\n\t\t}\n\n\t\tlet newActions = [];\n\t\tlet actualSlice = [];\n\t\tlet expectedSlice = [];\n\n\t\tconst counter = { equal: 0, insert: 0, delete: 0 };\n\n\t\tfor ( const action of actions ) {\n\t\t\tif ( action === 'insert' ) {\n\t\t\t\texpectedSlice.push( expectedDom[ counter.equal + counter.insert ] );\n\t\t\t} else if ( action === 'delete' ) {\n\t\t\t\tactualSlice.push( actualDom[ counter.equal + counter.delete ] );\n\t\t\t} else { // equal\n\t\t\t\tnewActions = newActions.concat( diff( actualSlice, expectedSlice, areSimilar ).map( x => x === 'equal' ? 'replace' : x ) );\n\t\t\t\tnewActions.push( 'equal' );\n\t\t\t\t// Reset stored elements on 'equal'.\n\t\t\t\tactualSlice = [];\n\t\t\t\texpectedSlice = [];\n\t\t\t}\n\t\t\tcounter[ action ]++;\n\t\t}\n\n\t\treturn newActions.concat( diff( actualSlice, expectedSlice, areSimilar ).map( x => x === 'equal' ? 'replace' : x ) );\n\t}\n\n\t/**\n\t * Marks text nodes to be synchronized.\n\t *\n\t * If a text node is passed, it will be marked. If an element is passed, all descendant text nodes inside it will be marked.\n\t *\n\t * @private\n\t * @param {module:engine/view/node~Node} viewNode View node to sync.\n\t */\n\t_markDescendantTextToSync( viewNode ) {\n\t\tif ( !viewNode ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( viewNode.is( '$text' ) ) {\n\t\t\tthis.markedTexts.add( viewNode );\n\t\t} else if ( viewNode.is( 'element' ) ) {\n\t\t\tfor ( const child of viewNode.getChildren() ) {\n\t\t\t\tthis._markDescendantTextToSync( child );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the selection needs to be updated and possibly updates it.\n\t *\n\t * @private\n\t */\n\t_updateSelection() {\n\t\t// If there is no selection - remove DOM and fake selections.\n\t\tif ( this.selection.rangeCount === 0 ) {\n\t\t\tthis._removeDomSelection();\n\t\t\tthis._removeFakeSelection();\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst domRoot = this.domConverter.mapViewToDom( this.selection.editableElement );\n\n\t\t// Do nothing if there is no focus, or there is no DOM element corresponding to selection's editable element.\n\t\tif ( !this.isFocused || !domRoot ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Render selection.\n\t\tif ( this.selection.isFake ) {\n\t\t\tthis._updateFakeSelection( domRoot );\n\t\t} else {\n\t\t\tthis._removeFakeSelection();\n\t\t\tthis._updateDomSelection( domRoot );\n\t\t}\n\t}\n\n\t/**\n\t * Updates the fake selection.\n\t *\n\t * @private\n\t * @param {HTMLElement} domRoot A valid DOM root where the fake selection container should be added.\n\t */\n\t_updateFakeSelection( domRoot ) {\n\t\tconst domDocument = domRoot.ownerDocument;\n\n\t\tif ( !this._fakeSelectionContainer ) {\n\t\t\tthis._fakeSelectionContainer = createFakeSelectionContainer( domDocument );\n\t\t}\n\n\t\tconst container = this._fakeSelectionContainer;\n\n\t\t// Bind fake selection container with the current selection *position*.\n\t\tthis.domConverter.bindFakeSelection( container, this.selection );\n\n\t\tif ( !this._fakeSelectionNeedsUpdate( domRoot ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !container.parentElement || container.parentElement != domRoot ) {\n\t\t\tdomRoot.appendChild( container );\n\t\t}\n\n\t\tcontainer.textContent = this.selection.fakeSelectionLabel || '\\u00A0';\n\n\t\tconst domSelection = domDocument.getSelection();\n\t\tconst domRange = domDocument.createRange();\n\n\t\tdomSelection.removeAllRanges();\n\t\tdomRange.selectNodeContents( container );\n\t\tdomSelection.addRange( domRange );\n\t}\n\n\t/**\n\t * Updates the DOM selection.\n\t *\n\t * @private\n\t * @param {HTMLElement} domRoot A valid DOM root where the DOM selection should be rendered.\n\t */\n\t_updateDomSelection( domRoot ) {\n\t\tconst domSelection = domRoot.ownerDocument.defaultView.getSelection();\n\n\t\t// Let's check whether DOM selection needs updating at all.\n\t\tif ( !this._domSelectionNeedsUpdate( domSelection ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Multi-range selection is not available in most browsers, and, at least in Chrome, trying to\n\t\t// set such selection, that is not continuous, throws an error. Because of that, we will just use anchor\n\t\t// and focus of view selection.\n\t\t// Since we are not supporting multi-range selection, we also do not need to check if proper editable is\n\t\t// selected. If there is any editable selected, it is okay (editable is taken from selection anchor).\n\t\tconst anchor = this.domConverter.viewPositionToDom( this.selection.anchor );\n\t\tconst focus = this.domConverter.viewPositionToDom( this.selection.focus );\n\n\t\tdomSelection.collapse( anchor.parent, anchor.offset );\n\t\tdomSelection.extend( focus.parent, focus.offset );\n\n\t\t// Firefox–specific hack (https://github.com/ckeditor/ckeditor5-engine/issues/1439).\n\t\tif ( env.isGecko ) {\n\t\t\tfixGeckoSelectionAfterBr( focus, domSelection );\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether a given DOM selection needs to be updated.\n\t *\n\t * @private\n\t * @param {Selection} domSelection The DOM selection to check.\n\t * @returns {Boolean}\n\t */\n\t_domSelectionNeedsUpdate( domSelection ) {\n\t\tif ( !this.domConverter.isDomSelectionCorrect( domSelection ) ) {\n\t\t\t// Current DOM selection is in incorrect position. We need to update it.\n\t\t\treturn true;\n\t\t}\n\n\t\tconst oldViewSelection = domSelection && this.domConverter.domSelectionToView( domSelection );\n\n\t\tif ( oldViewSelection && this.selection.isEqual( oldViewSelection ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If selection is not collapsed, it does not need to be updated if it is similar.\n\t\tif ( !this.selection.isCollapsed && this.selection.isSimilar( oldViewSelection ) ) {\n\t\t\t// Selection did not changed and is correct, do not update.\n\t\t\treturn false;\n\t\t}\n\n\t\t// Selections are not similar.\n\t\treturn true;\n\t}\n\n\t/**\n\t * Checks whether the fake selection needs to be updated.\n\t *\n\t * @private\n\t * @param {HTMLElement} domRoot A valid DOM root where a new fake selection container should be added.\n\t * @returns {Boolean}\n\t */\n\t_fakeSelectionNeedsUpdate( domRoot ) {\n\t\tconst container = this._fakeSelectionContainer;\n\t\tconst domSelection = domRoot.ownerDocument.getSelection();\n\n\t\t// Fake selection needs to be updated if there's no fake selection container, or the container currently sits\n\t\t// in a different root.\n\t\tif ( !container || container.parentElement !== domRoot ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Make sure that the selection actually is within the fake selection.\n\t\tif ( domSelection.anchorNode !== container && !container.contains( domSelection.anchorNode ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn container.textContent !== this.selection.fakeSelectionLabel;\n\t}\n\n\t/**\n\t * Removes the DOM selection.\n\t *\n\t * @private\n\t */\n\t_removeDomSelection() {\n\t\tfor ( const doc of this.domDocuments ) {\n\t\t\tconst domSelection = doc.getSelection();\n\n\t\t\tif ( domSelection.rangeCount ) {\n\t\t\t\tconst activeDomElement = doc.activeElement;\n\t\t\t\tconst viewElement = this.domConverter.mapDomToView( activeDomElement );\n\n\t\t\t\tif ( activeDomElement && viewElement ) {\n\t\t\t\t\tdoc.getSelection().removeAllRanges();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Removes the fake selection.\n\t *\n\t * @private\n\t */\n\t_removeFakeSelection() {\n\t\tconst container = this._fakeSelectionContainer;\n\n\t\tif ( container ) {\n\t\t\tcontainer.remove();\n\t\t}\n\t}\n\n\t/**\n\t * Checks if focus needs to be updated and possibly updates it.\n\t *\n\t * @private\n\t */\n\t_updateFocus() {\n\t\tif ( this.isFocused ) {\n\t\t\tconst editable = this.selection.editableElement;\n\n\t\t\tif ( editable ) {\n\t\t\t\tthis.domConverter.focus( editable );\n\t\t\t}\n\t\t}\n\t}\n}\n\nmix( Renderer, ObservableMixin );\n\n// Checks if provided element is editable.\n//\n// @private\n// @param {module:engine/view/element~Element} element\n// @returns {Boolean}\nfunction isEditable( element ) {\n\tif ( element.getAttribute( 'contenteditable' ) == 'false' ) {\n\t\treturn false;\n\t}\n\n\tconst parent = element.findAncestor( element => element.hasAttribute( 'contenteditable' ) );\n\n\treturn !parent || parent.getAttribute( 'contenteditable' ) == 'true';\n}\n\n// Adds inline filler at a given position.\n//\n// The position can be given as an array of DOM nodes and an offset in that array,\n// or a DOM parent element and an offset in that element.\n//\n// @private\n// @param {Document} domDocument\n// @param {Element|Array.} domParentOrArray\n// @param {Number} offset\n// @returns {Text} The DOM text node that contains an inline filler.\nfunction addInlineFiller( domDocument, domParentOrArray, offset ) {\n\tconst childNodes = domParentOrArray instanceof Array ? domParentOrArray : domParentOrArray.childNodes;\n\tconst nodeAfterFiller = childNodes[ offset ];\n\n\tif ( isText( nodeAfterFiller ) ) {\n\t\tnodeAfterFiller.data = INLINE_FILLER + nodeAfterFiller.data;\n\n\t\treturn nodeAfterFiller;\n\t} else {\n\t\tconst fillerNode = domDocument.createTextNode( INLINE_FILLER );\n\n\t\tif ( Array.isArray( domParentOrArray ) ) {\n\t\t\tchildNodes.splice( offset, 0, fillerNode );\n\t\t} else {\n\t\t\tinsertAt( domParentOrArray, offset, fillerNode );\n\t\t}\n\n\t\treturn fillerNode;\n\t}\n}\n\n// Whether two DOM nodes should be considered as similar.\n// Nodes are considered similar if they have the same tag name.\n//\n// @private\n// @param {Node} node1\n// @param {Node} node2\n// @returns {Boolean}\nfunction areSimilar( node1, node2 ) {\n\treturn isNode( node1 ) && isNode( node2 ) &&\n\t\t!isText( node1 ) && !isText( node2 ) &&\n\t\tnode1.nodeType !== Node.COMMENT_NODE && node2.nodeType !== Node.COMMENT_NODE &&\n\t\tnode1.tagName.toLowerCase() === node2.tagName.toLowerCase();\n}\n\n// Whether two dom nodes should be considered as the same.\n// Two nodes which are considered the same are:\n//\n//\t\t* Text nodes with the same text.\n//\t\t* Element nodes represented by the same object.\n//\t\t* Two block filler elements.\n//\n// @private\n// @param {String} blockFillerMode Block filler mode, see {@link module:engine/view/domconverter~DomConverter#blockFillerMode}.\n// @param {Node} node1\n// @param {Node} node2\n// @returns {Boolean}\nfunction sameNodes( domConverter, actualDomChild, expectedDomChild ) {\n\t// Elements.\n\tif ( actualDomChild === expectedDomChild ) {\n\t\treturn true;\n\t}\n\t// Texts.\n\telse if ( isText( actualDomChild ) && isText( expectedDomChild ) ) {\n\t\treturn actualDomChild.data === expectedDomChild.data;\n\t}\n\t// Block fillers.\n\telse if ( domConverter.isBlockFiller( actualDomChild ) &&\n\t\tdomConverter.isBlockFiller( expectedDomChild ) ) {\n\t\treturn true;\n\t}\n\n\t// Not matching types.\n\treturn false;\n}\n\n// The following is a Firefox–specific hack (https://github.com/ckeditor/ckeditor5-engine/issues/1439).\n// When the native DOM selection is at the end of the block and preceded by
e.g.\n//\n//\t\t

foo
[]

\n//\n// which happens a lot when using the soft line break, the browser fails to (visually) move the\n// caret to the new line. A quick fix is as simple as force–refreshing the selection with the same range.\nfunction fixGeckoSelectionAfterBr( focus, domSelection ) {\n\tconst parent = focus.parent;\n\n\t// This fix works only when the focus point is at the very end of an element.\n\t// There is no point in running it in cases unrelated to the browser bug.\n\tif ( parent.nodeType != Node.ELEMENT_NODE || focus.offset != parent.childNodes.length - 1 ) {\n\t\treturn;\n\t}\n\n\tconst childAtOffset = parent.childNodes[ focus.offset ];\n\n\t// To stay on the safe side, the fix being as specific as possible, it targets only the\n\t// selection which is at the very end of the element and preceded by
.\n\tif ( childAtOffset && childAtOffset.tagName == 'BR' ) {\n\t\tdomSelection.addRange( domSelection.getRangeAt( 0 ) );\n\t}\n}\n\nfunction filterOutFakeSelectionContainer( domChildList, fakeSelectionContainer ) {\n\tconst childList = Array.from( domChildList );\n\n\tif ( childList.length == 0 || !fakeSelectionContainer ) {\n\t\treturn childList;\n\t}\n\n\tconst last = childList[ childList.length - 1 ];\n\n\tif ( last == fakeSelectionContainer ) {\n\t\tchildList.pop();\n\t}\n\n\treturn childList;\n}\n\n// Creates a fake selection container for a given document.\n//\n// @private\n// @param {Document} domDocument\n// @returns {HTMLElement}\nfunction createFakeSelectionContainer( domDocument ) {\n\tconst container = domDocument.createElement( 'div' );\n\n\tcontainer.className = 'ck-fake-selection-container';\n\n\tObject.assign( container.style, {\n\t\tposition: 'fixed',\n\t\ttop: 0,\n\t\tleft: '-9999px',\n\t\t// See https://github.com/ckeditor/ckeditor5/issues/752.\n\t\twidth: '42px'\n\t} );\n\n\t// Fill it with a text node so we can update it later.\n\tcontainer.textContent = '\\u00A0';\n\n\treturn container;\n}\n"],"sourceRoot":""}