8
0
Просмотр исходного кода

Change how the downcast dispatcher handles triggerBy attribute for refreshing.

Maciej Gołaszewski 5 лет назад
Родитель
Сommit
0f59a7a8f1
1 измененных файлов с 21 добавлено и 34 удалено
  1. 21 34
      packages/ckeditor5-engine/src/conversion/downcastdispatcher.js

+ 21 - 34
packages/ckeditor5-engine/src/conversion/downcastdispatcher.js

@@ -11,6 +11,7 @@ import Consumable from './modelconsumable';
 import Range from '../model/range';
 import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
+import Position from '../model/position';
 
 /**
  * Downcast dispatcher is a central point of downcasting (conversion from the model to the view), which is a process of reacting to changes
@@ -586,38 +587,10 @@ export default class DowncastDispatcher {
 	 */
 	_getChangesAfterAutomaticRefreshing( differ ) {
 		const changes = differ.getChanges();
-		const elementsToRefresh = this._getElementsForAutomaticRefresh( changes );
 
-		if ( !elementsToRefresh.size ) {
-			return changes;
-		}
-
-		for ( const element of elementsToRefresh.values() ) {
-			differ.refreshItem( element );
-		}
+		const refreshedItems = new Set();
 
-		// The `differ.refreshItem()` invalidates differ cache - we can't re-use previous changes.
-		const changesAfterRefresh = differ.getChanges();
-
-		return changesAfterRefresh.filter( entry => !elementsToRefresh.has( getElementFromChange( entry ) ) );
-	}
-
-	/**
-	 * Returns elements that should be converted using {@link #convertRefresh} defined by a `triggerBy` configuration for
-	 * {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`} conversion helper.
-	 *
-	 * This will return:
-	 *
-	 * * Element which attributes changed for an 'attribute' change.
-	 * * Parent of inserted or removed element for matched 'insert' or 'remove' changes.
-	 *
-	 * @param {Array.<Object>} changes The changes diff set from the differ.
-	 * @returns {Set.<module:engine/model/element~Element>}
-	 * @private
-	 */
-	_getElementsForAutomaticRefresh( changes ) {
-		const found = changes
-			.filter( ( { type } ) => type === 'attribute' || type === 'insert' || type === 'remove' )
+		const updated = changes
 			.map( entry => {
 				const element = getElementFromChange( entry );
 
@@ -626,7 +599,7 @@ export default class DowncastDispatcher {
 				if ( entry.type === 'attribute' ) {
 					if ( !element ) {
 						// Refreshing is done only on elements so skip text attribute changes.
-						return;
+						return entry;
 					}
 
 					eventName = `attribute:${ entry.attributeKey }:${ element.name }`;
@@ -635,12 +608,26 @@ export default class DowncastDispatcher {
 				}
 
 				if ( this._isRefreshTriggerEvent( eventName, element.name ) ) {
-					return element;
+					if ( refreshedItems.has( element ) ) {
+						return null;
+					}
+
+					refreshedItems.add( element );
+
+					return {
+						type: 'refresh',
+						position: Position._createBefore( element ),
+						name: element.name,
+						length: 1
+					};
 				}
+
+				return entry;
 			} )
-			.filter( element => !!element );
+			// TODO: could be done in for...of loop or using reduce to not run double loop on big diffsets.
+			.filter( entry => !!entry );
 
-		return new Set( found );
+		return updated;
 	}
 
 	/**