8
0
فهرست منبع

document package renamed to treeModel.

Szymon Cofalik 10 سال پیش
والد
کامیت
b501884b26
54فایلهای تغییر یافته به همراه0 افزوده شده و 9728 حذف شده
  1. 0 125
      packages/ckeditor5-utils/src/document/attribute.js
  2. 0 21
      packages/ckeditor5-utils/src/document/batch.js
  3. 0 36
      packages/ckeditor5-utils/src/document/character.js
  4. 0 160
      packages/ckeditor5-utils/src/document/delta/attributedelta.js
  5. 0 123
      packages/ckeditor5-utils/src/document/delta/batch-base.js
  6. 0 58
      packages/ckeditor5-utils/src/document/delta/delta.js
  7. 0 44
      packages/ckeditor5-utils/src/document/delta/insertdelta.js
  8. 0 78
      packages/ckeditor5-utils/src/document/delta/mergedelta.js
  9. 0 14
      packages/ckeditor5-utils/src/document/delta/register.js
  10. 0 47
      packages/ckeditor5-utils/src/document/delta/removedelta.js
  11. 0 71
      packages/ckeditor5-utils/src/document/delta/splitdelta.js
  12. 0 188
      packages/ckeditor5-utils/src/document/document.js
  13. 0 121
      packages/ckeditor5-utils/src/document/element.js
  14. 0 247
      packages/ckeditor5-utils/src/document/node.js
  15. 0 156
      packages/ckeditor5-utils/src/document/nodelist.js
  16. 0 142
      packages/ckeditor5-utils/src/document/operation/attributeoperation.js
  17. 0 74
      packages/ckeditor5-utils/src/document/operation/insertoperation.js
  18. 0 138
      packages/ckeditor5-utils/src/document/operation/moveoperation.js
  19. 0 37
      packages/ckeditor5-utils/src/document/operation/nooperation.js
  20. 0 80
      packages/ckeditor5-utils/src/document/operation/operation.js
  21. 0 37
      packages/ckeditor5-utils/src/document/operation/reinsertoperation.js
  22. 0 49
      packages/ckeditor5-utils/src/document/operation/removeoperation.js
  23. 0 422
      packages/ckeditor5-utils/src/document/operation/transform.js
  24. 0 490
      packages/ckeditor5-utils/src/document/position.js
  25. 0 178
      packages/ckeditor5-utils/src/document/positioniterator.js
  26. 0 304
      packages/ckeditor5-utils/src/document/range.js
  27. 0 35
      packages/ckeditor5-utils/src/document/rootelement.js
  28. 0 42
      packages/ckeditor5-utils/src/document/text.js
  29. 0 81
      packages/ckeditor5-utils/tests/document/attribute.js
  30. 0 83
      packages/ckeditor5-utils/tests/document/batch.js
  31. 0 56
      packages/ckeditor5-utils/tests/document/character.js
  32. 0 301
      packages/ckeditor5-utils/tests/document/deltas/attributedelta.js
  33. 0 67
      packages/ckeditor5-utils/tests/document/deltas/delta.js
  34. 0 46
      packages/ckeditor5-utils/tests/document/deltas/insertdelta.js
  35. 0 80
      packages/ckeditor5-utils/tests/document/deltas/mergedelta.js
  36. 0 61
      packages/ckeditor5-utils/tests/document/deltas/removedelta.js
  37. 0 101
      packages/ckeditor5-utils/tests/document/deltas/splitdelta.js
  38. 0 186
      packages/ckeditor5-utils/tests/document/document/change-event.js
  39. 0 123
      packages/ckeditor5-utils/tests/document/document/document.js
  40. 0 128
      packages/ckeditor5-utils/tests/document/element.js
  41. 0 276
      packages/ckeditor5-utils/tests/document/node.js
  42. 0 115
      packages/ckeditor5-utils/tests/document/nodelist.js
  43. 0 385
      packages/ckeditor5-utils/tests/document/operation/attributeoperation.js
  44. 0 197
      packages/ckeditor5-utils/tests/document/operation/insertoperation.js
  45. 0 261
      packages/ckeditor5-utils/tests/document/operation/moveoperation.js
  46. 0 48
      packages/ckeditor5-utils/tests/document/operation/nooperation.js
  47. 0 85
      packages/ckeditor5-utils/tests/document/operation/reinsertoperation.js
  48. 0 113
      packages/ckeditor5-utils/tests/document/operation/removeoperation.js
  49. 0 2382
      packages/ckeditor5-utils/tests/document/operation/transform.js
  50. 0 501
      packages/ckeditor5-utils/tests/document/position.js
  51. 0 137
      packages/ckeditor5-utils/tests/document/positioniterator.js
  52. 0 325
      packages/ckeditor5-utils/tests/document/range.js
  53. 0 42
      packages/ckeditor5-utils/tests/document/rootelement.js
  54. 0 31
      packages/ckeditor5-utils/tests/document/text.js

+ 0 - 125
packages/ckeditor5-utils/src/document/attribute.js

@@ -1,125 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [ 'utils' ], ( utils ) => {
-	/**
-	 * Attributes can store any additional information for nodes in the data model.
-	 *
-	 * @class document.Attribute
-	 */
-	class Attribute {
-		/**
-		 * Creates a new instance of the `Attribute` class. Once attribute is created it is immutable.
-		 *
-		 * @param {String} key Attribute key.
-		 * @param {Mixed} value Attribute value.
-		 * @constructor
-		 */
-		constructor( key, value ) {
-			/**
-			 * Attribute key.
-			 *
-			 * @readonly
-			 * @property {String} key
-			 */
-			this.key = key;
-
-			/**
-			 * Attribute value. Note that value may be any type, including objects.
-			 *
-			 * @readonly
-			 * @property {Mixed} value
-			 */
-			this.value = value;
-
-			/**
-			 * Attribute hash. Used to compare attributes. Two attributes with the same key and value will have the same hash.
-			 *
-			 * @readonly
-			 * @private
-			 * @property {String} _hash
-			 */
-			this._hash = this.key + ': ' + JSON.stringify( this.value, sort );
-
-			// If attribute is already registered the registered one should be returned.
-			if ( Attribute._register[ this._hash ] ) {
-				return Attribute._register[ this._hash ];
-			}
-
-			// We do not care about the order, so collections with the same elements should return the same hash.
-			function sort( key, value ) {
-				if ( !utils.isArray( value ) && utils.isObject( value ) ) {
-					const sorted = {};
-
-					// Sort keys and fill up the sorted object.
-					Object.keys( value ).sort().forEach( ( key ) => {
-						sorted[ key ] = value[ key ];
-					} );
-
-					return sorted;
-				} else {
-					return value;
-				}
-			}
-		}
-
-		/**
-		 * Compares two attributes. Returns `true` if two attributes have the same key and value even if the order of keys
-		 * in the value object is different.
-		 *
-		 *		let attr1 = new Attribute( 'foo', { a: 1, b: 2 } );
-		 *		let attr2 = new Attribute( 'foo', { b: 2, a: 1 } );
-		 *		attr1.isEqual( attr2 ); // true
-		 *
-		 * @param {document.Attribute} otherAttr Attribute to compare with.
-		 * @returns {Boolean} True if attributes are equal to each other.
-		 */
-		isEqual( otherAttr ) {
-			return this._hash === otherAttr._hash;
-		}
-
-		/**
-		 * To save memory, commonly used attributes may be registered. If an attribute is registered the constructor will
-		 * always return the same instance of this attribute.
-		 *
-		 * Note that attributes are registered globally.
-		 *
-		 *		let attr1 = Attribute.register( 'bold', true );
-		 *		let attr2 = Attribute.register( 'bold', true );
-		 *		let attr3 = new Attribute( 'bold', true );
-		 *		attr1 === attr2 // true
-		 *		attr1 === attr3 // true
-		 *
-		 * @static
-		 * @param {String} key Attribute key.
-		 * @param {Mixed} value Attribute value.
-		 * @returns {document.Attribute} Registered attribute.
-		 */
-		static register( key, value ) {
-			const attr = new Attribute( key, value );
-
-			if ( this._register[ attr._hash ] ) {
-				return this._register[ attr._hash ];
-			} else {
-				this._register[ attr._hash ] = attr;
-
-				return attr;
-			}
-		}
-	}
-
-	/**
-	 * Register of attributes in which all registered attributes are stored.
-	 *
-	 * @static
-	 * @private
-	 * @property {String} _hash
-	 */
-	Attribute._register = {};
-
-	return Attribute;
-} );

+ 0 - 21
packages/ckeditor5-utils/src/document/batch.js

@@ -1,21 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-// All deltas need to be loaded so they can register themselves as Batch methods.
-//
-// To solve circular dependencies (deltas need to require Batch class), Batch class body is moved
-// to document/delta/batch-base.
-CKEDITOR.define( [
-	'document/delta/batch-base',
-	'document/delta/insertdelta',
-	'document/delta/removedelta',
-	'document/delta/attributedelta',
-	'document/delta/splitdelta',
-	'document/delta/mergedelta'
-], ( Batch ) => {
-	return Batch;
-} );

+ 0 - 36
packages/ckeditor5-utils/src/document/character.js

@@ -1,36 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [ 'document/node' ], ( Node ) => {
-	/**
-	 * Data structure for character stored in the tree data model.
-	 *
-	 * @class document.Character
-	 */
-	class Character extends Node {
-		/**
-		 * Creates character linear item.
-		 *
-		 * @param {String} character Described character.
-		 * @param {Iterable} attrs Iterable collection of {@link document.Attribute attributes}.
-		 * @constructor
-		 */
-		constructor( character, attrs ) {
-			super( attrs );
-
-			/**
-			 * Described character.
-			 *
-			 * @readonly
-			 * @property {String} character
-			 */
-			this.character = character;
-		}
-	}
-
-	return Character;
-} );

+ 0 - 160
packages/ckeditor5-utils/src/document/delta/attributedelta.js

@@ -1,160 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/delta/delta',
-	'document/delta/register',
-	'document/operation/attributeoperation',
-	'document/position',
-	'document/range',
-	'document/positioniterator',
-	'document/attribute',
-	'document/element'
-], ( Delta, register, AttributeOperation, Position, Range, PositionIterator, Attribute, Element ) => {
-	/**
-	 * To provide specific OT behavior and better collisions solving, change methods ({@link document.Batch#setAttr}
-	 * and {@link document.Batch#removeAttr}) use `AttributeDelta` class which inherits from the `Delta` class and may
-	 * overwrite some methods.
-	 *
-	 * @class document.delta.AttributeDelta
-	 */
-	class AttributeDelta extends Delta {}
-
-	/**
-	 * Sets the value of the attribute of the node or on the range.
-	 *
-	 * @chainable
-	 * @method setAttr
-	 * @memberOf document.Batch
-	 * @param {String} key Attribute key.
-	 * @param {*} value Attribute new value.
-	 * @param {document.Node|document.Range} nodeOrRange Node or range on which the attribute will be set.
-	 */
-	register( 'setAttr', function( key, value, nodeOrRange ) {
-		attribute( this, key, value, nodeOrRange );
-
-		return this;
-	} );
-
-	/**
-	 * Removes an attribute from the range.
-	 *
-	 * @chainable
-	 * @method removeAttr
-	 * @memberOf document.Batch
-	 * @param {String} key Attribute key.
-	 * @param {document.Node|document.Range} nodeOrRange Node or range on which the attribute will be removed.
-	 */
-	register( 'removeAttr', function( key, nodeOrRange ) {
-		attribute( this, key, null, nodeOrRange );
-
-		return this;
-	} );
-
-	function attribute( batch, key, value, nodeOrRange ) {
-		const delta = new AttributeDelta();
-
-		if ( nodeOrRange instanceof Range ) {
-			changeRange( batch.doc, delta, key, value, nodeOrRange );
-		} else {
-			changeNode( batch.doc, delta, key, value, nodeOrRange );
-		}
-
-		batch.addDelta( delta );
-	}
-
-	function changeNode( doc, delta, key, value, node ) {
-		const previousValue = node.getAttr( key );
-		let range;
-
-		if ( previousValue != value ) {
-			if ( node instanceof Element ) {
-				// If we change the attribute of the element, we do not want to change attributes of its children, so
-				// the end on the range can not be put after the closing tag, it should be inside that element with the
-				// offset 0, so the range will contains only the opening tag...
-				range = new Range( Position.createBefore( node ), Position.createFromParentAndOffset( node, 0 ) );
-			} else {
-				// ...but for characters we can not put the range inside it, so we end the range after that character.
-				range = new Range( Position.createBefore( node ), Position.createAfter( node ) );
-			}
-
-			const operation = new AttributeOperation(
-					range,
-					previousValue ? new Attribute( key, previousValue ) : null,
-					value ? new Attribute( key, value ) : null,
-					doc.version
-				);
-
-			doc.applyOperation( operation );
-			delta.addOperation( operation );
-		}
-	}
-
-	// Because attribute operation needs to have the same attribute value on the whole range, this function split the range
-	// into smaller parts.
-	function changeRange( doc, delta, key, value, range ) {
-		// Position of the last split, the beginning of the new range.
-		let lastSplitPosition = range.start;
-
-		// Currently position in the scanning range. Because we need value after the position, it is not a current
-		// position of the iterator but the previous one (we need to iterate one more time to get the value after).
-		let position;
-		// Value before the currently position.
-		let valueBefore;
-		// Value after the currently position.
-		let valueAfter;
-
-		// Because we need not only a node, but also a position, we can not use ( value of range ).
-		const iterator = range[ Symbol.iterator ]();
-		// Iterator state.
-		let next = iterator.next();
-
-		while ( !next.done ) {
-			// We check values only when the range contains given element, that is when the iterator "enters" the element.
-			// To prevent double-checking or not needed checking, we filter-out iterator values for ELEMENT_LEAVE position.
-			if ( next.value.type != PositionIterator.ELEMENT_LEAVE ) {
-				valueAfter = next.value.node.getAttr( key );
-
-				// At the first run of the iterator the position in undefined. We also do not have a valueBefore, but
-				// because valueAfter may be null, valueBefore may be equal valueAfter ( undefined == null ).
-				if ( position && valueBefore != valueAfter ) {
-					// if valueBefore == value there is nothing to change, so we add operation only if these values are different.
-					if ( valueBefore != value ) {
-						addOperation();
-					}
-
-					lastSplitPosition = position;
-				}
-
-				position = iterator.position;
-				valueBefore = valueAfter;
-			}
-
-			next = iterator.next();
-		}
-
-		// Because position in the loop is not the iterator position (see let position comment), the last position in
-		// the while loop will be last but one position in the range. We need to check the last position manually.
-		if ( position != lastSplitPosition && valueBefore != value ) {
-			addOperation();
-		}
-
-		function addOperation() {
-			const operation = new AttributeOperation(
-					new Range( lastSplitPosition, position ),
-					valueBefore ? new Attribute( key, valueBefore ) : null,
-					value ? new Attribute( key, value ) : null,
-					doc.version
-				);
-
-			doc.applyOperation( operation );
-			delta.addOperation( operation );
-		}
-	}
-
-	return AttributeDelta;
-} );

+ 0 - 123
packages/ckeditor5-utils/src/document/delta/batch-base.js

@@ -1,123 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [ 'ckeditorerror' ], ( CKEditorError ) => {
-	/**
-	 * The Batch class groups document changes (deltas). All deltas grouped in a single Batch can be
-	 * reverted together, so you can think about the Batch as a single undo step. If you want to extend one
-	 * undo step you can call another method on the same Batch object. If you want to create a separate undo step
-	 * you can create a new Batch.
-	 *
-	 * For example to create two separate undo steps you can call:
-	 *
-	 *		doc.batch().insert( firstPosition, 'foo' );
-	 *		doc.batch().insert( secondPosition, 'bar' );
-	 *
-	 * To create a single undo step:
-	 *
-	 *		const batch = doc.batch();
-	 *		batch.insert( firstPosition, 'foo' );
-	 *		batch.insert( secondPosition, 'bar' );
-	 *
-	 * Note that all document modification methods (insert, remove, split, etc.) are chainable so you can shorten code to:
-	 *
-	 *		doc.batch().insert( firstPosition, 'foo' ).insert( secondPosition, 'bar' );
-	 *
-	 * @class document.Batch
-	 */
-	class Batch {
-		/**
-		 * Creates Batch instance. Not recommended to use directly, use {@link document.Document#batch} instead.
-		 *
-		 * @constructor
-		 * @param {document.Document} doc Document which this Batch changes.
-		 */
-		constructor( doc ) {
-			/**
-			 * Document which this Batch changes.
-			 *
-			 * @readonly
-			 * @type {document.Document}
-			 */
-			this.doc = doc;
-
-			/**
-			 * Array of deltas which compose Batch.
-			 *
-			 * @readonly
-			 * @type {Array.<document.delta.Delta>}
-			 */
-			this.deltas = [];
-		}
-
-		/**
-		 * Adds delta to the Batch instance. All modification methods (insert, remove, split, etc.) use this method
-		 * to add created deltas.
-		 *
-		 * @param {document.delta.Delta} delta Delta to add.
-		 * @return {document.delta.Delta} Added delta.
-		 */
-		addDelta( delta ) {
-			delta.batch = this;
-			this.deltas.push( delta );
-
-			return delta;
-		}
-
-		/**
-		 * Static method to register Batch methods. To make code scalable Batch do not have modification
-		 * methods built in. They can be registered using this method.
-		 *
-		 * This method checks if there is no naming collision and throws `batch-register-taken` if the method name
-		 * is already taken.
-		 *
-		 * Besides that no magic happens here, the method is added to the `Batch` class prototype.
-		 *
-		 * For example:
-		 *
-		 *		Batch.register( 'insert', function( position, nodes ) {
-		 *			// You can use a class inherit from Delta if that class should handle OT in the special way.
-		 *			const delta = new Delta();
-		 *
-		 * 			// Create operations which should be components of this delta.
-		 *			const operation = new InsertOperation( position, nodes, this.doc.version );
-		 *
-		 *			// Remember to apply every operation, no magic, you need to do it manually.
-		 *			this.doc.applyOperation( operation );
-		 *
-		 *			// Add operation to the delta.
-		 *			delta.addOperation( operation );
-		 *
-		 *			// Add delta to the Batch instance.
-		 *			this.addDelta( delta );
-		 *
-		 * 			// Make this method chainable.
-		 * 			return this;
-		 *		} );
-		 *
-		 * @param {String} name Method name.
-		 * @param {Function} creator Method body.
-		 */
-		static register( name, creator ) {
-			if ( Batch.prototype[ name ] ) {
-				/**
-				 * This batch method name is already taken.
-				 *
-				 * @error batch-register-taken
-				 * @param {String} name
-				 */
-				throw new CKEditorError(
-					'batch-register-taken: This batch method name is already taken.',
-					{ name: name } );
-			}
-
-			Batch.prototype[ name ] = creator;
-		}
-	}
-
-	return Batch;
-} );

+ 0 - 58
packages/ckeditor5-utils/src/document/delta/delta.js

@@ -1,58 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [], () => {
-	/**
-	 * Base class for all deltas.
-	 *
-	 * Delta is a single, from the user action point of view, change in the editable document, like insert, split or
-	 * rename element. Delta is composed of operations, which are unit changes needed to be done to execute user action.
-	 *
-	 * Multiple deltas are grouped into a single {@link document.Batch}.
-	 *
-	 * @class document.delta.Delta
-	 */
-	class Delta {
-		/**
-		 * Creates a delta instance.
-		 *
-		 * @constructor
-		 */
-		constructor() {
-			/**
-			 * {@link document.Batch} which delta is a part of. This property is null by default and set by the
-			 * {@link Document.Batch#addDelta} method.
-			 *
-			 * @readonly
-			 * @type {document.Batch}
-			 */
-			this.batch = null;
-
-			/**
-			 * Array of operations which compose delta.
-			 *
-			 * @readonly
-			 * @type {document.operation.Operation[]}
-			 */
-			this.operations = [];
-		}
-
-		/**
-		 * Add operation to the delta.
-		 *
-		 * @param {document.operation.Operation} operation Operation instance.
-		 */
-		addOperation( operation ) {
-			operation.delta = this;
-			this.operations.push( operation );
-
-			return operation;
-		}
-	}
-
-	return Delta;
-} );

+ 0 - 44
packages/ckeditor5-utils/src/document/delta/insertdelta.js

@@ -1,44 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/delta/delta',
-	'document/delta/register',
-	'document/operation/insertoperation'
-], ( Delta, register, InsertOperation ) => {
-	/**
-	 * To provide specific OT behavior and better collisions solving, the {@link document.Batch#insert} method
-	 * uses the `InsertDelta` class which inherits from the `Delta` class and may overwrite some methods.
-	 *
-	 * @class document.delta.InsertDelta
-	 */
-	class InsertDelta extends Delta {}
-
-	/**
-	 * Inserts a node or nodes at the given position.
-	 *
-	 * @chainable
-	 * @memberOf document.Batch
-	 * @method insert
-	 * @param {document.Position} position Position of insertion.
-	 * @param {document.Node|document.Text|document.NodeList|String|Iterable} nodes The list of nodes to be inserted.
-	 * List of nodes can be of any type accepted by the {@link document.NodeList} constructor.
-	 */
-	register( 'insert', function( position, nodes ) {
-		const delta = new InsertDelta();
-
-		const operation = new InsertOperation( position, nodes, this.doc.version );
-		this.doc.applyOperation( operation );
-		delta.addOperation( operation );
-
-		this.addDelta( delta );
-
-		return this;
-	} );
-
-	return InsertDelta;
-} );

+ 0 - 78
packages/ckeditor5-utils/src/document/delta/mergedelta.js

@@ -1,78 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/delta/delta',
-	'document/delta/register',
-	'document/position',
-	'document/element',
-	'document/operation/removeoperation',
-	'document/operation/moveoperation',
-	'ckeditorerror'
-], ( Delta, register, Position, Element, RemoveOperation, MoveOperation, CKEditorError ) => {
-	/**
-	 * To provide specific OT behavior and better collisions solving, {@link document.Batch#merge} method
-	 * uses the `MergeDelta` class which inherits from the `Delta` class and may overwrite some methods.
-	 *
-	 * @class document.delta.MergeDelta
-	 */
-	class MergeDelta extends Delta {}
-
-	/**
-	 * Merges two siblings at the given position.
-	 *
-	 * Node before and after the position have to be an element. Otherwise `batch-merge-no-element-before` or
-	 * `batch-merge-no-element-after` error will be thrown.
-	 *
-	 * @chainable
-	 * @method merge
-	 * @memberOf document.Batch
-	 * @param {document.Position} position Position of merge.
-	 */
-	register( 'merge', function( position ) {
-		const delta = new MergeDelta();
-		const nodeBefore = position.nodeBefore;
-		const nodeAfter = position.nodeAfter;
-
-		if ( !( nodeBefore instanceof Element ) ) {
-			/**
-			 * Node before merge position must be an element.
-			 *
-			 * @error batch-merge-no-element-before
-			 */
-			throw new CKEditorError(
-				'batch-merge-no-element-before: Node before merge position must be an element.' );
-		}
-
-		if ( !( nodeAfter instanceof Element ) ) {
-			/**
-			 * Node after merge position must be an element.
-			 *
-			 * @error batch-merge-no-element-after
-			 */
-			throw new CKEditorError(
-				'batch-merge-no-element-after: Node after merge position must be an element.' );
-		}
-
-		const positionAfter = Position.createFromParentAndOffset( nodeAfter, 0 );
-		const positionBefore = Position.createFromParentAndOffset( nodeBefore, nodeBefore.getChildCount() );
-
-		const move = new MoveOperation( positionAfter, nodeAfter.getChildCount(), positionBefore, this.doc.version );
-		this.doc.applyOperation( move );
-		delta.addOperation( move );
-
-		const remove = new RemoveOperation( position, 1, this.doc.version );
-		this.doc.applyOperation( remove );
-		delta.addOperation( remove );
-
-		this.addDelta( delta );
-
-		return this;
-	} );
-
-	return MergeDelta;
-} );

+ 0 - 14
packages/ckeditor5-utils/src/document/delta/register.js

@@ -1,14 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-// Register method exposed for deltas, which needs only this method, to make code simpler, more beautiful and, first of
-// all, to solve circular dependencies.
-CKEDITOR.define( [
-	'document/delta/batch-base'
-], ( Batch ) => {
-	return Batch.register;
-} );

+ 0 - 47
packages/ckeditor5-utils/src/document/delta/removedelta.js

@@ -1,47 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/delta/delta',
-	'document/delta/register',
-	'document/operation/removeoperation'
-], ( Delta, register, RemoveOperation ) => {
-	/**
-	 * To provide specific OT behavior and better collisions solving, {@link document.Batch#remove} method
-	 * uses the `RemoveDelta` class which inherits from the `Delta` class and may overwrite some methods.
-	 *
-	 * @class document.delta.RemoveDelta
-	 */
-	class RemoveDelta extends Delta {}
-
-	/**
-	 * Removes nodes starting from the given position.
-	 *
-	 * @chainable
-	 * @method remove
-	 * @memberOf document.Batch
-	 * @param {document.Position} position Position before the first node to remove.
-	 * @param {Number} howMany How many nodes to remove.
-	 */
-	register( 'remove', function( position, howMany ) {
-		if ( typeof howMany !== 'number' ) {
-			howMany = 1;
-		}
-
-		const delta = new RemoveDelta();
-
-		const operation = new RemoveOperation( position, howMany, this.doc.version );
-		this.doc.applyOperation( operation );
-		delta.addOperation( operation );
-
-		this.addDelta( delta );
-
-		return this;
-	} );
-
-	return RemoveDelta;
-} );

+ 0 - 71
packages/ckeditor5-utils/src/document/delta/splitdelta.js

@@ -1,71 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/delta/delta',
-	'document/delta/register',
-	'document/position',
-	'document/element',
-	'document/operation/insertoperation',
-	'document/operation/moveoperation',
-	'ckeditorerror'
-], ( Delta, register, Position, Element, InsertOperation, MoveOperation, CKEditorError ) => {
-	/**
-	 * To provide specific OT behavior and better collisions solving, the {@link document.Batch#split} method
-	 * uses `SplitDelta` class which inherits from the `Delta` class and may overwrite some methods.
-	 *
-	 * @class document.delta.SplitDelta
-	 */
-	class SplitDelta extends Delta {}
-
-	/**
-	 * Splits a node at the given position.
-	 *
-	 * This cannot be a position inside the root element. The `batch-split-root` error will be thrown if
-	 * you try to split the root element.
-	 *
-	 * @chainable
-	 * @method split
-	 * @memberOf document.Batch
-	 * @param {document.Position} position Position of split.
-	 */
-	register( 'split', function( position ) {
-		const delta = new SplitDelta();
-		const splitElement = position.parent;
-
-		if ( !splitElement.parent ) {
-			/**
-			 * Root element can not be split.
-			 *
-			 * @error batch-split-root
-			 */
-			throw new CKEditorError( 'batch-split-root: Root element can not be split.' );
-		}
-
-		const copy = new Element( splitElement.name, splitElement.getAttrs() );
-		const insert = new InsertOperation( Position.createAfter( splitElement ), copy, this.doc.version );
-
-		this.doc.applyOperation( insert );
-		delta.addOperation( insert );
-
-		const move = new MoveOperation(
-			position,
-			splitElement.getChildCount() - position.offset,
-			Position.createFromParentAndOffset( copy, 0 ),
-			this.doc.version
-		);
-
-		this.doc.applyOperation( move );
-		delta.addOperation( move );
-
-		this.addDelta( delta );
-
-		return this;
-	} );
-
-	return SplitDelta;
-} );

+ 0 - 188
packages/ckeditor5-utils/src/document/document.js

@@ -1,188 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/element',
-	'document/rootelement',
-	'document/batch',
-	'emittermixin',
-	'utils',
-	'ckeditorerror'
-], ( Element, RootElement, Batch, EmitterMixin, utils, CKEditorError ) => {
-	const graveyardSymbol = Symbol( 'graveyard' );
-
-	/**
-	 * Document tree model describes all editable data in the editor. It may contain multiple {@link #roots root elements},
-	 * for example if the editor have multiple editable areas, each area will be represented by the separate root.
-	 *
-	 * All changes in the document are done by {@link document.operation.Operation operations}. To create operations in
-	 * the simple way use use the {@link document.Batch} API, for example:
-	 *
-	 *		document.batch().insert( position, nodes ).split( otherPosition );
-	 *
-	 * @see #batch
-	 *
-	 * @class document.Document
-	 */
-	class Document {
-		/**
-		 * Creates an empty document instance with no {@link #roots}.
-		 *
-		 * @constructor
-		 */
-		constructor() {
-			/**
-			 * List of roots that are owned and managed by this document.
-			 *
-			 * @readonly
-			 * @property {Map} roots
-			 */
-			this.roots = new Map();
-
-			// Graveyard tree root. Document always have a graveyard root, which stores removed nodes.
-			this.createRoot( graveyardSymbol );
-
-			/**
-			 * Document version. It starts from `0` and every operation increases the version number. It is used to ensure that
-			 * operations are applied on the proper document version. If the {@link document.operation.Operation#baseVersion} will
-			 * not match document version the {@link document-applyOperation-wrong-version} error is thrown.
-			 *
-			 * @readonly
-			 * @property {Number} version
-			 */
-			this.version = 0;
-		}
-
-		/**
-		 * Graveyard tree root. Document always have a graveyard root, which stores removed nodes.
-		 *
-		 * @protected
-		 * @readonly
-		 * @property {document.RootElement} _graveyard
-		 */
-		get _graveyard() {
-			return this.getRoot( graveyardSymbol );
-		}
-
-		/**
-		 * This is the entry point for all document changes. All changes on the document are done using
-		 * {@link document.operation.Operation operations}. To create operations in the simple way use the
-		 * {@link document.Batch} API available via {@link #batch} method.
-		 *
-		 * @param {document.operation.Operation} operation Operation to be applied.
-		 */
-		applyOperation( operation ) {
-			if ( operation.baseVersion !== this.version ) {
-				/**
-				 * Only operations with matching versions can be applied.
-				 *
-				 * @error document-applyOperation-wrong-version
-				 * @param {document.operation.Operation} operation
-				 */
-				throw new CKEditorError(
-					'document-applyOperation-wrong-version: Only operations with matching versions can be applied.',
-					{ operation: operation } );
-			}
-
-			let changes = operation._execute();
-
-			this.version++;
-
-			this.fire( 'change', operation.type, changes );
-		}
-
-		/**
-		 * Creates a {@link document.Batch} instance which allows to change the document.
-		 *
-		 * @returns {document.Batch} Batch instance.
-		 */
-		batch() {
-			return new Batch( this );
-		}
-
-		/**
-		 * Creates a new top-level root.
-		 *
-		 * @param {String|Symbol} name Unique root name.
-		 * @returns {document.RootElement} Created root.
-		 */
-		createRoot( name ) {
-			if ( this.roots.has( name ) ) {
-				/**
-				 * Root with specified name already exists.
-				 *
-				 * @error document-createRoot-name-exists
-				 * @param {document.Document} doc
-				 * @param {String} name
-				 */
-				throw new CKEditorError(
-					'document-createRoot-name-exists: Root with specified name already exists.',
-					{ name: name }
-				);
-			}
-
-			const root = new RootElement( this );
-			this.roots.set( name, root );
-
-			return root;
-		}
-
-		/**
-		 * Returns top-level root by it's name.
-		 *
-		 * @param {String|Symbol} name Name of the root to get.
-		 * @returns (document.RootElement} Root registered under given name.
-		 */
-		getRoot( name ) {
-			if ( !this.roots.has( name ) ) {
-				/**
-				 * Root with specified name does not exist.
-				 *
-				 * @error document-createRoot-root-not-exist
-				 * @param {String} name
-				 */
-				throw new CKEditorError(
-					'document-createRoot-root-not-exist: Root with specified name does not exist.',
-					{ name: name }
-				);
-			}
-
-			return this.roots.get( name );
-		}
-
-		/**
-		 * Fired when document changes by applying an operation.
-		 *
-		 * There are 5 types of change:
-		 *
-		 * * 'insert' when nodes are inserted,
-		 * * 'remove' when nodes are removed,
-		 * * 'reinsert' when remove is undone,
-		 * * 'move' when nodes are moved,
-		 * * 'attr' when attributes change.
-		 *
-		 * Change event is fired after the change is done. This means that any ranges or positions passed in
-		 * `changeInfo` are referencing nodes and paths in updated tree model.
-		 *
-		 * @event change
-		 * @param {String} type Change type, possible option: 'insert', 'remove', 'reinsert', 'move', 'attr'.
-		 * @param {Object} changeInfo Additional information about the change.
-		 * @param {document.Range} changeInfo.range Range containing changed nodes. Note that for 'remove' the range will be in the
-		 * {@link #_graveyard graveyard root}.
-		 * @param {document.Position} [changeInfo.sourcePosition] Change source position. Exists for 'remove', 'reinsert' and 'move'.
-		 * Note that for 'reinsert' the source position will be in the {@link #_graveyard graveyard root}.
-		 * @param {document.Attribute} [changeInfo.oldAttr] Only for 'attr' type. If the type is 'attr' and `oldAttr`
-		 * is `undefined` it means that new attribute was inserted. Otherwise it contains changed or removed attribute.
-		 * @param {document.Attribute} [changeInfo.newAttr] Only for 'attr' type. If the type is 'attr' and `newAttr`
-		 * is `undefined` it means that attribute was removed. Otherwise it contains changed or inserted attribute.
-		 */
-	}
-
-	utils.extend( Document.prototype, EmitterMixin );
-
-	return Document;
-} );

+ 0 - 121
packages/ckeditor5-utils/src/document/element.js

@@ -1,121 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/node',
-	'document/nodelist'
-], ( Node, NodeList ) => {
-	/**
-	 * Tree data model element.
-	 *
-	 * @class document.Element
-	 */
-	class Element extends Node {
-		/**
-		 * Creates a tree data model element.
-		 *
-		 * This constructor should be used only internally by the document.
-		 *
-		 * @param {String} name Node name.
-		 * @param {Iterable} attrs Iterable collection of {@link document.Attribute attributes}.
-		 * @param {document.Node|document.Text|document.NodeList|String|Iterable} children List of nodes to be inserted
-		 * into created element. List of nodes can be of any type accepted by the {@link document.NodeList} constructor.
-		 * @constructor
-		 */
-		constructor( name, attrs, children ) {
-			super( attrs );
-
-			/**
-			 * Element name.
-			 *
-			 * @readonly
-			 * @property {String} name
-			 */
-			this.name = name;
-
-			/**
-			 * List of children nodes.
-			 *
-			 * @protected
-			 * @property {document.NodeList} _children
-			 */
-			this._children = new NodeList();
-
-			if ( children ) {
-				this.insertChildren( 0, children );
-			}
-		}
-
-		/**
-		 * Gets child at the given index.
-		 *
-		 * @param {Number} index Index of child.
-		 * @returns {document.Node} Child node.
-		 */
-		getChild( index ) {
-			return this._children.get( index );
-		}
-
-		/**
-		 * Gets the number of element's children.
-		 *
-		 * @returns {Number} The number of element's children.
-		 */
-		getChildCount() {
-			return this._children.length;
-		}
-
-		/**
-		 * Gets index of the given child node.
-		 *
-		 * @param {document.Node} node Child node.
-		 * @returns {Number} Index of the child node.
-		 */
-		getChildIndex( node ) {
-			return this._children.indexOf( node );
-		}
-
-		/**
-		 * Inserts a list of child nodes on the given index and sets the parent of these nodes to this element.
-		 *
-		 * Note that the list of children can be modified only in elements not yet attached to the document.
-		 * All attached nodes should be modified using the {@link document.operation.InsertOperation}.
-		 *
-		 * @param {Number} index Position where nodes should be inserted.
-		 * @param {document.Node|document.Text|document.NodeList|String|Iterable} nodes The list of nodes to be inserted.
-		 * The list of nodes can be of any type accepted by the {@link document.NodeList} constructor.
-		 */
-		insertChildren( index, nodes ) {
-			this._children.insert( index, new NodeList( nodes ) );
-
-			for ( let node of this._children ) {
-				node.parent = this;
-			}
-		}
-
-		/**
-		 * Removes number of child nodes starting at the given index and set the parent of these nodes to `null`.
-		 *
-		 * Note that the list of children can be modified only in elements not yet attached to the document.
-		 * All attached nodes should be modified using the {@link document.operation.RemoveOperation}.
-		 *
-		 * @param {Number} index Position of the first node to remove.
-		 * @param {Number} number Number of nodes to remove.
-		 * @returns {document.NodeList} The list of removed nodes.
-		 */
-
-		removeChildren( index, number ) {
-			for ( let i = index; i < index + number; i++ ) {
-				this._children.get( i ).parent = null;
-			}
-
-			return this._children.remove( index, number );
-		}
-	}
-
-	return Element;
-} );

