@ckeditor/ckeditor5-undo 41.3.0-alpha.0 → 41.3.0-alpha.2
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/translations/ar.d.ts +8 -0
- package/dist/translations/ar.js +5 -0
- package/dist/translations/ast.d.ts +8 -0
- package/dist/translations/ast.js +5 -0
- package/dist/translations/az.d.ts +8 -0
- package/dist/translations/az.js +5 -0
- package/dist/translations/bg.d.ts +8 -0
- package/dist/translations/bg.js +5 -0
- package/dist/translations/bn.d.ts +8 -0
- package/dist/translations/bn.js +5 -0
- package/dist/translations/ca.d.ts +8 -0
- package/dist/translations/ca.js +5 -0
- package/dist/translations/cs.d.ts +8 -0
- package/dist/translations/cs.js +5 -0
- package/dist/translations/da.d.ts +8 -0
- package/dist/translations/da.js +5 -0
- package/dist/translations/de-ch.d.ts +8 -0
- package/dist/translations/de-ch.js +5 -0
- package/dist/translations/de.d.ts +8 -0
- package/dist/translations/de.js +5 -0
- package/dist/translations/el.d.ts +8 -0
- package/dist/translations/el.js +5 -0
- package/dist/translations/en-au.d.ts +8 -0
- package/dist/translations/en-au.js +5 -0
- package/dist/translations/en-gb.d.ts +8 -0
- package/dist/translations/en-gb.js +5 -0
- package/dist/translations/en.d.ts +8 -0
- package/dist/translations/en.js +5 -0
- package/dist/translations/eo.d.ts +8 -0
- package/dist/translations/eo.js +5 -0
- package/dist/translations/es.d.ts +8 -0
- package/dist/translations/es.js +5 -0
- package/dist/translations/et.d.ts +8 -0
- package/dist/translations/et.js +5 -0
- package/dist/translations/eu.d.ts +8 -0
- package/dist/translations/eu.js +5 -0
- package/dist/translations/fa.d.ts +8 -0
- package/dist/translations/fa.js +5 -0
- package/dist/translations/fi.d.ts +8 -0
- package/dist/translations/fi.js +5 -0
- package/dist/translations/fr.d.ts +8 -0
- package/dist/translations/fr.js +5 -0
- package/dist/translations/gl.d.ts +8 -0
- package/dist/translations/gl.js +5 -0
- package/dist/translations/he.d.ts +8 -0
- package/dist/translations/he.js +5 -0
- package/dist/translations/hi.d.ts +8 -0
- package/dist/translations/hi.js +5 -0
- package/dist/translations/hr.d.ts +8 -0
- package/dist/translations/hr.js +5 -0
- package/dist/translations/hu.d.ts +8 -0
- package/dist/translations/hu.js +5 -0
- package/dist/translations/id.d.ts +8 -0
- package/dist/translations/id.js +5 -0
- package/dist/translations/it.d.ts +8 -0
- package/dist/translations/it.js +5 -0
- package/dist/translations/ja.d.ts +8 -0
- package/dist/translations/ja.js +5 -0
- package/dist/translations/km.d.ts +8 -0
- package/dist/translations/km.js +5 -0
- package/dist/translations/kn.d.ts +8 -0
- package/dist/translations/kn.js +5 -0
- package/dist/translations/ko.d.ts +8 -0
- package/dist/translations/ko.js +5 -0
- package/dist/translations/ku.d.ts +8 -0
- package/dist/translations/ku.js +5 -0
- package/dist/translations/lt.d.ts +8 -0
- package/dist/translations/lt.js +5 -0
- package/dist/translations/lv.d.ts +8 -0
- package/dist/translations/lv.js +5 -0
- package/dist/translations/ms.d.ts +8 -0
- package/dist/translations/ms.js +5 -0
- package/dist/translations/nb.d.ts +8 -0
- package/dist/translations/nb.js +5 -0
- package/dist/translations/ne.d.ts +8 -0
- package/dist/translations/ne.js +5 -0
- package/dist/translations/nl.d.ts +8 -0
- package/dist/translations/nl.js +5 -0
- package/dist/translations/no.d.ts +8 -0
- package/dist/translations/no.js +5 -0
- package/dist/translations/pl.d.ts +8 -0
- package/dist/translations/pl.js +5 -0
- package/dist/translations/pt-br.d.ts +8 -0
- package/dist/translations/pt-br.js +5 -0
- package/dist/translations/pt.d.ts +8 -0
- package/dist/translations/pt.js +5 -0
- package/dist/translations/ro.d.ts +8 -0
- package/dist/translations/ro.js +5 -0
- package/dist/translations/ru.d.ts +8 -0
- package/dist/translations/ru.js +5 -0
- package/dist/translations/si.d.ts +8 -0
- package/dist/translations/si.js +5 -0
- package/dist/translations/sk.d.ts +8 -0
- package/dist/translations/sk.js +5 -0
- package/dist/translations/sq.d.ts +8 -0
- package/dist/translations/sq.js +5 -0
- package/dist/translations/sr-latn.d.ts +8 -0
- package/dist/translations/sr-latn.js +5 -0
- package/dist/translations/sr.d.ts +8 -0
- package/dist/translations/sr.js +5 -0
- package/dist/translations/sv.d.ts +8 -0
- package/dist/translations/sv.js +5 -0
- package/dist/translations/th.d.ts +8 -0
- package/dist/translations/th.js +5 -0
- package/dist/translations/tk.d.ts +8 -0
- package/dist/translations/tk.js +5 -0
- package/dist/translations/tr.d.ts +8 -0
- package/dist/translations/tr.js +5 -0
- package/dist/translations/tt.d.ts +8 -0
- package/dist/translations/tt.js +5 -0
- package/dist/translations/ug.d.ts +8 -0
- package/dist/translations/ug.js +5 -0
- package/dist/translations/uk.d.ts +8 -0
- package/dist/translations/uk.js +5 -0
- package/dist/translations/ur.d.ts +8 -0
- package/dist/translations/ur.js +5 -0
- package/dist/translations/uz.d.ts +8 -0
- package/dist/translations/uz.js +5 -0
- package/dist/translations/vi.d.ts +8 -0
- package/dist/translations/vi.js +5 -0
- package/dist/translations/zh-cn.d.ts +8 -0
- package/dist/translations/zh-cn.js +5 -0
- package/dist/translations/zh.d.ts +8 -0
- package/dist/translations/zh.js +5 -0
- package/dist/types/augmentation.d.ts +4 -0
- package/dist/types/basecommand.d.ts +4 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/redocommand.d.ts +4 -0
- package/dist/types/undo.d.ts +4 -0
- package/dist/types/undocommand.d.ts +4 -0
- package/dist/types/undoediting.d.ts +4 -0
- package/dist/types/undoui.d.ts +4 -0
- package/package.json +4 -4
- package/dist/index.js +0 -556
- package/dist/index.js.map +0 -1
package/dist/index.js
DELETED
@@ -1,556 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
-
*/
|
5
|
-
import { Command, Plugin, icons } from '@ckeditor/ckeditor5-core/dist/index.js';
|
6
|
-
import { transformSets, NoOperation } from '@ckeditor/ckeditor5-engine/dist/index.js';
|
7
|
-
import { ButtonView } from '@ckeditor/ckeditor5-ui/dist/index.js';
|
8
|
-
|
9
|
-
/**
|
10
|
-
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
11
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
12
|
-
*/
|
13
|
-
/**
|
14
|
-
* @module undo/basecommand
|
15
|
-
*/
|
16
|
-
/**
|
17
|
-
* Base class for the undo feature commands: {@link module:undo/undocommand~UndoCommand} and {@link module:undo/redocommand~RedoCommand}.
|
18
|
-
*/
|
19
|
-
class BaseCommand extends Command {
|
20
|
-
/**
|
21
|
-
* @inheritDoc
|
22
|
-
*/
|
23
|
-
constructor(editor) {
|
24
|
-
super(editor);
|
25
|
-
/**
|
26
|
-
* Stack of items stored by the command. These are pairs of:
|
27
|
-
*
|
28
|
-
* * {@link module:engine/model/batch~Batch batch} saved by the command,
|
29
|
-
* * {@link module:engine/model/selection~Selection selection} state at the moment of saving the batch.
|
30
|
-
*/
|
31
|
-
this._stack = [];
|
32
|
-
/**
|
33
|
-
* Stores all batches that were created by this command.
|
34
|
-
*
|
35
|
-
* @internal
|
36
|
-
*/
|
37
|
-
this._createdBatches = new WeakSet();
|
38
|
-
// Refresh state, so the command is inactive right after initialization.
|
39
|
-
this.refresh();
|
40
|
-
// This command should not depend on selection change.
|
41
|
-
this._isEnabledBasedOnSelection = false;
|
42
|
-
// Set the transparent batch for the `editor.data.set()` call if the
|
43
|
-
// batch type is not set already.
|
44
|
-
this.listenTo(editor.data, 'set', (evt, data) => {
|
45
|
-
// Create a shallow copy of the options to not change the original args.
|
46
|
-
// And make sure that an object is assigned to data[ 1 ].
|
47
|
-
data[1] = { ...data[1] };
|
48
|
-
const options = data[1];
|
49
|
-
// If batch type is not set, default to non-undoable batch.
|
50
|
-
if (!options.batchType) {
|
51
|
-
options.batchType = { isUndoable: false };
|
52
|
-
}
|
53
|
-
}, { priority: 'high' });
|
54
|
-
// Clear the stack for the `transparent` batches.
|
55
|
-
this.listenTo(editor.data, 'set', (evt, data) => {
|
56
|
-
// We can assume that the object exists and it has a `batchType` property.
|
57
|
-
// It was ensured with a higher priority listener before.
|
58
|
-
const options = data[1];
|
59
|
-
if (!options.batchType.isUndoable) {
|
60
|
-
this.clearStack();
|
61
|
-
}
|
62
|
-
});
|
63
|
-
}
|
64
|
-
/**
|
65
|
-
* @inheritDoc
|
66
|
-
*/
|
67
|
-
refresh() {
|
68
|
-
this.isEnabled = this._stack.length > 0;
|
69
|
-
}
|
70
|
-
/**
|
71
|
-
* Returns all batches created by this command.
|
72
|
-
*/
|
73
|
-
get createdBatches() {
|
74
|
-
return this._createdBatches;
|
75
|
-
}
|
76
|
-
/**
|
77
|
-
* Stores a batch in the command, together with the selection state of the {@link module:engine/model/document~Document document}
|
78
|
-
* created by the editor which this command is registered to.
|
79
|
-
*
|
80
|
-
* @param batch The batch to add.
|
81
|
-
*/
|
82
|
-
addBatch(batch) {
|
83
|
-
const docSelection = this.editor.model.document.selection;
|
84
|
-
const selection = {
|
85
|
-
ranges: docSelection.hasOwnRange ? Array.from(docSelection.getRanges()) : [],
|
86
|
-
isBackward: docSelection.isBackward
|
87
|
-
};
|
88
|
-
this._stack.push({ batch, selection });
|
89
|
-
this.refresh();
|
90
|
-
}
|
91
|
-
/**
|
92
|
-
* Removes all items from the stack.
|
93
|
-
*/
|
94
|
-
clearStack() {
|
95
|
-
this._stack = [];
|
96
|
-
this.refresh();
|
97
|
-
}
|
98
|
-
/**
|
99
|
-
* Restores the {@link module:engine/model/document~Document#selection document selection} state after a batch was undone.
|
100
|
-
*
|
101
|
-
* @param ranges Ranges to be restored.
|
102
|
-
* @param isBackward A flag describing whether the restored range was selected forward or backward.
|
103
|
-
* @param operations Operations which has been applied since selection has been stored.
|
104
|
-
*/
|
105
|
-
_restoreSelection(ranges, isBackward, operations) {
|
106
|
-
const model = this.editor.model;
|
107
|
-
const document = model.document;
|
108
|
-
// This will keep the transformed selection ranges.
|
109
|
-
const selectionRanges = [];
|
110
|
-
// Transform all ranges from the restored selection.
|
111
|
-
const transformedRangeGroups = ranges.map(range => range.getTransformedByOperations(operations));
|
112
|
-
const allRanges = transformedRangeGroups.flat();
|
113
|
-
for (const rangeGroup of transformedRangeGroups) {
|
114
|
-
// While transforming there could appear ranges that are contained by other ranges, we shall ignore them.
|
115
|
-
const transformed = rangeGroup
|
116
|
-
.filter(range => range.root != document.graveyard)
|
117
|
-
.filter(range => !isRangeContainedByAnyOtherRange(range, allRanges));
|
118
|
-
// All the transformed ranges ended up in graveyard.
|
119
|
-
if (!transformed.length) {
|
120
|
-
continue;
|
121
|
-
}
|
122
|
-
// After the range got transformed, we have an array of ranges. Some of those
|
123
|
-
// ranges may be "touching" -- they can be next to each other and could be merged.
|
124
|
-
normalizeRanges(transformed);
|
125
|
-
// For each `range` from `ranges`, we take only one transformed range.
|
126
|
-
// This is because we want to prevent situation where single-range selection
|
127
|
-
// got transformed to multi-range selection.
|
128
|
-
selectionRanges.push(transformed[0]);
|
129
|
-
}
|
130
|
-
// @if CK_DEBUG_ENGINE // console.log( `Restored selection by undo: ${ selectionRanges.join( ', ' ) }` );
|
131
|
-
// `selectionRanges` may be empty if all ranges ended up in graveyard. If that is the case, do not restore selection.
|
132
|
-
if (selectionRanges.length) {
|
133
|
-
model.change(writer => {
|
134
|
-
writer.setSelection(selectionRanges, { backward: isBackward });
|
135
|
-
});
|
136
|
-
}
|
137
|
-
}
|
138
|
-
/**
|
139
|
-
* Undoes a batch by reversing that batch, transforming reversed batch and finally applying it.
|
140
|
-
* This is a helper method for {@link #execute}.
|
141
|
-
*
|
142
|
-
* @param batchToUndo The batch to be undone.
|
143
|
-
* @param undoingBatch The batch that will contain undoing changes.
|
144
|
-
*/
|
145
|
-
_undo(batchToUndo, undoingBatch) {
|
146
|
-
const model = this.editor.model;
|
147
|
-
const document = model.document;
|
148
|
-
// All changes done by the command execution will be saved as one batch.
|
149
|
-
this._createdBatches.add(undoingBatch);
|
150
|
-
const operationsToUndo = batchToUndo.operations.slice().filter(operation => operation.isDocumentOperation);
|
151
|
-
operationsToUndo.reverse();
|
152
|
-
// We will process each operation from `batchToUndo`, in reverse order. If there were operations A, B and C in undone batch,
|
153
|
-
// we need to revert them in reverse order, so first C' (reversed C), then B', then A'.
|
154
|
-
for (const operationToUndo of operationsToUndo) {
|
155
|
-
const nextBaseVersion = operationToUndo.baseVersion + 1;
|
156
|
-
const historyOperations = Array.from(document.history.getOperations(nextBaseVersion));
|
157
|
-
const transformedSets = transformSets([operationToUndo.getReversed()], historyOperations, {
|
158
|
-
useRelations: true,
|
159
|
-
document: this.editor.model.document,
|
160
|
-
padWithNoOps: false,
|
161
|
-
forceWeakRemove: true
|
162
|
-
});
|
163
|
-
const reversedOperations = transformedSets.operationsA;
|
164
|
-
// After reversed operation has been transformed by all history operations, apply it.
|
165
|
-
for (let operation of reversedOperations) {
|
166
|
-
// Do not apply any operation on non-editable space.
|
167
|
-
const affectedSelectable = operation.affectedSelectable;
|
168
|
-
if (affectedSelectable && !model.canEditAt(affectedSelectable)) {
|
169
|
-
operation = new NoOperation(operation.baseVersion);
|
170
|
-
}
|
171
|
-
// Before applying, add the operation to the `undoingBatch`.
|
172
|
-
undoingBatch.addOperation(operation);
|
173
|
-
model.applyOperation(operation);
|
174
|
-
document.history.setOperationAsUndone(operationToUndo, operation);
|
175
|
-
}
|
176
|
-
}
|
177
|
-
}
|
178
|
-
}
|
179
|
-
/**
|
180
|
-
* Normalizes list of ranges by joining intersecting or "touching" ranges.
|
181
|
-
*
|
182
|
-
* @param ranges Ranges to be normalized.
|
183
|
-
*/
|
184
|
-
function normalizeRanges(ranges) {
|
185
|
-
ranges.sort((a, b) => a.start.isBefore(b.start) ? -1 : 1);
|
186
|
-
for (let i = 1; i < ranges.length; i++) {
|
187
|
-
const previousRange = ranges[i - 1];
|
188
|
-
const joinedRange = previousRange.getJoined(ranges[i], true);
|
189
|
-
if (joinedRange) {
|
190
|
-
// Replace the ranges on the list with the new joined range.
|
191
|
-
i--;
|
192
|
-
ranges.splice(i, 2, joinedRange);
|
193
|
-
}
|
194
|
-
}
|
195
|
-
}
|
196
|
-
function isRangeContainedByAnyOtherRange(range, ranges) {
|
197
|
-
return ranges.some(otherRange => otherRange !== range && otherRange.containsRange(range, true));
|
198
|
-
}
|
199
|
-
|
200
|
-
/**
|
201
|
-
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
202
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
203
|
-
*/
|
204
|
-
/**
|
205
|
-
* @module undo/undocommand
|
206
|
-
*/
|
207
|
-
/**
|
208
|
-
* The undo command stores {@link module:engine/model/batch~Batch batches} applied to the
|
209
|
-
* {@link module:engine/model/document~Document document} and is able to undo a batch by reversing it and transforming by
|
210
|
-
* batches from {@link module:engine/model/document~Document#history history} that happened after the reversed batch.
|
211
|
-
*
|
212
|
-
* The undo command also takes care of restoring the {@link module:engine/model/document~Document#selection document selection}.
|
213
|
-
*/
|
214
|
-
class UndoCommand extends BaseCommand {
|
215
|
-
/**
|
216
|
-
* Executes the command. This method reverts a {@link module:engine/model/batch~Batch batch} added to the command's stack, transforms
|
217
|
-
* and applies the reverted version on the {@link module:engine/model/document~Document document} and removes the batch from the stack.
|
218
|
-
* Then, it restores the {@link module:engine/model/document~Document#selection document selection}.
|
219
|
-
*
|
220
|
-
* @fires execute
|
221
|
-
* @fires revert
|
222
|
-
* @param batch A batch that should be undone. If not set, the last added batch will be undone.
|
223
|
-
*/
|
224
|
-
execute(batch = null) {
|
225
|
-
// If batch is not given, set `batchIndex` to the last index in command stack.
|
226
|
-
const batchIndex = batch ? this._stack.findIndex(a => a.batch == batch) : this._stack.length - 1;
|
227
|
-
const item = this._stack.splice(batchIndex, 1)[0];
|
228
|
-
const undoingBatch = this.editor.model.createBatch({ isUndo: true });
|
229
|
-
// All changes have to be done in one `enqueueChange` callback so other listeners will not
|
230
|
-
// step between consecutive operations, or won't do changes to the document before selection is properly restored.
|
231
|
-
this.editor.model.enqueueChange(undoingBatch, () => {
|
232
|
-
this._undo(item.batch, undoingBatch);
|
233
|
-
const operations = this.editor.model.document.history.getOperations(item.batch.baseVersion);
|
234
|
-
this._restoreSelection(item.selection.ranges, item.selection.isBackward, operations);
|
235
|
-
});
|
236
|
-
// Firing `revert` event after the change block to make sure that it includes all changes from post-fixers
|
237
|
-
// and make sure that the selection is "stabilized" (the selection range is saved after undo is executed and then
|
238
|
-
// restored on redo, so it is important that the selection range is saved after post-fixers are done).
|
239
|
-
this.fire('revert', item.batch, undoingBatch);
|
240
|
-
this.refresh();
|
241
|
-
}
|
242
|
-
}
|
243
|
-
|
244
|
-
/**
|
245
|
-
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
246
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
247
|
-
*/
|
248
|
-
/**
|
249
|
-
* @module undo/redocommand
|
250
|
-
*/
|
251
|
-
/**
|
252
|
-
* The redo command stores {@link module:engine/model/batch~Batch batches} that were used to undo a batch by
|
253
|
-
* {@link module:undo/undocommand~UndoCommand}. It is able to redo a previously undone batch by reversing the undoing
|
254
|
-
* batches created by `UndoCommand`. The reversed batch is transformed by all the batches from
|
255
|
-
* {@link module:engine/model/document~Document#history history} that happened after the reversed undo batch.
|
256
|
-
*
|
257
|
-
* The redo command also takes care of restoring the {@link module:engine/model/document~Document#selection document selection}.
|
258
|
-
*/
|
259
|
-
class RedoCommand extends BaseCommand {
|
260
|
-
/**
|
261
|
-
* Executes the command. This method reverts the last {@link module:engine/model/batch~Batch batch} added to
|
262
|
-
* the command's stack, applies the reverted and transformed version on the
|
263
|
-
* {@link module:engine/model/document~Document document} and removes the batch from the stack.
|
264
|
-
* Then, it restores the {@link module:engine/model/document~Document#selection document selection}.
|
265
|
-
*
|
266
|
-
* @fires execute
|
267
|
-
*/
|
268
|
-
execute() {
|
269
|
-
const item = this._stack.pop();
|
270
|
-
const redoingBatch = this.editor.model.createBatch({ isUndo: true });
|
271
|
-
// All changes have to be done in one `enqueueChange` callback so other listeners will not step between consecutive
|
272
|
-
// operations, or won't do changes to the document before selection is properly restored.
|
273
|
-
this.editor.model.enqueueChange(redoingBatch, () => {
|
274
|
-
const lastOperation = item.batch.operations[item.batch.operations.length - 1];
|
275
|
-
const nextBaseVersion = lastOperation.baseVersion + 1;
|
276
|
-
const operations = this.editor.model.document.history.getOperations(nextBaseVersion);
|
277
|
-
this._restoreSelection(item.selection.ranges, item.selection.isBackward, operations);
|
278
|
-
this._undo(item.batch, redoingBatch);
|
279
|
-
});
|
280
|
-
this.refresh();
|
281
|
-
}
|
282
|
-
}
|
283
|
-
|
284
|
-
/**
|
285
|
-
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
286
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
287
|
-
*/
|
288
|
-
/**
|
289
|
-
* @module undo/undoediting
|
290
|
-
*/
|
291
|
-
/**
|
292
|
-
* The undo engine feature.
|
293
|
-
*
|
294
|
-
* It introduces the `'undo'` and `'redo'` commands to the editor.
|
295
|
-
*/
|
296
|
-
class UndoEditing extends Plugin {
|
297
|
-
constructor() {
|
298
|
-
super(...arguments);
|
299
|
-
/**
|
300
|
-
* Keeps track of which batches were registered in undo.
|
301
|
-
*/
|
302
|
-
this._batchRegistry = new WeakSet();
|
303
|
-
}
|
304
|
-
/**
|
305
|
-
* @inheritDoc
|
306
|
-
*/
|
307
|
-
static get pluginName() {
|
308
|
-
return 'UndoEditing';
|
309
|
-
}
|
310
|
-
/**
|
311
|
-
* @inheritDoc
|
312
|
-
*/
|
313
|
-
init() {
|
314
|
-
const editor = this.editor;
|
315
|
-
const t = editor.t;
|
316
|
-
// Create commands.
|
317
|
-
this._undoCommand = new UndoCommand(editor);
|
318
|
-
this._redoCommand = new RedoCommand(editor);
|
319
|
-
// Register command to the editor.
|
320
|
-
editor.commands.add('undo', this._undoCommand);
|
321
|
-
editor.commands.add('redo', this._redoCommand);
|
322
|
-
this.listenTo(editor.model, 'applyOperation', (evt, args) => {
|
323
|
-
const operation = args[0];
|
324
|
-
// Do not register batch if the operation is not a document operation.
|
325
|
-
// This prevents from creating empty undo steps, where all operations where non-document operations.
|
326
|
-
// Non-document operations creates and alters content in detached tree fragments (for example, document fragments).
|
327
|
-
// Most of time this is preparing data before it is inserted into actual tree (for example during copy & paste).
|
328
|
-
// Such operations should not be reversed.
|
329
|
-
if (!operation.isDocumentOperation) {
|
330
|
-
return;
|
331
|
-
}
|
332
|
-
const batch = operation.batch;
|
333
|
-
const isRedoBatch = this._redoCommand.createdBatches.has(batch);
|
334
|
-
const isUndoBatch = this._undoCommand.createdBatches.has(batch);
|
335
|
-
const wasProcessed = this._batchRegistry.has(batch);
|
336
|
-
// Skip the batch if it was already processed.
|
337
|
-
if (wasProcessed) {
|
338
|
-
return;
|
339
|
-
}
|
340
|
-
// Add the batch to the registry so it will not be processed again.
|
341
|
-
this._batchRegistry.add(batch);
|
342
|
-
if (!batch.isUndoable) {
|
343
|
-
return;
|
344
|
-
}
|
345
|
-
if (isRedoBatch) {
|
346
|
-
// If this batch comes from `redoCommand`, add it to the `undoCommand` stack.
|
347
|
-
this._undoCommand.addBatch(batch);
|
348
|
-
}
|
349
|
-
else if (!isUndoBatch) {
|
350
|
-
// If the batch comes neither from `redoCommand` nor from `undoCommand` then it is a new, regular batch.
|
351
|
-
// Add the batch to the `undoCommand` stack and clear the `redoCommand` stack.
|
352
|
-
this._undoCommand.addBatch(batch);
|
353
|
-
this._redoCommand.clearStack();
|
354
|
-
}
|
355
|
-
}, { priority: 'highest' });
|
356
|
-
this.listenTo(this._undoCommand, 'revert', (evt, undoneBatch, undoingBatch) => {
|
357
|
-
this._redoCommand.addBatch(undoingBatch);
|
358
|
-
});
|
359
|
-
editor.keystrokes.set('CTRL+Z', 'undo');
|
360
|
-
editor.keystrokes.set('CTRL+Y', 'redo');
|
361
|
-
editor.keystrokes.set('CTRL+SHIFT+Z', 'redo');
|
362
|
-
// Add the information about the keystrokes to the accessibility database.
|
363
|
-
editor.accessibility.addKeystrokeInfos({
|
364
|
-
keystrokes: [
|
365
|
-
{
|
366
|
-
label: t('Undo'),
|
367
|
-
keystroke: 'CTRL+Z'
|
368
|
-
},
|
369
|
-
{
|
370
|
-
label: t('Redo'),
|
371
|
-
keystroke: [['CTRL+Y'], ['CTRL+SHIFT+Z']]
|
372
|
-
}
|
373
|
-
]
|
374
|
-
});
|
375
|
-
}
|
376
|
-
}
|
377
|
-
|
378
|
-
/**
|
379
|
-
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
380
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
381
|
-
*/
|
382
|
-
/**
|
383
|
-
* @module undo/undoui
|
384
|
-
*/
|
385
|
-
/**
|
386
|
-
* The undo UI feature. It introduces the `'undo'` and `'redo'` buttons to the editor.
|
387
|
-
*/
|
388
|
-
class UndoUI extends Plugin {
|
389
|
-
/**
|
390
|
-
* @inheritDoc
|
391
|
-
*/
|
392
|
-
static get pluginName() {
|
393
|
-
return 'UndoUI';
|
394
|
-
}
|
395
|
-
/**
|
396
|
-
* @inheritDoc
|
397
|
-
*/
|
398
|
-
init() {
|
399
|
-
const editor = this.editor;
|
400
|
-
const locale = editor.locale;
|
401
|
-
const t = editor.t;
|
402
|
-
const localizedUndoIcon = locale.uiLanguageDirection == 'ltr' ? icons.undo : icons.redo;
|
403
|
-
const localizedRedoIcon = locale.uiLanguageDirection == 'ltr' ? icons.redo : icons.undo;
|
404
|
-
this._addButton('undo', t('Undo'), 'CTRL+Z', localizedUndoIcon);
|
405
|
-
this._addButton('redo', t('Redo'), 'CTRL+Y', localizedRedoIcon);
|
406
|
-
}
|
407
|
-
/**
|
408
|
-
* Creates a button for the specified command.
|
409
|
-
*
|
410
|
-
* @param name Command name.
|
411
|
-
* @param label Button label.
|
412
|
-
* @param keystroke Command keystroke.
|
413
|
-
* @param Icon Source of the icon.
|
414
|
-
*/
|
415
|
-
_addButton(name, label, keystroke, Icon) {
|
416
|
-
const editor = this.editor;
|
417
|
-
editor.ui.componentFactory.add(name, locale => {
|
418
|
-
const command = editor.commands.get(name);
|
419
|
-
const view = new ButtonView(locale);
|
420
|
-
view.set({
|
421
|
-
label,
|
422
|
-
icon: Icon,
|
423
|
-
keystroke,
|
424
|
-
tooltip: true
|
425
|
-
});
|
426
|
-
view.bind('isEnabled').to(command, 'isEnabled');
|
427
|
-
this.listenTo(view, 'execute', () => {
|
428
|
-
editor.execute(name);
|
429
|
-
editor.editing.view.focus();
|
430
|
-
});
|
431
|
-
return view;
|
432
|
-
});
|
433
|
-
}
|
434
|
-
}
|
435
|
-
|
436
|
-
/**
|
437
|
-
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
438
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
439
|
-
*/
|
440
|
-
/**
|
441
|
-
* @module undo/undo
|
442
|
-
*/
|
443
|
-
/**
|
444
|
-
* The undo feature.
|
445
|
-
*
|
446
|
-
* This is a "glue" plugin which loads the {@link module:undo/undoediting~UndoEditing undo editing feature}
|
447
|
-
* and the {@link module:undo/undoui~UndoUI undo UI feature}.
|
448
|
-
*
|
449
|
-
* Below is an explanation of the undo mechanism working together with {@link module:engine/model/history~History History}:
|
450
|
-
*
|
451
|
-
* Whenever an {@link module:engine/model/operation/operation~Operation operation} is applied to the
|
452
|
-
* {@link module:engine/model/document~Document document}, it is saved to `History` as is.
|
453
|
-
* The {@link module:engine/model/batch~Batch batch} that owns that operation is also saved, in
|
454
|
-
* {@link module:undo/undocommand~UndoCommand}, together with the selection that was present in the document before the
|
455
|
-
* operation was applied. A batch is saved instead of the operation because changes are undone batch-by-batch, not operation-by-operation
|
456
|
-
* and a batch is seen as one undo step.
|
457
|
-
*
|
458
|
-
* After changes happen to the document, the `History` and `UndoCommand` stack can be represented as follows:
|
459
|
-
*
|
460
|
-
* ```
|
461
|
-
* History Undo stack
|
462
|
-
* ============== ==================================
|
463
|
-
* [operation A1] [ batch A ]
|
464
|
-
* [operation B1] [ batch B ]
|
465
|
-
* [operation B2] [ batch C ]
|
466
|
-
* [operation C1]
|
467
|
-
* [operation C2]
|
468
|
-
* [operation B3]
|
469
|
-
* [operation C3]
|
470
|
-
* ```
|
471
|
-
*
|
472
|
-
* Where operations starting with the same letter are from same batch.
|
473
|
-
*
|
474
|
-
* Undoing a batch means that a set of operations which will reverse the effects of that batch needs to be generated.
|
475
|
-
* For example, if a batch added several letters, undoing the batch should remove them. It is important to apply undoing
|
476
|
-
* operations in the reversed order, so if a batch has operation `X`, `Y`, `Z`, reversed operations `Zr`, `Yr` and `Xr`
|
477
|
-
* need to be applied. Otherwise reversed operation `Xr` would operate on a wrong document state, because operation `X`
|
478
|
-
* does not know that operations `Y` and `Z` happened.
|
479
|
-
*
|
480
|
-
* After operations from an undone batch got {@link module:engine/model/operation/operation~Operation#getReversed reversed},
|
481
|
-
* one needs to make sure if they are ready to be applied. In the scenario above, operation `C3` is the last operation and `C3r`
|
482
|
-
* bases on up-to-date document state, so it can be applied to the document.
|
483
|
-
*
|
484
|
-
* ```
|
485
|
-
* History Undo stack
|
486
|
-
* ================= ==================================
|
487
|
-
* [ operation A1 ] [ batch A ]
|
488
|
-
* [ operation B1 ] [ batch B ]
|
489
|
-
* [ operation B2 ] [ processing undoing batch C ]
|
490
|
-
* [ operation C1 ]
|
491
|
-
* [ operation C2 ]
|
492
|
-
* [ operation B3 ]
|
493
|
-
* [ operation C3 ]
|
494
|
-
* [ operation C3r ]
|
495
|
-
* ```
|
496
|
-
*
|
497
|
-
* Next is operation `C2`, reversed to `C2r`. `C2r` bases on `C2`, so it bases on the wrong document state. It needs to be
|
498
|
-
* transformed by operations from history that happened after it, so it "knows" about them. Let us assume that `C2' = C2r * B3 * C3 * C3r`,
|
499
|
-
* where `*` means "transformed by". Rest of operations from that batch are processed in the same fashion.
|
500
|
-
*
|
501
|
-
* ```
|
502
|
-
* History Undo stack Redo stack
|
503
|
-
* ================= ================================== ==================================
|
504
|
-
* [ operation A1 ] [ batch A ] [ batch Cr ]
|
505
|
-
* [ operation B1 ] [ batch B ]
|
506
|
-
* [ operation B2 ]
|
507
|
-
* [ operation C1 ]
|
508
|
-
* [ operation C2 ]
|
509
|
-
* [ operation B3 ]
|
510
|
-
* [ operation C3 ]
|
511
|
-
* [ operation C3r ]
|
512
|
-
* [ operation C2' ]
|
513
|
-
* [ operation C1' ]
|
514
|
-
* ```
|
515
|
-
*
|
516
|
-
* Selective undo works on the same basis, however, instead of undoing the last batch in the undo stack, any batch can be undone.
|
517
|
-
* The same algorithm applies: operations from a batch (i.e. `A1`) are reversed and then transformed by operations stored in history.
|
518
|
-
*
|
519
|
-
* Redo also is very similar to undo. It has its own stack that is filled with undoing (reversed batches). Operations from
|
520
|
-
* the batch that is re-done are reversed-back, transformed in proper order and applied to the document.
|
521
|
-
*
|
522
|
-
* ```
|
523
|
-
* History Undo stack Redo stack
|
524
|
-
* ================= ================================== ==================================
|
525
|
-
* [ operation A1 ] [ batch A ]
|
526
|
-
* [ operation B1 ] [ batch B ]
|
527
|
-
* [ operation B2 ] [ batch Crr ]
|
528
|
-
* [ operation C1 ]
|
529
|
-
* [ operation C2 ]
|
530
|
-
* [ operation B3 ]
|
531
|
-
* [ operation C3 ]
|
532
|
-
* [ operation C3r ]
|
533
|
-
* [ operation C2' ]
|
534
|
-
* [ operation C1' ]
|
535
|
-
* [ operation C1'r]
|
536
|
-
* [ operation C2'r]
|
537
|
-
* [ operation C3rr]
|
538
|
-
* ```
|
539
|
-
*/
|
540
|
-
class Undo extends Plugin {
|
541
|
-
/**
|
542
|
-
* @inheritDoc
|
543
|
-
*/
|
544
|
-
static get requires() {
|
545
|
-
return [UndoEditing, UndoUI];
|
546
|
-
}
|
547
|
-
/**
|
548
|
-
* @inheritDoc
|
549
|
-
*/
|
550
|
-
static get pluginName() {
|
551
|
-
return 'Undo';
|
552
|
-
}
|
553
|
-
}
|
554
|
-
|
555
|
-
export { Undo, UndoEditing, UndoUI };
|
556
|
-
//# sourceMappingURL=index.js.map
|