Przeglądaj źródła

Fixing after changes introduced in t/ckeditor5-engine/1236

Szymon Cofalik 8 lat temu
rodzic
commit
2e756b9c11

+ 18 - 23
packages/ckeditor5-image/src/image/converters.js

@@ -25,7 +25,11 @@ import first from '@ckeditor/ckeditor5-utils/src/first';
  * @returns {Function}
  */
 export function viewFigureToModel() {
-	return ( evt, data, conversionApi ) => {
+	return dispatcher => {
+		dispatcher.on( 'element:figure', converter );
+	};
+
+	function converter( evt, data, conversionApi ) {
 		// Do not convert if this is not an "image figure".
 		if ( !conversionApi.consumable.test( data.viewItem, { name: true, class: 'image' } ) ) {
 			return;
@@ -58,20 +62,6 @@ export function viewFigureToModel() {
 
 		// Continue conversion where image conversion ends.
 		data.modelCursor = conversionResult.modelCursor;
-	};
-}
-
-/**
- * Creates the image attribute converter for provided model conversion dispatchers.
- *
- * @param {Array.<module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher>} dispatchers
- * @param {String} attributeName
- * @param {Function} [converter] Custom converter for the attribute - default one converts attribute from model `image` element
- * to the same attribute in `img` in the view.
- */
-export function createImageAttributeConverter( dispatchers, attributeName, converter = modelToViewAttributeConverter ) {
-	for ( const dispatcher of dispatchers ) {
-		dispatcher.on( `attribute:${ attributeName }:image`, converter() );
 	}
 }
 
@@ -81,7 +71,11 @@ export function createImageAttributeConverter( dispatchers, attributeName, conve
  * @return {Function}
  */
 export function srcsetAttributeConverter() {
-	return ( evt, data, consumable, conversionApi ) => {
+	return dispatcher => {
+		dispatcher.on( 'attribute:srcset:image', converter );
+	};
+
+	function converter( evt, data, consumable, conversionApi ) {
 		const parts = evt.name.split( ':' );
 		const consumableType = parts[ 0 ] + ':' + parts[ 1 ];
 		const modelImage = data.item;
@@ -117,14 +111,15 @@ export function srcsetAttributeConverter() {
 				}
 			}
 		}
-	};
+	}
 }
 
-// Returns model to view image converter converting given attribute, and adding it to `img` element nested inside `figure` element.
-//
-// @private
-function modelToViewAttributeConverter() {
-	return ( evt, data, consumable, conversionApi ) => {
+export function modelToViewAttributeConverter( attributeKey ) {
+	return dispatcher => {
+		dispatcher.on( `attribute:${ attributeKey }:image`, converter );
+	};
+
+	function converter( evt, data, consumable, conversionApi ) {
 		const parts = evt.name.split( ':' );
 		const consumableType = parts[ 0 ] + ':' + parts[ 1 ];
 		const modelImage = data.item;
@@ -141,5 +136,5 @@ function modelToViewAttributeConverter() {
 		} else {
 			img.removeAttribute( data.attributeKey );
 		}
-	};
+	}
 }

+ 55 - 48
packages/ckeditor5-image/src/image/imageengine.js

@@ -8,15 +8,18 @@
  */
 
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
-import buildModelConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildmodelconverter';
-import buildViewConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildviewconverter';
+
 import {
 	viewFigureToModel,
-	createImageAttributeConverter,
+	modelToViewAttributeConverter,
 	srcsetAttributeConverter
 } from './converters';
+
 import { toImageWidget } from './utils';
-import ModelElement from '@ckeditor/ckeditor5-engine/src/model/element';
+
+import { downcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/downcast-converters';
+import { upcastElementToElement, upcastAttributeToAttribute } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';
+
 import ViewContainerElement from '@ckeditor/ckeditor5-engine/src/view/containerelement';
 import ViewEmptyElement from '@ckeditor/ckeditor5-engine/src/view/emptyelement';
 
@@ -34,9 +37,8 @@ export default class ImageEngine extends Plugin {
 	init() {
 		const editor = this.editor;
 		const schema = editor.model.schema;
-		const data = editor.data;
-		const editing = editor.editing;
 		const t = editor.t;
+		const conversion = editor.conversion;
 
 		// Configure schema.
 		schema.register( 'image', {
@@ -46,54 +48,59 @@ export default class ImageEngine extends Plugin {
 			allowAttributes: [ 'alt', 'src', 'srcset' ]
 		} );
 
-		// Build converter from model to view for data pipeline.
-		buildModelConverter().for( data.modelToView )
-			.fromElement( 'image' )
-			.toElement( () => createImageViewElement() );
-
-		// Build converter from model to view for editing pipeline.
-		buildModelConverter().for( editing.modelToView )
-			.fromElement( 'image' )
-			.toElement( () => toImageWidget( createImageViewElement(), t( 'image widget' ) ) );
+		editor.conversion.for( 'toData' ).add( downcastElementToElement( {
+			model: 'image',
+			view: () => createImageViewElement()
+		} ) );
 
-		createImageAttributeConverter( [ editing.modelToView, data.modelToView ], 'src' );
-		createImageAttributeConverter( [ editing.modelToView, data.modelToView ], 'alt' );
+		editor.conversion.for( 'toEditing' ).add( downcastElementToElement( {
+			model: 'image',
+			view: () => toImageWidget( createImageViewElement(), t( 'image widget' ) )
+		} ) );
 
-		// Convert `srcset` attribute changes and add or remove `sizes` attribute when necessary.
-		createImageAttributeConverter( [ editing.modelToView, data.modelToView ], 'srcset', srcsetAttributeConverter );
+		conversion.for( 'downcast' )
+			.add( modelToViewAttributeConverter( 'src' ) )
+			.add( modelToViewAttributeConverter( 'alt' ) )
+			.add( srcsetAttributeConverter() );
 
-		// Build converter for view img element to model image element.
-		buildViewConverter().for( data.viewToModel )
-			.from( { name: 'img', attribute: { src: true } } )
-			.toElement( viewImage => new ModelElement( 'image', { src: viewImage.getAttribute( 'src' ) } ) );
-
-		// Build converter for alt attribute.
-		buildViewConverter().for( data.viewToModel )
-			.from( { name: 'img', attribute: { alt: true } } )
-			.consuming( { attribute: [ 'alt' ] } )
-			.toAttribute( viewImage => ( { key: 'alt', value: viewImage.getAttribute( 'alt' ) } ) );
+		conversion.for( 'upcast' )
+			.add( upcastElementToElement( {
+				view: {
+					name: 'img',
+					attribute: {
+						src: true
+					}
+				},
+				model: ( viewImage, modelWriter ) => modelWriter.createElement( 'image', { src: viewImage.getAttribute( 'src' ) } )
+			} ) )
+			.add( upcastAttributeToAttribute( {
+				view: {
+					name: 'img',
+					key: 'alt'
+				},
+				model: 'alt'
+			} ) )
+			.add( upcastAttributeToAttribute( {
+				view: {
+					name: 'img',
+					key: 'srcset'
+				},
+				model: {
+					key: 'srcset',
+					value: viewImage => {
+						const value = {
+							data: viewImage.getAttribute( 'srcset' )
+						};
 
-		// Build converter for srcset attribute.
-		buildViewConverter().for( data.viewToModel )
-			.from( { name: 'img', attribute: { srcset: true } } )
-			.consuming( { attribute: [ 'srcset' ] } )
-			.toAttribute( viewImage => {
-				const value = {
-					data: viewImage.getAttribute( 'srcset' )
-				};
+						if ( viewImage.hasAttribute( 'width' ) ) {
+							value.width = viewImage.getAttribute( 'width' );
+						}
 
-				if ( viewImage.hasAttribute( 'width' ) ) {
-					value.width = viewImage.getAttribute( 'width' );
+						return value;
+					}
 				}
-
-				return {
-					key: 'srcset',
-					value
-				};
-			} );
-
-		// Converter for figure element from view to model.
-		data.viewToModel.on( 'element:figure', viewFigureToModel() );
+			} ) )
+			.add( viewFigureToModel() );
 	}
 }
 

+ 13 - 9
packages/ckeditor5-image/src/imagecaption/imagecaptionengine.js

@@ -12,7 +12,7 @@ import ViewContainerElement from '@ckeditor/ckeditor5-engine/src/view/containere
 import ViewElement from '@ckeditor/ckeditor5-engine/src/view/element';
 import viewWriter from '@ckeditor/ckeditor5-engine/src/view/writer';
 import ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position';
-import buildViewConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildviewconverter';
+import { upcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';
 import { isImage } from '../image/utils';
 import {
 	captionElementCreator,
@@ -67,22 +67,26 @@ export default class ImageCaptionEngine extends Plugin {
 		editor.model.document.registerPostFixer( writer => this._insertMissingModelCaptionElement( writer ) );
 
 		// View to model converter for the data pipeline.
-		buildViewConverter()
-			.for( data.viewToModel )
-			.from( matchImageCaption )
-			.toElement( 'caption' );
+		editor.conversion.for( 'upcast' ).add( upcastElementToElement( {
+			view: matchImageCaption,
+			model: 'caption'
+		} ) );
 
 		// Model to view converter for the data pipeline.
-		data.modelToView.on( 'insert:caption', captionModelToView( new ViewContainerElement( 'figcaption' ), false ) );
+		data.downcastDispatcher.on( 'insert:caption', captionModelToView( new ViewContainerElement( 'figcaption' ), false ) );
 
 		// Model to view converter for the editing pipeline.
-		editing.modelToView.on( 'insert:caption', captionModelToView( this._createCaption ) );
+		editing.downcastDispatcher.on( 'insert:caption', captionModelToView( this._createCaption ) );
 
 		// Always show caption in view when something is inserted in model.
-		editing.modelToView.on( 'insert', ( evt, data ) => this._fixCaptionVisibility( data.item ), { priority: 'high' } );
+		editing.downcastDispatcher.on( 'insert', ( evt, data ) => this._fixCaptionVisibility( data.item ), { priority: 'high' } );
 
 		// Hide caption when everything is removed from it.
-		editing.modelToView.on( 'remove', ( evt, data ) => this._fixCaptionVisibility( data.position.parent ), { priority: 'high' } );
+		editing.downcastDispatcher.on(
+			'remove',
+			( evt, data ) => this._fixCaptionVisibility( data.position.parent ),
+			{ priority: 'high' }
+		);
 
 		// Update view before each rendering.
 		this.listenTo( viewDocument, 'render', () => this._updateCaptionVisibility(), { priority: 'high' } );

+ 3 - 3
packages/ckeditor5-image/src/imagestyle/imagestyleengine.js

@@ -60,11 +60,11 @@ export default class ImageStyleEngine extends Plugin {
 
 		// Converters for imageStyle attribute from model to view.
 		const modelToViewConverter = modelToViewStyleAttribute( styles );
-		editing.modelToView.on( 'attribute:imageStyle:image', modelToViewConverter );
-		data.modelToView.on( 'attribute:imageStyle:image', modelToViewConverter );
+		editing.downcastDispatcher.on( 'attribute:imageStyle:image', modelToViewConverter );
+		data.downcastDispatcher.on( 'attribute:imageStyle:image', modelToViewConverter );
 
 		// Converter for figure element from view to model.
-		data.viewToModel.on( 'element:figure', viewToModelStyleAttribute( styles ), { priority: 'low' } );
+		data.upcastDispatcher.on( 'element:figure', viewToModelStyleAttribute( styles ), { priority: 'low' } );
 
 		// Register separate command for each style.
 		for ( const style of styles ) {

+ 1 - 1
packages/ckeditor5-image/src/imageupload/imageuploadprogress.js

@@ -43,7 +43,7 @@ export default class ImageUploadProgress extends Plugin {
 		const editor = this.editor;
 
 		// Upload status change - update image's view according to that status.
-		editor.editing.modelToView.on( 'attribute:uploadStatus:image', ( ...args ) => this.uploadStatusChange( ...args ) );
+		editor.editing.downcastDispatcher.on( 'attribute:uploadStatus:image', ( ...args ) => this.uploadStatusChange( ...args ) );
 	}
 
 	/**

+ 38 - 31
packages/ckeditor5-image/tests/image/converters.js

@@ -5,15 +5,17 @@
 
 import {
 	viewFigureToModel,
-	createImageAttributeConverter,
+	modelToViewAttributeConverter
 } from '../../src/image/converters';
-import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
-import { createImageViewElement } from '../../src/image/imageengine';
 import { toImageWidget } from '../../src/image/utils';
-import buildModelConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildmodelconverter';
-import buildViewConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildviewconverter';
+import { createImageViewElement } from '../../src/image/imageengine';
+import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
+
+import { downcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/downcast-converters';
+import { upcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';
+import { elementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/two-way-converters';
+
 import ModelRange from '@ckeditor/ckeditor5-engine/src/model/range';
-import ModelElement from '@ckeditor/ckeditor5-engine/src/model/element';
 import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
 import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
@@ -37,12 +39,14 @@ describe( 'Image converters', () => {
 					isBlock: true
 				} );
 
-				buildModelConverter().for( editor.editing.modelToView )
-					.fromElement( 'image' )
-					.toElement( () => toImageWidget( createImageViewElement() ) );
+				editor.conversion.for( 'toEditing' ).add( downcastElementToElement( {
+					model: 'image',
+					view: () => toImageWidget( createImageViewElement() )
+				} ) );
 
-				createImageAttributeConverter( [ editor.editing.modelToView ], 'src' );
-				createImageAttributeConverter( [ editor.editing.modelToView ], 'alt' );
+				editor.conversion.for( 'downcast' )
+					.add( modelToViewAttributeConverter( 'src' ) )
+					.add( modelToViewAttributeConverter( 'alt' ) );
 			} );
 	} );
 
@@ -51,7 +55,7 @@ describe( 'Image converters', () => {
 			expect( getModelData( model, { withoutSelection: true } ) ).to.equal( data );
 		}
 
-		let dispatcher, schema, imgConverterCalled;
+		let schema, imgConverterCalled;
 
 		beforeEach( () => {
 			// Since this part of test tests only view->model conversion editing pipeline is not necessary
@@ -61,16 +65,21 @@ describe( 'Image converters', () => {
 			schema = model.schema;
 			schema.extend( '$text', { allowIn: 'image' } );
 
-			dispatcher = editor.data.viewToModel;
-			dispatcher.on( 'element:figure', viewFigureToModel() );
-
-			buildViewConverter().for( dispatcher )
-				.from( { name: 'img', attribute: { src: true } } )
-				.toElement( viewImage => {
-					imgConverterCalled = true;
-
-					return new ModelElement( 'image', { src: viewImage.getAttribute( 'src' ) } );
-				} );
+			editor.conversion.for( 'upcast' )
+				.add( viewFigureToModel() )
+				.add( upcastElementToElement( {
+					view: {
+						name: 'img',
+						attribute: {
+							src: true
+						}
+					},
+					model: ( viewImage, writer ) => {
+						imgConverterCalled = true;
+
+						return writer.createElement( 'image', { src: viewImage.getAttribute( 'src' ) } );
+					}
+				} ) );
 		} );
 
 		it( 'should find img element among children and convert it using already defined converters', () => {
@@ -81,8 +90,8 @@ describe( 'Image converters', () => {
 		} );
 
 		it( 'should convert children allowed by schema and omit disallowed', () => {
-			buildViewConverter().for( editor.data.viewToModel ).fromElement( 'foo' ).toElement( 'foo' );
-			buildViewConverter().for( editor.data.viewToModel ).fromElement( 'bar' ).toElement( 'bar' );
+			editor.conversion.for( 'upcast' ).add( upcastElementToElement( { view: 'foo', model: 'foo' } ) );
+			editor.conversion.for( 'upcast' ).add( upcastElementToElement( { view: 'bar', model: 'bar' } ) );
 
 			schema.register( 'foo', { allowIn: 'image' } );
 			// Is allowed in root, but should not try to split image element.
@@ -95,7 +104,7 @@ describe( 'Image converters', () => {
 		} );
 
 		it( 'should split parent element when image is not allowed - in the middle', () => {
-			buildViewConverter().for( editor.data.viewToModel ).fromElement( 'div' ).toElement( 'div' );
+			editor.conversion.for( 'upcast' ).add( upcastElementToElement( { view: 'div', model: 'div' } ) );
 
 			schema.register( 'div', { inheritAllFrom: '$block' } );
 			schema.extend( 'image', { disallowIn: 'div' } );
@@ -114,8 +123,7 @@ describe( 'Image converters', () => {
 		} );
 
 		it( 'should split parent element when image is not allowed - at the end', () => {
-			buildViewConverter().for( editor.data.viewToModel ).fromElement( 'div' ).toElement( 'div' );
-			buildModelConverter().for( editor.editing.modelToView ).fromElement( 'div' ).toElement( 'div' );
+			elementToElement( editor.conversion, { model: 'div', view: 'div' } );
 
 			schema.register( 'div', { inheritAllFrom: '$block' } );
 			schema.extend( 'image', { disallowIn: 'div' } );
@@ -133,8 +141,7 @@ describe( 'Image converters', () => {
 		} );
 
 		it( 'should split parent element when image is not allowed - at the beginning', () => {
-			buildViewConverter().for( editor.data.viewToModel ).fromElement( 'div' ).toElement( 'div' );
-			buildModelConverter().for( editor.editing.modelToView ).fromElement( 'div' ).toElement( 'div' );
+			elementToElement( editor.conversion, { model: 'div', view: 'div' } );
 
 			schema.register( 'div', { inheritAllFrom: '$block' } );
 			schema.extend( 'image', { disallowIn: 'div' } );
@@ -152,7 +159,7 @@ describe( 'Image converters', () => {
 		} );
 
 		it( 'should be possible to overwrite', () => {
-			dispatcher.on( 'element:figure', ( evt, data, conversionApi ) => {
+			editor.data.upcastDispatcher.on( 'element:figure', ( evt, data, conversionApi ) => {
 				conversionApi.consumable.consume( data.viewItem, { name: true } );
 				conversionApi.consumable.consume( data.viewItem.getChild( 0 ), { name: true } );
 
@@ -237,7 +244,7 @@ describe( 'Image converters', () => {
 		} );
 
 		it( 'should not set attribute if change was already consumed', () => {
-			editor.editing.modelToView.on( 'attribute:alt:image', ( evt, data, consumable ) => {
+			editor.editing.downcastDispatcher.on( 'attribute:alt:image', ( evt, data, consumable ) => {
 				consumable.consume( data.item, 'attribute:alt' );
 			}, { priority: 'high' } );
 

+ 11 - 31
packages/ckeditor5-image/tests/image/imageengine.js

@@ -7,8 +7,7 @@ import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtest
 import ImageEngine from '../../src/image/imageengine';
 import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
-import buildViewConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildviewconverter';
-import buildModelConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildmodelconverter';
+import { elementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/two-way-converters';
 import { isImageWidget } from '../../src/image/utils';
 import normalizeHtml from '@ckeditor/ckeditor5-utils/tests/_utils/normalizehtml';
 
@@ -87,7 +86,7 @@ describe( 'ImageEngine', () => {
 			} );
 
 			it( 'should not convert srcset attribute if is already consumed', () => {
-				editor.data.modelToView.on( 'attribute:srcset:image', ( evt, data, consumable ) => {
+				editor.data.downcastDispatcher.on( 'attribute:srcset:image', ( evt, data, consumable ) => {
 					const modelImage = data.item;
 
 					consumable.consume( modelImage, evt.name );
@@ -173,9 +172,6 @@ describe( 'ImageEngine', () => {
 			} );
 
 			it( 'should not convert in wrong context', () => {
-				const data = editor.data;
-				const editing = editor.editing;
-
 				model.schema.register( 'div', { inheritAllFrom: '$block' } );
 				model.schema.addChildCheck( ( ctx, childDef ) => {
 					if ( ctx.endsWith( '$root' ) && childDef.name == 'image' ) {
@@ -183,8 +179,7 @@ describe( 'ImageEngine', () => {
 					}
 				} );
 
-				buildModelConverter().for( data.modelToView, editing.modelToView ).fromElement( 'div' ).toElement( 'div' );
-				buildViewConverter().for( data.viewToModel ).fromElement( 'div' ).toElement( 'div' );
+				elementToElement( editor.conversion, { model: 'div', view: 'div' } );
 
 				editor.setData( '<div><figure class="image"><img src="foo.png" alt="alt text" /></figure></div>' );
 
@@ -193,7 +188,7 @@ describe( 'ImageEngine', () => {
 			} );
 
 			it( 'should not convert if img is already consumed', () => {
-				editor.data.viewToModel.on( 'element:figure', ( evt, data, conversionApi ) => {
+				editor.data.upcastDispatcher.on( 'element:figure', ( evt, data, conversionApi ) => {
 					const img = data.viewItem.getChild( 0 );
 					conversionApi.consumable.consume( img, { name: true } );
 				}, { priority: 'high' } );
@@ -205,7 +200,7 @@ describe( 'ImageEngine', () => {
 			} );
 
 			it( 'should not convert if figure is already consumed', () => {
-				editor.data.viewToModel.on( 'element:figure', ( evt, data, conversionApi ) => {
+				editor.data.upcastDispatcher.on( 'element:figure', ( evt, data, conversionApi ) => {
 					conversionApi.consumable.consume( data.viewItem, { name: true, class: 'image' } );
 				}, { priority: 'high' } );
 
@@ -217,7 +212,7 @@ describe( 'ImageEngine', () => {
 
 			it( 'should dispatch conversion for nested elements', () => {
 				const conversionSpy = sinon.spy();
-				editor.data.viewToModel.on( 'element:figcaption', conversionSpy );
+				editor.data.upcastDispatcher.on( 'element:figcaption', conversionSpy );
 
 				editor.setData( '<figure class="image"><img src="foo.png" alt="alt text" /><figcaption></figcaption></figure>' );
 
@@ -232,16 +227,12 @@ describe( 'ImageEngine', () => {
 			} );
 
 			it( 'should not convert alt attribute on non-img element', () => {
-				const data = editor.data;
-				const editing = editor.editing;
-
 				model.schema.register( 'div', {
 					inheritAllFrom: '$block',
 					allowAttributes: 'alt'
 				} );
 
-				buildModelConverter().for( data.modelToView, editing.modelToView ).fromElement( 'div' ).toElement( 'div' );
-				buildViewConverter().for( data.viewToModel ).fromElement( 'div' ).toElement( 'div' );
+				elementToElement( editor.conversion, { model: 'div', view: 'div' } );
 
 				editor.setData( '<div alt="foo"></div>' );
 
@@ -285,15 +276,7 @@ describe( 'ImageEngine', () => {
 				beforeEach( () => {
 					model.schema.register( 'div', { inheritAllFrom: '$block' } );
 
-					buildModelConverter()
-						.for( editor.data.modelToView, editor.editing.modelToView )
-						.fromElement( 'div' )
-						.toElement( 'div' );
-
-					buildViewConverter()
-						.for( editor.data.viewToModel )
-						.fromElement( 'div' )
-						.toElement( 'div' );
+					elementToElement( editor.conversion, { model: 'div', view: 'div' } );
 				} );
 
 				it( 'image between non-hoisted elements', () => {
@@ -375,10 +358,7 @@ describe( 'ImageEngine', () => {
 					} );
 					model.schema.extend( 'div', { allowIn: 'limit' } );
 
-					buildModelConverter()
-						.for( editor.data.modelToView, editor.editing.modelToView ).fromElement( 'limit' ).toElement( 'limit' );
-
-					buildViewConverter().for( editor.data.viewToModel ).fromElement( 'limit' ).toElement( 'limit' );
+					elementToElement( editor.conversion, { model: 'limit', view: 'limit' } );
 
 					editor.setData( '<limit><div>foo<img src="foo.jpg" alt="foo" />bar</div></limit>' );
 
@@ -442,7 +422,7 @@ describe( 'ImageEngine', () => {
 				setModelData( model, '<image src="foo.png" alt="alt text"></image>' );
 				const image = document.getRoot().getChild( 0 );
 
-				editor.editing.modelToView.on( 'attribute:alt:image', ( evt, data, consumable ) => {
+				editor.editing.downcastDispatcher.on( 'attribute:alt:image', ( evt, data, consumable ) => {
 					consumable.consume( data.item, 'attribute:alt' );
 				}, { priority: 'high' } );
 
@@ -541,7 +521,7 @@ describe( 'ImageEngine', () => {
 			} );
 
 			it( 'should not convert srcset attribute if is already consumed', () => {
-				editor.editing.modelToView.on( 'attribute:srcset:image', ( evt, data, consumable ) => {
+				editor.editing.downcastDispatcher.on( 'attribute:srcset:image', ( evt, data, consumable ) => {
 					const modelImage = data.item;
 
 					consumable.consume( modelImage, evt.name );

+ 6 - 12
packages/ckeditor5-image/tests/imagecaption/imagecaptionengine.js

@@ -19,8 +19,7 @@ import ModelRange from '@ckeditor/ckeditor5-engine/src/model/range';
 import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
 
-import buildViewConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildviewconverter';
-import buildModelConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildmodelconverter';
+import { elementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/two-way-converters';
 
 describe( 'ImageCaptionEngine', () => {
 	let editor, model, doc, viewDocument;
@@ -40,15 +39,10 @@ describe( 'ImageCaptionEngine', () => {
 				model.schema.extend( 'caption', { allowIn: 'widget' } );
 				model.schema.extend( '$text', { allowIn: 'widget' } );
 
-				buildViewConverter()
-					.for( editor.data.viewToModel )
-					.fromElement( 'widget' )
-					.toElement( 'widget' );
-
-				buildModelConverter()
-					.for( editor.data.modelToView, editor.editing.modelToView )
-					.fromElement( 'widget' )
-					.toElement( 'widget' );
+				elementToElement( editor.conversion, {
+					model: 'widget',
+					view: 'widget'
+				} );
 			} );
 	} );
 
@@ -149,7 +143,7 @@ describe( 'ImageCaptionEngine', () => {
 			} );
 
 			it( 'should not convert when element is already consumed', () => {
-				editor.editing.modelToView.on(
+				editor.editing.downcastDispatcher.on(
 					'insert:caption',
 					( evt, data, consumable, conversionApi ) => {
 						consumable.consume( data.item, 'insert' );

+ 2 - 2
packages/ckeditor5-image/tests/imagestyle/imagestyleengine.js

@@ -192,7 +192,7 @@ describe( 'ImageStyleEngine', () => {
 		} );
 
 		it( 'should not convert from model to view if already consumed: adding attribute', () => {
-			editor.editing.modelToView.on( 'attribute:imageStyle', ( evt, data, consumable ) => {
+			editor.editing.downcastDispatcher.on( 'attribute:imageStyle', ( evt, data, consumable ) => {
 				consumable.consume( data.item, 'attribute:imageStyle' );
 			}, { priority: 'high' } );
 
@@ -209,7 +209,7 @@ describe( 'ImageStyleEngine', () => {
 		} );
 
 		it( 'should not set attribute if change was already consumed', () => {
-			editor.editing.modelToView.on( 'attribute:imageStyle', ( evt, data, consumable ) => {
+			editor.editing.downcastDispatcher.on( 'attribute:imageStyle', ( evt, data, consumable ) => {
 				consumable.consume( data.item, 'attribute:imageStyle' );
 			}, { priority: 'high' } );
 

+ 2 - 4
packages/ckeditor5-image/tests/imageupload/imageuploadcommand.js

@@ -14,7 +14,7 @@ import { createNativeFileMock, UploadAdapterMock } from '@ckeditor/ckeditor5-upl
 import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 import Image from '../../src/image/imageengine';
 import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
-import buildModelConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildmodelconverter';
+import { downcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/downcast-converters';
 import ModelPosition from '@ckeditor/ckeditor5-engine/src/model/position';
 
 import log from '@ckeditor/ckeditor5-utils/src/log';
@@ -104,9 +104,7 @@ describe( 'ImageUploadCommand', () => {
 			} );
 			model.schema.extend( '$text', { allowIn: 'other' } );
 
-			buildModelConverter().for( editor.editing.modelToView )
-				.fromElement( 'other' )
-				.toElement( 'p' );
+			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'other', view: 'p' } ) );
 
 			setModelData( model, '<other>[]</other>' );
 

+ 1 - 1
packages/ckeditor5-image/tests/imageupload/imageuploadediting.js

@@ -197,7 +197,7 @@ describe( 'ImageUploadEditing', () => {
 	} );
 
 	it( 'should not convert image\'s uploadId attribute if is consumed already', () => {
-		editor.editing.modelToView.on( 'attribute:uploadId:image', ( evt, data, consumable ) => {
+		editor.editing.downcastDispatcher.on( 'attribute:uploadId:image', ( evt, data, consumable ) => {
 			consumable.consume( data.item, evt.name );
 		}, { priority: 'high' } );
 

+ 1 - 1
packages/ckeditor5-image/tests/imageupload/imageuploadprogress.js

@@ -153,7 +153,7 @@ describe( 'ImageUploadProgress', () => {
 	} );
 
 	it( 'should not process attribute change if it is already consumed', () => {
-		editor.editing.modelToView.on( 'attribute:uploadStatus:image', ( evt, data, consumable ) => {
+		editor.editing.downcastDispatcher.on( 'attribute:uploadStatus:image', ( evt, data, consumable ) => {
 			consumable.consume( data.item, evt.name );
 		}, { priority: 'highest' } );