+ 0 - 247
packages/ckeditor5-utils/src/document/node.js

@@ -1,247 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [ 'document/attribute', 'utils', 'ckeditorerror' ], ( Attribute, utils, CKEditorError ) => {
-	/**
-	 * Abstract document tree node class.
-	 *
-	 * @abstract
-	 * @class document.Node
-	 */
-	class Node {
-		/**
-		 * Creates a tree node.
-		 *
-		 * This is an abstract class, so this constructor should not be used directly.
-		 *
-		 * @param {Iterable} attrs Iterable collection of {@link document.Attribute attributes}.
-		 * @constructor
-		 */
-		constructor( attrs ) {
-			/**
-			 * Parent element. Null by default. Set by {@link document.Element#insertChildren}.
-			 *
-			 * @readonly
-			 * @property {document.Element|null} parent
-			 */
-			this.parent = null;
-
-			/**
-			 * Attributes set.
-			 *
-			 * Attributes of nodes attached to the document can be changed only be the {@link document.operation.AttributeOperation}.
-			 *
-			 * @private
-			 * @property {Set} _attrs
-			 */
-			this._attrs = new Set( attrs );
-		}
-
-		/**
-		 * Depth of the node, which equals to total number of its parents.
-		 *
-		 * @readonly
-		 * @property {Number} depth
-		 */
-		get depth() {
-			let depth = 0;
-			let parent = this.parent;
-
-			while ( parent ) {
-				depth++;
-
-				parent = parent.parent;
-			}
-
-			return depth;
-		}
-
-		/**
-		 * Nodes next sibling or `null` if it is the last child.
-		 *
-		 * @readonly
-		 * @property {document.Node|null} nextSibling
-		 */
-		get nextSibling() {
-			const index = this.getIndex();
-
-			return ( index !== null && this.parent.getChild( index + 1 ) ) || null;
-		}
-
-		/**
-		 * Nodes previous sibling or null if it is the last child.
-		 *
-		 * @readonly
-		 * @property {document.Node|null} previousSibling
-		 */
-		get previousSibling() {
-			const index = this.getIndex();
-
-			return ( index !== null && this.parent.getChild( index - 1 ) ) || null;
-		}
-
-		/**
-		 * The top parent for the node. If node has no parent it is the root itself.
-		 *
-		 * @readonly
-		 * @property {Number} depth
-		 */
-		get root() {
-			let root = this; // jscs:ignore safeContextKeyword
-
-			while ( root.parent ) {
-				root = root.parent;
-			}
-
-			return root;
-		}
-
-		/**
-		 * Finds an attribute by a key.
-		 *
-		 * @param {String} attr The attribute key.
-		 * @returns {document.Attribute} The found attribute.
-		 */
-		getAttr( key ) {
-			for ( let attr of this._attrs ) {
-				if ( attr.key == key ) {
-					return attr.value;
-				}
-			}
-
-			return null;
-		}
-
-		/**
-		 * Returns attribute iterator. It can be use to create a new element with the same attributes:
-		 *
-		 *		const copy = new Element( element.name, element.getAttrs() );
-		 *
-		 * @returns {Iterable.<document.Attribute>} Attribute iterator.
-		 */
-		getAttrs() {
-			return this._attrs[ Symbol.iterator ]();
-		}
-
-		/**
-		 * Index of the node in the parent element or null if the node has no parent.
-		 *
-		 * Throws error if the parent element does not contain this node.
-		 *
-		 * @returns {Number|Null} Index of the node in the parent element or null if the node has not parent.
-		 */
-		getIndex() {
-			let pos;
-
-			if ( !this.parent ) {
-				return null;
-			}
-
-			// No parent or child doesn't exist in parent's children.
-			if ( ( pos = this.parent.getChildIndex( this ) ) == -1 ) {
-				/**
-				 * The node's parent does not contain this node. It means that the document tree is corrupted.
-				 *
-				 * @error node-not-found-in-parent
-				 */
-				throw new CKEditorError( 'node-not-found-in-parent: The node\'s parent does not contain this node.' );
-			}
-
-			return pos;
-		}
-
-		/**
-		 * Gets path to the node. For example if the node is the second child of the first child of the root then the path
-		 * will be `[ 1, 2 ]`. This path can be used as a parameter of {@link document.Position}.
-		 *
-		 * @returns {Number[]} The path.
-		 */
-		getPath() {
-			const path = [];
-			let node = this; // jscs:ignore safeContextKeyword
-
-			while ( node.parent ) {
-				path.unshift( node.getIndex() );
-				node = node.parent;
-			}
-
-			return path;
-		}
-
-		/**
-		 * Returns `true` if the node contains an attribute with the same key and value as given or the same key if the
-		 * given parameter is a string.
-		 *
-		 * @param {document.Attribute|String} key An attribute or a key to compare.
-		 * @returns {Boolean} True if node contains given attribute or an attribute with the given key.
-		 */
-		hasAttr( key ) {
-			let attr;
-
-			// Attribute.
-			if ( key instanceof Attribute ) {
-				for ( attr of this._attrs ) {
-					if ( attr.isEqual( key ) ) {
-						return true;
-					}
-				}
-			}
-			// Key.
-			else {
-				for ( attr of this._attrs ) {
-					if ( attr.key == key ) {
-						return true;
-					}
-				}
-			}
-
-			return false;
-		}
-
-		/**
-		 * Removes attribute from the list of attributes.
-		 *
-		 * @param {String} key The attribute key.
-		 */
-		removeAttr( key ) {
-			for ( let attr of this._attrs ) {
-				if ( attr.key == key ) {
-					this._attrs.delete( attr );
-
-					return;
-				}
-			}
-		}
-
-		/**
-		 * Sets a given attribute. If the attribute with the same key already exists it will be removed.
-		 *
-		 * @param {document.Attribute} attr Attribute to set.
-		 */
-		setAttr( attr ) {
-			this.removeAttr( attr.key );
-
-			this._attrs.add( attr );
-		}
-
-		/**
-		 * Custom toJSON method to solve child-parent circular dependencies.
-		 *
-		 * @returns {Object} Clone of this object with the parent property replaced with its name.
-		 */
-		toJSON() {
-			const json = utils.clone( this );
-
-			// Due to circular references we need to remove parent reference.
-			json.parent = this.parent ? this.parent.name : null;
-
-			return json;
-		}
-	}
-
-	return Node;
-} );

+ 0 - 156
packages/ckeditor5-utils/src/document/nodelist.js

@@ -1,156 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/character',
-	'document/text',
-	'document/node',
-	'utils'
-], ( Character, Text, Node, utils ) => {
-	/**
-	 * List of nodes. It is used to represent multiple nodes with a given order, for example children of
-	 * {@link document.Element} object or nodes inserted using {@link document.operation.InsertOperation}.
-	 *
-	 * Thanks to the constructor, which accepts various arguments, this class lets you easily create desired list of nodes.
-	 *
-	 * It also may internally compress nodes.
-	 *
-	 * @class document.NodeList
-	 */
-	class NodeList {
-		/**
-		 * Constructor let you create a list of nodes in many ways. See examples:
-		 *
-		 *		let nodeList = new NodeList( [ new Element( p1 ), new Element( p1 ) ] );
-		 *		nodeList.length; // 2
-		 *
-		 *		let nodeList = new NodeList( new Element( p ) );
-		 *		nodeList.length; // 1
-		 *
-		 *		let nodeList = new NodeList( [ 'foo', new Element( p ), 'bar' ] );
-		 *		nodeList.length; // 7
-		 *
-		 *		let nodeList = new NodeList( 'foo' );
-		 *		nodeList.length; // 3
-		 *
-		 *		let nodeList = new NodeList( new Text( 'foo', [ new Attribute( 'bar', 'bom' ) ] ) );
-		 *		nodeList.length; // 3
-		 *		nodeList.get( 0 ).getAttr( 'bar' ); // 'bom'
-		 *		nodeList.get( 1 ).getAttr( 'bar' ); // 'bom'
-		 *		nodeList.get( 2 ).getAttr( 'bar' ); // 'bom'
-		 *
-		 *		let nodeListA = new NodeList( 'foo' );
-		 *		let nodeListB = new NodeList( nodeListA );
-		 *		nodeListA === nodeListB // true
-		 *		nodeListB.length // 3
-		 *
-		 * @param {document.Node|document.Text|document.NodeList|String|Iterable} nodes List of nodes.
-		 * @constructor
-		 */
-		constructor( nodes ) {
-			if ( nodes instanceof NodeList ) {
-				// We do not clone anything.
-				return nodes;
-			}
-
-			/**
-			 * Internal array to store nodes.
-			 *
-			 * @private
-			 * @property {Array}
-			 */
-			this._nodes = [];
-
-			if ( nodes ) {
-				let node, character;
-
-				if ( !utils.isIterable( nodes ) ) {
-					nodes = [ nodes ];
-				}
-
-				for ( node of nodes ) {
-					// Node.
-					if ( node instanceof Node ) {
-						this._nodes.push( node );
-					}
-					// Text.
-					else if ( node instanceof Text ) {
-						for ( character of node.text ) {
-							this._nodes.push( new Character( character, node.attrs ) );
-						}
-					}
-					// String.
-					else {
-						for ( character of node ) {
-							this._nodes.push( new Character( character ) );
-						}
-					}
-				}
-			}
-		}
-
-		/**
-		 * Number of nodes in the node list.
-		 *
-		 * @readonly
-		 * @property {Number} length
-		 */
-		get length() {
-			return this._nodes.length;
-		}
-
-		/**
-		 * Node list iterator.
-		 */
-		[ Symbol.iterator ]() {
-			return this._nodes[ Symbol.iterator ]();
-		}
-
-		/**
-		 * Returns node at the given index.
-		 *
-		 * @param {Number} index Node index.
-		 * @returns {document.Node} Node at given index.
-		 */
-		get( index ) {
-			return this._nodes[ index ];
-		}
-
-		/**
-		 * Search for the node in the node list.
-		 *
-		 * @param {document.Node} node Node to find.
-		 * @returns {Number} Position of the node in the list.
-		 */
-		indexOf( node ) {
-			return this._nodes.indexOf( node );
-		}
-
-		/**
-		 * Inserts nodes from the given node list into this node list at the given index.
-		 *
-		 * @param {Number} index Position where nodes should be inserted.
-		 * @param {document.NodeList} nodeList List of nodes to insert.
-		 */
-		insert( index, nodeList ) {
-			this._nodes.splice.apply( this._nodes, [ index, 0 ].concat( nodeList._nodes ) );
-		}
-
-		/**
-		 * Removes number of nodes starting at the given index.
-		 *
-		 * @param {Number} index Position of the first node to remove.
-		 * @param {Number} number Number of nodes to remove.
-		 * @returns {document.NodeList} List of removed nodes.
-		 */
-		remove( index, number ) {
-			return new NodeList( this._nodes.splice( index, number ) );
-		}
-	}
-
-	return NodeList;
-} );

+ 0 - 142
packages/ckeditor5-utils/src/document/operation/attributeoperation.js

@@ -1,142 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/operation/operation',
-	'ckeditorerror'
-], ( Operation, CKEditorError ) => {
-	/**
-	 * Operation to change nodes' attribute. Using this class you can add, remove or change value of the attribute.
-	 *
-	 * @class document.operation.AttributeOperation
-	 */
-	class AttributeOperation extends Operation {
-		/**
-		 * Creates an operation that changes, removes or adds attributes.
-		 *
-		 * If only the new attribute is set, then it will be inserted. Note that in all nodes in ranges there must be
-		 * no attributes with the same key as the new attribute.
-		 *
-		 * If only the old attribute is set, then it will be removed. Note that this attribute must be present in all nodes in
-		 * ranges.
-		 *
-		 * If both new and old attributes are set, then the operation will change the attribute value. Note that both new and
-		 * old attributes have to have the same key and the old attribute must be present in all nodes in ranges.
-		 *
-		 * @param {document.Range} range Range on which the operation should be applied.
-		 * @param {document.Attribute|null} oldAttr Attribute to be removed. If `null`, then the operation just inserts a new attribute.
-		 * @param {document.Attribute|null} newAttr Attribute to be added. If `null`, then the operation just removes the attribute.
-		 * @param {Number} baseVersion {@link document.Document#version} on which the operation can be applied.
-		 * @constructor
-		 */
-		constructor( range, oldAttr, newAttr, baseVersion ) {
-			super( baseVersion );
-
-			/**
-			 * Range on which operation should be applied.
-			 *
-			 * @readonly
-			 * @type {document.Range}
-			 */
-			this.range = range;
-
-			/**
-			 * Old attribute to change. Set to `null` if operation inserts a new attribute.
-			 *
-			 * @readonly
-			 * @type {document.Attribute|null}
-			 */
-			this.oldAttr = oldAttr;
-
-			/**
-			 * New attribute. Set to `null` if operation removes the attribute.
-			 *
-			 * @readonly
-			 * @type {document.Attribute|null}
-			 */
-			this.newAttr = newAttr;
-		}
-
-		get type() {
-			return 'attr';
-		}
-
-		clone() {
-			return new AttributeOperation( this.range.clone(), this.oldAttr, this.newAttr, this.baseVersion );
-		}
-
-		getReversed() {
-			return new AttributeOperation( this.range, this.newAttr, this.oldAttr, this.baseVersion + 1 );
-		}
-
-		_execute() {
-			const oldAttr = this.oldAttr;
-			const newAttr = this.newAttr;
-
-			if ( oldAttr !== null && newAttr !== null && oldAttr.key != newAttr.key ) {
-				/**
-				 * Old and new attributes should have the same keys.
-				 *
-				 * @error operation-attribute-different-keys
-				 * @param {document.Attribute} oldAttr
-				 * @param {document.Attribute} newAttr
-				 */
-				throw new CKEditorError(
-					'operation-attribute-different-keys: Old and new attributes should have the same keys.',
-					{ oldAttr: oldAttr, newAttr: newAttr } );
-			}
-
-			// Remove or change.
-			if ( oldAttr !== null ) {
-				for ( let node of this.range.getNodes() ) {
-					if ( !node.hasAttr( oldAttr ) ) {
-						/**
-						 * The attribute which should be removed does not exists for the given node.
-						 *
-						 * @error operation-attribute-no-attr-to-remove
-						 * @param {document.Node} node
-						 * @param {document.Attribute} attr
-						 */
-						throw new CKEditorError(
-							'operation-attribute-no-attr-to-remove: The attribute which should be removed does not exists for given node.',
-							{ node: node, attr: oldAttr } );
-					}
-
-					// There is no use in removing attribute if we will overwrite it later.
-					// Still it is profitable to run through the loop to check if all nodes in the range has old attribute.
-					if ( newAttr === null ) {
-						node.removeAttr( oldAttr.key );
-					}
-				}
-			}
-
-			// Insert or change.
-			if ( newAttr !== null ) {
-				for ( let node of this.range.getNodes() ) {
-					if ( oldAttr === null && node.hasAttr( newAttr.key ) ) {
-						/**
-						 * The attribute with given key already exists for the given node.
-						 *
-						 * @error operation-attribute-attr-exists
-						 * @param {document.Node} node
-						 * @param {document.Attribute} attr
-						 */
-						throw new CKEditorError(
-							'operation-attribute-attr-exists: The attribute with given key already exists.',
-							{ node: node, attr: newAttr } );
-					}
-
-					node.setAttr( newAttr );
-				}
-			}
-
-			return { range: this.range, oldAttr: oldAttr, newAttr: newAttr };
-		}
-	}
-
-	return AttributeOperation;
-} );

+ 0 - 74
packages/ckeditor5-utils/src/document/operation/insertoperation.js

@@ -1,74 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/operation/operation',
-	'document/nodelist',
-	'document/range',
-	'document/operation/removeoperation'
-], ( Operation, NodeList, Range ) => {
-	/**
-	 * Operation to insert list of nodes on the given position in the tree data model.
-	 *
-	 * @class document.operation.InsertOperation
-	 */
-	class InsertOperation extends Operation {
-		/**
-		 * Creates an insert operation.
-		 *
-		 * @param {document.Position} position Position of insertion.
-		 * @param {document.Node|document.Text|document.NodeList|String|Iterable} nodes The list of nodes to be inserted.
-		 * List of nodes can be any type accepted by the {@link document.NodeList} constructor.
-		 * @param {Number} baseVersion {@link document.Document#version} on which operation can be applied.
-		 * @constructor
-		 */
-		constructor( position, nodes, baseVersion ) {
-			super( baseVersion );
-
-			/**
-			 * Position of insertion.
-			 *
-			 * @readonly
-			 * @type {document.Position}
-			 */
-			this.position = position;
-
-			/**
-			 * List of nodes to insert.
-			 *
-			 * @readonly
-			 * @type {document.NodeList}
-			 */
-			this.nodeList = new NodeList( nodes );
-		}
-
-		get type() {
-			return 'insert';
-		}
-
-		clone() {
-			return new InsertOperation( this.position, this.nodeList, this.baseVersion );
-		}
-
-		getReversed() {
-			// Because of circular dependencies we need to re-require remove operation here.
-			const RemoveOperation = CKEDITOR.require( 'document/operation/removeoperation' );
-
-			return new RemoveOperation( this.position, this.nodeList.length, this.baseVersion + 1 );
-		}
-
-		_execute() {
-			this.position.parent.insertChildren( this.position.offset, this.nodeList );
-
-			return {
-				range: Range.createFromPositionAndOffset( this.position, this.nodeList.length )
-			};
-		}
-	}
-
-	return InsertOperation;
-} );

+ 0 - 138
packages/ckeditor5-utils/src/document/operation/moveoperation.js

@@ -1,138 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/operation/operation',
-	'document/range',
-	'ckeditorerror',
-	'utils'
-], ( Operation, Range, CKEditorError, utils ) => {
-	/**
-	 * Operation to move list of subsequent nodes from one position in the document to another.
-	 *
-	 * @class document.operation.MoveOperation
-	 */
-	class MoveOperation extends Operation {
-		/**
-		 * Creates a move operation.
-		 *
-		 * @param {document.Position} sourcePosition Position before the first element to move.
-		 * @param {Number} howMany How many consecutive nodes to move, starting from `sourcePosition`.
-		 * @param {document.Position} targetPosition Position where moved elements will be inserted.
-		 * @param {Number} baseVersion {@link document.Document#version} on which operation can be applied.
-		 * @constructor
-		 */
-		constructor( sourcePosition, howMany, targetPosition, baseVersion ) {
-			super( baseVersion );
-
-			/**
-			 * Source move position.
-			 *
-			 * @type {document.Position}
-			 */
-			this.sourcePosition = sourcePosition;
-
-			/**
-			 * How many nodes to move.
-			 *
-			 * @type {Number}
-			 */
-			this.howMany = howMany;
-
-			/**
-			 * Target move position.
-			 *
-			 * @type {document.Position}
-			 */
-			this.targetPosition = targetPosition;
-		}
-
-		get type() {
-			return 'move';
-		}
-
-		clone() {
-			return new MoveOperation( this.sourcePosition.clone(), this.howMany, this.targetPosition.clone(), this.baseVersion );
-		}
-
-		getReversed() {
-			return new MoveOperation( this.targetPosition.clone(), this.howMany, this.sourcePosition.clone(), this.baseVersion + 1 );
-		}
-
-		_execute() {
-			let sourceElement = this.sourcePosition.parent;
-			let targetElement = this.targetPosition.parent;
-			let sourceOffset = this.sourcePosition.offset;
-			let targetOffset = this.targetPosition.offset;
-
-			// Validate whether move operation has correct parameters.
-			// Validation is pretty complex but move operation is one of the core ways to manipulate the document state.
-			// We expect that many errors might be connected with one of scenarios described below.
-			if ( !sourceElement || !targetElement ) {
-				/**
-				 * Source position or target position is invalid.
-				 *
-				 * @error operation-move-position-invalid
-				 */
-				throw new CKEditorError(
-					'operation-move-position-invalid: Source position or target position is invalid.'
-				);
-			} else if ( sourceOffset + this.howMany > sourceElement.getChildCount() ) {
-				/**
-				 * The nodes which should be moved do not exist.
-				 *
-				 * @error operation-move-nodes-do-not-exist
-				 */
-				throw new CKEditorError(
-					'operation-move-nodes-do-not-exist: The nodes which should be moved do not exist.'
-				);
-			} else if ( sourceElement === targetElement && sourceOffset <= targetOffset && targetOffset < sourceOffset + this.howMany ) {
-				/**
-				 * Trying to move a range of nodes into the middle of that range.
-				 *
-				 * @error operation-move-range-into-itself
-				 */
-				throw new CKEditorError(
-					'operation-move-range-into-itself: Trying to move a range of nodes to the inside of that range.'
-				);
-			} else {
-				if ( utils.compareArrays( this.sourcePosition.getParentPath(), this.targetPosition.getParentPath() ) == utils.compareArrays.PREFIX ) {
-					let i = this.sourcePosition.path.length - 1;
-
-					if ( this.targetPosition.path[ i ] >= sourceOffset && this.targetPosition.path[ i ] < sourceOffset + this.howMany ) {
-						/**
-						 * Trying to move a range of nodes into one of nodes from that range.
-						 *
-						 * @error operation-move-node-into-itself
-						 */
-						throw new CKEditorError(
-							'operation-move-node-into-itself: Trying to move a range of nodes into one of nodes from that range.'
-						);
-					}
-				}
-			}
-			// End of validation.
-
-			// If we move children in the same element and we remove elements on the position before the target we
-			// need to update a target offset.
-			if ( sourceElement === targetElement && sourceOffset < targetOffset ) {
-				targetOffset -= this.howMany;
-			}
-
-			const removedNodes = sourceElement.removeChildren( sourceOffset, this.howMany );
-
-			targetElement.insertChildren( targetOffset, removedNodes );
-
-			return {
-				sourcePosition: this.sourcePosition,
-				range: Range.createFromPositionAndOffset( this.targetPosition, this.howMany )
-			};
-		}
-	}
-
-	return MoveOperation;
-} );

+ 0 - 37
packages/ckeditor5-utils/src/document/operation/nooperation.js

@@ -1,37 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/operation/operation'
-], ( Operation ) => {
-	/**
-	 * Operation which is doing nothing ("empty operation", "do-nothing operation", "noop").
-	 * This is an operation, which when executed does not change the tree model.
-	 * It still has some parameters defined for transformation purposes.
-	 *
-	 * In most cases this operation is a result of transforming operations. When transformation returns
-	 * {@link document.operation.NoOperation} it means that changes done by the transformed operation
-	 * have already been applied.
-	 *
-	 * @class document.operation.NoOperation
-	 */
-	class NoOperation extends Operation {
-		clone() {
-			return new NoOperation( this.baseVersion );
-		}
-
-		getReversed() {
-			return new NoOperation( this.baseVersion + 1 );
-		}
-
-		_execute() {
-			// Do nothing.
-		}
-	}
-
-	return NoOperation;
-} );

+ 0 - 80
packages/ckeditor5-utils/src/document/operation/operation.js

@@ -1,80 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [], () => {
-	/**
-	 * Abstract base operation class.
-	 *
-	 * @abstract
-	 * @class document.operation.Operation
-	 */
-	class Operation {
-		/**
-		 * Base operation constructor.
-		 *
-		 * @param {Number} baseVersion {@link document.Document#version} on which the operation can be applied.
-		 * @constructor
-		 */
-		constructor( baseVersion ) {
-			/**
-			 * {@link document.Document#version} on which operation can be applied. If you try to
-			 * {@link document.Document#applyOperation apply} operation with different base version than the
-			 * {@link document.Document#version document version} the {@link document-applyOperation-wrong-version}
-			 * error is thrown.
-			 *
-			 * @property {Number}
-			 */
-			this.baseVersion = baseVersion;
-
-			/**
-			 * Operation type.
-			 *
-			 * @property {String} type
-			 */
-
-			/**
-			 * {@link Document.Delta Delta} which the operation is a part of. This property is set by the
-			 * {@link Document.Delta delta} when the operations is added to it by the
-			 * {@link Document.Delta#addOperation} method.
-			 *
-			 * @property {Document.Delta} delta
-			 */
-
-			/**
-			 * Creates and returns an operation that has the same parameters as this operation.
-			 *
-			 * @method clone
-			 * @returns {document.operation.Operation} Clone of this operation.
-			 */
-
-			/**
-			 * Creates and returns a reverse operation. Reverse operation when executed right after
-			 * the original operation will bring back tree model state to the point before the original
-			 * operation execution. In other words, it reverses changes done by the original operation.
-			 *
-			 * Keep in mind that tree model state may change since executing the original operation,
-			 * so reverse operation will be "outdated". In that case you will need to
-			 * {@link document.operation.transform} it by all operations that were executed after the original operation.
-			 *
-			 * @method getReversed
-			 * @returns {document.operation.Operation} Reversed operation.
-			 */
-
-			/**
-			 * Executes the operation - modifications described by the operation attributes
-			 * will be applied to the tree model.
-			 *
-			 * @protected
-			 * @method _execute
-			 * @returns {Object} Object with additional information about the applied changes. Always has `range`
-			 * property containing changed nodes. May have additional properties depending on the operation type.
-			 */
-		}
-	}
-
-	return Operation;
-} );

+ 0 - 37
packages/ckeditor5-utils/src/document/operation/reinsertoperation.js

@@ -1,37 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/operation/moveoperation',
-	'document/operation/removeoperation'
-], ( MoveOperation ) => {
-	/**
-	 * Operation to reinsert previously removed nodes back to the non-graveyard root.
-	 * This is basically {@link document.operation.MoveOperation} but it returns
-	 * {@link document.operation.RemoveOperation} when reversed.
-	 *
-	 * With this class, we achieve two goals: by having separate classes it's easier to distinguish whether move
-	 * operation is actually a remove/reinsert operation and fire proper events. Also it
-	 * will be easier to expand if we need to change operation's behavior if it is remove/reinsert.
-	 *
-	 * @class document.operation.ReinsertOperation
-	 */
-	class ReinsertOperation extends MoveOperation {
-		getReversed() {
-			// Because of circular dependencies we need to re-require reinsert operation here.
-			const RemoveOperation = CKEDITOR.require( 'document/operation/removeoperation' );
-
-			return new RemoveOperation( this.targetPosition, this.howMany, this.baseVersion + 1 );
-		}
-
-		get type() {
-			return 'reinsert';
-		}
-	}
-
-	return ReinsertOperation;
-} );

+ 0 - 49
packages/ckeditor5-utils/src/document/operation/removeoperation.js

@@ -1,49 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/operation/moveoperation',
-	'document/position',
-	'document/operation/reinsertoperation'
-], ( MoveOperation, Position ) => {
-	/**
-	 * Operation to remove a range of nodes.
-	 *
-	 * @class document.operation.RemoveOperation
-	 */
-	class RemoveOperation extends MoveOperation {
-		/**
-		 * Creates a remove operation.
-		 *
-		 * @param {document.Position} position Position before the first node to remove.
-		 * @param {Number} howMany How many nodes to remove.
-		 * @param {Number} baseVersion {@link document.Document#version} on which operation can be applied.
-		 * @constructor
-		 */
-		constructor( position, howMany, baseVersion ) {
-			const graveyard = position.root.document._graveyard;
-
-			// Position in a graveyard where nodes were moved.
-			const graveyardPosition = Position.createFromParentAndOffset( graveyard, 0 );
-
-			super( position, howMany, graveyardPosition, baseVersion );
-		}
-
-		get type() {
-			return 'remove';
-		}
-
-		getReversed() {
-			// Because of circular dependencies we need to re-require reinsert operation here.
-			const ReinsertOperation = CKEDITOR.require( 'document/operation/reinsertoperation' );
-
-			return new ReinsertOperation( this.targetPosition, this.howMany, this.sourcePosition, this.baseVersion + 1 );
-		}
-	}
-
-	return RemoveOperation;
-} );

+ 0 - 422
packages/ckeditor5-utils/src/document/operation/transform.js

