Browse Source

Added `usingOperation` flag to `setMarker` and `removeMarker`.

Maciej Bukowski 7 years ago
parent
commit
874c1b142b

+ 12 - 3
packages/ckeditor5-engine/src/model/writer.js

@@ -194,7 +194,7 @@ export default class Writer {
 					markerRange.end._getCombined( rangeRootPosition, position )
 				);
 
-				this.setMarker( markerName, range );
+				this.setMarker( markerName, range, { usingOperation: true } );
 			}
 		}
 	}
@@ -775,7 +775,7 @@ export default class Writer {
 	 * @param {module:engine/model/markercollection~Marker|String} markerOrName Marker or marker name to add or update.
 	 * @param {module:engine/model/range~Range} [newRange] Marker range.
 	 */
-	setMarker( markerOrName, newRange ) {
+	setMarker( markerOrName, newRange, options = { usingOperation: false } ) {
 		this._assertWriterUsedCorrectly();
 
 		const name = typeof markerOrName == 'string' ? markerOrName : markerOrName.name;
@@ -790,6 +790,11 @@ export default class Writer {
 			throw new CKEditorError( 'writer-setMarker-no-range: Range parameter is required when adding a new marker.' );
 		}
 
+		if ( !options.usingOperation ) {
+			const marker = this.model.markers.set( name, newRange );
+			return marker;
+		}
+
 		const currentRange = currentMarker ? currentMarker.getRange() : null;
 
 		if ( !newRange ) {
@@ -807,7 +812,7 @@ export default class Writer {
 	 *
 	 * @param {module:engine/model/markercollection~Marker|String} markerOrName Marker or marker name to remove.
 	 */
-	removeMarker( markerOrName ) {
+	removeMarker( markerOrName, options = { usingOperation: false } ) {
 		this._assertWriterUsedCorrectly();
 
 		const name = typeof markerOrName == 'string' ? markerOrName : markerOrName.name;
@@ -821,6 +826,10 @@ export default class Writer {
 			throw new CKEditorError( 'writer-removeMarker-no-marker: Trying to remove marker which does not exist.' );
 		}
 
+		if ( !options.usingOperation ) {
+			return this.model.markers.remove( name );
+		}
+
 		const oldRange = this.model.markers.get( name ).getRange();
 
 		addMarkerOperation( this, name, oldRange, null );

+ 3 - 3
packages/ckeditor5-engine/tests/controller/datacontroller.js

@@ -321,7 +321,7 @@ describe( 'DataController', () => {
 
 			model.change( writer => {
 				writer.insert( modelElement, modelRoot, 0 );
-				writer.setMarker( 'marker:a', Range.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 1 ) );
+				writer.setMarker( 'marker:a', Range.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 1 ), { usingOperation: true } );
 			} );
 
 			const viewDocumentFragment = data.toView( modelElement );
@@ -343,8 +343,8 @@ describe( 'DataController', () => {
 			model.change( writer => {
 				writer.insert( modelElement, modelRoot, 0 );
 
-				writer.setMarker( 'marker:a', Range.createFromParentsAndOffsets( modelP1, 1, modelP1, 3 ) );
-				writer.setMarker( 'marker:b', Range.createFromParentsAndOffsets( modelP2, 0, modelP2, 2 ) );
+				writer.setMarker( 'marker:a', Range.createFromParentsAndOffsets( modelP1, 1, modelP1, 3 ), { usingOperation: true } );
+				writer.setMarker( 'marker:b', Range.createFromParentsAndOffsets( modelP2, 0, modelP2, 2 ), { usingOperation: true } );
 			} );
 
 			const viewDocumentFragment = data.toView( modelP1 );

+ 38 - 37
packages/ckeditor5-engine/tests/controller/editingcontroller.js

@@ -232,8 +232,8 @@ describe( 'EditingController', () => {
 		it( 'should convert adding marker', () => {
 			const range = new ModelRange( new ModelPosition( modelRoot, [ 0, 1 ] ), new ModelPosition( modelRoot, [ 2, 2 ] ) );
 
-			model.change( () => {
-				model.markers.set( 'marker', range );
+			model.change( writer => {
+				writer.setMarker( 'marker', range );
 			} );
 
 			expect( getViewData( editing.view, { withoutSelection: true } ) )
@@ -243,12 +243,12 @@ describe( 'EditingController', () => {
 		it( 'should convert removing marker', () => {
 			const range = new ModelRange( new ModelPosition( modelRoot, [ 0, 1 ] ), new ModelPosition( modelRoot, [ 2, 2 ] ) );
 
-			model.change( () => {
-				model.markers.set( 'marker', range );
+			model.change( writer => {
+				writer.setMarker( 'marker', range );
 			} );
 
-			model.change( () => {
-				model.markers.remove( 'marker' );
+			model.change( writer => {
+				writer.removeMarker( 'marker' );
 			} );
 
 			expect( getViewData( editing.view, { withoutSelection: true } ) )
@@ -258,14 +258,14 @@ describe( 'EditingController', () => {
 		it( 'should convert changing marker', () => {
 			const range = new ModelRange( new ModelPosition( modelRoot, [ 0, 1 ] ), new ModelPosition( modelRoot, [ 2, 2 ] ) );
 
-			model.change( () => {
-				model.markers.set( 'marker', range );
+			model.change( writer => {
+				writer.setMarker( 'marker', range );
 			} );
 
 			const range2 = new ModelRange( new ModelPosition( modelRoot, [ 0, 0 ] ), new ModelPosition( modelRoot, [ 0, 2 ] ) );
 
-			model.change( () => {
-				model.markers.set( 'marker', range2 );
+			model.change( writer => {
+				writer.setMarker( 'marker', range2 );
 			} );
 
 			expect( getViewData( editing.view, { withoutSelection: true } ) )
@@ -275,11 +275,8 @@ describe( 'EditingController', () => {
 		it( 'should convert insertion into marker', () => {
 			const range = new ModelRange( new ModelPosition( modelRoot, [ 0, 1 ] ), new ModelPosition( modelRoot, [ 2, 2 ] ) );
 
-			model.change( () => {
-				model.markers.set( 'marker', range );
-			} );
-
 			model.change( writer => {
+				writer.setMarker( 'marker', range );
 				writer.insertText( 'xyz', new ModelPosition( modelRoot, [ 1, 0 ] ) );
 			} );
 
@@ -290,8 +287,8 @@ describe( 'EditingController', () => {
 		it( 'should convert move to marker', () => {
 			const range = new ModelRange( new ModelPosition( modelRoot, [ 0, 1 ] ), new ModelPosition( modelRoot, [ 2, 2 ] ) );
 
-			model.change( () => {
-				model.markers.set( 'marker', range );
+			model.change( writer => {
+				writer.setMarker( 'marker', range );
 			} );
 
 			model.change( writer => {
@@ -308,8 +305,8 @@ describe( 'EditingController', () => {
 		it( 'should convert move from marker', () => {
 			const range = new ModelRange( new ModelPosition( modelRoot, [ 0, 1 ] ), new ModelPosition( modelRoot, [ 2, 2 ] ) );
 
-			model.change( () => {
-				model.markers.set( 'marker', range );
+			model.change( writer => {
+				writer.setMarker( 'marker', range );
 			} );
 
 			model.change( writer => {
@@ -326,8 +323,8 @@ describe( 'EditingController', () => {
 		it( 'should convert the whole marker move', () => {
 			const range = new ModelRange( new ModelPosition( modelRoot, [ 0, 1 ] ), new ModelPosition( modelRoot, [ 0, 3 ] ) );
 
-			model.change( () => {
-				model.markers.set( 'marker', range );
+			model.change( writer => {
+				writer.setMarker( 'marker', range );
 			} );
 
 			model.change( writer => {
@@ -386,7 +383,7 @@ describe( 'EditingController', () => {
 
 		it( 'should remove marker from view if it will be affected by insert operation', () => {
 			model.change( writer => {
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ) );
+				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ), { usingOperation: true } );
 			} );
 
 			// Adding with 'high' priority, because `applyOperation` is decorated - its default callback is fired with 'normal' priority.
@@ -404,7 +401,7 @@ describe( 'EditingController', () => {
 
 		it( 'should remove marker from view if it will be affected by remove operation', () => {
 			model.change( writer => {
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ) );
+				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ), { usingOperation: true } );
 			} );
 
 			// Adding with 'high' priority, because `applyOperation` is decorated - its default callback is fired with 'normal' priority.
@@ -422,7 +419,7 @@ describe( 'EditingController', () => {
 
 		it( 'should remove marker from view if it will be affected by move operation', () => {
 			model.change( writer => {
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ) );
+				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ), { usingOperation: true } );
 			} );
 
 			// Adding with 'high' priority, because `applyOperation` is decorated - its default callback is fired with 'normal' priority.
@@ -442,7 +439,11 @@ describe( 'EditingController', () => {
 
 		it( 'should remove marker from view if it will be affected by rename operation', () => {
 			model.change( writer => {
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 1 ) );
+				writer.setMarker(
+					'marker',
+					ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 1 ),
+					{ usingOperation: true }
+				);
 			} );
 
 			// Adding with 'high' priority, because `applyOperation` is decorated - its default callback is fired with 'normal' priority.
@@ -460,7 +461,7 @@ describe( 'EditingController', () => {
 
 		it( 'should remove marker from view if it will be affected by marker operation', () => {
 			model.change( writer => {
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ) );
+				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ), { usingOperation: true } );
 			} );
 
 			// Adding with 'high' priority, because `applyOperation` is decorated - its default callback is fired with 'normal' priority.
@@ -472,7 +473,7 @@ describe( 'EditingController', () => {
 			model.change( writer => {
 				const p2 = p1.nextSibling;
 
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p2, 1, p2, 2 ) );
+				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p2, 1, p2, 2 ), { usingOperation: true } );
 			} );
 
 			expect( getViewData( editing.view, { withoutSelection: true } ) ).to.equal( '<p>foo</p><p>b<span>a</span>r</p>' );
@@ -480,7 +481,7 @@ describe( 'EditingController', () => {
 
 		it( 'should remove marker from view if it is removed through marker collection', () => {
 			model.change( writer => {
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ) );
+				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ), { usingOperation: true } );
 			} );
 
 			// Adding with 'high' priority, because `applyOperation` is decorated - its default callback is fired with 'normal' priority.
@@ -489,8 +490,8 @@ describe( 'EditingController', () => {
 				expect( getViewData( editing.view, { withoutSelection: true } ) ).to.equal( '<p>foo</p><p>bar</p>' );
 			}, { priority: 'low' } );
 
-			model.change( () => {
-				model.markers.remove( 'marker' );
+			model.change( writer => {
+				writer.removeMarker( 'marker' );
 			} );
 
 			expect( getViewData( editing.view, { withoutSelection: true } ) ).to.equal( '<p>foo</p><p>bar</p>' );
@@ -498,7 +499,7 @@ describe( 'EditingController', () => {
 
 		it( 'should not remove marker if applied operation is an attribute operation', () => {
 			model.change( writer => {
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ) );
+				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ), { usingOperation: true } );
 			} );
 
 			// Adding with 'high' priority, because `applyOperation` is decorated - its default callback is fired with 'normal' priority.
@@ -516,7 +517,7 @@ describe( 'EditingController', () => {
 
 		it( 'should not crash if multiple operations affect a marker', () => {
 			model.change( writer => {
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ) );
+				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ), { usingOperation: true } );
 			} );
 
 			model.change( writer => {
@@ -530,12 +531,12 @@ describe( 'EditingController', () => {
 
 		it( 'should not crash if marker is removed, added and removed #1', () => {
 			model.change( writer => {
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ) );
+				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ), { usingOperation: true } );
 			} );
 
 			model.change( writer => {
 				writer.insertText( 'a', p1, 0 );
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 3, p1, 4 ) );
+				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 3, p1, 4 ), { usingOperation: true } );
 				writer.insertText( 'a', p1, 0 );
 			} );
 
@@ -544,13 +545,13 @@ describe( 'EditingController', () => {
 
 		it( 'should not crash if marker is removed, added and removed #2', () => {
 			model.change( writer => {
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ) );
+				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 1, p1, 2 ), { usingOperation: true } );
 			} );
 
 			model.change( writer => {
-				writer.removeMarker( 'marker' );
-				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 0, p1, 1 ) );
-				writer.removeMarker( 'marker' );
+				writer.removeMarker( 'marker', { usingOperation: true } );
+				writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( p1, 0, p1, 1 ), { usingOperation: true } );
+				writer.removeMarker( 'marker', { usingOperation: true } );
 			} );
 
 			expect( getViewData( editing.view, { withoutSelection: true } ) ).to.equal( '<p>foo</p><p>bar</p>' );

+ 40 - 40
packages/ckeditor5-engine/tests/conversion/buildmodelconverter.js

@@ -348,8 +348,8 @@ describe( 'Model converter builder', () => {
 				attributes: { title: 'highlight title' }
 			} );
 
-			model.change( () => {
-				model.markers.set( 'search', ModelRange.createFromParentsAndOffsets( modelElement, 2, modelElement, 4 ) );
+			model.change( writer => {
+				writer.setMarker( 'search', ModelRange.createFromParentsAndOffsets( modelElement, 2, modelElement, 4 ) );
 			} );
 
 			expect( viewToString( viewRoot ) ).to.equal(
@@ -363,8 +363,8 @@ describe( 'Model converter builder', () => {
 
 			expect( viewRoot.getChild( 0 ).getChild( 1 ).priority ).to.equal( 3 );
 
-			model.change( () => {
-				model.markers.remove( 'search' );
+			model.change( writer => {
+				writer.removeMarker( 'search' );
 			} );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -377,8 +377,8 @@ describe( 'Model converter builder', () => {
 				attributes: { title: 'highlight title' }
 			} ) );
 
-			model.change( () => {
-				model.markers.set( 'search', ModelRange.createFromParentsAndOffsets( modelElement, 2, modelElement, 4 ) );
+			model.change( writer => {
+				writer.setMarker( 'search', ModelRange.createFromParentsAndOffsets( modelElement, 2, modelElement, 4 ) );
 			} );
 
 			expect( viewToString( viewRoot ) ).to.equal(
@@ -392,8 +392,8 @@ describe( 'Model converter builder', () => {
 
 			expect( viewRoot.getChild( 0 ).getChild( 1 ).priority ).to.equal( 12 );
 
-			model.change( () => {
-				model.markers.remove( 'search' );
+			model.change( writer => {
+				writer.removeMarker( 'search' );
 			} );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -404,14 +404,14 @@ describe( 'Model converter builder', () => {
 				class: 'highlight'
 			} );
 
-			model.change( () => {
-				model.markers.set( 'search', ModelRange.createFromParentsAndOffsets( modelElement, 2, modelElement, 2 ) );
+			model.change( writer => {
+				writer.setMarker( 'search', ModelRange.createFromParentsAndOffsets( modelElement, 2, modelElement, 2 ) );
 			} );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
 
-			model.change( () => {
-				model.markers.remove( 'search' );
+			model.change( writer => {
+				writer.removeMarker( 'search' );
 			} );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -421,8 +421,8 @@ describe( 'Model converter builder', () => {
 			buildModelConverter().for( dispatcher ).fromMarker( 'search' ).toHighlight( { class: 'highlight' } );
 			buildModelConverter().for( dispatcher ).fromMarker( 'search' ).withPriority( 'high' ).toHighlight( { class: 'override' } );
 
-			model.change( () => {
-				model.markers.set( 'search', ModelRange.createFromParentsAndOffsets( modelElement, 2, modelElement, 4 ) );
+			model.change( writer => {
+				writer.setMarker( 'search', ModelRange.createFromParentsAndOffsets( modelElement, 2, modelElement, 4 ) );
 			} );
 
 			expect( viewToString( viewRoot ) ).to.equal(
@@ -468,14 +468,14 @@ describe( 'Model converter builder', () => {
 			it( 'using passed view element name', () => {
 				buildModelConverter().for( dispatcher ).fromMarker( 'search' ).toElement( 'span' );
 
-				model.change( () => {
-					model.markers.set( 'search', range );
+				model.change( writer => {
+					writer.setMarker( 'search', range );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>fo<span></span>obar</p></div>' );
 
-				model.change( () => {
-					model.markers.remove( 'search' );
+				model.change( writer => {
+					writer.removeMarker( 'search' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -485,14 +485,14 @@ describe( 'Model converter builder', () => {
 				const viewElement = new ViewUIElement( 'span', { class: 'search' } );
 				buildModelConverter().for( dispatcher ).fromMarker( 'search' ).toElement( viewElement );
 
-				model.change( () => {
-					model.markers.set( 'search', range );
+				model.change( writer => {
+					writer.setMarker( 'search', range );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>fo<span class="search"></span>obar</p></div>' );
 
-				model.change( () => {
-					model.markers.remove( 'search' );
+				model.change( writer => {
+					writer.removeMarker( 'search' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -505,14 +505,14 @@ describe( 'Model converter builder', () => {
 					return new ViewUIElement( 'span', { class: className } );
 				} );
 
-				model.change( () => {
-					model.markers.set( 'search:red', range );
+				model.change( writer => {
+					writer.setMarker( 'search:red', range );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>fo<span class="search search-color-red"></span>obar</p></div>' );
 
-				model.change( () => {
-					model.markers.remove( 'search:red' );
+				model.change( writer => {
+					writer.removeMarker( 'search:red' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -527,14 +527,14 @@ describe( 'Model converter builder', () => {
 			it( 'using passed view element name', () => {
 				buildModelConverter().for( dispatcher ).fromMarker( 'search' ).toElement( 'span' );
 
-				model.change( () => {
-					model.markers.set( 'search', range );
+				model.change( writer => {
+					writer.setMarker( 'search', range );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>fo<span></span>ob<span></span>ar</p></div>' );
 
-				model.change( () => {
-					model.markers.remove( 'search' );
+				model.change( writer => {
+					writer.removeMarker( 'search' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -544,16 +544,16 @@ describe( 'Model converter builder', () => {
 				const viewElement = new ViewUIElement( 'span', { class: 'search' } );
 				buildModelConverter().for( dispatcher ).fromMarker( 'search' ).toElement( viewElement );
 
-				model.change( () => {
-					model.markers.set( 'search', range );
+				model.change( writer => {
+					writer.setMarker( 'search', range );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal(
 					'<div><p>fo<span class="search"></span>ob<span class="search"></span>ar</p></div>'
 				);
 
-				model.change( () => {
-					model.markers.remove( 'search' );
+				model.change( writer => {
+					writer.removeMarker( 'search' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -566,16 +566,16 @@ describe( 'Model converter builder', () => {
 					return new ViewUIElement( 'span', { class: className } );
 				} );
 
-				model.change( () => {
-					model.markers.set( 'search:red', range );
+				model.change( writer => {
+					writer.setMarker( 'search:red', range );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal(
 					'<div><p>fo<span class="search search-color-red"></span>ob<span class="search search-color-red"></span>ar</p></div>'
 				);
 
-				model.change( () => {
-					model.markers.remove( 'search:red' );
+				model.change( writer => {
+					writer.removeMarker( 'search:red' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -588,8 +588,8 @@ describe( 'Model converter builder', () => {
 			buildModelConverter().for( dispatcher ).fromMarker( 'search' ).toElement( 'normal' );
 			buildModelConverter().for( dispatcher ).fromMarker( 'search' ).withPriority( 'high' ).toElement( 'high' );
 
-			model.change( () => {
-				model.markers.set( 'search', range );
+			model.change( writer => {
+				writer.setMarker( 'search', range );
 			} );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>fo<high></high>obar</p></div>' );

+ 6 - 4
packages/ckeditor5-engine/tests/conversion/model-selection-to-view-converters.js

@@ -176,6 +176,8 @@ describe( 'model-selection-to-view-converters', () => {
 		} );
 
 		describe( 'collapsed selection', () => {
+			let marker;
+
 			it( 'in container', () => {
 				test(
 					[ 1, 1 ],
@@ -194,9 +196,9 @@ describe( 'model-selection-to-view-converters', () => {
 
 			it( 'in attribute and marker', () => {
 				setModelData( model, 'fo<$text bold="true">ob</$text>ar' );
-				const marker = model.markers.set( 'marker', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 5 ) );
 
 				model.change( writer => {
+					marker = writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 5 ) );
 					writer.setSelection( new ModelRange( ModelPosition.createAt( modelRoot, 3 ) ) );
 				} );
 
@@ -218,9 +220,9 @@ describe( 'model-selection-to-view-converters', () => {
 
 			it( 'in attribute and marker - no attribute', () => {
 				setModelData( model, 'fo<$text bold="true">ob</$text>ar' );
-				const marker = model.markers.set( 'marker', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 5 ) );
 
 				model.change( writer => {
+					marker = writer.setMarker( 'marker', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 5 ) );
 					writer.setSelection( new ModelRange( ModelPosition.createAt( modelRoot, 3 ) ) );
 					writer.removeSelectionAttribute( 'bold' );
 				} );
@@ -246,9 +248,9 @@ describe( 'model-selection-to-view-converters', () => {
 				) );
 
 				setModelData( model, 'foobar' );
-				const marker = model.markers.set( 'marker2', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 5 ) );
 
 				model.change( writer => {
+					marker = writer.setMarker( 'marker2', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 5 ) );
 					writer.setSelection( new ModelRange( ModelPosition.createAt( modelRoot, 3 ) ) );
 				} );
 
@@ -271,9 +273,9 @@ describe( 'model-selection-to-view-converters', () => {
 				dispatcher.on( 'addMarker:marker3', highlightText( () => null ) );
 
 				setModelData( model, 'foobar' );
-				const marker = model.markers.set( 'marker3', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 5 ) );
 
 				model.change( writer => {
+					marker = writer.setMarker( 'marker3', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 5 ) );
 					writer.setSelection( new ModelRange( ModelPosition.createAt( modelRoot, 3 ) ) );
 				} );
 

+ 50 - 50
packages/ckeditor5-engine/tests/conversion/model-to-view-converters.js

@@ -370,14 +370,14 @@ describe( 'model-to-view-converters', () => {
 				dispatcher.on( 'addMarker:marker', insertUIElement( viewUi ) );
 				dispatcher.on( 'removeMarker:marker', removeUIElement( viewUi ) );
 
-				model.change( () => {
-					model.markers.set( 'marker', range );
+				model.change( writer => {
+					writer.setMarker( 'marker', range );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo<span class="marker"></span>bar</p></div>' );
 
-				model.change( () => {
-					model.markers.remove( 'marker' );
+				model.change( writer => {
+					writer.removeMarker( 'marker' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -389,14 +389,14 @@ describe( 'model-to-view-converters', () => {
 				dispatcher.on( 'addMarker:marker', insertUIElement( () => viewUi ) );
 				dispatcher.on( 'removeMarker:marker', removeUIElement( () => viewUi ) );
 
-				model.change( () => {
-					model.markers.set( 'marker', range );
+				model.change( writer => {
+					writer.setMarker( 'marker', range );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo<span class="marker"></span>bar</p></div>' );
 
-				model.change( () => {
-					model.markers.remove( 'marker' );
+				model.change( writer => {
+					writer.removeMarker( 'marker' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -422,14 +422,14 @@ describe( 'model-to-view-converters', () => {
 				dispatcher.on( 'addMarker:marker', insertUIElement( () => null ) );
 				dispatcher.on( 'removeMarker:marker', removeUIElement( () => null ) );
 
-				model.change( () => {
-					model.markers.set( 'marker', range );
+				model.change( writer => {
+					writer.setMarker( 'marker', range );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
 
-				model.change( () => {
-					model.markers.remove( 'marker' );
+				model.change( writer => {
+					writer.removeMarker( 'marker' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -447,15 +447,15 @@ describe( 'model-to-view-converters', () => {
 				dispatcher.on( 'addMarker:marker', insertUIElement( viewUi ) );
 				dispatcher.on( 'removeMarker:marker', removeUIElement( viewUi ) );
 
-				model.change( () => {
-					model.markers.set( 'marker', range );
+				model.change( writer => {
+					writer.setMarker( 'marker', range );
 				} );
 
 				expect( viewToString( viewRoot ) )
 					.to.equal( '<div><p>fo<span class="marker"></span>oba<span class="marker"></span>r</p></div>' );
 
-				model.change( () => {
-					model.markers.remove( 'marker' );
+				model.change( writer => {
+					writer.removeMarker( 'marker' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -467,15 +467,15 @@ describe( 'model-to-view-converters', () => {
 				dispatcher.on( 'addMarker:marker', insertUIElement( viewUi ) );
 				dispatcher.on( 'removeMarker:marker', removeUIElement( viewUi ) );
 
-				model.change( () => {
-					model.markers.set( 'marker', range );
+				model.change( writer => {
+					writer.setMarker( 'marker', range );
 				} );
 
 				expect( viewToString( viewRoot ) )
 					.to.equal( '<div><p>fo<span class="marker"></span>oba<span class="marker"></span>r</p></div>' );
 
-				model.change( () => {
-					model.markers.remove( 'marker' );
+				model.change( writer => {
+					writer.removeMarker( 'marker' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -493,16 +493,16 @@ describe( 'model-to-view-converters', () => {
 				dispatcher.on( 'addMarker:marker', insertUIElement( creator ) );
 				dispatcher.on( 'removeMarker:marker', removeUIElement( creator ) );
 
-				model.change( () => {
-					model.markers.set( 'marker', range );
+				model.change( writer => {
+					writer.setMarker( 'marker', range );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal(
 					'<div><p>fo<span class="marker" data-start="true"></span>oba<span class="marker" data-end="true"></span>r</p></div>'
 				);
 
-				model.change( () => {
-					model.markers.remove( 'marker' );
+				model.change( writer => {
+					writer.removeMarker( 'marker' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
@@ -726,8 +726,8 @@ describe( 'model-to-view-converters', () => {
 				dispatcher.on( 'addMarker:marker', highlightElement( highlightDescriptor ) );
 				dispatcher.on( 'removeMarker:marker', removeHighlight( highlightDescriptor ) );
 
-				model.change( () => {
-					model.markers.set( 'marker', markerRange );
+				model.change( writer => {
+					writer.setMarker( 'marker', markerRange );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal(
@@ -741,8 +741,8 @@ describe( 'model-to-view-converters', () => {
 					'</div>'
 				);
 
-				model.change( () => {
-					model.markers.remove( 'marker' );
+				model.change( writer => {
+					writer.removeMarker( 'marker' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
@@ -759,8 +759,8 @@ describe( 'model-to-view-converters', () => {
 				dispatcher.on( 'addMarker:marker', highlightElement( newDescriptor ), { priority: 'high' } );
 				dispatcher.on( 'removeMarker:marker', removeHighlight( newDescriptor ), { priority: 'high' } );
 
-				model.change( () => {
-					model.markers.set( 'marker', markerRange );
+				model.change( writer => {
+					writer.setMarker( 'marker', markerRange );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal(
@@ -774,8 +774,8 @@ describe( 'model-to-view-converters', () => {
 					'</div>'
 				);
 
-				model.change( () => {
-					model.markers.remove( 'marker' );
+				model.change( writer => {
+					writer.removeMarker( 'marker' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
@@ -786,14 +786,14 @@ describe( 'model-to-view-converters', () => {
 				dispatcher.on( 'addMarker:marker', highlightElement( () => null ), { priority: 'high' } );
 				dispatcher.on( 'removeMarker:marker', removeHighlight( () => null ), { priority: 'high' } );
 
-				model.change( () => {
-					model.markers.set( 'marker', markerRange );
+				model.change( writer => {
+					writer.setMarker( 'marker', markerRange );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
 
-				model.change( () => {
-					model.markers.remove( 'marker' );
+				model.change( writer => {
+					writer.removeMarker( 'marker' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
@@ -840,8 +840,8 @@ describe( 'model-to-view-converters', () => {
 			} );
 
 			it( 'should use addHighlight and removeHighlight on elements and not convert children nodes', () => {
-				model.change( () => {
-					model.markers.set( 'marker', markerRange );
+				model.change( writer => {
+					writer.setMarker( 'marker', markerRange );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal(
@@ -852,8 +852,8 @@ describe( 'model-to-view-converters', () => {
 					'</div>'
 				);
 
-				model.change( () => {
-					model.markers.remove( 'marker' );
+				model.change( writer => {
+					writer.removeMarker( 'marker' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div></div>' );
@@ -866,8 +866,8 @@ describe( 'model-to-view-converters', () => {
 				dispatcher.on( 'addMarker:marker', highlightElement( newDescriptor ), { priority: 'high' } );
 				dispatcher.on( 'removeMarker:marker', removeHighlight( newDescriptor ), { priority: 'high' } );
 
-				model.change( () => {
-					model.markers.set( 'marker', markerRange );
+				model.change( writer => {
+					writer.setMarker( 'marker', markerRange );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal(
@@ -878,8 +878,8 @@ describe( 'model-to-view-converters', () => {
 					'</div>'
 				);
 
-				model.change( () => {
-					model.markers.remove( 'marker' );
+				model.change( writer => {
+					writer.removeMarker( 'marker' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div></div>' );
@@ -901,8 +901,8 @@ describe( 'model-to-view-converters', () => {
 					expect( id ).to.equal( 'marker:foo-bar-baz' );
 				} );
 
-				model.change( () => {
-					model.markers.set( 'marker2', markerRange );
+				model.change( writer => {
+					writer.setMarker( 'marker2', markerRange );
 				} );
 			} );
 
@@ -911,14 +911,14 @@ describe( 'model-to-view-converters', () => {
 				dispatcher.on( 'addMarker:marker2', highlightElement( () => null ) );
 				dispatcher.on( 'removeMarker:marker2', removeHighlight( () => null ) );
 
-				model.change( () => {
-					model.markers.set( 'marker2', markerRange );
+				model.change( writer => {
+					writer.setMarker( 'marker2', markerRange );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div></div>' );
 
-				model.change( () => {
-					model.markers.remove( 'marker2' );
+				model.change( writer => {
+					writer.removeMarker( 'marker2' );
 				} );
 
 				expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div></div>' );

+ 7 - 7
packages/ckeditor5-engine/tests/conversion/modelconversiondispatcher.js

@@ -333,10 +333,9 @@ describe( 'ModelConversionDispatcher', () => {
 				writer.setSelection(
 					new ModelRange( new ModelPosition( root, [ 1 ] ), new ModelPosition( root, [ 1 ] ) )
 				);
+				writer.setMarker( 'name', ModelRange.createFromParentsAndOffsets( root, 0, root, 2 ) );
 			} );
 
-			model.markers.set( 'name', ModelRange.createFromParentsAndOffsets( root, 0, root, 2 ) );
-
 			sinon.spy( dispatcher, 'fire' );
 
 			const markers = Array.from( model.markers.getMarkersAtPosition( doc.selection.getFirstPosition() ) );
@@ -346,7 +345,9 @@ describe( 'ModelConversionDispatcher', () => {
 		} );
 
 		it( 'should not fire events for markers for non-collapsed selection', () => {
-			model.markers.set( 'name', ModelRange.createFromParentsAndOffsets( root, 0, root, 2 ) );
+			model.change( writer => {
+				writer.setMarker( 'name', ModelRange.createFromParentsAndOffsets( root, 0, root, 2 ) );
+			} );
 
 			sinon.spy( dispatcher, 'fire' );
 
@@ -384,8 +385,8 @@ describe( 'ModelConversionDispatcher', () => {
 				}
 			};
 
-			model.markers.set( 'name', ModelRange.createFromParentsAndOffsets( root, 0, root, 1 ) );
 			model.change( writer => {
+				writer.setMarker( 'name', ModelRange.createFromParentsAndOffsets( root, 0, root, 1 ) );
 				writer.setSelection( ModelRange.createFromParentsAndOffsets( caption, 1, caption, 1 ) );
 			} );
 			sinon.spy( dispatcher, 'fire' );
@@ -402,11 +403,10 @@ describe( 'ModelConversionDispatcher', () => {
 				writer.setSelection(
 					new ModelRange( new ModelPosition( root, [ 1 ] ), new ModelPosition( root, [ 1 ] ) )
 				);
+				writer.setMarker( 'foo', ModelRange.createFromParentsAndOffsets( root, 0, root, 2 ) );
+				writer.setMarker( 'bar', ModelRange.createFromParentsAndOffsets( root, 0, root, 2 ) );
 			} );
 
-			model.markers.set( 'foo', ModelRange.createFromParentsAndOffsets( root, 0, root, 2 ) );
-			model.markers.set( 'bar', ModelRange.createFromParentsAndOffsets( root, 0, root, 2 ) );
-
 			sinon.spy( dispatcher, 'fire' );
 
 			dispatcher.on( 'addMarker:foo', ( evt, data, consumable ) => {

+ 6 - 6
packages/ckeditor5-engine/tests/manual/highlight.js

@@ -103,9 +103,9 @@ ClassicEditor.create( global.document.querySelector( '#editor' ), {
 		document.getElementById( 'remove-markers' ).addEventListener( 'mousedown', evt => {
 			const markers = editor.model.markers;
 
-			editor.model.change( () => {
+			editor.model.change( writer => {
 				for ( const marker of markers ) {
-					markers.remove( marker );
+					writer.removeMarker( marker );
 				}
 			} );
 
@@ -117,14 +117,14 @@ ClassicEditor.create( global.document.querySelector( '#editor' ), {
 	} );
 
 function addMarker( editor, color ) {
-	editor.model.change( () => {
+	editor.model.change( writer => {
 		const range = ModelRange.createFromRange( editor.model.document.selection.getFirstRange() );
-		editor.model.markers.set( 'marker:' + color, range );
+		writer.setMarker( 'marker:' + color, range );
 	} );
 }
 
 function removeMarker( editor, color ) {
-	editor.model.change( () => {
-		editor.model.markers.remove( 'marker:' + color );
+	editor.model.change( writer => {
+		writer.removeMarker( 'marker:' + color );
 	} );
 }

+ 6 - 6
packages/ckeditor5-engine/tests/manual/markers.js

@@ -73,13 +73,13 @@ ClassicEditor
 			moveSelectionByOffset( 1 );
 		} );
 
-		model.change( () => {
+		model.change( writer => {
 			const root = model.document.getRoot();
 			const range = new Range( new Position( root, [ 0, 10 ] ), new Position( root, [ 0, 16 ] ) );
 			const name = 'highlight:yellow:' + uid();
 
 			markerNames.push( name );
-			model.markers.set( name, range );
+			writer.setMarker( name, range );
 		} );
 	} )
 	.catch( err => {
@@ -91,17 +91,17 @@ function uid() {
 }
 
 function addHighlight( color ) {
-	model.change( () => {
+	model.change( writer => {
 		const range = Range.createFromRange( model.document.selection.getFirstRange() );
 		const name = 'highlight:' + color + ':' + uid();
 
 		markerNames.push( name );
-		model.markers.set( name, range );
+		writer.setMarker( name, range );
 	} );
 }
 
 function removeHighlight() {
-	model.change( () => {
+	model.change( writer => {
 		const pos = model.document.selection.getFirstPosition();
 
 		for ( let i = 0; i < markerNames.length; i++ ) {
@@ -110,7 +110,7 @@ function removeHighlight() {
 			const range = marker.getRange();
 
 			if ( range.containsPosition( pos ) || range.start.isEqual( pos ) || range.end.isEqual( pos ) ) {
-				model.markers.remove( name );
+				writer.removeMarker( name );
 
 				markerNames.splice( i, 1 );
 				break;

+ 2 - 2
packages/ckeditor5-engine/tests/model/document.js

@@ -237,8 +237,8 @@ describe( 'Document', () => {
 		it( 'should buffer marker changes in differ', () => {
 			sinon.spy( doc.differ, 'bufferMarkerChange' );
 
-			model.change( () => {
-				model.markers.set( 'marker', Range.createCollapsedAt( doc.getRoot(), 0 ) );
+			model.change( writer => {
+				writer.setMarker( 'marker', Range.createCollapsedAt( doc.getRoot(), 0 ) );
 			} );
 
 			expect( doc.differ.bufferMarkerChange.called ).to.be.true;

+ 3 - 1
packages/ckeditor5-engine/tests/model/operation/markeroperation.js

@@ -86,7 +86,9 @@ describe( 'MarkerOperation', () => {
 	} );
 
 	it( 'should not fire document markers set event if newRange is same as current marker range', () => {
-		model.markers.set( 'name', range );
+		model.change( writer => {
+			writer.setMarker( 'name', range );
+		} );
 
 		sinon.spy( model.markers, 'fire' );
 

+ 19 - 15
packages/ckeditor5-engine/tests/model/writer.js

@@ -1965,25 +1965,25 @@ describe( 'Writer', () => {
 		} );
 
 		it( 'should add marker to the document marker collection', () => {
-			setMarker( 'name', range );
+			setMarker( 'name', range, { usingOperation: true } );
 
 			expect( model.markers.get( 'name' ).getRange().isEqual( range ) ).to.be.true;
 		} );
 
 		it( 'should update marker in the document marker collection', () => {
-			setMarker( 'name', range );
+			setMarker( 'name', range, { usingOperation: true } );
 
 			const range2 = Range.createFromParentsAndOffsets( root, 0, root, 0 );
-			setMarker( 'name', range2 );
+			setMarker( 'name', range2, { usingOperation: true } );
 
 			expect( model.markers.get( 'name' ).getRange().isEqual( range2 ) ).to.be.true;
 		} );
 
 		it( 'should accept marker instance', () => {
-			const marker = model.markers.set( 'name', range );
+			const marker = setMarker( 'name', range );
 			const range2 = Range.createFromParentsAndOffsets( root, 0, root, 0 );
 
-			setMarker( marker, range2 );
+			setMarker( marker, range2, { usingOperation: true } );
 			const op = batch.deltas[ 0 ].operations[ 0 ];
 
 			expect( model.markers.get( 'name' ).getRange().isEqual( range2 ) ).to.be.true;
@@ -1992,12 +1992,12 @@ describe( 'Writer', () => {
 		} );
 
 		it( 'should accept empty range parameter if marker instance is passed', () => {
-			const marker = model.markers.set( 'name', range );
+			const marker = setMarker( 'name', range );
 			const spy = sinon.spy();
 
 			model.on( 'applyOperation', spy );
 
-			setMarker( marker );
+			setMarker( marker, null, { usingOperation: true } );
 			const op = batch.deltas[ 0 ].operations[ 0 ];
 
 			expect( spy.calledOnce ).to.be.true;
@@ -2013,11 +2013,11 @@ describe( 'Writer', () => {
 		} );
 
 		it( 'should throw when trying to use detached writer', () => {
-			const marker = model.markers.set( 'name', range );
+			const marker = setMarker( 'name', range );
 			const writer = new Writer( model, batch );
 
 			expect( () => {
-				writer.setMarker( marker );
+				writer.setMarker( marker, null, { usingOperation: true } );
 			} ).to.throw( CKEditorError, /^writer-incorrect-use/ );
 		} );
 	} );
@@ -2033,7 +2033,7 @@ describe( 'Writer', () => {
 
 		it( 'should remove marker from the document marker collection', () => {
 			setMarker( 'name', range );
-			removeMarker( 'name' );
+			removeMarker( 'name', { usingOperation: true } );
 
 			expect( model.markers.get( 'name' ) ).to.be.null;
 		} );
@@ -2056,7 +2056,7 @@ describe( 'Writer', () => {
 			setMarker( 'name', range );
 			const marker = model.markers.get( 'name' );
 
-			removeMarker( marker );
+			removeMarker( marker, { usingOperation: true } );
 
 			expect( model.markers.get( 'name' ) ).to.be.null;
 		} );
@@ -2353,15 +2353,19 @@ describe( 'Writer', () => {
 		} );
 	}
 
-	function setMarker( markerOrName, newRange ) {
+	function setMarker( markerOrName, newRange, options ) {
+		let marker;
+
 		model.enqueueChange( batch, writer => {
-			writer.setMarker( markerOrName, newRange );
+			marker = writer.setMarker( markerOrName, newRange, options );
 		} );
+
+		return marker;
 	}
 
-	function removeMarker( markerOrName ) {
+	function removeMarker( markerOrName, options ) {
 		model.enqueueChange( batch, writer => {
-			writer.removeMarker( markerOrName );
+			writer.removeMarker( markerOrName, options );
 		} );
 	}