Przeglądaj źródła

Introduce UpcastHelpers and conversion.for( 'upcast' ).elementToElement() helper.

Maciej Gołaszewski 7 lat temu
rodzic
commit
512b86194c

+ 5 - 3
packages/ckeditor5-engine/src/conversion/conversion.js

@@ -87,7 +87,8 @@ export default class Conversion {
 	 * module:engine/conversion/upcastdispatcher~UpcastDispatcher|Array.<module:engine/conversion/downcastdispatcher~DowncastDispatcher|
 	 * module:engine/conversion/upcastdispatcher~UpcastDispatcher>} options.dispatcher Dispatcher or array of dispatchers to register
 	 * under the given name.
-	 * @param {module:engine/conversion/downcast-converters~DowncastHelpers} helpers
+	 * @param {module:engine/conversion/downcast-converters~DowncastHelpers|
+	 * module:engine/conversion/upcast-converters~UpcastHelpers} helpers
 	 */
 	register( options ) {
 		if ( this._dispatchersGroups.has( options.name ) ) {
@@ -151,7 +152,8 @@ export default class Conversion {
 	 *		conversion.for( 'downcast' ).add( conversion.customConverter( 'insert:paragraph', myConverter ) );
 	 *
 	 * @param {String} groupName The name of dispatchers group to add the converters to.
-	 * @returns {module:engine/conversion/conversion~ConversionHelpers|module:engine/conversion/downcast-converters~DowncastHelpers}
+	 * @returns {module:engine/conversion/conversion~ConversionHelpers|module:engine/conversion/downcast-converters~DowncastHelpers|
+	 * module:engine/conversion/upcast-converters~UpcastHelpers}
 	 * An object with the `.add()` method, providing a way to add converters.
 	 */
 	for( groupName ) {
@@ -599,7 +601,7 @@ export default class Conversion {
  * @property {String} name Group name
  * @property {Array.<module:engine/conversion/downcastdispatcher~DowncastDispatcher|
  * module:engine/conversion/upcastdispatcher~UpcastDispatcher>} dispatchers
- * @property {module:engine/conversion/downcast-converters~DowncastHelpers} helpers
+ * @property {module:engine/conversion/downcast-converters~DowncastHelpers|module:engine/conversion/upcast-converters~UpcastHelpers} helpers
  */
 
 /**

+ 53 - 0
packages/ckeditor5-engine/src/conversion/upcast-converters.js

@@ -607,3 +607,56 @@ export function convertText() {
 		}
 	};
 }
+
+/**
+ * Upcast conversion helper functions.
+ *
+ * @interface module:engine/conversion/upcast-converters~UpcastHelpers
+ * @extends module:engine/conversion/conversion~ConversionHelpers
+ */
+export const helpers = {
+	/**
+	 * View element to model element conversion helper.
+	 *
+	 * This conversion results in creating a model element. For example,
+	 * view `<p>Foo</p>` becomes `<paragraph>Foo</paragraph>` in the model.
+	 *
+	 * Keep in mind that the element will be inserted only if it is allowed
+	 * by {@link module:engine/model/schema~Schema schema} configuration.
+	 *
+	 *		conversion.for( 'upcast' ).elementToElement( { view: 'p', model: 'paragraph' } );
+	 *
+	 *		conversion.for( 'upcast' ).elementToElement( { view: 'p', model: 'paragraph', converterPriority: 'high' } );
+	 *
+	 *		conversion.for( 'upcast' ).elementToElement( {
+	 *			view: {
+	 *				name: 'p',
+	 *				classes: 'fancy'
+	 *			},
+	 *			model: 'fancyParagraph'
+	 *		} );
+	 *
+	 *		conversion.for( 'upcast' ).elementToElement( {
+	 * 			view: {
+	 *				name: 'p',
+	 *				classes: 'heading'
+	 * 			},
+	 * 			model: ( viewElement, modelWriter ) => {
+	 * 				return modelWriter.createElement( 'heading', { level: viewElement.getAttribute( 'data-level' ) } );
+	 * 			}
+	 * 		} );
+	 *
+	 * See {@link module:engine/conversion/conversion~Conversion#for} to learn how to add converter to conversion process.
+	 *
+	 * @method #elementToElement
+	 * @param {Object} config Conversion configuration.
+	 * @param {module:engine/view/matcher~MatcherPattern} config.view Pattern matching all view elements which should be converted.
+	 * @param {String|module:engine/model/element~Element|Function} config.model Name of the model element, a model element
+	 * instance or a function that takes a view element and returns a model element. The model element will be inserted in the model.
+	 * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
+	 * @returns {Function} Conversion helper.
+	 */
+	elementToElement( config ) {
+		return this.add( upcastElementToElement( config ) );
+	}
+};

+ 20 - 2
packages/ckeditor5-engine/tests/conversion/conversion.js

@@ -8,7 +8,7 @@ import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 
 import UpcastDispatcher from '../../src/conversion/upcastdispatcher';
 
-import { convertText, convertToModelFragment } from '../../src/conversion/upcast-converters';
+import { helpers as upcastHelpers, convertText, convertToModelFragment } from '../../src/conversion/upcast-converters';
 
 import EditingController from '../../src/controller/editingcontroller';
 
@@ -114,7 +114,7 @@ describe( 'Conversion', () => {
 			viewDispatcher.on( 'documentFragment', convertToModelFragment(), { priority: 'lowest' } );
 
 			conversion = new Conversion();
-			conversion.register( { name: 'upcast', dispatcher: [ viewDispatcher ] } );
+			conversion.register( { name: 'upcast', dispatcher: [ viewDispatcher ], helpers: upcastHelpers } );
 			conversion.register( { name: 'downcast', dispatcher: [ controller.downcastDispatcher ], helpers: downcastHelpers } );
 		} );
 
@@ -698,12 +698,30 @@ describe( 'Conversion', () => {
 			} );
 		} );
 
+		describe( 'for( \'upcast\' )', () => {
+			describe( 'elementToElement()', () => {
+				it( 'adds downcast converter', () => {
+					conversion.for( 'upcast' ).elementToElement( { model: 'paragraph', view: 'p' } );
+					// TODO this shouldn't be required
+					conversion.for( 'downcast' ).elementToElement( { model: 'paragraph', view: 'p' } );
+
+					testUpcast( '<p>foo</p>', '<paragraph>foo</paragraph>' );
+				} );
+			} );
+		} );
+
 		function testDowncast( input, expectedView ) {
 			setData( model, input );
 
 			expect( viewStringify( viewRoot, null, { ignoreRoot: true } ) ).to.equal( expectedView );
 		}
 
+		function testUpcast( input, expectedModel ) {
+			loadData( input );
+
+			expect( modelStringify( model.document.getRoot() ) ).to.equal( expectedModel );
+		}
+
 		function test( input, expectedModel, expectedView = null ) {
 			loadData( input );