@@ -1,422 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-/**
- * Transforms given {document.operation.Operation} by another {document.operation.Operation} and returns the result of
- * that transformation as an array containing one or more {document.operation.Operation} elements.
- *
- * Operations work on specified positions, passed to them when they are created. Whenever {@link document.Document document}
- * changes, we have to reflect those modifications by updating or "transforming" operations which are not yet applied.
- * When an operation is transformed, its parameters may change based on the operation by which it is transformed.
- * If the transform-by operation applied any modifications to the Tree Data Model which affect positions or nodes
- * connected with transformed operation, those changes will be reflected in the parameters of the returned operation(s).
- *
- * Whenever the {@link document.Document document} has different {@link document.Document#baseVersion}
- * than the operation you want to {@link document.Document#applyOperation apply}, you need to transform that
- * operation by all operations which were already applied to the {@link document.Document document} and have greater
- * {@link document.Document#baseVersion} than the operation being applied. Transform them in the same order as those
- * operations which were applied. This way all modifications done to the Tree Data Model will be reflected
- * in the operation parameters and the operation will "operate" on "up-to-date" version of the Tree Data Model.
- * This is mostly the case with Operational Transformations but it might be needed in particular features as well.
- *
- * In some cases, when given operation apply changes to the same nodes as this operation, two or more operations need
- * to be created as one would not be able to reflect the combination of these operations.
- * This is why an array is returned instead of a single object. All returned operations have to be applied
- * (or further transformed) to get an effect which was intended in pre-transformed operation.
- *
- * Sometimes two operations are in conflict. This happens when they modify the same node in a different way, i.e.
- * set different value for the same attribute or move the node into different positions. When this happens,
- * we need to decide which operation is more important. We can't assume that operation `a` or operation `b` is always
- * more important. In Operational Transformations algorithms we often need to get a result of transforming
- * `a` by `b` and also `b` by `a`. In both transformations the same operation has to be the important one. If we assume
- * that first or the second passed operation is always more important we won't be able to solve this case.
- *
- * @function document.operation.transform
- * @param {document.operation.Operation} a Operation that will be transformed.
- * @param {document.operation.Operation} b Operation to transform by.
- * @param {Boolean} isAMoreImportantThanB Flag indicating whether the operation which will be transformed (`a`) should be treated
- * as more important when resolving conflicts.
- * @returns {Array.<document.operation.Operation>} Result of the transformation.
- */
-
-CKEDITOR.define( [
-	'document/operation/insertoperation',
-	'document/operation/attributeoperation',
-	'document/operation/moveoperation',
-	'document/operation/nooperation',
-	'document/range',
-	'utils'
-], ( InsertOperation, AttributeOperation, MoveOperation, NoOperation, Range, utils ) => {
-	const ot = {
-		InsertOperation: {
-			// Transforms InsertOperation `a` by InsertOperation `b`. Accepts a flag stating whether `a` is more important
-			// than `b` when it comes to resolving conflicts. Returns results as an array of operations.
-			InsertOperation( a, b, isStrong ) {
-				// Transformed operations are always new instances, not references to the original operations.
-				const transformed = a.clone();
-
-				// Transform insert position by the other operation position.
-				transformed.position = transformed.position.getTransformedByInsertion( b.position, b.nodeList.length, !isStrong );
-
-				return [ transformed ];
-			},
-
-			AttributeOperation: doNotUpdate,
-
-			// Transforms InsertOperation `a` by MoveOperation `b`. Accepts a flag stating whether `a` is more important
-			// than `b` when it comes to resolving conflicts. Returns results as an array of operations.
-			MoveOperation( a, b, isStrong ) {
-				const transformed = a.clone();
-
-				// Transform insert position by the other operation parameters.
-				transformed.position = a.position.getTransformedByMove( b.sourcePosition, b.targetPosition, b.howMany, !isStrong );
-
-				return [ transformed ];
-			}
-		},
-
-		AttributeOperation: {
-			// Transforms AttributeOperation `a` by InsertOperation `b`. Returns results as an array of operations.
-			InsertOperation( a, b ) {
-				// Transform this operation's range.
-				const ranges = a.range.getTransformedByInsertion( b.position, b.nodeList.length );
-
-				// Map transformed range(s) to operations and return them.
-				return ranges.reverse().map( ( range ) => {
-					return new AttributeOperation(
-						range,
-						a.oldAttr,
-						a.newAttr,
-						a.baseVersion
-					);
-				} );
-			},
-
-			// Transforms AttributeOperation `a` by AttributeOperation `b`. Accepts a flag stating whether `a` is more important
-			// than `b` when it comes to resolving conflicts. Returns results as an array of operations.
-			AttributeOperation( a, b, isStrong ) {
-				if ( haveConflictingAttributes( a, b ) ) {
-					// If operations attributes are in conflict, check if their ranges intersect and manage them properly.
-					let operations = [];
-
-					// First, we want to apply change to the part of a range that has not been changed by the other operation.
-					operations = operations.concat(
-						a.range.getDifference( b.range ).map( ( range ) => {
-							return new AttributeOperation( range, a.oldAttr, a.newAttr, a.baseVersion );
-						} )
-					);
-
-					if ( isStrong ) {
-						// If this operation is more important, we want also want to apply change to the part of the
-						// original range that has already been changed by the other operation. Since that range
-						// got changed we have to update oldAttr.
-						const common = a.range.getIntersection( b.range );
-
-						if ( common !== null ) {
-							operations.push( new AttributeOperation( common, b.oldAttr, a.newAttr, a.baseVersion ) );
-						}
-					}
-
-					// If no operations has been added nothing should get updated, but since we need to return
-					// an instance of Operation we add NoOperation to the array.
-					if ( operations.length === 0 ) {
-						operations.push( new NoOperation( a.baseVersion ) );
-					}
-
-					return operations;
-				} else {
-					// If operations don't conflict simply, return an array containing just a clone of this operation.
-					return [ a.clone() ];
-				}
-			},
-
-			// Transforms AttributeOperation `a` by MoveOperation `b`. Returns results as an array of operations.
-			MoveOperation( a, b ) {
-				// Convert MoveOperation properties into a range.
-				const rangeB = Range.createFromPositionAndOffset( b.sourcePosition, b.howMany );
-
-				// Get target position from the state "after" nodes specified by MoveOperation are "detached".
-				const newTargetPosition = b.targetPosition.getTransformedByDeletion( b.sourcePosition, b.howMany );
-
-				// This will aggregate transformed ranges.
-				let ranges = [];
-
-				// Difference is a part of changed range that is modified by AttributeOperation but are not affected
-				// by MoveOperation. This can be zero, one or two ranges (if moved range is inside changed range).
-				// If two ranges were returned it means that rangeB was inside rangeA. We will cover rangeB later.
-				// Right now we will make a simplification and join difference ranges and transform them as one.
-				const difference = joinRanges( a.range.getDifference( rangeB ) );
-
-				// Common is a range of nodes that is affected by MoveOperation. So it got moved to other place.
-				const common = a.range.getIntersection( rangeB );
-
-				if ( difference !== null ) {
-					// MoveOperation removes nodes from their original position. We acknowledge this by proper transformation.
-					// Take the start and the end of the range and transform them by deletion of moved nodes.
-					// Note that if rangeB was inside AttributeOperation range, only difference.end will be transformed.
-					// This nicely covers the joining simplification we did in the previous step.
-					difference.start = difference.start.getTransformedByDeletion( b.sourcePosition, b.howMany );
-					difference.end = difference.end.getTransformedByDeletion( b.sourcePosition, b.howMany );
-
-					// MoveOperation pastes nodes into target position. We acknowledge this by proper transformation.
-					// Note that since we operate on transformed difference range, we should transform by
-					// previously transformed target position.
-					// Note that we do not use Position.getTransformedByMove on range boundaries because we need to
-					// transform by insertion a range as a whole, since newTargetPosition might be inside that range.
-					ranges = difference.getTransformedByInsertion( newTargetPosition, b.howMany, false ).reverse();
-				}
-
-				if ( common !== null ) {
-					// Here we do not need to worry that newTargetPosition is inside moved range, because that
-					// would mean that the MoveOperation targets into itself, and that is incorrect operation.
-					// Instead, we calculate the new position of that part of original range.
-					common.start = common.start._getCombined( b.sourcePosition, newTargetPosition );
-					common.end = common.end._getCombined( b.sourcePosition, newTargetPosition );
-
-					ranges.push( common );
-				}
-
-				// Map transformed range(s) to operations and return them.
-				return ranges.map( ( range ) => {
-					return new AttributeOperation(
-						range,
-						a.oldAttr,
-						a.newAttr,
-						a.baseVersion
-					);
-				} );
-			}
-		},
-
-		MoveOperation: {
-			// Transforms MoveOperation `a` by InsertOperation `b`. Accepts a flag stating whether `a` is more important
-			// than `b` when it comes to resolving conflicts. Returns results as an array of operations.
-			InsertOperation( a, b, isStrong ) {
-				// Get target position from the state "after" nodes are inserted by InsertOperation.
-				const newTargetPosition = a.targetPosition.getTransformedByInsertion( b.position, b.nodeList.length, !isStrong );
-
-				// Create range from MoveOperation properties and transform it by insertion as well.
-				const rangeB = Range.createFromPositionAndOffset( a.sourcePosition, a.howMany );
-				const ranges = rangeB.getTransformedByInsertion( b.position, b.nodeList.length, true );
-
-				// Map transformed range(s) to operations and return them.
-				return ranges.reverse().map( ( range ) => {
-					return new MoveOperation(
-						range.start,
-						range.end.offset - range.start.offset,
-						newTargetPosition.clone(),
-						a.baseVersion
-					);
-				} );
-			},
-
-			AttributeOperation: doNotUpdate,
-
-			// Transforms MoveOperation `a` by MoveOperation `b`. Accepts a flag stating whether `a` is more important
-			// than `b` when it comes to resolving conflicts. Returns results as an array of operations.
-			MoveOperation( a, b, isStrong ) {
-				// Special case when both move operations' target positions are inside nodes that are
-				// being moved by the other move operation. So in other words, we move ranges into inside of each other.
-				// This case can't be solved reasonably (on the other hand, it should not happen often).
-				if ( moveTargetIntoMovedRange( a, b ) && moveTargetIntoMovedRange( b, a ) ) {
-					// Instead of transforming operation, we return a reverse of the operation that we transform by.
-					// So when the results of this "transformation" will be applied, `b` MoveOperation will get reversed.
-					return [ b.getReversed() ];
-				}
-
-				// Create ranges from MoveOperations properties.
-				const rangeA = Range.createFromPositionAndOffset( a.sourcePosition, a.howMany );
-				const rangeB = Range.createFromPositionAndOffset( b.sourcePosition, b.howMany );
-
-				// Special case when transformed range contains both the other operation's whole range and target.
-				// In such case, operations are not really conflicting and we should leave transformed operation as it is.
-				// Without this we would have 3 or 4 operations and the transformation result would probably be not intuitive.
-				if ( rangeA.containsRange( rangeB ) && rangeA.containsPosition( b.targetPosition ) ) {
-					return [ a.clone() ];
-				}
-				// Mirror situation for the case above - now transformed range is wholly contained in the other
-				// operation's range and also targets to that range. Without this special treatment we would
-				// transform this operation into NoOperation, but this would not be compatible with the result
-				// generated by the special case above.
-				else if ( rangeB.containsRange( rangeA ) && rangeB.containsPosition( a.targetPosition ) ) {
-					return [
-						new MoveOperation(
-							a.sourcePosition._getCombined( b.sourcePosition, b.targetPosition ),
-							a.howMany,
-							a.targetPosition._getCombined( b.sourcePosition, b.targetPosition ),
-							a.baseVersion
-						)
-					];
-				}
-
-				// All the other non-special cases are treated by generic algorithm below.
-
-				const differenceSet = rangeA.getDifference( rangeB );
-				const common = rangeA.getIntersection( rangeB );
-
-				// This will aggregate transformed ranges.
-				let ranges = [];
-
-				// Get target position from the state "after" nodes specified by other MoveOperation are "detached".
-				const moveTargetPosition = b.targetPosition.getTransformedByDeletion( b.sourcePosition, b.howMany );
-
-				// First, we take care of that part of the range that is only modified by transformed operation.
-				for ( let i = 0; i < differenceSet.length; i++ ) {
-					// MoveOperation removes nodes from their original position. We acknowledge this by proper transformation.
-					// Take the start and the end of the range and transform them by deletion of moved nodes.
-					differenceSet[ i ].start = differenceSet[ i ].start.getTransformedByDeletion( b.sourcePosition, b.howMany );
-					differenceSet[ i ].end = differenceSet[ i ].end.getTransformedByDeletion( b.sourcePosition, b.howMany );
-
-					// MoveOperation pastes nodes into target position. We acknowledge this by proper transformation.
-					// Note that since we operate on transformed difference range, we should transform by
-					// previously transformed target position.
-					// Note that we do not use Position.getTransformedByMove on range boundaries because we need to
-					// transform by insertion a range as a whole, since newTargetPosition might be inside that range.
-					ranges = ranges.concat( differenceSet[ i ].getTransformedByInsertion( moveTargetPosition, b.howMany, true ) );
-				}
-
-				// Then, we have to manage the common part of both move ranges.
-				// If MoveOperations has common range it can be one of two:
-				// * on the same tree level - it means that we move the same nodes into different places
-				// * on deeper tree level - it means that we move nodes that are inside moved nodes
-				// The operations are conflicting only if they try to move exactly same nodes, so only in the first case.
-				// So, we will handle common range if it is "deeper" or if transformed operation is more important.
-				let isDeeper = utils.compareArrays( b.sourcePosition.getParentPath(), a.sourcePosition.getParentPath() ) == utils.compareArrays.PREFIX;
-
-				if ( common !== null && ( isDeeper || isStrong ) ) {
-					// Here we do not need to worry that newTargetPosition is inside moved range, because that
-					// would mean that the MoveOperation targets into itself, and that is incorrect operation.
-					// Instead, we calculate the new position of that part of original range.
-					common.start = common.start._getCombined( b.sourcePosition, moveTargetPosition );
-					common.end = common.end._getCombined( b.sourcePosition, moveTargetPosition );
-
-					// We have to take care of proper range order.
-					// Note that both push, splice and unshift do the same if there are no ranges in the array.
-					if ( rangeB.end.isAfter( rangeA.end ) ) {
-						ranges.push( common );
-					} else if ( rangeB.start.isBefore( rangeA.start ) ) {
-						ranges.unshift( common );
-					} else {
-						ranges.splice( 1, 0, common );
-					}
-				}
-
-				// At this point we transformed this operation's source ranges it means that nothing should be changed.
-				// But since we need to return an instance of Operation we return an array with NoOperation.
-				if ( ranges.length === 0 ) {
-					return [ new NoOperation( a.baseVersion ) ];
-				}
-
-				// Target position also could be affected by the other MoveOperation. We will transform it.
-				let newTargetPosition = a.targetPosition.getTransformedByMove( b.sourcePosition, moveTargetPosition, b.howMany, !isStrong );
-
-				// Map transformed range(s) to operations and return them.
-				return ranges.reverse().map( ( range ) => {
-					return new MoveOperation(
-						range.start,
-						range.end.offset - range.start.offset,
-						newTargetPosition,
-						a.baseVersion
-					);
-				} );
-			}
-		}
-	};
-
-	return ( a, b, isStrong ) => {
-		let group;
-		let algorithm;
-
-		if ( a instanceof InsertOperation ) {
-			group = ot.InsertOperation;
-		} else if ( a instanceof AttributeOperation ) {
-			group = ot.AttributeOperation;
-		} else if ( a instanceof MoveOperation ) {
-			group = ot.MoveOperation;
-		} else {
-			algorithm = doNotUpdate;
-		}
-
-		if ( group ) {
-			if ( b instanceof InsertOperation ) {
-				algorithm = group.InsertOperation;
-			} else if ( b instanceof AttributeOperation ) {
-				algorithm = group.AttributeOperation;
-			} else if ( b instanceof MoveOperation ) {
-				algorithm = group.MoveOperation;
-			} else {
-				algorithm = doNotUpdate;
-			}
-		}
-
-		let transformed = algorithm( a, b, isStrong );
-
-		return updateBaseVersions( a.baseVersion, transformed );
-	};
-
-	// When we don't want to update an operation, we create and return a clone of it.
-	// Returns the operation in "unified format" - wrapped in an Array.
-	function doNotUpdate( operation ) {
-		return [ operation.clone() ];
-	}
-
-	// Takes an Array of operations and sets consecutive base versions for them, starting from given base version.
-	// Returns the passed array.
-	function updateBaseVersions( baseVersion, operations ) {
-		for ( let i = 0; i < operations.length; i++ ) {
-			operations[ i ].baseVersion = baseVersion + i + 1;
-		}
-
-		return operations;
-	}
-
-	// Checks whether MoveOperation targetPosition is inside a node from the moved range of the other MoveOperation.
-	function moveTargetIntoMovedRange( a, b ) {
-		return a.targetPosition.getTransformedByDeletion( b.sourcePosition, b.howMany ) === null;
-	}
-
-	// Takes two AttributeOperations and checks whether their attributes are in conflict.
-	// This happens when both operations changes an attribute with the same key and they either set different
-	// values for this attribute or one of them removes it while the other one sets it.
-	// Returns true if attributes are in conflict.
-	function haveConflictingAttributes( a, b ) {
-		// Keeping in mind that newAttr or oldAttr might be null.
-		// We will retrieve the key from whichever parameter is set.
-		const keyA = ( a.newAttr || a.oldAttr ).key;
-		const keyB = ( b.newAttr || b.oldAttr ).key;
-
-		if ( keyA != keyB ) {
-			// Different keys - not conflicting.
-			return false;
-		}
-
-		if ( a.newAttr === null && b.newAttr === null ) {
-			// Both remove the attribute - not conflicting.
-			return false;
-		}
-
-		// Check if they set different value or one of them removes the attribute.
-		return ( a.newAttr === null && b.newAttr !== null ) ||
-			( a.newAttr !== null && b.newAttr === null ) ||
-			( !a.newAttr.isEqual( b.newAttr ) );
-	}
-
-	// Gets an array of Ranges and produces one Range out of it. The root of a new range will be same as
-	// the root of the first range in the array. If any of given ranges has different root than the first range,
-	// it will be discarded.
-	function joinRanges( ranges ) {
-		if ( ranges.length === 0 ) {
-			return null;
-		} else if ( ranges.length == 1 ) {
-			return ranges[ 0 ];
-		} else {
-			ranges[ 0 ].end = ranges[ ranges.length - 1 ].end;
-
-			return ranges[ 0 ];
-		}
-	}
-} );

+ 0 - 490
packages/ckeditor5-utils/src/document/position.js

@@ -1,490 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [ 'document/rootelement', 'utils', 'ckeditorerror' ], ( RootElement, utils, CKEditorError ) => {
-	const SAME = 0;
-	const AFTER = 1;
-	const BEFORE = 2;
-	const DIFFERENT = 3;
-
-	/**
-	 * Position in the tree. Position is always located before or after a node.
-	 * See {@link #path} property for more information.
-	 *
-	 * @class document.Position
-	 */
-	class Position {
-		/**
-		 * Creates a position.
-		 *
-		 * @param {document.RootElement} root Root element for the path. Note that this element can not have a parent.
-		 * @param {Array.<Number>} path Position path. Must contain at least one item. See {@link #path} property for more information.
-		 * @constructor
-		 */
-		constructor( root, path ) {
-			if ( !( root instanceof RootElement ) ) {
-				/**
-				 * Position root has to be an instance of RootElement.
-				 *
-				 * @error position-root-not-rootelement
-				 * @param root
-				 */
-				throw new CKEditorError( 'position-root-not-rootelement: Position root has to be an instance of RootElement.', { root: root } );
-			}
-
-			/**
-			 * Root element for the path. Note that this element can not have a parent.
-			 *
-			 * @type {document.RootElement}
-			 */
-			this.root = root;
-
-			if ( !( path instanceof Array ) || path.length === 0 ) {
-				/**
-				 * Position path must be an Array with at least one item.
-				 *
-				 * @error position-path-incorrect
-				 * @param path
-				 */
-				throw new CKEditorError( 'position-path-incorrect: Position path must be an Array with at least one item.', { path: path } );
-			}
-
-			/**
-			 * Position of the node it the tree. For example:
-			 *
-			 * root
-			 *  |- p         Before: [ 0 ]       After: [ 1 ]
-			 *  |- ul        Before: [ 1 ]       After: [ 2 ]
-			 *     |- li     Before: [ 1, 0 ]    After: [ 1, 1 ]
-			 *     |  |- f   Before: [ 1, 0, 0 ] After: [ 1, 0, 1 ]
-			 *     |  |- o   Before: [ 1, 0, 1 ] After: [ 1, 0, 2 ]
-			 *     |  |- o   Before: [ 1, 0, 2 ] After: [ 1, 0, 3 ]
-			 *     |- li     Before: [ 1, 1 ]    After: [ 1, 2 ]
-			 *        |- b   Before: [ 1, 1, 0 ] After: [ 1, 1, 1 ]
-			 *        |- a   Before: [ 1, 1, 1 ] After: [ 1, 1, 2 ]
-			 *        |- r   Before: [ 1, 1, 2 ] After: [ 1, 1, 3 ]
-			 *
-			 * @type {Number[]}
-			 */
-			this.path = path;
-		}
-
-		/**
-		 * Node directly after the position.
-		 *
-		 * @readonly
-		 * @property {document.Node}
-		 */
-		get nodeAfter() {
-			return this.parent.getChild( this.offset ) || null;
-		}
-
-		/**
-		 * Node directly before the position.
-		 *
-		 * @readonly
-		 * @type {document.Node}
-		 */
-		get nodeBefore() {
-			return this.parent.getChild( this.offset - 1 ) || null;
-		}
-
-		/**
-		 * Offset at which the position is located in the {@link #parent}.
-		 *
-		 * @readonly
-		 * @property {Number} offset
-		 */
-		get offset() {
-			return utils.last( this.path );
-		}
-
-		/**
-		 * Sets offset in the parent, which is the last element of the path.
-		 */
-		set offset( newOffset ) {
-			this.path[ this.path.length - 1 ] = newOffset;
-		}
-
-		/**
-		 * Parent element of the position. The position is located at {@link #offset} in this element.
-		 *
-		 * @readonly
-		 * @property {document.Element} parent
-		 */
-		get parent() {
-			let parent = this.root;
-
-			let i, len;
-
-			for ( i = 0, len = this.path.length - 1; i < len; i++ ) {
-				parent = parent.getChild( this.path[ i ] );
-			}
-
-			return parent;
-		}
-
-		/**
-		 * Creates and returns a new instance of {@link document.Position}
-		 * which is equal to this {@link document.Position position}.
-		 *
-		 * @returns {document.Position} Cloned {@link document.Position position}.
-		 */
-		clone() {
-			return new Position( this.root, this.path.slice() );
-		}
-
-		/**
-		 * Checks whether this position is before or after given position.
-		 *
-		 * @param {document.Position} otherPosition Position to compare with.
-		 * @returns {Number} A flag indicating whether this position is {@link #BEFORE} or
-		 * {@link #AFTER} or {@link #SAME} as given position. If positions are in different roots,
-		 * {@link #DIFFERENT} flag is returned.
-		 */
-		compareWith( otherPosition ) {
-			if ( this.root != otherPosition.root ) {
-				return DIFFERENT;
-			}
-
-			const result = utils.compareArrays( this.path, otherPosition.path );
-
-			switch ( result ) {
-				case utils.compareArrays.SAME:
-					return SAME;
-
-				case utils.compareArrays.PREFIX:
-					return BEFORE;
-
-				case utils.compareArrays.EXTENSION:
-					return AFTER;
-
-				default:
-					if ( this.path[ result ] < otherPosition.path[ result ] ) {
-						return BEFORE;
-					} else {
-						return AFTER;
-					}
-			}
-		}
-
-		/**
-		 * Returns the path to the parent, which is the {@link document.Position#path} without the last element.
-		 *
-		 * This method returns the parent path even if the parent does not exists.
-		 *
-		 * @returns {Number[]} Path to the parent.
-		 */
-		getParentPath() {
-			return this.path.slice( 0, -1 );
-		}
-
-		/**
-		 * Returns this position after being updated by removing `howMany` nodes starting from `deletePosition`.
-		 * It may happen that this position is in a removed node. If that is the case, `null` is returned instead.
-		 *
-		 * @param {document.Position} deletePosition Position before the first removed node.
-		 * @param {Number} howMany How many nodes are removed.
-		 * @returns {document.Position|null} Transformed position or `null`.
-		 */
-		getTransformedByDeletion( deletePosition, howMany ) {
-			let transformed = this.clone();
-
-			// This position can't be affected if deletion was in a different root.
-			if ( this.root != deletePosition.root ) {
-				return transformed;
-			}
-
-			if ( utils.compareArrays( deletePosition.getParentPath(), this.getParentPath() ) == utils.compareArrays.SAME ) {
-				// If nodes are removed from the node that is pointed by this position...
-				if ( deletePosition.offset < this.offset ) {
-					// And are removed from before an offset of that position...
-					// Decrement the offset accordingly.
-					if ( deletePosition.offset + howMany > this.offset ) {
-						transformed.offset = deletePosition.offset;
-					} else {
-						transformed.offset -= howMany;
-					}
-				}
-			} else if ( utils.compareArrays( deletePosition.getParentPath(), this.getParentPath() ) == utils.compareArrays.PREFIX ) {
-				// If nodes are removed from a node that is on a path to this position...
-				const i = deletePosition.path.length - 1;
-
-				if ( deletePosition.offset < this.path[ i ] ) {
-					// And are removed from before next node of that path...
-					if ( deletePosition.offset + howMany > this.path[ i ] ) {
-						// If the next node of that path is removed return null
-						// because the node containing this position got removed.
-						return null;
-					} else {
-						// Otherwise, decrement index on that path.
-						transformed.path[ i ] -= howMany;
-					}
-				}
-			}
-
-			return transformed;
-		}
-
-		/**
-		 * Returns this position after being updated by inserting `howMany` nodes at `insertPosition`.
-		 *
-		 * @param {document.Position} insertPosition Position where nodes are inserted.
-		 * @param {Number} howMany How many nodes are inserted.
-		 * @param {Boolean} insertBefore Flag indicating whether nodes are inserted before or after `insertPosition`.
-		 * This is important only when `insertPosition` and this position are same. If that is the case and the flag is
-		 * set to `true`, this position will get transformed. If the flag is set to `false`, it won't.
-		 * @returns {document.Position} Transformed position.
-		 */
-		getTransformedByInsertion( insertPosition, howMany, insertBefore ) {
-			let transformed = this.clone();
-
-			// This position can't be affected if insertion was in a different root.
-			if ( this.root != insertPosition.root ) {
-				return transformed;
-			}
-
-			if ( utils.compareArrays( insertPosition.getParentPath(), this.getParentPath() ) == utils.compareArrays.SAME ) {
-				// If nodes are inserted in the node that is pointed by this position...
-				if ( insertPosition.offset < this.offset || ( insertPosition.offset == this.offset && insertBefore ) ) {
-					// And are inserted before an offset of that position...
-					// "Push" this positions offset.
-					transformed.offset += howMany;
-				}
-			} else if ( utils.compareArrays( insertPosition.getParentPath(), this.getParentPath() ) == utils.compareArrays.PREFIX ) {
-				// If nodes are inserted in a node that is on a path to this position...
-				const i = insertPosition.path.length - 1;
-
-				if ( insertPosition.offset <= this.path[ i ] ) {
-					// And are inserted before next node of that path...
-					// "Push" the index on that path.
-					transformed.path[ i ] += howMany;
-				}
-			}
-
-			return transformed;
-		}
-
-		/**
-		 * Returns this position after being updated by moving `howMany` attributes from `sourcePosition` to `targetPosition`.
-		 *
-		 * @param {document.Position} sourcePosition Position before the first element to move.
-		 * @param {document.Position} targetPosition Position where moved elements will be inserted.
-		 * @param {Number} howMany How many consecutive nodes to move, starting from `sourcePosition`.
-		 * @param {Boolean} insertBefore Flag indicating whether moved nodes are pasted before or after `insertPosition`.
-		 * This is important only when `targetPosition` and this position are same. If that is the case and the flag is
-		 * set to `true`, this position will get transformed by range insertion. If the flag is set to `false`, it won't.
-		 * @returns {document.Position} Transformed position.
-		 */
-		getTransformedByMove( sourcePosition, targetPosition, howMany, insertBefore ) {
-			// Moving a range removes nodes from their original position. We acknowledge this by proper transformation.
-			let transformed = this.getTransformedByDeletion( sourcePosition, howMany );
-
-			if ( transformed !== null ) {
-				// This position is not inside a removed node.
-				// Next step is to reflect pasting nodes, which might further affect the position.
-				transformed = transformed.getTransformedByInsertion( targetPosition, howMany, insertBefore );
-			} else {
-				// This position is inside a removed node. In this case, we are unable to simply transform it by range insertion.
-				// Instead, we calculate a combination of this position, move source position and target position.
-				transformed = this._getCombined( sourcePosition, targetPosition );
-			}
-
-			return transformed;
-		}
-
-		/**
-		 * Checks whether this position is after given position.
-		 *
-		 * **Note:** see {document.Position#isBefore}.
-		 *
-		 * @param {document.Position} otherPosition Position to compare with.
-		 * @returns {Boolean} True if this position is after given position.
-		 */
-		isAfter( otherPosition ) {
-			return this.compareWith( otherPosition ) == AFTER;
-		}
-
-		/**
-		 * Checks whether this position is before given position.
-		 *
-		 * **Note:** watch out when using negation of the value returned by this method, because the negation will also
-		 * be `true` if positions are in different roots and you might not expect this. You should probably use
-		 * `a.isAfter( b ) || a.isEqual( b )` or `!a.isBefore( p ) && a.root == b.root` in most scenarios. If your
-		 * condition uses multiple `isAfter` and `isBefore` checks, build them so they do not use negated values, i.e.:
-		 *
-		 *  if ( a.isBefore( b ) && c.isAfter( d ) ) {
-		 *    // do A.
-		 *  } else {
-		 *    // do B.
-		 *  }
-		 *
-		 * or, if you have only one if-branch:
-		 *
-		 *  if ( !( a.isBefore( b ) && c.isAfter( d ) ) {
-		 *    // do B.
-		 *  }
-		 *
-		 * rather than:
-		 *
-		 *  if ( !a.isBefore( b ) || && !c.isAfter( d ) ) {
-		 *    // do B.
-		 *  } else {
-		 *    // do A.
-		 *  }
-		 *
-		 * @param {document.Position} otherPosition Position to compare with.
-		 * @returns {Boolean} True if this position is before given position.
-		 */
-		isBefore( otherPosition ) {
-			return this.compareWith( otherPosition ) == BEFORE;
-		}
-
-		/**
-		 * Checks whether this position equals given position.
-		 *
-		 * @param {document.Position} otherPosition Position to compare with.
-		 * @returns {Boolean} True if positions are same.
-		 */
-		isEqual( otherPosition ) {
-			return this.compareWith( otherPosition ) == SAME;
-		}
-
-		/**
-		 * Creates a new position after given node.
-		 *
-		 * @param {document.Node} node Node the position should be directly after.
-		 * @returns {document.Position}
-		 */
-		static createAfter( node ) {
-			if ( !node.parent ) {
-				/**
-				 * You can not make position after root.
-				 *
-				 * @error position-after-root
-				 * @param {document.Node} root
-				 */
-				throw new CKEditorError( 'position-after-root: You can not make position after root.', { root: node } );
-			}
-
-			return Position.createFromParentAndOffset( node.parent, node.getIndex() + 1 );
-		}
-
-		/**
-		 * Creates a new position before the given node.
-		 *
-		 * @param {document.node} node Node the position should be directly before.
-		 * @returns {document.Position}
-		 */
-		static createBefore( node ) {
-			if ( !node.parent ) {
-				/**
-				 * You can not make position before root.
-				 *
-				 * @error position-before-root
-				 * @param {document.Node} root
-				 */
-				throw new CKEditorError( 'position-before-root: You can not make position before root.', { root: node } );
-			}
-
-			return Position.createFromParentAndOffset( node.parent, node.getIndex() );
-		}
-
-		/**
-		 * Creates a new position from the parent element and the offset in that element.
-		 *
-		 * @param {document.Element} parent Position parent element.
-		 * @param {Number} offset Position offset.
-		 * @returns {document.Position}
-		 */
-		static createFromParentAndOffset( parent, offset ) {
-			const path = parent.getPath();
-
-			path.push( offset );
-
-			return new Position( parent.root, path );
-		}
-
-		/**
-		 * Returns a new position that is a combination of this position and given positions. The combined
-		 * position is this position transformed by moving a range starting at `from` to `to` position.
-		 * It is expected that this position is inside the moved range.
-		 *
-		 * In other words, this method in a smart way "cuts out" `source` path from this position and
-		 * injects `target` path in it's place, while doing necessary fixes in order to get a correct path.
-		 *
-		 * Example:
-		 *
-		 * 	let original = new Position( root, [ 2, 3, 1 ] );
-		 * 	let source = new Position( root, [ 2, 2 ] );
-		 * 	let target = new Position( otherRoot, [ 1, 1, 3 ] );
-		 * 	let combined = original.getCombined( source, target );
-		 * 	// combined.path is [ 1, 1, 4, 1 ], combined.root is otherRoot
-		 *
-		 * Explanation:
-		 *
-		 * We have a position `[ 2, 3, 1 ]` and move some nodes from `[ 2, 2 ]` to `[ 1, 1, 3 ]`. The original position
-		 * was inside moved nodes and now should point to the new place. The moved nodes will be after
-		 * positions `[ 1, 1, 3 ]`, `[ 1, 1, 4 ]`, `[ 1, 1, 5 ]`. Since our position was in the second moved node,
-		 * the transformed position will be in a sub-tree of a node at `[ 1, 1, 4 ]`. Looking at original path, we
-		 * took care of `[ 2, 3 ]` part of it. Now we have to add the rest of the original path to the transformed path.
-		 * Finally, the transformed position will point to `[ 1, 1, 4, 1 ]`.
-		 *
-		 * @protected
-		 * @param {document.Position} source Beginning of the moved range.
-		 * @param {document.Position} target Position where the range is moved.
-		 * @returns {document.Position} Combined position.
-		 */
-		_getCombined( source, target ) {
-			const i = source.path.length - 1;
-
-			// The first part of a path to combined position is a path to the place where nodes were moved.
-			let combined = target.clone();
-
-			// Then we have to update the rest of the path.
-
-			// Fix the offset because this position might be after `from` position and we have to reflect that.
-			combined.offset = combined.offset + this.path[ i ] - source.offset;
-
-			// Then, add the rest of the path.
-			// If this position is at the same level as `from` position nothing will get added.
-			combined.path = combined.path.concat( this.path.slice( i + 1 ) );
-
-			return combined;
-		}
-	}
-
-	/**
-	 * Flag for "is after" relation between Positions.
-	 *
-	 * @type {Number}
-	 */
-	Position.AFTER = AFTER;
-
-	/**
-	 * Flag for "is before" relation between Positions.
-	 *
-	 * @type {Number}
-	 */
-	Position.BEFORE = BEFORE;
-
-	/**
-	 * Flag for "are in different roots" relation between Positions.
-	 *
-	 * @type {Number}
-	 */
-	Position.DIFFERENT = DIFFERENT;
-
-	/**
-	 * Flag for "are same" relation between Positions.
-	 *
-	 * @type {Number}
-	 */
-	Position.SAME = SAME;
-
-	return Position;
-} );

+ 0 - 178
packages/ckeditor5-utils/src/document/positioniterator.js

@@ -1,178 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [
-	'document/character',
-	'document/element',
-	'document/position'
-], ( Character, Element, Position ) => {
-	const ELEMENT_ENTER = 0;
-	const ELEMENT_LEAVE = 1;
-	const CHARACTER = 2;
-
-	/**
-	 * Position iterator class. It allows to iterate forward and backward over the tree document.
-	 *
-	 * @class document.PositionIterator
-	 */
-	class PositionIterator {
-		/**
-		 * Creates a range iterator.
-		 *
-		 * @param {document.Range} [boundaries] Range to define boundaries of the iterator.
-		 * @param {document.Position} [iteratorPosition] Starting position.
-		 * @constructor
-		 */
-		constructor( boundaries, iteratorPosition ) {
-			if ( boundaries instanceof Position ) {
-				this.position = boundaries;
-			} else {
-				this.boundaries =  boundaries;
-				this.position = iteratorPosition || boundaries.start;
-			}
-
-			/**
-			 * Iterator position.
-			 *
-			 * @property {document.Position} position
-			 */
-
-			/**
-			 * Iterator boundaries.
-			 *
-			 * When the {@link #next} method is called on the end boundary or the {@link #previous} method
-			 * on the start boundary, then `{ done: true }` is returned.
-			 *
-			 * If boundaries are not defined they are set before first and after last child of the root node.
-			 *
-			 * @property {document.Range} boundaries
-			 */
-		}
-
-		/**
-		 * Moves the {@link #position} to the next position and returns the enctountered value.
-		 *
-		 * @returns {Object} Value between the previous and the new {@link #position}.
-		 * @returns {Boolean} return.done True if iterator is done.
-		 * @returns {Object} return.value
-		 * @returns {Number} return.value.type Encountered value type, possible options: {@link PositionIterator#ELEMENT_ENTER},
-		 * {@link PositionIterator#ELEMENT_LEAVE} or {@link PositionIterator#CHARACTER}.
-		 * @returns {document.Node} return.value.node Encountered node.
-		 */
-		next() {
-			const position = this.position;
-			const parent = position.parent;
-
-			// Ugh... added here because of circular deps in AMD ;<.
-			Element = CKEDITOR.require( 'document/element' );
-
-			// We are at the end of the root.
-			if ( parent.parent === null && position.offset === parent.getChildCount() ) {
-				return { done: true };
-			}
-
-			if ( this.boundaries && position.isEqual( this.boundaries.end ) ) {
-				return { done: true };
-			}
-
-			const nodeAfter = position.nodeAfter;
-
-			if ( nodeAfter instanceof Element ) {
-				this.position = Position.createFromParentAndOffset( nodeAfter, 0 );
-
-				return formatReturnValue( ELEMENT_ENTER, nodeAfter );
-			} else if ( nodeAfter instanceof Character ) {
-				this.position = Position.createFromParentAndOffset( parent, position.offset + 1 );
-
-				return formatReturnValue( CHARACTER, nodeAfter );
-			} else {
-				this.position = Position.createFromParentAndOffset( parent.parent, parent.getIndex() + 1 );
-
-				return formatReturnValue( ELEMENT_LEAVE, this.position.nodeBefore );
-			}
-		}
-
-		/**
-		 * Moves the {@link #position} to the previous position and returns the encountered value.
-		 *
-		 * @returns {Object} Value between the previous and the new {@link #position}.
-		 * @returns {Boolean} return.done True if iterator is done.
-		 * @returns {Object} return.value
-		 * @returns {Number} return.value.type Encountered value type, possible options: {@link PositionIterator#ELEMENT_ENTER},
-		 * {@link PositionIterator#ELEMENT_LEAVE} or {@link PositionIterator#CHARACTER}.
-		 * @returns {document.Node} return.value.node Scanned node.
-		 */
-		previous() {
-			const position = this.position;
-			const parent = position.parent;
-
-			// We are at the beginning of the root.
-			if ( parent.parent === null && position.offset === 0 ) {
-				return { done: true };
-			}
-
-			if ( this.boundaries && position.isEqual( this.boundaries.start ) ) {
-				return { done: true };
-			}
-
-			const nodeBefore = position.nodeBefore;
-
-			if ( nodeBefore instanceof Element ) {
-				this.position = Position.createFromParentAndOffset( nodeBefore, nodeBefore.getChildCount() );
-
-				return formatReturnValue( ELEMENT_LEAVE, nodeBefore );
-			} else if ( nodeBefore instanceof Character ) {
-				this.position = Position.createFromParentAndOffset( parent, position.offset - 1 );
-
-				return formatReturnValue( CHARACTER, nodeBefore );
-			} else {
-				this.position = Position.createFromParentAndOffset( parent.parent, parent.getIndex() );
-
-				return formatReturnValue( ELEMENT_ENTER, this.position.nodeAfter );
-			}
-		}
-	}
-
-	function formatReturnValue( type, node ) {
-		return {
-			done: false,
-			value: {
-				type: type,
-				node: node
-			}
-		};
-	}
-
-	/**
-	 * Flag for character.
-	 *
-	 * @static
-	 * @readonly
-	 * @property {Number}
-	 */
-	PositionIterator.CHARACTER = CHARACTER;
-
-	/**
-	 * Flag for entering element.
-	 *
-	 * @static
-	 * @readonly
-	 * @property {Number}
-	 */
-	PositionIterator.ELEMENT_ENTER = ELEMENT_ENTER;
-
-	/**
-	 * Flag for leaving element.
-	 *
-	 * @static
-	 * @readonly
-	 * @property {Number}
-	 */
-	PositionIterator.ELEMENT_LEAVE = ELEMENT_LEAVE;
-
-	return PositionIterator;
-} );

+ 0 - 304
packages/ckeditor5-utils/src/document/range.js

