Fixed ve.dm.Transaction.newFromRemoval so it supports trimming off extra openings and closings

Change-Id: Icbcf4129a51aa92d47aa89738facd0d288337cbd
This commit is contained in:
Trevor Parscal 2012-06-01 14:34:59 -07:00
parent e7f03c6d70
commit 386faa5569
3 changed files with 52 additions and 3 deletions

View file

@ -72,13 +72,23 @@ ve.dm.Transaction.newFromRemoval = function( doc, range ) {
return tx;
}
// Select nodes and validate selection
var selection = doc.selectNodes( range, 'leaves' );
var selection = doc.selectNodes( range, 'leaves' ),
nodeRange;
if ( selection.length === 0 ) {
// Empty selection? Something is wrong!
throw 'Invalid range, can not remove from ' + range.start + ' to ' + range.end;
}
// Decide whether to merge or strip
if ( selection[0].node.canBeMergedWith( selection[selection.length - 1].node ) ) {
// If only one node was selected, ignore anything past this node
if ( selection.length === 1 ) {
// Include the parent's wrapping (if any - there should always be, but let's be safe)
wrapping = selection[0].node.getParent().isWrapped() ? 1 : 0;
// Only reduces the range to cover the selected node if it's shorter
range.start = Math.max( range.start, selection[0].nodeRange.start - wrapping );
// Only reduces the range to cover the selected node if it's shorter
range.end = Math.min( range.end, selection[0].nodeRange.end + wrapping );
}
// Retain to the start of the range
if ( range.start > 0 ) {
tx.pushRetain( range.start );
@ -90,8 +100,7 @@ ve.dm.Transaction.newFromRemoval = function( doc, range ) {
tx.pushRetain( data.length - range.end );
}
} else {
var offset = 0,
nodeRange;
var offset = 0;
for ( var i = 0; i < selection.length; i++ ) {
nodeRange = selection[i].nodeRange;
// Retain up to where the next removal starts

View file

@ -96,3 +96,14 @@ test( 'detach', 2, function() {
strictEqual( node1.getRoot(), node1 );
} );
test( 'canBeMergedWith', 4, function() {
var node1 = new ve.dm.LeafNodeStub(),
node2 = new ve.dm.BranchNodeStub( [node1] ),
node3 = new ve.dm.BranchNodeStub( [node2] ),
node4 = new ve.dm.LeafNodeStub(),
node5 = new ve.dm.BranchNodeStub( [node4] );
strictEqual( node3.canBeMergedWith( node5 ), true, 'same level, same type' );
strictEqual( node2.canBeMergedWith( node5 ), false, 'different level, same type' );
strictEqual( node2.canBeMergedWith( node1 ), false, 'different level, different type' );
strictEqual( node2.canBeMergedWith( node4 ), false, 'same level, different type' );
} );

View file

@ -150,6 +150,23 @@ test( 'newFromRemoval', function() {
{ 'type': 'retain', 'length': 19 }
]
},
'extra openings': {
'args': [doc, new ve.Range( 0, 7 )],
'ops': [
{
'type': 'replace',
'remove': [
{ 'type': 'heading', 'attributes': { 'level': 1 } },
'a',
['b', { '{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' } }],
['c', { '{"type":"textStyle/italic"}': { 'type': 'textStyle/italic' } }],
{ 'type': '/heading' }
],
'insert': []
},
{ 'type': 'retain', 'length': 54 }
]
},
'last element': {
'args': [doc, new ve.Range( 56, 59 )],
'ops': [
@ -161,6 +178,18 @@ test( 'newFromRemoval', function() {
}
]
},
'extra closings': {
'args': [doc, new ve.Range( 30, 37 )],
'ops': [
{ 'type': 'retain', 'length': 36 },
{
'type': 'replace',
'remove': ['h'],
'insert': []
},
{ 'type': 'retain', 'length': 22 }
]
},
'merge last two elements': {
'args': [doc, new ve.Range( 55, 57 )],
'ops': [