Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit 60ac1ab

Browse files
authored
Merge pull request #80 from ckeditor/t/79
Fix: Do not register batches which have only non-document operations. Closes #79. Closes ckeditor/ckeditor5#781.
2 parents 9d1536c + d99b618 commit 60ac1ab

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

src/undoengine.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ export default class UndoEngine extends Plugin {
6565

6666
this.listenTo( this.editor.model, 'applyOperation', ( evt, args ) => {
6767
const operation = args[ 0 ];
68+
69+
// Do not register batch if the operation is not a document operation.
70+
// This prevents from creating empty undo steps, where all operations where non-document operations.
71+
// Non-document operations creates and alters content in detached tree fragments (for example, document fragments).
72+
// Most of time this is preparing data before it is inserted into actual tree (for example during copy & paste).
73+
// Such operations should not be reversed.
74+
if ( !operation.isDocumentOperation ) {
75+
return;
76+
}
77+
6878
const batch = operation.delta.batch;
6979

7080
// If changes are not a part of a batch or this is not a new batch, omit those changes.

tests/undoengine-integration.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ describe( 'UndoEngine integration', () => {
918918
} );
919919
} );
920920

921-
describe( 'pasting', () => {
921+
describe( 'clipboard', () => {
922922
function pasteHtml( editor, html ) {
923923
editor.editing.view.document.fire( 'paste', {
924924
dataTransfer: createDataTransfer( { 'text/html': html } ),
@@ -930,7 +930,8 @@ describe( 'UndoEngine integration', () => {
930930
return {
931931
getData( type ) {
932932
return data[ type ];
933-
}
933+
},
934+
setData() {}
934935
};
935936
}
936937

@@ -958,6 +959,22 @@ describe( 'UndoEngine integration', () => {
958959
editor.execute( 'undo' );
959960
output( '<paragraph>Foo[]</paragraph>' );
960961
} );
962+
963+
// ckeditor5#781
964+
it( 'cutting should not create empty undo step', () => {
965+
input( '<paragraph>Fo[oba]r</paragraph>' );
966+
967+
editor.editing.view.document.fire( 'cut', {
968+
dataTransfer: createDataTransfer(),
969+
preventDefault() {},
970+
method: 'cut'
971+
} );
972+
973+
editor.execute( 'undo' );
974+
975+
output( '<paragraph>Fo[oba]r</paragraph>' );
976+
undoDisabled();
977+
} );
961978
} );
962979

963980
describe( 'other edge cases', () => {

tests/undoengine.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,31 @@ describe( 'UndoEngine', () => {
5656
expect( undo._undoCommand.addBatch.calledOnce ).to.be.true;
5757
} );
5858

59+
it( 'should not add a batch that has only non-document operations', () => {
60+
sinon.spy( undo._undoCommand, 'addBatch' );
61+
62+
model.change( writer => {
63+
const docFrag = writer.createDocumentFragment();
64+
const element = writer.createElement( 'paragraph' );
65+
writer.insert( element, docFrag, 0 );
66+
writer.insertText( 'foo', null, element, 0 );
67+
} );
68+
69+
expect( undo._undoCommand.addBatch.called ).to.be.false;
70+
} );
71+
72+
it( 'should add a batch that has both document and non-document operations', () => {
73+
sinon.spy( undo._undoCommand, 'addBatch' );
74+
75+
model.change( writer => {
76+
const element = writer.createElement( 'paragraph' );
77+
writer.insertText( 'foo', null, element, 0 );
78+
writer.insert( element, root, 0 );
79+
} );
80+
81+
expect( undo._undoCommand.addBatch.calledOnce ).to.be.true;
82+
} );
83+
5984
it( 'should add a batch to undo command, if it\'s type is undo and it comes from redo command', () => {
6085
sinon.spy( undo._undoCommand, 'addBatch' );
6186
sinon.spy( undo._redoCommand, 'clearStack' );

0 commit comments

Comments
 (0)