@@ -1,304 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [ 'document/position', 'document/positioniterator', 'utils' ], ( Position, PositionIterator, utils ) => {
-	/**
-	 * Range class. Range is iterable.
-	 *
-	 * @class document.Range
-	 */
-	class Range {
-		/**
-		 * Creates a range.
-		 *
-		 * @param {document.Position} start Start position.
-		 * @param {document.Position} end End position.
-		 * @constructor
-		 */
-		constructor( start, end ) {
-			/**
-			 * Start position.
-			 *
-			 * @property {document.Position}
-			 */
-			this.start = start;
-
-			/**
-			 * End position.
-			 *
-			 * @property {document.Position}
-			 */
-			this.end = end;
-		}
-
-		/**
-		 * Range iterator.
-		 *
-		 * @see document.PositionIterator
-		 */
-		[ Symbol.iterator ]() {
-			return new PositionIterator( this );
-		}
-
-		/**
-		 * Creates and returns a new instance of {@link document.Range}
-		 * which is equal to this {@link document.Range range}.
-		 *
-		 * @returns {document.Position} Cloned {@link document.Range range}.
-		 */
-		clone() {
-			return new Range( this.start.clone(), this.end.clone() );
-		}
-
-		/**
-		 * Checks whether this contains given {@link document.Position position}.
-		 *
-		 * @param {document.Position} position Position to check.
-		 * @returns {Boolean} True if given {@link document.Position position} is contained.
-		 */
-		containsPosition( position ) {
-			return position.isAfter( this.start ) && position.isBefore( this.end );
-		}
-
-		/**
-		 * Checks whether this range contains given {@link document.Range range}.
-		 *
-		 * @param {document.Range} otherRange Range to check.
-		 * @returns {Boolean} True if given {@link document.Range range} boundaries are contained by this range.
-		 */
-		containsRange( otherRange ) {
-			return this.containsPosition( otherRange.start ) && this.containsPosition( otherRange.end );
-		}
-
-		/**
-		 * Gets a part of this {@link document.Range range} which is not a part of given {@link document.Range range}. Returned
-		 * array contains zero, one or two {@link document.Range ranges}.
-		 *
-		 * Examples:
-		 *
-		 * 	let range = new Range( new Position( root, [ 2, 7 ] ), new Position( root, [ 4, 0, 1 ] ) );
-		 * 	let otherRange = new Range( new Position( root, [ 1 ] ), new Position( root, [ 5 ] ) );
-		 * 	let transformed = range.getDifference( otherRange );
-		 * 	// transformed array has no ranges because `otherRange` contains `range`
-		 *
-		 * 	otherRange = new Range( new Position( root, [ 1 ] ), new Position( root, [ 3 ] ) );
-		 * 	transformed = range.getDifference( otherRange );
-		 * 	// transformed array has one range: from [ 3 ] to [ 4, 0, 1 ]
-		 *
-		 * 	otherRange = new Range( new Position( root, [ 3 ] ), new Position( root, [ 4 ] ) );
-		 * 	transformed = range.getDifference( otherRange );
-		 * 	// transformed array has two ranges: from [ 2, 7 ] to [ 3 ] and from [ 4 ] to [ 4, 0, 1 ]
-		 *
-		 * @param {document.Range} otherRange Range to differentiate against.
-		 * @returns {Array.<document.Range>} The difference between ranges.
-		 */
-		getDifference( otherRange ) {
-			const ranges = [];
-
-			if ( this.start.isBefore( otherRange.end ) && this.end.isAfter( otherRange.start ) ) {
-				// Ranges intersect.
-
-				if ( this.containsPosition( otherRange.start ) ) {
-					// Given range start is inside this range. This means that we have to
-					// add shrunken range - from the start to the middle of this range.
-					ranges.push(
-						new Range(
-							this.start.clone(),
-							otherRange.start.clone()
-						)
-					);
-				}
-
-				if ( this.containsPosition( otherRange.end ) ) {
-					// Given range end is inside this range. This means that we have to
-					// add shrunken range - from the middle of this range to the end.
-					ranges.push(
-						new Range(
-							otherRange.end.clone(),
-							this.end.clone()
-						)
-					);
-				}
-			} else {
-				// Ranges do not intersect, return the original range.
-				ranges.push( this.clone() );
-			}
-
-			return ranges;
-		}
-
-		/**
-		 * Returns an intersection of this {@link document.Range range} and given {@link document.Range range}. Intersection
-		 * is a common part of both of those ranges. If ranges has no common part, returns `null`.
-		 *
-		 * Examples:
-		 *
-		 * 	let range = new Range( new Position( root, [ 2, 7 ] ), new Position( root, [ 4, 0, 1 ] ) );
-		 * 	let otherRange = new Range( new Position( root, [ 1 ] ), new Position( root, [ 2 ] ) );
-		 * 	let transformed = range.getIntersection( otherRange ); // null - ranges have no common part
-		 *
-		 * 	otherRange = new Range( new Position( root, [ 3 ] ), new Position( root, [ 5 ] ) );
-		 * 	transformed = range.getIntersection( otherRange ); // range from [ 3 ] to [ 4, 0, 1 ]
-		 *
-		 * @param {document.Range} otherRange Range to check for intersection.
-		 * @returns {document.Range|null} A common part of given ranges or null if ranges have no common part.
-		 */
-		getIntersection( otherRange ) {
-			if ( this.start.isBefore( otherRange.end ) && this.end.isAfter( otherRange.start ) ) {
-				// Ranges intersect, so a common range will be returned.
-				// At most, it will be same as this range.
-				let commonRangeStart = this.start;
-				let commonRangeEnd = this.end;
-
-				if ( this.containsPosition( otherRange.start ) ) {
-					// Given range start is inside this range. This means thaNt we have to
-					// shrink common range to the given range start.
-					commonRangeStart = otherRange.start;
-				}
-
-				if ( this.containsPosition( otherRange.end ) ) {
-					// Given range end is inside this range. This means that we have to
-					// shrink common range to the given range end.
-					commonRangeEnd = otherRange.end;
-				}
-
-				return new Range( commonRangeStart.clone(), commonRangeEnd.clone() );
-			}
-
-			// Ranges do not intersect, so they do not have common part.
-			return null;
-		}
-
-		/**
-		 * Returns an iterator that iterates over all {@link document.Node nodes} that are in this range and returns them.
-		 * A node is in the range when it is after a {@link document.Position position} contained in this range.
-		 * In other words, this iterates over all {@link document.Character}s that are inside the range and
-		 * all the {@link document.Element}s we enter into when iterating over this range.
-		 *
-		 * Note, that this method will not return a parent node of start position. This is in contrary to {@link document.PositionIterator}
-		 * which will return that node with {@link document.PositionIterator#ELEMENT_LEAVE} type.
-		 *
-		 * @see {document.PositionIterator}
-		 * @returns {document.Node}
-		 */
-		*getNodes() {
-			for ( let value of this ) {
-				if ( value.type != PositionIterator.ELEMENT_LEAVE ) {
-					yield value.node;
-				}
-			}
-		}
-
-		/**
-		 * Returns an array containing one or two {document.Range ranges} that are a result of transforming this
-		 * {@link document.Range range} by inserting `howMany` nodes at `insertPosition`. Two {@link document.Range ranges} are
-		 * returned if the insertion was inside this {@link document.Range range}.
-		 *
-		 * Examples:
-		 *
-		 * 	let range = new Range( new Position( root, [ 2, 7 ] ), new Position( root, [ 4, 0, 1 ] ) );
-		 * 	let transformed = range.getTransformedByInsertion( new Position( root, [ 1 ] ), 2 );
-		 * 	// transformed array has one range from [ 4, 7 ] to [ 6, 0, 1 ]
-		 *
-		 * 	transformed = range.getTransformedByInsertion( new Position( root, [ 3, 2 ] ), 4 );
-		 * 	// transformed array has two ranges: from [ 2, 7 ] to [ 3, 2 ] and from [ 3, 6 ] to [ 4, 0, 1 ]
-		 *
-		 * 	transformed = range.getTransformedByInsertion( new Position( root, [ 3, 2 ] ), 4, true );
-		 * 	// transformed array has one range which is equal to `range`. This is because of spreadOnlyOnSameLevel flag.
-		 *
-		 * @param {document.Position} insertPosition Position where nodes are inserted.
-		 * @param {Number} howMany How many nodes are inserted.
-		 * @param {Boolean} spreadOnlyOnSameLevel Flag indicating whether this {document.Range range} should be spread
-		 * if insertion was inside a node from this {document.Range range} but not in the range itself.
-		 * @returns {Array.<document.Range>} Result of the transformation.
-		 */
-		getTransformedByInsertion( insertPosition, howMany, spreadOnlyOnSameLevel ) {
-			// Flag indicating whether this whole range and given insertPosition is on the same tree level.
-			const areOnSameLevel = utils.compareArrays( this.start.getParentPath(), this.end.getParentPath() ) == utils.compareArrays.SAME &&
-				utils.compareArrays( this.start.getParentPath(), insertPosition.getParentPath() ) == utils.compareArrays.SAME;
-
-			if ( this.containsPosition( insertPosition ) && ( !spreadOnlyOnSameLevel || areOnSameLevel ) ) {
-				// Range has to be spread. The first part is from original start to the spread point.
-				// The other part is from spread point to the original end, but transformed by
-				// insertion to reflect insertion changes.
-
-				return [
-					new Range(
-						this.start.clone(),
-						insertPosition.clone()
-					),
-					new Range(
-						insertPosition.getTransformedByInsertion( insertPosition, howMany, true ),
-						this.end.getTransformedByInsertion( insertPosition, howMany, true )
-					)
-				];
-			} else {
-				// If insertion is not inside the range, simply transform range boundaries (positions) by the insertion.
-				// Both, one or none of them might be affected by the insertion.
-
-				const range = this.clone();
-
-				range.start = range.start.getTransformedByInsertion( insertPosition, howMany, true );
-				range.end = range.end.getTransformedByInsertion( insertPosition, howMany, false );
-
-				return [ range ];
-			}
-		}
-
-		/**
-		 * Two ranges equal if their start and end positions equal.
-		 *
-		 * @param {document.Range} otherRange Range to compare with.
-		 * @returns {Boolean} True if ranges equal.
-		 */
-		isEqual( otherRange ) {
-			return this.start.isEqual( otherRange.start ) && this.end.isEqual( otherRange.end );
-		}
-
-		/**
-		 * Creates a range inside an element which starts before the first child and ends after the last child.
-		 *
-		 * @param {document.Element} element Element which is a parent for the range.
-		 * @returns {document.Range} Created range.
-		 */
-		static createFromElement( element ) {
-			return Range.createFromParentsAndOffsets( element, 0, element, element.getChildCount() );
-		}
-
-		/**
-		 * Creates a new range spreading from specified position to the same position moved by given offset.
-		 *
-		 * @param {document.Position} position Beginning of the range.
-		 * @param {Number} offset How long the range should be.
-		 * @returns {document.Range}
-		 */
-		static createFromPositionAndOffset( position, offset ) {
-			let endPosition = position.clone();
-			endPosition.offset += offset;
-
-			return new Range( position, endPosition );
-		}
-
-		/**
-		 * Creates a range from given parents and offsets.
-		 *
-		 * @param {document.Element} startElement Start position parent element.
-		 * @param {Number} startOffset Start position offset.
-		 * @param {document.Element} endElement End position parent element.
-		 * @param {Number} endOffset End position offset.
-		 * @returns {document.Range} Created range.
-		 */
-		static createFromParentsAndOffsets( startElement, startOffset, endElement, endOffset ) {
-			return new Range(
-				Position.createFromParentAndOffset( startElement, startOffset ),
-				Position.createFromParentAndOffset( endElement, endOffset )
-			);
-		}
-	}
-
-	return Range;
-} );

+ 0 - 35
packages/ckeditor5-utils/src/document/rootelement.js

@@ -1,35 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [ 'document/element' ], ( Element ) => {
-	/**
-	 * Class for nodes that are roots of trees in tree data model.
-	 *
-	 * @class document.RootElement
-	 */
-	class RootElement extends Element {
-		/**
-		 * Creates tree root node.
-		 *
-		 * @param {document.Document} doc {@link document.Document} that is an owner of the root.
-		 * @constructor
-		 */
-		constructor( doc ) {
-			super( 'root' );
-
-			/**
-			 * {@link document.Document} that is an owner of this root.
-			 *
-			 * @readonly
-			 * @property {document.Document}
-			 */
-			this.document = doc;
-		}
-	}
-
-	return RootElement;
-} );

+ 0 - 42
packages/ckeditor5-utils/src/document/text.js

@@ -1,42 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( [], () => {
-	/**
-	 * Data structure for text with attributes. Note that the `Text` is not a {@link document.Node},
-	 * because it will never be part of the document tree. {@link document.Character is a node}.
-	 *
-	 * @class document.Text
-	 */
-	class Text {
-		/**
-		 * Creates a text with attributes.
-		 *
-		 * @param {String} text Described text.
-		 * @param {Iterable} attrs Iterable collection of {@link document.Attribute attributes}.
-		 * @constructor
-		 */
-		constructor( text, attrs ) {
-			/**
-			 * Text.
-			 *
-			 * @readonly
-			 * @property {String}
-			 */
-			this.text = text;
-
-			/**
-			 * Iterable collection of {@link document.Attribute attributes}.
-			 *
-			 * @property {Iterable}
-			 */
-			this.attrs = attrs;
-		}
-	}
-
-	return Text;
-} );

+ 0 - 81
packages/ckeditor5-utils/tests/document/attribute.js

@@ -1,81 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-
-'use strict';
-
-const modules = bender.amd.require( 'document/attribute' );
-
-describe( 'Attribute', () => {
-	let Attribute;
-
-	before( () => {
-		Attribute = modules[ 'document/attribute' ];
-	} );
-
-	beforeEach( () => {
-		Attribute._register = {};
-	} );
-
-	describe( 'constructor', () => {
-		it( 'should create attribute', () => {
-			let attr = new Attribute( 'foo', 'bar' );
-
-			expect( attr ).to.have.property( 'key' ).that.equals( 'foo' );
-			expect( attr ).to.have.property( 'value' ).that.equals( 'bar' );
-		} );
-
-		it( 'should create equal instance even if object has different order', () => {
-			let attr1 = new Attribute( 'foo', { a: 1, b: 2 } );
-			let attr2 = new Attribute( 'foo', { b: 2, a: 1 } );
-
-			expect( attr1.isEqual( attr2 ) ).to.be.true;
-		} );
-
-		it( 'should return the same object for registered objects', () => {
-			Attribute.register( 'register', true );
-
-			let attr1 = new Attribute( 'register', true );
-			let attr2 = new Attribute( 'register', true );
-
-			expect( attr1 ).to.equal( attr2 );
-			expect( attr1.isEqual( attr2 ) ).to.be.true;
-		} );
-
-		it( 'should return different objects for different values', () => {
-			Attribute.register( 'register', true );
-
-			let attr1 = new Attribute( 'register', true );
-			let attr2 = new Attribute( 'register', false );
-
-			expect( attr1 ).to.not.be.equals( attr2 );
-			expect( attr1.isEqual( attr2 ) ).to.not.be.true;
-		} );
-
-		it( 'should return different objects for not registered objects', () => {
-			Attribute.register( 'register', true );
-
-			let attr1 = new Attribute( 'register', false );
-			let attr2 = new Attribute( 'register', false );
-
-			expect( attr1 ).to.not.be.equals( attr2 );
-			expect( attr1.isEqual( attr2 ) ).to.be.true;
-		} );
-	} );
-
-	describe( 'register', () => {
-		it( 'Attribute.register should return registered attribute', () => {
-			let attr1 = new Attribute( 'register', true );
-			let attr2 = Attribute.register( 'register', true );
-			let attr3 = Attribute.register( 'register', true );
-			let attr4 = new Attribute( 'register', true );
-
-			expect( attr1 ).to.not.be.equals( attr2 );
-			expect( attr2 ).to.equal( attr3 );
-			expect( attr3 ).to.equal( attr4 );
-		} );
-	} );
-} );

+ 0 - 83
packages/ckeditor5-utils/tests/document/batch.js

@@ -1,83 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document, delta */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/batch',
-	'document/delta/delta',
-	'ckeditorerror'
-);
-
-describe( 'Batch', () => {
-	let Batch, Delta, CKEditorError;
-
-	before( () => {
-		Batch = modules[ 'document/batch' ];
-		Delta = modules[ 'document/delta/delta' ];
-		CKEditorError = modules.ckeditorerror;
-	} );
-
-	it( 'should have registered basic methods', () => {
-		const batch = new Batch();
-
-		expect( batch.setAttr ).to.be.a( 'function' );
-		expect( batch.removeAttr ).to.be.a( 'function' );
-	} );
-
-	describe( 'Batch.register', () => {
-		let TestDelta;
-
-		before( () => {
-			TestDelta = class extends Delta {
-				constructor( batch ) {
-					super( batch, [] );
-				}
-			};
-		} );
-
-		afterEach( () => {
-			delete Batch.prototype.foo;
-		} );
-
-		it( 'should register function which return an delta', () => {
-			Batch.register( 'foo', function() {
-				this.addDelta( new TestDelta() );
-			} );
-
-			const batch = new Batch();
-
-			batch.foo();
-
-			expect( batch.deltas.length ).to.equal( 1 );
-			expect( batch.deltas[ 0 ] ).to.be.instanceof( TestDelta );
-		} );
-
-		it( 'should register function which return an multiple deltas', () => {
-			Batch.register( 'foo', function() {
-				this.addDelta( new TestDelta() );
-				this.addDelta( new TestDelta() );
-			} );
-
-			const batch = new Batch();
-
-			batch.foo();
-
-			expect( batch.deltas.length ).to.equal( 2 );
-			expect( batch.deltas[ 0 ] ).to.be.instanceof( TestDelta );
-			expect( batch.deltas[ 1 ] ).to.be.instanceof( TestDelta );
-		} );
-
-		it( 'should throw if one try to register the same batch twice', () => {
-			Batch.register( 'foo', () => {} );
-
-			expect( () => {
-				Batch.register( 'foo', () => {} );
-			} ).to.throw( CKEditorError, /^batch-register-taken/ );
-		} );
-	} );
-} );

+ 0 - 56
packages/ckeditor5-utils/tests/document/character.js

@@ -1,56 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* jshint expr: true */
-
-/* bender-tags: document */
-
-/* bender-include: ../_tools/tools.js */
-
-'use strict';
-
-const getIteratorCount = bender.tools.core.getIteratorCount;
-
-const modules = bender.amd.require(
-	'document/character',
-	'document/node',
-	'document/element',
-	'document/attribute'
-);
-
-describe( 'Character', () => {
-	let Element, Character, Node, Attribute;
-
-	before( () => {
-		Element = modules[ 'document/element' ];
-		Character = modules[ 'document/character' ];
-		Node = modules[ 'document/node' ];
-		Attribute = modules[ 'document/attribute' ];
-	} );
-
-	describe( 'constructor', () => {
-		it( 'should create character without attributes', () => {
-			let character = new Character( 'f' );
-			let parent = new Element( 'parent', [], character );
-
-			expect( character ).to.be.an.instanceof( Node );
-			expect( character ).to.have.property( 'character' ).that.equals( 'f' );
-			expect( character ).to.have.property( 'parent' ).that.equals( parent );
-			expect( getIteratorCount( character.getAttrs() ) ).to.equal( 0 );
-		} );
-
-		it( 'should create character with attributes', () => {
-			let attr = new Attribute( 'foo', 'bar' );
-			let character = new Character( 'f', [ attr ] );
-			let parent = new Element( 'parent', [], character );
-
-			expect( character ).to.be.an.instanceof( Node );
-			expect( character ).to.have.property( 'character' ).that.equals( 'f' );
-			expect( character ).to.have.property( 'parent' ).that.equals( parent );
-			expect( getIteratorCount( character.getAttrs() ) ).to.equal( 1 );
-			expect( character.getAttr( attr.key ) ).to.equal( attr.value );
-		} );
-	} );
-} );

+ 0 - 301
packages/ckeditor5-utils/tests/document/deltas/attributedelta.js

@@ -1,301 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document, delta */
-
-/* bender-include: ../../_tools/tools.js */
-
-'use strict';
-
-const getIteratorCount = bender.tools.core.getIteratorCount;
-
-const modules = bender.amd.require(
-	'document/batch',
-	'document/document',
-	'document/text',
-	'document/attribute',
-	'document/range',
-	'document/position',
-	'document/element',
-	'document/character' );
-
-describe( 'Batch', () => {
-	let Batch, Document, Text, Attribute, Range, Position, Element, Character;
-
-	let doc, root, batch;
-
-	before( () => {
-		Batch = modules[ 'document/batch' ];
-		Document = modules[ 'document/document' ];
-		Text = modules[ 'document/text' ];
-		Attribute = modules[ 'document/attribute' ];
-		Range = modules[ 'document/range' ];
-		Position = modules[ 'document/position' ];
-		Element = modules[ 'document/element' ];
-		Character = modules[ 'document/character' ];
-	} );
-
-	beforeEach( () => {
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-		batch = doc.batch();
-	} );
-
-	function getOperationsCount() {
-		let count = 0;
-
-		for ( let delta of batch.deltas ) {
-			count += getIteratorCount( delta.operations );
-		}
-
-		return count;
-	}
-
-	describe( 'change attribute on node', () => {
-		let node, character;
-
-		beforeEach( () => {
-			node = new Element( 'p', [ new Attribute( 'a', 1 ) ] );
-			character = new Character( 'c', [ new Attribute( 'a', 1 ) ] );
-			root.insertChildren( 0, [ node, character ] );
-		} );
-
-		describe( 'setAttr', () => {
-			it( 'should create the attribute on element', () => {
-				batch.setAttr( 'b', 2, node );
-				expect( getOperationsCount() ).to.equal( 1 );
-				expect( node.getAttr( 'b' ) ).to.equal( 2 );
-			} );
-
-			it( 'should change the attribute of element', () => {
-				batch.setAttr( 'a', 2, node );
-				expect( getOperationsCount() ).to.equal( 1 );
-				expect( node.getAttr( 'a' ) ).to.equal( 2 );
-			} );
-
-			it( 'should create the attribute on character', () => {
-				batch.setAttr( 'b', 2, character );
-				expect( getOperationsCount() ).to.equal( 1 );
-				expect( character.getAttr( 'b' ) ).to.equal( 2 );
-			} );
-
-			it( 'should change the attribute of character', () => {
-				batch.setAttr( 'a', 2, character );
-				expect( getOperationsCount() ).to.equal( 1 );
-				expect( character.getAttr( 'a' ) ).to.equal( 2 );
-			} );
-
-			it( 'should do nothing if the attribute value is the same', () => {
-				batch.setAttr( 'a', 1, node );
-				expect( getOperationsCount() ).to.equal( 0 );
-				expect( node.getAttr( 'a' ) ).to.equal( 1 );
-			} );
-
-			it( 'should be chainable', () => {
-				const chain = batch.setAttr( 'b', 2, node );
-				expect( chain ).to.equal( batch );
-			} );
-		} );
-
-		describe( 'removeAttr', () => {
-			it( 'should remove the attribute from element', () => {
-				batch.removeAttr( 'a', node );
-				expect( getOperationsCount() ).to.equal( 1 );
-				expect( node.getAttr( 'a' ) ).to.be.null;
-			} );
-
-			it( 'should remove the attribute from character', () => {
-				batch.removeAttr( 'a', character );
-				expect( getOperationsCount() ).to.equal( 1 );
-				expect( character.getAttr( 'a' ) ).to.be.null;
-			} );
-
-			it( 'should do nothing if the attribute is not set', () => {
-				batch.removeAttr( 'b', node );
-				expect( getOperationsCount() ).to.equal( 0 );
-			} );
-
-			it( 'should be chainable', () => {
-				const chain = batch.removeAttr( 'a', node );
-				expect( chain ).to.equal( batch );
-			} );
-		} );
-	} );
-
-	describe( 'change attribute on range', () => {
-		beforeEach( () => {
-			root.insertChildren( 0, [
-				new Text( 'xxx', [ new Attribute( 'a', 1 ) ] ),
-				'xxx',
-				new Text( 'xxx', [ new Attribute( 'a', 1 ) ] ),
-				new Text( 'xxx', [ new Attribute( 'a', 2 ) ] ),
-				'xxx',
-				new Text( 'xxx', [ new Attribute( 'a', 1 ) ] ),
-				new Element( 'e', [ new Attribute( 'a', 2 ) ], 'xxx' ),
-				'xxx'
-			] );
-		} );
-
-		function getRange( startIndex, endIndex ) {
-			return new Range(
-					Position.createFromParentAndOffset( root, startIndex ),
-					Position.createFromParentAndOffset( root, endIndex )
-				);
-		}
-
-		function getChangesAttrsCount() {
-			let count = 0;
-
-			for ( let delta of batch.deltas ) {
-				for ( let operation of delta.operations ) {
-					count += getIteratorCount( operation.range.getNodes() );
-				}
-			}
-
-			return count;
-		}
-
-		function getCompressedAttrs() {
-			// default: 111---111222---1112------
-			const range = Range.createFromElement( root );
-
-			return Array.from( range.getNodes() ).map( node => node.getAttr( 'a' ) || '-' ).join( '' );
-		}
-
-		describe( 'setAttr', () => {
-			it( 'should set the attribute on the range', () => {
-				batch.setAttr( 'a', 3, getRange( 3, 6 ) );
-				expect( getOperationsCount() ).to.equal( 1 );
-				expect( getChangesAttrsCount() ).to.equal( 3 );
-				expect( getCompressedAttrs() ).to.equal( '111333111222---1112------' );
-			} );
-
-			it( 'should split the operations if parts of the range have different attributes', () => {
-				batch.setAttr( 'a', 3, getRange( 4, 14 ) );
-				expect( getOperationsCount() ).to.equal( 4 );
-				expect( getChangesAttrsCount() ).to.equal( 10 );
-				expect( getCompressedAttrs() ).to.equal( '111-3333333333-1112------' );
-			} );
-
-			it( 'should split the operations if parts of the part of the range have the attribute', () => {
-				batch.setAttr( 'a', 2, getRange( 4, 14 ) );
-				expect( getOperationsCount() ).to.equal( 3 );
-				expect( getChangesAttrsCount() ).to.equal( 7 );
-				expect( getCompressedAttrs() ).to.equal( '111-2222222222-1112------' );
-			} );
-
-			it( 'should strip the range if the beginning have the attribute', () => {
-				batch.setAttr( 'a', 1, getRange( 1, 5 ) );
-				expect( getOperationsCount() ).to.equal( 1 );
-				expect( getChangesAttrsCount() ).to.equal( 2 );
-				expect( getCompressedAttrs() ).to.equal( '11111-111222---1112------' );
-			} );
-
-			it( 'should strip the range if the ending have the attribute', () => {
-				batch.setAttr( 'a', 1, getRange( 13, 17 ) );
-				expect( getOperationsCount() ).to.equal( 1 );
-				expect( getChangesAttrsCount() ).to.equal( 2 );
-				expect( getCompressedAttrs() ).to.equal( '111---111222-111112------' );
-			} );
-
-			it( 'should do nothing if the range has attribute', () => {
-				batch.setAttr( 'a', 1, getRange( 0, 3 ) );
-				expect( getOperationsCount() ).to.equal( 0 );
-				expect( getCompressedAttrs() ).to.equal( '111---111222---1112------' );
-			} );
-
-			it( 'should not check range\'s start position node when creating operations', () => {
-				let range = new Range(
-					new Position( root, [ 18, 1 ] ),
-					new Position( root, [ 19 ] )
-				);
-
-				batch.setAttr( 'a', 1, range );
-				expect( getOperationsCount() ).to.equal( 1 );
-				expect( getChangesAttrsCount() ).to.equal( 2 );
-				expect( getCompressedAttrs() ).to.equal( '111---111222---1112-11---' );
-			} );
-
-			it( 'should create a proper operations for the mixed range', () => {
-				batch.setAttr( 'a', 1, getRange( 0, 20 ) );
-				expect( getOperationsCount() ).to.equal( 5 );
-				expect( getChangesAttrsCount() ).to.equal( 14 );
-				expect( getCompressedAttrs() ).to.equal( '11111111111111111111111--' );
-			} );
-
-			it( 'should be chainable', () => {
-				const chain = batch.setAttr( 'a', 3, getRange( 3, 6 ) );
-				expect( chain ).to.equal( batch );
-			} );
-		} );
-
-		describe( 'removeAttr', () => {
-			it( 'should remove the attribute on the range', () => {
-				batch.removeAttr( 'a', getRange( 0, 2 ) );
-				expect( getOperationsCount() ).to.equal( 1 );
-				expect( getChangesAttrsCount() ).to.equal( 2 );
-				expect( getCompressedAttrs() ).to.equal( '--1---111222---1112------' );
-			} );
-
-			it( 'should split the operations if parts of the range have different attributes', () => {
-				batch.removeAttr( 'a', getRange( 7, 11 ) );
-				expect( getOperationsCount() ).to.equal( 2 );
-				expect( getChangesAttrsCount() ).to.equal( 4 );
-				expect( getCompressedAttrs() ).to.equal( '111---1----2---1112------' );
-			} );
-
-			it( 'should split the operations if parts of the part of the range have no attribute', () => {
-				batch.removeAttr( 'a', getRange( 1, 7 ) );
-				expect( getOperationsCount() ).to.equal( 2 );
-				expect( getChangesAttrsCount() ).to.equal( 3 );
-				expect( getCompressedAttrs() ).to.equal( '1------11222---1112------' );
-			} );
-
-			it( 'should strip the range if the beginning have no attribute', () => {
-				batch.removeAttr( 'a', getRange( 4, 12 ) );
-				expect( getOperationsCount() ).to.equal( 2 );
-				expect( getChangesAttrsCount() ).to.equal( 6 );
-				expect( getCompressedAttrs() ).to.equal( '111------------1112------' );
-			} );
-
-			it( 'should strip the range if the ending have no attribute', () => {
-				batch.removeAttr( 'a', getRange( 7, 15 ) );
-				expect( getOperationsCount() ).to.equal( 2 );
-				expect( getChangesAttrsCount() ).to.equal( 5 );
-				expect( getCompressedAttrs() ).to.equal( '111---1--------1112------' );
-			} );
-
-			it( 'should do nothing if the range has no attribute', () => {
-				batch.removeAttr( 'a', getRange( 4, 5 ) );
-				expect( getOperationsCount() ).to.equal( 0 );
-				expect( getCompressedAttrs() ).to.equal( '111---111222---1112------' );
-			} );
-
-			it( 'should not check range\'s start position node when creating operations', () => {
-				let range = new Range(
-					new Position( root, [ 18, 3 ] ),
-					new Position( root, [ 19 ] )
-				);
-
-				batch.removeAttr( 'a', range );
-				expect( getOperationsCount() ).to.equal( 0 );
-				expect( getChangesAttrsCount() ).to.equal( 0 );
-				expect( getCompressedAttrs() ).to.equal( '111---111222---1112------' );
-			} );
-
-			it( 'should create a proper operations for the mixed range', () => {
-				batch.removeAttr( 'a', getRange( 3, 15 ) );
-				expect( getOperationsCount() ).to.equal( 2 );
-				expect( getChangesAttrsCount() ).to.equal( 6 );
-				expect( getCompressedAttrs() ).to.equal( '111------------1112------' );
-			} );
-
-			it( 'should be chainable', () => {
-				const chain = batch.removeAttr( 'a', getRange( 0, 2 ) );
-				expect( chain ).to.equal( batch );
-			} );
-		} );
-	} );
-} );

+ 0 - 67
packages/ckeditor5-utils/tests/document/deltas/delta.js

@@ -1,67 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document, delta */
-
-/* bender-include: ../../_tools/tools.js */
-
-'use strict';
-
-const getIteratorCount = bender.tools.core.getIteratorCount;
-
-const modules = bender.amd.require(
-	'document/delta/delta' );
-
-describe( 'Delta', () => {
-	let Delta;
-
-	before( () => {
-		Delta = modules[ 'document/delta/delta' ];
-	} );
-
-	describe( 'constructor', () => {
-		it( 'should create an delta with empty properties', () => {
-			const delta = new Delta();
-
-			expect( delta ).to.have.property( 'batch' ).that.is.null;
-			expect( delta ).to.have.property( 'operations' ).that.a( 'array' ).and.have.length( 0 );
-		} );
-	} );
-
-	describe( 'addOperation', () => {
-		it( 'should add operation to the delta', () => {
-			const delta = new Delta();
-			const operation = {};
-
-			delta.addOperation( operation );
-
-			expect( delta.operations ).to.have.length( 1 );
-			expect( delta.operations[ 0 ] ).to.equal( operation );
-		} );
-
-		it( 'should add delta property to the operation', () => {
-			const delta = new Delta();
-			const operation = {};
-
-			delta.addOperation( operation );
-
-			expect( operation.delta ).to.equal( delta );
-		} );
-	} );
-
-	describe( 'iterator', () => {
-		it( 'should iterate over delta operations', () => {
-			const delta = new Delta();
-
-			delta.addOperation( {} );
-			delta.addOperation( {} );
-			delta.addOperation( {} );
-
-			const count = getIteratorCount( delta.operations );
-
-			expect( count ).to.equal( 3 );
-		} );
-	} );
-} );

+ 0 - 46
packages/ckeditor5-utils/tests/document/deltas/insertdelta.js

@@ -1,46 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document, delta */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/position' );
-
-describe( 'Batch', () => {
-	let Document, Position;
-
-	let doc, root;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		Position = modules[ 'document/position' ];
-	} );
-
-	beforeEach( () => {
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-	} );
-
-	it( 'should insert text', () => {
-		const position = new Position( root, [ 0 ] );
-		doc.batch().insert( position, 'foo' );
-
-		expect( root.getChildCount() ).to.equal( 3 );
-		expect( root.getChild( 0 ).character ).to.equal( 'f' );
-		expect( root.getChild( 1 ).character ).to.equal( 'o' );
-		expect( root.getChild( 2 ).character ).to.equal( 'o' );
-	} );
-
-	it( 'should be chainable', () => {
-		const position = new Position( root, [ 0 ] );
-		const batch = doc.batch();
-
-		const chain = batch.insert( position, 'foo' );
-		expect( chain ).to.equal( batch );
-	} );
-} );

+ 0 - 80
packages/ckeditor5-utils/tests/document/deltas/mergedelta.js

@@ -1,80 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document, delta */
-
-/* bender-include: ../../_tools/tools.js */
-
-'use strict';
-
-const getIteratorCount = bender.tools.core.getIteratorCount;
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/position',
-	'document/element',
-	'document/attribute',
-	'ckeditorerror' );
-
-describe( 'Batch', () => {
-	let Document, Position, Element, Attribute, CKEditorError;
-
-	let doc, root, p1, p2;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		Position = modules[ 'document/position' ];
-		Element = modules[ 'document/element' ];
-		Attribute = modules[ 'document/attribute' ];
-		CKEditorError = modules.ckeditorerror;
-	} );
-
-	beforeEach( () => {
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-
-		p1 = new Element( 'p', [ new Attribute( 'key1', 'value1' ) ], 'foo' );
-		p2 = new Element( 'p', [ new Attribute( 'key2', 'value2' ) ], 'bar' );
-
-		root.insertChildren( 0, [ p1, p2 ] );
-	} );
-
-	describe( 'merge', () => {
-		it( 'should merge foo and bar into foobar', () => {
-			doc.batch().merge( new Position( root, [ 1 ] ) );
-
-			expect( root.getChildCount() ).to.equal( 1 );
-			expect( root.getChild( 0 ).name ).to.equal( 'p' );
-			expect( root.getChild( 0 ).getChildCount() ).to.equal( 6 );
-			expect( getIteratorCount( root.getChild( 0 ).getAttrs() ) ).to.equal( 1 );
-			expect( root.getChild( 0 ).getAttr( 'key1' ) ).to.equal( 'value1' );
-			expect( root.getChild( 0 ).getChild( 0 ).character ).to.equal( 'f' );
-			expect( root.getChild( 0 ).getChild( 1 ).character ).to.equal( 'o' );
-			expect( root.getChild( 0 ).getChild( 2 ).character ).to.equal( 'o' );
-			expect( root.getChild( 0 ).getChild( 3 ).character ).to.equal( 'b' );
-			expect( root.getChild( 0 ).getChild( 4 ).character ).to.equal( 'a' );
-			expect( root.getChild( 0 ).getChild( 5 ).character ).to.equal( 'r' );
-		} );
-
-		it( 'should throw if there is no element after', () => {
-			expect( () => {
-				doc.batch().merge( new Position( root, [ 2 ] ) );
-			} ).to.throw( CKEditorError, /^batch-merge-no-element-after/ );
-		} );
-
-		it( 'should throw if there is no element before', () => {
-			expect( () => {
-				doc.batch().merge( new Position( root, [ 0, 2 ] ) );
-			} ).to.throw( CKEditorError, /^batch-merge-no-element-before/ );
-		} );
-
-		it( 'should be chainable', () => {
-			const batch = doc.batch();
-
-			const chain = batch.merge( new Position( root, [ 1 ] ) );
-			expect( chain ).to.equal( batch );
-		} );
-	} );
-} );

+ 0 - 61
packages/ckeditor5-utils/tests/document/deltas/removedelta.js

@@ -1,61 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document, delta */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/position' );
-
-describe( 'Batch', () => {
-	let Document, Position;
-
-	let doc, root;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		Position = modules[ 'document/position' ];
-	} );
-
-	beforeEach( () => {
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-		root.insertChildren( 0, 'foobar' );
-	} );
-
-	describe( 'remove', () => {
-		it( 'should remove one element', () => {
-			const position = new Position( root, [ 1 ] );
-			doc.batch().remove( position );
-
-			expect( root.getChildCount() ).to.equal( 5 );
-			expect( root.getChild( 0 ).character ).to.equal( 'f' );
-			expect( root.getChild( 1 ).character ).to.equal( 'o' );
-			expect( root.getChild( 2 ).character ).to.equal( 'b' );
-			expect( root.getChild( 3 ).character ).to.equal( 'a' );
-			expect( root.getChild( 4 ).character ).to.equal( 'r' );
-		} );
-
-		it( 'should remove 3 elements', () => {
-			const position = new Position( root, [ 1 ] );
-			doc.batch().remove( position, 3 );
-
-			expect( root.getChildCount() ).to.equal( 3 );
-			expect( root.getChild( 0 ).character ).to.equal( 'f' );
-			expect( root.getChild( 1 ).character ).to.equal( 'a' );
-			expect( root.getChild( 2 ).character ).to.equal( 'r' );
-		} );
-
-		it( 'should be chainable', () => {
-			const position = new Position( root, [ 1 ] );
-			const batch = doc.batch();
-
-			const chain = batch.remove( position );
-			expect( chain ).to.equal( batch );
-		} );
-	} );
-} );

+ 0 - 101
packages/ckeditor5-utils/tests/document/deltas/splitdelta.js

@@ -1,101 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document, delta */
-
-/* bender-include: ../../_tools/tools.js */
-
-'use strict';
-
-const getIteratorCount = bender.tools.core.getIteratorCount;
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/position',
-	'document/element',
-	'document/attribute',
-	'ckeditorerror' );
-
-describe( 'Batch', () => {
-	let Document, Position, Element, Attribute, CKEditorError;
-
-	let doc, root, p;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		Position = modules[ 'document/position' ];
-		Element = modules[ 'document/element' ];
-		Attribute = modules[ 'document/attribute' ];
-		CKEditorError = modules.ckeditorerror;
-	} );
-
-	beforeEach( () => {
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-
-		p = new Element( 'p', [ new Attribute( 'key', 'value' ) ], 'foobar' );
-
-		root.insertChildren( 0, p );
-	} );
-
-	describe( 'split', () => {
-		it( 'should split foobar to foo and bar', () => {
-			doc.batch().split( new Position( root, [ 0, 3 ] ) );
-
-			expect( root.getChildCount() ).to.equal( 2 );
-
-			expect( root.getChild( 0 ).name ).to.equal( 'p' );
-			expect( root.getChild( 0 ).getChildCount() ).to.equal( 3 );
-			expect( getIteratorCount( root.getChild( 0 ).getAttrs() ) ).to.equal( 1 );
-			expect( root.getChild( 0 ).getAttr( 'key' ) ).to.equal( 'value' );
-			expect( root.getChild( 0 ).getChild( 0 ).character ).to.equal( 'f' );
-			expect( root.getChild( 0 ).getChild( 1 ).character ).to.equal( 'o' );
-			expect( root.getChild( 0 ).getChild( 2 ).character ).to.equal( 'o' );
-
-			expect( root.getChild( 1 ).name ).to.equal( 'p' );
-			expect( root.getChild( 1 ).getChildCount() ).to.equal( 3 );
-			expect( getIteratorCount( root.getChild( 1 ).getAttrs() ) ).to.equal( 1 );
-			expect( root.getChild( 1 ).getAttr( 'key' ) ).to.equal( 'value' );
-			expect( root.getChild( 1 ).getChild( 0 ).character ).to.equal( 'b' );
-			expect( root.getChild( 1 ).getChild( 1 ).character ).to.equal( 'a' );
-			expect( root.getChild( 1 ).getChild( 2 ).character ).to.equal( 'r' );
-		} );
-
-		it( 'should create an empty paragraph if we split at the end', () => {
-			doc.batch().split( new Position( root, [ 0, 6 ] ) );
-
-			expect( root.getChildCount() ).to.equal( 2 );
-
-			expect( root.getChild( 0 ).name ).to.equal( 'p' );
-			expect( root.getChild( 0 ).getChildCount() ).to.equal( 6 );
-			expect( getIteratorCount( root.getChild( 0 ).getAttrs() ) ).to.equal( 1 );
-			expect( root.getChild( 0 ).getAttr( 'key' ) ).to.equal( 'value' );
-			expect( root.getChild( 0 ).getChild( 0 ).character ).to.equal( 'f' );
-			expect( root.getChild( 0 ).getChild( 1 ).character ).to.equal( 'o' );
-			expect( root.getChild( 0 ).getChild( 2 ).character ).to.equal( 'o' );
-			expect( root.getChild( 0 ).getChild( 3 ).character ).to.equal( 'b' );
-			expect( root.getChild( 0 ).getChild( 4 ).character ).to.equal( 'a' );
-			expect( root.getChild( 0 ).getChild( 5 ).character ).to.equal( 'r' );
-
-			expect( root.getChild( 1 ).name ).to.equal( 'p' );
-			expect( root.getChild( 1 ).getChildCount() ).to.equal( 0 );
-			expect( getIteratorCount( root.getChild( 1 ).getAttrs() ) ).to.equal( 1 );
-			expect( root.getChild( 1 ).getAttr( 'key' ) ).to.equal( 'value' );
-		} );
-
-		it( 'should throw if we try to split a root', () => {
-			expect( () => {
-				doc.batch().split( new Position( root, [ 0 ] ) );
-			} ).to.throw( CKEditorError, /^batch-split-root/ );
-		} );
-
-		it( 'should be chainable', () => {
-			const batch = doc.batch();
-
-			const chain = batch.split( new Position( root, [ 0, 3 ] ) );
-			expect( chain ).to.equal( batch );
-		} );
-	} );
-} );

