Explorar el Código

Improved insert and remove UIElement to handle collapsed and non-collapsed ranges.

Oskar Wróbel hace 9 años
padre
commit
46800c5e9c

+ 6 - 2
packages/ckeditor5-engine/src/conversion/model-to-view-converters.js

@@ -113,9 +113,13 @@ export function insertUIElement( elementCreator ) {
 			return;
 		}
 
-		const viewPosition = conversionApi.mapper.toViewPosition( data.range.start );
+		const mapper = conversionApi.mapper;
 
-		viewWriter.insert( viewPosition, viewElement );
+		viewWriter.insert( mapper.toViewPosition( data.range.start ), viewElement );
+
+		if ( !data.range.isCollapsed ) {
+			viewWriter.insert( mapper.toViewPosition( data.range.end ), viewElement.clone( true ) );
+		}
 	};
 }
 

+ 92 - 0
packages/ckeditor5-engine/tests/conversion/model-to-view-converters.js

@@ -771,6 +771,98 @@ describe( 'model-to-view-converters', () => {
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
 			expect( dispatcher.fire.calledWith( 'removeMarker:marker' ) );
 		} );
+
+		it( 'should not convert or consume if generator function returned null', () => {
+			const viewUi = () => null;
+
+			sinon.spy( dispatcher, 'fire' );
+
+			dispatcher.on( 'addMarker:marker', insertUIElement( viewUi ) );
+			dispatcher.on( 'removeMarker:marker', removeUIElement( viewUi ) );
+
+			dispatcher.on( 'addMarker:marker', ( evt, data, consumable ) => {
+				expect( consumable.test( data.range, 'addMarker' ) ).to.be.true;
+			} );
+
+			dispatcher.on( 'removeMarker:marker', ( evt, data, consumable ) => {
+				expect( consumable.test( data.range, 'removeMarker' ) ).to.be.true;
+			} );
+
+			dispatcher.convertMarker( 'addMarker', 'marker', range );
+
+			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+			expect( dispatcher.fire.calledWith( 'addMarker:marker' ) );
+
+			dispatcher.convertMarker( 'removeMarker', 'marker', range );
+
+			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+			expect( dispatcher.fire.calledWith( 'removeMarker:marker' ) );
+		} );
+
+		it( 'should be possible to overwrite', () => {
+			const viewUi = new ViewUIElement( 'span', { 'class': 'marker' } );
+
+			sinon.spy( dispatcher, 'fire' );
+
+			dispatcher.on( 'addMarker:marker', insertUIElement( viewUi ) );
+			dispatcher.on( 'removeMarker:marker', removeUIElement( viewUi ) );
+
+			dispatcher.on( 'addMarker:marker', ( evt, data, consumable ) => {
+				consumable.consume( data.range, 'addMarker' );
+			}, { priority: 'high' } );
+
+			dispatcher.on( 'removeMarker:marker', ( evt, data, consumable ) => {
+				consumable.consume( data.range, 'removeMarker' );
+			}, { priority: 'high' } );
+
+			dispatcher.convertMarker( 'addMarker', 'marker', range );
+
+			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+			expect( dispatcher.fire.calledWith( 'addMarker:marker' ) );
+
+			dispatcher.convertMarker( 'removeMarker', 'marker', range );
+
+			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+			expect( dispatcher.fire.calledWith( 'removeMarker:marker' ) );
+		} );
+
+		describe( 'non-collapsed range', () => {
+			beforeEach( () => {
+				range = ModelRange.createFromParentsAndOffsets( modelElement, 2, modelElement, 5 );
+			} );
+
+			it( 'should insert and remove ui element - element as a creator', () => {
+				const viewUi = new ViewUIElement( 'span', { 'class': 'marker' } );
+
+				dispatcher.on( 'addMarker:marker', insertUIElement( viewUi ) );
+				dispatcher.on( 'removeMarker:marker', removeUIElement( viewUi ) );
+
+				dispatcher.convertMarker( 'addMarker', 'marker', range );
+
+				expect( viewToString( viewRoot ) )
+					.to.equal( '<div><p>fo<span class="marker"></span>oba<span class="marker"></span>r</p></div>' );
+
+				dispatcher.convertMarker( 'removeMarker', 'marker', range );
+
+				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+			} );
+
+			it( 'should insert and remove ui element - function as a creator', () => {
+				const viewUi = ( data ) => new ViewUIElement( 'span', { 'class': data.name } );
+
+				dispatcher.on( 'addMarker:marker', insertUIElement( viewUi ) );
+				dispatcher.on( 'removeMarker:marker', removeUIElement( viewUi ) );
+
+				dispatcher.convertMarker( 'addMarker', 'marker', range );
+
+				expect( viewToString( viewRoot ) )
+					.to.equal( '<div><p>fo<span class="marker"></span>oba<span class="marker"></span>r</p></div>' );
+
+				dispatcher.convertMarker( 'removeMarker', 'marker', range );
+
+				expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
+			} );
+		} );
 	} );
 
 	describe( 'remove', () => {