浏览代码

Omit deltas with non-document operations.

Oskar Wróbel 8 年之前
父节点
当前提交
8182faa3e9
共有 2 个文件被更改,包括 42 次插入22 次删除
  1. 27 22
      packages/ckeditor5-undo/src/basecommand.js
  2. 15 0
      packages/ckeditor5-undo/tests/undocommand.js

+ 27 - 22
packages/ckeditor5-undo/src/basecommand.js

@@ -133,29 +133,34 @@ export default class BaseCommand extends Command {
 		// We will process each delta from `batchToUndo`, in reverse order. If there were deltas A, B and C in undone batch,
 		// we need to revert them in reverse order, so first C' (reversed C), then B', then A'.
 		for ( const deltaToUndo of deltasToUndo ) {
-			// Keep in mind that transformation algorithms return arrays. That's because the transformation might result in multiple
-			// deltas, so we need arrays to handle them. To simplify algorithms, it is better to always operate on arrays.
-			const nextBaseVersion = deltaToUndo.baseVersion + deltaToUndo.operations.length;
-
-			// Reverse delta from the history.
-			const historyDeltas = Array.from( document.history.getDeltas( nextBaseVersion ) );
-			const transformedSets = document.transformDeltas( [ deltaToUndo.getReversed() ], historyDeltas, true );
-			const reversedDeltas = transformedSets.deltasA;
-
-			// After reversed delta has been transformed by all history deltas, apply it.
-			for ( const delta of reversedDeltas ) {
-				// Fix base version.
-				delta.baseVersion = document.version;
-
-				// Before applying, add the delta to the `undoingBatch`.
-				undoingBatch.addDelta( delta );
-
-				// Now, apply all operations of the delta.
-				for ( const operation of delta.operations ) {
-					document.applyOperation( operation );
+			// For now let's skip deltas with operation applied on detached document.
+			// We assumed that there is no deltas with mixed (document and document fragment) operations
+			// so we can skip entire delta.
+			if ( deltaToUndo.operations.some( op => op.isDocumentOperation ) ) {
+				// Keep in mind that transformation algorithms return arrays. That's because the transformation might result in multiple
+				// deltas, so we need arrays to handle them. To simplify algorithms, it is better to always operate on arrays.
+				const nextBaseVersion = deltaToUndo.baseVersion + deltaToUndo.operations.length;
+
+				// Reverse delta from the history.
+				const historyDeltas = Array.from( document.history.getDeltas( nextBaseVersion ) );
+				const transformedSets = document.transformDeltas( [ deltaToUndo.getReversed() ], historyDeltas, true );
+				const reversedDeltas = transformedSets.deltasA;
+
+				// After reversed delta has been transformed by all history deltas, apply it.
+				for ( const delta of reversedDeltas ) {
+					// Fix base version.
+					delta.baseVersion = document.version;
+
+					// Before applying, add the delta to the `undoingBatch`.
+					undoingBatch.addDelta( delta );
+
+					// Now, apply all operations of the delta.
+					for ( const operation of delta.operations ) {
+						document.applyOperation( operation );
+					}
+
+					document.history.setDeltaAsUndone( deltaToUndo, delta );
 				}
-
-				document.history.setDeltaAsUndone( deltaToUndo, delta );
 			}
 		}
 

+ 15 - 0
packages/ckeditor5-undo/tests/undocommand.js

@@ -256,6 +256,21 @@ describe( 'UndoCommand', () => {
 				expect( editor.document.selection.getFirstRange().isEqual( r( 0, 0 ) ) ).to.be.true;
 				expect( editor.document.selection.isBackward ).to.be.false;
 			} );
+
+			it( 'should omit deltas with non-document operations', () => {
+				const batch = doc.batch();
+				const element = batch.createElement( 'p' );
+
+				undo.addBatch( batch );
+
+				batch.setAttribute( element, 'foo', 'bar' );
+				batch.setAttribute( root, 'foo', 'bar' );
+
+				undo.execute();
+
+				expect( element.getAttribute( 'foo' ) ).to.equal( 'bar' );
+				expect( root.getAttribute( 'foo' ) ).to.not.equal( 'bar' );
+			} );
 		} );
 
 		it( 'merges touching ranges when restoring selection', () => {