+ 0 - 186
packages/ckeditor5-utils/tests/document/document/change-event.js

@@ -1,186 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/element',
-	'document/rootelement',
-	'document/attribute',
-	'document/position',
-	'document/range',
-	'document/operation/changeoperation',
-	'document/operation/insertoperation',
-	'document/operation/moveoperation',
-	'document/operation/reinsertoperation',
-	'document/operation/removeoperation'
-);
-
-describe( 'Document change event', () => {
-	let Document, RootElement, Element, Range, Position;
-	let ChangeOperation, InsertOperation, MoveOperation, ReinsertOperation, RemoveOperation, Attribute;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		Element = modules[ 'document/element' ];
-		RootElement = modules[ 'document/rootelement' ];
-		Attribute = modules[ 'document/attribute' ];
-		Position = modules[ 'document/position' ];
-		Range = modules[ 'document/range' ];
-
-		InsertOperation = modules[ 'document/operation/insertoperation' ];
-		ChangeOperation = modules[ 'document/operation/changeoperation' ];
-		MoveOperation = modules[ 'document/operation/moveoperation' ];
-		ReinsertOperation = modules[ 'document/operation/reinsertoperation' ];
-		RemoveOperation = modules[ 'document/operation/removeoperation' ];
-	} );
-
-	let doc, root, graveyard, types, changes;
-
-	beforeEach( () => {
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-		graveyard = doc._graveyard;
-
-		types = [];
-		changes = [];
-
-		doc.on( 'change', ( evt, type, change ) => {
-			types.push( type );
-			changes.push( change );
-		} );
-	} );
-
-	it( 'should be fired when text is inserted', () => {
-		doc.applyOperation( new InsertOperation( new Position( [ 0 ], root ), 'foo', doc.version ) );
-
-		expect( changes ).to.have.length( 1 );
-		expect( types[ 0 ] ).to.equal( 'insert' );
-		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 3 ) );
-	} );
-
-	it( 'should be fired when element is inserted', () => {
-		const element = new Element( 'p' );
-		doc.applyOperation( new InsertOperation( new Position( [ 0 ], root ), element, doc.version ) );
-
-		expect( changes ).to.have.length( 1 );
-		expect( types[ 0 ] ).to.equal( 'insert' );
-		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 1 ) );
-	} );
-
-	it( 'should be fired when nodes are inserted', () => {
-		const element = new Element( 'p' );
-		doc.applyOperation( new InsertOperation( new Position( [ 0 ], root ), [ element, 'foo' ], doc.version ) );
-
-		expect( changes ).to.have.length( 1 );
-		expect( types[ 0 ] ).to.equal( 'insert' );
-		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 4 ) );
-	} );
-
-	it( 'should be fired when nodes are moved', () => {
-		const p1 = new Element( 'p' );
-		p1.insertChildren( 0, [ new Element( 'p' ), 'foo' ] );
-
-		const p2 = new Element( 'p' );
-
-		root.insertChildren( 0, [ p1, p2 ] );
-
-		doc.applyOperation(
-			new MoveOperation(
-				new Position( [ 0, 0 ], root ),
-				new Position( [ 1, 0 ], root ),
-				3,
-				doc.version
-			)
-		);
-
-		expect( changes ).to.have.length( 1 );
-		expect( types[ 0 ] ).to.equal( 'move' );
-		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( p2, 0, p2, 3 ) );
-		expect( changes[ 0 ].sourcePosition ).to.deep.equal( Position.createFromParentAndOffset( p1, 0 ) );
-	} );
-
-	it( 'should be fired when multiple nodes are removed and reinserted', () => {
-		root.insertChildren( 0, 'foo' );
-
-		const removeOperation = new RemoveOperation( new Position( [ 0 ], root ), 3, doc.version );
-		doc.applyOperation( removeOperation );
-
-		const reinsertOperation = removeOperation.getReversed();
-		doc.applyOperation( reinsertOperation );
-
-		expect( changes ).to.have.length( 2 );
-
-		expect( types[ 0 ] ).to.equal( 'remove' );
-		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( graveyard, 0, graveyard, 3 ) );
-		expect( changes[ 0 ].sourcePosition ).to.deep.equal( Position.createFromParentAndOffset( root, 0 ) );
-
-		expect( types[ 1 ] ).to.equal( 'reinsert' );
-		expect( changes[ 1 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 3 ) );
-		expect( changes[ 1 ].sourcePosition ).to.deep.equal( Position.createFromParentAndOffset( graveyard, 0 ) );
-	} );
-
-	it( 'should be fired when attribute is inserted', () => {
-		root.insertChildren( 0, 'foo' );
-
-		doc.applyOperation(
-			new ChangeOperation(
-				Range.createFromParentsAndOffsets( root, 0, root, 3 ),
-				null,
-				new Attribute( 'key', 'new' ),
-				doc.version
-			)
-		);
-
-		expect( changes ).to.have.length( 1 );
-		expect( types[ 0 ] ).to.equal( 'attr' );
-		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 3 ) );
-		expect( changes[ 0 ].oldAttr ).to.be.null;
-		expect( changes[ 0 ].newAttr ).to.deep.equal( new Attribute( 'key', 'new' ) );
-	} );
-
-	it( 'should be fired when attribute is removed', () => {
-		const elem = new Element( 'p', [ new Attribute( 'key', 'old' ) ] );
-		root.insertChildren( 0, elem );
-
-		doc.applyOperation(
-			new ChangeOperation(
-				Range.createFromParentsAndOffsets( root, 0, elem, 0 ),
-				new Attribute( 'key', 'old' ),
-				null,
-				doc.version
-			)
-		);
-
-		expect( changes ).to.have.length( 1 );
-		expect( types[ 0 ] ).to.equal( 'attr' );
-		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, elem, 0 ) );
-		expect( changes[ 0 ].oldAttr ).to.deep.equal( new Attribute( 'key', 'old' ) );
-		expect( changes[ 0 ].newAttr ).to.be.null;
-	}  );
-
-	it( 'should be fired when attribute changes', () => {
-		const elem = new Element( 'p', [ new Attribute( 'key', 'old' ) ] );
-		root.insertChildren( 0, elem );
-
-		doc.applyOperation(
-			new ChangeOperation(
-				Range.createFromParentsAndOffsets( root, 0, elem, 0 ),
-				new Attribute( 'key', 'old' ),
-				new Attribute( 'key', 'new' ),
-				doc.version
-			)
-		);
-
-		expect( changes ).to.have.length( 1 );
-		expect( types[ 0 ] ).to.equal( 'attr' );
-		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, elem, 0 ) );
-		expect( changes[ 0 ].oldAttr ).to.deep.equal( new Attribute( 'key', 'old' ) );
-		expect( changes[ 0 ].newAttr ).to.deep.equal( new Attribute( 'key', 'new' ) );
-	}  );
-} );

+ 0 - 123
packages/ckeditor5-utils/tests/document/document/document.js

@@ -1,123 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/rootelement',
-	'document/batch',
-	'ckeditorerror'
-);
-
-describe( 'Document', () => {
-	let Document, RootElement, Batch, CKEditorError;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		RootElement = modules[ 'document/rootelement' ];
-		Batch = modules[ 'document/batch' ];
-		CKEditorError = modules.ckeditorerror;
-	} );
-
-	let document;
-
-	beforeEach( () => {
-		document = new Document();
-	} );
-
-	describe( 'constructor', () => {
-		it( 'should create Document with no data and empty graveyard', () => {
-			expect( document ).to.have.property( 'roots' ).that.is.instanceof( Map );
-			expect( document.roots.size ).to.equal( 1 );
-			expect( document._graveyard ).to.be.instanceof( RootElement );
-			expect( document._graveyard.getChildCount() ).to.equal( 0 );
-		} );
-	} );
-
-	describe( 'createRoot', () => {
-		it( 'should create a new RootElement, add it to roots map and return it', () => {
-			let root = document.createRoot( 'root' );
-
-			expect( document.roots.size ).to.equal( 2 );
-			expect( root ).to.be.instanceof( RootElement );
-			expect( root.getChildCount() ).to.equal( 0 );
-		} );
-
-		it( 'should throw an error when trying to create a second root with the same name', () => {
-			document.createRoot( 'root' );
-
-			expect(
-				() => {
-					document.createRoot( 'root' );
-				}
-			).to.throw( CKEditorError, /document-createRoot-name-exists/ );
-		} );
-	} );
-
-	describe( 'getRoot', () => {
-		it( 'should return a RootElement previously created with given name', () => {
-			let newRoot = document.createRoot( 'root' );
-			let getRoot = document.getRoot( 'root' );
-
-			expect( getRoot ).to.equal( newRoot );
-		} );
-
-		it( 'should throw an error when trying to get non-existent root', () => {
-			expect(
-				() => {
-					document.getRoot( 'root' );
-				}
-			).to.throw( CKEditorError, /document-createRoot-root-not-exist/ );
-		} );
-	} );
-
-	describe( 'applyOperation', () => {
-		it( 'should increase document version, execute operation and fire event with proper data', () => {
-			const changeCallback = sinon.spy();
-			const type = 't';
-			const data = { data: 'x' };
-
-			let operation = {
-				type: type,
-				baseVersion: 0,
-				_execute: sinon.stub().returns( data )
-			};
-
-			document.on( 'change', changeCallback );
-			document.applyOperation( operation );
-
-			expect( document.version ).to.equal( 1 );
-			sinon.assert.calledOnce( operation._execute );
-
-			sinon.assert.calledOnce( changeCallback );
-			expect( changeCallback.args[ 0 ][ 1 ] ).to.equal( type );
-			expect( changeCallback.args[ 0 ][ 2 ] ).to.equal( data );
-		} );
-
-		it( 'should throw an error on the operation base version and the document version is different', () => {
-			let operation = {
-				baseVersion: 1
-			};
-
-			expect(
-				() => {
-					document.applyOperation( operation );
-				}
-			).to.throw( CKEditorError, /document-applyOperation-wrong-version/ );
-		} );
-	} );
-
-	describe( 'batch', () => {
-		it( 'should create a new batch with the document property', () => {
-			const batch = document.batch();
-
-			expect( batch ).to.be.instanceof( Batch );
-			expect( batch ).to.have.property( 'doc' ).that.equals( document );
-		} );
-	} );
-} );

+ 0 - 128
packages/ckeditor5-utils/tests/document/element.js

@@ -1,128 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* jshint expr: true */
-
-/* bender-tags: document */
-
-/* bender-include: ../_tools/tools.js */
-
-'use strict';
-
-const getIteratorCount = bender.tools.core.getIteratorCount;
-
-const modules = bender.amd.require(
-	'document/node',
-	'document/nodelist',
-	'document/element',
-	'document/attribute'
-);
-
-describe( 'Element', () => {
-	let Element, Node, NodeList, Attribute;
-
-	before( () => {
-		Element = modules[ 'document/element' ];
-		Node = modules[ 'document/node' ];
-		NodeList = modules[ 'document/nodelist' ];
-		Attribute = modules[ 'document/attribute' ];
-	} );
-
-	describe( 'constructor', () => {
-		it( 'should create element without attributes', () => {
-			let element = new Element( 'elem' );
-			let parent = new Element( 'parent', [], [ element ] );
-
-			expect( element ).to.be.an.instanceof( Node );
-			expect( element ).to.have.property( 'name' ).that.equals( 'elem' );
-			expect( element ).to.have.property( 'parent' ).that.equals( parent );
-			expect( getIteratorCount( element.getAttrs() ) ).to.equal( 0 );
-		} );
-
-		it( 'should create element with attributes', () => {
-			let attr = new Attribute( 'foo', 'bar' );
-
-			let element = new Element( 'elem', [ attr ] );
-			let parent = new Element( 'parent', [], [ element ] );
-
-			expect( element ).to.be.an.instanceof( Node );
-			expect( element ).to.have.property( 'name' ).that.equals( 'elem' );
-			expect( element ).to.have.property( 'parent' ).that.equals( parent );
-			expect( getIteratorCount( element.getAttrs() ) ).to.equal( 1 );
-			expect( element.getAttr( attr.key ) ).to.equal( attr.value );
-		} );
-
-		it( 'should create element with children', () => {
-			let element = new Element( 'elem', [], 'foo' );
-
-			expect( element ).to.have.property( 'name' ).that.equals( 'elem' );
-			expect( element.getChildCount() ).to.equal( 3 );
-			expect( element.getChild( 0 ) ).to.have.property( 'character' ).that.equals( 'f' );
-			expect( element.getChild( 1 ) ).to.have.property( 'character' ).that.equals( 'o' );
-			expect( element.getChild( 2 ) ).to.have.property( 'character' ).that.equals( 'o' );
-		} );
-	} );
-
-	describe( 'insertChildren', () => {
-		it( 'should add children to the element', () => {
-			let element = new Element( 'elem', [], [ 'xy' ] );
-			element.insertChildren( 1, 'foo' );
-
-			expect( element ).to.have.property( 'name' ).that.equals( 'elem' );
-			expect( element.getChildCount() ).to.equal( 5 );
-			expect( element.getChild( 0 ) ).to.have.property( 'character' ).that.equals( 'x' );
-			expect( element.getChild( 1 ) ).to.have.property( 'character' ).that.equals( 'f' );
-			expect( element.getChild( 2 ) ).to.have.property( 'character' ).that.equals( 'o' );
-			expect( element.getChild( 3 ) ).to.have.property( 'character' ).that.equals( 'o' );
-			expect( element.getChild( 4 ) ).to.have.property( 'character' ).that.equals( 'y' );
-		} );
-	} );
-
-	describe( 'removeChildren', () => {
-		it( 'should remove children from the element and return them as a NodeList', () => {
-			let element = new Element( 'elem', [], [ 'foobar' ] );
-			let o = element.getChild( 2 );
-			let b = element.getChild( 3 );
-			let a = element.getChild( 4 );
-			let removed = element.removeChildren( 2, 3 );
-
-			expect( element.getChildCount() ).to.equal( 3 );
-			expect( element.getChild( 0 ) ).to.have.property( 'character' ).that.equals( 'f' );
-			expect( element.getChild( 1 ) ).to.have.property( 'character' ).that.equals( 'o' );
-			expect( element.getChild( 2 ) ).to.have.property( 'character' ).that.equals( 'r' );
-
-			expect( o ).to.have.property( 'parent' ).that.is.null;
-			expect( b ).to.have.property( 'parent' ).that.is.null;
-			expect( a ).to.have.property( 'parent' ).that.is.null;
-
-			expect( removed ).to.be.instanceof( NodeList );
-			expect( removed.length ).to.equal( 3 );
-			expect( removed.get( 0 ) ).to.equal( o );
-			expect( removed.get( 1 ) ).to.equal( b );
-			expect( removed.get( 2 ) ).to.equal( a );
-		} );
-	} );
-
-	describe( 'getChildIndex', () => {
-		it( 'should return child index', () => {
-			let element = new Element( 'elem', [], [ 'bar' ] );
-			let b = element.getChild( 0 );
-			let a = element.getChild( 1 );
-			let r = element.getChild( 2 );
-
-			expect( element.getChildIndex( b ) ).to.equal( 0 );
-			expect( element.getChildIndex( a ) ).to.equal( 1 );
-			expect( element.getChildIndex( r ) ).to.equal( 2 );
-		} );
-	} );
-
-	describe( 'getChildCount', () => {
-		it( 'should return number of children', () => {
-			let element = new Element( 'elem', [], [ 'bar' ] );
-
-			expect( element.getChildCount() ).to.equal( 3 );
-		} );
-	} );
-} );

+ 0 - 276
packages/ckeditor5-utils/tests/document/node.js

@@ -1,276 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-
-/* bender-include: ../_tools/tools.js */
-
-'use strict';
-
-const getIteratorCount = bender.tools.core.getIteratorCount;
-
-const modules = bender.amd.require(
-	'document/element',
-	'document/character',
-	'document/attribute',
-	'document/nodelist',
-	'ckeditorerror'
-);
-
-describe( 'Node', () => {
-	let Element, Character, Attribute, NodeList, CKEditorError;
-
-	let root;
-	let one, two, three;
-	let charB, charA, charR, img;
-
-	before( () => {
-		Element = modules[ 'document/element' ];
-		Character = modules[ 'document/character' ];
-		Attribute = modules[ 'document/attribute' ];
-		NodeList = modules[ 'document/nodelist' ];
-		CKEditorError = modules.ckeditorerror;
-
-		charB = new Character( 'b' );
-		charA = new Character( 'a' );
-		img = new Element( 'img' );
-		charR = new Character( 'r' );
-
-		one = new Element( 'one' );
-		two = new Element( 'two', null, [ charB, charA, img, charR ] );
-		three = new Element( 'three' );
-
-		root = new Element( null, null, [ one, two, three ] );
-	} );
-
-	describe( 'should have a correct property', () => {
-		it( 'depth', () => {
-			expect( root ).to.have.property( 'depth' ).that.equals( 0 );
-
-			expect( one ).to.have.property( 'depth' ).that.equals( 1 );
-			expect( two ).to.have.property( 'depth' ).that.equals( 1 );
-			expect( three ).to.have.property( 'depth' ).that.equals( 1 );
-
-			expect( charB ).to.have.property( 'depth' ).that.equals( 2 );
-			expect( charA ).to.have.property( 'depth' ).that.equals( 2 );
-			expect( img ).to.have.property( 'depth' ).that.equals( 2 );
-			expect( charR ).to.have.property( 'depth' ).that.equals( 2 );
-		} );
-
-		it( 'root', () => {
-			expect( root ).to.have.property( 'root' ).that.equals( root );
-
-			expect( one ).to.have.property( 'root' ).that.equals( root );
-			expect( two ).to.have.property( 'root' ).that.equals( root );
-			expect( three ).to.have.property( 'root' ).that.equals( root );
-
-			expect( charB ).to.have.property( 'root' ).that.equals( root );
-			expect( charA ).to.have.property( 'root' ).that.equals( root );
-			expect( img ).to.have.property( 'root' ).that.equals( root );
-			expect( charR ).to.have.property( 'root' ).that.equals( root );
-		} );
-
-		it( 'nextSibling', () => {
-			expect( root ).to.have.property( 'nextSibling' ).that.is.null;
-
-			expect( one ).to.have.property( 'nextSibling' ).that.equals( two );
-			expect( two ).to.have.property( 'nextSibling' ).that.equals( three );
-			expect( three ).to.have.property( 'nextSibling' ).that.is.null;
-
-			expect( charB ).to.have.property( 'nextSibling' ).that.equals( charA );
-			expect( charA ).to.have.property( 'nextSibling' ).that.equals( img );
-			expect( img ).to.have.property( 'nextSibling' ).that.equals( charR );
-			expect( charR ).to.have.property( 'nextSibling' ).that.is.null;
-		} );
-
-		it( 'previousSibling', () => {
-			expect( root ).to.have.property( 'previousSibling' ).that.is.expect;
-
-			expect( one ).to.have.property( 'previousSibling' ).that.is.null;
-			expect( two ).to.have.property( 'previousSibling' ).that.equals( one );
-			expect( three ).to.have.property( 'previousSibling' ).that.equals( two );
-
-			expect( charB ).to.have.property( 'previousSibling' ).that.is.null;
-			expect( charA ).to.have.property( 'previousSibling' ).that.equals( charB );
-			expect( img ).to.have.property( 'previousSibling' ).that.equals( charA );
-			expect( charR ).to.have.property( 'previousSibling' ).that.equals( img );
-		} );
-	} );
-
-	describe( 'constructor', () => {
-		it( 'should copy attributes, not pass by reference', () => {
-			let attrs = [ new Attribute( 'attr', true ) ];
-			let foo = new Element( 'foo', attrs );
-			let bar = new Element( 'bar', attrs );
-
-			foo.removeAttr( 'attr' );
-
-			expect( getIteratorCount( foo.getAttrs() ) ).to.equal( 0 );
-			expect( getIteratorCount( bar.getAttrs() ) ).to.equal( 1 );
-		} );
-	} );
-
-	describe( 'getAttr', () => {
-		let fooAttr, element;
-
-		beforeEach( () => {
-			fooAttr = new Attribute( 'foo', true );
-			element = new Element( 'foo', [ fooAttr ] );
-		} );
-
-		it( 'should be possible to get attribute by key', () => {
-			expect( element.getAttr( 'foo' ) ).to.equal( fooAttr.value );
-		} );
-
-		it( 'should return null if attribute was not found by key', () => {
-			expect( element.getAttr( 'bar' ) ).to.be.null;
-		} );
-	} );
-
-	describe( 'setAttr', () => {
-		it( 'should insert an attribute', () => {
-			let element = new Element( 'elem' );
-			let attr = new Attribute( 'foo', 'bar' );
-
-			element.setAttr( attr );
-
-			expect( getIteratorCount( element.getAttrs() ) ).to.equal( 1 );
-			expect( element.getAttr( attr.key ) ).to.equal( attr.value );
-		} );
-
-		it( 'should overwrite attribute with the same key', () => {
-			let oldAttr = new Attribute( 'foo', 'bar' );
-			let newAttr = new Attribute( 'foo', 'bar' );
-			let element = new Element( 'elem', [ oldAttr ] );
-
-			element.setAttr( newAttr );
-
-			expect( getIteratorCount( element.getAttrs() ) ).to.equal( 1 );
-			expect( element.getAttr( newAttr.key ) ).to.equal( newAttr.value );
-		} );
-	} );
-
-	describe( 'removeAttr', () => {
-		it( 'should remove an attribute', () => {
-			let attrA = new Attribute( 'a', 'A' );
-			let attrB = new Attribute( 'b', 'b' );
-			let attrC = new Attribute( 'c', 'C' );
-			let element = new Element( 'elem', [ attrA, attrB, attrC ] );
-
-			element.removeAttr( attrB.key );
-
-			expect( getIteratorCount( element.getAttrs() ) ).to.equal( 2 );
-			expect( element.getAttr( attrA.key ) ).to.equal( attrA.value );
-			expect( element.getAttr( attrC.key ) ).to.equal( attrC.value );
-			expect( element.getAttr( attrB.key ) ).to.be.null;
-		} );
-	} );
-
-	describe( 'hasAttr', () => {
-		it( 'should check attribute by key', () => {
-			let fooAttr = new Attribute( 'foo', true );
-			let element = new Element( 'foo', [ fooAttr ] );
-
-			expect( element.hasAttr( 'foo' ) ).to.be.true;
-		} );
-
-		it( 'should return false if attribute was not found by key', () => {
-			let fooAttr = new Attribute( 'foo', true );
-			let element = new Element( 'foo', [ fooAttr ] );
-
-			expect( element.hasAttr( 'bar' ) ).to.be.false;
-		} );
-
-		it( 'should check attribute by object', () => {
-			let fooAttr = new Attribute( 'foo', true );
-			let foo2Attr = new Attribute( 'foo', true );
-			let element = new Element( 'foo', [ fooAttr ] );
-
-			expect( element.hasAttr( foo2Attr ) ).to.be.true;
-		} );
-
-		it( 'should return false if attribute was not found by object', () => {
-			let fooAttr = new Attribute( 'foo', true );
-			let element = new Element( 'foo' );
-
-			expect( element.hasAttr( fooAttr ) ).to.be.false;
-		} );
-
-		it( 'should create proper JSON string using toJSON method', () => {
-			let b = new Character( 'b' );
-			let foo = new Element( 'foo', [], [ b ] );
-
-			let parsedFoo = JSON.parse( JSON.stringify( foo ) );
-			let parsedBar = JSON.parse( JSON.stringify( b ) );
-
-			expect( parsedFoo.parent ).to.equal( null );
-			expect( parsedBar.parent ).to.equal( 'foo' );
-		} );
-	} );
-
-	describe( 'getAttrs', () => {
-		it( 'should allows to get attribute count', () => {
-			let element = new Element( 'foo', [
-				new Attribute( 1, true ),
-				new Attribute( 2, true ),
-				new Attribute( 3, true )
-			] );
-
-			expect( getIteratorCount( element.getAttrs() ) ).to.equal( 3 );
-		} );
-
-		it( 'should allows to copy attributes', () => {
-			let element = new Element( 'foo', [ new Attribute( 'x', true ) ] );
-			let copy = new Element( 'bar', element.getAttrs() );
-
-			expect( copy.getAttr( 'x' ) ).to.be.true;
-		} );
-	} );
-
-	describe( 'getIndex', () => {
-		it( 'should return null if the parent is null', () => {
-			expect( root.getIndex() ).to.be.null;
-		} );
-
-		it( 'should return index in the parent', () => {
-			expect( one.getIndex() ).to.equal( 0 );
-			expect( two.getIndex() ).to.equal( 1 );
-			expect( three.getIndex() ).to.equal( 2 );
-
-			expect( charB.getIndex() ).to.equal( 0 );
-			expect( charA.getIndex() ).to.equal( 1 );
-			expect( img.getIndex() ).to.equal( 2 );
-			expect( charR.getIndex() ).to.equal( 3 );
-		} );
-
-		it( 'should throw an error if parent does not contains element', () => {
-			let f = new Character( 'f' );
-			let bar = new Element( 'bar', [], [] );
-
-			f.parent = bar;
-
-			expect(
-				() => {
-					f.getIndex();
-				}
-			).to.throw( CKEditorError, /node-not-found-in-parent/ );
-		} );
-	} );
-
-	describe( 'getPath', () => {
-		it( 'should return proper path', () => {
-			expect( root.getPath() ).to.deep.equal( [] );
-
-			expect( one.getPath() ).to.deep.equal( [ 0 ] );
-			expect( two.getPath() ).to.deep.equal( [ 1 ] );
-			expect( three.getPath() ).to.deep.equal( [ 2 ] );
-
-			expect( charB.getPath() ).to.deep.equal( [ 1, 0 ] );
-			expect( charA.getPath() ).to.deep.equal( [ 1, 1 ] );
-			expect( img.getPath() ).to.deep.equal( [ 1, 2 ] );
-			expect( charR.getPath() ).to.deep.equal( [ 1, 3 ] );
-		} );
-	} );
-} );

+ 0 - 115
packages/ckeditor5-utils/tests/document/nodelist.js

@@ -1,115 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/nodelist',
-	'document/character',
-	'document/text',
-	'document/attribute'
-);
-
-describe( 'NodeList', () => {
-	let NodeList, Character, Text, Attribute;
-
-	before( () => {
-		NodeList = modules[ 'document/nodelist' ];
-		Character = modules[ 'document/character' ];
-		Text = modules[ 'document/text' ];
-		Attribute = modules[ 'document/attribute' ];
-	} );
-
-	describe( 'constructor', () => {
-		it( 'should change array of strings into a set of nodes', () => {
-			let nodeList = new NodeList( [ 'foo', new Character( 'x' ), 'bar' ] );
-
-			expect( nodeList.length ).to.equal( 7 );
-			expect( nodeList.get( 0 ).character ).to.equal( 'f' );
-			expect( nodeList.get( 1 ).character ).to.equal( 'o' );
-			expect( nodeList.get( 2 ).character ).to.equal( 'o' );
-			expect( nodeList.get( 3 ).character ).to.equal( 'x' );
-			expect( nodeList.get( 4 ).character ).to.equal( 'b' );
-			expect( nodeList.get( 5 ).character ).to.equal( 'a' );
-			expect( nodeList.get( 6 ).character ).to.equal( 'r' );
-		} );
-
-		it( 'should change string into a set of nodes', () => {
-			let nodeList = new NodeList( 'foo' );
-
-			expect( nodeList.length ).to.equal( 3 );
-			expect( nodeList.get( 0 ).character ).to.equal( 'f' );
-			expect( nodeList.get( 1 ).character ).to.equal( 'o' );
-			expect( nodeList.get( 2 ).character ).to.equal( 'o' );
-		} );
-
-		it( 'should change node into a set of nodes', () => {
-			let nodeList = new NodeList( new Character( 'x' ) );
-
-			expect( nodeList.length ).to.equal( 1 );
-			expect( nodeList.get( 0 ).character ).to.equal( 'x' );
-		} );
-
-		it( 'should change text with attribute into a set of nodes', () => {
-			let attr = new Attribute( 'bold', true );
-			let nodeList = new NodeList( new Text( 'foo', [ attr ] ) );
-
-			expect( nodeList.length ).to.equal( 3 );
-			expect( nodeList.get( 0 ).character ).to.equal( 'f' );
-			expect( nodeList.get( 0 ).getAttr( attr.key ) ).to.equal( attr.value );
-			expect( nodeList.get( 1 ).character ).to.equal( 'o' );
-			expect( nodeList.get( 1 ).getAttr( attr.key ) ).to.equal( attr.value );
-			expect( nodeList.get( 2 ).character ).to.equal( 'o' );
-			expect( nodeList.get( 2 ).getAttr( attr.key ) ).to.equal( attr.value );
-		} );
-	} );
-
-	describe( 'insert', () => {
-		it( 'should insert one nodelist into another', () => {
-			let outerList = new NodeList( 'foo' );
-			let innerList = new NodeList( 'xxx' );
-
-			outerList.insert( 2, innerList );
-
-			expect( outerList.length ).to.equal( 6 );
-			expect( outerList.get( 0 ).character ).to.equal( 'f' );
-			expect( outerList.get( 1 ).character ).to.equal( 'o' );
-			expect( outerList.get( 2 ).character ).to.equal( 'x' );
-			expect( outerList.get( 3 ).character ).to.equal( 'x' );
-			expect( outerList.get( 4 ).character ).to.equal( 'x' );
-			expect( outerList.get( 5 ).character ).to.equal( 'o' );
-		} );
-	} );
-
-	describe( 'remove', () => {
-		it( 'should remove part of the nodelist', () => {
-			let nodeList = new NodeList( 'foobar' );
-
-			nodeList.remove( 2, 3 );
-
-			expect( nodeList.length ).to.equal( 3 );
-			expect( nodeList.get( 0 ).character ).to.equal( 'f' );
-			expect( nodeList.get( 1 ).character ).to.equal( 'o' );
-			expect( nodeList.get( 2 ).character ).to.equal( 'r' );
-		} );
-	} );
-
-	describe( 'iterator', () => {
-		it( 'should iterate over all elements in the collection', () => {
-			let characters = 'foo';
-			let nodeList = new NodeList( characters );
-			let i = 0;
-
-			for ( let node of nodeList ) {
-				expect( node.character ).to.equal( characters[ i ] );
-				i++;
-			}
-
-			expect( i ).to.equal( 3 );
-		} );
-	} );
-} );

+ 0 - 385
packages/ckeditor5-utils/tests/document/operation/attributeoperation.js

