浏览代码

Introduce conversion.( 'upcast' ).elementToMarker() helper.

Maciej Gołaszewski 7 年之前
父节点
当前提交
ff7b0d95fd

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

@@ -816,5 +816,45 @@ export const helpers = {
 	 */
 	attributeToAttribute( config ) {
 		return this.add( upcastAttributeToAttribute( config ) );
+	},
+
+	/**
+	 * View element to model marker conversion helper.
+	 *
+	 * This conversion results in creating a model marker. For example, if the marker was stored in a view as an element:
+	 * `<p>Fo<span data-marker="comment" data-comment-id="7"></span>o</p><p>B<span data-marker="comment" data-comment-id="7"></span>ar</p>`,
+	 * after the conversion is done, the marker will be available in
+	 * {@link module:engine/model/model~Model#markers model document markers}.
+	 *
+	 *        conversion.for( 'upcast' ).elementToMarker( { view: 'marker-search', model: 'search' } );
+	 *
+	 *        conversion.for( 'upcast' ).elementToMarker( { view: 'marker-search', model: 'search', converterPriority: 'high' } );
+	 *
+	 *        conversion.for( 'upcast' ).elementToMarker( {
+	 *			view: 'marker-search',
+	 *			model: viewElement => 'comment:' + viewElement.getAttribute( 'data-comment-id' )
+	 *		} );
+	 *
+	 *        conversion.for( 'upcast' ).elementToMarker( {
+	 *			view: {
+	 *				name: 'span',
+	 *				attributes: {
+	 *					'data-marker': 'search'
+	 *				}
+	 *			},
+	 *			model: 'search'
+	 *		} );
+	 *
+	 * See {@link module:engine/conversion/conversion~Conversion#for} to learn how to add converter to conversion process.
+	 *
+	 * @param {Object} config Conversion configuration.
+	 * @param {module:engine/view/matcher~MatcherPattern} config.view Pattern matching all view elements which should be converted.
+	 * @param {String|Function} config.model Name of the model marker, or a function that takes a view element and returns
+	 * a model marker name.
+	 * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
+	 * @returns {Function} Conversion helper.
+	 */
+	elementToMarker( config ) {
+		return this.add( upcastElementToMarker( config ) );
 	}
 };

+ 38 - 0
packages/ckeditor5-engine/tests/conversion/conversion.js

@@ -17,6 +17,9 @@ import Model from '../../src/model/model';
 import { parse as viewParse, stringify as viewStringify } from '../../src/dev-utils/view';
 import { setData, stringify as modelStringify } from '../../src/dev-utils/model';
 import { helpers as downcastHelpers } from '../../src/conversion/downcast-converters';
+import ViewDocumentFragment from '../../src/view/documentfragment';
+import ViewText from '../../src/view/text';
+import ViewUIElement from '../../src/view/uielement';
 
 describe( 'Conversion', () => {
 	let conversion, dispA, dispB;
@@ -101,6 +104,7 @@ describe( 'Conversion', () => {
 			schema = model.schema;
 
 			schema.extend( '$text', {
+				allowIn: '$root',
 				allowAttributes: [ 'bold' ]
 			} );
 
@@ -737,6 +741,25 @@ describe( 'Conversion', () => {
 					testUpcast( '<img src="foo.jpg"></img>', '<image source="foo.jpg"></image>' );
 				} );
 			} );
+
+			describe( 'markerToElement()', () => {
+				it( 'adds upcast converter', () => {
+					conversion.for( 'upcast' ).elementToMarker( { model: 'search', view: 'marker-search' } );
+					conversion.for( 'downcast' ).markerToElement( { model: 'search', view: 'marker-search' } );
+
+					const frag = new ViewDocumentFragment( [
+						new ViewText( 'fo' ),
+						new ViewUIElement( 'marker-search' ),
+						new ViewText( 'oba' ),
+						new ViewUIElement( 'marker-search' ),
+						new ViewText( 'r' )
+					] );
+
+					const marker = { name: 'search', start: [ 2 ], end: [ 5 ] };
+
+					testUpcastMarker( frag, 'foobar', marker );
+				} );
+			} );
 		} );
 
 		function testDowncast( input, expectedView ) {
@@ -774,5 +797,20 @@ describe( 'Conversion', () => {
 				writer.insert( convertedModel, modelRoot, 0 );
 			} );
 		}
+
+		function testUpcastMarker( viewToConvert, modelString, marker ) {
+			const conversionResult = model.change( writer => viewDispatcher.convert( viewToConvert, writer ) );
+
+			if ( marker ) {
+				expect( conversionResult.markers.has( marker.name ) ).to.be.true;
+
+				const convertedMarker = conversionResult.markers.get( marker.name );
+
+				expect( convertedMarker.start.path ).to.deep.equal( marker.start );
+				expect( convertedMarker.end.path ).to.deep.equal( marker.end );
+			}
+
+			expect( viewStringify( conversionResult ) ).to.equal( modelString );
+		}
 	} );
 } );