ソースを参照

Refactor downcastHelpers & upcastHelpers to classes.

Maciej Gołaszewski 7 年 前
コミット
9dc573db50

+ 52 - 51
packages/ckeditor5-engine/src/conversion/conversion.js

@@ -79,8 +79,8 @@ export default class Conversion {
 	 * @param {module:engine/conversion/downcast-converters~DowncastHelpers|
 	 * module:engine/conversion/upcast-converters~UpcastHelpers} helpers
 	 */
-	register( options ) {
-		if ( this._dispatchersGroups.has( options.name ) ) {
+	register( name, group ) {
+		if ( this._dispatchersGroups.has( name ) ) {
 			/**
 			 * Trying to register a group name that was already registered.
 			 *
@@ -89,13 +89,7 @@ export default class Conversion {
 			throw new CKEditorError( 'conversion-register-group-exists: Trying to register a group name that was already registered.' );
 		}
 
-		const group = {
-			name: options.name,
-			dispatchers: Array.isArray( options.dispatcher ) ? options.dispatcher : [ options.dispatcher ],
-			helpers: options.helpers
-		};
-
-		this._dispatchersGroups.set( options.name, group );
+		this._dispatchersGroups.set( name, group );
 	}
 
 	/* eslint-disable max-len */
@@ -147,17 +141,9 @@ export default class Conversion {
 	 */
 	/* eslint-enable max-len */
 	for( groupName ) {
-		const { dispatchers, helpers } = this._getDispatchersGroup( groupName );
-
-		const baseRetVal = {
-			add( conversionHelper ) {
-				_addToDispatchers( dispatchers, conversionHelper );
-
-				return this;
-			}
-		};
+		const group = this._getDispatchersGroup( groupName );
 
-		return Object.assign( {}, baseRetVal, helpers );
+		return group;
 	}
 
 	/**
@@ -591,38 +577,6 @@ export default class Conversion {
  * @property {module:engine/conversion/downcast-converters~DowncastHelpers|module:engine/conversion/upcast-converters~UpcastHelpers} helpers
  */
 
-/**
- * Base class for conversion utilises.
- *
- * @interface module:engine/conversion/conversion~ConversionHelpers
- */
-
-/**
- * Registers a conversion helper.
- *
- * **Note**: See full usage example in the `{@link module:engine/conversion/conversion~Conversion#for conversion.for()}` method description
- *
- * @method module:engine/conversion/conversion~ConversionHelpers#add
- * @param {Function} conversionHelper The function to be called on event.
- * @returns {module:engine/conversion/conversion~ConversionHelpers|module:engine/conversion/downcast-converters~DowncastHelpers|
- * module:engine/conversion/upcast-converters~UpcastHelpers}
- */
-
-// Helper function for the `Conversion` `.add()` method.
-//
-// Calls `conversionHelper` on each dispatcher from the group specified earlier in the `.for()` call, effectively
-// adding converters to all specified dispatchers.
-//
-// @private
-// @param {Array.<module:engine/conversion/downcastdispatcher~DowncastDispatcher|
-// module:engine/conversion/upcastdispatcher~UpcastDispatcher>} dispatchers
-// @param {Function} conversionHelper
-function _addToDispatchers( dispatchers, conversionHelper ) {
-	for ( const dispatcher of dispatchers ) {
-		conversionHelper( dispatcher );
-	}
-}
-
 // Helper function that creates a joint array out of an item passed in `definition.view` and items passed in
 // `definition.upcastAlso`.
 //
@@ -653,3 +607,50 @@ function* _getUpcastDefinition( model, view, upcastAlso ) {
 		}
 	}
 }
+
+/**
+ * Base class for conversion utilises.
+ *
+ */
+export class ConversionHelpers {
+	/**
+	 * Creates ConversionHelpers instance.
+	 *
+	 * @param {Array.<module:engine/conversion/downcastdispatcher~DowncastDispatcher|
+	 * module:engine/conversion/upcastdispatcher~UpcastDispatcher>} dispatcher
+	 */
+	constructor( dispatcher ) {
+		this._dispatchers = Array.isArray( dispatcher ) ? dispatcher : [ dispatcher ];
+	}
+
+	/**
+	 * Registers a conversion helper.
+	 *
+	 * **Note**: See full usage example in the `{@link module:engine/conversion/conversion~Conversion#for conversion.for()}`
+	 * method description
+	 *
+	 * @param {Function} conversionHelper The function to be called on event.
+	 * @returns {module:engine/conversion/conversion~ConversionHelpers|module:engine/conversion/downcast-converters~DowncastHelpers|
+	 * module:engine/conversion/upcast-converters~UpcastHelpers}
+	 */
+	add( conversionHelper ) {
+		this._addToDispatchers( conversionHelper );
+
+		return this;
+	}
+
+	/**
+	 * Helper function for the `Conversion` `.add()` method.
+	 *
+	 * Calls `conversionHelper` on each dispatcher from the group specified earlier in the `.for()` call, effectively
+	 * adding converters to all specified dispatchers.
+	 *
+	 * @private
+	 * @param {Function} conversionHelper
+	 */
+	_addToDispatchers( conversionHelper ) {
+		for ( const dispatcher of this._dispatchers ) {
+			conversionHelper( dispatcher );
+		}
+	}
+}

ファイルの差分が大きいため隠しています
+ 576 - 621
packages/ckeditor5-engine/src/conversion/downcast-converters.js


ファイルの差分が大きいため隠しています
+ 543 - 576
packages/ckeditor5-engine/src/conversion/upcast-converters.js


+ 24 - 29
packages/ckeditor5-engine/tests/controller/datacontroller.js

@@ -18,19 +18,11 @@ import { parse as parseView, stringify as stringifyView } from '../../src/dev-ut
 
 import count from '@ckeditor/ckeditor5-utils/src/count';
 
-import {
-	_upcastElementToElement,
-	_upcastElementToAttribute
-} from '../../src/conversion/upcast-converters';
-
-import {
-	_downcastElementToElement,
-	_downcastAttributeToElement,
-	_downcastMarkerToHighlight
-} from '../../src/conversion/downcast-converters';
+import UpcastHelpers from '../../src/conversion/upcast-converters';
+import DowncastHelpers from '../../src/conversion/downcast-converters';
 
 describe( 'DataController', () => {
-	let model, modelDocument, htmlDataProcessor, data, schema;
+	let model, modelDocument, htmlDataProcessor, data, schema, upcastHelpers, downcastHelpers;
 
 	beforeEach( () => {
 		model = new Model();
@@ -46,6 +38,9 @@ describe( 'DataController', () => {
 		htmlDataProcessor = new HtmlDataProcessor();
 
 		data = new DataController( model, htmlDataProcessor );
+
+		upcastHelpers = new UpcastHelpers( data.upcastDispatcher );
+		downcastHelpers = new DowncastHelpers( data.downcastDispatcher );
 	} );
 
 	describe( 'constructor()', () => {
@@ -68,7 +63,7 @@ describe( 'DataController', () => {
 		it( 'should set paragraph', () => {
 			schema.register( 'paragraph', { inheritAllFrom: '$block' } );
 
-			_upcastElementToElement( { view: 'p', model: 'paragraph' } )( data.upcastDispatcher );
+			upcastHelpers.elementToElement( { view: 'p', model: 'paragraph' } );
 
 			const output = data.parse( '<p>foo<b>bar</b></p>' );
 
@@ -79,7 +74,7 @@ describe( 'DataController', () => {
 		it( 'should set two paragraphs', () => {
 			schema.register( 'paragraph', { inheritAllFrom: '$block' } );
 
-			_upcastElementToElement( { view: 'p', model: 'paragraph' } )( data.upcastDispatcher );
+			upcastHelpers.elementToElement( { view: 'p', model: 'paragraph' } );
 
 			const output = data.parse( '<p>foo</p><p>bar</p>' );
 
@@ -93,8 +88,8 @@ describe( 'DataController', () => {
 				allowAttributes: [ 'bold' ]
 			} );
 
-			_upcastElementToElement( { view: 'p', model: 'paragraph' } )( data.upcastDispatcher );
-			_upcastElementToAttribute( { view: 'strong', model: 'bold' } )( data.upcastDispatcher );
+			upcastHelpers.elementToElement( { view: 'p', model: 'paragraph' } );
+			upcastHelpers.elementToAttribute( { view: 'strong', model: 'bold' } );
 
 			const output = data.parse( '<p>foo<strong>bar</strong></p>' );
 
@@ -119,7 +114,7 @@ describe( 'DataController', () => {
 		beforeEach( () => {
 			schema.register( 'paragraph', { inheritAllFrom: '$block' } );
 
-			_upcastElementToElement( { view: 'p', model: 'paragraph' } )( data.upcastDispatcher );
+			upcastHelpers.elementToElement( { view: 'p', model: 'paragraph' } );
 		} );
 
 		it( 'should convert content of an element #1', () => {
@@ -285,7 +280,7 @@ describe( 'DataController', () => {
 			schema.register( 'paragraph', { inheritAllFrom: '$block' } );
 			setData( model, '<paragraph>foo</paragraph>' );
 
-			_downcastElementToElement( { model: 'paragraph', view: 'p' } )( data.downcastDispatcher );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
 			expect( data.get() ).to.equal( '<p>foo</p>' );
 		} );
@@ -294,7 +289,7 @@ describe( 'DataController', () => {
 			schema.register( 'paragraph', { inheritAllFrom: '$block' } );
 			setData( model, '<paragraph></paragraph>' );
 
-			_downcastElementToElement( { model: 'paragraph', view: 'p' } )( data.downcastDispatcher );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
 			expect( data.get() ).to.equal( '<p>&nbsp;</p>' );
 		} );
@@ -303,7 +298,7 @@ describe( 'DataController', () => {
 			schema.register( 'paragraph', { inheritAllFrom: '$block' } );
 			setData( model, '<paragraph>foo</paragraph><paragraph>bar</paragraph>' );
 
-			_downcastElementToElement( { model: 'paragraph', view: 'p' } )( data.downcastDispatcher );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
 			expect( data.get() ).to.equal( '<p>foo</p><p>bar</p>' );
 		} );
@@ -319,7 +314,7 @@ describe( 'DataController', () => {
 			schema.register( 'paragraph', { inheritAllFrom: '$block' } );
 			setData( model, '<paragraph>foo<$text bold="true">bar</$text></paragraph>' );
 
-			_downcastElementToElement( { model: 'paragraph', view: 'p' } )( data.downcastDispatcher );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
 			expect( data.get() ).to.equal( '<p>foobar</p>' );
 		} );
@@ -328,8 +323,8 @@ describe( 'DataController', () => {
 			schema.register( 'paragraph', { inheritAllFrom: '$block' } );
 			setData( model, '<paragraph>foo<$text bold="true">bar</$text></paragraph>' );
 
-			_downcastElementToElement( { model: 'paragraph', view: 'p' } )( data.downcastDispatcher );
-			_downcastAttributeToElement( { model: 'bold', view: 'strong' } )( data.downcastDispatcher );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
+			downcastHelpers.attributeToElement( { model: 'bold', view: 'strong' } );
 
 			expect( data.get() ).to.equal( '<p>foo<strong>bar</strong></p>' );
 		} );
@@ -341,8 +336,8 @@ describe( 'DataController', () => {
 			setData( model, '<paragraph>foo</paragraph>', { rootName: 'main' } );
 			setData( model, 'Bar', { rootName: 'title' } );
 
-			_downcastElementToElement( { model: 'paragraph', view: 'p' } )( data.downcastDispatcher );
-			_downcastAttributeToElement( { model: 'bold', view: 'strong' } )( data.downcastDispatcher );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
+			downcastHelpers.attributeToElement( { model: 'bold', view: 'strong' } );
 
 			expect( data.get() ).to.equal( '<p>foo</p>' );
 			expect( data.get( 'main' ) ).to.equal( '<p>foo</p>' );
@@ -358,7 +353,7 @@ describe( 'DataController', () => {
 			schema.extend( '$block', { allowIn: 'div' } );
 			schema.extend( 'div', { allowIn: '$root' } );
 
-			_downcastElementToElement( { model: 'paragraph', view: 'p' } )( data.downcastDispatcher );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 		} );
 
 		it( 'should stringify a content of an element', () => {
@@ -382,7 +377,7 @@ describe( 'DataController', () => {
 			schema.extend( '$block', { allowIn: 'div' } );
 			schema.extend( 'div', { allowIn: '$root' } );
 
-			_downcastElementToElement( { model: 'paragraph', view: 'p' } )( data.downcastDispatcher );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 		} );
 
 		it( 'should convert a content of an element', () => {
@@ -403,7 +398,7 @@ describe( 'DataController', () => {
 			const modelElement = parseModel( '<div><paragraph>foobar</paragraph></div>', schema );
 			const modelRoot = model.document.getRoot();
 
-			_downcastMarkerToHighlight( { model: 'marker:a', view: { classes: 'a' } } )( data.downcastDispatcher );
+			downcastHelpers.markerToHighlight( { model: 'marker:a', view: { classes: 'a' } } );
 
 			model.change( writer => {
 				writer.insert( modelElement, modelRoot, 0 );
@@ -421,8 +416,8 @@ describe( 'DataController', () => {
 			const modelElement = parseModel( '<div><paragraph>foo</paragraph><paragraph>bar</paragraph></div>', schema );
 			const modelRoot = model.document.getRoot();
 
-			_downcastMarkerToHighlight( { model: 'marker:a', view: { classes: 'a' } } )( data.downcastDispatcher );
-			_downcastMarkerToHighlight( { model: 'marker:b', view: { classes: 'b' } } )( data.downcastDispatcher );
+			downcastHelpers.markerToHighlight( { model: 'marker:a', view: { classes: 'a' } } );
+			downcastHelpers.markerToHighlight( { model: 'marker:b', view: { classes: 'b' } } );
 
 			const modelP1 = modelElement.getChild( 0 );
 			const modelP2 = modelElement.getChild( 1 );

+ 6 - 4
packages/ckeditor5-engine/tests/controller/editingcontroller.js

@@ -14,7 +14,7 @@ import View from '../../src/view/view';
 import Mapper from '../../src/conversion/mapper';
 import DowncastDispatcher from '../../src/conversion/downcastdispatcher';
 
-import { _downcastElementToElement, _downcastMarkerToHighlight } from '../../src/conversion/downcast-converters';
+import DowncastHelpers from '../../src/conversion/downcast-converters';
 import Model from '../../src/model/model';
 import ModelPosition from '../../src/model/position';
 import ModelRange from '../../src/model/range';
@@ -90,9 +90,11 @@ describe( 'EditingController', () => {
 			model.schema.register( 'paragraph', { inheritAllFrom: '$block' } );
 			model.schema.register( 'div', { inheritAllFrom: '$block' } );
 
-			_downcastElementToElement( { model: 'paragraph', view: 'p' } )( editing.downcastDispatcher );
-			_downcastElementToElement( { model: 'div', view: 'div' } )( editing.downcastDispatcher );
-			_downcastMarkerToHighlight( { model: 'marker', view: {} } )( editing.downcastDispatcher );
+			const downcastHelpers = new DowncastHelpers( editing.downcastDispatcher );
+
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
+			downcastHelpers.elementToElement( { model: 'div', view: 'div' } );
+			downcastHelpers.markerToHighlight( { model: 'marker', view: {} } );
 
 			// Note: The below code is highly overcomplicated due to #455.
 			model.change( writer => {

+ 120 - 173
packages/ckeditor5-engine/tests/conversion/downcast-converters.js

@@ -20,12 +20,7 @@ import ViewText from '../../src/view/text';
 import log from '@ckeditor/ckeditor5-utils/src/log';
 import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
 
-import {
-	_downcastElementToElement,
-	_downcastAttributeToElement,
-	_downcastAttributeToAttribute,
-	_downcastMarkerToElement,
-	_downcastMarkerToHighlight,
+import DowncastHelpers, {
 	insertElement, insertUIElement, changeAttribute, wrap, removeUIElement,
 	highlightElement, highlightText, removeHighlight, createViewElementFromHighlightDescriptor
 } from '../../src/conversion/downcast-converters';
@@ -33,7 +28,7 @@ import {
 import { stringify } from '../../src/dev-utils/view';
 
 describe( 'downcast-helpers', () => {
-	let conversion, model, modelRoot, viewRoot;
+	let conversion, model, modelRoot, viewRoot, downcastHelpers;
 
 	beforeEach( () => {
 		model = new Model();
@@ -48,15 +43,15 @@ describe( 'downcast-helpers', () => {
 
 		viewRoot = controller.view.document.getRoot();
 
+		downcastHelpers = new DowncastHelpers( controller.downcastDispatcher );
+
 		conversion = new Conversion();
-		conversion.register( { name: 'downcast', dispatcher: controller.downcastDispatcher } );
+		conversion.register( 'downcast', downcastHelpers );
 	} );
 
 	describe( '_downcastElementToElement', () => {
 		it( 'config.view is a string', () => {
-			const helper = _downcastElementToElement( { model: 'paragraph', view: 'p' } );
-
-			conversion.for( 'downcast' ).add( helper );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
 			model.change( writer => {
 				writer.insertElement( 'paragraph', modelRoot, 0 );
@@ -66,10 +61,8 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'can be overwritten using converterPriority', () => {
-			const helperA = _downcastElementToElement( { model: 'paragraph', view: 'p' } );
-			const helperB = _downcastElementToElement( { model: 'paragraph', view: 'foo', converterPriority: 'high' } );
-
-			conversion.for( 'downcast' ).add( helperA ).add( helperB );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'foo', converterPriority: 'high' } );
 
 			model.change( writer => {
 				writer.insertElement( 'paragraph', modelRoot, 0 );
@@ -79,7 +72,7 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.view is a view element definition', () => {
-			const helper = _downcastElementToElement( {
+			downcastHelpers.elementToElement( {
 				model: 'fancyParagraph',
 				view: {
 					name: 'p',
@@ -87,8 +80,6 @@ describe( 'downcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertElement( 'fancyParagraph', modelRoot, 0 );
 			} );
@@ -97,13 +88,11 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.view is a function', () => {
-			const helper = _downcastElementToElement( {
+			downcastHelpers.elementToElement( {
 				model: 'heading',
 				view: ( modelElement, viewWriter ) => viewWriter.createContainerElement( 'h' + modelElement.getAttribute( 'level' ) )
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertElement( 'heading', { level: 2 }, modelRoot, 0 );
 			} );
@@ -114,9 +103,7 @@ describe( 'downcast-helpers', () => {
 
 	describe( '_downcastAttributeToElement', () => {
 		it( 'config.view is a string', () => {
-			const helper = _downcastAttributeToElement( { model: 'bold', view: 'strong' } );
-
-			conversion.for( 'downcast' ).add( helper );
+			downcastHelpers.attributeToElement( { model: 'bold', view: 'strong' } );
 
 			model.change( writer => {
 				writer.insertText( 'foo', { bold: true }, modelRoot, 0 );
@@ -126,10 +113,8 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'can be overwritten using converterPriority', () => {
-			const helperA = _downcastAttributeToElement( { model: 'bold', view: 'strong' } );
-			const helperB = _downcastAttributeToElement( { model: 'bold', view: 'b', converterPriority: 'high' } );
-
-			conversion.for( 'downcast' ).add( helperA ).add( helperB );
+			downcastHelpers.attributeToElement( { model: 'bold', view: 'strong' } );
+			downcastHelpers.attributeToElement( { model: 'bold', view: 'b', converterPriority: 'high' } );
 
 			model.change( writer => {
 				writer.insertText( 'foo', { bold: true }, modelRoot, 0 );
@@ -139,7 +124,7 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.view is a view element definition', () => {
-			const helper = _downcastAttributeToElement( {
+			downcastHelpers.attributeToElement( {
 				model: 'invert',
 				view: {
 					name: 'span',
@@ -147,8 +132,6 @@ describe( 'downcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertText( 'foo', { invert: true }, modelRoot, 0 );
 			} );
@@ -158,7 +141,7 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.view allows specifying the element\'s priority', () => {
-			const helper = _downcastAttributeToElement( {
+			downcastHelpers.attributeToElement( {
 				model: 'invert',
 				view: {
 					name: 'span',
@@ -166,8 +149,6 @@ describe( 'downcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertText( 'foo', { invert: true }, modelRoot, 0 );
 			} );
@@ -176,7 +157,7 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'model attribute value is enum', () => {
-			const helper = _downcastAttributeToElement( {
+			downcastHelpers.attributeToElement( {
 				model: {
 					key: 'fontSize',
 					values: [ 'big', 'small' ]
@@ -198,8 +179,6 @@ describe( 'downcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertText( 'foo', { fontSize: 'big' }, modelRoot, 0 );
 			} );
@@ -222,15 +201,13 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.view is a function', () => {
-			const helper = _downcastAttributeToElement( {
+			downcastHelpers.attributeToElement( {
 				model: 'bold',
 				view: ( modelAttributeValue, viewWriter ) => {
 					return viewWriter.createAttributeElement( 'span', { style: 'font-weight:' + modelAttributeValue } );
 				}
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertText( 'foo', { bold: '500' }, modelRoot, 0 );
 			} );
@@ -239,7 +216,7 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.model.name is given', () => {
-			const helper = _downcastAttributeToElement( {
+			downcastHelpers.attributeToElement( {
 				model: {
 					key: 'color',
 					name: '$text'
@@ -249,17 +226,15 @@ describe( 'downcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'downcast' )
-				.add( helper )
-				.add( _downcastElementToElement( {
-					model: 'smiley',
-					view: ( modelElement, viewWriter ) => {
-						return viewWriter.createEmptyElement( 'img', {
-							src: 'smile.jpg',
-							class: 'smiley'
-						} );
-					}
-				} ) );
+			downcastHelpers.elementToElement( {
+				model: 'smiley',
+				view: ( modelElement, viewWriter ) => {
+					return viewWriter.createEmptyElement( 'img', {
+						src: 'smile.jpg',
+						class: 'smiley'
+					} );
+				}
+			} );
 
 			model.change( writer => {
 				writer.insertText( 'foo', { color: '#FF0000' }, modelRoot, 0 );
@@ -274,13 +249,11 @@ describe( 'downcast-helpers', () => {
 		testUtils.createSinonSandbox();
 
 		beforeEach( () => {
-			conversion.for( 'downcast' ).add( _downcastElementToElement( { model: 'image', view: 'img' } ) );
+			downcastHelpers.elementToElement( { model: 'image', view: 'img' } );
 		} );
 
 		it( 'config.view is a string', () => {
-			const helper = _downcastAttributeToAttribute( { model: 'source', view: 'src' } );
-
-			conversion.for( 'downcast' ).add( helper );
+			downcastHelpers.attributeToAttribute( { model: 'source', view: 'src' } );
 
 			model.change( writer => {
 				writer.insertElement( 'image', { source: 'foo.jpg' }, modelRoot, 0 );
@@ -296,10 +269,8 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'can be overwritten using converterPriority', () => {
-			const helperA = _downcastAttributeToAttribute( { model: 'source', view: 'href' } );
-			const helperB = _downcastAttributeToAttribute( { model: 'source', view: 'src', converterPriority: 'high' } );
-
-			conversion.for( 'downcast' ).add( helperA ).add( helperB );
+			downcastHelpers.attributeToAttribute( { model: 'source', view: 'href' } );
+			downcastHelpers.attributeToAttribute( { model: 'source', view: 'src', converterPriority: 'high' } );
 
 			model.change( writer => {
 				writer.insertElement( 'image', { source: 'foo.jpg' }, modelRoot, 0 );
@@ -309,9 +280,9 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'model element name specified', () => {
-			conversion.for( 'downcast' ).add( _downcastElementToElement( { model: 'paragraph', view: 'p' } ) );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
-			const helper = _downcastAttributeToAttribute( {
+			downcastHelpers.attributeToAttribute( {
 				model: {
 					name: 'image',
 					key: 'source'
@@ -319,8 +290,6 @@ describe( 'downcast-helpers', () => {
 				view: 'src'
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertElement( 'image', { source: 'foo.jpg' }, modelRoot, 0 );
 			} );
@@ -335,9 +304,9 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.view is an object, model attribute value is enum', () => {
-			conversion.for( 'downcast' ).add( _downcastElementToElement( { model: 'paragraph', view: 'p' } ) );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
-			const helper = _downcastAttributeToAttribute( {
+			downcastHelpers.attributeToAttribute( {
 				model: {
 					key: 'styled',
 					values: [ 'dark', 'light' ]
@@ -354,8 +323,6 @@ describe( 'downcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertElement( 'paragraph', { styled: 'dark' }, modelRoot, 0 );
 			} );
@@ -376,9 +343,9 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.view is an object, model attribute value is enum, view has style', () => {
-			conversion.for( 'downcast' ).add( _downcastElementToElement( { model: 'paragraph', view: 'p' } ) );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
-			const helper = _downcastAttributeToAttribute( {
+			downcastHelpers.attributeToAttribute( {
 				model: {
 					key: 'align',
 					values: [ 'right', 'center' ]
@@ -399,8 +366,6 @@ describe( 'downcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertElement( 'paragraph', { align: 'right' }, modelRoot, 0 );
 			} );
@@ -421,9 +386,9 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.view is an object, only name and key are provided', () => {
-			conversion.for( 'downcast' ).add( _downcastElementToElement( { model: 'paragraph', view: 'p' } ) );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
-			const helper = _downcastAttributeToAttribute( {
+			downcastHelpers.attributeToAttribute( {
 				model: {
 					name: 'paragraph',
 					key: 'class'
@@ -434,8 +399,6 @@ describe( 'downcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertElement( 'paragraph', { class: 'dark' }, modelRoot, 0 );
 			} );
@@ -456,13 +419,11 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.view is a function', () => {
-			const helper = _downcastAttributeToAttribute( {
+			downcastHelpers.attributeToAttribute( {
 				model: 'styled',
 				view: attributeValue => ( { key: 'class', value: 'styled-' + attributeValue } )
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertElement( 'image', { styled: 'pull-out' }, modelRoot, 0 );
 			} );
@@ -474,9 +435,9 @@ describe( 'downcast-helpers', () => {
 		it( 'config.view and config.model as strings in generic conversion (elements only)', () => {
 			const logSpy = testUtils.sinon.spy( log, 'warn' );
 
-			conversion.for( 'downcast' ).add( _downcastElementToElement( { model: 'paragraph', view: 'p' } ) );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
-			conversion.for( 'downcast' ).add( _downcastAttributeToAttribute( { model: 'test', view: 'test' } ) );
+			downcastHelpers.attributeToAttribute( { model: 'test', view: 'test' } );
 
 			model.change( writer => {
 				writer.insertElement( 'paragraph', { test: '1' }, modelRoot, 0 );
@@ -497,9 +458,9 @@ describe( 'downcast-helpers', () => {
 		it( 'config.view and config.model as strings in generic conversion (elements + text)', () => {
 			const logSpy = testUtils.sinon.spy( log, 'warn' );
 
-			conversion.for( 'downcast' ).add( _downcastElementToElement( { model: 'paragraph', view: 'p' } ) );
+			downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
-			conversion.for( 'downcast' ).add( _downcastAttributeToAttribute( { model: 'test', view: 'test' } ) );
+			downcastHelpers.attributeToAttribute( { model: 'test', view: 'test' } );
 
 			model.change( writer => {
 				writer.insertElement( 'paragraph', modelRoot, 0 );
@@ -523,9 +484,7 @@ describe( 'downcast-helpers', () => {
 
 	describe( '_downcastMarkerToElement', () => {
 		it( 'config.view is a string', () => {
-			const helper = _downcastMarkerToElement( { model: 'search', view: 'marker-search' } );
-
-			conversion.for( 'downcast' ).add( helper );
+			downcastHelpers.markerToElement( { model: 'search', view: 'marker-search' } );
 
 			model.change( writer => {
 				writer.insertText( 'foo', modelRoot, 0 );
@@ -538,10 +497,8 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'can be overwritten using converterPriority', () => {
-			const helperA = _downcastMarkerToElement( { model: 'search', view: 'marker-search' } );
-			const helperB = _downcastMarkerToElement( { model: 'search', view: 'search', converterPriority: 'high' } );
-
-			conversion.for( 'downcast' ).add( helperA ).add( helperB );
+			downcastHelpers.markerToElement( { model: 'search', view: 'marker-search' } );
+			downcastHelpers.markerToElement( { model: 'search', view: 'search', converterPriority: 'high' } );
 
 			model.change( writer => {
 				writer.insertText( 'foo', modelRoot, 0 );
@@ -553,7 +510,7 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.view is a view element definition', () => {
-			const helper = _downcastMarkerToElement( {
+			downcastHelpers.markerToElement( {
 				model: 'search',
 				view: {
 					name: 'span',
@@ -563,8 +520,6 @@ describe( 'downcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertText( 'foo', modelRoot, 0 );
 				const range = writer.createRange( writer.createPositionAt( modelRoot, 1 ), writer.createPositionAt( modelRoot, 2 ) );
@@ -575,15 +530,13 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.view is a function', () => {
-			const helper = _downcastMarkerToElement( {
+			downcastHelpers.markerToElement( {
 				model: 'search',
 				view: ( data, viewWriter ) => {
 					return viewWriter.createUIElement( 'span', { 'data-marker': 'search', 'data-start': data.isOpening } );
 				}
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertText( 'foo', modelRoot, 0 );
 				const range = writer.createRange( writer.createPositionAt( modelRoot, 1 ), writer.createPositionAt( modelRoot, 2 ) );
@@ -596,9 +549,7 @@ describe( 'downcast-helpers', () => {
 
 	describe( '_downcastMarkerToHighlight', () => {
 		it( 'config.view is a highlight descriptor', () => {
-			const helper = _downcastMarkerToHighlight( { model: 'comment', view: { classes: 'comment' } } );
-
-			conversion.for( 'downcast' ).add( helper );
+			downcastHelpers.markerToHighlight( { model: 'comment', view: { classes: 'comment' } } );
 
 			model.change( writer => {
 				writer.insertText( 'foo', modelRoot, 0 );
@@ -610,10 +561,8 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'can be overwritten using converterPriority', () => {
-			const helperA = _downcastMarkerToHighlight( { model: 'comment', view: { classes: 'comment' } } );
-			const helperB = _downcastMarkerToHighlight( { model: 'comment', view: { classes: 'new-comment' }, converterPriority: 'high' } );
-
-			conversion.for( 'downcast' ).add( helperA ).add( helperB );
+			downcastHelpers.markerToHighlight( { model: 'comment', view: { classes: 'comment' } } );
+			downcastHelpers.markerToHighlight( { model: 'comment', view: { classes: 'new-comment' }, converterPriority: 'high' } );
 
 			model.change( writer => {
 				writer.insertText( 'foo', modelRoot, 0 );
@@ -625,7 +574,7 @@ describe( 'downcast-helpers', () => {
 		} );
 
 		it( 'config.view is a function', () => {
-			const helper = _downcastMarkerToHighlight( {
+			downcastHelpers.markerToHighlight( {
 				model: 'comment',
 				view: data => {
 					const commentType = data.markerName.split( ':' )[ 1 ];
@@ -636,8 +585,6 @@ describe( 'downcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'downcast' ).add( helper );
-
 			model.change( writer => {
 				writer.insertText( 'foo', modelRoot, 0 );
 				const range = writer.createRange( writer.createPositionAt( modelRoot, 0 ), writer.createPositionAt( modelRoot, 3 ) );
@@ -1373,12 +1320,12 @@ describe( 'downcast-converters', () => {
 
 				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>' +
+					'<p>' +
+					'<span class="highlight-class" title="title">foo</span>' +
+					'</p>' +
+					'<p>' +
+					'<span class="highlight-class" title="title">bar</span>' +
+					'</p>' +
 					'</div>'
 				);
 
@@ -1406,12 +1353,12 @@ describe( 'downcast-converters', () => {
 
 				expect( viewToString( viewRoot ) ).to.equal(
 					'<div>' +
-						'<p>' +
-							'<span class="override-class">foo</span>' +
-						'</p>' +
-						'<p>' +
-							'<span class="override-class">bar</span>' +
-						'</p>' +
+					'<p>' +
+					'<span class="override-class">foo</span>' +
+					'</p>' +
+					'<p>' +
+					'<span class="override-class">bar</span>' +
+					'</p>' +
 					'</div>'
 				);
 
@@ -1485,10 +1432,10 @@ describe( 'downcast-converters', () => {
 
 				expect( viewToString( viewRoot ) ).to.equal(
 					'<div>' +
-						'<p>' +
-							'<span class="foo">foo</span>' +
-						'</p>' +
-						'<p>bar</p>' +
+					'<p>' +
+					'<span class="foo">foo</span>' +
+					'</p>' +
+					'<p>bar</p>' +
 					'</div>'
 				);
 
@@ -1499,16 +1446,16 @@ describe( 'downcast-converters', () => {
 
 				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>' +
+					'<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>'
 				);
 
@@ -1519,21 +1466,21 @@ describe( 'downcast-converters', () => {
 
 				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>' +
+					'<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>'
 				);
 
@@ -1543,15 +1490,15 @@ describe( 'downcast-converters', () => {
 
 				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>' +
+					'<p>' +
+					'<span class="foo">' +
+					'fo' +
+					'<span class="xyz">o</span>' +
+					'</span>' +
+					'</p>' +
+					'<p>' +
+					'<span class="xyz">bar</span>' +
+					'</p>' +
 					'</div>'
 				);
 
@@ -1561,13 +1508,13 @@ describe( 'downcast-converters', () => {
 
 				expect( viewToString( viewRoot ) ).to.equal(
 					'<div>' +
-						'<p>' +
-							'fo' +
-							'<span class="xyz">o</span>' +
-						'</p>' +
-						'<p>' +
-							'<span class="xyz">bar</span>' +
-						'</p>' +
+					'<p>' +
+					'fo' +
+					'<span class="xyz">o</span>' +
+					'</p>' +
+					'<p>' +
+					'<span class="xyz">bar</span>' +
+					'</p>' +
 					'</div>'
 				);
 
@@ -1647,9 +1594,9 @@ describe( 'downcast-converters', () => {
 
 				expect( viewToString( viewRoot ) ).to.equal(
 					'<div>' +
-						'<div class="highlight-class">' +
-							'foo' +
-						'</div>' +
+					'<div class="highlight-class">' +
+					'foo' +
+					'</div>' +
 					'</div>'
 				);
 
@@ -1673,9 +1620,9 @@ describe( 'downcast-converters', () => {
 
 				expect( viewToString( viewRoot ) ).to.equal(
 					'<div>' +
-						'<div class="override-class">' +
-							'foo' +
-						'</div>' +
+					'<div class="override-class">' +
+					'foo' +
+					'</div>' +
 					'</div>'
 				);
 
@@ -1732,7 +1679,7 @@ describe( 'downcast-converters', () => {
 			const descriptor = {
 				classes: 'foo-class',
 				attributes: { one: '1', two: '2' },
-				priority: 7,
+				priority: 7
 			};
 			const element = createViewElementFromHighlightDescriptor( descriptor );
 
@@ -1750,7 +1697,7 @@ describe( 'downcast-converters', () => {
 			const descriptor = {
 				classes: [ 'foo-class', 'bar-class' ],
 				attributes: { one: '1', two: '2' },
-				priority: 7,
+				priority: 7
 			};
 			const element = createViewElementFromHighlightDescriptor( descriptor );
 
@@ -1768,7 +1715,7 @@ describe( 'downcast-converters', () => {
 		it( 'should create element without class', () => {
 			const descriptor = {
 				attributes: { one: '1', two: '2' },
-				priority: 7,
+				priority: 7
 			};
 			const element = createViewElementFromHighlightDescriptor( descriptor );
 
@@ -1784,7 +1731,7 @@ describe( 'downcast-converters', () => {
 		it( 'should create element without priority', () => {
 			const descriptor = {
 				classes: 'foo-class',
-				attributes: { one: '1', two: '2' },
+				attributes: { one: '1', two: '2' }
 			};
 			const element = createViewElementFromHighlightDescriptor( descriptor );
 

+ 56 - 125
packages/ckeditor5-engine/tests/conversion/upcast-converters.js

@@ -19,15 +19,12 @@ import ModelText from '../../src/model/text';
 import ModelRange from '../../src/model/range';
 import ModelPosition from '../../src/model/position';
 
-import {
-	_upcastElementToElement, _upcastElementToAttribute, _upcastAttributeToAttribute, _upcastElementToMarker,
-	convertToModelFragment, convertText
-} from '../../src/conversion/upcast-converters';
+import UpcastHelpers, { convertToModelFragment, convertText } from '../../src/conversion/upcast-converters';
 
 import { stringify } from '../../src/dev-utils/model';
 
-describe( 'upcast-helpers', () => {
-	let upcastDispatcher, model, schema, conversion;
+describe( 'UpcastHelpers', () => {
+	let upcastDispatcher, model, schema, conversion, upcastHelpers;
 
 	beforeEach( () => {
 		model = new Model();
@@ -49,14 +46,13 @@ describe( 'upcast-helpers', () => {
 		upcastDispatcher.on( 'documentFragment', convertToModelFragment(), { priority: 'lowest' } );
 
 		conversion = new Conversion();
-		conversion.register( { name: 'upcast', dispatcher: upcastDispatcher } );
+		upcastHelpers = new UpcastHelpers( upcastDispatcher );
+		conversion.register( 'upcast', upcastHelpers );
 	} );
 
 	describe( '_upcastElementToElement', () => {
 		it( 'config.view is a string', () => {
-			const helper = _upcastElementToElement( { view: 'p', model: 'paragraph' } );
-
-			conversion.for( 'upcast' ).add( helper );
+			upcastHelpers.elementToElement( { view: 'p', model: 'paragraph' } );
 
 			expectResult( new ViewContainerElement( 'p' ), '<paragraph></paragraph>' );
 		} );
@@ -66,10 +62,8 @@ describe( 'upcast-helpers', () => {
 				inheritAllFrom: '$block'
 			} );
 
-			const helperA = _upcastElementToElement( { view: 'p', model: 'p' } );
-			const helperB = _upcastElementToElement( { view: 'p', model: 'paragraph', converterPriority: 'high' } );
-
-			conversion.for( 'upcast' ).add( helperA ).add( helperB );
+			upcastHelpers.elementToElement( { view: 'p', model: 'p' } );
+			upcastHelpers.elementToElement( { view: 'p', model: 'paragraph', converterPriority: 'high' } );
 
 			expectResult( new ViewContainerElement( 'p' ), '<paragraph></paragraph>' );
 		} );
@@ -79,16 +73,14 @@ describe( 'upcast-helpers', () => {
 				inheritAllFrom: '$block'
 			} );
 
-			const helperFancy = _upcastElementToElement( {
+			upcastHelpers.elementToElement( {
 				view: {
 					name: 'p',
 					classes: 'fancy'
 				},
-				model: 'fancyParagraph',
+				model: 'fancyParagraph'
 			} );
 
-			conversion.for( 'upcast' ).add( helperFancy );
-
 			expectResult( new ViewContainerElement( 'p', { class: 'fancy' } ), '<fancyParagraph></fancyParagraph>' );
 			expectResult( new ViewContainerElement( 'p' ), '' );
 		} );
@@ -99,7 +91,7 @@ describe( 'upcast-helpers', () => {
 				allowAttributes: [ 'level' ]
 			} );
 
-			const helper = _upcastElementToElement( {
+			upcastHelpers.elementToElement( {
 				view: {
 					name: 'p',
 					classes: 'heading'
@@ -109,24 +101,18 @@ describe( 'upcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'upcast' ).add( helper );
-
 			expectResult( new ViewContainerElement( 'p', { class: 'heading', 'data-level': 2 } ), '<heading level="2"></heading>' );
 			expectResult( new ViewContainerElement( 'p', { 'data-level': 2 } ), '' );
 		} );
 
 		it( 'should fire conversion of the element children', () => {
-			const helper = _upcastElementToElement( { view: 'p', model: 'paragraph' } );
-
-			conversion.for( 'upcast' ).add( helper );
+			upcastHelpers.elementToElement( { view: 'p', model: 'paragraph' } );
 
 			expectResult( new ViewContainerElement( 'p', null, new ViewText( 'foo' ) ), '<paragraph>foo</paragraph>' );
 		} );
 
 		it( 'should not insert a model element if it is not allowed by schema', () => {
-			const helper = _upcastElementToElement( { view: 'h2', model: 'heading' } );
-
-			conversion.for( 'upcast' ).add( helper );
+			upcastHelpers.elementToElement( { view: 'h2', model: 'heading' } );
 
 			expectResult( new ViewContainerElement( 'h2' ), '' );
 		} );
@@ -136,10 +122,8 @@ describe( 'upcast-helpers', () => {
 				inheritAllFrom: '$block'
 			} );
 
-			const helperParagraph = _upcastElementToElement( { view: 'p', model: 'paragraph' } );
-			const helperHeading = _upcastElementToElement( { view: 'h2', model: 'heading' } );
-
-			conversion.for( 'upcast' ).add( helperParagraph ).add( helperHeading );
+			upcastHelpers.elementToElement( { view: 'p', model: 'paragraph' } );
+			upcastHelpers.elementToElement( { view: 'h2', model: 'heading' } );
 
 			expectResult(
 				new ViewContainerElement( 'p', null, [
@@ -152,10 +136,8 @@ describe( 'upcast-helpers', () => {
 		} );
 
 		it( 'should not do anything if returned model element is null', () => {
-			const helperA = _upcastElementToElement( { view: 'p', model: 'paragraph' } );
-			const helperB = _upcastElementToElement( { view: 'p', model: () => null, converterPriority: 'high' } );
-
-			conversion.for( 'upcast' ).add( helperA ).add( helperB );
+			upcastHelpers.elementToElement( { view: 'p', model: 'paragraph' } );
+			upcastHelpers.elementToElement( { view: 'p', model: () => null, converterPriority: 'high' } );
 
 			expectResult( new ViewContainerElement( 'p' ), '<paragraph></paragraph>' );
 		} );
@@ -163,9 +145,7 @@ describe( 'upcast-helpers', () => {
 
 	describe( '_upcastElementToAttribute', () => {
 		it( 'config.view is string', () => {
-			const helper = _upcastElementToAttribute( { view: 'strong', model: 'bold' } );
-
-			conversion.for( 'upcast' ).add( helper );
+			upcastHelpers.elementToAttribute( { view: 'strong', model: 'bold' } );
 
 			expectResult(
 				new ViewAttributeElement( 'strong', null, new ViewText( 'foo' ) ),
@@ -174,10 +154,8 @@ describe( 'upcast-helpers', () => {
 		} );
 
 		it( 'can be overwritten using converterPriority', () => {
-			const helperA = _upcastElementToAttribute( { view: 'strong', model: 'strong' } );
-			const helperB = _upcastElementToAttribute( { view: 'strong', model: 'bold', converterPriority: 'high' } );
-
-			conversion.for( 'upcast' ).add( helperA ).add( helperB );
+			upcastHelpers.elementToAttribute( { view: 'strong', model: 'strong' } );
+			upcastHelpers.elementToAttribute( { view: 'strong', model: 'bold', converterPriority: 'high' } );
 
 			expectResult(
 				new ViewAttributeElement( 'strong', null, new ViewText( 'foo' ) ),
@@ -186,7 +164,7 @@ describe( 'upcast-helpers', () => {
 		} );
 
 		it( 'config.view is an object', () => {
-			const helper = _upcastElementToAttribute( {
+			upcastHelpers.elementToAttribute( {
 				view: {
 					name: 'span',
 					classes: 'bold'
@@ -194,8 +172,6 @@ describe( 'upcast-helpers', () => {
 				model: 'bold'
 			} );
 
-			conversion.for( 'upcast' ).add( helper );
-
 			expectResult(
 				new ViewAttributeElement( 'span', { class: 'bold' }, new ViewText( 'foo' ) ),
 				'<$text bold="true">foo</$text>'
@@ -209,7 +185,7 @@ describe( 'upcast-helpers', () => {
 				allowAttributes: [ 'styled' ]
 			} );
 
-			const helper = _upcastElementToAttribute( {
+			upcastHelpers.elementToAttribute( {
 				view: {
 					name: 'span',
 					classes: [ 'styled', 'styled-dark' ]
@@ -220,8 +196,6 @@ describe( 'upcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'upcast' ).add( helper );
-
 			expectResult(
 				new ViewAttributeElement( 'span', { class: 'styled styled-dark' }, new ViewText( 'foo' ) ),
 				'<$text styled="dark">foo</$text>'
@@ -235,7 +209,7 @@ describe( 'upcast-helpers', () => {
 				allowAttributes: [ 'fontSize' ]
 			} );
 
-			const helper = _upcastElementToAttribute( {
+			upcastHelpers.elementToAttribute( {
 				view: {
 					name: 'span',
 					styles: {
@@ -259,8 +233,6 @@ describe( 'upcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'upcast' ).add( helper );
-
 			expectResult(
 				new ViewAttributeElement( 'span', { style: 'font-size:9px' }, new ViewText( 'foo' ) ),
 				'<$text fontSize="small">foo</$text>'
@@ -278,9 +250,7 @@ describe( 'upcast-helpers', () => {
 		} );
 
 		it( 'should not set an attribute if it is not allowed by schema', () => {
-			const helper = _upcastElementToAttribute( { view: 'em', model: 'italic' } );
-
-			conversion.for( 'upcast' ).add( helper );
+			upcastHelpers.elementToAttribute( { view: 'em', model: 'italic' } );
 
 			expectResult(
 				new ViewAttributeElement( 'em', null, new ViewText( 'foo' ) ),
@@ -289,8 +259,8 @@ describe( 'upcast-helpers', () => {
 		} );
 
 		it( 'should not do anything if returned model attribute is null', () => {
-			const helperA = _upcastElementToAttribute( { view: 'strong', model: 'bold' } );
-			const helperB = _upcastElementToAttribute( {
+			upcastHelpers.elementToAttribute( { view: 'strong', model: 'bold' } );
+			upcastHelpers.elementToAttribute( {
 				view: 'strong',
 				model: {
 					key: 'bold',
@@ -299,8 +269,6 @@ describe( 'upcast-helpers', () => {
 				converterPriority: 'high'
 			} );
 
-			conversion.for( 'upcast' ).add( helperA ).add( helperB );
-
 			expectResult(
 				new ViewAttributeElement( 'strong', null, new ViewText( 'foo' ) ),
 				'<$text bold="true">foo</$text>'
@@ -308,18 +276,16 @@ describe( 'upcast-helpers', () => {
 		} );
 
 		it( 'should allow two converters to convert attributes on the same element', () => {
-			const helperA = _upcastElementToAttribute( {
+			upcastHelpers.elementToAttribute( {
 				model: 'attribA',
 				view: { name: 'span', classes: 'attrib-a' }
 			} );
 
-			const helperB = _upcastElementToAttribute( {
+			upcastHelpers.elementToAttribute( {
 				model: 'attribB',
 				view: { name: 'span', styles: { color: 'attrib-b' } }
 			} );
 
-			conversion.for( 'upcast' ).add( helperA ).add( helperB );
-
 			expectResult(
 				new ViewAttributeElement( 'span', { class: 'attrib-a', style: 'color:attrib-b;' }, new ViewText( 'foo' ) ),
 				'<$text attribA="true" attribB="true">foo</$text>'
@@ -327,23 +293,21 @@ describe( 'upcast-helpers', () => {
 		} );
 
 		it( 'should consume element only when only is name specified', () => {
-			const helperBold = _upcastElementToAttribute( {
+			upcastHelpers.elementToAttribute( {
 				model: 'bold',
 				view: { name: 'strong' }
 			} );
 
-			const helperA = _upcastElementToAttribute( {
+			upcastHelpers.elementToAttribute( {
 				model: 'attribA',
 				view: { name: 'strong' }
 			} );
 
-			const helperB = _upcastElementToAttribute( {
+			upcastHelpers.elementToAttribute( {
 				model: 'attribB',
 				view: { name: 'strong', classes: 'foo' }
 			} );
 
-			conversion.for( 'upcast' ).add( helperBold ).add( helperA ).add( helperB );
-
 			expectResult(
 				new ViewAttributeElement( 'strong', { class: 'foo' }, new ViewText( 'foo' ) ),
 				'<$text attribB="true" bold="true">foo</$text>'
@@ -352,14 +316,12 @@ describe( 'upcast-helpers', () => {
 
 		// #1443.
 		it( 'should set attributes on the element\'s children', () => {
-			const helperBold = _upcastElementToAttribute( {
+			upcastHelpers.elementToAttribute( {
 				model: 'bold',
 				view: { name: 'strong' }
 			} );
 
-			const helperP = _upcastElementToElement( { view: 'p', model: 'paragraph' } );
-
-			conversion.for( 'upcast' ).add( helperP ).add( helperBold );
+			upcastHelpers.elementToElement( { view: 'p', model: 'paragraph' } );
 
 			expectResult(
 				new ViewAttributeElement(
@@ -374,7 +336,7 @@ describe( 'upcast-helpers', () => {
 
 	describe( '_upcastAttributeToAttribute', () => {
 		beforeEach( () => {
-			conversion.for( 'upcast' ).add( _upcastElementToElement( { view: 'img', model: 'image' } ) );
+			upcastHelpers.elementToElement( { view: 'img', model: 'image' } );
 
 			schema.register( 'image', {
 				inheritAllFrom: '$block'
@@ -386,9 +348,7 @@ describe( 'upcast-helpers', () => {
 				allowAttributes: [ 'source' ]
 			} );
 
-			const helper = _upcastAttributeToAttribute( { view: 'src', model: 'source' } );
-
-			conversion.for( 'upcast' ).add( helper );
+			upcastHelpers.attributeToAttribute( { view: 'src', model: 'source' } );
 
 			expectResult(
 				new ViewAttributeElement( 'img', { src: 'foo.jpg' } ),
@@ -401,9 +361,7 @@ describe( 'upcast-helpers', () => {
 				allowAttributes: [ 'source' ]
 			} );
 
-			const helper = _upcastAttributeToAttribute( { view: { key: 'src' }, model: 'source' } );
-
-			conversion.for( 'upcast' ).add( helper );
+			upcastHelpers.attributeToAttribute( { view: { key: 'src' }, model: 'source' } );
 
 			expectResult(
 				new ViewAttributeElement( 'img', { src: 'foo.jpg' } ),
@@ -416,9 +374,7 @@ describe( 'upcast-helpers', () => {
 				allowAttributes: [ 'source' ]
 			} );
 
-			const helper = _upcastAttributeToAttribute( { view: { name: 'img', key: 'src' }, model: { name: 'image', key: 'source' } } );
-
-			conversion.for( 'upcast' ).add( helper );
+			upcastHelpers.attributeToAttribute( { view: { name: 'img', key: 'src' }, model: { name: 'image', key: 'source' } } );
 
 			expectResult(
 				new ViewAttributeElement( 'img', { src: 'foo.jpg' } ),
@@ -431,10 +387,8 @@ describe( 'upcast-helpers', () => {
 				allowAttributes: [ 'src', 'source' ]
 			} );
 
-			const helperA = _upcastAttributeToAttribute( { view: { key: 'src' }, model: 'src' } );
-			const helperB = _upcastAttributeToAttribute( { view: { key: 'src' }, model: 'source', converterPriority: 'normal' } );
-
-			conversion.for( 'upcast' ).add( helperA ).add( helperB );
+			upcastHelpers.attributeToAttribute( { view: { key: 'src' }, model: 'src' } );
+			upcastHelpers.attributeToAttribute( { view: { key: 'src' }, model: 'source', converterPriority: 'normal' } );
 
 			expectResult(
 				new ViewAttributeElement( 'img', { src: 'foo.jpg' } ),
@@ -447,7 +401,7 @@ describe( 'upcast-helpers', () => {
 				allowAttributes: [ 'styled' ]
 			} );
 
-			const helper = _upcastAttributeToAttribute( {
+			upcastHelpers.attributeToAttribute( {
 				view: {
 					key: 'data-style',
 					value: /[\s\S]*/
@@ -455,8 +409,6 @@ describe( 'upcast-helpers', () => {
 				model: 'styled'
 			} );
 
-			conversion.for( 'upcast' ).add( helper );
-
 			expectResult(
 				new ViewAttributeElement( 'img', { 'data-style': 'dark' } ),
 				'<image styled="dark"></image>'
@@ -468,7 +420,7 @@ describe( 'upcast-helpers', () => {
 				allowAttributes: [ 'styled' ]
 			} );
 
-			const helper = _upcastAttributeToAttribute( {
+			upcastHelpers.attributeToAttribute( {
 				view: {
 					name: 'img',
 					key: 'class',
@@ -480,9 +432,7 @@ describe( 'upcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'upcast' )
-				.add( helper )
-				.add( _upcastElementToElement( { view: 'p', model: 'paragraph' } ) );
+			upcastHelpers.elementToElement( { view: 'p', model: 'paragraph' } );
 
 			expectResult(
 				new ViewContainerElement( 'img', { class: 'styled-dark' } ),
@@ -505,7 +455,7 @@ describe( 'upcast-helpers', () => {
 				allowAttributes: [ 'styled' ]
 			} );
 
-			const helper = _upcastAttributeToAttribute( {
+			upcastHelpers.attributeToAttribute( {
 				view: {
 					key: 'class',
 					value: /styled-[\S]+/
@@ -521,8 +471,6 @@ describe( 'upcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'upcast' ).add( helper );
-
 			expectResult(
 				new ViewAttributeElement( 'img', { 'class': 'styled-dark' } ),
 				'<image styled="dark"></image>'
@@ -530,9 +478,7 @@ describe( 'upcast-helpers', () => {
 		} );
 
 		it( 'should not set an attribute if it is not allowed by schema', () => {
-			const helper = _upcastAttributeToAttribute( { view: 'src', model: 'source' } );
-
-			conversion.for( 'upcast' ).add( helper );
+			upcastHelpers.attributeToAttribute( { view: 'src', model: 'source' } );
 
 			expectResult(
 				new ViewAttributeElement( 'img', { src: 'foo.jpg' } ),
@@ -545,7 +491,7 @@ describe( 'upcast-helpers', () => {
 				allowAttributes: [ 'styled' ]
 			} );
 
-			const helperA = _upcastAttributeToAttribute( {
+			upcastHelpers.attributeToAttribute( {
 				view: {
 					key: 'class',
 					value: 'styled'
@@ -556,7 +502,7 @@ describe( 'upcast-helpers', () => {
 				}
 			} );
 
-			const helperB = _upcastAttributeToAttribute( {
+			upcastHelpers.attributeToAttribute( {
 				view: {
 					key: 'class',
 					value: 'styled'
@@ -567,8 +513,6 @@ describe( 'upcast-helpers', () => {
 				}
 			} );
 
-			conversion.for( 'upcast' ).add( helperA ).add( helperB );
-
 			expectResult(
 				new ViewAttributeElement( 'img', { class: 'styled' } ),
 				'<image styled="true"></image>'
@@ -584,13 +528,10 @@ describe( 'upcast-helpers', () => {
 				allowAttributes: [ 'border', 'shade' ]
 			} );
 
-			conversion.for( 'upcast' ).add( _upcastElementToElement( { view: 'div', model: 'div' } ) );
+			upcastHelpers.elementToElement( { view: 'div', model: 'div' } );
 
-			const shadeHelper = _upcastAttributeToAttribute( { view: { key: 'class', value: 'shade' }, model: 'shade' } );
-			const borderHelper = _upcastAttributeToAttribute( { view: { key: 'class', value: 'border' }, model: 'border' } );
-
-			conversion.for( 'upcast' ).add( shadeHelper );
-			conversion.for( 'upcast' ).add( borderHelper );
+			upcastHelpers.attributeToAttribute( { view: { key: 'class', value: 'shade' }, model: 'shade' } );
+			upcastHelpers.attributeToAttribute( { view: { key: 'class', value: 'border' }, model: 'border' } );
 
 			expectResult(
 				new ViewContainerElement(
@@ -605,9 +546,7 @@ describe( 'upcast-helpers', () => {
 
 	describe( '_upcastElementToMarker', () => {
 		it( 'config.view is a string', () => {
-			const helper = _upcastElementToMarker( { view: 'marker-search', model: 'search' } );
-
-			conversion.for( 'upcast' ).add( helper );
+			upcastHelpers.elementToMarker( { view: 'marker-search', model: 'search' } );
 
 			const frag = new ViewDocumentFragment( [
 				new ViewText( 'fo' ),
@@ -623,10 +562,8 @@ describe( 'upcast-helpers', () => {
 		} );
 
 		it( 'can be overwritten using converterPriority', () => {
-			const helperA = _upcastElementToMarker( { view: 'marker-search', model: 'search-result' } );
-			const helperB = _upcastElementToMarker( { view: 'marker-search', model: 'search', converterPriority: 'high' } );
-
-			conversion.for( 'upcast' ).add( helperA ).add( helperB );
+			upcastHelpers.elementToMarker( { view: 'marker-search', model: 'search-result' } );
+			upcastHelpers.elementToMarker( { view: 'marker-search', model: 'search', converterPriority: 'high' } );
 
 			const frag = new ViewDocumentFragment( [
 				new ViewText( 'fo' ),
@@ -642,7 +579,7 @@ describe( 'upcast-helpers', () => {
 		} );
 
 		it( 'config.view is an object', () => {
-			const helper = _upcastElementToMarker( {
+			upcastHelpers.elementToMarker( {
 				view: {
 					name: 'span',
 					'data-marker': 'search'
@@ -650,8 +587,6 @@ describe( 'upcast-helpers', () => {
 				model: 'search'
 			} );
 
-			conversion.for( 'upcast' ).add( helper );
-
 			const frag = new ViewDocumentFragment( [
 				new ViewText( 'f' ),
 				new ViewUIElement( 'span', { 'data-marker': 'search' } ),
@@ -666,13 +601,11 @@ describe( 'upcast-helpers', () => {
 		} );
 
 		it( 'config.model is a function', () => {
-			const helper = _upcastElementToMarker( {
+			upcastHelpers.elementToMarker( {
 				view: 'comment',
 				model: viewElement => 'comment:' + viewElement.getAttribute( 'data-comment-id' )
 			} );
 
-			conversion.for( 'upcast' ).add( helper );
-
 			const frag = new ViewDocumentFragment( [
 				new ViewText( 'foo' ),
 				new ViewUIElement( 'comment', { 'data-comment-id': 4 } ),
@@ -687,11 +620,9 @@ describe( 'upcast-helpers', () => {
 		} );
 
 		it( 'marker is in a block element', () => {
-			conversion.for( 'upcast' ).add( _upcastElementToElement( { model: 'paragraph', view: 'p' } ) );
-
-			const helper = _upcastElementToMarker( { view: 'marker-search', model: 'search' } );
+			upcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
-			conversion.for( 'upcast' ).add( helper );
+			upcastHelpers.elementToMarker( { view: 'marker-search', model: 'search' } );
 
 			const element = new ViewContainerElement( 'p', null, [
 				new ViewText( 'fo' ),