mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-15 10:35:48 +00:00
Fixed ve.dm.Transaction.newFromRemoval so it supports trimming off extra openings and closings
Change-Id: Icbcf4129a51aa92d47aa89738facd0d288337cbd
This commit is contained in:
parent
e7f03c6d70
commit
386faa5569
|
@ -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
|
||||
|
|
|
@ -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' );
|
||||
} );
|
||||
|
|
|
@ -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': [
|
||||
|
|
Loading…
Reference in a new issue