8
0
Просмотр исходного кода

Remove removeUIElement(), changeAttribute(), highlightText(), highlightElement() and removeHighlight() from API.

Maciej Gołaszewski 7 лет назад
Родитель
Сommit
82c8b9b7ce

+ 144 - 142
packages/ckeditor5-engine/src/conversion/downcasthelpers.js

@@ -345,50 +345,6 @@ export default class DowncastHelpers extends ConversionHelpers {
 	}
 }
 
-/**
- * Function factory that creates a converter which converts node insertion changes from the model to the view.
- * The function passed will be provided with all the parameters of the dispatcher's
- * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert `insert` event}.
- * It is expected that the function returns an {@link module:engine/view/element~Element}.
- * The result of the function will be inserted into the view.
- *
- * The converter automatically consumes the corresponding value from the consumables list, stops the event (see
- * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}) and binds the model and view elements.
- *
- *		downcastDispatcher.on(
- *			'insert:myElem',
- *			insertElement( ( modelItem, viewWriter ) => {
- *				const text = viewWriter.createText( 'myText' );
- *				const myElem = viewWriter.createElement( 'myElem', { myAttr: 'my-' + modelItem.getAttribute( 'myAttr' ) }, text );
- *
- *				// Do something fancy with `myElem` using `modelItem` or other parameters.
- *
- *				return myElem;
- *			}
- *		) );
- *
- * @param {Function} elementCreator Function returning a view element, which will be inserted.
- * @returns {Function} Insert element event converter.
- */
-export function insertElement( elementCreator ) {
-	return ( evt, data, conversionApi ) => {
-		const viewElement = elementCreator( data.item, conversionApi.writer );
-
-		if ( !viewElement ) {
-			return;
-		}
-
-		if ( !conversionApi.consumable.consume( data.item, 'insert' ) ) {
-			return;
-		}
-
-		const viewPosition = conversionApi.mapper.toViewPosition( data.range.start );
-
-		conversionApi.mapper.bindElements( data.item, viewElement );
-		conversionApi.writer.insert( viewPosition, viewElement );
-	};
-}
-
 /**
  * Function factory that creates a default downcast converter for text insertion changes.
  *
@@ -441,6 +397,145 @@ export function remove() {
 	};
 }
 
+/**
+ * Creates a `<span>` {@link module:engine/view/attributeelement~AttributeElement view attribute element} from the information
+ * provided by the {@link module:engine/conversion/downcasthelpers~HighlightDescriptor highlight descriptor} object. If a priority
+ * is not provided in the descriptor, the default priority will be used.
+ *
+ * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} descriptor
+ * @returns {module:engine/view/attributeelement~AttributeElement}
+ */
+export function createViewElementFromHighlightDescriptor( descriptor ) {
+	const viewElement = new ViewAttributeElement( 'span', descriptor.attributes );
+
+	if ( descriptor.classes ) {
+		viewElement._addClass( descriptor.classes );
+	}
+
+	if ( descriptor.priority ) {
+		viewElement._priority = descriptor.priority;
+	}
+
+	viewElement._id = descriptor.id;
+
+	return viewElement;
+}
+
+// only: insertText, insertElement, wrap, insertUIElement
+
+/**
+ * Function factory that creates a converter which converts set/change/remove attribute changes from the model to the view.
+ * It can also be used to convert selection attributes. In that case, an empty attribute element will be created and the
+ * selection will be put inside it.
+ *
+ * Attributes from the model are converted to a view element that will be wrapping these view nodes that are bound to
+ * model elements having the given attribute. This is useful for attributes like `bold` that may be set on text nodes in the model
+ * but are represented as an element in the view:
+ *
+ *		[paragraph]              MODEL ====> VIEW        <p>
+ *			|- a {bold: true}                             |- <b>
+ *			|- b {bold: true}                             |   |- ab
+ *			|- c                                          |- c
+ *
+ * Passed `Function` will be provided with the attribute value and then all the parameters of the
+ * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute `attribute` event}.
+ * It is expected that the function returns an {@link module:engine/view/element~Element}.
+ * The result of the function will be the wrapping element.
+ * When the provided `Function` does not return any element, no conversion will take place.
+ *
+ * The converter automatically consumes the corresponding value from the consumables list and stops the event (see
+ * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}).
+ *
+ *		modelDispatcher.on( 'attribute:bold', wrapItem( ( modelAttributeValue, viewWriter ) => {
+ *			return viewWriter.createAttributeElement( 'strong' );
+ *		} );
+ *
+ * @param {Function} elementCreator Function returning a view element that will be used for wrapping.
+ * @returns {Function} Set/change attribute converter.
+ */
+export function wrap( elementCreator ) {
+	return ( evt, data, conversionApi ) => {
+		// Recreate current wrapping node. It will be used to unwrap view range if the attribute value has changed
+		// or the attribute was removed.
+		const oldViewElement = elementCreator( data.attributeOldValue, conversionApi.writer );
+
+		// Create node to wrap with.
+		const newViewElement = elementCreator( data.attributeNewValue, conversionApi.writer );
+
+		if ( !oldViewElement && !newViewElement ) {
+			return;
+		}
+
+		if ( !conversionApi.consumable.consume( data.item, evt.name ) ) {
+			return;
+		}
+
+		const viewWriter = conversionApi.writer;
+		const viewSelection = viewWriter.document.selection;
+
+		if ( data.item instanceof ModelSelection || data.item instanceof DocumentSelection ) {
+			// Selection attribute conversion.
+			viewWriter.wrap( viewSelection.getFirstRange(), newViewElement );
+		} else {
+			// Node attribute conversion.
+			let viewRange = conversionApi.mapper.toViewRange( data.range );
+
+			// First, unwrap the range from current wrapper.
+			if ( data.attributeOldValue !== null && oldViewElement ) {
+				viewRange = viewWriter.unwrap( viewRange, oldViewElement );
+			}
+
+			if ( data.attributeNewValue !== null && newViewElement ) {
+				viewWriter.wrap( viewRange, newViewElement );
+			}
+		}
+	};
+}
+
+/**
+ * Function factory that creates a converter which converts node insertion changes from the model to the view.
+ * The function passed will be provided with all the parameters of the dispatcher's
+ * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert `insert` event}.
+ * It is expected that the function returns an {@link module:engine/view/element~Element}.
+ * The result of the function will be inserted into the view.
+ *
+ * The converter automatically consumes the corresponding value from the consumables list, stops the event (see
+ * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}) and binds the model and view elements.
+ *
+ *		downcastDispatcher.on(
+ *			'insert:myElem',
+ *			insertElement( ( modelItem, viewWriter ) => {
+ *				const text = viewWriter.createText( 'myText' );
+ *				const myElem = viewWriter.createElement( 'myElem', { myAttr: 'my-' + modelItem.getAttribute( 'myAttr' ) }, text );
+ *
+ *				// Do something fancy with `myElem` using `modelItem` or other parameters.
+ *
+ *				return myElem;
+ *			}
+ *		) );
+ *
+ * @param {Function} elementCreator Function returning a view element, which will be inserted.
+ * @returns {Function} Insert element event converter.
+ */
+export function insertElement( elementCreator ) {
+	return ( evt, data, conversionApi ) => {
+		const viewElement = elementCreator( data.item, conversionApi.writer );
+
+		if ( !viewElement ) {
+			return;
+		}
+
+		if ( !conversionApi.consumable.consume( data.item, 'insert' ) ) {
+			return;
+		}
+
+		const viewPosition = conversionApi.mapper.toViewPosition( data.range.start );
+
+		conversionApi.mapper.bindElements( data.item, viewElement );
+		conversionApi.writer.insert( viewPosition, viewElement );
+	};
+}
+
 /**
  * Function factory that creates a converter which converts marker adding change to the
  * {@link module:engine/view/uielement~UIElement view UI element}.
@@ -510,7 +605,7 @@ export function insertUIElement( elementCreator ) {
  *
  * @returns {Function} Removed UI element converter.
  */
