{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/conversion/upcastdispatcher.js"],"names":["UpcastDispatcher","conversionApi","arguments","length","undefined","Object","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_classCallCheck_js__WEBPACK_IMPORTED_MODULE_12__","this","_splitParts","Map","_cursorParents","_modelCursor","assign","convertItem","_convertItem","bind","convertChildren","_convertChildren","safeInsert","_safeInsert","updateConversionResult","_updateConversionResult","splitToAllowedParent","_splitToAllowedParent","getSplitParts","_getSplitParts","viewItem","writer","context","fire","createContextTree","consumable","ViewConsumable","createFrom","store","_this$_convertItem","modelRange","documentFragment","createDocumentFragment","_removeEmptyElements","_i","_Array$from","Array","from","parent","getChildren","item","append","markers","extractMarkersFromModelFragment","clear","modelCursor","data","is","name","ModelRange","CKEditorError","elementOrModelCursor","nextModelCursor","ModelPosition","_createAt","_i2","_Array$from2","viewChild","result","end","modelElement","position","splitResult","insert","parts","createRange","createPositionBefore","createPositionAfter","savedCursorParent","get","createPositionAt","node","_this$conversionApi","schema","allowedParent","findAllowedParent","getAncestors","includes","isParagraphable","wrapInParagraph","_step","split","stack","_iterator","_createForOfIteratorHelper","range","getWalker","s","n","done","treeWalkerValue","value","type","push","originalPart","pop","splitPart","_registerSplitPair","err","e","f","cursorParent","set","has","list","element","_step2","anyRemoved","_iterator2","keys","isEmpty","remove","delete","modelItem","_step3","markerElements","Set","_createIn","getItems","_iterator3","add","_step4","_iterator4","markerElement","markerName","getAttribute","currentPosition","clone","contextDefinition","_step5","_iterator5","SchemaContext","_step6","attributes","_iterator6","getAttributeKeys","key","current","createElement","mix","EmitterMixin"],"mappings":"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","file":"js/chunk-2d0c7d4e.bde7bf16.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/upcastdispatcher\n */\n\nimport ViewConsumable from './viewconsumable';\nimport ModelRange from '../model/range';\nimport ModelPosition from '../model/position';\nimport { SchemaContext } from '../model/schema';\nimport { isParagraphable, wrapInParagraph } from '../model/utils/autoparagraphing';\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * Upcast dispatcher is a central point of the view-to-model conversion, which is a process of\n * converting a given {@link module:engine/view/documentfragment~DocumentFragment view document fragment} or\n * {@link module:engine/view/element~Element view element} into a correct model structure.\n *\n * During the conversion process, the dispatcher fires events for all {@link module:engine/view/node~Node view nodes}\n * from the converted view document fragment.\n * Special callbacks called \"converters\" should listen to these events in order to convert the view nodes.\n *\n * The second parameter of the callback is the `data` object with the following properties:\n *\n * * `data.viewItem` contains a {@link module:engine/view/node~Node view node} or a\n * {@link module:engine/view/documentfragment~DocumentFragment view document fragment}\n * that is converted at the moment and might be handled by the callback.\n * * `data.modelRange` is used to point to the result\n * of the current conversion (e.g. the element that is being inserted)\n * and is always a {@link module:engine/model/range~Range} when the conversion succeeds.\n * * `data.modelCursor` is a {@link module:engine/model/position~Position position} on which the converter should insert\n * the newly created items.\n *\n * The third parameter of the callback is an instance of {@link module:engine/conversion/upcastdispatcher~UpcastConversionApi}\n * which provides additional tools for converters.\n *\n * You can read more about conversion in the following guides:\n *\n * * {@glink framework/guides/deep-dive/conversion/conversion-introduction Advanced conversion concepts — attributes}\n * * {@glink framework/guides/deep-dive/conversion/custom-element-conversion Custom element conversion}\n *\n * Examples of event-based converters:\n *\n *\t\t// A converter for links ().\n *\t\teditor.data.upcastDispatcher.on( 'element:a', ( evt, data, conversionApi ) => {\n *\t\t\tif ( conversionApi.consumable.consume( data.viewItem, { name: true, attributes: [ 'href' ] } ) ) {\n *\t\t\t\t// The element is inline and is represented by an attribute in the model.\n *\t\t\t\t// This is why you need to convert only children.\n *\t\t\t\tconst { modelRange } = conversionApi.convertChildren( data.viewItem, data.modelCursor );\n *\n *\t\t\t\tfor ( let item of modelRange.getItems() ) {\n *\t\t\t\t\tif ( conversionApi.schema.checkAttribute( item, 'linkHref' ) ) {\n *\t\t\t\t\t\tconversionApi.writer.setAttribute( 'linkHref', data.viewItem.getAttribute( 'href' ), item );\n *\t\t\t\t\t}\n *\t\t\t\t}\n *\t\t\t}\n *\t\t} );\n *\n *\t\t// Convert

element's font-size style.\n *\t\t// Note: You should use a low-priority observer in order to ensure that\n *\t\t// it is executed after the element-to-element converter.\n *\t\teditor.data.upcastDispatcher.on( 'element:p', ( evt, data, conversionApi ) => {\n *\t\t\tconst { consumable, schema, writer } = conversionApi;\n *\n *\t\t\tif ( !consumable.consume( data.viewItem, { style: 'font-size' } ) ) {\n *\t\t\t\treturn;\n *\t\t\t}\n *\n *\t\t\tconst fontSize = data.viewItem.getStyle( 'font-size' );\n *\n *\t\t\t// Do not go for the model element after data.modelCursor because it might happen\n *\t\t\t// that a single view element was converted to multiple model elements. Get all of them.\n *\t\t\tfor ( const item of data.modelRange.getItems( { shallow: true } ) ) {\n *\t\t\t\tif ( schema.checkAttribute( item, 'fontSize' ) ) {\n *\t\t\t\t\twriter.setAttribute( 'fontSize', fontSize, item );\n *\t\t\t\t}\n *\t\t\t}\n *\t\t}, { priority: 'low' } );\n *\n *\t\t// Convert all elements which have no custom converter into a paragraph (autoparagraphing).\n *\t\teditor.data.upcastDispatcher.on( 'element', ( evt, data, conversionApi ) => {\n *\t\t\t// Check if an element can be converted.\n *\t\t\tif ( !conversionApi.consumable.test( data.viewItem, { name: data.viewItem.name } ) ) {\n *\t\t\t\t// When an element is already consumed by higher priority converters, do nothing.\n *\t\t\t\treturn;\n *\t\t\t}\n *\n *\t\t\tconst paragraph = conversionApi.writer.createElement( 'paragraph' );\n *\n *\t\t\t// Try to safely insert a paragraph at the model cursor - it will find an allowed parent for the current element.\n *\t\t\tif ( !conversionApi.safeInsert( paragraph, data.modelCursor ) ) {\n *\t\t\t\t// When an element was not inserted, it means that you cannot insert a paragraph at this position.\n *\t\t\t\treturn;\n *\t\t\t}\n *\n *\t\t\t// Consume the inserted element.\n *\t\t\tconversionApi.consumable.consume( data.viewItem, { name: data.viewItem.name } ) );\n *\n *\t\t\t// Convert the children to a paragraph.\n *\t\t\tconst { modelRange } = conversionApi.convertChildren( data.viewItem, paragraph ) );\n *\n *\t\t\t// Update `modelRange` and `modelCursor` in the `data` as a conversion result.\n *\t\t\tconversionApi.updateConversionResult( paragraph, data );\n *\t\t}, { priority: 'low' } );\n *\n * @mixes module:utils/emittermixin~EmitterMixin\n * @fires viewCleanup\n * @fires element\n * @fires text\n * @fires documentFragment\n */\nexport default class UpcastDispatcher {\n\t/**\n\t * Creates an upcast dispatcher that operates using the passed API.\n\t *\n\t * @see module:engine/conversion/upcastdispatcher~UpcastConversionApi\n\t * @param {Object} [conversionApi] Additional properties for an interface that will be passed to events fired\n\t * by the upcast dispatcher.\n\t */\n\tconstructor( conversionApi = {} ) {\n\t\t/**\n\t\t * The list of elements that were created during splitting.\n\t\t *\n\t\t * After the conversion process the list is cleared.\n\t\t *\n\t\t * @private\n\t\t * @type {Map.>}\n\t\t */\n\t\tthis._splitParts = new Map();\n\n\t\t/**\n\t\t * The list of cursor parent elements that were created during splitting.\n\t\t *\n\t\t * After the conversion process the list is cleared.\n\t\t *\n\t\t * @private\n\t\t * @type {Map.>}\n\t\t */\n\t\tthis._cursorParents = new Map();\n\n\t\t/**\n\t\t * The position in the temporary structure where the converted content is inserted. The structure reflects the context of\n\t\t * the target position where the content will be inserted. This property is built based on the context parameter of the\n\t\t * convert method.\n\t\t *\n\t\t * @private\n\t\t * @type {module:engine/model/position~Position|null}\n\t\t */\n\t\tthis._modelCursor = null;\n\n\t\t/**\n\t\t * An interface passed by the dispatcher to the event callbacks.\n\t\t *\n\t\t * @member {module:engine/conversion/upcastdispatcher~UpcastConversionApi}\n\t\t */\n\t\tthis.conversionApi = Object.assign( {}, conversionApi );\n\n\t\t// The below methods are bound to this `UpcastDispatcher` instance and set on `conversionApi`.\n\t\t// This way only a part of `UpcastDispatcher` API is exposed.\n\t\tthis.conversionApi.convertItem = this._convertItem.bind( this );\n\t\tthis.conversionApi.convertChildren = this._convertChildren.bind( this );\n\t\tthis.conversionApi.safeInsert = this._safeInsert.bind( this );\n\t\tthis.conversionApi.updateConversionResult = this._updateConversionResult.bind( this );\n\t\t// Advanced API - use only if custom position handling is needed.\n\t\tthis.conversionApi.splitToAllowedParent = this._splitToAllowedParent.bind( this );\n\t\tthis.conversionApi.getSplitParts = this._getSplitParts.bind( this );\n\t}\n\n\t/**\n\t * Starts the conversion process. The entry point for the conversion.\n\t *\n\t * @fires element\n\t * @fires text\n\t * @fires documentFragment\n\t * @param {module:engine/view/documentfragment~DocumentFragment|module:engine/view/element~Element} viewItem\n\t * The part of the view to be converted.\n\t * @param {module:engine/model/writer~Writer} writer An instance of the model writer.\n\t * @param {module:engine/model/schema~SchemaContextDefinition} [context=['$root']] Elements will be converted according to this context.\n\t * @returns {module:engine/model/documentfragment~DocumentFragment} Model data that is the result of the conversion process\n\t * wrapped in `DocumentFragment`. Converted marker elements will be set as the document fragment's\n\t * {@link module:engine/model/documentfragment~DocumentFragment#markers static markers map}.\n\t */\n\tconvert( viewItem, writer, context = [ '$root' ] ) {\n\t\tthis.fire( 'viewCleanup', viewItem );\n\n\t\t// Create context tree and set position in the top element.\n\t\t// Items will be converted according to this position.\n\t\tthis._modelCursor = createContextTree( context, writer );\n\n\t\t// Store writer in conversion as a conversion API\n\t\t// to be sure that conversion process will use the same batch.\n\t\tthis.conversionApi.writer = writer;\n\n\t\t// Create consumable values list for conversion process.\n\t\tthis.conversionApi.consumable = ViewConsumable.createFrom( viewItem );\n\n\t\t// Custom data stored by converter for conversion process.\n\t\tthis.conversionApi.store = {};\n\n\t\t// Do the conversion.\n\t\tconst { modelRange } = this._convertItem( viewItem, this._modelCursor );\n\n\t\t// Conversion result is always a document fragment so let's create it.\n\t\tconst documentFragment = writer.createDocumentFragment();\n\n\t\t// When there is a conversion result.\n\t\tif ( modelRange ) {\n\t\t\t// Remove all empty elements that were create while splitting.\n\t\t\tthis._removeEmptyElements();\n\n\t\t\t// Move all items that were converted in context tree to the document fragment.\n\t\t\tfor ( const item of Array.from( this._modelCursor.parent.getChildren() ) ) {\n\t\t\t\twriter.append( item, documentFragment );\n\t\t\t}\n\n\t\t\t// Extract temporary markers elements from model and set as static markers collection.\n\t\t\tdocumentFragment.markers = extractMarkersFromModelFragment( documentFragment, writer );\n\t\t}\n\n\t\t// Clear context position.\n\t\tthis._modelCursor = null;\n\n\t\t// Clear split elements & parents lists.\n\t\tthis._splitParts.clear();\n\t\tthis._cursorParents.clear();\n\n\t\t// Clear conversion API.\n\t\tthis.conversionApi.writer = null;\n\t\tthis.conversionApi.store = null;\n\n\t\t// Return fragment as conversion result.\n\t\treturn documentFragment;\n\t}\n\n\t/**\n\t * @private\n\t * @see module:engine/conversion/upcastdispatcher~UpcastConversionApi#convertItem\n\t */\n\t_convertItem( viewItem, modelCursor ) {\n\t\tconst data = Object.assign( { viewItem, modelCursor, modelRange: null } );\n\n\t\tif ( viewItem.is( 'element' ) ) {\n\t\t\tthis.fire( 'element:' + viewItem.name, data, this.conversionApi );\n\t\t} else if ( viewItem.is( '$text' ) ) {\n\t\t\tthis.fire( 'text', data, this.conversionApi );\n\t\t} else {\n\t\t\tthis.fire( 'documentFragment', data, this.conversionApi );\n\t\t}\n\n\t\t// Handle incorrect conversion result.\n\t\tif ( data.modelRange && !( data.modelRange instanceof ModelRange ) ) {\n\t\t\t/**\n\t\t\t * Incorrect conversion result was dropped.\n\t\t\t *\n\t\t\t * {@link module:engine/model/range~Range Model range} should be a conversion result.\n\t\t\t *\n\t\t\t * @error view-conversion-dispatcher-incorrect-result\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-conversion-dispatcher-incorrect-result', this );\n\t\t}\n\n\t\treturn { modelRange: data.modelRange, modelCursor: data.modelCursor };\n\t}\n\n\t/**\n\t * @private\n\t * @see module:engine/conversion/upcastdispatcher~UpcastConversionApi#convertChildren\n\t */\n\t_convertChildren( viewItem, elementOrModelCursor ) {\n\t\tlet nextModelCursor = elementOrModelCursor.is( 'position' ) ?\n\t\t\telementOrModelCursor : ModelPosition._createAt( elementOrModelCursor, 0 );\n\n\t\tconst modelRange = new ModelRange( nextModelCursor );\n\n\t\tfor ( const viewChild of Array.from( viewItem.getChildren() ) ) {\n\t\t\tconst result = this._convertItem( viewChild, nextModelCursor );\n\n\t\t\tif ( result.modelRange instanceof ModelRange ) {\n\t\t\t\tmodelRange.end = result.modelRange.end;\n\t\t\t\tnextModelCursor = result.modelCursor;\n\t\t\t}\n\t\t}\n\n\t\treturn { modelRange, modelCursor: nextModelCursor };\n\t}\n\n\t/**\n\t * @private\n\t * @see module:engine/conversion/upcastdispatcher~UpcastConversionApi#safeInsert\n\t */\n\t_safeInsert( modelElement, position ) {\n\t\t// Find allowed parent for element that we are going to insert.\n\t\t// If current parent does not allow to insert element but one of the ancestors does\n\t\t// then split nodes to allowed parent.\n\t\tconst splitResult = this._splitToAllowedParent( modelElement, position );\n\n\t\t// When there is no split result it means that we can't insert element to model tree, so let's skip it.\n\t\tif ( !splitResult ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Insert element on allowed position.\n\t\tthis.conversionApi.writer.insert( modelElement, splitResult.position );\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * @private\n\t * @see module:engine/conversion/upcastdispatcher~UpcastConversionApi#updateConversionResult\n\t */\n\t_updateConversionResult( modelElement, data ) {\n\t\tconst parts = this._getSplitParts( modelElement );\n\n\t\tconst writer = this.conversionApi.writer;\n\n\t\t// Set conversion result range - only if not set already.\n\t\tif ( !data.modelRange ) {\n\t\t\tdata.modelRange = writer.createRange(\n\t\t\t\twriter.createPositionBefore( modelElement ),\n\t\t\t\twriter.createPositionAfter( parts[ parts.length - 1 ] )\n\t\t\t);\n\t\t}\n\n\t\tconst savedCursorParent = this._cursorParents.get( modelElement );\n\n\t\t// Now we need to check where the `modelCursor` should be.\n\t\tif ( savedCursorParent ) {\n\t\t\t// If we split parent to insert our element then we want to continue conversion in the new part of the split parent.\n\t\t\t//\n\t\t\t// before: foo[]\n\t\t\t// after: foo []\n\n\t\t\tdata.modelCursor = writer.createPositionAt( savedCursorParent, 0 );\n\t\t} else {\n\t\t\t// Otherwise just continue after inserted element.\n\n\t\t\tdata.modelCursor = data.modelRange.end;\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t * @see module:engine/conversion/upcastdispatcher~UpcastConversionApi#splitToAllowedParent\n\t */\n\t_splitToAllowedParent( node, modelCursor ) {\n\t\tconst { schema, writer } = this.conversionApi;\n\n\t\t// Try to find allowed parent.\n\t\tlet allowedParent = schema.findAllowedParent( modelCursor, node );\n\n\t\tif ( allowedParent ) {\n\t\t\t// When current position parent allows to insert node then return this position.\n\t\t\tif ( allowedParent === modelCursor.parent ) {\n\t\t\t\treturn { position: modelCursor };\n\t\t\t}\n\n\t\t\t// When allowed parent is in context tree (it's outside the converted tree).\n\t\t\tif ( this._modelCursor.parent.getAncestors().includes( allowedParent ) ) {\n\t\t\t\tallowedParent = null;\n\t\t\t}\n\t\t}\n\n\t\tif ( !allowedParent ) {\n\t\t\t// Check if the node wrapped with a paragraph would be accepted by the schema.\n\t\t\tif ( !isParagraphable( modelCursor, node, schema ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tposition: wrapInParagraph( modelCursor, writer )\n\t\t\t};\n\t\t}\n\n\t\t// Split element to allowed parent.\n\t\tconst splitResult = this.conversionApi.writer.split( modelCursor, allowedParent );\n\n\t\t// Using the range returned by `model.Writer#split`, we will pair original elements with their split parts.\n\t\t//\n\t\t// The range returned from the writer spans \"over the split\" or, precisely saying, from the end of the original element (the one\n\t\t// that got split) to the beginning of the other part of that element:\n\t\t//\n\t\t// X[]Y ->\n\t\t// X[]Y\n\t\t//\n\t\t// After the split there cannot be any full node between the positions in `splitRange`. The positions are touching.\n\t\t// Also, because of how splitting works, it is easy to notice, that \"closing tags\" are in the reverse order than \"opening tags\".\n\t\t// Also, since we split all those elements, each of them has to have the other part.\n\t\t//\n\t\t// With those observations in mind, we will pair the original elements with their split parts by saving \"closing tags\" and matching\n\t\t// them with \"opening tags\" in the reverse order. For that we can use a stack.\n\t\tconst stack = [];\n\n\t\tfor ( const treeWalkerValue of splitResult.range.getWalker() ) {\n\t\t\tif ( treeWalkerValue.type == 'elementEnd' ) {\n\t\t\t\tstack.push( treeWalkerValue.item );\n\t\t\t} else {\n\t\t\t\t// There should not be any text nodes after the element is split, so the only other value is `elementStart`.\n\t\t\t\tconst originalPart = stack.pop();\n\t\t\t\tconst splitPart = treeWalkerValue.item;\n\n\t\t\t\tthis._registerSplitPair( originalPart, splitPart );\n\t\t\t}\n\t\t}\n\n\t\tconst cursorParent = splitResult.range.end.parent;\n\t\tthis._cursorParents.set( node, cursorParent );\n\n\t\treturn {\n\t\t\tposition: splitResult.position,\n\t\t\tcursorParent\n\t\t};\n\t}\n\n\t/**\n\t * Registers that a `splitPart` element is a split part of the `originalPart` element.\n\t *\n\t * The data set by this method is used by {@link #_getSplitParts} and {@link #_removeEmptyElements}.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} originalPart\n\t * @param {module:engine/model/element~Element} splitPart\n\t */\n\t_registerSplitPair( originalPart, splitPart ) {\n\t\tif ( !this._splitParts.has( originalPart ) ) {\n\t\t\tthis._splitParts.set( originalPart, [ originalPart ] );\n\t\t}\n\n\t\tconst list = this._splitParts.get( originalPart );\n\n\t\tthis._splitParts.set( splitPart, list );\n\t\tlist.push( splitPart );\n\t}\n\n\t/**\n\t * @private\n\t * @see module:engine/conversion/upcastdispatcher~UpcastConversionApi#getSplitParts\n\t */\n\t_getSplitParts( element ) {\n\t\tlet parts;\n\n\t\tif ( !this._splitParts.has( element ) ) {\n\t\t\tparts = [ element ];\n\t\t} else {\n\t\t\tparts = this._splitParts.get( element );\n\t\t}\n\n\t\treturn parts;\n\t}\n\n\t/**\n\t * Checks if there are any empty elements created while splitting and removes them.\n\t *\n\t * This method works recursively to re-check empty elements again after at least one element was removed in the initial call,\n\t * as some elements might have become empty after other empty elements were removed from them.\n\t *\n\t * @private\n\t */\n\t_removeEmptyElements() {\n\t\tlet anyRemoved = false;\n\n\t\tfor ( const element of this._splitParts.keys() ) {\n\t\t\tif ( element.isEmpty ) {\n\t\t\t\tthis.conversionApi.writer.remove( element );\n\t\t\t\tthis._splitParts.delete( element );\n\n\t\t\t\tanyRemoved = true;\n\t\t\t}\n\t\t}\n\n\t\tif ( anyRemoved ) {\n\t\t\tthis._removeEmptyElements();\n\t\t}\n\t}\n\n\t/**\n\t * Fired before the first conversion event, at the beginning of the upcast (view-to-model conversion) process.\n\t *\n\t * @event viewCleanup\n\t * @param {module:engine/view/documentfragment~DocumentFragment|module:engine/view/element~Element}\n\t * viewItem A part of the view to be converted.\n\t */\n\n\t/**\n\t * Fired when an {@link module:engine/view/element~Element} is converted.\n\t *\n\t * `element` is a namespace event for a class of events. Names of actually called events follow the pattern of\n\t * `element:` where `elementName` is the name of the converted element. This way listeners may listen to\n\t * a conversion of all or just specific elements.\n\t *\n\t * @event element\n\t * @param {module:engine/conversion/upcastdispatcher~UpcastConversionData} data The conversion data. Keep in mind that this object is\n\t * shared by reference between all callbacks that will be called. This means that callbacks can override values if needed, and these\n\t * values will be available in other callbacks.\n\t * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion utilities to be used by the\n\t * callback.\n\t */\n\n\t/**\n\t * Fired when a {@link module:engine/view/text~Text} is converted.\n\t *\n\t * @event text\n\t * @see #event:element\n\t */\n\n\t/**\n\t * Fired when a {@link module:engine/view/documentfragment~DocumentFragment} is converted.\n\t *\n\t * @event documentFragment\n\t * @see #event:element\n\t */\n}\n\nmix( UpcastDispatcher, EmitterMixin );\n\n// Traverses given model item and searches elements which marks marker range. Found element is removed from\n// DocumentFragment but path of this element is stored in a Map which is then returned.\n//\n// @param {module:engine/view/documentfragment~DocumentFragment|module:engine/view/node~Node} modelItem Fragment of model.\n// @returns {Map} List of static markers.\nfunction extractMarkersFromModelFragment( modelItem, writer ) {\n\tconst markerElements = new Set();\n\tconst markers = new Map();\n\n\t// Create ModelTreeWalker.\n\tconst range = ModelRange._createIn( modelItem ).getItems();\n\n\t// Walk through DocumentFragment and collect marker elements.\n\tfor ( const item of range ) {\n\t\t// Check if current element is a marker.\n\t\tif ( item.name == '$marker' ) {\n\t\t\tmarkerElements.add( item );\n\t\t}\n\t}\n\n\t// Walk through collected marker elements store its path and remove its from the DocumentFragment.\n\tfor ( const markerElement of markerElements ) {\n\t\tconst markerName = markerElement.getAttribute( 'data-name' );\n\t\tconst currentPosition = writer.createPositionBefore( markerElement );\n\n\t\t// When marker of given name is not stored it means that we have found the beginning of the range.\n\t\tif ( !markers.has( markerName ) ) {\n\t\t\tmarkers.set( markerName, new ModelRange( currentPosition.clone() ) );\n\t\t// Otherwise is means that we have found end of the marker range.\n\t\t} else {\n\t\t\tmarkers.get( markerName ).end = currentPosition.clone();\n\t\t}\n\n\t\t// Remove marker element from DocumentFragment.\n\t\twriter.remove( markerElement );\n\t}\n\n\treturn markers;\n}\n\n// Creates model fragment according to given context and returns position in the bottom (the deepest) element.\nfunction createContextTree( contextDefinition, writer ) {\n\tlet position;\n\n\tfor ( const item of new SchemaContext( contextDefinition ) ) {\n\t\tconst attributes = {};\n\n\t\tfor ( const key of item.getAttributeKeys() ) {\n\t\t\tattributes[ key ] = item.getAttribute( key );\n\t\t}\n\n\t\tconst current = writer.createElement( item.name, attributes );\n\n\t\tif ( position ) {\n\t\t\twriter.append( current, position );\n\t\t}\n\n\t\tposition = ModelPosition._createAt( current, 0 );\n\t}\n\n\treturn position;\n}\n\n/**\n * A set of conversion utilities available as the third parameter of the\n * {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher upcast dispatcher}'s events.\n *\n * @interface module:engine/conversion/upcastdispatcher~UpcastConversionApi\n */\n\n/**\n * Starts the conversion of a given item by firing an appropriate event.\n *\n * Every fired event is passed (as the first parameter) an object with the `modelRange` property. Every event may set and/or\n * modify that property. When all callbacks are done, the final value of the `modelRange` property is returned by this method.\n * The `modelRange` must be a {@link module:engine/model/range~Range model range} or `null` (as set by default).\n *\n * @method #convertItem\n * @fires module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element\n * @fires module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:text\n * @fires module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:documentFragment\n * @param {module:engine/view/item~Item} viewItem Item to convert.\n * @param {module:engine/model/position~Position} modelCursor The conversion position.\n * @returns {Object} result The conversion result.\n * @returns {module:engine/model/range~Range|null} result.modelRange The model range containing the result of the item conversion,\n * created and modified by callbacks attached to the fired event, or `null` if the conversion result was incorrect.\n * @returns {module:engine/model/position~Position} result.modelCursor The position where the conversion should be continued.\n */\n\n/**\n * Starts the conversion of all children of a given item by firing appropriate events for all the children.\n *\n * @method #convertChildren\n * @fires module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element\n * @fires module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:text\n * @fires module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:documentFragment\n * @param {module:engine/view/item~Item} viewItem An element whose children should be converted.\n * @param {module:engine/model/position~Position|module:engine/model/element~Element} positionOrElement A position or an element of\n * the conversion.\n * @returns {Object} result The conversion result.\n * @returns {module:engine/model/range~Range} result.modelRange The model range containing the results of the conversion of all children\n * of the given item. When no child was converted, the range is collapsed.\n * @returns {module:engine/model/position~Position} result.modelCursor The position where the conversion should be continued.\n */\n\n/**\n * Safely inserts an element to the document, checking the {@link module:engine/model/schema~Schema schema} to find an allowed parent for\n * an element that you are going to insert, starting from the given position. If the current parent does not allow to insert the element\n * but one of the ancestors does, then splits the nodes to allowed parent.\n *\n * If the schema allows to insert the node in a given position, nothing is split.\n *\n * If it was not possible to find an allowed parent, `false` is returned and nothing is split.\n *\n * Otherwise, ancestors are split.\n *\n * For instance, if `` is not allowed in `` but is allowed in `$root`:\n *\n *\t\tfoo[]bar\n *\n *\t\t-> safe insert for `` will split ->\n *\n *\t\tfoo[]bar\n *\n * Example usage:\n *\n *\t\tconst myElement = conversionApi.writer.createElement( 'myElement' );\n *\n *\t\tif ( !conversionApi.safeInsert( myElement, data.modelCursor ) ) {\n *\t\t\treturn;\n *\t\t}\n *\n * The split result is saved and {@link #updateConversionResult} should be used to update the\n * {@link module:engine/conversion/upcastdispatcher~UpcastConversionData conversion data}.\n *\n * @method #safeInsert\n * @param {module:engine/model/node~Node} node The node to insert.\n * @param {module:engine/model/position~Position} position The position where an element is going to be inserted.\n * @returns {Boolean} The split result. If it was not possible to find an allowed position, `false` is returned.\n */\n\n/**\n * Updates the conversion result and sets a proper {@link module:engine/conversion/upcastdispatcher~UpcastConversionData#modelRange} and\n * the next {@link module:engine/conversion/upcastdispatcher~UpcastConversionData#modelCursor} after the conversion.\n * Used together with {@link #safeInsert}, it enables you to easily convert elements without worrying if the node was split\n * during the conversion of its children.\n *\n * A usage example in converter code:\n *\n *\t\tconst myElement = conversionApi.writer.createElement( 'myElement' );\n *\n *\t\tif ( !conversionApi.safeInsert( myElement, data.modelCursor ) ) {\n *\t\t\treturn;\n *\t\t}\n *\n *\t\t// Children conversion may split `myElement`.\n *\t\tconversionApi.convertChildren( data.viewItem, myElement );\n *\n *\t\tconversionApi.updateConversionResult( myElement, data );\n *\n * @method #updateConversionResult\n * @param {module:engine/model/element~Element} element\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionData} data Conversion data.\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion utilities to be used by the callback.\n */\n\n/**\n * Checks the {@link module:engine/model/schema~Schema schema} to find an allowed parent for an element that is going to be inserted\n * starting from the given position. If the current parent does not allow inserting an element but one of the ancestors does, the method\n * splits nodes to allowed parent.\n *\n * If the schema allows inserting the node in the given position, nothing is split and an object with that position is returned.\n *\n * If it was not possible to find an allowed parent, `null` is returned and nothing is split.\n *\n * Otherwise, ancestors are split and an object with a position and the copy of the split element is returned.\n *\n * For instance, if `` is not allowed in `` but is allowed in `$root`:\n *\n *\t\tfoo[]bar\n *\n *\t\t-> split for `` ->\n *\n *\t\tfoo[]bar\n *\n * In the example above, the position between `` elements will be returned as `position` and the second `paragraph`\n * as `cursorParent`.\n *\n * **Note:** This is an advanced method. For most cases {@link #safeInsert} and {@link #updateConversionResult} should be used.\n *\n * @method #splitToAllowedParent\n * @param {module:engine/model/position~Position} position The position where the element is going to be inserted.\n * @param {module:engine/model/node~Node} node The node to insert.\n * @returns {Object|null} The split result. If it was not possible to find an allowed position, `null` is returned.\n * @returns {module:engine/model/position~Position} The position between split elements.\n * @returns {module:engine/model/element~Element} [cursorParent] The element inside which the cursor should be placed to\n * continue the conversion. When the element is not defined it means that there was no split.\n */\n\n/**\n * Returns all the split parts of the given `element` that were created during upcasting through using {@link #splitToAllowedParent}.\n * It enables you to easily track these elements and continue processing them after they are split during the conversion of their children.\n *\n *\t\tFoobarbaz ->\n *\t\tFoobarbaz\n *\n * For a reference to any of above paragraphs, the function will return all three paragraphs (the original element included),\n * sorted in the order of their creation (the original element is the first one).\n *\n * If the given `element` was not split, an array with a single element is returned.\n *\n * A usage example in the converter code:\n *\n *\t\tconst myElement = conversionApi.writer.createElement( 'myElement' );\n *\n *\t\t// Children conversion may split `myElement`.\n *\t\tconversionApi.convertChildren( data.viewItem, data.modelCursor );\n *\n *\t\tconst splitParts = conversionApi.getSplitParts( myElement );\n *\t\tconst lastSplitPart = splitParts[ splitParts.length - 1 ];\n *\n *\t\t// Setting `data.modelRange` basing on split parts:\n *\t\tdata.modelRange = conversionApi.writer.createRange(\n *\t\t\tconversionApi.writer.createPositionBefore( myElement ),\n *\t\t\tconversionApi.writer.createPositionAfter( lastSplitPart )\n *\t\t);\n *\n *\t\t// Setting `data.modelCursor` to continue after the last split element:\n *\t\tdata.modelCursor = conversionApi.writer.createPositionAfter( lastSplitPart );\n *\n * **Tip:** If you are unable to get a reference to the original element (for example because the code is split into multiple converters\n * or even classes) but it has already been converted, you may want to check the first element in `data.modelRange`. This is a common\n * situation if an attribute converter is separated from an element converter.\n *\n * **Note:** This is an advanced method. For most cases {@link #safeInsert} and {@link #updateConversionResult} should be used.\n *\n * @method #getSplitParts\n * @param {module:engine/model/element~Element} element\n * @returns {Array.}\n */\n\n/**\n * Stores information about what parts of the processed view item are still waiting to be handled. After a piece of view item\n * was converted, an appropriate consumable value should be\n * {@link module:engine/conversion/viewconsumable~ViewConsumable#consume consumed}.\n *\n * @member {module:engine/conversion/viewconsumable~ViewConsumable} #consumable\n */\n\n/**\n * Custom data stored by converters for the conversion process. Custom properties of this object can be defined and use to\n * pass parameters between converters.\n *\n * The difference between this property and the `data` parameter of\n * {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element} is that the `data` parameters allow you\n * to pass parameters within a single event and `store` within the whole conversion.\n *\n * @member {Object} #store\n */\n\n/**\n * The model's schema instance.\n *\n * @member {module:engine/model/schema~Schema} #schema\n */\n\n/**\n * The {@link module:engine/model/writer~Writer} instance used to manipulate the data during conversion.\n *\n * @member {module:engine/model/writer~Writer} #writer\n */\n\n/**\n * Conversion data.\n *\n * **Note:** Keep in mind that this object is shared by reference between all conversion callbacks that will be called.\n * This means that callbacks can override values if needed, and these values will be available in other callbacks.\n *\n * @typedef {Object} module:engine/conversion/upcastdispatcher~UpcastConversionData\n *\n * @property {module:engine/view/item~Item} viewItem The converted item.\n * @property {module:engine/model/position~Position} modelCursor The position where the converter should start changes.\n * Change this value for the next converter to tell where the conversion should continue.\n * @property {module:engine/model/range~Range} [modelRange] The current state of conversion result. Every change to\n * the converted element should be reflected by setting or modifying this property.\n */\n"],"sourceRoot":""}