Преглед изворни кода

Merge branch 'master' into t/ckeditor5/488

# Conflicts:
#	tests/undoengine.js
Szymon Cofalik пре 8 година
родитељ
комит
e863e85cf4

+ 10 - 0
packages/ckeditor5-undo/src/undoediting.js

@@ -67,6 +67,16 @@ export default class UndoEditing extends Plugin {
 
 		this.listenTo( editor.model, 'applyOperation', ( evt, args ) => {
 			const operation = args[ 0 ];
+
+			// Do not register batch if the operation is not a document operation.
+			// This prevents from creating empty undo steps, where all operations where non-document operations.
+			// Non-document operations creates and alters content in detached tree fragments (for example, document fragments).
+			// Most of time this is preparing data before it is inserted into actual tree (for example during copy & paste).
+			// Such operations should not be reversed.
+			if ( !operation.isDocumentOperation ) {
+				return;
+			}
+
 			const batch = operation.delta.batch;
 
 			// If changes are not a part of a batch or this is not a new batch, omit those changes.

+ 19 - 2
packages/ckeditor5-undo/tests/undoediting-integration.js

@@ -918,7 +918,7 @@ describe( 'UndoEditing integration', () => {
 		} );
 	} );
 
-	describe( 'pasting', () => {
+	describe( 'clipboard', () => {
 		function pasteHtml( editor, html ) {
 			editor.editing.view.document.fire( 'paste', {
 				dataTransfer: createDataTransfer( { 'text/html': html } ),
@@ -930,7 +930,8 @@ describe( 'UndoEditing integration', () => {
 			return {
 				getData( type ) {
 					return data[ type ];
-				}
+				},
+				setData() {}
 			};
 		}
 
@@ -958,6 +959,22 @@ describe( 'UndoEditing integration', () => {
 			editor.execute( 'undo' );
 			output( '<paragraph>Foo[]</paragraph>' );
 		} );
+
+		// ckeditor5#781
+		it( 'cutting should not create empty undo step', () => {
+			input( '<paragraph>Fo[oba]r</paragraph>' );
+
+			editor.editing.view.document.fire( 'cut', {
+				dataTransfer: createDataTransfer(),
+				preventDefault() {},
+				method: 'cut'
+			} );
+
+			editor.execute( 'undo' );
+
+			output( '<paragraph>Fo[oba]r</paragraph>' );
+			undoDisabled();
+		} );
 	} );
 
 	describe( 'other edge cases', () => {

+ 25 - 0
packages/ckeditor5-undo/tests/undoediting.js

@@ -82,6 +82,31 @@ describe( 'UndoEditing', () => {
 		expect( undo._redoCommand.clearStack.called ).to.be.false;
 	} );
 
+	it( 'should not add a batch that has only non-document operations', () => {
+		sinon.spy( undo._undoCommand, 'addBatch' );
+
+		model.change( writer => {
+			const docFrag = writer.createDocumentFragment();
+			const element = writer.createElement( 'paragraph' );
+			writer.insert( element, docFrag, 0 );
+			writer.insertText( 'foo', null, element, 0 );
+		} );
+
+		expect( undo._undoCommand.addBatch.called ).to.be.false;
+	} );
+
+	it( 'should add a batch that has both document and non-document operations', () => {
+		sinon.spy( undo._undoCommand, 'addBatch' );
+
+		model.change( writer => {
+			const element = writer.createElement( 'paragraph' );
+			writer.insertText( 'foo', null, element, 0 );
+			writer.insert( element, root, 0 );
+		} );
+
+		expect( undo._undoCommand.addBatch.calledOnce ).to.be.true;
+	} );
+
 	it( 'should set CTRL+Z keystroke', () => {
 		const spy = sinon.stub( editor, 'execute' );