Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #1756 from ckeditor/t/ckeditor5-typing/187
Browse files Browse the repository at this point in the history
Feature: Introduced `model.Differ#refreshItem()`.
  • Loading branch information
Piotr Jasiun authored Jul 12, 2019
2 parents 52e701d + b84cf9b commit 7dc8710
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/model/differ.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,32 @@ export default class Differ {
return this._changesInElement.size == 0 && this._changedMarkers.size == 0;
}

/**
* Marks given `item` in differ to be "refreshed". It means that the item will be marked as removed and inserted in the differ changes
* set, so it will be effectively re-converted when differ changes will be handled by a dispatcher.
*
* @param {module:engine/model/item~Item} item Item to refresh.
*/
refreshItem( item ) {
if ( this._isInInsertedElement( item.parent ) ) {
return;
}

this._markRemove( item.parent, item.startOffset, item.offsetSize );
this._markInsert( item.parent, item.startOffset, item.offsetSize );

const range = Range._createOn( item );

for ( const marker of this._markerCollection.getMarkersIntersectingRange( range ) ) {
const markerRange = marker.getRange();

this.bufferMarkerChange( marker.name, markerRange, markerRange, marker.affectsData );
}

// Clear cache after each buffered operation as it is no longer valid.
this._cachedChanges = null;
}

/**
* Buffers the given operation. An operation has to be buffered before it is executed.
*
Expand Down
70 changes: 70 additions & 0 deletions tests/model/differ.js
Original file line number Diff line number Diff line change
Expand Up @@ -1759,6 +1759,76 @@ describe( 'Differ', () => {
} );
} );

describe( 'refreshItem()', () => {
it( 'should mark given element to be removed and added again', () => {
const p = root.getChild( 0 );

differ.refreshItem( p );

expectChanges( [
{ type: 'remove', name: 'paragraph', length: 1, position: model.createPositionBefore( p ) },
{ type: 'insert', name: 'paragraph', length: 1, position: model.createPositionBefore( p ) }
], true );
} );

it( 'should mark given text proxy to be removed and added again', () => {
const p = root.getChild( 0 );
const range = model.createRangeIn( p );
const textProxy = [ ...range.getItems() ][ 0 ];

differ.refreshItem( textProxy );

expectChanges( [
{ type: 'remove', name: '$text', length: 3, position: model.createPositionAt( p, 0 ) },
{ type: 'insert', name: '$text', length: 3, position: model.createPositionAt( p, 0 ) }
], true );
} );

it( 'inside a new element', () => {
// Since the refreshed element is inside a new element, it should not be listed on changes list.
model.change( () => {
insert( new Element( 'blockQuote', null, new Element( 'paragraph' ) ), new Position( root, [ 2 ] ) );

differ.refreshItem( root.getChild( 2 ).getChild( 0 ) );

expectChanges( [
{ type: 'insert', name: 'blockQuote', length: 1, position: new Position( root, [ 2 ] ) }
] );
} );
} );

it( 'markers refreshing', () => {
model.change( () => {
// Refreshed element contains marker.
model.markers._set( 'markerA', new Range( new Position( root, [ 1, 1 ] ), new Position( root, [ 1, 2 ] ) ) );

// Marker contains refreshed element.
model.markers._set( 'markerB', new Range( new Position( root, [ 0 ] ), new Position( root, [ 2 ] ) ) );

// Intersecting.
model.markers._set( 'markerC', new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 1, 2 ] ) ) );

// Not intersecting.
model.markers._set( 'markerD', new Range( new Position( root, [ 0, 0 ] ), new Position( root, [ 1 ] ) ) );
} );

const markersToRefresh = [ 'markerA', 'markerB', 'markerC' ];

differ.refreshItem( root.getChild( 1 ) );

expectChanges( [
{ type: 'remove', name: 'paragraph', length: 1, position: new Position( root, [ 1 ] ) },
{ type: 'insert', name: 'paragraph', length: 1, position: new Position( root, [ 1 ] ) }
] );

const markersToRemove = differ.getMarkersToRemove().map( entry => entry.name );
const markersToAdd = differ.getMarkersToAdd().map( entry => entry.name );

expect( markersToRefresh ).to.deep.equal( markersToRemove );
expect( markersToRefresh ).to.deep.equal( markersToAdd );
} );
} );

describe( 'getChanges()', () => {
let position, p1, rangeAttrChange, range;

Expand Down

0 comments on commit 7dc8710

Please sign in to comment.