{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/conversion/mapper.js"],"names":["Mapper","_this","this","Object","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_classCallCheck_js__WEBPACK_IMPORTED_MODULE_10__","_modelToViewMapping","WeakMap","_viewToModelMapping","_viewToModelLengthCallbacks","Map","_markerNameToElements","_elementToMarkerNames","_unboundMarkerNames","Set","on","evt","data","viewPosition","viewContainer","get","modelPosition","parent","findPositionIn","offset","priority","viewBlock","findMappedViewAncestor","modelParent","modelOffset","_toModelOffset","ModelPosition","_createAt","modelElement","viewElement","set","toModelElement","delete","has","_step","_iterator","_createForOfIteratorHelper","s","n","done","markerName","value","add","err","e","f","toViewElement","element","name","elements","names","nameToElements","size","elementToNames","markerNames","Array","from","clear","viewRange","ModelRange","toModelPosition","start","end","modelRange","ViewRange","toViewPosition","mapper","fire","options","arguments","length","undefined","isPhantom","boundElements","_step2","_iterator2","is","_step3","_iterator3","getElementsWithSameId","clone","viewElementName","lengthCallback","viewParent","viewOffset","offsetToParentStart","index","offsetInParent","i","getModelLength","getChild","viewNode","callback","_step4","len","_iterator4","getChildren","child","expectedOffset","lastLength","ViewPosition","_moveViewPositionToTextNode","nodeBefore","nodeAfter","ViewText","mix","EmitterMixin"],"mappings":";;;;OAuCqBA,aAIpB,SAAAA,IAAc,IAAAC,EAAAC,KAAAC,OAAAC,EAAA,KAAAD,CAAAD,KAAAF,GAObE,KAAKG,oBAAsB,IAAIC,QAQ/BJ,KAAKK,oBAAsB,IAAID,QAS/BJ,KAAKM,4BAA8B,IAAIC,IAWvCP,KAAKQ,sBAAwB,IAAID,IAUjCP,KAAKS,sBAAwB,IAAIF,IASjCP,KAAKU,oBAAsB,IAAIC,IAG/BX,KAAKY,GAAI,sBAAuB,SAAEC,EAAKC,GACtC,IAAKA,EAAKC,aAAV,CAIA,IAAMC,EAAgBjB,EAAKI,oBAAoBc,IAAKH,EAAKI,cAAcC,QAEvEL,EAAKC,aAAehB,EAAKqB,eAAgBJ,EAAeF,EAAKI,cAAcG,WACvEC,SAAU,QAGftB,KAAKY,GAAI,sBAAuB,SAAEC,EAAKC,GACtC,IAAKA,EAAKI,cAAV,CAIA,IAAMK,EAAYxB,EAAKyB,uBAAwBV,EAAKC,cAC9CU,EAAc1B,EAAKM,oBAAoBY,IAAKM,GAC5CG,EAAc3B,EAAK4B,eAAgBb,EAAKC,aAAaI,OAAQL,EAAKC,aAAaM,OAAQE,GAE7FT,EAAKI,cAAgBU,OAAcC,UAAWJ,EAAaC,MACvDJ,SAAU,2DAYhB,SAAcQ,EAAcC,GAC3B/B,KAAKG,oBAAoB6B,IAAKF,EAAcC,GAC5C/B,KAAKK,oBAAoB2B,IAAKD,EAAaD,oCAc5C,SAAmBC,GAClB,IAAMD,EAAe9B,KAAKiC,eAAgBF,GAI1C,GAFA/B,KAAKK,oBAAoB6B,OAAQH,GAE5B/B,KAAKS,sBAAsB0B,IAAKJ,GAAgB,KAAAK,EAAAC,EAAAC,EAC1BtC,KAAKS,sBAAsBQ,IAAKc,IADN,IACpD,IAAAM,EAAAE,MAAAH,EAAAC,EAAAG,KAAAC,MAA0E,KAA9DC,EAA8DN,EAAAO,MACzE3C,KAAKU,oBAAoBkC,IAAKF,IAFqB,MAAAG,GAAAR,EAAAS,EAAAD,GAAA,QAAAR,EAAAU,KAMhD/C,KAAKG,oBAAoBc,IAAKa,IAAkBC,GACpD/B,KAAKG,oBAAoB+B,OAAQJ,qCAenC,SAAoBA,GACnB,IAAMC,EAAc/B,KAAKgD,cAAelB,GAExC9B,KAAKG,oBAAoB+B,OAAQJ,GAE5B9B,KAAKK,oBAAoBY,IAAKc,IAAiBD,GACnD9B,KAAKK,oBAAoB6B,OAAQH,sCAWnC,SAAqBkB,EAASC,GAC7B,IAAMC,EAAWnD,KAAKQ,sBAAsBS,IAAKiC,IAAU,IAAIvC,IAC/DwC,EAASP,IAAKK,GAEd,IAAMG,EAAQpD,KAAKS,sBAAsBQ,IAAKgC,IAAa,IAAItC,IAC/DyC,EAAMR,IAAKM,GAEXlD,KAAKQ,sBAAsBwB,IAAKkB,EAAMC,GACtCnD,KAAKS,sBAAsBuB,IAAKiB,EAASG,8CAS1C,SAA6BH,EAASC,GACrC,IAAMG,EAAiBrD,KAAKQ,sBAAsBS,IAAKiC,GAElDG,IACJA,EAAenB,OAAQe,GAEK,GAAvBI,EAAeC,MACnBtD,KAAKQ,sBAAsB0B,OAAQgB,IAIrC,IAAMK,EAAiBvD,KAAKS,sBAAsBQ,IAAKgC,GAElDM,IACJA,EAAerB,OAAQgB,GAEK,GAAvBK,EAAeD,MACnBtD,KAAKS,sBAAsByB,OAAQe,2CAWtC,WACC,IAAMO,EAAcC,MAAMC,KAAM1D,KAAKU,qBAIrC,OAFAV,KAAKU,oBAAoBiD,QAElBH,+BAMR,WACCxD,KAAKG,oBAAsB,IAAIC,QAC/BJ,KAAKK,oBAAsB,IAAID,QAC/BJ,KAAKQ,sBAAwB,IAAID,IACjCP,KAAKS,sBAAwB,IAAIF,IACjCP,KAAKU,oBAAsB,IAAIC,kCAWhC,SAAgBoB,GACf,OAAO/B,KAAKK,oBAAoBY,IAAKc,gCAStC,SAAeD,GACd,OAAO9B,KAAKG,oBAAoBc,IAAKa,+BAStC,SAAc8B,GACb,OAAO,IAAIC,OAAY7D,KAAK8D,gBAAiBF,EAAUG,OAAS/D,KAAK8D,gBAAiBF,EAAUI,iCASjG,SAAaC,GACZ,OAAO,IAAIC,OAAWlE,KAAKmE,eAAgBF,EAAWF,OAAS/D,KAAKmE,eAAgBF,EAAWD,qCAUhG,SAAiBjD,GAChB,IAAMD,GACLC,eACAqD,OAAQpE,MAKT,OAFAA,KAAKqE,KAAM,sBAAuBvD,GAE3BA,EAAKI,4CAab,SAAgBA,GAAgD,IAAjCoD,EAAiCC,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,IAArBG,WAAW,GAC/C5D,GACLI,gBACAkD,OAAQpE,KACR0E,UAAWJ,EAAQI,WAKpB,OAFA1E,KAAKqE,KAAM,sBAAuBvD,GAE3BA,EAAKC,iDAUb,SAAsBmC,GACrB,IAAMyB,EAAgB3E,KAAKQ,sBAAsBS,IAAKiC,GAEtD,IAAMyB,EACL,OAAO,KAGR,IAP4BC,EAOtBzB,EAAW,IAAIxC,IAPOkE,EAAAvC,EASLqC,GATK,IAS5B,IAAAE,EAAAtC,MAAAqC,EAAAC,EAAArC,KAAAC,MAAuC,KAA3BQ,EAA2B2B,EAAAjC,MACtC,GAAKM,EAAQ6B,GAAI,oBAAuB,KAAAC,EAAAC,EAAA1C,EAClBW,EAAQgC,yBADU,IACvC,IAAAD,EAAAzC,MAAAwC,EAAAC,EAAAxC,KAAAC,MAAuD,KAA3CyC,EAA2CH,EAAApC,MACtDQ,EAASP,IAAKsC,IAFwB,MAAArC,GAAAmC,EAAAlC,EAAAD,GAAA,QAAAmC,EAAAjC,UAKvCI,EAASP,IAAKK,IAfY,MAAAJ,GAAAgC,EAAA/B,EAAAD,GAAA,QAAAgC,EAAA9B,IAmB5B,OAAOI,2CAgCR,SAA2BgC,EAAiBC,GAC3CpF,KAAKM,4BAA4B0B,IAAKmD,EAAiBC,yCAUxD,SAAwBrE,GACvB,IAAII,EAASJ,EAAaI,OAE1B,OAASnB,KAAKK,oBAAoB8B,IAAKhB,GACtCA,EAASA,EAAOA,OAGjB,OAAOA,gCAqBR,SAAgBkE,EAAYC,EAAY/D,GACvC,GAAKA,GAAa8D,EAAa,CAE9B,IAAME,EAAsBvF,KAAK2B,eAAgB0D,EAAWlE,OAAQkE,EAAWG,MAAOjE,GAChFkE,EAAiBzF,KAAK2B,eAAgB0D,EAAYC,EAAYD,GAEpE,OAAOE,EAAsBE,EAM9B,GAAKJ,EAAWP,GAAI,SACnB,OAAOQ,EAMR,IAFA,IAAI5D,EAAc,EAERgE,EAAI,EAAGA,EAAIJ,EAAYI,IAChChE,GAAe1B,KAAK2F,eAAgBN,EAAWO,SAAUF,IAG1D,OAAOhE,gCAyBR,SAAgBmE,GACf,GAAK7F,KAAKM,4BAA4BW,IAAK4E,EAAS3C,MAAS,CAC5D,IAAM4C,EAAW9F,KAAKM,4BAA4BW,IAAK4E,EAAS3C,MAEhE,OAAO4C,EAAUD,GACX,GAAK7F,KAAKK,oBAAoB8B,IAAK0D,GACzC,OAAO,EACD,GAAKA,EAASf,GAAI,SACxB,OAAOe,EAAS/E,KAAK0D,OACf,GAAKqB,EAASf,GAAI,aACxB,OAAO,EAEP,IADMiB,EACFC,EAAM,EADJC,EAAA3D,EAGeuD,EAASK,eAHxB,IAGN,IAAAD,EAAA1D,MAAAwD,EAAAE,EAAAzD,KAAAC,MAA8C,KAAlC0D,EAAkCJ,EAAApD,MAC7CqD,GAAOhG,KAAK2F,eAAgBQ,IAJvB,MAAAtD,GAAAoD,EAAAnD,EAAAD,GAAA,QAAAoD,EAAAlD,IAON,OAAOiD,gCA4BT,SAAgBX,EAAYe,GAE3B,IAAIP,EAEAQ,EAAa,EAEb3E,EAAc,EACd4D,EAAa,EAGjB,GAAKD,EAAWP,GAAI,SACnB,OAAO,IAAIwB,OAAcjB,EAAYe,GAMtC,MAAQ1E,EAAc0E,EACrBP,EAAWR,EAAWO,SAAUN,GAChCe,EAAarG,KAAK2F,eAAgBE,GAClCnE,GAAe2E,EACff,IAID,OAAK5D,GAAe0E,EACZpG,KAAKuG,4BAA6B,IAAID,OAAcjB,EAAYC,IAMhEtF,KAAKoB,eAAgByE,EAAUO,GAAmB1E,EAAc2E,+CAgBzE,SAA6BtF,GAG5B,IAAMyF,EAAazF,EAAayF,WAC1BC,EAAY1F,EAAa0F,UAE/B,OAAKD,aAAsBE,OACnB,IAAIJ,OAAcE,EAAYA,EAAW1F,KAAK0D,QAC1CiC,aAAqBC,OACzB,IAAIJ,OAAcG,EAAW,GAI9B1F,WAwGT4F,eAAK7G,EAAQ8G","file":"js/chunk-2d0a4d2c.e7ac0de3.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/conversion/mapper\n */\n\nimport ModelPosition from '../model/position';\nimport ModelRange from '../model/range';\n\nimport ViewPosition from '../view/position';\nimport ViewRange from '../view/range';\nimport ViewText from '../view/text';\n\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * Maps elements, positions and markers between {@link module:engine/view/document~Document the view} and\n * {@link module:engine/model/model the model}.\n *\n * The instance of the Mapper used for the editing pipeline is available in\n * {@link module:engine/controller/editingcontroller~EditingController#mapper `editor.editing.mapper`}.\n *\n * Mapper uses bound elements to find corresponding elements and positions, so, to get proper results,\n * all model elements should be {@link module:engine/conversion/mapper~Mapper#bindElements bound}.\n *\n * To map complex model to/from view relations, you may provide custom callbacks for\n * {@link module:engine/conversion/mapper~Mapper#event:modelToViewPosition modelToViewPosition event} and\n * {@link module:engine/conversion/mapper~Mapper#event:viewToModelPosition viewToModelPosition event} that are fired whenever\n * a position mapping request occurs.\n * Those events are fired by {@link module:engine/conversion/mapper~Mapper#toViewPosition toViewPosition}\n * and {@link module:engine/conversion/mapper~Mapper#toModelPosition toModelPosition} methods. `Mapper` adds it's own default callbacks\n * with `'lowest'` priority. To override default `Mapper` mapping, add custom callback with higher priority and\n * stop the event.\n * @mixes module:utils/emittermixin~EmitterMixin\n */\nexport default class Mapper {\n\t/**\n\t * Creates an instance of the mapper.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Model element to view element mapping.\n\t\t *\n\t\t * @private\n\t\t * @member {WeakMap}\n\t\t */\n\t\tthis._modelToViewMapping = new WeakMap();\n\n\t\t/**\n\t\t * View element to model element mapping.\n\t\t *\n\t\t * @private\n\t\t * @member {WeakMap}\n\t\t */\n\t\tthis._viewToModelMapping = new WeakMap();\n\n\t\t/**\n\t\t * A map containing callbacks between view element names and functions evaluating length of view elements\n\t\t * in model.\n\t\t *\n\t\t * @private\n\t\t * @member {Map}\n\t\t */\n\t\tthis._viewToModelLengthCallbacks = new Map();\n\n\t\t/**\n\t\t * Model marker name to view elements mapping.\n\t\t *\n\t\t * Keys are `String`s while values are `Set`s with {@link module:engine/view/element~Element view elements}.\n\t\t * One marker (name) can be mapped to multiple elements.\n\t\t *\n\t\t * @private\n\t\t * @member {Map}\n\t\t */\n\t\tthis._markerNameToElements = new Map();\n\n\t\t/**\n\t\t * View element to model marker names mapping.\n\t\t *\n\t\t * This is reverse to {@link ~Mapper#_markerNameToElements} map.\n\t\t *\n\t\t * @private\n\t\t * @member {Map}\n\t\t */\n\t\tthis._elementToMarkerNames = new Map();\n\n\t\t/**\n\t\t * Stores marker names of markers which has changed due to unbinding a view element (so it is assumed that the view element\n\t\t * has been removed, moved or renamed).\n\t\t *\n\t\t * @private\n\t\t * @member {Set.}\n\t\t */\n\t\tthis._unboundMarkerNames = new Set();\n\n\t\t// Default mapper algorithm for mapping model position to view position.\n\t\tthis.on( 'modelToViewPosition', ( evt, data ) => {\n\t\t\tif ( data.viewPosition ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst viewContainer = this._modelToViewMapping.get( data.modelPosition.parent );\n\n\t\t\tdata.viewPosition = this.findPositionIn( viewContainer, data.modelPosition.offset );\n\t\t}, { priority: 'low' } );\n\n\t\t// Default mapper algorithm for mapping view position to model position.\n\t\tthis.on( 'viewToModelPosition', ( evt, data ) => {\n\t\t\tif ( data.modelPosition ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst viewBlock = this.findMappedViewAncestor( data.viewPosition );\n\t\t\tconst modelParent = this._viewToModelMapping.get( viewBlock );\n\t\t\tconst modelOffset = this._toModelOffset( data.viewPosition.parent, data.viewPosition.offset, viewBlock );\n\n\t\t\tdata.modelPosition = ModelPosition._createAt( modelParent, modelOffset );\n\t\t}, { priority: 'low' } );\n\t}\n\n\t/**\n\t * Marks model and view elements as corresponding. Corresponding elements can be retrieved by using\n\t * the {@link module:engine/conversion/mapper~Mapper#toModelElement toModelElement} and\n\t * {@link module:engine/conversion/mapper~Mapper#toViewElement toViewElement} methods.\n\t * The information that elements are bound is also used to translate positions.\n\t *\n\t * @param {module:engine/model/element~Element} modelElement Model element.\n\t * @param {module:engine/view/element~Element} viewElement View element.\n\t */\n\tbindElements( modelElement, viewElement ) {\n\t\tthis._modelToViewMapping.set( modelElement, viewElement );\n\t\tthis._viewToModelMapping.set( viewElement, modelElement );\n\t}\n\n\t/**\n\t * Unbinds given {@link module:engine/view/element~Element view element} from the map.\n\t *\n\t * **Note:** view-to-model binding will be removed, if it existed. However, corresponding model-to-view binding\n\t * will be removed only if model element is still bound to passed `viewElement`.\n\t *\n\t * This behavior lets for re-binding model element to another view element without fear of losing the new binding\n\t * when the previously bound view element is unbound.\n\t *\n\t * @param {module:engine/view/element~Element} viewElement View element to unbind.\n\t */\n\tunbindViewElement( viewElement ) {\n\t\tconst modelElement = this.toModelElement( viewElement );\n\n\t\tthis._viewToModelMapping.delete( viewElement );\n\n\t\tif ( this._elementToMarkerNames.has( viewElement ) ) {\n\t\t\tfor ( const markerName of this._elementToMarkerNames.get( viewElement ) ) {\n\t\t\t\tthis._unboundMarkerNames.add( markerName );\n\t\t\t}\n\t\t}\n\n\t\tif ( this._modelToViewMapping.get( modelElement ) == viewElement ) {\n\t\t\tthis._modelToViewMapping.delete( modelElement );\n\t\t}\n\t}\n\n\t/**\n\t * Unbinds given {@link module:engine/model/element~Element model element} from the map.\n\t *\n\t * **Note:** model-to-view binding will be removed, if it existed. However, corresponding view-to-model binding\n\t * will be removed only if view element is still bound to passed `modelElement`.\n\t *\n\t * This behavior lets for re-binding view element to another model element without fear of losing the new binding\n\t * when the previously bound model element is unbound.\n\t *\n\t * @param {module:engine/model/element~Element} modelElement Model element to unbind.\n\t */\n\tunbindModelElement( modelElement ) {\n\t\tconst viewElement = this.toViewElement( modelElement );\n\n\t\tthis._modelToViewMapping.delete( modelElement );\n\n\t\tif ( this._viewToModelMapping.get( viewElement ) == modelElement ) {\n\t\t\tthis._viewToModelMapping.delete( viewElement );\n\t\t}\n\t}\n\n\t/**\n\t * Binds given marker name with given {@link module:engine/view/element~Element view element}. The element\n\t * will be added to the current set of elements bound with given marker name.\n\t *\n\t * @param {module:engine/view/element~Element} element Element to bind.\n\t * @param {String} name Marker name.\n\t */\n\tbindElementToMarker( element, name ) {\n\t\tconst elements = this._markerNameToElements.get( name ) || new Set();\n\t\telements.add( element );\n\n\t\tconst names = this._elementToMarkerNames.get( element ) || new Set();\n\t\tnames.add( name );\n\n\t\tthis._markerNameToElements.set( name, elements );\n\t\tthis._elementToMarkerNames.set( element, names );\n\t}\n\n\t/**\n\t * Unbinds an element from given marker name.\n\t *\n\t * @param {module:engine/view/element~Element} element Element to unbind.\n\t * @param {String} name Marker name.\n\t */\n\tunbindElementFromMarkerName( element, name ) {\n\t\tconst nameToElements = this._markerNameToElements.get( name );\n\n\t\tif ( nameToElements ) {\n\t\t\tnameToElements.delete( element );\n\n\t\t\tif ( nameToElements.size == 0 ) {\n\t\t\t\tthis._markerNameToElements.delete( name );\n\t\t\t}\n\t\t}\n\n\t\tconst elementToNames = this._elementToMarkerNames.get( element );\n\n\t\tif ( elementToNames ) {\n\t\t\telementToNames.delete( name );\n\n\t\t\tif ( elementToNames.size == 0 ) {\n\t\t\t\tthis._elementToMarkerNames.delete( element );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns all marker names of markers which has changed due to unbinding a view element (so it is assumed that the view element\n\t * has been removed, moved or renamed) since the last flush. After returning, the marker names list is cleared.\n\t *\n\t * @returns {Array.}\n\t */\n\tflushUnboundMarkerNames() {\n\t\tconst markerNames = Array.from( this._unboundMarkerNames );\n\n\t\tthis._unboundMarkerNames.clear();\n\n\t\treturn markerNames;\n\t}\n\n\t/**\n\t * Removes all model to view and view to model bindings.\n\t */\n\tclearBindings() {\n\t\tthis._modelToViewMapping = new WeakMap();\n\t\tthis._viewToModelMapping = new WeakMap();\n\t\tthis._markerNameToElements = new Map();\n\t\tthis._elementToMarkerNames = new Map();\n\t\tthis._unboundMarkerNames = new Set();\n\t}\n\n\t/**\n\t * Gets the corresponding model element.\n\t *\n\t * **Note:** {@link module:engine/view/uielement~UIElement} does not have corresponding element in model.\n\t *\n\t * @param {module:engine/view/element~Element} viewElement View element.\n\t * @returns {module:engine/model/element~Element|undefined} Corresponding model element or `undefined` if not found.\n\t */\n\ttoModelElement( viewElement ) {\n\t\treturn this._viewToModelMapping.get( viewElement );\n\t}\n\n\t/**\n\t * Gets the corresponding view element.\n\t *\n\t * @param {module:engine/model/element~Element} modelElement Model element.\n\t * @returns {module:engine/view/element~Element|undefined} Corresponding view element or `undefined` if not found.\n\t */\n\ttoViewElement( modelElement ) {\n\t\treturn this._modelToViewMapping.get( modelElement );\n\t}\n\n\t/**\n\t * Gets the corresponding model range.\n\t *\n\t * @param {module:engine/view/range~Range} viewRange View range.\n\t * @returns {module:engine/model/range~Range} Corresponding model range.\n\t */\n\ttoModelRange( viewRange ) {\n\t\treturn new ModelRange( this.toModelPosition( viewRange.start ), this.toModelPosition( viewRange.end ) );\n\t}\n\n\t/**\n\t * Gets the corresponding view range.\n\t *\n\t * @param {module:engine/model/range~Range} modelRange Model range.\n\t * @returns {module:engine/view/range~Range} Corresponding view range.\n\t */\n\ttoViewRange( modelRange ) {\n\t\treturn new ViewRange( this.toViewPosition( modelRange.start ), this.toViewPosition( modelRange.end ) );\n\t}\n\n\t/**\n\t * Gets the corresponding model position.\n\t *\n\t * @fires viewToModelPosition\n\t * @param {module:engine/view/position~Position} viewPosition View position.\n\t * @returns {module:engine/model/position~Position} Corresponding model position.\n\t */\n\ttoModelPosition( viewPosition ) {\n\t\tconst data = {\n\t\t\tviewPosition,\n\t\t\tmapper: this\n\t\t};\n\n\t\tthis.fire( 'viewToModelPosition', data );\n\n\t\treturn data.modelPosition;\n\t}\n\n\t/**\n\t * Gets the corresponding view position.\n\t *\n\t * @fires modelToViewPosition\n\t * @param {module:engine/model/position~Position} modelPosition Model position.\n\t * @param {Object} [options] Additional options for position mapping process.\n\t * @param {Boolean} [options.isPhantom=false] Should be set to `true` if the model position to map is pointing to a place\n\t * in model tree which no longer exists. For example, it could be an end of a removed model range.\n\t * @returns {module:engine/view/position~Position} Corresponding view position.\n\t */\n\ttoViewPosition( modelPosition, options = { isPhantom: false } ) {\n\t\tconst data = {\n\t\t\tmodelPosition,\n\t\t\tmapper: this,\n\t\t\tisPhantom: options.isPhantom\n\t\t};\n\n\t\tthis.fire( 'modelToViewPosition', data );\n\n\t\treturn data.viewPosition;\n\t}\n\n\t/**\n\t * Gets all view elements bound to the given marker name.\n\t *\n\t * @param {String} name Marker name.\n\t * @returns {Set.|null} View elements bound with given marker name or `null`\n\t * if no elements are bound to given marker name.\n\t */\n\tmarkerNameToElements( name ) {\n\t\tconst boundElements = this._markerNameToElements.get( name );\n\n\t\tif ( !boundElements ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst elements = new Set();\n\n\t\tfor ( const element of boundElements ) {\n\t\t\tif ( element.is( 'attributeElement' ) ) {\n\t\t\t\tfor ( const clone of element.getElementsWithSameId() ) {\n\t\t\t\t\telements.add( clone );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\telements.add( element );\n\t\t\t}\n\t\t}\n\n\t\treturn elements;\n\t}\n\n\t/**\n\t * Registers a callback that evaluates the length in the model of a view element with given name.\n\t *\n\t * The callback is fired with one argument, which is a view element instance. The callback is expected to return\n\t * a number representing the length of view element in model.\n\t *\n\t *\t\t// List item in view may contain nested list, which have other list items. In model though,\n\t *\t\t// the lists are represented by flat structure. Because of those differences, length of list view element\n\t *\t\t// may be greater than one. In the callback it's checked how many nested list items are in evaluated list item.\n\t *\n\t *\t\tfunction getViewListItemLength( element ) {\n\t *\t\t\tlet length = 1;\n\t *\n\t *\t\t\tfor ( let child of element.getChildren() ) {\n\t *\t\t\t\tif ( child.name == 'ul' || child.name == 'ol' ) {\n\t *\t\t\t\t\tfor ( let item of child.getChildren() ) {\n\t *\t\t\t\t\t\tlength += getViewListItemLength( item );\n\t *\t\t\t\t\t}\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\n\t *\t\t\treturn length;\n\t *\t\t}\n\t *\n\t *\t\tmapper.registerViewToModelLength( 'li', getViewListItemLength );\n\t *\n\t * @param {String} viewElementName Name of view element for which callback is registered.\n\t * @param {Function} lengthCallback Function return a length of view element instance in model.\n\t */\n\tregisterViewToModelLength( viewElementName, lengthCallback ) {\n\t\tthis._viewToModelLengthCallbacks.set( viewElementName, lengthCallback );\n\t}\n\n\t/**\n\t * For given `viewPosition`, finds and returns the closest ancestor of this position that has a mapping to\n\t * the model.\n\t *\n\t * @param {module:engine/view/position~Position} viewPosition Position for which mapped ancestor should be found.\n\t * @returns {module:engine/view/element~Element}\n\t */\n\tfindMappedViewAncestor( viewPosition ) {\n\t\tlet parent = viewPosition.parent;\n\n\t\twhile ( !this._viewToModelMapping.has( parent ) ) {\n\t\t\tparent = parent.parent;\n\t\t}\n\n\t\treturn parent;\n\t}\n\n\t/**\n\t * Calculates model offset based on the view position and the block element.\n\t *\n\t * Example:\n\t *\n\t *\t\t

fooba|r

// _toModelOffset( b, 2, p ) -> 5\n\t *\n\t * Is a sum of:\n\t *\n\t *\t\t

foo|bar

// _toModelOffset( p, 3, p ) -> 3\n\t *\t\t

fooba|r

// _toModelOffset( b, 2, b ) -> 2\n\t *\n\t * @private\n\t * @param {module:engine/view/element~Element} viewParent Position parent.\n\t * @param {Number} viewOffset Position offset.\n\t * @param {module:engine/view/element~Element} viewBlock Block used as a base to calculate offset.\n\t * @returns {Number} Offset in the model.\n\t */\n\t_toModelOffset( viewParent, viewOffset, viewBlock ) {\n\t\tif ( viewBlock != viewParent ) {\n\t\t\t// See example.\n\t\t\tconst offsetToParentStart = this._toModelOffset( viewParent.parent, viewParent.index, viewBlock );\n\t\t\tconst offsetInParent = this._toModelOffset( viewParent, viewOffset, viewParent );\n\n\t\t\treturn offsetToParentStart + offsetInParent;\n\t\t}\n\n\t\t// viewBlock == viewParent, so we need to calculate the offset in the parent element.\n\n\t\t// If the position is a text it is simple (\"ba|r\" -> 2).\n\t\tif ( viewParent.is( '$text' ) ) {\n\t\t\treturn viewOffset;\n\t\t}\n\n\t\t// If the position is in an element we need to sum lengths of siblings ( bar foo | -> 3 + 3 = 6 ).\n\t\tlet modelOffset = 0;\n\n\t\tfor ( let i = 0; i < viewOffset; i++ ) {\n\t\t\tmodelOffset += this.getModelLength( viewParent.getChild( i ) );\n\t\t}\n\n\t\treturn modelOffset;\n\t}\n\n\t/**\n\t * Gets the length of the view element in the model.\n\t *\n\t * The length is calculated as follows:\n\t * * if {@link #registerViewToModelLength length mapping callback} is provided for given `viewNode` it is used to\n\t * evaluate model length (`viewNode` is used as first and only parameter passed to the callback),\n\t * * length of a {@link module:engine/view/text~Text text node} is equal to the length of it's\n\t * {@link module:engine/view/text~Text#data data},\n\t * * length of a {@link module:engine/view/uielement~UIElement ui element} is equal to 0,\n\t * * length of a mapped {@link module:engine/view/element~Element element} is equal to 1,\n\t * * length of a not-mapped {@link module:engine/view/element~Element element} is equal to the length of it's children.\n\t *\n\t * Examples:\n\t *\n\t *\t\tfoo -> 3 // Text length is equal to it's data length.\n\t *\t\t

foo

-> 1 // Length of an element which is mapped is by default equal to 1.\n\t *\t\tfoo -> 3 // Length of an element which is not mapped is a length of its children.\n\t *\t\t

x

y

-> 2 // Assuming that
is not mapped and

are mapped.\n\t *\n\t * @param {module:engine/view/element~Element} viewNode View node.\n\t * @returns {Number} Length of the node in the tree model.\n\t */\n\tgetModelLength( viewNode ) {\n\t\tif ( this._viewToModelLengthCallbacks.get( viewNode.name ) ) {\n\t\t\tconst callback = this._viewToModelLengthCallbacks.get( viewNode.name );\n\n\t\t\treturn callback( viewNode );\n\t\t} else if ( this._viewToModelMapping.has( viewNode ) ) {\n\t\t\treturn 1;\n\t\t} else if ( viewNode.is( '$text' ) ) {\n\t\t\treturn viewNode.data.length;\n\t\t} else if ( viewNode.is( 'uiElement' ) ) {\n\t\t\treturn 0;\n\t\t} else {\n\t\t\tlet len = 0;\n\n\t\t\tfor ( const child of viewNode.getChildren() ) {\n\t\t\t\tlen += this.getModelLength( child );\n\t\t\t}\n\n\t\t\treturn len;\n\t\t}\n\t}\n\n\t/**\n\t * Finds the position in the view node (or its children) with the expected model offset.\n\t *\n\t * Example:\n\t *\n\t *\t\t

fobarbom

-> expected offset: 4\n\t *\n\t *\t\tfindPositionIn( p, 4 ):\n\t *\t\t

|fobarbom

-> expected offset: 4, actual offset: 0\n\t *\t\t

fo|barbom

-> expected offset: 4, actual offset: 2\n\t *\t\t

fobar|bom

-> expected offset: 4, actual offset: 5 -> we are too far\n\t *\n\t *\t\tfindPositionIn( b, 4 - ( 5 - 3 ) ):\n\t *\t\t

fo|barbom

-> expected offset: 2, actual offset: 0\n\t *\t\t

fobar|bom

-> expected offset: 2, actual offset: 3 -> we are too far\n\t *\n\t *\t\tfindPositionIn( bar, 2 - ( 3 - 3 ) ):\n\t *\t\tWe are in the text node so we can simple find the offset.\n\t *\t\t

foba|rbom

-> expected offset: 2, actual offset: 2 -> position found\n\t *\n\t * @param {module:engine/view/element~Element} viewParent Tree view element in which we are looking for the position.\n\t * @param {Number} expectedOffset Expected offset.\n\t * @returns {module:engine/view/position~Position} Found position.\n\t */\n\tfindPositionIn( viewParent, expectedOffset ) {\n\t\t// Last scanned view node.\n\t\tlet viewNode;\n\t\t// Length of the last scanned view node.\n\t\tlet lastLength = 0;\n\n\t\tlet modelOffset = 0;\n\t\tlet viewOffset = 0;\n\n\t\t// In the text node it is simple: offset in the model equals offset in the text.\n\t\tif ( viewParent.is( '$text' ) ) {\n\t\t\treturn new ViewPosition( viewParent, expectedOffset );\n\t\t}\n\n\t\t// In other cases we add lengths of child nodes to find the proper offset.\n\n\t\t// If it is smaller we add the length.\n\t\twhile ( modelOffset < expectedOffset ) {\n\t\t\tviewNode = viewParent.getChild( viewOffset );\n\t\t\tlastLength = this.getModelLength( viewNode );\n\t\t\tmodelOffset += lastLength;\n\t\t\tviewOffset++;\n\t\t}\n\n\t\t// If it equals we found the position.\n\t\tif ( modelOffset == expectedOffset ) {\n\t\t\treturn this._moveViewPositionToTextNode( new ViewPosition( viewParent, viewOffset ) );\n\t\t}\n\t\t// If it is higher we need to enter last child.\n\t\telse {\n\t\t\t// ( modelOffset - lastLength ) is the offset to the child we enter,\n\t\t\t// so we subtract it from the expected offset to fine the offset in the child.\n\t\t\treturn this.findPositionIn( viewNode, expectedOffset - ( modelOffset - lastLength ) );\n\t\t}\n\t}\n\n\t/**\n\t * Because we prefer positions in text nodes over positions next to text node moves view position to the text node\n\t * if it was next to it.\n\t *\n\t *\t\t

[]foo

->

[]foo

// do not touch if position is not directly next to text\n\t *\t\t

foo[]foo

->

foo{}foo

// move to text node\n\t *\t\t

[]foo

->

{}foo

// move to text node\n\t *\n\t * @private\n\t * @param {module:engine/view/position~Position} viewPosition Position potentially next to text node.\n\t * @returns {module:engine/view/position~Position} Position in text node if possible.\n\t */\n\t_moveViewPositionToTextNode( viewPosition ) {\n\t\t// If the position is just after text node, put it at the end of that text node.\n\t\t// If the position is just before text node, put it at the beginning of that text node.\n\t\tconst nodeBefore = viewPosition.nodeBefore;\n\t\tconst nodeAfter = viewPosition.nodeAfter;\n\n\t\tif ( nodeBefore instanceof ViewText ) {\n\t\t\treturn new ViewPosition( nodeBefore, nodeBefore.data.length );\n\t\t} else if ( nodeAfter instanceof ViewText ) {\n\t\t\treturn new ViewPosition( nodeAfter, 0 );\n\t\t}\n\n\t\t// Otherwise, just return the given position.\n\t\treturn viewPosition;\n\t}\n\n\t/**\n\t * Fired for each model-to-view position mapping request. The purpose of this event is to enable custom model-to-view position\n\t * mapping. Callbacks added to this event take {@link module:engine/model/position~Position model position} and are expected to\n\t * calculate {@link module:engine/view/position~Position view position}. Calculated view position should be added as `viewPosition`\n\t * value in `data` object that is passed as one of parameters to the event callback.\n\t *\n\t * \t\t// Assume that \"captionedImage\" model element is converted to and following elements in view,\n\t * \t\t// and the model element is bound to element. Force mapping model positions inside \"captionedImage\" to that\n\t * \t\t// element.\n\t *\t\tmapper.on( 'modelToViewPosition', ( evt, data ) => {\n\t *\t\t\tconst positionParent = modelPosition.parent;\n\t *\n\t *\t\t\tif ( positionParent.name == 'captionedImage' ) {\n\t *\t\t\t\tconst viewImg = data.mapper.toViewElement( positionParent );\n\t *\t\t\t\tconst viewCaption = viewImg.nextSibling; // The element.\n\t *\n\t *\t\t\t\tdata.viewPosition = new ViewPosition( viewCaption, modelPosition.offset );\n\t *\n\t *\t\t\t\t// Stop the event if other callbacks should not modify calculated value.\n\t *\t\t\t\tevt.stop();\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * **Note:** keep in mind that sometimes a \"phantom\" model position is being converted. \"Phantom\" model position is\n\t * a position that points to a non-existing place in model. Such position might still be valid for conversion, though\n\t * (it would point to a correct place in view when converted). One example of such situation is when a range is\n\t * removed from model, there may be a need to map the range's end (which is no longer valid model position). To\n\t * handle such situation, check `data.isPhantom` flag:\n\t *\n\t * \t\t// Assume that there is \"customElement\" model element and whenever position is before it, we want to move it\n\t * \t\t// to the inside of the view element bound to \"customElement\".\n\t *\t\tmapper.on( 'modelToViewPosition', ( evt, data ) => {\n\t *\t\t\tif ( data.isPhantom ) {\n\t *\t\t\t\treturn;\n\t *\t\t\t}\n\t *\n\t *\t\t\t// Below line might crash for phantom position that does not exist in model.\n\t *\t\t\tconst sibling = data.modelPosition.nodeBefore;\n\t *\n\t *\t\t\t// Check if this is the element we are interested in.\n\t *\t\t\tif ( !sibling.is( 'element', 'customElement' ) ) {\n\t *\t\t\t\treturn;\n\t *\t\t\t}\n\t *\n\t *\t\t\tconst viewElement = data.mapper.toViewElement( sibling );\n\t *\n\t *\t\t\tdata.viewPosition = new ViewPosition( sibling, 0 );\n\t *\n\t *\t\t\tevt.stop();\n\t *\t\t} );\n\t *\n\t * **Note:** default mapping callback is provided with `low` priority setting and does not cancel the event, so it is possible to\n\t * attach a custom callback after default callback and also use `data.viewPosition` calculated by default callback\n\t * (for example to fix it).\n\t *\n\t * **Note:** default mapping callback will not fire if `data.viewPosition` is already set.\n\t *\n\t * **Note:** these callbacks are called **very often**. For efficiency reasons, it is advised to use them only when position\n\t * mapping between given model and view elements is unsolvable using just elements mapping and default algorithm. Also,\n\t * the condition that checks if special case scenario happened should be as simple as possible.\n\t *\n\t * @event modelToViewPosition\n\t * @param {Object} data Data pipeline object that can store and pass data between callbacks. The callback should add\n\t * `viewPosition` value to that object with calculated {@link module:engine/view/position~Position view position}.\n\t * @param {module:engine/conversion/mapper~Mapper} data.mapper Mapper instance that fired the event.\n\t */\n\n\t/**\n\t * Fired for each view-to-model position mapping request. See {@link module:engine/conversion/mapper~Mapper#event:modelToViewPosition}.\n\t *\n\t * \t\t// See example in `modelToViewPosition` event description.\n\t * \t\t// This custom mapping will map positions from element next to to the \"captionedImage\" element.\n\t *\t\tmapper.on( 'viewToModelPosition', ( evt, data ) => {\n\t *\t\t\tconst positionParent = viewPosition.parent;\n\t *\n\t *\t\t\tif ( positionParent.hasClass( 'image-caption' ) ) {\n\t *\t\t\t\tconst viewImg = positionParent.previousSibling;\n\t *\t\t\t\tconst modelImg = data.mapper.toModelElement( viewImg );\n\t *\n\t *\t\t\t\tdata.modelPosition = new ModelPosition( modelImg, viewPosition.offset );\n\t *\t\t\t\tevt.stop();\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * **Note:** default mapping callback is provided with `low` priority setting and does not cancel the event, so it is possible to\n\t * attach a custom callback after default callback and also use `data.modelPosition` calculated by default callback\n\t * (for example to fix it).\n\t *\n\t * **Note:** default mapping callback will not fire if `data.modelPosition` is already set.\n\t *\n\t * **Note:** these callbacks are called **very often**. For efficiency reasons, it is advised to use them only when position\n\t * mapping between given model and view elements is unsolvable using just elements mapping and default algorithm. Also,\n\t * the condition that checks if special case scenario happened should be as simple as possible.\n\t *\n\t * @event viewToModelPosition\n\t * @param {Object} data Data pipeline object that can store and pass data between callbacks. The callback should add\n\t * `modelPosition` value to that object with calculated {@link module:engine/model/position~Position model position}.\n\t * @param {module:engine/conversion/mapper~Mapper} data.mapper Mapper instance that fired the event.\n\t */\n}\n\nmix( Mapper, EmitterMixin );\n"],"sourceRoot":""}