@@ -1,385 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-/* global describe, before, beforeEach, it, expect */
-
-/* bender-include: ../../_tools/tools.js */
-
-'use strict';
-
-const getIteratorCount = bender.tools.core.getIteratorCount;
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/element',
-	'document/operation/attributeoperation',
-	'document/position',
-	'document/range',
-	'document/character',
-	'document/attribute',
-	'document/text',
-	'ckeditorerror'
-);
-
-describe( 'AttributeOperation', () => {
-	let Document, Element, AttributeOperation, Position, Range, Character, Attribute, Text, CKEditorError;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		Element = modules[ 'document/element' ];
-		AttributeOperation = modules[ 'document/operation/attributeoperation' ];
-		Position = modules[ 'document/position' ];
-		Range = modules[ 'document/range' ];
-		Character = modules[ 'document/character' ];
-		Attribute = modules[ 'document/attribute' ];
-		Text = modules[ 'document/text' ];
-		CKEditorError = modules.ckeditorerror;
-	} );
-
-	let doc, root;
-
-	beforeEach( () => {
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-	} );
-
-	it( 'should have proper type', () => {
-		const op = new AttributeOperation(
-			new Range( new Position( root, [ 0 ] ), new Position( root, [ 2 ] ) ),
-			null,
-			new Attribute( 'isNew', true ),
-			doc.version
-		);
-
-		expect( op.type ).to.equal( 'attr' );
-	} );
-
-	it( 'should insert attribute to the set of nodes', () => {
-		let newAttr = new Attribute( 'isNew', true );
-
-		root.insertChildren( 0, 'bar' );
-
-		doc.applyOperation(
-			new AttributeOperation(
-				new Range( new Position( root, [ 0 ] ), new Position( root, [ 2 ] ) ),
-				null,
-				newAttr,
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 3 );
-		expect( root.getChild( 0 ).hasAttr( newAttr ) ).to.be.true;
-		expect( root.getChild( 1 ).hasAttr( newAttr ) ).to.be.true;
-		expect( getIteratorCount( root.getChild( 2 ).getAttrs() ) ).to.equal( 0 );
-	} );
-
-	it( 'should add attribute to the existing attributes', () => {
-		let newAttr = new Attribute( 'isNew', true );
-		let fooAttr = new Attribute( 'foo', true );
-		let barAttr = new Attribute( 'bar', true );
-
-		root.insertChildren( 0, new Character( 'x', [ fooAttr, barAttr ] ) );
-
-		doc.applyOperation(
-			new AttributeOperation(
-				new Range( new Position( root, [ 0 ] ), new Position( root, [ 1 ] ) ),
-				null,
-				newAttr,
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 1 );
-		expect( getIteratorCount( root.getChild( 0 ).getAttrs() ) ).to.equal( 3 );
-		expect( root.getChild( 0 ).hasAttr( newAttr ) ).to.be.true;
-		expect( root.getChild( 0 ).hasAttr( fooAttr ) ).to.be.true;
-		expect( root.getChild( 0 ).hasAttr( barAttr ) ).to.be.true;
-	} );
-
-	it( 'should change attribute to the set of nodes', () => {
-		let oldAttr = new Attribute( 'isNew', false );
-		let newAttr = new Attribute( 'isNew', true );
-
-		root.insertChildren( 0, new Text( 'bar', [ oldAttr ] ) );
-
-		doc.applyOperation(
-			new AttributeOperation(
-				new Range( new Position( root, [ 0 ] ), new Position( root, [ 2 ] ) ),
-				oldAttr,
-				newAttr,
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 3 );
-		expect( getIteratorCount( root.getChild( 0 ).getAttrs() ) ).to.equal( 1 );
-		expect( root.getChild( 0 ).hasAttr( newAttr ) ).to.be.true;
-		expect( getIteratorCount( root.getChild( 1 ).getAttrs() ) ).to.equal( 1 );
-		expect( root.getChild( 1 ).hasAttr( newAttr ) ).to.be.true;
-		expect( getIteratorCount( root.getChild( 2 ).getAttrs() ) ).to.equal( 1 );
-		expect( root.getChild( 2 ).hasAttr( oldAttr ) ).to.be.true;
-	} );
-
-	it( 'should change attribute in the middle of existing attributes', () => {
-		let fooAttr = new Attribute( 'foo', true );
-		let x1Attr = new Attribute( 'x', 1 );
-		let x2Attr = new Attribute( 'x', 2 );
-		let barAttr = new Attribute( 'bar', true );
-
-		root.insertChildren( 0, new Character( 'x', [ fooAttr, x1Attr, barAttr ] ) );
-
-		doc.applyOperation(
-			new AttributeOperation(
-				new Range( new Position( root, [ 0 ] ), new Position( root, [ 1 ] ) ),
-				x1Attr,
-				x2Attr,
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 1 );
-		expect( getIteratorCount( root.getChild( 0 ).getAttrs() ) ).to.equal( 3 );
-		expect( root.getChild( 0 ).hasAttr( fooAttr ) ).to.be.true;
-		expect( root.getChild( 0 ).hasAttr( x2Attr ) ).to.be.true;
-		expect( root.getChild( 0 ).hasAttr( barAttr ) ).to.be.true;
-	} );
-
-	it( 'should remove attribute', () => {
-		let fooAttr = new Attribute( 'foo', true );
-		let xAttr = new Attribute( 'x', true );
-		let barAttr = new Attribute( 'bar', true );
-
-		root.insertChildren( 0, new Character( 'x', [ fooAttr, xAttr, barAttr ] ) );
-
-		doc.applyOperation(
-			new AttributeOperation(
-				new Range( new Position( root, [ 0 ] ), new Position( root, [ 1 ] ) ),
-				xAttr,
-				null,
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 1 );
-		expect( getIteratorCount( root.getChild( 0 ).getAttrs() ) ).to.equal( 2 );
-		expect( root.getChild( 0 ).hasAttr( fooAttr ) ).to.be.true;
-		expect( root.getChild( 0 ).hasAttr( barAttr ) ).to.be.true;
-	} );
-
-	it( 'should create an AttributeOperation as a reverse', () => {
-		let oldAttr = new Attribute( 'x', 'old' );
-		let newAttr = new Attribute( 'x', 'new' );
-		let range = new Range( new Position( root, [ 0 ] ), new Position( root, [ 3 ] ) );
-		let operation = new AttributeOperation( range, oldAttr, newAttr, doc.version );
-		let reverse = operation.getReversed();
-
-		expect( reverse ).to.be.an.instanceof( AttributeOperation );
-		expect( reverse.baseVersion ).to.equal( 1 );
-		expect( reverse.range ).to.equal( range );
-		expect( reverse.oldAttr ).to.equal( newAttr );
-		expect( reverse.newAttr ).to.equal( oldAttr );
-	} );
-
-	it( 'should undo adding attribute by applying reverse operation', () => {
-		let newAttr = new Attribute( 'isNew', true );
-
-		root.insertChildren( 0, 'bar' );
-
-		let operation = new AttributeOperation(
-			new Range( new Position( root, [ 0 ] ), new Position( root, [ 3 ] ) ),
-			null,
-			newAttr,
-			doc.version
-		);
-
-		let reverse = operation.getReversed();
-
-		doc.applyOperation( operation );
-		doc.applyOperation( reverse );
-
-		expect( doc.version ).to.equal( 2 );
-		expect( root.getChildCount() ).to.equal( 3 );
-		expect( getIteratorCount( root.getChild( 0 ).getAttrs() ) ).to.equal( 0 );
-		expect( getIteratorCount( root.getChild( 1 ).getAttrs() ) ).to.equal( 0 );
-		expect( getIteratorCount( root.getChild( 2 ).getAttrs() ) ).to.equal( 0 );
-	} );
-
-	it( 'should not set attribute of element if change range starts in the middle of that element', () => {
-		let fooAttr = new Attribute( 'foo', true );
-
-		let eleA = new Element( 'a', [], 'abc' );
-		let eleB = new Element( 'b', [], 'xyz' );
-
-		root.insertChildren( 0, [ eleA, eleB ] );
-
-		doc.applyOperation(
-			new AttributeOperation(
-				new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 1, 2 ] ) ),
-				null,
-				fooAttr,
-				doc.version
-			)
-		);
-
-		expect( root.getChild( 0 ).hasAttr( fooAttr ) ).to.be.false;
-	} );
-
-	it( 'should not remove attribute of element if change range starts in the middle of that element', () => {
-		let fooAttr = new Attribute( 'foo', true );
-
-		let eleA = new Element( 'a', [ fooAttr ], 'abc' );
-		let eleB = new Element( 'b', [ fooAttr ], 'xyz' );
-
-		root.insertChildren( 0, [ eleA, eleB ] );
-
-		doc.applyOperation(
-			new AttributeOperation(
-				new Range( new Position( root, [ 0, 3 ] ), new Position( root, [ 1, 0 ] ) ),
-				fooAttr,
-				null,
-				doc.version
-			)
-		);
-
-		expect( root.getChild( 0 ).hasAttr( fooAttr ) ).to.be.true;
-	} );
-
-	it( 'should undo changing attribute by applying reverse operation', () => {
-		let oldAttr = new Attribute( 'isNew', false );
-		let newAttr = new Attribute( 'isNew', true );
-
-		root.insertChildren( 0, new Text( 'bar', [ oldAttr ] ) );
-
-		let operation = new AttributeOperation(
-			new Range( new Position( root, [ 0 ] ), new Position( root, [ 3 ] ) ),
-			oldAttr,
-			newAttr,
-			doc.version
-		);
-
-		let reverse = operation.getReversed();
-
-		doc.applyOperation( operation );
-
-		doc.applyOperation( reverse );
-
-		expect( doc.version ).to.equal( 2 );
-		expect( root.getChildCount() ).to.equal( 3 );
-		expect( getIteratorCount( root.getChild( 0 ).getAttrs() ) ).to.equal( 1 );
-		expect( root.getChild( 0 ).hasAttr( oldAttr ) ).to.be.true;
-		expect( getIteratorCount( root.getChild( 1 ).getAttrs() ) ).to.equal( 1 );
-		expect( root.getChild( 1 ).hasAttr( oldAttr ) ).to.be.true;
-		expect( getIteratorCount( root.getChild( 2 ).getAttrs() ) ).to.equal( 1 );
-		expect( root.getChild( 2 ).hasAttr( oldAttr ) ).to.be.true;
-	} );
-
-	it( 'should undo remove attribute by applying reverse operation', () => {
-		let fooAttr = new Attribute( 'foo', false );
-
-		root.insertChildren( 0, new Text( 'bar', [ fooAttr ] ) );
-
-		let operation = new AttributeOperation(
-			new Range( new Position( root, [ 0 ] ), new Position( root, [ 3 ] ) ),
-			fooAttr,
-			null,
-			doc.version
-		);
-
-		let reverse = operation.getReversed();
-
-		doc.applyOperation( operation );
-
-		doc.applyOperation( reverse );
-
-		expect( doc.version ).to.equal( 2 );
-		expect( root.getChildCount() ).to.equal( 3 );
-		expect( getIteratorCount( root.getChild( 0 ).getAttrs() ) ).to.equal( 1 );
-		expect( root.getChild( 0 ).hasAttr( fooAttr ) ).to.be.true;
-		expect( getIteratorCount( root.getChild( 1 ).getAttrs() ) ).to.equal( 1 );
-		expect( root.getChild( 1 ).hasAttr( fooAttr ) ).to.be.true;
-		expect( getIteratorCount( root.getChild( 2 ).getAttrs() ) ).to.equal( 1 );
-		expect( root.getChild( 2 ).hasAttr( fooAttr ) ).to.be.true;
-	} );
-
-	it( 'should throw an error when one try to remove and the attribute does not exists', () => {
-		let fooAttr = new Attribute( 'foo', true );
-
-		root.insertChildren( 0, 'x' );
-
-		expect( () => {
-			doc.applyOperation(
-				new AttributeOperation(
-					new Range( new Position( root, [ 0 ] ), new Position( root, [ 1 ] ) ),
-					fooAttr,
-					null,
-					doc.version
-				)
-			);
-		} ).to.throw( CKEditorError, /operation-attribute-no-attr-to-remove/ );
-	} );
-
-	it( 'should throw an error when one try to insert and the attribute already exists', () => {
-		let x1Attr = new Attribute( 'x', 1 );
-		let x2Attr = new Attribute( 'x', 2 );
-
-		root.insertChildren( 0, new Character( 'x', [ x1Attr ] ) );
-
-		expect( () => {
-			doc.applyOperation(
-				new AttributeOperation(
-					new Range( new Position( root, [ 0 ] ), new Position( root, [ 1 ] ) ),
-					null,
-					x2Attr,
-					doc.version
-				)
-			);
-		} ).to.throw( CKEditorError, /operation-attribute-attr-exists/ );
-	} );
-
-	it( 'should throw an error when one try to change and the new and old attributes have different keys', () => {
-		let fooAttr = new Attribute( 'foo', true );
-		let barAttr = new Attribute( 'bar', true );
-
-		root.insertChildren( 0, 'x' );
-
-		expect( () => {
-			doc.applyOperation(
-				new AttributeOperation(
-					new Range( new Position( root, [ 0 ] ), new Position( root, [ 1 ] ) ),
-					fooAttr,
-					barAttr,
-					doc.version
-				)
-			);
-		} ).to.throw( CKEditorError, /operation-attribute-different-keys/ );
-	} );
-
-	it( 'should create an AttributeOperation with the same parameters when cloned', () => {
-		let range = new Range( new Position( root, [ 0 ] ), new Position( root, [ 1 ] ) );
-		let oldAttr = new Attribute( 'foo', 'old' );
-		let newAttr = new Attribute( 'foo', 'bar' );
-		let baseVersion = doc.version;
-
-		let op = new AttributeOperation( range, oldAttr, newAttr, baseVersion );
-
-		let clone = op.clone();
-
-		// New instance rather than a pointer to the old instance.
-		expect( clone ).not.to.be.equal( op );
-
-		expect( clone ).to.be.instanceof( AttributeOperation );
-		expect( clone.range.isEqual( range ) ).to.be.true;
-		expect( clone.oldAttr.isEqual( oldAttr ) ).to.be.true;
-		expect( clone.newAttr.isEqual( newAttr ) ).to.be.true;
-		expect( clone.baseVersion ).to.equal( baseVersion );
-	} );
-} );

+ 0 - 197
packages/ckeditor5-utils/tests/document/operation/insertoperation.js

@@ -1,197 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-/* global describe, before, beforeEach, it, expect */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/node',
-	'document/nodelist',
-	'document/operation/insertoperation',
-	'document/operation/removeoperation',
-	'document/position',
-	'document/character',
-	'document/nodelist'
-);
-
-describe( 'InsertOperation', () => {
-	let Document, Node, NodeList, InsertOperation, RemoveOperation, Position, Character;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		Node = modules[ 'document/node' ];
-		NodeList = modules[ 'document/nodelist' ];
-		InsertOperation = modules[ 'document/operation/insertoperation' ];
-		RemoveOperation = modules[ 'document/operation/removeoperation' ];
-		Position = modules[ 'document/position' ];
-		Character = modules[ 'document/character' ];
-	} );
-
-	let doc, root;
-
-	beforeEach( () => {
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-	} );
-
-	it( 'should have proper type', () => {
-		const opp = new InsertOperation(
-			new Position( root, [ 0 ] ),
-			new Character( 'x' ),
-			doc.version
-		);
-
-		expect( opp.type ).to.equal( 'insert' );
-	} );
-
-	it( 'should insert node', () => {
-		doc.applyOperation(
-			new InsertOperation(
-				new Position( root, [ 0 ] ),
-				new Character( 'x' ),
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 1 );
-		expect( root.getChild( 0 ).character ).to.equal( 'x' );
-	} );
-
-	it( 'should insert set of nodes', () => {
-		doc.applyOperation(
-			new InsertOperation(
-				new Position( root, [ 0 ] ),
-				'bar',
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 3 );
-		expect( root.getChild( 0 ).character ).to.equal( 'b' );
-		expect( root.getChild( 1 ).character ).to.equal( 'a' );
-		expect( root.getChild( 2 ).character ).to.equal( 'r' );
-	} );
-
-	it( 'should insert between existing nodes', () => {
-		root.insertChildren( 0, 'xy' );
-
-		doc.applyOperation(
-			new InsertOperation(
-				new Position( root, [ 1 ] ),
-				'bar',
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 5 );
-		expect( root.getChild( 0 ).character ).to.equal( 'x' );
-		expect( root.getChild( 1 ).character ).to.equal( 'b' );
-		expect( root.getChild( 2 ).character ).to.equal( 'a' );
-		expect( root.getChild( 3 ).character ).to.equal( 'r' );
-		expect( root.getChild( 4 ).character ).to.equal( 'y' );
-	} );
-
-	it( 'should insert text', () => {
-		doc.applyOperation(
-			new InsertOperation(
-				new Position( root, [ 0 ] ),
-				[ 'foo', new Character( 'x' ), 'bar' ],
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 7 );
-		expect( root.getChild( 0 ).character ).to.equal( 'f' );
-		expect( root.getChild( 1 ).character ).to.equal( 'o' );
-		expect( root.getChild( 2 ).character ).to.equal( 'o' );
-		expect( root.getChild( 3 ).character ).to.equal( 'x' );
-		expect( root.getChild( 4 ).character ).to.equal( 'b' );
-		expect( root.getChild( 5 ).character ).to.equal( 'a' );
-		expect( root.getChild( 6 ).character ).to.equal( 'r' );
-	} );
-
-	it( 'should create a remove operation as a reverse', () => {
-		let position = new Position( root, [ 0 ] );
-		let operation = new InsertOperation(
-			position,
-			[ 'foo', new Character( 'x' ), 'bar' ],
-			0
-		);
-
-		let reverse = operation.getReversed();
-
-		expect( reverse ).to.be.an.instanceof( RemoveOperation );
-		expect( reverse.baseVersion ).to.equal( 1 );
-		expect( reverse.sourcePosition ).to.equal( position );
-		expect( reverse.howMany ).to.equal( 7 );
-	} );
-
-	it( 'should undo insert node by applying reverse operation', () => {
-		let operation = new InsertOperation(
-			new Position( root, [ 0 ] ),
-			new Character( 'x' ),
-			doc.version
-		);
-
-		let reverse = operation.getReversed();
-
-		doc.applyOperation( operation );
-
-		expect( doc.version ).to.equal( 1 );
-
-		doc.applyOperation( reverse );
-
-		expect( doc.version ).to.equal( 2 );
-		expect( root.getChildCount() ).to.equal( 0 );
-	} );
-
-	it( 'should undo insert set of nodes by applying reverse operation', () => {
-		let operation = new InsertOperation(
-			new Position( root, [ 0 ] ),
-			'bar',
-			doc.version
-		);
-
-		let reverse = operation.getReversed();
-
-		doc.applyOperation( operation );
-
-		expect( doc.version ).to.equal( 1 );
-
-		doc.applyOperation( reverse );
-
-		expect( doc.version ).to.equal( 2 );
-		expect( root.getChildCount() ).to.equal( 0 );
-	} );
-
-	it( 'should create operation with the same parameters when cloned', () => {
-		let position = new Position( root, [ 0 ] );
-		let nodeA = new Node();
-		let nodeB = new Node();
-		let nodes = new NodeList( [ nodeA, nodeB ] );
-		let baseVersion = doc.version;
-
-		let op = new InsertOperation( position, nodes, baseVersion );
-
-		let clone = op.clone();
-
-		// New instance rather than a pointer to the old instance.
-		expect( clone ).not.to.be.equal( op );
-
-		expect( clone ).to.be.instanceof( InsertOperation );
-		expect( clone.position.isEqual( position ) ).to.be.true;
-		expect( clone.nodeList.get( 0 ) ).to.equal( nodeA );
-		expect( clone.nodeList.get( 1 ) ).to.equal( nodeB );
-		expect( clone.nodeList.length ).to.equal( 2 );
-		expect( clone.baseVersion ).to.equal( baseVersion );
-	} );
-} );

+ 0 - 261
packages/ckeditor5-utils/tests/document/operation/moveoperation.js

@@ -1,261 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-/* global describe, before, beforeEach, it, expect */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/operation/moveoperation',
-	'document/position',
-	'document/element',
-	'document/nodelist',
-	'ckeditorerror'
-);
-
-describe( 'MoveOperation', () => {
-	let Document, MoveOperation, Position, Element, NodeList, CKEditorError;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		MoveOperation = modules[ 'document/operation/moveoperation' ];
-		Position = modules[ 'document/position' ];
-		Element = modules[ 'document/element' ];
-		NodeList = modules[ 'document/nodelist' ];
-		CKEditorError = modules.ckeditorerror;
-	} );
-
-	let doc, root;
-
-	beforeEach( () => {
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-	} );
-
-	it( 'should have proper type', () => {
-		const opp = new MoveOperation(
-			new Position( root, [ 0, 0 ] ),
-			new Position( root, [ 1, 0 ] ),
-			1,
-			doc.version
-		);
-
-		expect( opp.type ).to.equal( 'move' );
-	} );
-
-	it( 'should move from one node to another', () => {
-		let p1 = new Element( 'p1', [], new Element( 'x' ) );
-		let p2 = new Element( 'p2' );
-
-		root.insertChildren( 0, [ p1, p2 ] );
-
-		doc.applyOperation(
-			new MoveOperation(
-				new Position( root, [ 0, 0 ] ),
-				1,
-				new Position( root, [ 1, 0 ] ),
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 2 );
-		expect( root.getChild( 0 ).name ).to.equal( 'p1' );
-		expect( root.getChild( 1 ).name ).to.equal( 'p2' );
-		expect( p1.getChildCount() ).to.equal( 0 );
-		expect( p2.getChildCount() ).to.equal( 1 );
-		expect( p2.getChild( 0 ).name ).to.equal( 'x' );
-	} );
-
-	it( 'should move position of children in one node backward', () => {
-		root.insertChildren( 0, 'xbarx' );
-
-		doc.applyOperation(
-			new MoveOperation(
-				new Position( root, [ 2 ] ),
-				2,
-				new Position( root, [ 1 ] ),
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 5 );
-		expect( root.getChild( 0 ).character ).to.equal( 'x' );
-		expect( root.getChild( 1 ).character ).to.equal( 'a' );
-		expect( root.getChild( 2 ).character ).to.equal( 'r' );
-		expect( root.getChild( 3 ).character ).to.equal( 'b' );
-		expect( root.getChild( 4 ).character ).to.equal( 'x' );
-	} );
-
-	it( 'should move position of children in one node forward', () => {
-		root.insertChildren( 0, 'xbarx' );
-
-		doc.applyOperation(
-			new MoveOperation(
-				new Position( root, [ 1 ] ),
-				2,
-				new Position( root, [ 4 ] ),
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 5 );
-		expect( root.getChild( 0 ).character ).to.equal( 'x' );
-		expect( root.getChild( 1 ).character ).to.equal( 'r' );
-		expect( root.getChild( 2 ).character ).to.equal( 'b' );
-		expect( root.getChild( 3 ).character ).to.equal( 'a' );
-		expect( root.getChild( 4 ).character ).to.equal( 'x' );
-	} );
-
-	it( 'should create a move operation as a reverse', () => {
-		let nodeList = new NodeList( 'bar' );
-
-		let sourcePosition = new Position( root, [ 0 ] );
-		let targetPosition = new Position( root, [ 4 ] );
-
-		let operation = new MoveOperation( sourcePosition, nodeList.length, targetPosition, doc.version );
-
-		let reverse = operation.getReversed();
-
-		expect( reverse ).to.be.an.instanceof( MoveOperation );
-		expect( reverse.baseVersion ).to.equal( 1 );
-		expect( reverse.howMany ).to.equal( nodeList.length );
-		expect( reverse.sourcePosition.isEqual( targetPosition ) ).to.be.true;
-		expect( reverse.targetPosition.isEqual( sourcePosition ) ).to.be.true;
-	} );
-
-	it( 'should undo move node by applying reverse operation', () => {
-		let p1 = new Element( 'p1', [], new Element( 'x' ) );
-		let p2 = new Element( 'p2' );
-
-		root.insertChildren( 0, [ p1, p2 ] );
-
-		let operation = new MoveOperation(
-			new Position( root, [ 0, 0 ] ),
-			1,
-			new Position( root, [ 1, 0 ] ),
-			doc.version
-		);
-
-		doc.applyOperation( operation );
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 2 );
-		expect( p1.getChildCount() ).to.equal( 0 );
-		expect( p2.getChildCount() ).to.equal( 1 );
-		expect( p2.getChild( 0 ).name ).to.equal( 'x' );
-
-		doc.applyOperation( operation.getReversed() );
-
-		expect( doc.version ).to.equal( 2 );
-		expect( root.getChildCount() ).to.equal( 2 );
-		expect( p1.getChildCount() ).to.equal( 1 );
-		expect( p1.getChild( 0 ).name ).to.equal( 'x' );
-		expect( p2.getChildCount() ).to.equal( 0 );
-	} );
-
-	it( 'should throw an error if number of nodes to move exceeds the number of existing nodes in given element', () => {
-		root.insertChildren( 0, 'xbarx' );
-
-		let operation = new MoveOperation(
-			new Position( root, [ 3 ] ),
-			3,
-			new Position( root, [ 1 ] ),
-			doc.version
-		);
-
-		expect( () => doc.applyOperation( operation ) ).to.throw( CKEditorError, /operation-move-nodes-do-not-exist/ );
-	} );
-
-	it( 'should throw an error if target or source parent-element specified by position does not exist', () => {
-		let p = new Element( 'p' );
-		p.insertChildren( 0, 'foo' );
-		root.insertChildren( 0, [ 'ab', p ] );
-
-		let operation = new MoveOperation(
-			new Position( root, [ 2, 0 ] ),
-			3,
-			new Position( root, [ 1 ] ),
-			doc.version
-		);
-
-		root.removeChildren( 2, 1 );
-
-		expect( () => doc.applyOperation( operation ) ).to.throw( CKEditorError, /operation-move-position-invalid/ );
-	} );
-
-	it( 'should throw an error if operation tries to move a range between the beginning and the end of that range', () => {
-		root.insertChildren( 0, 'xbarx' );
-
-		let operation = new MoveOperation(
-			new Position( root, [ 1 ] ),
-			3,
-			new Position( root, [ 2 ] ),
-			doc.version
-		);
-
-		expect( () => doc.applyOperation( operation ) ).to.throw( CKEditorError, /operation-move-range-into-itself/ );
-	} );
-
-	it( 'should throw an error if operation tries to move a range into a sub-tree of a node that is in that range', () => {
-		let p = new Element( 'p', [], [ new Element( 'p' ) ] );
-		root.insertChildren( 0, [ 'ab', p, 'xy' ] );
-
-		let operation = new MoveOperation(
-			new Position( root, [ 1 ] ),
-			3,
-			new Position( root, [ 2, 0, 0 ] ),
-			doc.version
-		);
-
-		expect( () => doc.applyOperation( operation ) ).to.throw( CKEditorError, /operation-move-node-into-itself/ );
-	} );
-
-	it( 'should not throw an error if operation move a range into a sibling', () => {
-		let p = new Element( 'p' );
-		root.insertChildren( 0, [ 'ab', p, 'xy' ] );
-
-		let operation = new MoveOperation(
-			new Position( root, [ 1 ] ),
-			1,
-			new Position( root, [ 2, 0 ] ),
-			doc.version
-		);
-
-		expect(
-			() => {
-				doc.applyOperation( operation );
-			}
-		).not.to.throw();
-
-		expect( root.getChildCount() ).to.equal( 4 );
-		expect( p.getChildCount() ).to.equal( 1 );
-		expect( p.getChild( 0 ).character ).to.equal( 'b' );
-	} );
-
-	it( 'should create operation with the same parameters when cloned', () => {
-		let sourcePosition = new Position( root, [ 0 ] );
-		let targetPosition = new Position( root, [ 1 ] );
-		let howMany = 4;
-		let baseVersion = doc.version;
-
-		let op = new MoveOperation( sourcePosition, howMany, targetPosition, baseVersion );
-
-		let clone = op.clone();
-
-		// New instance rather than a pointer to the old instance.
-		expect( clone ).not.to.be.equal( op );
-
-		expect( clone ).to.be.instanceof( MoveOperation );
-		expect( clone.sourcePosition.isEqual( sourcePosition ) ).to.be.true;
-		expect( clone.targetPosition.isEqual( targetPosition ) ).to.be.true;
-		expect( clone.howMany ).to.equal( howMany );
-		expect( clone.baseVersion ).to.equal( baseVersion );
-	} );
-} );

+ 0 - 48
packages/ckeditor5-utils/tests/document/operation/nooperation.js

@@ -1,48 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/operation/nooperation'
-);
-
-describe( 'NoOperation', () => {
-	let Document, NoOperation;
-
-	before( function() {
-		Document = modules[ 'document/document' ];
-		NoOperation = modules[ 'document/operation/nooperation' ];
-	} );
-
-	let noop, doc, root;
-
-	beforeEach( () => {
-		noop = new NoOperation( 0 );
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-	} );
-
-	it( 'should not throw an error when applied', () => {
-		expect( () => doc.applyOperation( noop ) ).to.not.throw( Error );
-	} );
-
-	it( 'should create a do-nothing operation as a reverse', () => {
-		const reverse = noop.getReversed();
-
-		expect( reverse ).to.be.an.instanceof( NoOperation );
-		expect( reverse.baseVersion ).to.equal( 1 );
-	} );
-
-	it( 'should create a do-nothing operation having same parameters when cloned', () => {
-		const clone = noop.clone();
-
-		expect( clone ).to.be.an.instanceof( NoOperation );
-		expect( clone.baseVersion ).to.equal( 0 );
-	} );
-} );

+ 0 - 85
packages/ckeditor5-utils/tests/document/operation/reinsertoperation.js

@@ -1,85 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/operation/reinsertoperation',
-	'document/operation/removeoperation',
-	'document/operation/moveoperation',
-	'document/position'
-);
-
-describe( 'ReinsertOperation', () => {
-	let Document, ReinsertOperation, RemoveOperation, MoveOperation, Position;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		ReinsertOperation = modules[ 'document/operation/reinsertoperation' ];
-		RemoveOperation = modules[ 'document/operation/removeoperation' ];
-		MoveOperation = modules[ 'document/operation/moveoperation' ];
-		Position = modules[ 'document/position' ];
-	} );
-
-	let doc, root, graveyard, operation, graveyardPosition, rootPosition;
-
-	beforeEach( () => {
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-		graveyard = doc._graveyard;
-
-		graveyardPosition = new Position( graveyard, [ 0 ] );
-		rootPosition = new Position( root, [ 0 ] );
-
-		operation = new ReinsertOperation(
-			graveyardPosition,
-			2,
-			rootPosition,
-			doc.version
-		);
-	} );
-
-	it( 'should have proper type', () => {
-		expect( operation.type ).to.equal( 'reinsert' );
-	} );
-
-	it( 'should extend MoveOperation class', () => {
-		expect( operation ).to.be.instanceof( MoveOperation );
-	} );
-
-	it( 'should create a remove operation as a reverse', () => {
-		let reverse = operation.getReversed();
-
-		expect( reverse ).to.be.an.instanceof( RemoveOperation );
-		expect( reverse.baseVersion ).to.equal( 1 );
-		expect( reverse.howMany ).to.equal( 2 );
-		expect( reverse.sourcePosition.isEqual( rootPosition ) ).to.be.true;
-		expect( reverse.targetPosition.isEqual( graveyardPosition ) ).to.be.true;
-	} );
-
-	it( 'should undo reinsert set of nodes by applying reverse operation', () => {
-		let reverse = operation.getReversed();
-
-		graveyard.insertChildren( 0, 'bar' );
-
-		doc.applyOperation( operation );
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 2 );
-
-		doc.applyOperation( reverse );
-
-		expect( doc.version ).to.equal( 2 );
-		expect( root.getChildCount() ).to.equal( 0 );
-		expect( graveyard.getChildCount() ).to.equal( 3 );
-
-		expect( graveyard.getChild( 0 ).character ).to.equal( 'b' );
-		expect( graveyard.getChild( 1 ).character ).to.equal( 'a' );
-		expect( graveyard.getChild( 2 ).character ).to.equal( 'r' );
-	} );
-} );

+ 0 - 113
packages/ckeditor5-utils/tests/document/operation/removeoperation.js

@@ -1,113 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/operation/reinsertoperation',
-	'document/operation/removeoperation',
-	'document/operation/moveoperation',
-	'document/position'
-);
-
-describe( 'RemoveOperation', () => {
-	let Document, ReinsertOperation, RemoveOperation, MoveOperation, Position;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		ReinsertOperation = modules[ 'document/operation/reinsertoperation' ];
-		RemoveOperation = modules[ 'document/operation/removeoperation' ];
-		MoveOperation = modules[ 'document/operation/removeoperation' ];
-		Position = modules[ 'document/position' ];
-	} );
-
-	let doc, root, graveyard;
-
-	beforeEach( () => {
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-		graveyard = doc._graveyard;
-	} );
-
-	it( 'should have proper type', () => {
-		const opp = new RemoveOperation(
-			new Position( root, [ 2 ] ),
-			2,
-			doc.version
-		);
-
-		expect( opp.type ).to.equal( 'remove' );
-	} );
-
-	it( 'should extend MoveOperation class', () => {
-		let operation = new RemoveOperation(
-			new Position( root, [ 2 ] ),
-			2,
-			doc.version
-		);
-
-		expect( operation ).to.be.instanceof( MoveOperation );
-	} );
-
-	it( 'should remove set of nodes and append them to graveyard root', () => {
-		root.insertChildren( 0, 'fozbar' );
-
-		let z = root.getChild( 2 );
-		let b = root.getChild( 3 );
-		let a = root.getChild( 4 );
-
-		doc.applyOperation(
-			new RemoveOperation(
-				new Position( root, [ 2 ] ),
-				2,
-				doc.version
-			)
-		);
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 4 );
-		expect( root.getChild( 2 ) ).to.equal( a );
-
-		expect( graveyard.getChildCount() ).to.equal( 2 );
-		expect( graveyard.getChild( 0 ) ).to.equal( z );
-		expect( graveyard.getChild( 1 ) ).to.equal( b );
-	} );
-
-	it( 'should create a reinsert operation as a reverse', () => {
-		let position = new Position( root, [ 0 ] );
-		let operation = new RemoveOperation( position, 2, 0 );
-		let reverse = operation.getReversed();
-
-		expect( reverse ).to.be.an.instanceof( ReinsertOperation );
-		expect( reverse.baseVersion ).to.equal( 1 );
-		expect( reverse.howMany ).to.equal( 2 );
-		expect( reverse.sourcePosition ).to.equal( operation.targetPosition );
-		expect( reverse.targetPosition ).to.equal( position );
-	} );
-
-	it( 'should undo remove set of nodes by applying reverse operation', () => {
-		let position = new Position( root, [ 0 ] );
-		let operation = new RemoveOperation( position, 3, 0 );
-		let reverse = operation.getReversed();
-
-		root.insertChildren( 0, 'bar' );
-
-		doc.applyOperation( operation );
-
-		expect( doc.version ).to.equal( 1 );
-		expect( root.getChildCount() ).to.equal( 0 );
-
-		doc.applyOperation( reverse );
-
-		expect( doc.version ).to.equal( 2 );
-		expect( root.getChildCount() ).to.equal( 3 );
-		expect( root.getChild( 0 ).character ).to.equal( 'b' );
-		expect( root.getChild( 1 ).character ).to.equal( 'a' );
-		expect( root.getChild( 2 ).character ).to.equal( 'r' );
-	} );
-} );

+ 0 - 2382
packages/ckeditor5-utils/tests/document/operation/transform.js

