Index: trunk/extensions/VisualEditor/tests/es/es.DocumentModel.test.js |
— | — | @@ -301,7 +301,7 @@ |
302 | 302 | ); |
303 | 303 | } ); |
304 | 304 | |
305 | | -test( 'es.DocumentModel.prepareRemoval', 3, function() { |
| 305 | +test( 'es.DocumentModel.prepareRemoval', 4, function() { |
306 | 306 | var documentModel = es.DocumentModel.newFromPlainObject( esTest.obj ); |
307 | 307 | |
308 | 308 | // Test 1 |
— | — | @@ -356,6 +356,22 @@ |
357 | 357 | ], |
358 | 358 | 'prepareRemoval merges two list items' |
359 | 359 | ); |
| 360 | + |
| 361 | + // Test 4 |
| 362 | + deepEqual( |
| 363 | + documentModel.prepareRemoval( new es.Range( 3, 9 ) ).getOperations(), |
| 364 | + [ |
| 365 | + { 'type': 'retain', 'length': 3 }, |
| 366 | + { |
| 367 | + 'type': 'remove', |
| 368 | + 'data': [ |
| 369 | + ['c', { 'type': 'textStyle/italic', 'hash': '#textStyle/italic' }] |
| 370 | + ] |
| 371 | + }, |
| 372 | + { 'type': 'retain', 'length': 24 } |
| 373 | + ], |
| 374 | + 'prepareRemoval works across structural nodes' |
| 375 | + ); |
360 | 376 | } ); |
361 | 377 | |
362 | 378 | test( 'es.DocumentModel.prepareInsertion', 11, function() { |
Index: trunk/extensions/VisualEditor/modules/es/models/es.DocumentModel.js |
— | — | @@ -961,6 +961,7 @@ |
962 | 962 | tx.pushRetain( this.data.length - offset ); |
963 | 963 | } |
964 | 964 | |
| 965 | + tx.optimize(); |
965 | 966 | return tx; |
966 | 967 | |
967 | 968 | /* |
— | — | @@ -1102,7 +1103,8 @@ |
1103 | 1104 | if ( range.end < doc.data.length ) { |
1104 | 1105 | tx.pushRetain( doc.data.length - range.end ); |
1105 | 1106 | } |
1106 | | - |
| 1107 | + |
| 1108 | + tx.optimize(); |
1107 | 1109 | return tx; |
1108 | 1110 | }; |
1109 | 1111 | |
— | — | @@ -1165,6 +1167,7 @@ |
1166 | 1168 | if ( range.end < this.data.length ) { |
1167 | 1169 | tx.pushRetain( this.data.length - range.end ); |
1168 | 1170 | } |
| 1171 | + tx.optimize(); |
1169 | 1172 | return tx; |
1170 | 1173 | }; |
1171 | 1174 | |
— | — | @@ -1189,6 +1192,7 @@ |
1190 | 1193 | if ( offset < this.data.length ) { |
1191 | 1194 | tx.pushRetain( this.data.length - offset ); |
1192 | 1195 | } |
| 1196 | + tx.optimize(); |
1193 | 1197 | return tx; |
1194 | 1198 | }; |
1195 | 1199 | |
Index: trunk/extensions/VisualEditor/modules/es/es.Transaction.js |
— | — | @@ -15,6 +15,26 @@ |
16 | 16 | return this.operations; |
17 | 17 | }; |
18 | 18 | |
| 19 | +es.Transaction.prototype.optimize = function() { |
| 20 | + for ( var i = 0; i < this.operations.length - 1; i++ ) { |
| 21 | + var a = this.operations[i]; |
| 22 | + var b = this.operations[i + 1]; |
| 23 | + if ( a.type === b.type ) { |
| 24 | + switch ( a.type ) { |
| 25 | + case 'retain': |
| 26 | + a.length += b.length; |
| 27 | + this.operations.splice( i + 1, 1 ); |
| 28 | + break; |
| 29 | + case 'insert': |
| 30 | + case 'remove': |
| 31 | + a.content = a.content.concat( b.content ); |
| 32 | + this.operations.splice( i + 1, 1 ); |
| 33 | + break; |
| 34 | + } |
| 35 | + } |
| 36 | + } |
| 37 | +}; |
| 38 | + |
19 | 39 | es.Transaction.prototype.pushRetain = function( length ) { |
20 | 40 | this.operations.push( { |
21 | 41 | 'type': 'retain', |