-export function removeUIElement() {
+function removeUIElement() {
 	return ( evt, data, conversionApi ) => {
 		const elements = conversionApi.mapper.markerNameToElements( data.markerName );
 
@@ -561,7 +656,7 @@ export function removeUIElement() {
  * The function is passed the model attribute value as the first parameter and additional data about the change as the second parameter.
  * @returns {Function} Set/change attribute converter.
  */
-export function changeAttribute( attributeCreator ) {
+function changeAttribute( attributeCreator ) {
 	attributeCreator = attributeCreator || ( ( value, data ) => ( { value, key: data.attributeKey } ) );
 
 	return ( evt, data, conversionApi ) => {
@@ -662,75 +757,6 @@ export function changeAttribute( attributeCreator ) {
 	};
 }
 
-/**
- * Function factory that creates a converter which converts set/change/remove attribute changes from the model to the view.
- * It can also be used to convert selection attributes. In that case, an empty attribute element will be created and the
- * selection will be put inside it.
- *
- * Attributes from the model are converted to a view element that will be wrapping these view nodes that are bound to
- * model elements having the given attribute. This is useful for attributes like `bold` that may be set on text nodes in the model
- * but are represented as an element in the view:
- *
- *		[paragraph]              MODEL ====> VIEW        <p>
- *			|- a {bold: true}                             |- <b>
- *			|- b {bold: true}                             |   |- ab
- *			|- c                                          |- c
- *
- * Passed `Function` will be provided with the attribute value and then all the parameters of the
- * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute `attribute` event}.
- * It is expected that the function returns an {@link module:engine/view/element~Element}.
- * The result of the function will be the wrapping element.
- * When the provided `Function` does not return any element, no conversion will take place.
- *
- * The converter automatically consumes the corresponding value from the consumables list and stops the event (see
- * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}).
- *
- *		modelDispatcher.on( 'attribute:bold', wrapItem( ( modelAttributeValue, viewWriter ) => {
- *			return viewWriter.createAttributeElement( 'strong' );
- *		} );
- *
- * @param {Function} elementCreator Function returning a view element that will be used for wrapping.
- * @returns {Function} Set/change attribute converter.
- */
-export function wrap( elementCreator ) {
-	return ( evt, data, conversionApi ) => {
-		// Recreate current wrapping node. It will be used to unwrap view range if the attribute value has changed
-		// or the attribute was removed.
-		const oldViewElement = elementCreator( data.attributeOldValue, conversionApi.writer );
-
-		// Create node to wrap with.
-		const newViewElement = elementCreator( data.attributeNewValue, conversionApi.writer );
-
-		if ( !oldViewElement && !newViewElement ) {
-			return;
-		}
-
-		if ( !conversionApi.consumable.consume( data.item, evt.name ) ) {
-			return;
-		}
-
-		const viewWriter = conversionApi.writer;
-		const viewSelection = viewWriter.document.selection;
-
-		if ( data.item instanceof ModelSelection || data.item instanceof DocumentSelection ) {
-			// Selection attribute conversion.
-			viewWriter.wrap( viewSelection.getFirstRange(), newViewElement );
-		} else {
-			// Node attribute conversion.
-			let viewRange = conversionApi.mapper.toViewRange( data.range );
-
-			// First, unwrap the range from current wrapper.
-			if ( data.attributeOldValue !== null && oldViewElement ) {
-				viewRange = viewWriter.unwrap( viewRange, oldViewElement );
-			}
-
-			if ( data.attributeNewValue !== null && newViewElement ) {
-				viewWriter.wrap( viewRange, newViewElement );
-			}
-		}
-	};
-}
-
 /**
  * Function factory that creates a converter which converts the text inside marker's range. The converter wraps the text with
  * {@link module:engine/view/attributeelement~AttributeElement} created from the provided descriptor.
@@ -749,7 +775,7 @@ export function wrap( elementCreator ) {
  * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} highlightDescriptor
  * @returns {Function}
  */
-export function highlightText( highlightDescriptor ) {
+function highlightText( highlightDescriptor ) {
 	return ( evt, data, conversionApi ) => {
 		if ( data.markerRange.isCollapsed ) {
 			return;
@@ -812,7 +838,7 @@ export function highlightText( highlightDescriptor ) {
  * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} highlightDescriptor
  * @returns {Function}
  */
-export function highlightElement( highlightDescriptor ) {
+function highlightElement( highlightDescriptor ) {
 	return ( evt, data, conversionApi ) => {
 		if ( data.markerRange.isCollapsed ) {
 			return;
@@ -874,7 +900,7 @@ export function highlightElement( highlightDescriptor ) {
  * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} highlightDescriptor
  * @returns {Function}
  */
-export function removeHighlight( highlightDescriptor ) {
+function removeHighlight( highlightDescriptor ) {
 	return ( evt, data, conversionApi ) => {
 		// This conversion makes sense only for non-collapsed range.
 		if ( data.markerRange.isCollapsed ) {
@@ -914,30 +940,6 @@ export function removeHighlight( highlightDescriptor ) {
 	};
 }
 
-/**
- * Creates a `<span>` {@link module:engine/view/attributeelement~AttributeElement view attribute element} from the information
- * provided by the {@link module:engine/conversion/downcasthelpers~HighlightDescriptor highlight descriptor} object. If a priority
- * is not provided in the descriptor, the default priority will be used.
- *
- * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} descriptor
- * @returns {module:engine/view/attributeelement~AttributeElement}
- */
-export function createViewElementFromHighlightDescriptor( descriptor ) {
-	const viewElement = new ViewAttributeElement( 'span', descriptor.attributes );
-
-	if ( descriptor.classes ) {
-		viewElement._addClass( descriptor.classes );
-	}
-
-	if ( descriptor.priority ) {
-		viewElement._priority = descriptor.priority;
-	}
-
-	viewElement._id = descriptor.id;
-
-	return viewElement;
-}
-
 // Model element to view element conversion helper.
 //
 // See {@link ~DowncastHelpers#elementToElement `.elementToElement()` downcast helper} for examples.

+ 13 - 15
packages/ckeditor5-engine/tests/conversion/downcast-selection-converters.js

@@ -16,13 +16,10 @@ import {
 	clearAttributes,
 } from '../../src/conversion/downcast-selection-converters';
 
-import {
+import DowncastHelpers, {
 	insertElement,
 	insertText,
-	wrap,
-	highlightElement,
-	highlightText,
-	removeHighlight
+	wrap
 } from '../../src/conversion/downcasthelpers';
 
 import createViewRoot from '../view/_utils/createroot';
@@ -30,7 +27,7 @@ import { stringify as stringifyView } from '../../src/dev-utils/view';
 import { setData as setModelData } from '../../src/dev-utils/model';
 
 describe( 'downcast-selection-converters', () => {
-	let dispatcher, mapper, model, view, modelDoc, modelRoot, docSelection, viewDoc, viewRoot, viewSelection, highlightDescriptor;
+	let dispatcher, mapper, model, view, modelDoc, modelRoot, docSelection, viewDoc, viewRoot, viewSelection, downcastHelpers;
 
 	beforeEach( () => {
 		model = new Model();
@@ -48,8 +45,6 @@ describe( 'downcast-selection-converters', () => {
 		mapper = new Mapper();
 		mapper.bindElements( modelRoot, viewRoot );
 
-		highlightDescriptor = { classes: 'marker', priority: 1 };
-
 		dispatcher = new DowncastDispatcher( { mapper, viewSelection } );
 
 		dispatcher.on( 'insert:$text', insertText() );
@@ -57,9 +52,8 @@ describe( 'downcast-selection-converters', () => {
 		const strongCreator = ( modelAttributeValue, viewWriter ) => viewWriter.createAttributeElement( 'strong' );
 		dispatcher.on( 'attribute:bold', wrap( strongCreator ) );
 
-		dispatcher.on( 'addMarker:marker', highlightText( highlightDescriptor ) );
-		dispatcher.on( 'addMarker:marker', highlightElement( highlightDescriptor ) );
-		dispatcher.on( 'removeMarker:marker', removeHighlight( highlightDescriptor ) );
+		downcastHelpers = new DowncastHelpers( dispatcher );
+		downcastHelpers.markerToHighlight( { model: 'marker', view: { classes: 'marker' }, converterPriority: 1 } );
 
 		// Default selection converters.
 		dispatcher.on( 'selection', clearAttributes(), { priority: 'low' } );
@@ -241,9 +235,10 @@ describe( 'downcast-selection-converters', () => {
 			} );
 
 			it( 'in marker - using highlight descriptor creator', () => {
-				dispatcher.on( 'addMarker:marker2', highlightText(
-					data => ( { classes: data.markerName } )
-				) );
+				downcastHelpers.markerToHighlight( {
+					model: 'marker2',
+					view: data => ( { classes: data.markerName } )
+				} );
 
 				setModelData( model, 'foobar' );
 
@@ -269,7 +264,10 @@ describe( 'downcast-selection-converters', () => {
 			} );
 
 			it( 'should do nothing if creator return null', () => {
-				dispatcher.on( 'addMarker:marker3', highlightText( () => null ) );
+				downcastHelpers.markerToHighlight( {
+					model: 'marker3',
+					view: () => null
+				} );
 
 				setModelData( model, 'foobar' );
 

+ 640 - 641
packages/ckeditor5-engine/tests/conversion/downcasthelpers.js

@@ -21,8 +21,7 @@ import log from '@ckeditor/ckeditor5-utils/src/log';
 import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
 
 import DowncastHelpers, {
-	insertElement, insertUIElement, changeAttribute, wrap, removeUIElement,
-	highlightElement, highlightText, removeHighlight, createViewElementFromHighlightDescriptor
+	insertElement, wrap, createViewElementFromHighlightDescriptor
 } from '../../src/conversion/downcasthelpers';
 
 import { stringify } from '../../src/dev-utils/view';
@@ -644,7 +643,7 @@ describe( 'downcast-converters', () => {
 			)
 		);
 
-		dispatcher.on( 'attribute:class', changeAttribute() );
+		// dispatcher.on( 'attribute:class', changeAttribute() );
 
 		modelRootStart = model.createPositionAt( modelRoot, 0 );
 	} );
@@ -735,95 +734,95 @@ describe( 'downcast-converters', () => {
 			expect( viewToString( viewRoot ) ).to.equal( '<div></div>' );
 		} );
 	} );
-
-	describe( 'changeAttribute', () => {
-		it( 'should convert attribute insert/change/remove on a model node', () => {
-			const modelElement = new ModelElement( 'paragraph', { class: 'foo' }, new ModelText( 'foobar' ) );
-
-			model.change( writer => {
-				writer.insert( modelElement, modelRootStart );
-			} );
-
-			expect( viewToString( viewRoot ) ).to.equal( '<div><p class="foo">foobar</p></div>' );
-
-			model.change( writer => {
-				writer.setAttribute( 'class', 'bar', modelElement );
-			} );
-
-			expect( viewToString( viewRoot ) ).to.equal( '<div><p class="bar">foobar</p></div>' );
-
-			model.change( writer => {
-				writer.removeAttribute( 'class', modelElement );
-			} );
-
-			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
-		} );
-
-		it( 'should convert insert/change/remove with attribute generating function as a parameter', () => {
-			const themeConverter = ( value, data ) => {
-				if ( data.item instanceof ModelElement && data.item.childCount > 0 ) {
-					value += ' fix-content';
-				}
-
-				return { key: 'class', value };
-			};
-
-			dispatcher.on( 'insert:div', insertElement( ( modelElement, viewWriter ) => viewWriter.createContainerElement( 'div' ) ) );
-			dispatcher.on( 'attribute:theme', changeAttribute( themeConverter ) );
-
-			const modelParagraph = new ModelElement( 'paragraph', { theme: 'nice' }, new ModelText( 'foobar' ) );
-			const modelDiv = new ModelElement( 'div', { theme: 'nice' } );
-
-			model.change( writer => {
-				writer.insert( [ modelParagraph, modelDiv ], modelRootStart );
-			} );
-
-			expect( viewToString( viewRoot ) ).to.equal( '<div><p class="nice fix-content">foobar</p><div class="nice"></div></div>' );
-
-			model.change( writer => {
-				writer.setAttribute( 'theme', 'awesome', modelParagraph );
-			} );
-
-			expect( viewToString( viewRoot ) ).to.equal( '<div><p class="awesome fix-content">foobar</p><div class="nice"></div></div>' );
-
-			model.change( writer => {
-				writer.removeAttribute( 'theme', modelParagraph );
-			} );
-
-			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p><div class="nice"></div></div>' );
-		} );
-
-		it( 'should be possible to override setAttribute', () => {
-			const modelElement = new ModelElement( 'paragraph', { classes: 'foo' }, new ModelText( 'foobar' ) );
-
-			dispatcher.on( 'attribute:class', ( evt, data, conversionApi ) => {
-				conversionApi.consumable.consume( data.item, 'attribute:class' );
-			}, { converterPriority: 'high' } );
-
-			model.change( writer => {
-				writer.insert( modelElement, modelRootStart );
-			} );
-
-			// No attribute set.
-			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
-		} );
-
-		it( 'should not convert or consume if element creator returned null', () => {
-			const callback = sinon.stub().returns( null );
-
-			dispatcher.on( 'attribute:class', changeAttribute( callback ) );
-
-			const modelElement = new ModelElement( 'paragraph', { class: 'foo' }, new ModelText( 'foobar' ) );
-
-			model.change( writer => {
-				writer.insert( modelElement, modelRootStart );
-			} );
-
-			expect( viewToString( viewRoot ) ).to.equal( '<div><p class="foo">foobar</p></div>' );
-
-			sinon.assert.called( callback );
-		} );
-	} );
+	//
+	// describe( 'changeAttribute', () => {
+	// 	it( 'should convert attribute insert/change/remove on a model node', () => {
+	// 		const modelElement = new ModelElement( 'paragraph', { class: 'foo' }, new ModelText( 'foobar' ) );
+	//
+	// 		model.change( writer => {
+	// 			writer.insert( modelElement, modelRootStart );
+	// 		} );
+	//
+	// 		expect( viewToString( viewRoot ) ).to.equal( '<div><p class="foo">foobar</p></div>' );
+	//
+	// 		model.change( writer => {
+	// 			writer.setAttribute( 'class', 'bar', modelElement );
+	// 		} );
+	//
+	// 		expect( viewToString( viewRoot ) ).to.equal( '<div><p class="bar">foobar</p></div>' );
+	//
+	// 		model.change( writer => {
+	// 			writer.removeAttribute( 'class', modelElement );
+	// 		} );
+	//
+	// 		expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+	// 	} );
+	//
+	// 	it( 'should convert insert/change/remove with attribute generating function as a parameter', () => {
+	// 		const themeConverter = ( value, data ) => {
+	// 			if ( data.item instanceof ModelElement && data.item.childCount > 0 ) {
+	// 				value += ' fix-content';
+	// 			}
+	//
+	// 			return { key: 'class', value };
+	// 		};
+	//
+	// 		dispatcher.on( 'insert:div', insertElement( ( modelElement, viewWriter ) => viewWriter.createContainerElement( 'div' ) ) );
+	// 		dispatcher.on( 'attribute:theme', changeAttribute( themeConverter ) );
+	//
+	// 		const modelParagraph = new ModelElement( 'paragraph', { theme: 'nice' }, new ModelText( 'foobar' ) );
+	// 		const modelDiv = new ModelElement( 'div', { theme: 'nice' } );
+	//
+	// 		model.change( writer => {
+	// 			writer.insert( [ modelParagraph, modelDiv ], modelRootStart );
+	// 		} );
+	//
+	// 		expect( viewToString( viewRoot ) ).to.equal( '<div><p class="nice fix-content">foobar</p><div class="nice"></div></div>' );
+	//
+	// 		model.change( writer => {
+	// 			writer.setAttribute( 'theme', 'awesome', modelParagraph );
+	// 		} );
+	//
+	// 		expect( viewToString( viewRoot ) ).to.equal( '<div><p class="awesome fix-content">foobar</p><div class="nice"></div></div>' );
+	//
+	// 		model.change( writer => {
+	// 			writer.removeAttribute( 'theme', modelParagraph );
+	// 		} );
+	//
+	// 		expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p><div class="nice"></div></div>' );
+	// 	} );
+	//
+	// 	it( 'should be possible to override setAttribute', () => {
+	// 		const modelElement = new ModelElement( 'paragraph', { classes: 'foo' }, new ModelText( 'foobar' ) );
+	//
+	// 		dispatcher.on( 'attribute:class', ( evt, data, conversionApi ) => {
+	// 			conversionApi.consumable.consume( data.item, 'attribute:class' );
+	// 		}, { converterPriority: 'high' } );
+	//
+	// 		model.change( writer => {
+	// 			writer.insert( modelElement, modelRootStart );
+	// 		} );
+	//
+	// 		// No attribute set.
+	// 		expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+	// 	} );
+	//
+	// 	it( 'should not convert or consume if element creator returned null', () => {
+	// 		const callback = sinon.stub().returns( null );
+	//
+	// 		dispatcher.on( 'attribute:class', changeAttribute( callback ) );
+	//
+	// 		const modelElement = new ModelElement( 'paragraph', { class: 'foo' }, new ModelText( 'foobar' ) );
+	//
+	// 		model.change( writer => {
+	// 			writer.insert( modelElement, modelRootStart );
+	// 		} );
+	//
+	// 		expect( viewToString( viewRoot ) ).to.equal( '<div><p class="foo">foobar</p></div>' );
+	//
+	// 		sinon.assert.called( callback );
+	// 	} );
+	// } );
 
 	describe( 'wrap', () => {
 		it( 'should convert insert/change/remove of attribute in model into wrapping element in a view', () => {
@@ -955,170 +954,170 @@ describe( 'downcast-converters', () => {
 		} );
 	} );
 
-	describe( 'insertUIElement/removeUIElement', () => {
-		let modelText, modelElement, range;
-
-		beforeEach( () => {
-			modelText = new ModelText( 'foobar' );
-			modelElement = new ModelElement( 'paragraph', null, modelText );
-
-			model.change( writer => {
-				writer.insert( modelElement, modelRootStart );
-			} );
-		} );
-
-		describe( 'collapsed range', () => {
-			beforeEach( () => {
-				range = model.createRange( model.createPositionAt( modelElement, 3 ), model.createPositionAt( modelElement, 3 ) );
-			} );
-
-			it( 'should insert and remove ui element', () => {
-				const creator = ( data, viewWriter ) => viewWriter.createUIElement( 'span', { 'class': 'marker' } );
-
-				dispatcher.on( 'addMarker:marker', insertUIElement( creator ) );
-				dispatcher.on( 'removeMarker:marker', removeUIElement( creator ) );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo<span class="marker"></span>bar</p></div>' );
-
-				model.change( writer => {
-					writer.removeMarker( 'marker' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
-			} );
-
-			it( 'should not convert if consumable was consumed', () => {
-				sinon.spy( dispatcher, 'fire' );
-
-				dispatcher.on( 'addMarker:marker', insertUIElement(
-					( data, viewWriter ) => viewWriter.createUIElement( 'span', { 'class': 'marker' } ) )
-				);
-
-				dispatcher.on( 'addMarker:marker', ( evt, data, conversionApi ) => {
-					conversionApi.consumable.consume( data.markerRange, 'addMarker:marker' );
-				}, { priority: 'high' } );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
-				expect( dispatcher.fire.calledWith( 'addMarker:marker' ) );
-			} );
-
-			it( 'should not convert if creator returned null', () => {
-				dispatcher.on( 'addMarker:marker', insertUIElement( () => null ) );
-				dispatcher.on( 'removeMarker:marker', removeUIElement( () => null ) );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
-
-				model.change( writer => {
-					writer.removeMarker( 'marker' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
-			} );
-		} );
-
-		describe( 'non-collapsed range', () => {
-			beforeEach( () => {
-				range = model.createRange( model.createPositionAt( modelElement, 2 ), model.createPositionAt( modelElement, 5 ) );
-			} );
-
-			it( 'should insert and remove ui element - element as a creator', () => {
-				const creator = ( data, viewWriter ) => viewWriter.createUIElement( 'span', { 'class': 'marker' } );
-
-				dispatcher.on( 'addMarker:marker', insertUIElement( creator ) );
-				dispatcher.on( 'removeMarker:marker', removeUIElement( creator ) );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) )
-					.to.equal( '<div><p>fo<span class="marker"></span>oba<span class="marker"></span>r</p></div>' );
-
-				model.change( writer => {
-					writer.removeMarker( 'marker' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
-			} );
-
-			it( 'should insert and remove ui element - function as a creator', () => {
-				const creator = ( data, viewWriter ) => viewWriter.createUIElement( 'span', { 'class': data.markerName } );
-
-				dispatcher.on( 'addMarker:marker', insertUIElement( creator ) );
-				dispatcher.on( 'removeMarker:marker', removeUIElement( creator ) );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) )
-					.to.equal( '<div><p>fo<span class="marker"></span>oba<span class="marker"></span>r</p></div>' );
-
-				model.change( writer => {
-					writer.removeMarker( 'marker' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
-			} );
-
-			it( 'should insert and remove different opening and ending element', () => {
-				function creator( data, viewWriter ) {
-					if ( data.isOpening ) {
-						return viewWriter.createUIElement( 'span', { 'class': data.markerName, 'data-start': true } );
-					}
-
-					return viewWriter.createUIElement( 'span', { 'class': data.markerName, 'data-end': true } );
-				}
-
-				dispatcher.on( 'addMarker:marker', insertUIElement( creator ) );
-				dispatcher.on( 'removeMarker:marker', removeUIElement( creator ) );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range, usingOperation: false } );
-				} );
-
-				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( writer => {
-					writer.removeMarker( 'marker' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
-			} );
-
-			it( 'should not convert if consumable was consumed', () => {
-				const creator = ( data, viewWriter ) => viewWriter.createUIElement( 'span', { 'class': 'marker' } );
-
-				sinon.spy( dispatcher, 'fire' );
-
-				dispatcher.on( 'addMarker:marker', insertUIElement( creator ) );
-				dispatcher.on( 'addMarker:marker', ( evt, data, conversionApi ) => {
-					conversionApi.consumable.consume( data.item, 'addMarker:marker' );
-				}, { priority: 'high' } );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
-				expect( dispatcher.fire.calledWith( 'addMarker:marker' ) );
-			} );
-		} );
-	} );
+	// describe( 'insertUIElement/removeUIElement', () => {
+	// 	let modelText, modelElement, range;
+	//
+	// 	beforeEach( () => {
+	// 		modelText = new ModelText( 'foobar' );
+	// 		modelElement = new ModelElement( 'paragraph', null, modelText );
+	//
+	// 		model.change( writer => {
+	// 			writer.insert( modelElement, modelRootStart );
+	// 		} );
+	// 	} );
+	//
+	// 	describe( 'collapsed range', () => {
+	// 		beforeEach( () => {
+	// 			range = model.createRange( model.createPositionAt( modelElement, 3 ), model.createPositionAt( modelElement, 3 ) );
+	// 		} );
+	//
+	// 		it( 'should insert and remove ui element', () => {
+	// 			const creator = ( data, viewWriter ) => viewWriter.createUIElement( 'span', { 'class': 'marker' } );
+	//
+	// 			dispatcher.on( 'addMarker:marker', insertUIElement( creator ) );
+	// 			dispatcher.on( 'removeMarker:marker', removeUIElement( creator ) );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo<span class="marker"></span>bar</p></div>' );
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'marker' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+	// 		} );
+	//
+	// 		it( 'should not convert if consumable was consumed', () => {
+	// 			sinon.spy( dispatcher, 'fire' );
+	//
+	// 			dispatcher.on( 'addMarker:marker', insertUIElement(
+	// 				( data, viewWriter ) => viewWriter.createUIElement( 'span', { 'class': 'marker' } ) )
+	// 			);
+	//
+	// 			dispatcher.on( 'addMarker:marker', ( evt, data, conversionApi ) => {
+	// 				conversionApi.consumable.consume( data.markerRange, 'addMarker:marker' );
+	// 			}, { priority: 'high' } );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+	// 			expect( dispatcher.fire.calledWith( 'addMarker:marker' ) );
+	// 		} );
+	//
+	// 		it( 'should not convert if creator returned null', () => {
+	// 			dispatcher.on( 'addMarker:marker', insertUIElement( () => null ) );
+	// 			dispatcher.on( 'removeMarker:marker', removeUIElement( () => null ) );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'marker' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+	// 		} );
+	// 	} );
+	//
+	// 	describe( 'non-collapsed range', () => {
+	// 		beforeEach( () => {
+	// 			range = model.createRange( model.createPositionAt( modelElement, 2 ), model.createPositionAt( modelElement, 5 ) );
+	// 		} );
+	//
+	// 		it( 'should insert and remove ui element - element as a creator', () => {
+	// 			const creator = ( data, viewWriter ) => viewWriter.createUIElement( 'span', { 'class': 'marker' } );
+	//
+	// 			dispatcher.on( 'addMarker:marker', insertUIElement( creator ) );
+	// 			dispatcher.on( 'removeMarker:marker', removeUIElement( creator ) );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) )
+	// 				.to.equal( '<div><p>fo<span class="marker"></span>oba<span class="marker"></span>r</p></div>' );
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'marker' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+	// 		} );
+	//
+	// 		it( 'should insert and remove ui element - function as a creator', () => {
+	// 			const creator = ( data, viewWriter ) => viewWriter.createUIElement( 'span', { 'class': data.markerName } );
+	//
+	// 			dispatcher.on( 'addMarker:marker', insertUIElement( creator ) );
+	// 			dispatcher.on( 'removeMarker:marker', removeUIElement( creator ) );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) )
+	// 				.to.equal( '<div><p>fo<span class="marker"></span>oba<span class="marker"></span>r</p></div>' );
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'marker' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+	// 		} );
+	//
+	// 		it( 'should insert and remove different opening and ending element', () => {
+	// 			function creator( data, viewWriter ) {
+	// 				if ( data.isOpening ) {
+	// 					return viewWriter.createUIElement( 'span', { 'class': data.markerName, 'data-start': true } );
+	// 				}
+	//
+	// 				return viewWriter.createUIElement( 'span', { 'class': data.markerName, 'data-end': true } );
+	// 			}
+	//
+	// 			dispatcher.on( 'addMarker:marker', insertUIElement( creator ) );
+	// 			dispatcher.on( 'removeMarker:marker', removeUIElement( creator ) );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range, usingOperation: false } );
+	// 			} );
+	//
+	// 			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( writer => {
+	// 				writer.removeMarker( 'marker' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+	// 		} );
+	//
+	// 		it( 'should not convert if consumable was consumed', () => {
+	// 			const creator = ( data, viewWriter ) => viewWriter.createUIElement( 'span', { 'class': 'marker' } );
+	//
+	// 			sinon.spy( dispatcher, 'fire' );
+	//
+	// 			dispatcher.on( 'addMarker:marker', insertUIElement( creator ) );
+	// 			dispatcher.on( 'addMarker:marker', ( evt, data, conversionApi ) => {
+	// 				conversionApi.consumable.consume( data.item, 'addMarker:marker' );
+	// 			}, { priority: 'high' } );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+	// 			expect( dispatcher.fire.calledWith( 'addMarker:marker' ) );
+	// 		} );
+	// 	} );
+	// } );
 
 	// Remove converter is by default already added in `EditingController` instance.
 	describe( 'remove', () => {
@@ -1308,391 +1307,391 @@ describe( 'downcast-converters', () => {
 		} );
 	} );
 
-	describe( 'highlight', () => {
-		describe( 'on text', () => {
-			const highlightDescriptor = {
-				classes: 'highlight-class',
-				priority: 7,
-				attributes: { title: 'title' }
-			};
-
-			let markerRange;
-
-			beforeEach( () => {
-				const modelElement1 = new ModelElement( 'paragraph', null, new ModelText( 'foo' ) );
-				const modelElement2 = new ModelElement( 'paragraph', null, new ModelText( 'bar' ) );
-
-				model.change( writer => {
-					writer.insert( [ modelElement1, modelElement2 ], modelRootStart );
-				} );
-
-				markerRange = model.createRangeIn( modelRoot );
-			} );
-
-			it( 'should wrap and unwrap text nodes', () => {
-				dispatcher.on( 'addMarker:marker', highlightText( highlightDescriptor ) );
-				dispatcher.on( 'addMarker:marker', highlightElement( highlightDescriptor ) );
-				dispatcher.on( 'removeMarker:marker', removeHighlight( highlightDescriptor ) );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal(
-					'<div>' +
-					'<p>' +
-					'<span class="highlight-class" title="title">foo</span>' +
-					'</p>' +
-					'<p>' +
-					'<span class="highlight-class" title="title">bar</span>' +
-					'</p>' +
-					'</div>'
-				);
-
-				model.change( writer => {
-					writer.removeMarker( 'marker' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
-			} );
-
-			it( 'should be possible to overwrite', () => {
-				dispatcher.on( 'addMarker:marker', highlightText( highlightDescriptor ) );
-				dispatcher.on( 'addMarker:marker', highlightElement( highlightDescriptor ) );
-				dispatcher.on( 'removeMarker:marker', removeHighlight( highlightDescriptor ) );
-
-				const newDescriptor = { classes: 'override-class' };
-
-				dispatcher.on( 'addMarker:marker', highlightText( newDescriptor ), { priority: 'high' } );
-				dispatcher.on( 'addMarker:marker', highlightElement( newDescriptor ), { priority: 'high' } );
-				dispatcher.on( 'removeMarker:marker', removeHighlight( newDescriptor ), { priority: 'high' } );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal(
-					'<div>' +
-					'<p>' +
-					'<span class="override-class">foo</span>' +
-					'</p>' +
-					'<p>' +
-					'<span class="override-class">bar</span>' +
-					'</p>' +
-					'</div>'
-				);
-
-				model.change( writer => {
-					writer.removeMarker( 'marker' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
-			} );
-
-			it( 'should do nothing if descriptor is not provided or generating function returns null', () => {
-				dispatcher.on( 'addMarker:marker', highlightText( () => null ), { priority: 'high' } );
-				dispatcher.on( 'addMarker:marker', highlightElement( () => null ), { priority: 'high' } );
-				dispatcher.on( 'removeMarker:marker', removeHighlight( () => null ), { priority: 'high' } );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
-
-				model.change( writer => {
-					writer.removeMarker( 'marker' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
-			} );
-
-			it( 'should do nothing if collapsed marker is converted', () => {
-				const descriptor = { classes: 'foo' };
-
-				dispatcher.on( 'addMarker:marker', highlightText( descriptor ), { priority: 'high' } );
-				dispatcher.on( 'addMarker:marker', highlightElement( descriptor ), { priority: 'high' } );
-				dispatcher.on( 'removeMarker:marker', removeHighlight( descriptor ), { priority: 'high' } );
-
-				markerRange = model.createRange( model.createPositionAt( modelRoot, 0 ), model.createPositionAt( modelRoot, 0 ) );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
-
-				model.change( () => {
-					model.markers._remove( 'marker' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
-			} );
-
-			it( 'should correctly wrap and unwrap multiple, intersecting markers', () => {
-				const descriptorFoo = { classes: 'foo' };
-				const descriptorBar = { classes: 'bar' };
-				const descriptorXyz = { classes: 'xyz' };
-
-				dispatcher.on( 'addMarker:markerFoo', highlightText( descriptorFoo ) );
-				dispatcher.on( 'addMarker:markerBar', highlightText( descriptorBar ) );
-				dispatcher.on( 'addMarker:markerXyz', highlightText( descriptorXyz ) );
-
-				dispatcher.on( 'removeMarker:markerFoo', removeHighlight( descriptorFoo ) );
-				dispatcher.on( 'removeMarker:markerBar', removeHighlight( descriptorBar ) );
-				dispatcher.on( 'removeMarker:markerXyz', removeHighlight( descriptorXyz ) );
-
-				const p1 = modelRoot.getChild( 0 );
-				const p2 = modelRoot.getChild( 1 );
-
-				model.change( writer => {
-					const range = writer.createRange( writer.createPositionAt( p1, 0 ), writer.createPositionAt( p1, 3 ) );
-					writer.addMarker( 'markerFoo', { range, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal(
-					'<div>' +
-					'<p>' +
-					'<span class="foo">foo</span>' +
-					'</p>' +
-					'<p>bar</p>' +
-					'</div>'
-				);
-
-				model.change( writer => {
-					const range = writer.createRange( writer.createPositionAt( p1, 1 ), writer.createPositionAt( p2, 2 ) );
-					writer.addMarker( 'markerBar', { range, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal(
-					'<div>' +
-					'<p>' +
-					'<span class="foo">f</span>' +
-					'<span class="bar">' +
-					'<span class="foo">oo</span>' +
-					'</span>' +
-					'</p>' +
-					'<p>' +
-					'<span class="bar">ba</span>' +
-					'r' +
-					'</p>' +
-					'</div>'
-				);
-
-				model.change( writer => {
-					const range = writer.createRange( writer.createPositionAt( p1, 2 ), writer.createPositionAt( p2, 3 ) );
-					writer.addMarker( 'markerXyz', { range, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal(
-					'<div>' +
-					'<p>' +
-					'<span class="foo">f</span>' +
-					'<span class="bar">' +
-					'<span class="foo">' +
-					'o' +
-					'<span class="xyz">o</span>' +
-					'</span>' +
-					'</span>' +
-					'</p>' +
-					'<p>' +
-					'<span class="bar">' +
-					'<span class="xyz">ba</span>' +
-					'</span>' +
-					'<span class="xyz">r</span>' +
-					'</p>' +
-					'</div>'
-				);
-
-				model.change( writer => {
-					writer.removeMarker( 'markerBar' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal(
-					'<div>' +
-					'<p>' +
-					'<span class="foo">' +
-					'fo' +
-					'<span class="xyz">o</span>' +
-					'</span>' +
-					'</p>' +
-					'<p>' +
-					'<span class="xyz">bar</span>' +
-					'</p>' +
-					'</div>'
-				);
-
-				model.change( writer => {
-					writer.removeMarker( 'markerFoo' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal(
-					'<div>' +
-					'<p>' +
-					'fo' +
-					'<span class="xyz">o</span>' +
-					'</p>' +
-					'<p>' +
-					'<span class="xyz">bar</span>' +
-					'</p>' +
-					'</div>'
-				);
-
-				model.change( writer => {
-					writer.removeMarker( 'markerXyz' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
-			} );
-
-			it( 'should do nothing if marker is applied and removed on empty-ish range', () => {
-				dispatcher.on( 'addMarker:marker', highlightText( highlightDescriptor ) );
-				dispatcher.on( 'removeMarker:marker', removeHighlight( highlightDescriptor ) );
-
-				const p1 = modelRoot.getChild( 0 );
-				const p2 = modelRoot.getChild( 1 );
-
-				const markerRange = model.createRange( model.createPositionAt( p1, 3 ), model.createPositionAt( p2, 0 ) );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
-
-				model.change( writer => {
-					writer.removeMarker( 'marker', { range: markerRange, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
-			} );
-		} );
-
-		describe( 'on element', () => {
-			const highlightDescriptor = {
-				classes: 'highlight-class',
-				priority: 7,
-				attributes: { title: 'title' },
-				id: 'customId'
-			};
-
-			let markerRange;
-
-			beforeEach( () => {
-				// Provide converter for div element. View div element will have custom highlight handling.
-				dispatcher.on( 'insert:div', insertElement( () => {
-					const viewContainer = new ViewContainerElement( 'div' );
-
-					viewContainer._setCustomProperty( 'addHighlight', ( element, descriptor, writer ) => {
-						writer.addClass( descriptor.classes, element );
-					} );
-
-					viewContainer._setCustomProperty( 'removeHighlight', ( element, id, writer ) => {
-						writer.setAttribute( 'class', '', element );
-					} );
-
-					return viewContainer;
-				} ) );
-
-				const modelElement = new ModelElement( 'div', null, new ModelText( 'foo' ) );
-
-				model.change( writer => {
-					writer.insert( modelElement, modelRootStart );
-				} );
-
-				markerRange = model.createRangeOn( modelElement );
-
-				dispatcher.on( 'addMarker:marker', highlightText( highlightDescriptor ) );
-				dispatcher.on( 'addMarker:marker', highlightElement( highlightDescriptor ) );
-				dispatcher.on( 'removeMarker:marker', removeHighlight( highlightDescriptor ) );
-			} );
-
-			it( 'should use addHighlight and removeHighlight on elements and not convert children nodes', () => {
-				model.change( writer => {
-					writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal(
-					'<div>' +
-					'<div class="highlight-class">' +
-					'foo' +
-					'</div>' +
-					'</div>'
-				);
-
-				model.change( writer => {
-					writer.removeMarker( 'marker' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div></div>' );
-			} );
-
-			it( 'should be possible to override', () => {
-				const newDescriptor = { classes: 'override-class' };
-
-				dispatcher.on( 'addMarker:marker', highlightText( newDescriptor ), { priority: 'high' } );
-				dispatcher.on( 'addMarker:marker', highlightElement( newDescriptor ), { priority: 'high' } );
-				dispatcher.on( 'removeMarker:marker', removeHighlight( newDescriptor ), { priority: 'high' } );
-
-				model.change( writer => {
-					writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal(
-					'<div>' +
-					'<div class="override-class">' +
-					'foo' +
-					'</div>' +
-					'</div>'
-				);
-
-				model.change( writer => {
-					writer.removeMarker( 'marker' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div></div>' );
-			} );
-
-			it( 'should use default priority and id if not provided', () => {
-				const viewDiv = viewRoot.getChild( 0 );
-
-				dispatcher.on( 'addMarker:marker2', highlightText( () => null ) );
-				dispatcher.on( 'addMarker:marker2', highlightElement( () => null ) );
-				dispatcher.on( 'removeMarker:marker2', removeHighlight( () => null ) );
-
-				viewDiv._setCustomProperty( 'addHighlight', ( element, descriptor ) => {
-					expect( descriptor.priority ).to.equal( ViewAttributeElement.DEFAULT_PRIORITY );
-					expect( descriptor.id ).to.equal( 'marker:foo-bar-baz' );
-				} );
-
-				viewDiv._setCustomProperty( 'removeHighlight', ( element, id ) => {
-					expect( id ).to.equal( 'marker:foo-bar-baz' );
-				} );
-
-				model.change( writer => {
-					writer.addMarker( 'marker2', { range: markerRange, usingOperation: false } );
-				} );
-			} );
-
-			it( 'should do nothing if descriptor is not provided', () => {
-				dispatcher.on( 'addMarker:marker2', highlightText( () => null ) );
-				dispatcher.on( 'addMarker:marker2', highlightElement( () => null ) );
-				dispatcher.on( 'removeMarker:marker2', removeHighlight( () => null ) );
-
-				model.change( writer => {
-					writer.addMarker( 'marker2', { range: markerRange, usingOperation: false } );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div></div>' );
-
-				model.change( writer => {
-					writer.removeMarker( 'marker2' );
-				} );
-
-				expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div></div>' );
-			} );
-		} );
-	} );
+	// describe( 'highlight', () => {
+	// 	describe( 'on text', () => {
+	// 		const highlightDescriptor = {
+	// 			classes: 'highlight-class',
+	// 			priority: 7,
+	// 			attributes: { title: 'title' }
+	// 		};
+	//
+	// 		let markerRange;
+	//
+	// 		beforeEach( () => {
+	// 			const modelElement1 = new ModelElement( 'paragraph', null, new ModelText( 'foo' ) );
+	// 			const modelElement2 = new ModelElement( 'paragraph', null, new ModelText( 'bar' ) );
+	//
+	// 			model.change( writer => {
+	// 				writer.insert( [ modelElement1, modelElement2 ], modelRootStart );
+	// 			} );
+	//
+	// 			markerRange = model.createRangeIn( modelRoot );
+	// 		} );
+	//
+	// 		it( 'should wrap and unwrap text nodes', () => {
+	// 			dispatcher.on( 'addMarker:marker', highlightText( highlightDescriptor ) );
+	// 			dispatcher.on( 'addMarker:marker', highlightElement( highlightDescriptor ) );
+	// 			dispatcher.on( 'removeMarker:marker', removeHighlight( highlightDescriptor ) );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal(
+	// 				'<div>' +
+	// 				'<p>' +
+	// 				'<span class="highlight-class" title="title">foo</span>' +
+	// 				'</p>' +
+	// 				'<p>' +
+	// 				'<span class="highlight-class" title="title">bar</span>' +
+	// 				'</p>' +
+	// 				'</div>'
+	// 			);
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'marker' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
+	// 		} );
+	//
+	// 		it( 'should be possible to overwrite', () => {
+	// 			dispatcher.on( 'addMarker:marker', highlightText( highlightDescriptor ) );
+	// 			dispatcher.on( 'addMarker:marker', highlightElement( highlightDescriptor ) );
+	// 			dispatcher.on( 'removeMarker:marker', removeHighlight( highlightDescriptor ) );
+	//
+	// 			const newDescriptor = { classes: 'override-class' };
+	//
+	// 			dispatcher.on( 'addMarker:marker', highlightText( newDescriptor ), { priority: 'high' } );
+	// 			dispatcher.on( 'addMarker:marker', highlightElement( newDescriptor ), { priority: 'high' } );
+	// 			dispatcher.on( 'removeMarker:marker', removeHighlight( newDescriptor ), { priority: 'high' } );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal(
+	// 				'<div>' +
+	// 				'<p>' +
+	// 				'<span class="override-class">foo</span>' +
+	// 				'</p>' +
+	// 				'<p>' +
+	// 				'<span class="override-class">bar</span>' +
+	// 				'</p>' +
+	// 				'</div>'
+	// 			);
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'marker' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
+	// 		} );
+	//
+	// 		it( 'should do nothing if descriptor is not provided or generating function returns null', () => {
+	// 			dispatcher.on( 'addMarker:marker', highlightText( () => null ), { priority: 'high' } );
+	// 			dispatcher.on( 'addMarker:marker', highlightElement( () => null ), { priority: 'high' } );
+	// 			dispatcher.on( 'removeMarker:marker', removeHighlight( () => null ), { priority: 'high' } );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'marker' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
+	// 		} );
+	//
+	// 		it( 'should do nothing if collapsed marker is converted', () => {
+	// 			const descriptor = { classes: 'foo' };
+	//
+	// 			dispatcher.on( 'addMarker:marker', highlightText( descriptor ), { priority: 'high' } );
+	// 			dispatcher.on( 'addMarker:marker', highlightElement( descriptor ), { priority: 'high' } );
+	// 			dispatcher.on( 'removeMarker:marker', removeHighlight( descriptor ), { priority: 'high' } );
+	//
+	// 			markerRange = model.createRange( model.createPositionAt( modelRoot, 0 ), model.createPositionAt( modelRoot, 0 ) );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
+	//
+	// 			model.change( () => {
+	// 				model.markers._remove( 'marker' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
+	// 		} );
+	//
+	// 		it( 'should correctly wrap and unwrap multiple, intersecting markers', () => {
+	// 			const descriptorFoo = { classes: 'foo' };
+	// 			const descriptorBar = { classes: 'bar' };
+	// 			const descriptorXyz = { classes: 'xyz' };
+	//
+	// 			dispatcher.on( 'addMarker:markerFoo', highlightText( descriptorFoo ) );
+	// 			dispatcher.on( 'addMarker:markerBar', highlightText( descriptorBar ) );
+	// 			dispatcher.on( 'addMarker:markerXyz', highlightText( descriptorXyz ) );
+	//
+	// 			dispatcher.on( 'removeMarker:markerFoo', removeHighlight( descriptorFoo ) );
+	// 			dispatcher.on( 'removeMarker:markerBar', removeHighlight( descriptorBar ) );
+	// 			dispatcher.on( 'removeMarker:markerXyz', removeHighlight( descriptorXyz ) );
+	//
+	// 			const p1 = modelRoot.getChild( 0 );
+	// 			const p2 = modelRoot.getChild( 1 );
+	//
+	// 			model.change( writer => {
+	// 				const range = writer.createRange( writer.createPositionAt( p1, 0 ), writer.createPositionAt( p1, 3 ) );
+	// 				writer.addMarker( 'markerFoo', { range, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal(
+	// 				'<div>' +
+	// 				'<p>' +
+	// 				'<span class="foo">foo</span>' +
+	// 				'</p>' +
+	// 				'<p>bar</p>' +
+	// 				'</div>'
+	// 			);
+	//
+	// 			model.change( writer => {
+	// 				const range = writer.createRange( writer.createPositionAt( p1, 1 ), writer.createPositionAt( p2, 2 ) );
+	// 				writer.addMarker( 'markerBar', { range, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal(
+	// 				'<div>' +
+	// 				'<p>' +
+	// 				'<span class="foo">f</span>' +
+	// 				'<span class="bar">' +
+	// 				'<span class="foo">oo</span>' +
+	// 				'</span>' +
+	// 				'</p>' +
+	// 				'<p>' +
+	// 				'<span class="bar">ba</span>' +
+	// 				'r' +
+	// 				'</p>' +
+	// 				'</div>'
+	// 			);
+	//
+	// 			model.change( writer => {
+	// 				const range = writer.createRange( writer.createPositionAt( p1, 2 ), writer.createPositionAt( p2, 3 ) );
+	// 				writer.addMarker( 'markerXyz', { range, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal(
+	// 				'<div>' +
+	// 				'<p>' +
+	// 				'<span class="foo">f</span>' +
+	// 				'<span class="bar">' +
+	// 				'<span class="foo">' +
+	// 				'o' +
+	// 				'<span class="xyz">o</span>' +
+	// 				'</span>' +
+	// 				'</span>' +
+	// 				'</p>' +
+	// 				'<p>' +
+	// 				'<span class="bar">' +
+	// 				'<span class="xyz">ba</span>' +
+	// 				'</span>' +
+	// 				'<span class="xyz">r</span>' +
+	// 				'</p>' +
+	// 				'</div>'
+	// 			);
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'markerBar' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal(
+	// 				'<div>' +
+	// 				'<p>' +
+	// 				'<span class="foo">' +
+	// 				'fo' +
+	// 				'<span class="xyz">o</span>' +
+	// 				'</span>' +
+	// 				'</p>' +
+	// 				'<p>' +
+	// 				'<span class="xyz">bar</span>' +
+	// 				'</p>' +
+	// 				'</div>'
+	// 			);
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'markerFoo' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal(
+	// 				'<div>' +
+	// 				'<p>' +
+	// 				'fo' +
+	// 				'<span class="xyz">o</span>' +
+	// 				'</p>' +
+	// 				'<p>' +
+	// 				'<span class="xyz">bar</span>' +
+	// 				'</p>' +
+	// 				'</div>'
+	// 			);
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'markerXyz' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
+	// 		} );
+	//
+	// 		it( 'should do nothing if marker is applied and removed on empty-ish range', () => {
+	// 			dispatcher.on( 'addMarker:marker', highlightText( highlightDescriptor ) );
+	// 			dispatcher.on( 'removeMarker:marker', removeHighlight( highlightDescriptor ) );
+	//
+	// 			const p1 = modelRoot.getChild( 0 );
+	// 			const p2 = modelRoot.getChild( 1 );
+	//
+	// 			const markerRange = model.createRange( model.createPositionAt( p1, 3 ), model.createPositionAt( p2, 0 ) );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'marker', { range: markerRange, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foo</p><p>bar</p></div>' );
+	// 		} );
+	// 	} );
+	//
+	// 	describe( 'on element', () => {
+	// 		const highlightDescriptor = {
+	// 			classes: 'highlight-class',
+	// 			priority: 7,
+	// 			attributes: { title: 'title' },
+	// 			id: 'customId'
+	// 		};
+	//
+	// 		let markerRange;
+	//
+	// 		beforeEach( () => {
+	// 			// Provide converter for div element. View div element will have custom highlight handling.
+	// 			dispatcher.on( 'insert:div', insertElement( () => {
+	// 				const viewContainer = new ViewContainerElement( 'div' );
+	//
+	// 				viewContainer._setCustomProperty( 'addHighlight', ( element, descriptor, writer ) => {
+	// 					writer.addClass( descriptor.classes, element );
+	// 				} );
+	//
+	// 				viewContainer._setCustomProperty( 'removeHighlight', ( element, id, writer ) => {
+	// 					writer.setAttribute( 'class', '', element );
+	// 				} );
+	//
+	// 				return viewContainer;
+	// 			} ) );
+	//
+	// 			const modelElement = new ModelElement( 'div', null, new ModelText( 'foo' ) );
+	//
+	// 			model.change( writer => {
+	// 				writer.insert( modelElement, modelRootStart );
+	// 			} );
+	//
+	// 			markerRange = model.createRangeOn( modelElement );
+	//
+	// 			dispatcher.on( 'addMarker:marker', highlightText( highlightDescriptor ) );
+	// 			dispatcher.on( 'addMarker:marker', highlightElement( highlightDescriptor ) );
+	// 			dispatcher.on( 'removeMarker:marker', removeHighlight( highlightDescriptor ) );
+	// 		} );
+	//
+	// 		it( 'should use addHighlight and removeHighlight on elements and not convert children nodes', () => {
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal(
+	// 				'<div>' +
+	// 				'<div class="highlight-class">' +
+	// 				'foo' +
+	// 				'</div>' +
+	// 				'</div>'
+	// 			);
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'marker' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div></div>' );
+	// 		} );
+	//
+	// 		it( 'should be possible to override', () => {
+	// 			const newDescriptor = { classes: 'override-class' };
+	//
+	// 			dispatcher.on( 'addMarker:marker', highlightText( newDescriptor ), { priority: 'high' } );
+	// 			dispatcher.on( 'addMarker:marker', highlightElement( newDescriptor ), { priority: 'high' } );
+	// 			dispatcher.on( 'removeMarker:marker', removeHighlight( newDescriptor ), { priority: 'high' } );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker', { range: markerRange, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal(
+	// 				'<div>' +
+	// 				'<div class="override-class">' +
+	// 				'foo' +
+	// 				'</div>' +
+	// 				'</div>'
+	// 			);
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'marker' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div></div>' );
+	// 		} );
+	//
+	// 		it( 'should use default priority and id if not provided', () => {
+	// 			const viewDiv = viewRoot.getChild( 0 );
+	//
+	// 			dispatcher.on( 'addMarker:marker2', highlightText( () => null ) );
+	// 			dispatcher.on( 'addMarker:marker2', highlightElement( () => null ) );
+	// 			dispatcher.on( 'removeMarker:marker2', removeHighlight( () => null ) );
+	//
+	// 			viewDiv._setCustomProperty( 'addHighlight', ( element, descriptor ) => {
+	// 				expect( descriptor.priority ).to.equal( ViewAttributeElement.DEFAULT_PRIORITY );
+	// 				expect( descriptor.id ).to.equal( 'marker:foo-bar-baz' );
+	// 			} );
+	//
+	// 			viewDiv._setCustomProperty( 'removeHighlight', ( element, id ) => {
+	// 				expect( id ).to.equal( 'marker:foo-bar-baz' );
+	// 			} );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker2', { range: markerRange, usingOperation: false } );
+	// 			} );
+	// 		} );
+	//
+	// 		it( 'should do nothing if descriptor is not provided', () => {
+	// 			dispatcher.on( 'addMarker:marker2', highlightText( () => null ) );
+	// 			dispatcher.on( 'addMarker:marker2', highlightElement( () => null ) );
+	// 			dispatcher.on( 'removeMarker:marker2', removeHighlight( () => null ) );
+	//
+	// 			model.change( writer => {
+	// 				writer.addMarker( 'marker2', { range: markerRange, usingOperation: false } );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div></div>' );
+	//
+	// 			model.change( writer => {
+	// 				writer.removeMarker( 'marker2' );
+	// 			} );
+	//
+	// 			expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div></div>' );
+	// 		} );
+	// 	} );
+	// } );
 
 	describe( 'createViewElementFromHighlightDescriptor()', () => {
 		it( 'should return attribute element from descriptor object', () => {