Ver código fonte

Handle remove when converting refresh change.

Maciej Gołaszewski 5 anos atrás
pai
commit
a8ab01154f

+ 29 - 3
packages/ckeditor5-engine/src/conversion/downcastdispatcher.js

@@ -135,6 +135,8 @@ export default class DowncastDispatcher {
 	convertChanges( differ, markers, writer ) {
 		const changes1 = differ.getChanges();
 
+		const mapRefreshedBy = new Map();
+
 		const found = [ ...changes1 ]
 			.filter( ( { type } ) => type === 'attribute' || type === 'insert' || type === 'remove' )
 			.map( entry => {
@@ -150,10 +152,22 @@ export default class DowncastDispatcher {
 					eventName = `${ type }:${ entry.name }`;
 				}
 
+				// @if CK_DEBUG console.log( 'expected event', eventName );
+
 				if ( this._map.has( eventName ) ) {
 					const expectedElement = this._map.get( eventName );
 
-					return element.is( 'element', expectedElement ) ? element : element.findAncestor( expectedElement );
+					const handledByParent = element.is( 'element', expectedElement ) ? element : element.findAncestor( expectedElement );
+
+					// @if CK_DEBUG console.log( `return: ${ handledByParent.name }` );
+
+					if ( handledByParent ) {
+						mapRefreshedBy.set( element, handledByParent );
+					}
+
+					return handledByParent;
+				} else {
+					// @if CK_DEBUG console.log( 'no event in map' );
 				}
 				// TODO: lacking API - handle inner change of given event. Either by:
 				// - a) differ API (mark change as invalid)
@@ -170,10 +184,16 @@ export default class DowncastDispatcher {
 			this.convertMarkerRemove( change.name, change.range, writer );
 		}
 
-		const changes = differ.getChanges();
+		const changes = differ.getChanges().filter( entry => {
+			const { range, position } = entry;
+			const element = range && range.start.nodeAfter || position && position.parent;
+
+			return !mapRefreshedBy.has( element );
+		} );
 
 		// Convert changes that happened on model tree.
 		for ( const entry of changes ) {
+			// @if CK_DEBUG console.log( `ENTRY: ${ entry.type }` );
 			if ( entry.type == 'insert' ) {
 				this.convertInsert( Range._createFromPositionAndShift( entry.position, entry.length ), writer );
 			} else if ( entry.type == 'remove' ) {
@@ -316,6 +336,7 @@ export default class DowncastDispatcher {
 				isRefresh: true
 			};
 
+			// @if CK_DEBUG console.log( 'converting refresh -> insert', item.name );
 			this._testAndFire( 'insert', data );
 		}
 
@@ -536,13 +557,18 @@ export default class DowncastDispatcher {
 	 */
 	_testAndFire( type, data ) {
 		if ( !this.conversionApi.consumable.test( data.item, type ) ) {
+			// @if CK_DEBUG console.log( ' > already consumed' );
 			// Do not fire event if the item was consumed.
 			return;
 		}
 
 		const name = data.item.name || '$text';
 
-		this.fire( type + ':' + name, data, this.conversionApi );
+		const eventName = `${ type }:${ name }`;
+
+		// @if CK_DEBUG console.log( 'Firing event', eventName );
+
+		this.fire( eventName, data, this.conversionApi );
 	}
 
 	/**

+ 40 - 32
packages/ckeditor5-engine/tests/conversion/downcasthelpers.js

@@ -38,6 +38,14 @@ import { expectToThrowCKEditorError } from '@ckeditor/ckeditor5-utils/tests/_uti
 import { StylesProcessor } from '../../src/view/stylesmap';
 import DowncastWriter from '../../src/view/downcastwriter';
 
+function insertBazSlot( writer, modelRoot ) {
+	const slot = writer.createElement( 'slot' );
+	const paragraph = writer.createElement( 'paragraph' );
+	writer.insertText( 'baz', paragraph, 0 );
+	writer.insert( paragraph, slot, 0 );
+	writer.insert( slot, modelRoot.getChild( 0 ), 'end' );
+}
+
 describe( 'DowncastHelpers', () => {
 	let model, modelRoot, viewRoot, downcastHelpers, controller, modelRootStart;
 
@@ -502,25 +510,21 @@ describe( 'DowncastHelpers', () => {
 				it( 'should convert element on adding slot', () => {
 					setModelData( model,
 						'<complex>' +
-						'<slot><paragraph>foo</paragraph></slot>' +
-						'<slot><paragraph>bar</paragraph></slot>' +
+							'<slot><paragraph>foo</paragraph></slot>' +
+							'<slot><paragraph>bar</paragraph></slot>' +
 						'</complex>' );
 
 					model.change( writer => {
-						const slot = writer.createElement( 'slot' );
-						const paragraph = writer.createElement( 'paragraph' );
-						writer.insertText( 'baz', paragraph, 0 );
-						writer.insert( paragraph, slot, 0 );
-						writer.insert( slot, modelRoot.getChild( 0 ), 'end' );
+						insertBazSlot( writer, modelRoot );
 					} );
 
 					expectResult(
 						'<div class="complex-slots">' +
-						'<div class="slots">' +
-						'<div class="slot"><p>foo</p></div>' +
-						'<div class="slot"><p>bar</p></div>' +
-						'<div class="slot"><p>baz</p></div>' +
-						'</div>' +
+							'<div class="slots">' +
+								'<div class="slot"><p>foo</p></div>' +
+								'<div class="slot"><p>bar</p></div>' +
+								'<div class="slot"><p>baz</p></div>' +
+							'</div>' +
 						'</div>'
 					);
 				} );
@@ -532,15 +536,17 @@ describe( 'DowncastHelpers', () => {
 							'<slot><paragraph>bar</paragraph></slot>' +
 						'</complex>' );
 
+					console.log( '---- change:' );
+
 					model.change( writer => {
 						writer.remove( modelRoot.getChild( 0 ).getChild( 0 ) );
 					} );
 
 					expectResult(
 						'<div class="complex-slots">' +
-						'<div class="slots">' +
-						'<div class="slot"><p>foo</p></div>' +
-						'</div>' +
+							'<div class="slots">' +
+								'<div class="slot"><p>bar</p></div>' +
+							'</div>' +
 						'</div>'
 					);
 				} );
@@ -548,20 +554,21 @@ describe( 'DowncastHelpers', () => {
 				it( 'should convert element on multiple triggers (remove + insert)', () => {
 					setModelData( model,
 						'<complex>' +
-						'<slot><paragraph>foo</paragraph></slot>' +
-						'<slot><paragraph>bar</paragraph></slot>' +
+							'<slot><paragraph>foo</paragraph></slot>' +
+							'<slot><paragraph>bar</paragraph></slot>' +
 						'</complex>' );
 
 					model.change( writer => {
 						writer.remove( modelRoot.getChild( 0 ).getChild( 0 ) );
-						writer.insert( modelRoot.getChild( 0 ).getChild( 0 ) );
+						insertBazSlot( writer, modelRoot );
 					} );
 
 					expectResult(
 						'<div class="complex-slots">' +
-						'<div class="slots">' +
-						'<div class="slot"><p>foo</p></div>' +
-						'</div>' +
+							'<div class="slots">' +
+								'<div class="slot"><p>foo</p></div>' +
+								'<div class="slot"><p>baz</p></div>' +
+							'</div>' +
 						'</div>'
 					);
 				} );
@@ -569,8 +576,8 @@ describe( 'DowncastHelpers', () => {
 				it( 'should convert element on multiple triggers (remove + attribute)', () => {
 					setModelData( model,
 						'<complex>' +
-						'<slot><paragraph>foo</paragraph></slot>' +
-						'<slot><paragraph>bar</paragraph></slot>' +
+							'<slot><paragraph>foo</paragraph></slot>' +
+							'<slot><paragraph>bar</paragraph></slot>' +
 						'</complex>' );
 
 					model.change( writer => {
@@ -580,9 +587,9 @@ describe( 'DowncastHelpers', () => {
 
 					expectResult(
 						'<div class="complex-slots with-class">' +
-						'<div class="slots">' +
-						'<div class="slot"><p>foo</p></div>' +
-						'</div>' +
+							'<div class="slots">' +
+								'<div class="slot"><p>foo</p></div>' +
+							'</div>' +
 						'</div>'
 					);
 				} );
@@ -590,20 +597,21 @@ describe( 'DowncastHelpers', () => {
 				it( 'should convert element on multiple triggers (insert + attribute)', () => {
 					setModelData( model,
 						'<complex>' +
-						'<slot><paragraph>foo</paragraph></slot>' +
-						'<slot><paragraph>bar</paragraph></slot>' +
+							'<slot><paragraph>foo</paragraph></slot>' +
+							'<slot><paragraph>bar</paragraph></slot>' +
 						'</complex>' );
 
 					model.change( writer => {
-						writer.insert( modelRoot.getChild( 0 ).getChild( 0 ) );
+						insertBazSlot( writer, modelRoot );
 						writer.setAttribute( 'classForMain', true, modelRoot.getChild( 0 ) );
 					} );
 
 					expectResult(
 						'<div class="complex-slots with-class">' +
-						'<div class="slots">' +
-						'<div class="slot"><p>foo</p></div>' +
-						'</div>' +
+							'<div class="slots">' +
+								'<div class="slot"><p>foo</p></div>' +
+								'<div class="slot"><p>baz</p></div>' +
+							'</div>' +
 						'</div>'
 					);
 				} );