{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/model/batch.js","webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/model/document.js","webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/index.js","webpack:///./node_modules/@ckeditor/ckeditor5-engine/src/model/documentfragment.js"],"names":["Batch","type","arguments","length","undefined","Object","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_classCallCheck_js__WEBPACK_IMPORTED_MODULE_6__","this","operations","_step","_iterator","_createForOfIteratorHelper","s","n","done","op","value","baseVersion","err","e","f","operation","batch","push","graveyardName","Document","model","_this","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_classCallCheck_js__WEBPACK_IMPORTED_MODULE_8__","version","history","History","selection","DocumentSelection","roots","Collection","idProperty","differ","Differ","markers","_postFixers","Set","_hasSelectionChangedFromTheLastChangeBlock","createRoot","listenTo","evt","args","isDocumentOperation","CKEditorError","priority","bufferOperation","addOperation","marker","oldRange","newRange","bufferMarkerChange","name","affectsData","on","getRange","getRoot","elementName","rootName","get","root","RootElement","add","destroy","stopListening","Array","from","filter","postFixer","json","clone","writer","_hasDocumentChangedFromTheLastChangeBlock","_callPostFixers","refresh","hasDataChanges","fire","reset","isEmpty","graveyard","defaultRoot","_getDefaultRoot","schema","position","createPositionFromPath","nearestRange","getNearestSelectionRange","createRange","range","validateTextNodePosition","start","end","wasFixed","_step2","_iterator2","callback","rangeBoundary","textNode","data","offset","startOffset","isInsideSurrogatePair","isInsideCombinedSymbol","mix","EmitterMixin","_view_placeholder__WEBPACK_IMPORTED_MODULE_0__","__webpack_require__","d","__webpack_exports__","_model_treewalker__WEBPACK_IMPORTED_MODULE_14__","_view_containerelement__WEBPACK_IMPORTED_MODULE_19__","_view_observer_observer__WEBPACK_IMPORTED_MODULE_20__","_view_observer_clickobserver__WEBPACK_IMPORTED_MODULE_21__","_view_observer_domeventobserver__WEBPACK_IMPORTED_MODULE_22__","_view_observer_mouseobserver__WEBPACK_IMPORTED_MODULE_23__","_view_upcastwriter__WEBPACK_IMPORTED_MODULE_25__","_view_styles_utils__WEBPACK_IMPORTED_MODULE_33__","DocumentFragment","children","Map","_children","NodeList","_insertChild","getChildren","maxOffset","childCount","index","getNode","Symbol","iterator","node","getNodeIndex","getNodeStartOffset","relativePath","getChild","offsetToIndex","toJSON","items","_step3","nodes","normalize","_iterator3","parent","_remove","_insertNodes","_step4","howMany","_removeNodes","_iterator4","_step5","_iterator5","child","Element","fromJSON","Text","isIterable","map","TextProxy","getAttributes"],"mappings":"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","file":"js/chunk-1ccebfc7.e4689b53.js","sourcesContent":["/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module engine/model/batch\n */\n\n/**\n * A batch instance groups model changes ({@link module:engine/model/operation/operation~Operation operations}). All operations\n * grouped in a single batch can be reverted together, so you can also think about a batch as of a single undo step. If you want\n * to extend a given undo step, you can add more changes to the batch using {@link module:engine/model/model~Model#enqueueChange}:\n *\n *\t\tmodel.enqueueChange( batch, writer => {\n *\t\t\twriter.insertText( 'foo', paragraph, 'end' );\n *\t\t} );\n *\n * @see module:engine/model/model~Model#enqueueChange\n * @see module:engine/model/model~Model#change\n */\nexport default class Batch {\n\t/**\n\t * Creates a batch instance.\n\t *\n\t * @see module:engine/model/model~Model#enqueueChange\n\t * @see module:engine/model/model~Model#change\n\t * @param {'transparent'|'default'} [type='default'] The type of the batch.\n\t */\n\tconstructor( type = 'default' ) {\n\t\t/**\n\t\t * An array of operations that compose this batch.\n\t\t *\n\t\t * @readonly\n\t\t * @type {Array.}\n\t\t */\n\t\tthis.operations = [];\n\n\t\t/**\n\t\t * The type of the batch.\n\t\t *\n\t\t * It can be one of the following values:\n\t\t * * `'default'` – All \"normal\" batches. This is the most commonly used type.\n\t\t * * `'transparent'` – A batch that should be ignored by other features, i.e. an initial batch or collaborative editing\n\t\t * changes.\n\t\t *\n\t\t * @readonly\n\t\t * @type {'transparent'|'default'}\n\t\t */\n\t\tthis.type = type;\n\t}\n\n\t/**\n\t * Returns the base version of this batch, which is equal to the base version of the first operation in the batch.\n\t * If there are no operations in the batch or neither operation has the base version set, it returns `null`.\n\t *\n\t * @readonly\n\t * @type {Number|null}\n\t */\n\tget baseVersion() {\n\t\tfor ( const op of this.operations ) {\n\t\t\tif ( op.baseVersion !== null ) {\n\t\t\t\treturn op.baseVersion;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Adds an operation to the batch instance.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} operation An operation to add.\n\t * @returns {module:engine/model/operation/operation~Operation} The added operation.\n\t */\n\taddOperation( operation ) {\n\t\toperation.batch = this;\n\t\tthis.operations.push( operation );\n\n\t\treturn operation;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module engine/model/document\n */\n\nimport Differ from './differ';\nimport RootElement from './rootelement';\nimport History from './history';\nimport DocumentSelection from './documentselection';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport { isInsideSurrogatePair, isInsideCombinedSymbol } from '@ckeditor/ckeditor5-utils/src/unicode';\nimport { clone } from 'lodash-es';\n\n// @if CK_DEBUG_ENGINE // const { logDocument } = require( '../dev-utils/utils' );\n\nconst graveyardName = '$graveyard';\n\n/**\n * Data model's document. It contains the model's structure, its selection and the history of changes.\n *\n * Read more about working with the model in\n * {@glink framework/guides/architecture/editing-engine#model introduction to the the editing engine's architecture}.\n *\n * Usually, the document contains just one {@link module:engine/model/document~Document#roots root element}, so\n * you can retrieve it by just calling {@link module:engine/model/document~Document#getRoot} without specifying its name:\n *\n *\t\tmodel.document.getRoot(); // -> returns the main root\n *\n * However, the document may contain multiple roots – e.g. when the editor has multiple editable areas\n * (e.g. a title and a body of a message).\n *\n * @mixes module:utils/emittermixin~EmitterMixin\n */\nexport default class Document {\n\t/**\n\t * Creates an empty document instance with no {@link #roots} (other than\n\t * the {@link #graveyard graveyard root}).\n\t */\n\tconstructor( model ) {\n\t\t/**\n\t\t * The {@link module:engine/model/model~Model model} that the document is a part of.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/model~Model}\n\t\t */\n\t\tthis.model = model;\n\n\t\t/**\n\t\t * The document version. It starts from `0` and every operation increases the version number. It is used to ensure that\n\t\t * operations are applied on a proper document version.\n\t\t *\n\t\t * If the {@link module:engine/model/operation/operation~Operation#baseVersion base version} does not match the document version,\n\t\t * a {@link module:utils/ckeditorerror~CKEditorError model-document-applyoperation-wrong-version} error is thrown.\n\t\t *\n\t\t * @type {Number}\n\t\t */\n\t\tthis.version = 0;\n\n\t\t/**\n\t\t * The document's history.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/history~History}\n\t\t */\n\t\tthis.history = new History( this );\n\n\t\t/**\n\t\t * The selection in this document.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/documentselection~DocumentSelection}\n\t\t */\n\t\tthis.selection = new DocumentSelection( this );\n\n\t\t/**\n\t\t * A list of roots that are owned and managed by this document. Use {@link #createRoot} and\n\t\t * {@link #getRoot} to manipulate it.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:utils/collection~Collection}\n\t\t */\n\t\tthis.roots = new Collection( { idProperty: 'rootName' } );\n\n\t\t/**\n\t\t * The model differ object. Its role is to buffer changes done on the model document and then calculate a diff of those changes.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/differ~Differ}\n\t\t */\n\t\tthis.differ = new Differ( model.markers );\n\n\t\t/**\n\t\t * Post-fixer callbacks registered to the model document.\n\t\t *\n\t\t * @private\n\t\t * @type {Set.}\n\t\t */\n\t\tthis._postFixers = new Set();\n\n\t\t/**\n\t\t * A boolean indicates whether the selection has changed until\n\t\t *\n\t\t * @private\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis._hasSelectionChangedFromTheLastChangeBlock = false;\n\n\t\t// Graveyard tree root. Document always have a graveyard root, which stores removed nodes.\n\t\tthis.createRoot( '$root', graveyardName );\n\n\t\t// First, if the operation is a document operation check if it's base version is correct.\n\t\tthis.listenTo( model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( operation.isDocumentOperation && operation.baseVersion !== this.version ) {\n\t\t\t\t/**\n\t\t\t\t * Only operations with matching versions can be applied.\n\t\t\t\t *\n\t\t\t\t * @error model-document-applyoperation-wrong-version\n\t\t\t\t * @param {module:engine/model/operation/operation~Operation} operation\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError( 'model-document-applyoperation-wrong-version', this, { operation } );\n\t\t\t}\n\t\t}, { priority: 'highest' } );\n\n\t\t// Then, still before an operation is applied on model, buffer the change in differ.\n\t\tthis.listenTo( model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( operation.isDocumentOperation ) {\n\t\t\t\tthis.differ.bufferOperation( operation );\n\t\t\t}\n\t\t}, { priority: 'high' } );\n\n\t\t// After the operation is applied, bump document's version and add the operation to the history.\n\t\tthis.listenTo( model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( operation.isDocumentOperation ) {\n\t\t\t\tthis.version++;\n\t\t\t\tthis.history.addOperation( operation );\n\t\t\t}\n\t\t}, { priority: 'low' } );\n\n\t\t// Listen to selection changes. If selection changed, mark it.\n\t\tthis.listenTo( this.selection, 'change', () => {\n\t\t\tthis._hasSelectionChangedFromTheLastChangeBlock = true;\n\t\t} );\n\n\t\t// Buffer marker changes.\n\t\t// This is not covered in buffering operations because markers may change outside of them (when they\n\t\t// are modified using `model.markers` collection, not through `MarkerOperation`).\n\t\tthis.listenTo( model.markers, 'update', ( evt, marker, oldRange, newRange ) => {\n\t\t\t// Whenever marker is updated, buffer that change.\n\t\t\tthis.differ.bufferMarkerChange( marker.name, oldRange, newRange, marker.affectsData );\n\n\t\t\tif ( oldRange === null ) {\n\t\t\t\t// If this is a new marker, add a listener that will buffer change whenever marker changes.\n\t\t\t\tmarker.on( 'change', ( evt, oldRange ) => {\n\t\t\t\t\tthis.differ.bufferMarkerChange( marker.name, oldRange, marker.getRange(), marker.affectsData );\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * The graveyard tree root. A document always has a graveyard root that stores removed nodes.\n\t *\n\t * @readonly\n\t * @member {module:engine/model/rootelement~RootElement}\n\t */\n\tget graveyard() {\n\t\treturn this.getRoot( graveyardName );\n\t}\n\n\t/**\n\t * Creates a new root.\n\t *\n\t * @param {String} [elementName='$root'] The element name. Defaults to `'$root'` which also has some basic schema defined\n\t * (`$block`s are allowed inside the `$root`). Make sure to define a proper schema if you use a different name.\n\t * @param {String} [rootName='main'] A unique root name.\n\t * @returns {module:engine/model/rootelement~RootElement} The created root.\n\t */\n\tcreateRoot( elementName = '$root', rootName = 'main' ) {\n\t\tif ( this.roots.get( rootName ) ) {\n\t\t\t/**\n\t\t\t * A root with the specified name already exists.\n\t\t\t *\n\t\t\t * @error model-document-createroot-name-exists\n\t\t\t * @param {module:engine/model/document~Document} doc\n\t\t\t * @param {String} name\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'model-document-createroot-name-exists', this, { name: rootName } );\n\t\t}\n\n\t\tconst root = new RootElement( this, elementName, rootName );\n\t\tthis.roots.add( root );\n\n\t\treturn root;\n\t}\n\n\t/**\n\t * Removes all event listeners set by the document instance.\n\t */\n\tdestroy() {\n\t\tthis.selection.destroy();\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Returns a root by its name.\n\t *\n\t * @param {String} [name='main'] A unique root name.\n\t * @returns {module:engine/model/rootelement~RootElement|null} The root registered under a given name or `null` when\n\t * there is no root with the given name.\n\t */\n\tgetRoot( name = 'main' ) {\n\t\treturn this.roots.get( name );\n\t}\n\n\t/**\n\t * Returns an array with names of all roots (without the {@link #graveyard}) added to the document.\n\t *\n\t * @returns {Array.} Roots names.\n\t */\n\tgetRootNames() {\n\t\treturn Array.from( this.roots, root => root.rootName ).filter( name => name != graveyardName );\n\t}\n\n\t/**\n\t * Used to register a post-fixer callback. A post-fixer mechanism guarantees that the features\n\t * will operate on a correct model state.\n\t *\n\t * An execution of a feature may lead to an incorrect document tree state. The callbacks are used to fix the document tree after\n\t * it has changed. Post-fixers are fired just after all changes from the outermost change block were applied but\n\t * before the {@link module:engine/model/document~Document#event:change change event} is fired. If a post-fixer callback made\n\t * a change, it should return `true`. When this happens, all post-fixers are fired again to check if something else should\n\t * not be fixed in the new document tree state.\n\t *\n\t * As a parameter, a post-fixer callback receives a {@link module:engine/model/writer~Writer writer} instance connected with the\n\t * executed changes block. Thanks to that, all changes done by the callback will be added to the same\n\t * {@link module:engine/model/batch~Batch batch} (and undo step) as the original changes. This makes post-fixer changes transparent\n\t * for the user.\n\t *\n\t * An example of a post-fixer is a callback that checks if all the data were removed from the editor. If so, the\n\t * callback should add an empty paragraph so that the editor is never empty:\n\t *\n\t *\t\tdocument.registerPostFixer( writer => {\n\t *\t\t\tconst changes = document.differ.getChanges();\n\t *\n\t *\t\t\t// Check if the changes lead to an empty root in the editor.\n\t *\t\t\tfor ( const entry of changes ) {\n\t *\t\t\t\tif ( entry.type == 'remove' && entry.position.root.isEmpty ) {\n\t *\t\t\t\t\twriter.insertElement( 'paragraph', entry.position.root, 0 );\n\t *\n\t *\t\t\t\t\t// It is fine to return early, even if multiple roots would need to be fixed.\n\t *\t\t\t\t\t// All post-fixers will be fired again, so if there are more empty roots, those will be fixed, too.\n\t *\t\t\t\t\treturn true;\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * @param {Function} postFixer\n\t */\n\tregisterPostFixer( postFixer ) {\n\t\tthis._postFixers.add( postFixer );\n\t}\n\n\t/**\n\t * A custom `toJSON()` method to solve child-parent circular dependencies.\n\t *\n\t * @returns {Object} A clone of this object with the document property changed to a string.\n\t */\n\ttoJSON() {\n\t\tconst json = clone( this );\n\n\t\t// Due to circular references we need to remove parent reference.\n\t\tjson.selection = '[engine.model.DocumentSelection]';\n\t\tjson.model = '[engine.model.Model]';\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * Check if there were any changes done on document, and if so, call post-fixers,\n\t * fire `change` event for features and conversion and then reset the differ.\n\t * Fire `change:data` event when at least one operation or buffered marker changes the data.\n\t *\n\t * @protected\n\t * @fires change\n\t * @fires change:data\n\t * @param {module:engine/model/writer~Writer} writer The writer on which post-fixers will be called.\n\t */\n\t_handleChangeBlock( writer ) {\n\t\tif ( this._hasDocumentChangedFromTheLastChangeBlock() ) {\n\t\t\tthis._callPostFixers( writer );\n\n\t\t\t// Refresh selection attributes according to the final position in the model after the change.\n\t\t\tthis.selection.refresh();\n\n\t\t\tif ( this.differ.hasDataChanges() ) {\n\t\t\t\tthis.fire( 'change:data', writer.batch );\n\t\t\t} else {\n\t\t\t\tthis.fire( 'change', writer.batch );\n\t\t\t}\n\n\t\t\t// Theoretically, it is not necessary to refresh selection after change event because\n\t\t\t// post-fixers are the last who should change the model, but just in case...\n\t\t\tthis.selection.refresh();\n\n\t\t\tthis.differ.reset();\n\t\t}\n\n\t\tthis._hasSelectionChangedFromTheLastChangeBlock = false;\n\t}\n\n\t/**\n\t * Returns whether there is a buffered change or if the selection has changed from the last\n\t * {@link module:engine/model/model~Model#enqueueChange `enqueueChange()` block}\n\t * or {@link module:engine/model/model~Model#change `change()` block}.\n\t *\n\t * @protected\n\t * @returns {Boolean} Returns `true` if document has changed from the last `change()` or `enqueueChange()` block.\n\t */\n\t_hasDocumentChangedFromTheLastChangeBlock() {\n\t\treturn !this.differ.isEmpty || this._hasSelectionChangedFromTheLastChangeBlock;\n\t}\n\n\t/**\n\t * Returns the default root for this document which is either the first root that was added to the document using\n\t * {@link #createRoot} or the {@link #graveyard graveyard root} if no other roots were created.\n\t *\n\t * @protected\n\t * @returns {module:engine/model/rootelement~RootElement} The default root for this document.\n\t */\n\t_getDefaultRoot() {\n\t\tfor ( const root of this.roots ) {\n\t\t\tif ( root !== this.graveyard ) {\n\t\t\t\treturn root;\n\t\t\t}\n\t\t}\n\n\t\treturn this.graveyard;\n\t}\n\n\t/**\n\t * Returns the default range for this selection. The default range is a collapsed range that starts and ends\n\t * at the beginning of this selection's document {@link #_getDefaultRoot default root}.\n\t *\n\t * @protected\n\t * @returns {module:engine/model/range~Range}\n\t */\n\t_getDefaultRange() {\n\t\tconst defaultRoot = this._getDefaultRoot();\n\t\tconst model = this.model;\n\t\tconst schema = model.schema;\n\n\t\t// Find the first position where the selection can be put.\n\t\tconst position = model.createPositionFromPath( defaultRoot, [ 0 ] );\n\t\tconst nearestRange = schema.getNearestSelectionRange( position );\n\n\t\t// If valid selection range is not found - return range collapsed at the beginning of the root.\n\t\treturn nearestRange || model.createRange( position );\n\t}\n\n\t/**\n\t * Checks whether a given {@link module:engine/model/range~Range range} is a valid range for\n\t * the {@link #selection document's selection}.\n\t *\n\t * @private\n\t * @param {module:engine/model/range~Range} range A range to check.\n\t * @returns {Boolean} `true` if `range` is valid, `false` otherwise.\n\t */\n\t_validateSelectionRange( range ) {\n\t\treturn validateTextNodePosition( range.start ) && validateTextNodePosition( range.end );\n\t}\n\n\t/**\n\t * Performs post-fixer loops. Executes post-fixer callbacks as long as none of them has done any changes to the model.\n\t *\n\t * @private\n\t * @param {module:engine/model/writer~Writer} writer The writer on which post-fixer callbacks will be called.\n\t */\n\t_callPostFixers( writer ) {\n\t\tlet wasFixed = false;\n\n\t\tdo {\n\t\t\tfor ( const callback of this._postFixers ) {\n\t\t\t\t// Ensure selection attributes are up to date before each post-fixer.\n\t\t\t\t// https://github.com/ckeditor/ckeditor5-engine/issues/1673.\n\t\t\t\t//\n\t\t\t\t// It might be good to refresh the selection after each operation but at the moment it leads\n\t\t\t\t// to losing attributes for composition or and spell checking\n\t\t\t\t// https://github.com/ckeditor/ckeditor5-typing/issues/188\n\t\t\t\tthis.selection.refresh();\n\n\t\t\t\twasFixed = callback( writer );\n\n\t\t\t\tif ( wasFixed ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} while ( wasFixed );\n\t}\n\n\t/**\n\t * Fired after each {@link module:engine/model/model~Model#enqueueChange `enqueueChange()` block} or the outermost\n\t * {@link module:engine/model/model~Model#change `change()` block} was executed and the document was changed\n\t * during that block's execution.\n\t *\n\t * The changes which this event will cover include:\n\t *\n\t * * document structure changes,\n\t * * selection changes,\n\t * * marker changes.\n\t *\n\t * If you want to be notified about all these changes, then simply listen to this event like this:\n\t *\n\t *\t\tmodel.document.on( 'change', () => {\n\t *\t\t\tconsole.log( 'The document has changed!' );\n\t *\t\t} );\n\t *\n\t * If, however, you only want to be notified about the data changes, then use the\n\t * {@link module:engine/model/document~Document#event:change:data change:data} event,\n\t * which is fired for document structure changes and marker changes (which affects the data).\n\t *\n\t *\t\tmodel.document.on( 'change:data', () => {\n\t *\t\t\tconsole.log( 'The data has changed!' );\n\t *\t\t} );\n\t *\n\t * @event change\n\t * @param {module:engine/model/batch~Batch} batch The batch that was used in the executed changes block.\n\t */\n\n\t/**\n\t * It is a narrower version of the {@link #event:change} event. It is fired for changes which\n\t * affect the editor data. This is:\n\t *\n\t * * document structure changes,\n\t * * marker changes (which affects the data).\n\t *\n\t * If you want to be notified about the data changes, then listen to this event:\n\t *\n\t *\t\tmodel.document.on( 'change:data', () => {\n\t *\t\t\tconsole.log( 'The data has changed!' );\n\t *\t\t} );\n\t *\n\t * If you would like to listen to all document changes, then check out the\n\t * {@link module:engine/model/document~Document#event:change change} event.\n\t *\n\t * @event change:data\n\t * @param {module:engine/model/batch~Batch} batch The batch that was used in the executed changes block.\n\t */\n\n\t// @if CK_DEBUG_ENGINE // log( version = null ) {\n\t// @if CK_DEBUG_ENGINE // \tversion = version === null ? this.version : version;\n\t// @if CK_DEBUG_ENGINE // \tlogDocument( this, version );\n\t// @if CK_DEBUG_ENGINE // }\n}\n\nmix( Document, EmitterMixin );\n\n// Checks whether given range boundary position is valid for document selection, meaning that is not between\n// unicode surrogate pairs or base character and combining marks.\nfunction validateTextNodePosition( rangeBoundary ) {\n\tconst textNode = rangeBoundary.textNode;\n\n\tif ( textNode ) {\n\t\tconst data = textNode.data;\n\t\tconst offset = rangeBoundary.offset - textNode.startOffset;\n\n\t\treturn !isInsideSurrogatePair( data, offset ) && !isInsideCombinedSymbol( data, offset );\n\t}\n\n\treturn true;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module engine\n */\n\nexport * from './view/placeholder';\n\nexport { default as EditingController } from './controller/editingcontroller';\nexport { default as DataController } from './controller/datacontroller';\n\nexport { default as Conversion } from './conversion/conversion';\n\nexport { default as HtmlDataProcessor } from './dataprocessor/htmldataprocessor';\n\nexport { default as InsertOperation } from './model/operation/insertoperation';\nexport { default as MarkerOperation } from './model/operation/markeroperation';\nexport { default as OperationFactory } from './model/operation/operationfactory';\nexport { transformSets } from './model/operation/transform';\n\nexport { default as DocumentSelection } from './model/documentselection';\nexport { default as Range } from './model/range';\nexport { default as LiveRange } from './model/liverange';\nexport { default as LivePosition } from './model/liveposition';\nexport { default as Model } from './model/model';\nexport { default as TreeWalker } from './model/treewalker';\nexport { default as Element } from './model/element';\n\nexport { default as DomConverter } from './view/domconverter';\nexport { default as Renderer } from './view/renderer';\nexport { default as ViewDocument } from './view/document';\n\nexport { getFillerOffset } from './view/containerelement';\nexport { default as Observer } from './view/observer/observer';\nexport { default as ClickObserver } from './view/observer/clickobserver';\nexport { default as DomEventObserver } from './view/observer/domeventobserver';\nexport { default as MouseObserver } from './view/observer/mouseobserver';\nexport { default as DowncastWriter } from './view/downcastwriter';\nexport { default as UpcastWriter } from './view/upcastwriter';\nexport { default as Matcher } from './view/matcher';\n\nexport { default as DomEventData } from './view/observer/domeventdata';\n\nexport { StylesProcessor } from './view/stylesmap';\nexport * from './view/styles/background';\nexport * from './view/styles/border';\nexport * from './view/styles/margin';\nexport * from './view/styles/padding';\nexport * from './view/styles/utils';\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module module:engine/model/documentfragment\n */\n\nimport NodeList from './nodelist';\nimport Element from './element';\nimport Text from './text';\nimport TextProxy from './textproxy';\nimport isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';\n\n// @if CK_DEBUG_ENGINE // const { stringifyMap } = require( '../dev-utils/utils' );\n\n/**\n * DocumentFragment represents a part of model which does not have a common root but its top-level nodes\n * can be seen as siblings. In other words, it is a detached part of model tree, without a root.\n *\n * DocumentFragment has own {@link module:engine/model/markercollection~MarkerCollection}. Markers from this collection\n * will be set to the {@link module:engine/model/model~Model#markers model markers} by a\n * {@link module:engine/model/writer~Writer#insert} function.\n */\nexport default class DocumentFragment {\n\t/**\n\t * Creates an empty `DocumentFragment`.\n\t *\n\t * **Note:** Constructor of this class shouldn't be used directly in the code.\n\t * Use the {@link module:engine/model/writer~Writer#createDocumentFragment} method instead.\n\t *\n\t * @protected\n\t * @param {module:engine/model/node~Node|Iterable.} [children]\n\t * Nodes to be contained inside the `DocumentFragment`.\n\t */\n\tconstructor( children ) {\n\t\t/**\n\t\t * DocumentFragment static markers map. This is a list of names and {@link module:engine/model/range~Range ranges}\n\t\t * which will be set as Markers to {@link module:engine/model/model~Model#markers model markers collection}\n\t\t * when DocumentFragment will be inserted to the document.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Map} module:engine/model/documentfragment~DocumentFragment#markers\n\t\t */\n\t\tthis.markers = new Map();\n\n\t\t/**\n\t\t * List of nodes contained inside the document fragment.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/nodelist~NodeList} module:engine/model/documentfragment~DocumentFragment#_children\n\t\t */\n\t\tthis._children = new NodeList();\n\n\t\tif ( children ) {\n\t\t\tthis._insertChild( 0, children );\n\t\t}\n\t}\n\n\t/**\n\t * Returns an iterator that iterates over all nodes contained inside this document fragment.\n\t *\n\t * @returns {Iterable.}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this.getChildren();\n\t}\n\n\t/**\n\t * Number of this document fragment's children.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget childCount() {\n\t\treturn this._children.length;\n\t}\n\n\t/**\n\t * Sum of {@link module:engine/model/node~Node#offsetSize offset sizes} of all of this document fragment's children.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget maxOffset() {\n\t\treturn this._children.maxOffset;\n\t}\n\n\t/**\n\t * Is `true` if there are no nodes inside this document fragment, `false` otherwise.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isEmpty() {\n\t\treturn this.childCount === 0;\n\t}\n\n\t/**\n\t * Artificial root of `DocumentFragment`. Returns itself. Added for compatibility reasons.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/documentfragment~DocumentFragment}\n\t */\n\tget root() {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Artificial parent of `DocumentFragment`. Returns `null`. Added for compatibility reasons.\n\t *\n\t * @readonly\n\t * @type {null}\n\t */\n\tget parent() {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t *\t\tdocFrag.is( 'documentFragment' ); // -> true\n\t *\t\tdocFrag.is( 'model:documentFragment' ); // -> true\n\t *\n\t *\t\tdocFrag.is( 'view:documentFragment' ); // -> false\n\t *\t\tdocFrag.is( 'element' ); // -> false\n\t *\t\tdocFrag.is( 'node' ); // -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type === 'documentFragment' || type === 'model:documentFragment';\n\t}\n\n\t/**\n\t * Gets the child at the given index. Returns `null` if incorrect index was passed.\n\t *\n\t * @param {Number} index Index of child.\n\t * @returns {module:engine/model/node~Node|null} Child node.\n\t */\n\tgetChild( index ) {\n\t\treturn this._children.getNode( index );\n\t}\n\n\t/**\n\t * Returns an iterator that iterates over all of this document fragment's children.\n\t *\n\t * @returns {Iterable.}\n\t */\n\tgetChildren() {\n\t\treturn this._children[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Returns an index of the given child node. Returns `null` if given node is not a child of this document fragment.\n\t *\n\t * @param {module:engine/model/node~Node} node Child node to look for.\n\t * @returns {Number|null} Child node's index.\n\t */\n\tgetChildIndex( node ) {\n\t\treturn this._children.getNodeIndex( node );\n\t}\n\n\t/**\n\t * Returns the starting offset of given child. Starting offset is equal to the sum of\n\t * {@link module:engine/model/node~Node#offsetSize offset sizes} of all node's siblings that are before it. Returns `null` if\n\t * given node is not a child of this document fragment.\n\t *\n\t * @param {module:engine/model/node~Node} node Child node to look for.\n\t * @returns {Number|null} Child node's starting offset.\n\t */\n\tgetChildStartOffset( node ) {\n\t\treturn this._children.getNodeStartOffset( node );\n\t}\n\n\t/**\n\t * Returns path to a `DocumentFragment`, which is an empty array. Added for compatibility reasons.\n\t *\n\t * @returns {Array}\n\t */\n\tgetPath() {\n\t\treturn [];\n\t}\n\n\t/**\n\t * Returns a descendant node by its path relative to this element.\n\t *\n\t *\t\t// ac\n\t *\t\tthis.getNodeByPath( [ 0 ] ); // -> \"a\"\n\t *\t\tthis.getNodeByPath( [ 1 ] ); // -> \n\t *\t\tthis.getNodeByPath( [ 1, 0 ] ); // -> \"c\"\n\t *\n\t * @param {Array.} relativePath Path of the node to find, relative to this element.\n\t * @returns {module:engine/model/node~Node|module:engine/model/documentfragment~DocumentFragment}\n\t */\n\tgetNodeByPath( relativePath ) {\n\t\tlet node = this; // eslint-disable-line consistent-this\n\n\t\tfor ( const index of relativePath ) {\n\t\t\tnode = node.getChild( node.offsetToIndex( index ) );\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Converts offset \"position\" to index \"position\".\n\t *\n\t * Returns index of a node that occupies given offset. If given offset is too low, returns `0`. If given offset is\n\t * too high, returns index after last child}.\n\t *\n\t *\t\tconst textNode = new Text( 'foo' );\n\t *\t\tconst pElement = new Element( 'p' );\n\t *\t\tconst docFrag = new DocumentFragment( [ textNode, pElement ] );\n\t *\t\tdocFrag.offsetToIndex( -1 ); // Returns 0, because offset is too low.\n\t *\t\tdocFrag.offsetToIndex( 0 ); // Returns 0, because offset 0 is taken by `textNode` which is at index 0.\n\t *\t\tdocFrag.offsetToIndex( 1 ); // Returns 0, because `textNode` has `offsetSize` equal to 3, so it occupies offset 1 too.\n\t *\t\tdocFrag.offsetToIndex( 2 ); // Returns 0.\n\t *\t\tdocFrag.offsetToIndex( 3 ); // Returns 1.\n\t *\t\tdocFrag.offsetToIndex( 4 ); // Returns 2. There are no nodes at offset 4, so last available index is returned.\n\t *\n\t * @param {Number} offset Offset to look for.\n\t * @returns {Number} Index of a node that occupies given offset.\n\t */\n\toffsetToIndex( offset ) {\n\t\treturn this._children.offsetToIndex( offset );\n\t}\n\n\t/**\n\t * Converts `DocumentFragment` instance to plain object and returns it.\n\t * Takes care of converting all of this document fragment's children.\n\t *\n\t * @returns {Object} `DocumentFragment` instance converted to plain object.\n\t */\n\ttoJSON() {\n\t\tconst json = [];\n\n\t\tfor ( const node of this._children ) {\n\t\t\tjson.push( node.toJSON() );\n\t\t}\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * Creates a `DocumentFragment` instance from given plain object (i.e. parsed JSON string).\n\t * Converts `DocumentFragment` children to proper nodes.\n\t *\n\t * @param {Object} json Plain object to be converted to `DocumentFragment`.\n\t * @returns {module:engine/model/documentfragment~DocumentFragment} `DocumentFragment` instance created using given plain object.\n\t */\n\tstatic fromJSON( json ) {\n\t\tconst children = [];\n\n\t\tfor ( const child of json ) {\n\t\t\tif ( child.name ) {\n\t\t\t\t// If child has name property, it is an Element.\n\t\t\t\tchildren.push( Element.fromJSON( child ) );\n\t\t\t} else {\n\t\t\t\t// Otherwise, it is a Text node.\n\t\t\t\tchildren.push( Text.fromJSON( child ) );\n\t\t\t}\n\t\t}\n\n\t\treturn new DocumentFragment( children );\n\t}\n\n\t/**\n\t * {@link #_insertChild Inserts} one or more nodes at the end of this document fragment.\n\t *\n\t * @protected\n\t * @param {module:engine/model/item~Item|Iterable.} items Items to be inserted.\n\t */\n\t_appendChild( items ) {\n\t\tthis._insertChild( this.childCount, items );\n\t}\n\n\t/**\n\t * Inserts one or more nodes at the given index and sets {@link module:engine/model/node~Node#parent parent} of these nodes\n\t * to this document fragment.\n\t *\n\t * @protected\n\t * @param {Number} index Index at which nodes should be inserted.\n\t * @param {module:engine/model/item~Item|Iterable.} items Items to be inserted.\n\t */\n\t_insertChild( index, items ) {\n\t\tconst nodes = normalize( items );\n\n\t\tfor ( const node of nodes ) {\n\t\t\t// If node that is being added to this element is already inside another element, first remove it from the old parent.\n\t\t\tif ( node.parent !== null ) {\n\t\t\t\tnode._remove();\n\t\t\t}\n\n\t\t\tnode.parent = this;\n\t\t}\n\n\t\tthis._children._insertNodes( index, nodes );\n\t}\n\n\t/**\n\t * Removes one or more nodes starting at the given index\n\t * and sets {@link module:engine/model/node~Node#parent parent} of these nodes to `null`.\n\t *\n\t * @protected\n\t * @param {Number} index Index of the first node to remove.\n\t * @param {Number} [howMany=1] Number of nodes to remove.\n\t * @returns {Array.} Array containing removed nodes.\n\t */\n\t_removeChildren( index, howMany = 1 ) {\n\t\tconst nodes = this._children._removeNodes( index, howMany );\n\n\t\tfor ( const node of nodes ) {\n\t\t\tnode.parent = null;\n\t\t}\n\n\t\treturn nodes;\n\t}\n\n\t// @if CK_DEBUG_ENGINE // toString() {\n\t// @if CK_DEBUG_ENGINE // \treturn 'documentFragment';\n\t// @if CK_DEBUG_ENGINE // }\n\n\t// @if CK_DEBUG_ENGINE // log() {\n\t// @if CK_DEBUG_ENGINE // \tconsole.log( 'ModelDocumentFragment: ' + this );\n\t// @if CK_DEBUG_ENGINE // }\n\n\t// @if CK_DEBUG_ENGINE // printTree() {\n\t// @if CK_DEBUG_ENGINE //\tlet string = 'ModelDocumentFragment: [';\n\n\t// @if CK_DEBUG_ENGINE //\tfor ( const child of this.getChildren() ) {\n\t// @if CK_DEBUG_ENGINE //\t\tstring += '\\n';\n\n\t// @if CK_DEBUG_ENGINE //\t\tif ( child.is( '$text' ) ) {\n\t// @if CK_DEBUG_ENGINE //\t\t\tconst textAttrs = stringifyMap( child._attrs );\n\n\t// @if CK_DEBUG_ENGINE //\t\t\tstring += '\\t'.repeat( 1 );\n\n\t// @if CK_DEBUG_ENGINE //\t\t\tif ( textAttrs !== '' ) {\n\t// @if CK_DEBUG_ENGINE //\t\t\t\tstring += `<$text${ textAttrs }>` + child.data + '';\n\t// @if CK_DEBUG_ENGINE //\t\t\t} else {\n\t// @if CK_DEBUG_ENGINE //\t\t\t\tstring += child.data;\n\t// @if CK_DEBUG_ENGINE //\t\t\t}\n\t// @if CK_DEBUG_ENGINE //\t\t} else {\n\t// @if CK_DEBUG_ENGINE //\t\t\tstring += child.printTree( 1 );\n\t// @if CK_DEBUG_ENGINE //\t\t}\n\t// @if CK_DEBUG_ENGINE //\t}\n\n\t// @if CK_DEBUG_ENGINE //\tstring += '\\n]';\n\n\t// @if CK_DEBUG_ENGINE //\treturn string;\n\t// @if CK_DEBUG_ENGINE // }\n\n\t// @if CK_DEBUG_ENGINE // logTree() {\n\t// @if CK_DEBUG_ENGINE // \tconsole.log( this.printTree() );\n\t// @if CK_DEBUG_ENGINE // }\n}\n\n// Converts strings to Text and non-iterables to arrays.\n//\n// @param {String|module:engine/model/item~Item|Iterable.}\n// @returns {Iterable.}\nfunction normalize( nodes ) {\n\t// Separate condition because string is iterable.\n\tif ( typeof nodes == 'string' ) {\n\t\treturn [ new Text( nodes ) ];\n\t}\n\n\tif ( !isIterable( nodes ) ) {\n\t\tnodes = [ nodes ];\n\t}\n\n\t// Array.from to enable .map() on non-arrays.\n\treturn Array.from( nodes )\n\t\t.map( node => {\n\t\t\tif ( typeof node == 'string' ) {\n\t\t\t\treturn new Text( node );\n\t\t\t}\n\n\t\t\tif ( node instanceof TextProxy ) {\n\t\t\t\treturn new Text( node.data, node.getAttributes() );\n\t\t\t}\n\n\t\t\treturn node;\n\t\t} );\n}\n"],"sourceRoot":""}