@@ -1,2382 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* jshint expr: true */
-
-/* bender-tags: document */
-/* global describe, before, beforeEach, it, expect */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/rootelement',
-	'document/node',
-	'document/position',
-	'document/range',
-	'document/attribute',
-	'document/operation/transform',
-	'document/operation/insertoperation',
-	'document/operation/attributeoperation',
-	'document/operation/moveoperation',
-	'document/operation/nooperation'
-);
-
-describe( 'transform', () => {
-	let RootElement, Node, Position, Range, Attribute, InsertOperation, AttributeOperation, MoveOperation, NoOperation;
-	let transform;
-
-	before( () => {
-		RootElement = modules[ 'document/rootelement' ];
-		Node = modules[ 'document/node' ];
-		Position = modules[ 'document/position' ];
-		Range = modules[ 'document/range' ];
-		Attribute = modules[ 'document/attribute' ];
-		InsertOperation = modules[ 'document/operation/insertoperation' ];
-		AttributeOperation = modules[ 'document/operation/attributeoperation' ];
-		MoveOperation = modules[ 'document/operation/moveoperation' ];
-		NoOperation = modules[ 'document/operation/nooperation' ];
-
-		transform = modules[ 'document/operation/transform' ];
-	} );
-
-	let root, op, nodeA, nodeB, expected, baseVersion;
-
-	beforeEach( () => {
-		root = new RootElement( null );
-
-		nodeA = new Node();
-		nodeB = new Node();
-
-		baseVersion = 0;
-	} );
-
-	function expectOperation( op, params ) {
-		for ( let i in params ) {
-			if ( params.hasOwnProperty( i ) ) {
-				if ( i == 'type' ) {
-					expect( op ).to.be.instanceof( params[ i ] );
-				}
-				else if ( params[ i ] instanceof Array ) {
-					expect( op[ i ].length ).to.equal( params[ i ].length );
-
-					for ( let j = 0; j < params[ i ].length; j++ ) {
-						expect( op[ i ][ j ] ).to.equal( params[ i ][ j ] );
-					}
-				} else if ( params[ i ] instanceof Position || params[ i ] instanceof Range ) {
-					expect( op[ i ].isEqual( params[ i ] ) ).to.be.true;
-				} else {
-					expect( op[ i ] ).to.equal( params[ i ] );
-				}
-			}
-		}
-	}
-
-	describe( 'InsertOperation', () => {
-		let nodeC, nodeD, position;
-
-		beforeEach( () => {
-			nodeC = new Node();
-			nodeD = new Node();
-
-			position = new Position( root, [ 0, 2, 1 ] );
-
-			op = new InsertOperation( position, [ nodeA, nodeB ], baseVersion );
-
-			expected = {
-				type: InsertOperation,
-				position: position.clone(),
-				baseVersion: baseVersion + 1
-			};
-		} );
-
-		describe( 'by InsertOperation', () => {
-			it( 'target at different position: no position update', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 1, 3, 2 ] ),
-					[ nodeC, nodeD ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target at offset before: increment offset', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 0, 2, 0 ] ),
-					[ nodeC, nodeD ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-				expected.position.offset += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target at same offset and is important: increment offset', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 0, 2, 1 ] ),
-					[ nodeC, nodeD ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-				expected.position.offset += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target at same offset and is less important: no position update', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 0, 2, 1 ] ),
-					[ nodeC, nodeD ],
-					baseVersion
-				);
-
-				let transOp = transform( transformBy, true );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target at offset after: no position update', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 0, 2, 2 ] ),
-					[ nodeC, nodeD ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target before node from path: increment index on path', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 0, 1 ] ),
-					[ nodeC, nodeD ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-				expected.position.path[ 1 ] += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target after node from path: no position update', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 0, 6 ] ),
-					[ nodeC, nodeD ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-		} );
-
-		describe( 'by AttributeOperation', () => {
-			it( 'no position update', () => {
-				let rangeStart = position.clone();
-				let rangeEnd = position.clone();
-				rangeEnd.offset += 2;
-
-				let transformBy = new AttributeOperation(
-					new Range( rangeStart, rangeEnd ),
-					null,
-					new Attribute( 'foo', 'bar' ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-		} );
-
-		describe( 'by MoveOperation', () => {
-			it( 'range and target are different than insert position: no position update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 1, 3, 2 ] ),
-					2,
-					new Position( root, [ 2, 1 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range offset is before insert position offset: decrement offset', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 0, 2, 0 ] ),
-					1,
-					new Position( root, [ 1, 1 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-				expected.position.offset--;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range offset is after insert position offset: no position update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 0, 2, 4 ] ),
-					1,
-					new Position( root, [ 1, 1 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset before insert position offset: increment offset', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 1, 1 ] ),
-					2,
-					new Position( root, [ 0, 2, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-				expected.position.offset += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset after insert position offset: no position update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 1, 1 ] ),
-					2,
-					new Position( root, [ 0, 2, 4 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset same as insert position offset and is important: increment offset', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 1, 1 ] ),
-					2,
-					new Position( root, [ 0, 2, 1 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-				expected.position.offset += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset same as insert position offset and is less important: no position update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 1, 1 ] ),
-					2,
-					new Position( root, [ 0, 2, 1 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy, true );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range is before node from insert position path: decrement index on path', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 0, 0 ] ),
-					2,
-					new Position( root, [ 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-				expected.position.path[ 1 ] -= 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range is after node from insert position path: no position update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 0, 4 ] ),
-					2,
-					new Position( root, [ 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target before node from insert position path: increment index on path', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 1, 0 ] ),
-					2,
-					new Position( root, [ 0, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-				expected.position.path[ 1 ] += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target after node from insert position path: no position update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 1, 0 ] ),
-					2,
-					new Position( root, [ 0, 4 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range has node that contains insert position: update position', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 0, 1 ] ),
-					2,
-					new Position( root, [ 1, 1 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-				expected.position.path = [ 1, 2, 1 ];
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range contains insert position (on same level): set position offset to range start', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 0, 2, 0 ] ),
-					3,
-					new Position( root, [ 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-				expected.position.offset = 0;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-		} );
-
-		describe( 'by NoOperation', () => {
-			it( 'no operation update', () => {
-				let transformBy = new NoOperation( baseVersion );
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-		} );
-	} );
-
-	describe( 'AttributeOperation', () => {
-		let start, end, range, oldAttr, newAttr, anotherOldAttr, anotherNewAttr;
-
-		beforeEach( () => {
-			oldAttr = new Attribute( 'foo', 'abc' );
-			newAttr = new Attribute( 'foo', 'bar' );
-
-			anotherOldAttr = new Attribute( oldAttr.key, 'another' );
-			anotherNewAttr = new Attribute( oldAttr.key, 'anothernew' );
-
-			expected = {
-				type: AttributeOperation,
-				oldAttr: oldAttr,
-				newAttr: newAttr,
-				baseVersion: baseVersion + 1
-			};
-		} );
-
-		describe( 'with multi-level range', () => {
-			beforeEach( () => {
-				start = new Position( root, [ 1, 2 ] );
-				end = new Position( root, [ 2, 2, 4 ] );
-
-				range = new Range( start, end );
-
-				op = new AttributeOperation( range, oldAttr, newAttr, baseVersion );
-
-				expected.range = new Range( start.clone(), end.clone() );
-			} );
-
-			describe( 'by InsertOperation', () => {
-				it( 'target at different position: no operation update', () => {
-					let transformBy = new InsertOperation(
-						new Position( root, [ 3, 3, 2 ] ),
-						[ nodeA, nodeB ],
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'target at offset before: increment offset', () => {
-					let transformBy = new InsertOperation(
-						new Position( root, [ 1, 1 ] ),
-						[ nodeA, nodeB ],
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.offset += 2;
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'target at same offset: increment offset', () => {
-					let transformBy = new InsertOperation(
-						new Position( root, [ 1, 2 ] ),
-						[ nodeA, nodeB ],
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.offset += 2;
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'target at offset after: no operation update', () => {
-					let transformBy = new InsertOperation(
-						new Position( root, [ 3, 2 ] ),
-						[ nodeA, nodeB ],
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'target before node from path: increment index on path', () => {
-					let transformBy = new InsertOperation(
-						new Position( root, [ 0 ] ),
-						[ nodeA, nodeB ],
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.path[ 0 ] += 2;
-					expected.range.end.path[ 0 ] += 2;
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'target after node from path: no position change', () => {
-					let transformBy = new InsertOperation(
-						new Position( root, [ 2, 6 ] ),
-						[ nodeA, nodeB ],
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'target inside change range: split into two operations', () => {
-					let transformBy = new InsertOperation(
-						new Position( root, [ 1, 3, 1 ] ),
-						[ nodeA, nodeB ],
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 2 );
-
-					expected.range.start.path = [ 1, 3, 3 ];
-
-					expectOperation( transOp[ 0 ], expected );
-
-					expected.range.start = op.range.start;
-					expected.range.end.path = [ 1, 3, 1 ];
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 1 ], expected );
-				} );
-			} );
-
-			describe( 'by AttributeOperation', () => {
-				it( 'attributes have different key: no operation update', () => {
-					let transformBy = new AttributeOperation(
-						range.clone(),
-						new Attribute( 'abc', true ),
-						new Attribute( 'abc', false ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'attributes set same value: no operation update', () => {
-					let transformBy = new AttributeOperation(
-						range.clone(),
-						oldAttr,
-						newAttr,
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'both operations removes attribute: no operation update', () => {
-					op.newAttr = null;
-
-					let transformBy = new AttributeOperation(
-						new Range( new Position( root, [ 1, 1, 4 ] ), new Position( root, [ 3 ] ) ),
-						anotherOldAttr,
-						null,
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy, true );
-
-					expected.newAttr = null;
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				describe( 'that is less important and', () => {
-					it( 'range does not intersect original range: no operation update', () => {
-						let transformBy = new AttributeOperation(
-							new Range( new Position( root, [ 3, 0 ] ), new Position( root, [ 4 ] ) ),
-							anotherOldAttr,
-							null,
-							baseVersion
-						);
-
-						let transOp = transform( op, transformBy, true );
-
-						expect( transOp.length ).to.equal( 1 );
-						expectOperation( transOp[ 0 ], expected );
-					} );
-
-					it( 'range contains original range: update oldAttr', () => {
-						let transformBy = new AttributeOperation(
-							new Range( new Position( root, [ 1, 1, 4 ] ), new Position( root, [ 3 ] ) ),
-							anotherOldAttr,
-							null,
-							baseVersion
-						);
-
-						let transOp = transform( op, transformBy, true );
-
-						expected.oldAttr = anotherOldAttr;
-
-						expect( transOp.length ).to.equal( 1 );
-						expectOperation( transOp[ 0 ], expected );
-					} );
-
-					// [ original range   <   ]   range transformed by >
-					it( 'range intersects on left: split into two operations, update oldAttr', () => {
-						// Get more test cases and better code coverage
-						op.newAttr = null;
-
-						let transformBy = new AttributeOperation(
-							new Range( new Position( root, [ 1, 4, 2 ] ), new Position( root, [ 3 ] ) ),
-							anotherOldAttr,
-							// Get more test cases and better code coverage
-							anotherNewAttr,
-							baseVersion
-						);
-
-						let transOp = transform( op, transformBy, true );
-
-						expect( transOp.length ).to.equal( 2 );
-
-						expected.newAttr = null;
-
-						expected.range.end.path = [ 1, 4, 2 ];
-
-						expectOperation( transOp[ 0 ], expected );
-
-						expected.range.start.path = [ 1, 4, 2 ];
-						expected.range.end = op.range.end;
-						expected.oldAttr = anotherOldAttr;
-						expected.baseVersion++;
-
-						expectOperation( transOp[ 1 ], expected );
-					} );
-
-					// [  range transformed by  <   ]  original range  >
-					it( 'range intersects on right: split into two operations, update oldAttr', () => {
-						let transformBy = new AttributeOperation(
-							new Range( new Position( root, [ 1 ] ), new Position( root, [ 2, 1 ] ) ),
-							anotherOldAttr,
-							null,
-							baseVersion
-						);
-
-						let transOp = transform( op, transformBy, true );
-
-						expect( transOp.length ).to.equal( 2 );
-
-						expected.range.start.path = [ 2, 1 ];
-
-						expectOperation( transOp[ 0 ], expected );
-
-						expected.range.start = op.range.start;
-						expected.range.end.path = [ 2, 1 ];
-						expected.oldAttr = anotherOldAttr;
-						expected.baseVersion++;
-
-						expectOperation( transOp[ 1 ], expected );
-					} );
-
-					it( 'range is inside original range: split into three operations, update oldAttr', () => {
-						let transformBy = new AttributeOperation(
-							new Range( new Position( root, [ 1, 4, 1 ] ), new Position( root, [ 2, 1 ] ) ),
-							anotherOldAttr,
-							null,
-							baseVersion
-						);
-
-						let transOp = transform( op, transformBy, true );
-
-						expect( transOp.length ).to.equal( 3 );
-
-						expected.range.end.path = [ 1, 4, 1 ];
-
-						expectOperation( transOp[ 0 ], expected );
-
-						expected.range.start.path = [ 2, 1 ];
-						expected.range.end = op.range.end;
-						expected.baseVersion++;
-
-						expectOperation( transOp[ 1 ], expected );
-
-						expected.range.start.path = [ 1, 4, 1 ];
-						expected.range.end.path = [ 2, 1 ];
-						expected.oldAttr = anotherOldAttr;
-						expected.baseVersion++;
-
-						expectOperation( transOp[ 2 ], expected );
-					} );
-				} );
-
-				describe( 'that is more important and', () => {
-					it( 'range does not intersect original range: no operation update', () => {
-						let transformBy = new AttributeOperation(
-							new Range( new Position( root, [ 3, 0 ] ), new Position( root, [ 4 ] ) ),
-							oldAttr,
-							null,
-							baseVersion
-						);
-
-						let transOp = transform( op, transformBy );
-
-						expect( transOp.length ).to.equal( 1 );
-						expectOperation( transOp[ 0 ], expected );
-					} );
-
-					it( 'range contains original range: convert to NoOperation', () => {
-						let transformBy = new AttributeOperation(
-							new Range( new Position( root, [ 1, 1, 4 ] ), new Position( root, [ 3 ] ) ),
-							oldAttr,
-							null,
-							baseVersion
-						);
-
-						let transOp = transform( op, transformBy );
-
-						expect( transOp.length ).to.equal( 1 );
-						expectOperation( transOp[ 0 ], {
-							type: NoOperation,
-							baseVersion: baseVersion + 1
-						} );
-					} );
-
-					// [ original range   <   ]   range transformed by >
-					it( 'range intersects on left: shrink original range', () => {
-						let transformBy = new AttributeOperation(
-							new Range( new Position( root, [ 1, 4, 2 ] ), new Position( root, [ 3 ] ) ),
-							oldAttr,
-							null,
-							baseVersion
-						);
-
-						let transOp = transform( op, transformBy );
-
-						expected.range.end.path = [ 1, 4, 2 ];
-
-						expect( transOp.length ).to.equal( 1 );
-						expectOperation( transOp[ 0 ], expected );
-					} );
-
-					// [  range transformed by  <   ]  original range  >
-					it( 'range intersects on right: shrink original range', () => {
-						let transformBy = new AttributeOperation(
-							new Range( new Position( root, [ 1 ] ), new Position( root, [ 2, 1 ] ) ),
-							oldAttr,
-							null,
-							baseVersion
-						);
-
-						let transOp = transform( op, transformBy );
-
-						expected.range.start.path = [ 2, 1 ];
-
-						expect( transOp.length ).to.equal( 1 );
-						expectOperation( transOp[ 0 ], expected );
-					} );
-
-					it( 'range is inside original range: split into two operations', () => {
-						let transformBy = new AttributeOperation(
-							new Range( new Position( root, [ 1, 4, 1 ] ), new Position( root, [ 2, 1 ] ) ),
-							oldAttr,
-							null,
-							baseVersion
-						);
-
-						let transOp = transform( op, transformBy );
-
-						expect( transOp.length ).to.equal( 2 );
-
-						expected.range.end.path = [ 1, 4, 1 ];
-
-						expectOperation( transOp[ 0 ], expected );
-
-						expected.range.start.path = [ 2, 1 ];
-						expected.range.end = op.range.end;
-						expected.baseVersion++;
-
-						expectOperation( transOp[ 1 ], expected );
-					} );
-				} );
-			} );
-
-			describe( 'by MoveOperation', () => {
-				it( 'range and target are different than change range: no operation update', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 1, 1, 2 ] ),
-						2,
-						new Position( root, [ 3, 4 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'range offset is before change range start offset: decrement offset', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 1, 0 ] ),
-						2,
-						new Position( root, [ 3, 4, 1 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.offset -= 2;
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'target offset is before change range start offset: increment offset', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 3, 4, 1 ] ),
-						2,
-						new Position( root, [ 1, 0 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.offset += 2;
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'range is before node from path to change range: decrement index on path', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 0 ] ),
-						1,
-						new Position( root, [ 2, 4, 1 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.path[ 0 ]--;
-					expected.range.end.path[ 0 ]--;
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'range is after node from path to change range: no position change', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 3 ] ),
-						2,
-						new Position( root, [ 0, 1 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'target before node from path to change range: increment index on path', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 3, 4, 1 ] ),
-						2,
-						new Position( root, [ 1, 0 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.path[ 1 ] += 2;
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'target after node from path to change range: no position change', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 3, 4, 1 ] ),
-						2,
-						new Position( root, [ 3 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'range intersects on left with change range: split into two operations', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 2, 1 ] ),
-						3,
-						new Position( root, [ 4 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 2 );
-
-					expected.range.end.path = [ 2, 1 ];
-
-					expectOperation( transOp[ 0 ], expected );
-
-					expected.range.start.path = [ 4 ];
-					expected.range.end.path = [ 5, 4 ];
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 1 ], expected );
-				} );
-
-				it( 'range intersects on right with change range: split into two operation', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 1, 1 ] ),
-						3,
-						new Position( root, [ 0, 0 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 2 );
-
-					expected.range.start.path = [ 1, 1 ];
-
-					expectOperation( transOp[ 0 ], expected );
-
-					expected.range.start.path = [ 0, 1 ];
-					expected.range.end.path = [ 0, 3 ];
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 1 ], expected );
-				} );
-
-				it( 'range contains change range: update change range', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 1 ] ),
-						2,
-						new Position( root, [ 3, 4, 1 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.path = [ 1, 4, 1, 2 ];
-					expected.range.end.path = [ 1, 4, 2, 2, 4 ];
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'range is inside change range: split into two operations', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 1, 4 ] ),
-						2,
-						new Position( root, [ 3, 2 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 2 );
-
-					expectOperation( transOp[ 0 ], expected );
-
-					expected.range.start.path = [ 3, 2 ];
-					expected.range.end.path = [ 3, 4 ];
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 1 ], expected );
-				} );
-
-				it( 'target inside change range: split into two operations', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 3, 4, 1 ] ),
-						2,
-						new Position( root, [ 1, 4 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 2 );
-
-					expected.range.start.path = [ 1, 6 ];
-
-					expectOperation( transOp[ 0 ], expected );
-
-					expected.range.start = op.range.start;
-					expected.range.end.path = [ 1, 4 ];
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 1 ], expected );
-				} );
-
-				it( 'range intersects change range and target inside change range: split into three operations', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 1, 1 ] ),
-						3,
-						new Position( root, [ 2 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 3 );
-
-					expected.range.start.path = [ 5 ];
-					expected.range.end.path = [ 5, 2, 4 ];
-
-					expectOperation( transOp[ 0 ], expected );
-
-					expected.range.start.path = [ 1, 1 ];
-					expected.range.end.path = [ 2 ];
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 1 ], expected );
-
-					expected.range.start.path = [ 3 ];
-					expected.range.end.path = [ 5 ];
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 2 ], expected );
-				} );
-			} );
-
-			describe( 'by NoOperation', () => {
-				it( 'no operation update', () => {
-					let transformBy = new NoOperation( baseVersion );
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-			} );
-		} );
-
-		// Some extra cases for a AttributeOperation that operates on single tree level range.
-		// This means that the change range start and end differs only on offset value.
-		// This test suite also have some modifications to the original operation
-		// to get more test cases covered and better code coverage.
-		describe( 'with single-level range', () => {
-			beforeEach( () => {
-				start = new Position( root, [ 0, 2, 1 ] );
-				end = new Position( root, [ 0, 2, 4 ] );
-
-				range = new Range( start, end );
-
-				op = new AttributeOperation( range, oldAttr, newAttr, baseVersion );
-
-				expected.range = new Range( start.clone(), end.clone() );
-			} );
-
-			describe( 'by InsertOperation', () => {
-				it( 'target at offset before: increment offset', () => {
-					let transformBy = new InsertOperation(
-						new Position( root, [ 0, 2, 0 ] ),
-						[ nodeA, nodeB ],
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.offset += 2;
-					expected.range.end.offset += 2;
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'target at same offset: increment offset', () => {
-					let transformBy = new InsertOperation(
-						new Position( root, [ 0, 2, 1 ] ),
-						[ nodeA, nodeB ],
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.offset += 2;
-					expected.range.end.offset += 2;
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-			} );
-
-			describe( 'by MoveOperation', () => {
-				it( 'range offset is before change range start offset: decrement offset', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 0, 2, 0 ] ),
-						1,
-						new Position( root, [ 2, 4, 1 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.offset--;
-					expected.range.end.offset--;
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'target offset is before change range start offset: increment offset', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 2, 4, 1 ] ),
-						2,
-						new Position( root, [ 0, 2, 0 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.offset += 2;
-					expected.range.end.offset += 2;
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'range intersects on left with change range: split into two operations', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 0, 2, 2 ] ),
-						4,
-						new Position( root, [ 2, 4, 1 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 2 );
-
-					expected.range.end.offset -= 2;
-
-					expectOperation( transOp[ 0 ], expected );
-
-					expected.range.start.path = [ 2, 4, 1 ];
-					expected.range.end.path = [ 2, 4, 3 ];
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 1 ], expected );
-				} );
-
-				it( 'range intersects on right with change range: split into two operation', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 0, 2, 0 ] ),
-						2,
-						new Position( root, [ 2, 4, 1 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 2 );
-
-					expected.range.start.offset -= 1;
-					expected.range.end.offset -= 2;
-
-					expectOperation( transOp[ 0 ], expected );
-
-					expected.range.start.path = [ 2, 4, 2 ];
-					expected.range.end.path = [ 2, 4, 3 ];
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 1 ], expected );
-				} );
-
-				it( 'range contains change range: update change range', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 0, 1 ] ),
-						3,
-						new Position( root, [ 2, 4, 1 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.path = [ 2, 4, 2, 1 ];
-					expected.range.end.path = [ 2, 4, 2, 4 ];
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'range is inside change range: split into two operations', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 0, 2, 2 ] ),
-						1,
-						new Position( root, [ 2, 4, 1 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 2 );
-
-					expected.range.end.offset--;
-
-					expectOperation( transOp[ 0 ], expected );
-
-					expected.range.start.path = [ 2, 4, 1 ];
-					expected.range.end.path = [ 2, 4, 2 ];
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 1 ], expected );
-				} );
-
-				it( 'range is same as change range: update change range', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 0, 2, 1 ] ),
-						3,
-						new Position( root, [ 2, 4, 1 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expected.range.start.path = [ 2, 4, 1 ];
-					expected.range.end.path = [ 2, 4, 4 ];
-
-					expect( transOp.length ).to.equal( 1 );
-					expectOperation( transOp[ 0 ], expected );
-				} );
-
-				it( 'target inside change range: split into two operations', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 2, 4, 1 ] ),
-						2,
-						new Position( root, [ 0, 2, 2 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 2 );
-
-					expected.range.start.offset = 4;
-					expected.range.end.offset = 6;
-
-					expectOperation( transOp[ 0 ], expected );
-
-					expected.range.start.offset = op.range.start.offset;
-					expected.range.end.offset = 2;
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 1 ], expected );
-				} );
-
-				it( 'range intersects change range and target inside change range: split into three operations', () => {
-					let transformBy = new MoveOperation(
-						new Position( root, [ 0, 2, 0 ] ),
-						2,
-						new Position( root, [ 0, 2, 3 ] ),
-						baseVersion
-					);
-
-					let transOp = transform( op, transformBy );
-
-					expect( transOp.length ).to.equal( 3 );
-
-					expected.range.start.offset = 3;
-					expected.range.end.offset = 4;
-
-					expectOperation( transOp[ 0 ], expected );
-
-					expected.range.start.offset = 0;
-					expected.range.end.offset = 1;
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 1 ], expected );
-
-					expected.range.start.offset = 2;
-					expected.range.end.offset = 3;
-					expected.baseVersion++;
-
-					expectOperation( transOp[ 2 ], expected );
-				} );
-			} );
-		} );
-	} );
-
-	describe( 'MoveOperation', () => {
-		let sourcePosition, targetPosition, rangeEnd, howMany;
-
-		beforeEach( () => {
-			sourcePosition = new Position( root, [ 2, 2, 4 ] );
-			targetPosition = new Position( root, [ 3, 3, 3 ] );
-			howMany = 2;
-
-			rangeEnd = sourcePosition.clone();
-			rangeEnd.offset += howMany;
-
-			op = new MoveOperation( sourcePosition, howMany, targetPosition, baseVersion );
-
-			expected = {
-				type: MoveOperation,
-				sourcePosition: sourcePosition.clone(),
-				targetPosition: targetPosition.clone(),
-				howMany: howMany,
-				baseVersion: baseVersion + 1
-			};
-		} );
-
-		describe( 'by InsertOperation', () => {
-			it( 'target at different position than move range and target: no operation update', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 1, 3, 2 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target inside node from move range: no operation update', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 2, 2, 3, 1 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target at offset before range offset: increment range offset', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 2, 2, 0 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.sourcePosition.offset += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target at offset after range offset: no operation update', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 2, 2, 6 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target before node from range start path: increment index on range start path', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 2, 0 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.sourcePosition.path[ 1 ] += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target after node from range start path: no operation update', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 2, 3 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset before move target offset: increment target offset', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 3, 3, 2 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.targetPosition.offset += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset after move target offset: no operation update', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 3, 3, 4 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target before node from move target position path: increment index on move target position path', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 3, 0 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.targetPosition.path[ 1 ] += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target after node from move target position path: no operation update', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 3, 6 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset same as move target offset and is important: increment target offset', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 3, 3, 3 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.targetPosition.offset += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset same as move target offset and is less important: no operation update', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 3, 3, 3 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy, true );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset same as move target offset and is important: increment target offset', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 3, 3 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.targetPosition.path[ 1 ] += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target inside move range: split into two operations', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 2, 2, 5 ] ),
-					[ nodeA, nodeB ],
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 2 );
-
-				expected.sourcePosition.path = [ 2, 2, 7 ];
-				expected.howMany = 1;
-
-				expectOperation( transOp[ 0 ], expected );
-
-				expected.sourcePosition.path = [ 2, 2, 4 ];
-				expected.howMany = 1;
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 1 ], expected );
-			} );
-		} );
-
-		describe( 'by AttributeOperation', () => {
-			it( 'no operation update', () => {
-				let transformBy = new AttributeOperation(
-					new Range( sourcePosition, rangeEnd ),
-					new Attribute( 'abc', true ),
-					new Attribute( 'abc', false ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-		} );
-
-		describe( 'by MoveOperation', () => {
-			it( 'range and target different than transforming range and target: no operation update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 1, 2 ] ),
-					3,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset before transforming range start offset: increment range offset', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 4, 1, 0 ] ),
-					2,
-					new Position( root, [ 2, 2, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.sourcePosition.offset += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset after transforming range start offset: no operation update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 4, 1, 0 ] ),
-					2,
-					new Position( root, [ 2, 2, 7 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range start offset before transforming range start offset: decrement range offset', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 0 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.sourcePosition.offset -= 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range start offset after transforming range start offset: no operation update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 9 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy, true );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target before node from transforming range start path: increment index on range start path', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 4, 1, 0 ] ),
-					2,
-					new Position( root, [ 2, 1 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.sourcePosition.path[ 1 ] += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target after node from transforming range start path: no operation update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 4, 1, 0 ] ),
-					2,
-					new Position( root, [ 2, 5 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range before node from transforming range start path: decrement index on range start path', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 0 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.sourcePosition.path[ 1 ] -= 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range after node from transforming range start path: no operation update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 3 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset before transforming target offset: increment target offset', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 4, 1, 0 ] ),
-					2,
-					new Position( root, [ 3, 3, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.targetPosition.offset += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target offset after transforming target offset: no operation update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 4, 1, 0 ] ),
-					2,
-					new Position( root, [ 3, 3, 5 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range offset before transforming target offset: decrement target offset', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 3, 3, 0 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.targetPosition.offset -= 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range offset after transforming target offset: no operation update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 3, 3, 5 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target before node from transforming target path: increment index on target path', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 4, 1, 0 ] ),
-					2,
-					new Position( root, [ 3, 1 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.targetPosition.path[ 1 ] += 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target after node from transforming target path: no operation update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 4, 1, 0 ] ),
-					2,
-					new Position( root, [ 3, 5 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range before node from transforming target path: decrement index on target path', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 3, 0 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.targetPosition.path[ 1 ] -= 2;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range after node from transforming target path: no operation update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 3, 5 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target inside transforming move range: split into two operations', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 4, 1, 0 ] ),
-					2,
-					new Position( root, [ 2, 2, 5 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 2 );
-
-				expected.howMany = 1;
-				expected.sourcePosition.offset = 7;
-
-				expectOperation( transOp[ 0 ], expected );
-
-				expected.sourcePosition.offset = 4;
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 1 ], expected );
-			} );
-
-			it( 'target inside a node from transforming range: no operation update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 4, 1, 0 ] ),
-					2,
-					new Position( root, [ 2, 2, 5, 1 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range has node that contains transforming range: update range path', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 1 ] ),
-					3,
-					new Position( root, [ 4, 2 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.sourcePosition.path = [ 4, 3, 4 ];
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range has node that contains transforming target: update target path', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 3, 2 ] ),
-					3,
-					new Position( root, [ 0, 1 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.targetPosition.path = [ 0, 2, 3 ];
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'target inside a node from transforming range and vice versa: reverse transform-by operation', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 3, 2 ] ),
-					3,
-					new Position( root, [ 2, 2, 5, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-				let reversed = transformBy.getReversed();
-
-				expected.sourcePosition = reversed.sourcePosition;
-				expected.targetPosition = reversed.targetPosition;
-				expected.howMany = reversed.howMany;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range is same as transforming range and is important: convert to NoOperation', () => {
-				let transformBy = new MoveOperation(
-					op.sourcePosition.clone(),
-					op.howMany,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], {
-					type: NoOperation,
-					baseVersion: baseVersion + 1
-				} );
-			} );
-
-			it( 'range is same as transforming range and is less important: update range path', () => {
-				let transformBy = new MoveOperation(
-					op.sourcePosition.clone(),
-					op.howMany,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy, true );
-
-				expected.sourcePosition.path = [ 4, 1, 0 ];
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range contains transforming range and is important: convert to NoOperation', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 3 ] ),
-					4,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], {
-					type: NoOperation,
-					baseVersion: baseVersion + 1
-				} );
-			} );
-
-			it( 'range contains transforming range and is less important: update range path', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 3 ] ),
-					4,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy, true );
-
-				expected.sourcePosition.path = [ 4, 1, 1 ];
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range contains transforming range and target and is important: update range path and target', () => {
-				op.targetPosition.path = [ 2, 2, 7 ];
-
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 3 ] ),
-					5,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-
-				expected.sourcePosition.path = [ 4, 1, 1 ];
-				expected.targetPosition.path = [ 4, 1, 4 ];
-
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range contains transforming range and target and is less important: update range path and target', () => {
-				op.targetPosition.path = [ 2, 2, 7 ];
-
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 3 ] ),
-					5,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy, true );
-
-				expect( transOp.length ).to.equal( 1 );
-
-				expected.sourcePosition.path = [ 4, 1, 1 ];
-				expected.targetPosition.path = [ 4, 1, 4 ];
-
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range intersects on left side of transforming range and is important: shrink range', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 3 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.sourcePosition.path = [ 2, 2, 3 ];
-				expected.howMany = 1;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range intersects on left side of transforming range and is less important: split into two operations', () => {
-				// Get more test cases and better code coverage
-				let otherRoot = new RootElement( null );
-
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 3 ] ),
-					2,
-					new Position( otherRoot, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy, true );
-
-				expect( transOp.length ).to.equal( 2 );
-
-				expected.sourcePosition.path = [ 2, 2, 3 ];
-				expected.howMany = 1;
-
-				expectOperation( transOp[ 0 ], expected );
-
-				expected.sourcePosition = new Position( otherRoot, [ 4, 1, 1 ] );
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 1 ], expected );
-			} );
-
-			it( 'range intersects on right side of transforming range and is important: shrink range', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 5 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expected.howMany = 1;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range intersects on right side of transforming range and is less important: split into two operations', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 5 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy, true );
-
-				expect( transOp.length ).to.equal( 2 );
-
-				expected.sourcePosition.path = [ 4, 1, 0 ];
-				expected.howMany = 1;
-
-				expectOperation( transOp[ 0 ], expected );
-
-				expected.sourcePosition.path = op.sourcePosition.path;
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 1 ], expected );
-			} );
-
-			it( 'range intersects on left side, target inside transforming range and is important: split into two operations', () => {
-				op.howMany = 4;
-
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 3 ] ),
-					2,
-					new Position( root, [ 2, 2, 6 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 2 );
-
-				expected.sourcePosition.path = [ 2, 2, 6 ];
-				expected.howMany = 2;
-
-				expectOperation( transOp[ 0 ], expected );
-
-				expected.sourcePosition.path = [ 2, 2, 3 ];
-				expected.howMany = 1;
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 1 ], expected );
-			} );
-
-			it( 'range intersects on left side, target inside transforming range and is less important: split into three operations', () => {
-				op.howMany = 4;
-
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 3 ] ),
-					2,
-					new Position( root, [ 2, 2, 6 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy, true );
-
-				expect( transOp.length ).to.equal( 3 );
-
-				expected.sourcePosition.path = [ 2, 2, 6 ];
-				expected.howMany = 2;
-
-				expectOperation( transOp[ 0 ], expected );
-
-				expected.sourcePosition.path = [ 2, 2, 3 ];
-				expected.howMany = 1;
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 1 ], expected );
-
-				expected.sourcePosition.path = [ 2, 2, 5 ];
-				expected.howMany = 1;
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 2 ], expected );
-			} );
-
-			it( 'range intersects on right side, target inside transforming range and is important: split into two operations', () => {
-				op.howMany = 4;
-
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 7 ] ),
-					2,
-					new Position( root, [ 2, 2, 5 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 2 );
-
-				expected.sourcePosition.path = [ 2, 2, 7 ];
-				expected.howMany = 2;
-
-				expectOperation( transOp[ 0 ], expected );
-
-				expected.sourcePosition.path = [ 2, 2, 4 ];
-				expected.howMany = 1;
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 1 ], expected );
-			} );
-
-			it( 'range intersects on right side, target inside transforming range and is less important: split into three operations', () => {
-				op.howMany = 4;
-
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 7 ] ),
-					2,
-					new Position( root, [ 2, 2, 5 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy, true );
-
-				expect( transOp.length ).to.equal( 3 );
-
-				expected.sourcePosition.path = [ 2, 2, 5 ];
-				expected.howMany = 1;
-
-				expectOperation( transOp[ 0 ], expected );
-
-				expected.sourcePosition.path = [ 2, 2, 7 ];
-				expected.howMany = 2;
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 1 ], expected );
-
-				expected.sourcePosition.path = [ 2, 2, 4 ];
-				expected.howMany = 1;
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 2 ], expected );
-			} );
-
-			it( 'range inside transforming range and is important: split into two operations', () => {
-				op.howMany = 4;
-
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 5 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 2 );
-
-				expected.sourcePosition.path = [ 2, 2, 5 ];
-				expected.howMany = 1;
-
-				expectOperation( transOp[ 0 ], expected );
-
-				expected.sourcePosition.path = [ 2, 2, 4 ];
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 1 ], expected );
-			} );
-
-			it( 'range inside transforming range and is less important: split into three operations', () => {
-				op.howMany = 4;
-
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 5 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy, true );
-
-				expect( transOp.length ).to.equal( 3 );
-
-				expected.sourcePosition.path = [ 2, 2, 5 ];
-				expected.howMany = 1;
-
-				expectOperation( transOp[ 0 ], expected );
-
-				expected.sourcePosition.path = [ 4, 1, 0 ];
-				expected.howMany = 2;
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 1 ], expected );
-
-				expected.sourcePosition.path = [ 2, 2, 4 ];
-				expected.howMany = 1;
-				expected.baseVersion++;
-
-				expectOperation( transOp[ 2 ], expected );
-			} );
-
-			it( 'range and target inside transforming range and is important: no operation update', () => {
-				op.howMany = 6;
-
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 5 ] ),
-					2,
-					new Position( root, [ 2, 2, 9 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-
-				expected.howMany = 6;
-
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range and target inside transforming range and is less important: no operation update', () => {
-				op.howMany = 6;
-
-				let transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 5 ] ),
-					2,
-					new Position( root, [ 2, 2, 9 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy, true );
-
-				expect( transOp.length ).to.equal( 1 );
-
-				expected.howMany = 6;
-
-				expectOperation( transOp[ 0 ], expected );
-			} );
-		} );
-
-		describe( 'by NoOperation', () => {
-			it( 'no operation update', () => {
-				let transformBy = new NoOperation( baseVersion );
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-		} );
-	} );
-
-	describe( 'NoOperation', () => {
-		beforeEach( () => {
-			op = new NoOperation( baseVersion );
-
-			expected = {
-				type: NoOperation,
-				baseVersion: baseVersion + 1
-			};
-		} );
-
-		describe( 'by InsertOperation', () => {
-			it( 'no operation update', () => {
-				let transformBy = new InsertOperation(
-					new Position( root, [ 0 ] ),
-					'a',
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-		} );
-
-		describe( 'by AttributeOperation', () => {
-			it( 'no operation update', () => {
-				let transformBy = new AttributeOperation(
-					new Range(
-						new Position( root, [ 0 ] ),
-						new Position( root, [ 1 ] )
-					),
-					new Attribute( 'foo', 'bar' ),
-					new Attribute( 'foo', 'xyz' ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-		} );
-
-		describe( 'by MoveOperation', () => {
-			it( 'no operation update', () => {
-				let transformBy = new MoveOperation(
-					new Position( root, [ 0 ] ),
-					2,
-					new Position( root, [ 1 ] ),
-					baseVersion
-				);
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-		} );
-
-		describe( 'by NoOperation', () => {
-			it( 'no operation update', () => {
-				let transformBy = new NoOperation( baseVersion );
-
-				let transOp = transform( op, transformBy );
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-		} );
-	} );
-} );

+ 0 - 501
packages/ckeditor5-utils/tests/document/position.js

@@ -1,501 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/element',
-	'document/character',
-	'document/position',
-	'document/document',
-	'ckeditorerror',
-	'document/nodelist'
-);
-
-describe( 'position', () => {
-	let Element, Character, Document, NodeList, Position, CKEditorError;
-
-	let doc, root, otherRoot, p, ul, li1, li2, f, o, z, b, a, r;
-
-	// root
-	//  |- p         Before: [ 0 ]       After: [ 1 ]
-	//  |- ul        Before: [ 1 ]       After: [ 2 ]
-	//     |- li     Before: [ 1, 0 ]    After: [ 1, 1 ]
-	//     |  |- f   Before: [ 1, 0, 0 ] After: [ 1, 0, 1 ]
-	//     |  |- o   Before: [ 1, 0, 1 ] After: [ 1, 0, 2 ]
-	//     |  |- z   Before: [ 1, 0, 2 ] After: [ 1, 0, 3 ]
-	//     |- li     Before: [ 1, 1 ]    After: [ 1, 2 ]
-	//        |- b   Before: [ 1, 1, 0 ] After: [ 1, 1, 1 ]
-	//        |- a   Before: [ 1, 1, 1 ] After: [ 1, 1, 2 ]
-	//        |- r   Before: [ 1, 1, 2 ] After: [ 1, 1, 3 ]
-	before( () => {
-		Element = modules[ 'document/element' ];
-		Character = modules[ 'document/character' ];
-		Document = modules[ 'document/document' ];
-		NodeList = modules[ 'document/nodelist' ];
-		Position = modules[ 'document/position' ];
-		CKEditorError = modules.ckeditorerror;
-
-		doc = new Document();
-
-		root = doc.createRoot( 'root' );
-		otherRoot = doc.createRoot( 'otherRoot' );
-
-		f = new Character( 'f' );
-		o = new Character( 'o' );
-		z = new Character( 'z' );
-
-		li1 = new Element( 'li', [], [ f, o, z ] );
-
-		b = new Character( 'b' );
-		a = new Character( 'a' );
-		r = new Character( 'r' );
-
-		li2 = new Element( 'li', [], [ b, a, r ] );
-
-		ul = new Element( 'ul', [], [ li1, li2 ] );
-
-		p = new Element( 'p' );
-
-		root.insertChildren( 0, [ p, ul ] );
-	} );
-
-	it( 'should create a position with path and document', () => {
-		let position = new Position( root, [ 0 ] );
-
-		expect( position ).to.have.property( 'path' ).that.deep.equals( [ 0 ] );
-		expect( position ).to.have.property( 'root' ).that.equals( root );
-	} );
-
-	it( 'should throw error if given path is incorrect', () => {
-		expect( () => {
-			new Position( root, {} );
-		} ).to.throw( CKEditorError, /position-path-incorrect/ );
-
-		expect( () => {
-			new Position( root, [] );
-		} ).to.throw( CKEditorError, /position-path-incorrect/ );
-	} );
-
-	it( 'should throw error if given root is not a RootElement instance', () => {
-		expect( () => {
-			new Position();
-		} ).to.throw( CKEditorError, /position-root-not-rootelement/ );
-
-		expect( () => {
-			new Position( new Element( 'p' ), [ 0 ] );
-		} ).to.throw( CKEditorError, /position-root-not-rootelement/ );
-	} );
-
-	it( 'should create positions form node and offset', () => {
-		expect( Position.createFromParentAndOffset( root, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 0 ] );
-		expect( Position.createFromParentAndOffset( root, 1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1 ] );
-		expect( Position.createFromParentAndOffset( root, 2 ) ).to.have.property( 'path' ).that.deep.equals( [ 2 ] );
-
-		expect( Position.createFromParentAndOffset( p, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 0, 0 ] );
-
-		expect( Position.createFromParentAndOffset( ul, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0 ] );
-		expect( Position.createFromParentAndOffset( ul, 1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1 ] );
-		expect( Position.createFromParentAndOffset( ul, 2 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 2 ] );
-
-		expect( Position.createFromParentAndOffset( li1, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 0 ] );
-		expect( Position.createFromParentAndOffset( li1, 1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 1 ] );
-		expect( Position.createFromParentAndOffset( li1, 2 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 2 ] );
-		expect( Position.createFromParentAndOffset( li1, 3 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 3 ] );
-	} );
-
-	it( 'should create positions before elements', () => {
-		expect( Position.createBefore( p ) ).to.have.property( 'path' ).that.deep.equals( [ 0 ] );
-
-		expect( Position.createBefore( ul ) ).to.have.property( 'path' ).that.deep.equals( [ 1 ] );
-
-		expect( Position.createBefore( li1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0 ] );
-
-		expect( Position.createBefore( f ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 0 ] );
-		expect( Position.createBefore( o ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 1 ] );
-		expect( Position.createBefore( z ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 2 ] );
-
-		expect( Position.createBefore( li2 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1 ] );
-
-		expect( Position.createBefore( b ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 0 ] );
-		expect( Position.createBefore( a ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 1 ] );
-		expect( Position.createBefore( r ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 2 ] );
-	} );
-
-	it( 'should throw error if one try to create positions before root', () => {
-		expect( () => {
-			Position.createBefore( root );
-		} ).to.throw( CKEditorError, /position-before-root/ );
-	} );
-
-	it( 'should create positions after elements', () => {
-		expect( Position.createAfter( p ) ).to.have.property( 'path' ).that.deep.equals( [ 1 ] );
-
-		expect( Position.createAfter( ul ) ).to.have.property( 'path' ).that.deep.equals( [ 2 ] );
-
-		expect( Position.createAfter( li1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1 ] );
-
-		expect( Position.createAfter( f ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 1 ] );
-		expect( Position.createAfter( o ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 2 ] );
-		expect( Position.createAfter( z ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 3 ] );
-
-		expect( Position.createAfter( li2 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 2 ] );
-
-		expect( Position.createAfter( b ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 1 ] );
-		expect( Position.createAfter( a ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 2 ] );
-		expect( Position.createAfter( r ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 3 ] );
-	} );
-
-	it( 'should throw error if one try to make positions after root', () => {
-		expect( () => {
-			Position.createAfter( root );
-		} ).to.throw( CKEditorError, /position-after-root/ );
-	} );
-
-	it( 'should have parent', () => {
-		expect( new Position( root, [ 0 ] ) ).to.have.property( 'parent' ).that.equals( root );
-		expect( new Position( root, [ 1 ] ) ).to.have.property( 'parent' ).that.equals( root );
-		expect( new Position( root, [ 2 ] ) ).to.have.property( 'parent' ).that.equals( root );
-
-		expect( new Position( root, [ 0, 0 ] ) ).to.have.property( 'parent' ).that.equals( p );
-
-		expect( new Position( root, [ 1, 0 ] ) ).to.have.property( 'parent' ).that.equals( ul );
-		expect( new Position( root, [ 1, 1 ] ) ).to.have.property( 'parent' ).that.equals( ul );
-		expect( new Position( root, [ 1, 2 ] ) ).to.have.property( 'parent' ).that.equals( ul );
-
-		expect( new Position( root, [ 1, 0, 0 ] ) ).to.have.property( 'parent' ).that.equals( li1 );
-		expect( new Position( root, [ 1, 0, 1 ] ) ).to.have.property( 'parent' ).that.equals( li1 );
-		expect( new Position( root, [ 1, 0, 2 ] ) ).to.have.property( 'parent' ).that.equals( li1 );
-		expect( new Position( root, [ 1, 0, 3 ] ) ).to.have.property( 'parent' ).that.equals( li1 );
-	} );
-
-	it( 'should have offset', () => {
-		expect( new Position( root, [ 0 ] ) ).to.have.property( 'offset' ).that.equals( 0 );
-		expect( new Position( root, [ 1 ] ) ).to.have.property( 'offset' ).that.equals( 1 );
-		expect( new Position( root, [ 2 ] ) ).to.have.property( 'offset' ).that.equals( 2 );
-
-		expect( new Position( root, [ 0, 0 ] ) ).to.have.property( 'offset' ).that.equals( 0 );
-
-		expect( new Position( root, [ 1, 0 ] ) ).to.have.property( 'offset' ).that.equals( 0 );
-		expect( new Position( root, [ 1, 1 ] ) ).to.have.property( 'offset' ).that.equals( 1 );
-		expect( new Position( root, [ 1, 2 ] ) ).to.have.property( 'offset' ).that.equals( 2 );
-
-		expect( new Position( root, [ 1, 0, 0 ] ) ).to.have.property( 'offset' ).that.equals( 0 );
-		expect( new Position( root, [ 1, 0, 1 ] ) ).to.have.property( 'offset' ).that.equals( 1 );
-		expect( new Position( root, [ 1, 0, 2 ] ) ).to.have.property( 'offset' ).that.equals( 2 );
-		expect( new Position( root, [ 1, 0, 3 ] ) ).to.have.property( 'offset' ).that.equals( 3 );
-	} );
-
-	it( 'should be able to set offset', () => {
-		let position = new Position( root, [ 1, 0, 2 ] );
-		position.offset = 4;
-
-		expect( position.offset ).to.equal( 4 );
-		expect( position.path ).to.deep.equal( [ 1, 0, 4 ] );
-	} );
-
-	it( 'should have nodeBefore', () => {
-		expect( new Position( root, [ 0 ] ) ).to.have.property( 'nodeBefore' ).that.is.null;
-		expect( new Position( root, [ 1 ] ) ).to.have.property( 'nodeBefore' ).that.equals( p );
-		expect( new Position( root, [ 2 ] ) ).to.have.property( 'nodeBefore' ).that.equals( ul );
-
-		expect( new Position( root, [ 0, 0 ] ) ).to.have.property( 'nodeBefore' ).that.is.null;
-
-		expect( new Position( root, [ 1, 0 ] ) ).to.have.property( 'nodeBefore' ).that.is.null;
-		expect( new Position( root, [ 1, 1 ] ) ).to.have.property( 'nodeBefore' ).that.equals( li1 );
-		expect( new Position( root, [ 1, 2 ] ) ).to.have.property( 'nodeBefore' ).that.equals( li2 );
-
-		expect( new Position( root, [ 1, 0, 0 ] ) ).to.have.property( 'nodeBefore' ).that.is.null;
-		expect( new Position( root, [ 1, 0, 1 ] ) ).to.have.property( 'nodeBefore' ).that.equals( f );
-		expect( new Position( root, [ 1, 0, 2 ] ) ).to.have.property( 'nodeBefore' ).that.equals( o );
-		expect( new Position( root, [ 1, 0, 3 ] ) ).to.have.property( 'nodeBefore' ).that.equals( z );
-	} );
-
-	it( 'should have nodeAfter', () => {
-		expect( new Position( root, [ 0 ] ) ).to.have.property( 'nodeAfter' ).that.equals( p );
-		expect( new Position( root, [ 1 ] ) ).to.have.property( 'nodeAfter' ).that.equals( ul );
-		expect( new Position( root, [ 2 ] ) ).to.have.property( 'nodeAfter' ).that.is.null;
-
-		expect( new Position( root, [ 0, 0 ] ) ).to.have.property( 'nodeAfter' ).that.is.null;
-
-		expect( new Position( root, [ 1, 0 ] ) ).to.have.property( 'nodeAfter' ).that.equals( li1 );
-		expect( new Position( root, [ 1, 1 ] ) ).to.have.property( 'nodeAfter' ).that.equals( li2 );
-		expect( new Position( root, [ 1, 2 ] ) ).to.have.property( 'nodeAfter' ).that.is.null;
-
-		expect( new Position( root, [ 1, 0, 0 ] ) ).to.have.property( 'nodeAfter' ).that.equals( f );
-		expect( new Position( root, [ 1, 0, 1 ] ) ).to.have.property( 'nodeAfter' ).that.equals( o );
-		expect( new Position( root, [ 1, 0, 2 ] ) ).to.have.property( 'nodeAfter' ).that.equals( z );
-		expect( new Position( root, [ 1, 0, 3 ] ) ).to.have.property( 'nodeAfter' ).that.is.null;
-	} );
-
-	it( 'should have proper parent path', () => {
-		let position = new Position( root, [ 1, 2, 3 ] );
-
-		expect( position.getParentPath() ).to.deep.equal( [ 1, 2 ] );
-	} );
-
-	it( 'should return a new, equal position when cloned', () => {
-		const position = new Position( root, [ 1, 2, 3 ] );
-		const clone = position.clone();
-
-		expect( clone ).not.to.be.equal( position ); // clone is not pointing to the same object as position
-		expect( clone.isEqual( position ) ).to.be.true; // but they are equal in the position-sense
-		expect( clone.path ).not.to.be.equal( position.path ); // make sure the paths are not the same array
-	} );
-
-	describe( 'isBefore', () => {
-		it( 'should return true if given position has same root and is before this position', () => {
-			let position = new Position( root, [ 1, 1, 2 ] );
-			let beforePosition = new Position( root, [ 1, 0 ] );
-
-			expect( position.isAfter( beforePosition ) ).to.be.true;
-		} );
-
-		it( 'should return false if given position has same root and is not before this position', () => {
-			let position = new Position( root, [ 1, 1, 2 ] );
-			let afterPosition = new Position( root, [ 1, 2 ] );
-
-			expect( position.isAfter( afterPosition ) ).to.be.false;
-		} );
-
-		it( 'should return false if given position has different root', () => {
-			let position = new Position( root, [ 1, 1, 2 ] );
-			let differentPosition = new Position( otherRoot, [ 1, 0 ] );
-
-			expect( position.isAfter( differentPosition ) ).to.be.false;
-		} );
-	} );
-
-	describe( 'isEqual', () => {
-		it( 'should return true if given position has same path and root', () => {
-			let position = new Position( root, [ 1, 1, 2 ] );
-			let samePosition = new Position( root, [ 1, 1, 2 ] );
-
-			expect( position.isEqual( samePosition ) ).to.be.true;
-		} );
-
-		it( 'should return false if given position has different path', () => {
-			let position = new Position( root, [ 1, 1, 1 ] );
-			let differentPosition = new Position( root, [ 1, 2, 2 ] );
-
-			expect( position.isEqual( differentPosition ) ).to.be.false;
-		} );
-
-		it( 'should return false if given position has different root', () => {
-			let position = new Position( root, [ 1, 1, 1 ] );
-			let differentPosition = new Position( otherRoot, [ 1, 1, 1 ] );
-
-			expect( position.isEqual( differentPosition ) ).to.be.false;
-		} );
-	} );
-
-	describe( 'isAfter', () => {
-		it( 'should return true if given position has same root and is after this position', () => {
-			let position = new Position( root, [ 1, 1, 2 ] );
-			let afterPosition = new Position( root, [ 1, 2 ] );
-
-			expect( position.isBefore( afterPosition ) ).to.be.true;
-		} );
-
-		it( 'should return false if given position has same root and is not after this position', () => {
-			let position = new Position( root, [ 1, 1, 2 ] );
-			let beforePosition = new Position( root, [ 1, 0 ] );
-
-			expect( position.isBefore( beforePosition ) ).to.be.false;
-		} );
-
-		it( 'should return false if given position has different root', () => {
-			let position = new Position( root, [ 1, 1, 2 ] );
-			let differentPosition = new Position( otherRoot, [ 1, 2 ] );
-
-			expect( position.isBefore( differentPosition ) ).to.be.false;
-		} );
-	} );
-
-	describe( 'compareWith', () => {
-		it( 'should return Position.SAME if positions are same', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const compared = new Position( root, [ 1, 2, 3 ] );
-
-			expect( position.compareWith( compared ) ).to.equal( Position.SAME );
-		} );
-
-		it( 'should return Position.BEFORE if the position is before compared one', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const compared = new Position( root, [ 1, 3 ] );
-
-			expect( position.compareWith( compared ) ).to.equal( Position.BEFORE );
-		} );
-
-		it( 'should return Position.AFTER if the position is after compared one', () => {
-			const position = new Position( root, [ 1, 2, 3, 4 ] );
-			const compared = new Position( root, [ 1, 2, 3 ] );
-
-			expect( position.compareWith( compared ) ).to.equal( Position.AFTER );
-		} );
-
-		it( 'should return Position.DIFFERENT if positions are in different roots', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const compared = new Position( otherRoot, [ 1, 2, 3 ] );
-
-			expect( position.compareWith( compared ) ).to.equal( Position.DIFFERENT );
-		} );
-	} );
-
-	describe( 'getTransformedByInsertion', () => {
-		it( 'should return a new Position instance', () => {
-			const position = new Position( root, [ 0 ] );
-			const transformed = position.getTransformedByInsertion( new Position( root, [ 2 ] ), 4, false );
-
-			expect( transformed ).not.to.equal( position );
-			expect( transformed ).to.be.instanceof( Position );
-		} );
-
-		it( 'should increment offset if insertion is in the same parent and closer offset', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByInsertion( new Position( root, [ 1, 2, 2 ] ), 2, false );
-
-			expect( transformed.offset ).to.equal( 5 );
-		} );
-
-		it( 'should not increment offset if insertion position is in different root', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByInsertion( new Position( otherRoot, [ 1, 2, 2 ] ), 2, false );
-
-			expect( transformed.offset ).to.equal( 3 );
-		} );
-
-		it( 'should not increment offset if insertion is in the same parent and the same offset', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByInsertion( new Position( root, [ 1, 2, 3 ] ), 2, false );
-
-			expect( transformed.offset ).to.equal( 3 );
-		} );
-
-		it( 'should increment offset if insertion is in the same parent and the same offset and it is inserted before', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByInsertion( new Position( root, [ 1, 2, 3 ] ), 2, true );
-
-			expect( transformed.offset ).to.equal( 5 );
-		} );
-
-		it( 'should not increment offset if insertion is in the same parent and further offset', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByInsertion( new Position( root, [ 1, 2, 4 ] ), 2, false );
-
-			expect( transformed.offset ).to.equal( 3 );
-		} );
-
-		it( 'should update path if insertion position parent is a node from that path and offset is before next node on that path', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByInsertion( new Position( root, [ 1, 2 ] ), 2, false );
-
-			expect( transformed.path ).to.deep.equal( [ 1, 4, 3 ] );
-		} );
-
-		it( 'should not update path if insertion position parent is a node from that path and offset is after next node on that path', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByInsertion( new Position( root, [ 1, 3 ] ), 2, false );
-
-			expect( transformed.path ).to.deep.equal( [ 1, 2, 3 ] );
-		} );
-	} );
-
-	describe( 'getTransformedByDeletion', () => {
-		it( 'should return a new Position instance', () => {
-			const position = new Position( root, [ 0 ] );
-			const transformed = position.getTransformedByDeletion( new Position( root, [ 2 ] ), 4 );
-
-			expect( transformed ).not.to.equal( position );
-			expect( transformed ).to.be.instanceof( Position );
-		} );
-
-		it( 'should return null if original position is inside one of removed nodes', () => {
-			const position = new Position( root, [ 1, 2 ] );
-			const transformed = position.getTransformedByDeletion( new Position( root, [ 0 ] ), 2 );
-
-			expect( transformed ).to.be.null;
-		} );
-
-		it( 'should decrement offset if deletion is in the same parent and closer offset', () => {
-			const position = new Position( root, [ 1, 2, 7 ] );
-			const transformed = position.getTransformedByDeletion( new Position( root, [ 1, 2, 2 ] ), 2 );
-
-			expect( transformed.offset ).to.equal( 5 );
-		} );
-
-		it( 'should set position offset to deletion offset if position is between removed nodes', () => {
-			const position = new Position( root, [ 1, 2, 4 ] );
-			const transformed = position.getTransformedByDeletion( new Position( root, [ 1, 2, 3 ] ), 5 );
-
-			expect( transformed.offset ).to.equal( 3 );
-		} );
-
-		it( 'should not decrement offset if deletion position is in different root', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByDeletion( new Position( otherRoot, [ 1, 2, 1 ] ), 2 );
-
-			expect( transformed.offset ).to.equal( 3 );
-		} );
-
-		it( 'should not decrement offset if deletion is in the same parent and further offset', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByDeletion( new Position( root, [ 1, 2, 4 ] ), 2 );
-
-			expect( transformed.offset ).to.equal( 3 );
-		} );
-
-		it( 'should update path if deletion position parent is a node from that path and offset is before next node on that path', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByDeletion( new Position( root, [ 1, 0 ] ), 2 );
-
-			expect( transformed.path ).to.deep.equal( [ 1, 0, 3 ] );
-		} );
-
-		it( 'should not update path if deletion position parent is a node from that path and offset is after next node on that path', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByDeletion( new Position( root, [ 1, 3 ] ), 2 );
-
-			expect( transformed.path ).to.deep.equal( [ 1, 2, 3 ] );
-		} );
-	} );
-
-	describe( 'getTransformedByMove', () => {
-		it( 'should increment offset if a range was moved to the same parent and closer offset', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByMove( new Position( root, [ 2 ] ), new Position( root, [ 1, 2, 0 ] ), 3, false );
-
-			expect( transformed.path ).to.deep.equal( [ 1, 2, 6 ] );
-		} );
-
-		it( 'should decrement offset if a range was moved from the same parent and closer offset', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByMove( new Position( root, [ 1, 2, 0 ] ), new Position( root, [ 2 ] ), 3, false );
-
-			expect( transformed.path ).to.deep.equal( [ 1, 2, 0 ] );
-		} );
-
-		it( 'should update path if a range contained this position', () => {
-			const position = new Position( root, [ 1, 2, 3 ] );
-			const transformed = position.getTransformedByMove( new Position( root, [ 1, 1 ] ), new Position( root, [ 2, 1 ] ), 3, false );
-
-			expect( transformed.path ).to.deep.equal( [ 2, 2, 3 ] );
-		} );
-	} );
-
-	describe( '_getCombined', () => {
-		it( 'should return correct combination of this and given positions', () => {
-			const position = new Position( root, [ 1, 3, 4, 2 ] );
-			const sourcePosition = new Position( root, [ 1, 1 ] );
-			const targetPosition = new Position( root, [ 2, 5 ] );
-
-			const combined = position._getCombined( sourcePosition, targetPosition );
-
-			expect( combined.path ).to.deep.equal( [ 2, 7, 4, 2 ] );
-		} );
-	} );
-} );

