From 031b96dd2a4f1ce640701bb56c49ff732be70a1d Mon Sep 17 00:00:00 2001 From: Catrope Date: Thu, 14 Mar 2013 14:23:16 -0700 Subject: [PATCH] Make metadata reaping handle replacement operations more sanely Before, replacement operations that both inserted and removed data at the same time would be treated as removals followed by insertions, so we'd reap the metadata from the affected range and move it to the start of the range. For a pure replacement, this doesn't make any sense. Instead, preserve the first min(insertLength, removeLength) elements in the metadata array, then perform a pure insertion splice or a pure removal splice for the length adjustment. Any metadata reaped in a removal splice is restored at the offset where we started removing, after the preserved portion. These changes make the behavior of metadata reaping saner in general (the previous behavior had the potential to move metadata around if it was near a paragraph opening or closing and you converted the paragraph to a heading), and makes the behavior match up with translateOffset(), which is desirable for MetaList synchronization. Change-Id: If9a1c6a7cf43ead7e3e1e8f6e081b139ca65fa53 --- modules/ve/dm/ve.dm.Document.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/ve/dm/ve.dm.Document.js b/modules/ve/dm/ve.dm.Document.js index d3f840e800..df6939a2af 100644 --- a/modules/ve/dm/ve.dm.Document.js +++ b/modules/ve/dm/ve.dm.Document.js @@ -533,10 +533,14 @@ ve.dm.Document.prototype.getLength = function () { * @param insert */ ve.dm.Document.prototype.spliceData = function ( offset, remove, insert ) { - var spliced, reaped, reapedFlat, i; + var spliced, retain, reaped, reapedFlat, i; insert = insert || []; spliced = ve.batchSplice( this.data, offset, remove, insert ); - reaped = ve.batchSplice( this.metadata, offset, remove, new Array( insert.length ) ); + // If we're both inserting and removing in the same operation, don't remove a bunch of metadata + // elements only to insert a bunch of new ones. Instead, only add or remove as many as the length + // delta. + retain = insert.length < remove ? insert.length : remove; + reaped = ve.batchSplice( this.metadata, offset + retain, remove - retain, new Array( insert.length - retain ) ); // reaped will be an array of arrays, flatten it reapedFlat = []; for ( i = 0; i < reaped.length; i++ ) { @@ -548,7 +552,7 @@ ve.dm.Document.prototype.spliceData = function ( offset, remove, insert ) { // after the removed data). Add it to the front, because it came from something that was // before it. if ( reapedFlat.length > 0 ) { - this.metadata[offset] = reapedFlat.concat( this.metadata[offset] || [] ); + this.metadata[offset + retain] = reapedFlat.concat( this.metadata[offset] || [] ); } return spliced; };