From 7e1aa2336e1137cf03ac68210ee2c47467c3c77f Mon Sep 17 00:00:00 2001 From: Catrope Date: Mon, 14 May 2012 21:46:39 -0700 Subject: [PATCH] Support splitting nodes in replace tree sync This means inserting things like

are now synced correctly and split the paragraph in the model tree. Merges (removing e.g.

) aren't supported yet. Also, this needs tests, Trevor tells me he's working on porting replace tests from the old ve/ directory Change-Id: Ic5050849d7d007a1696dc36548654979aedb53a8 --- modules/ve2/dm/ve.dm.Document.js | 3 ++ modules/ve2/dm/ve.dm.TransactionProcessor.js | 32 ++++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/modules/ve2/dm/ve.dm.Document.js b/modules/ve2/dm/ve.dm.Document.js index c62f098cc8..5f7a340fb9 100644 --- a/modules/ve2/dm/ve.dm.Document.js +++ b/modules/ve2/dm/ve.dm.Document.js @@ -197,6 +197,9 @@ ve.dm.Document.containsElementData = function( data ) { * @returns {ve.Node} Lowest level parent node being affected */ ve.dm.Document.getScope = function( node, data ) { + // TODO improve this to return a set of siblings, rather than a common ancestor, that'll + // make for much more efficient rebuilds + // TODO also make it track offsets var i, length, level = 0, diff --git a/modules/ve2/dm/ve.dm.TransactionProcessor.js b/modules/ve2/dm/ve.dm.TransactionProcessor.js index e95f322818..f210ddd0ef 100644 --- a/modules/ve2/dm/ve.dm.TransactionProcessor.js +++ b/modules/ve2/dm/ve.dm.TransactionProcessor.js @@ -254,7 +254,7 @@ ve.dm.TransactionProcessor.prototype.replace = function( op ) { insert = this.reversed ? op.remove : op.insert, removeHasStructure = ve.dm.Document.containsElementData( remove ), insertHasStructure = ve.dm.Document.containsElementData( insert ), - node, selection; + node, scope, selection; // Figure out if this is a structural insert or a content insert if ( !removeHasStructure && !insertHasStructure ) { // Content replacement @@ -272,8 +272,7 @@ ve.dm.TransactionProcessor.prototype.replace = function( op ) { // Advance the cursor this.cursor += insert.length; } else { - // Structural insert - // TODO generalize for insert/remove + // Structural replacement // It's possible that multiple replace operations are needed before the // model is back in a consistent state. This loop applies the current @@ -342,8 +341,29 @@ ve.dm.TransactionProcessor.prototype.replace = function( op ) { throw 'Unbalanced set of replace operations found'; } } - // Queue a rebuild for the replaced node - this.synchronizer.pushRebuild( new ve.Range( startOffset, this.cursor - adjustment ), - new ve.Range( startOffset, this.cursor ) ); + + // TODO this handles splitting nodes but not merging nodes + // Figure out in which node the start was + selection = this.document.selectNodes( new ve.Range( startOffset, startOffset ) ); + node = selection[0].node; + // Figure out what the scope of the insertion is + scope = ve.dm.Document.getScope( node, op.insert ); + if ( scope === node ) { + // Simple case: no splits occurred, we can just rebuild the affected range + this.synchronizer.pushRebuild( + new ve.Range( startOffset, this.cursor - adjustment ), + new ve.Range( startOffset, this.cursor ) + ); + } else { + // A split occurred. Rebuild the entirety of scope + // TODO do something better to get the offset, possibly via getScope() + // or through whatever we have to do for deletion painting + var scopeStart = this.document.getDocumentNode().getOffsetFromNode( scope ); + var scopeEnd = scopeStart + scope.getOuterLength(); + this.synchronizer.pushRebuild( + new ve.Range( scopeStart, scopeEnd ), + new ve.Range( scopeStart, scopeEnd + adjustment ) + ); + } } };