+ 0 - 137
packages/ckeditor5-utils/tests/document/positioniterator.js

@@ -1,137 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/element',
-	'document/character',
-	'document/positioniterator',
-	'document/position',
-	'document/range'
-);
-
-describe( 'range iterator', () => {
-	let Document, Element, Character, PositionIterator, Position, Range;
-	let ELEMENT_ENTER, ELEMENT_LEAVE, CHARACTER;
-
-	let doc, expectedItems, root, img1, paragraph, b, a, r, img2, x;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		Element = modules[ 'document/element' ];
-		Character = modules[ 'document/character' ];
-		PositionIterator = modules[ 'document/positioniterator' ];
-		Position = modules[ 'document/position' ];
-		Range = modules[ 'document/range' ];
-
-		ELEMENT_ENTER = PositionIterator.ELEMENT_ENTER;
-		ELEMENT_LEAVE = PositionIterator.ELEMENT_LEAVE;
-		CHARACTER = PositionIterator.CHARACTER;
-
-		doc = new Document();
-		root = doc.createRoot( 'root' );
-
-		// root
-		//  |- img1
-		//  |- p
-		//     |- B
-		//     |- A
-		//     |- R
-		//     |
-		//     |- img2
-		//     |
-		//     |- X
-
-		b = new Character( 'b' );
-		a = new Character( 'a' );
-		r = new Character( 'r' );
-		img2 = new Element( 'img2' );
-		x = new Character( 'x' );
-
-		paragraph = new Element( 'p', [], [ b, a, r, img2, x ] );
-		img1 = new Element( 'img1' );
-
-		root.insertChildren( 0, [ img1, paragraph ] );
-
-		expectedItems = [
-			{ type: ELEMENT_ENTER, node: img1 },
-			{ type: ELEMENT_LEAVE, node: img1 },
-			{ type: ELEMENT_ENTER, node: paragraph },
-			{ type: CHARACTER, node: b },
-			{ type: CHARACTER, node: a },
-			{ type: CHARACTER, node: r },
-			{ type: ELEMENT_ENTER, node: img2 },
-			{ type: ELEMENT_LEAVE, node: img2 },
-			{ type: CHARACTER, node: x },
-			{ type: ELEMENT_LEAVE, node: paragraph }
-		];
-	} );
-
-	it( 'should return next position', () => {
-		let iterator = new PositionIterator( new Position( root, [ 0 ] ) ); // beginning of root
-		let i, len;
-
-		for ( i = 0, len = expectedItems.length; i < len; i++ ) {
-			expect( iterator.next() ).to.deep.equal( { done: false, value: expectedItems[ i ] } );
-		}
-		expect( iterator.next() ).to.have.property( 'done' ).that.is.true;
-	} );
-
-	it( 'should return previous position', () => {
-		let iterator = new PositionIterator( new Position( root, [ 2 ] ) ); // ending of root
-
-		for ( let i = expectedItems.length - 1; i >= 0; i-- ) {
-			expect( iterator.previous() ).to.deep.equal( { done: false, value: expectedItems[ i ] } );
-		}
-		expect( iterator.previous() ).to.have.property( 'done' ).that.is.true;
-	} );
-
-	it( 'should return next position in the boundaries', () => {
-		let start = new Position( root, [ 1, 0 ] ); // p, 0
-		let end = new Position( root, [ 1, 3, 0 ] ); // img, 0
-
-		let iterator = new PositionIterator( new Range( start, end ) );
-
-		let i, len;
-
-		for ( i = 3, len = expectedItems.length; i < 7; i++ ) {
-			expect( iterator.next() ).to.deep.equal( { done: false, value: expectedItems[ i ] } );
-		}
-		expect( iterator.next() ).to.have.property( 'done' ).that.is.true;
-	} );
-
-	it( 'should return previous position in the boundaries', () => {
-		let start = new Position( root, [ 1, 0 ] ); // p, 0
-		let end = new Position( root, [ 1, 3, 0 ] ); // img, 0
-
-		let iterator = new PositionIterator( new Range( start, end ), end );
-
-		let i, len;
-
-		for ( i = 6, len = expectedItems.length; i > 2; i-- ) {
-			expect( iterator.previous() ).to.deep.equal( { done: false, value: expectedItems[ i ] } );
-		}
-		expect( iterator.previous() ).to.have.property( 'done' ).that.is.true;
-	} );
-
-	it( 'should return iterate over the range', () => {
-		let start = new Position( root, [ 0 ] ); // begging of root
-		let end = new Position( root, [ 2 ] ); // ending of root
-		let range = new Range( start, end );
-
-		let i = 0;
-		let value;
-
-		for ( value of range ) {
-			expect( value ).to.deep.equal( expectedItems[ i ] );
-			i++;
-		}
-		expect( i ).to.equal( expectedItems.length );
-	} );
-} );

+ 0 - 325
packages/ckeditor5-utils/tests/document/range.js

@@ -1,325 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: document */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/range',
-	'document/position',
-	'document/element',
-	'document/character',
-	'document/document'
-);
-
-describe( 'Range', () => {
-	let Range, Position, Element, Character, Document;
-
-	before( () => {
-		Position = modules[ 'document/position' ];
-		Range = modules[ 'document/range' ];
-		Element = modules[ 'document/element' ];
-		Character = modules[ 'document/character' ];
-		Document = modules[ 'document/document' ];
-	} );
-
-	let range, start, end, root;
-
-	beforeEach( () => {
-		let doc = new Document();
-		root = doc.createRoot( 'root' );
-
-		start = new Position( root, [ 0 ] );
-		end = new Position( root, [ 1 ] );
-
-		range = new Range( start, end );
-	} );
-
-	describe( 'constructor', () => {
-		it( 'should create a range with given positions', () => {
-			expect( range ).to.have.property( 'start' ).that.equal( start );
-			expect( range ).to.have.property( 'end' ).that.equal( end );
-		} );
-	} );
-
-	describe( 'isEqual', () => {
-		it( 'should return true if the ranges are the same', () => {
-			let sameStart = new Position( root, [ 0 ] );
-			let sameEnd = new Position( root, [ 1 ] );
-
-			let sameRange = new Range( sameStart, sameEnd );
-
-			expect( range.isEqual( sameRange ) ).to.be.true;
-		} );
-
-		it( 'should return false if the start position is different', () => {
-			let range = new Range( start, end );
-
-			let diffStart = new Position( root, [ 1 ] );
-			let sameEnd = new Position( root, [ 1 ] );
-
-			let diffRange = new Range( diffStart, sameEnd );
-
-			expect( range.isEqual( diffRange ) ).to.not.be.true;
-		} );
-
-		it( 'should return false if the end position is different', () => {
-			let sameStart = new Position( root, [ 0 ] );
-			let diffEnd = new Position( root, [ 0 ] );
-
-			let diffRange = new Range( sameStart, diffEnd );
-
-			expect( range.isEqual( diffRange ) ).to.not.be.true;
-		} );
-	} );
-
-	describe( 'static constructors', () => {
-		let p, f, o, z;
-
-		// root
-		//  |- p
-		//     |- f
-		//     |- o
-		//     |- z
-		before( () => {
-			f = new Character( 'f' );
-			o = new Character( 'o' );
-			z = new Character( 'z' );
-
-			p = new Element( 'p', [], [ f, o, z ] );
-
-			root.insertChildren( 0, [ p ] );
-		} );
-
-		describe( 'createFromElement', () => {
-			it( 'should return range', () => {
-				const range = Range.createFromElement( p );
-
-				expect( range.start.path ).to.deep.equal( [ 0, 0 ] );
-				expect( range.end.path ).to.deep.equal( [ 0, 3 ] );
-			} );
-		} );
-
-		describe( 'createFromParentsAndOffsets', () => {
-			it( 'should return range', () => {
-				const range = Range.createFromParentsAndOffsets( root, 0, p, 2 );
-
-				expect( range.start.path ).to.deep.equal( [ 0 ] );
-				expect( range.end.path ).to.deep.equal( [ 0, 2 ] );
-			} );
-		} );
-
-		describe( 'createFromPositionAndOffset', () => {
-			it( 'should make range from start position and offset', () => {
-				const position = new Position( root, [ 1, 2, 3 ] );
-				const range = Range.createFromPositionAndOffset( position, 4 );
-
-				expect( range ).to.be.instanceof( Range );
-				expect( range.start.isEqual( position ) ).to.be.true;
-				expect( range.end.root ).to.equal( range.start.root );
-				expect( range.end.path ).to.deep.equal( [ 1, 2, 7 ] );
-			} );
-		} );
-	} );
-
-	describe( 'getNodes', () => {
-		it( 'should iterate over all nodes which "starts" in the range', () => {
-			let nodes = [];
-
-			const a = new Character( 'a' );
-			const b = new Character( 'b' );
-			const x = new Character( 'x' );
-			const y = new Character( 'y' );
-
-			const e1 = new Element( 'e1' );
-			const e2 = new Element( 'e2' );
-
-			e1.insertChildren( 0, [ a, b ] );
-			e2.insertChildren( 0, [ x, y ] );
-			root.insertChildren( 0, [ e1, e2 ] );
-
-			let range = new Range(
-				new Position( root, [ 0, 1 ] ),
-				new Position( root, [ 1, 1 ] )
-			);
-
-			for ( let node of range.getNodes() ) {
-				nodes.push( node );
-			}
-
-			expect( nodes ).to.deep.equal( [ b, e2, x ] );
-		} );
-	} );
-
-	describe( 'clone', () => {
-		it( 'should return a new, equal position', () => {
-			const clone = range.clone();
-
-			expect( clone ).not.to.be.equal( range ); // clone is not pointing to the same object as position
-			expect( clone.isEqual( range ) ).to.be.true; // but they are equal in the position-sense
-		} );
-	} );
-
-	describe( 'containsPosition', () => {
-		beforeEach( () => {
-			range = new Range( new Position( root, [ 1 ] ), new Position( root, [ 3 ] ) );
-		} );
-
-		it( 'should return false if position is before range', () => {
-			const position = new Position( root, [ 0, 4 ] );
-
-			expect( range.containsPosition( position ) ).to.be.false;
-		} );
-
-		it( 'should return false if position is after range', () => {
-			const position = new Position( root, [ 3, 0 ] );
-
-			expect( range.containsPosition( position ) ).to.be.false;
-		} );
-
-		it( 'should return true if position is inside range', () => {
-			const position = new Position( root, [ 2, 2 ] );
-
-			expect( range.containsPosition( position ) ).to.be.true;
-		} );
-	} );
-
-	describe( 'getTransformedByInsertion', () => {
-		it( 'should return an array of Range objects', () => {
-			const range = new Range( new Position( root, [ 0 ] ), new Position( root, [ 1 ] ) );
-			const transformed = range.getTransformedByInsertion( new Position( root, [ 2 ] ), 2 );
-
-			expect( transformed ).to.be.instanceof( Array );
-			expect( transformed[ 0 ] ).to.be.instanceof( Range );
-		} );
-
-		it( 'should update it\'s positions offsets if insertion is before range and they are affected', () => {
-			const range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 3, 4 ] ) );
-			const transformed = range.getTransformedByInsertion( new Position( root, [ 3, 1 ] ), 2 );
-
-			expect( transformed[ 0 ].start.offset ).to.equal( 4 );
-			expect( transformed[ 0 ].end.offset ).to.equal( 6 );
-		} );
-
-		it( 'should update it\'s positions paths if insertion is before range and they are affected', () => {
-			const range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 4, 4 ] ) );
-			const transformed = range.getTransformedByInsertion( new Position( root, [ 0 ] ), 2 );
-
-			expect( transformed[ 0 ].start.path[ 0 ] ).to.equal( 5 );
-			expect( transformed[ 0 ].end.path[ 0 ] ).to.equal( 6 );
-		} );
-
-		it( 'should return array with two ranges and updated positions if insertion was in the middle of range', () => {
-			const range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 5, 4 ] ) );
-			const transformed = range.getTransformedByInsertion( new Position( root, [ 4, 1, 6 ] ), 4 );
-
-			expect( transformed.length ).to.equal( 2 );
-
-			expect( transformed[ 0 ].start.path ).to.deep.equal( [ 3, 2 ] );
-			expect( transformed[ 0 ].end.path ).to.deep.equal( [ 4, 1, 6 ] );
-
-			expect( transformed[ 1 ].start.path ).to.deep.equal( [ 4, 1, 10 ] );
-			expect( transformed[ 1 ].end.path ).to.deep.equal( [ 5, 4 ] );
-		} );
-
-		it( 'should not updated positions if insertion is after range', () => {
-			const range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 4, 4 ] ) );
-			const transformed = range.getTransformedByInsertion( new Position( root, [ 4, 4 ] ), 3 );
-
-			expect( transformed[ 0 ].start.path ).to.deep.equal( [ 3, 2 ] );
-			expect( transformed[ 0 ].end.path ).to.deep.equal( [ 4, 4 ] );
-		} );
-	} );
-
-	describe( 'getDifference', () => {
-		let range;
-
-		beforeEach( () => {
-			range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 5, 4 ] ) );
-		} );
-
-		it( 'should return an array of Range objects', () => {
-			const otherRange = new Range( new Position( root, [ 6 ] ), new Position( root, [ 7 ] ) );
-			const diff = range.getDifference( otherRange );
-
-			expect( diff ).to.be.instanceof( Array );
-			expect( diff[ 0 ] ).to.be.instanceof( Range );
-		} );
-
-		it( 'should return original range if other range does not intersect with it', () => {
-			const otherRange = new Range( new Position( root, [ 6 ] ), new Position( root, [ 7 ] ) );
-			const diff = range.getDifference( otherRange );
-
-			expect( diff[ 0 ].start.path ).to.deep.equal( [ 3, 2 ] );
-			expect( diff[ 0 ].end.path ).to.deep.equal( [ 5, 4 ] );
-		} );
-
-		it( 'should return shrunken range if other range intersects with it', () => {
-			const otherRange = new Range( new Position( root, [ 4, 1 ] ), new Position( root, [ 7 ] ) );
-			const diff = range.getDifference( otherRange );
-
-			expect( diff[ 0 ].start.path ).to.deep.equal( [ 3, 2 ] );
-			expect( diff[ 0 ].end.path ).to.deep.equal( [ 4, 1 ] );
-		} );
-
-		it( 'should return an empty array if other range contains or is same as the original range', () => {
-			const otherRange = new Range( new Position( root, [ 2 ] ), new Position( root, [ 6 ] ) );
-			const diff = range.getDifference( otherRange );
-
-			expect( diff.length ).to.equal( 0 );
-		} );
-
-		it( 'should two ranges if other range is contained by the original range', () => {
-			const otherRange = new Range( new Position( root, [ 3, 7 ] ), new Position( root, [ 4, 1 ] ) );
-			const diff = range.getDifference( otherRange );
-
-			expect( diff.length ).to.equal( 2 );
-
-			expect( diff[ 0 ].start.path ).to.deep.equal( [ 3, 2 ] );
-			expect( diff[ 0 ].end.path ).to.deep.equal( [ 3, 7 ] );
-
-			expect( diff[ 1 ].start.path ).to.deep.equal( [ 4, 1 ] );
-			expect( diff[ 1 ].end.path ).to.deep.equal( [ 5, 4 ] );
-		} );
-	} );
-
-	describe( 'getIntersection', () => {
-		let range;
-
-		beforeEach( () => {
-			range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 5, 4 ] ) );
-		} );
-
-		it( 'should return null if ranges do not intersect', () => {
-			const otherRange = new Range( new Position( root, [ 5, 4 ] ), new Position( root, [ 7 ] ) );
-			const common = range.getIntersection( otherRange );
-
-			expect( common ).to.be.null;
-		} );
-
-		it( 'should return a range equal to the common part of ranges - original range contains the other range', () => {
-			const otherRange = new Range( new Position( root, [ 4 ] ), new Position( root, [ 5 ] ) );
-			const common = range.getIntersection( otherRange );
-
-			expect( common.isEqual( otherRange ) ).to.be.true;
-		} );
-
-		it( 'should return a range equal to the common part of ranges - original range is contained by the other range', () => {
-			const otherRange = new Range( new Position( root, [ 3 ] ), new Position( root, [ 6 ] ) );
-			const common = range.getIntersection( otherRange );
-
-			expect( common.isEqual( range ) ).to.be.true;
-		} );
-
-		it( 'should return a range equal to the common part of ranges - original range intersects with the other range', () => {
-			const otherRange = new Range( new Position( root, [ 3 ] ), new Position( root, [ 4, 7 ] ) );
-			const common = range.getIntersection( otherRange );
-
-			expect( common.start.path ).to.deep.equal( [ 3, 2 ] );
-			expect( common.end.path ).to.deep.equal( [ 4, 7 ] );
-		} );
-	} );
-} );

+ 0 - 42
packages/ckeditor5-utils/tests/document/rootelement.js

@@ -1,42 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* jshint expr: true */
-
-/* bender-tags: document */
-
-/* bender-include: ../_tools/tools.js */
-
-'use strict';
-
-const getIteratorCount = bender.tools.core.getIteratorCount;
-
-const modules = bender.amd.require(
-	'document/document',
-	'document/element',
-	'document/rootelement'
-);
-
-describe( 'Element', () => {
-	let Document, Element, RootElement;
-
-	before( () => {
-		Document = modules[ 'document/document' ];
-		Element = modules[ 'document/element' ];
-		RootElement = modules[ 'document/rootelement' ];
-	} );
-
-	describe( 'constructor', () => {
-		it( 'should create root element without attributes', () => {
-			let doc = new Document();
-			let root = new RootElement( doc );
-
-			expect( root ).to.be.an.instanceof( Element );
-			expect( root ).to.have.property( 'document' ).that.equals( doc );
-			expect( getIteratorCount( root.getAttrs() ) ).to.equal( 0 );
-			expect( root.getChildCount() ).to.equal( 0 );
-		} );
-	} );
-} );

+ 0 - 31
packages/ckeditor5-utils/tests/document/text.js

@@ -1,31 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* jshint expr: true */
-
-/* bender-tags: document */
-
-'use strict';
-
-const modules = bender.amd.require(
-	'document/text',
-	'document/attribute'
-);
-
-describe( 'Text', () => {
-	describe( 'constructor', () => {
-		it( 'should create character without attributes', () => {
-			const Text = modules[ 'document/text' ];
-			const Attribute = modules[ 'document/attribute' ];
-
-			let attrs = [ new Attribute( 'bold', true ) ];
-			let text = new Text( 'bar', attrs );
-
-			expect( text ).to.have.property( 'text' ).that.equals( 'bar' );
-			expect( text ).to.have.property( 'attrs' ).that.is.an( 'array' );
-			expect( text.attrs ).to.be.deep.equals( attrs );
-		} );
-	} );
-} );