@y/y 14.0.0-16 → 14.0.0-17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-DyTeTfmj.js → index-BV-j5wdP.js} +2 -2
- package/dist/{index-R7GxO-36.js.map → index-BV-j5wdP.js.map} +1 -1
- package/dist/{internals.mjs → internals.js} +1 -1
- package/dist/internals.js.map +1 -0
- package/dist/{testHelper.mjs → testHelper.js} +2 -2
- package/dist/testHelper.js.map +1 -0
- package/dist/{yjs.mjs → yjs.js} +2 -2
- package/dist/yjs.js.map +1 -0
- package/package.json +8 -17
- package/dist/Skip-j0kX7pdq.js +0 -12173
- package/dist/Skip-j0kX7pdq.js.map +0 -1
- package/dist/index-DyTeTfmj.js.map +0 -1
- package/dist/index-R7GxO-36.js +0 -165
- package/dist/internals.cjs +0 -286
- package/dist/internals.cjs.map +0 -1
- package/dist/internals.mjs.map +0 -1
- package/dist/testHelper.cjs +0 -780
- package/dist/testHelper.cjs.map +0 -1
- package/dist/testHelper.mjs.map +0 -1
- package/dist/yjs.cjs +0 -151
- package/dist/yjs.cjs.map +0 -1
- package/dist/yjs.mjs.map +0 -1
- package/src/index.js +0 -153
- package/src/internals.js +0 -44
- package/src/structs/AbstractStruct.js +0 -59
- package/src/structs/ContentAny.js +0 -115
- package/src/structs/ContentBinary.js +0 -93
- package/src/structs/ContentDeleted.js +0 -101
- package/src/structs/ContentDoc.js +0 -141
- package/src/structs/ContentEmbed.js +0 -98
- package/src/structs/ContentFormat.js +0 -105
- package/src/structs/ContentJSON.js +0 -119
- package/src/structs/ContentString.js +0 -113
- package/src/structs/ContentType.js +0 -176
- package/src/structs/GC.js +0 -80
- package/src/structs/Item.js +0 -845
- package/src/structs/Skip.js +0 -75
- package/src/types/AbstractType.js +0 -1434
- package/src/types/YArray.js +0 -270
- package/src/types/YMap.js +0 -244
- package/src/types/YText.js +0 -934
- package/src/types/YXmlElement.js +0 -227
- package/src/types/YXmlFragment.js +0 -266
- package/src/types/YXmlHook.js +0 -68
- package/src/types/YXmlText.js +0 -66
- package/src/utils/AbstractConnector.js +0 -25
- package/src/utils/AttributionManager.js +0 -619
- package/src/utils/Doc.js +0 -372
- package/src/utils/EventHandler.js +0 -87
- package/src/utils/ID.js +0 -89
- package/src/utils/IdMap.js +0 -629
- package/src/utils/IdSet.js +0 -823
- package/src/utils/RelativePosition.js +0 -352
- package/src/utils/Snapshot.js +0 -220
- package/src/utils/StructSet.js +0 -137
- package/src/utils/StructStore.js +0 -289
- package/src/utils/Transaction.js +0 -489
- package/src/utils/UndoManager.js +0 -391
- package/src/utils/UpdateDecoder.js +0 -281
- package/src/utils/UpdateEncoder.js +0 -320
- package/src/utils/YEvent.js +0 -216
- package/src/utils/delta-helpers.js +0 -54
- package/src/utils/encoding.js +0 -623
- package/src/utils/isParentOf.js +0 -21
- package/src/utils/logging.js +0 -21
- package/src/utils/types.js +0 -28
- package/src/utils/updates.js +0 -715
- package/tests/testHelper.js +0 -600
package/src/utils/UndoManager.js
DELETED
|
@@ -1,391 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
mergeIdSets,
|
|
3
|
-
iterateStructsByIdSet,
|
|
4
|
-
keepItem,
|
|
5
|
-
transact,
|
|
6
|
-
createID,
|
|
7
|
-
redoItem,
|
|
8
|
-
isParentOf,
|
|
9
|
-
followRedone,
|
|
10
|
-
getItemCleanStart,
|
|
11
|
-
YEvent, Transaction, Doc, Item, GC, IdSet, AbstractType // eslint-disable-line
|
|
12
|
-
} from '../internals.js'
|
|
13
|
-
|
|
14
|
-
import * as time from 'lib0/time'
|
|
15
|
-
import * as array from 'lib0/array'
|
|
16
|
-
import * as logging from 'lib0/logging'
|
|
17
|
-
import { ObservableV2 } from 'lib0/observable'
|
|
18
|
-
|
|
19
|
-
export class StackItem {
|
|
20
|
-
/**
|
|
21
|
-
* @param {IdSet} deletions
|
|
22
|
-
* @param {IdSet} insertions
|
|
23
|
-
*/
|
|
24
|
-
constructor (deletions, insertions) {
|
|
25
|
-
this.insertions = insertions
|
|
26
|
-
this.deletions = deletions
|
|
27
|
-
/**
|
|
28
|
-
* Use this to save and restore metadata like selection range
|
|
29
|
-
*/
|
|
30
|
-
this.meta = new Map()
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* @param {Transaction} tr
|
|
35
|
-
* @param {UndoManager} um
|
|
36
|
-
* @param {StackItem} stackItem
|
|
37
|
-
*/
|
|
38
|
-
const clearUndoManagerStackItem = (tr, um, stackItem) => {
|
|
39
|
-
iterateStructsByIdSet(tr, stackItem.deletions, item => {
|
|
40
|
-
if (item instanceof Item && um.scope.some(type => type === tr.doc || isParentOf(/** @type {import('../utils/types.js').YType} */ (type), item))) {
|
|
41
|
-
keepItem(item, false)
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* @param {UndoManager} undoManager
|
|
48
|
-
* @param {Array<StackItem>} stack
|
|
49
|
-
* @param {'undo'|'redo'} eventType
|
|
50
|
-
* @return {StackItem?}
|
|
51
|
-
*/
|
|
52
|
-
const popStackItem = (undoManager, stack, eventType) => {
|
|
53
|
-
/**
|
|
54
|
-
* Keep a reference to the transaction so we can fire the event with the changedParentTypes
|
|
55
|
-
* @type {any}
|
|
56
|
-
*/
|
|
57
|
-
let _tr = null
|
|
58
|
-
const doc = undoManager.doc
|
|
59
|
-
const scope = undoManager.scope
|
|
60
|
-
transact(doc, transaction => {
|
|
61
|
-
while (stack.length > 0 && undoManager.currStackItem === null) {
|
|
62
|
-
const store = doc.store
|
|
63
|
-
const stackItem = /** @type {StackItem} */ (stack.pop())
|
|
64
|
-
/**
|
|
65
|
-
* @type {Set<Item>}
|
|
66
|
-
*/
|
|
67
|
-
const itemsToRedo = new Set()
|
|
68
|
-
/**
|
|
69
|
-
* @type {Array<Item>}
|
|
70
|
-
*/
|
|
71
|
-
const itemsToDelete = []
|
|
72
|
-
let performedChange = false
|
|
73
|
-
iterateStructsByIdSet(transaction, stackItem.insertions, struct => {
|
|
74
|
-
if (struct instanceof Item) {
|
|
75
|
-
if (struct.redone !== null) {
|
|
76
|
-
let { item, diff } = followRedone(store, struct.id)
|
|
77
|
-
if (diff > 0) {
|
|
78
|
-
item = getItemCleanStart(transaction, createID(item.id.client, item.id.clock + diff))
|
|
79
|
-
}
|
|
80
|
-
struct = item
|
|
81
|
-
}
|
|
82
|
-
if (!struct.deleted && scope.some(type => type === transaction.doc || isParentOf(/** @type {import('../utils/types.js').YType} */ (type), /** @type {Item} */ (struct)))) {
|
|
83
|
-
itemsToDelete.push(struct)
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
})
|
|
87
|
-
iterateStructsByIdSet(transaction, stackItem.deletions, struct => {
|
|
88
|
-
if (
|
|
89
|
-
struct instanceof Item &&
|
|
90
|
-
scope.some(type => type === transaction.doc || isParentOf(/** @type {import('../utils/types.js').YType} */ (type), struct)) &&
|
|
91
|
-
// Never redo structs in stackItem.insertions because they were created and deleted in the same capture interval.
|
|
92
|
-
!stackItem.insertions.hasId(struct.id)
|
|
93
|
-
) {
|
|
94
|
-
itemsToRedo.add(struct)
|
|
95
|
-
}
|
|
96
|
-
})
|
|
97
|
-
itemsToRedo.forEach(struct => {
|
|
98
|
-
performedChange = redoItem(transaction, struct, itemsToRedo, stackItem.insertions, undoManager.ignoreRemoteMapChanges, undoManager) !== null || performedChange
|
|
99
|
-
})
|
|
100
|
-
// We want to delete in reverse order so that children are deleted before
|
|
101
|
-
// parents, so we have more information available when items are filtered.
|
|
102
|
-
for (let i = itemsToDelete.length - 1; i >= 0; i--) {
|
|
103
|
-
const item = itemsToDelete[i]
|
|
104
|
-
if (undoManager.deleteFilter(item)) {
|
|
105
|
-
item.delete(transaction)
|
|
106
|
-
performedChange = true
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
undoManager.currStackItem = performedChange ? stackItem : null
|
|
110
|
-
}
|
|
111
|
-
transaction.changed.forEach((subProps, type) => {
|
|
112
|
-
// destroy search marker if necessary
|
|
113
|
-
if (subProps.has(null) && type._searchMarker) {
|
|
114
|
-
type._searchMarker.length = 0
|
|
115
|
-
}
|
|
116
|
-
})
|
|
117
|
-
_tr = transaction
|
|
118
|
-
}, undoManager)
|
|
119
|
-
const res = undoManager.currStackItem
|
|
120
|
-
if (res != null) {
|
|
121
|
-
const changedParentTypes = _tr.changedParentTypes
|
|
122
|
-
undoManager.emit('stack-item-popped', [{ stackItem: res, type: eventType, changedParentTypes, origin: undoManager }, undoManager])
|
|
123
|
-
undoManager.currStackItem = null
|
|
124
|
-
}
|
|
125
|
-
return res
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* @typedef {Object} UndoManagerOptions
|
|
130
|
-
* @property {number} [UndoManagerOptions.captureTimeout=500]
|
|
131
|
-
* @property {function(Transaction):boolean} [UndoManagerOptions.captureTransaction] Do not capture changes of a Transaction if result false.
|
|
132
|
-
* @property {function(Item):boolean} [UndoManagerOptions.deleteFilter=()=>true] Sometimes
|
|
133
|
-
* it is necessary to filter what an Undo/Redo operation can delete. If this
|
|
134
|
-
* filter returns false, the type/item won't be deleted even it is in the
|
|
135
|
-
* undo/redo scope.
|
|
136
|
-
* @property {Set<any>} [UndoManagerOptions.trackedOrigins=new Set([null])]
|
|
137
|
-
* @property {boolean} [ignoreRemoteMapChanges] Experimental. By default, the UndoManager will never overwrite remote changes. Enable this property to enable overwriting remote changes on key-value changes (Y.Map, properties on Y.Xml, etc..).
|
|
138
|
-
* @property {Doc} [doc] The document that this UndoManager operates on. Only needed if typeScope is empty.
|
|
139
|
-
*/
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* @typedef {Object} StackItemEvent
|
|
143
|
-
* @property {StackItem} StackItemEvent.stackItem
|
|
144
|
-
* @property {any} StackItemEvent.origin
|
|
145
|
-
* @property {'undo'|'redo'} StackItemEvent.type
|
|
146
|
-
* @property {Map<import('../utils/types.js').YType,Array<YEvent<any>>>} StackItemEvent.changedParentTypes
|
|
147
|
-
*/
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Fires 'stack-item-added' event when a stack item was added to either the undo- or
|
|
151
|
-
* the redo-stack. You may store additional stack information via the
|
|
152
|
-
* metadata property on `event.stackItem.meta` (it is a `Map` of metadata properties).
|
|
153
|
-
* Fires 'stack-item-popped' event when a stack item was popped from either the
|
|
154
|
-
* undo- or the redo-stack. You may restore the saved stack information from `event.stackItem.meta`.
|
|
155
|
-
*
|
|
156
|
-
* @extends {ObservableV2<{'stack-item-added':function(StackItemEvent, UndoManager):void, 'stack-item-popped': function(StackItemEvent, UndoManager):void, 'stack-cleared': function({ undoStackCleared: boolean, redoStackCleared: boolean }):void, 'stack-item-updated': function(StackItemEvent, UndoManager):void }>}
|
|
157
|
-
*/
|
|
158
|
-
export class UndoManager extends ObservableV2 {
|
|
159
|
-
/**
|
|
160
|
-
* @param {Doc|import('../utils/types.js').YType|Array<import('../utils/types.js').YType>} typeScope Limits the scope of the UndoManager. If this is set to a ydoc instance, all changes on that ydoc will be undone. If set to a specific type, only changes on that type or its children will be undone. Also accepts an array of types.
|
|
161
|
-
* @param {UndoManagerOptions} options
|
|
162
|
-
*/
|
|
163
|
-
constructor (typeScope, {
|
|
164
|
-
captureTimeout = 500,
|
|
165
|
-
captureTransaction = _tr => true,
|
|
166
|
-
deleteFilter = () => true,
|
|
167
|
-
trackedOrigins = new Set([null]),
|
|
168
|
-
ignoreRemoteMapChanges = false,
|
|
169
|
-
doc = /** @type {Doc} */ (array.isArray(typeScope) ? typeScope[0].doc : typeScope instanceof Doc ? typeScope : typeScope.doc)
|
|
170
|
-
} = {}) {
|
|
171
|
-
super()
|
|
172
|
-
/**
|
|
173
|
-
* @type {Array<import('../utils/types.js').YType | Doc>}
|
|
174
|
-
*/
|
|
175
|
-
this.scope = []
|
|
176
|
-
this.doc = doc
|
|
177
|
-
this.addToScope(typeScope)
|
|
178
|
-
this.deleteFilter = deleteFilter
|
|
179
|
-
trackedOrigins.add(this)
|
|
180
|
-
this.trackedOrigins = trackedOrigins
|
|
181
|
-
this.captureTransaction = captureTransaction
|
|
182
|
-
/**
|
|
183
|
-
* @type {Array<StackItem>}
|
|
184
|
-
*/
|
|
185
|
-
this.undoStack = []
|
|
186
|
-
/**
|
|
187
|
-
* @type {Array<StackItem>}
|
|
188
|
-
*/
|
|
189
|
-
this.redoStack = []
|
|
190
|
-
/**
|
|
191
|
-
* Whether the client is currently undoing (calling UndoManager.undo)
|
|
192
|
-
*
|
|
193
|
-
* @type {boolean}
|
|
194
|
-
*/
|
|
195
|
-
this.undoing = false
|
|
196
|
-
this.redoing = false
|
|
197
|
-
/**
|
|
198
|
-
* The currently popped stack item if UndoManager.undoing or UndoManager.redoing
|
|
199
|
-
*
|
|
200
|
-
* @type {StackItem|null}
|
|
201
|
-
*/
|
|
202
|
-
this.currStackItem = null
|
|
203
|
-
this.lastChange = 0
|
|
204
|
-
this.ignoreRemoteMapChanges = ignoreRemoteMapChanges
|
|
205
|
-
this.captureTimeout = captureTimeout
|
|
206
|
-
/**
|
|
207
|
-
* @param {Transaction} transaction
|
|
208
|
-
*/
|
|
209
|
-
this.afterTransactionHandler = transaction => {
|
|
210
|
-
// Only track certain transactions
|
|
211
|
-
if (
|
|
212
|
-
!this.captureTransaction(transaction) ||
|
|
213
|
-
!this.scope.some(type => transaction.changedParentTypes.has(/** @type {import('../utils/types.js').YType} */ (type)) || type === this.doc) ||
|
|
214
|
-
(!this.trackedOrigins.has(transaction.origin) && (!transaction.origin || !this.trackedOrigins.has(transaction.origin.constructor)))
|
|
215
|
-
) {
|
|
216
|
-
return
|
|
217
|
-
}
|
|
218
|
-
const undoing = this.undoing
|
|
219
|
-
const redoing = this.redoing
|
|
220
|
-
const stack = undoing ? this.redoStack : this.undoStack
|
|
221
|
-
if (undoing) {
|
|
222
|
-
this.stopCapturing() // next undo should not be appended to last stack item
|
|
223
|
-
} else if (!redoing) {
|
|
224
|
-
// neither undoing nor redoing: delete redoStack
|
|
225
|
-
this.clear(false, true)
|
|
226
|
-
}
|
|
227
|
-
const insertions = transaction.insertSet
|
|
228
|
-
const now = time.getUnixTime()
|
|
229
|
-
let didAdd = false
|
|
230
|
-
if (this.lastChange > 0 && now - this.lastChange < this.captureTimeout && stack.length > 0 && !undoing && !redoing) {
|
|
231
|
-
// append change to last stack op
|
|
232
|
-
const lastOp = stack[stack.length - 1]
|
|
233
|
-
lastOp.deletions = mergeIdSets([lastOp.deletions, transaction.deleteSet])
|
|
234
|
-
lastOp.insertions = mergeIdSets([lastOp.insertions, insertions])
|
|
235
|
-
} else {
|
|
236
|
-
// create a new stack op
|
|
237
|
-
stack.push(new StackItem(transaction.deleteSet, insertions))
|
|
238
|
-
didAdd = true
|
|
239
|
-
}
|
|
240
|
-
if (!undoing && !redoing) {
|
|
241
|
-
this.lastChange = now
|
|
242
|
-
}
|
|
243
|
-
// make sure that deleted structs are not gc'd
|
|
244
|
-
iterateStructsByIdSet(transaction, transaction.deleteSet, /** @param {Item|GC} item */ item => {
|
|
245
|
-
if (item instanceof Item && this.scope.some(type => type === transaction.doc || isParentOf(/** @type {import('../utils/types.js').YType} */ (type), item))) {
|
|
246
|
-
keepItem(item, true)
|
|
247
|
-
}
|
|
248
|
-
})
|
|
249
|
-
/**
|
|
250
|
-
* @type {[StackItemEvent, UndoManager]}
|
|
251
|
-
*/
|
|
252
|
-
const changeEvent = [{ stackItem: stack[stack.length - 1], origin: transaction.origin, type: undoing ? 'redo' : 'undo', changedParentTypes: transaction.changedParentTypes }, this]
|
|
253
|
-
if (didAdd) {
|
|
254
|
-
this.emit('stack-item-added', changeEvent)
|
|
255
|
-
} else {
|
|
256
|
-
this.emit('stack-item-updated', changeEvent)
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
this.doc.on('afterTransaction', this.afterTransactionHandler)
|
|
260
|
-
this.doc.on('destroy', () => {
|
|
261
|
-
this.destroy()
|
|
262
|
-
})
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Extend the scope.
|
|
267
|
-
*
|
|
268
|
-
* @param {Array<import('../utils/types.js').YType | Doc> | import('../utils/types.js').YType | Doc} ytypes
|
|
269
|
-
*/
|
|
270
|
-
addToScope (ytypes) {
|
|
271
|
-
const tmpSet = new Set(this.scope)
|
|
272
|
-
ytypes = array.isArray(ytypes) ? ytypes : [ytypes]
|
|
273
|
-
ytypes.forEach(ytype => {
|
|
274
|
-
if (!tmpSet.has(ytype)) {
|
|
275
|
-
tmpSet.add(ytype)
|
|
276
|
-
if (ytype instanceof AbstractType ? ytype.doc !== this.doc : ytype !== this.doc) logging.warn('[yjs#509] Not same Y.Doc') // use MultiDocUndoManager instead. also see https://github.com/yjs/yjs/issues/509
|
|
277
|
-
this.scope.push(ytype)
|
|
278
|
-
}
|
|
279
|
-
})
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* @param {any} origin
|
|
284
|
-
*/
|
|
285
|
-
addTrackedOrigin (origin) {
|
|
286
|
-
this.trackedOrigins.add(origin)
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* @param {any} origin
|
|
291
|
-
*/
|
|
292
|
-
removeTrackedOrigin (origin) {
|
|
293
|
-
this.trackedOrigins.delete(origin)
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
clear (clearUndoStack = true, clearRedoStack = true) {
|
|
297
|
-
if ((clearUndoStack && this.canUndo()) || (clearRedoStack && this.canRedo())) {
|
|
298
|
-
this.doc.transact(tr => {
|
|
299
|
-
if (clearUndoStack) {
|
|
300
|
-
this.undoStack.forEach(item => clearUndoManagerStackItem(tr, this, item))
|
|
301
|
-
this.undoStack = []
|
|
302
|
-
}
|
|
303
|
-
if (clearRedoStack) {
|
|
304
|
-
this.redoStack.forEach(item => clearUndoManagerStackItem(tr, this, item))
|
|
305
|
-
this.redoStack = []
|
|
306
|
-
}
|
|
307
|
-
this.emit('stack-cleared', [{ undoStackCleared: clearUndoStack, redoStackCleared: clearRedoStack }])
|
|
308
|
-
})
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* UndoManager merges Undo-StackItem if they are created within time-gap
|
|
314
|
-
* smaller than `options.captureTimeout`. Call `um.stopCapturing()` so that the next
|
|
315
|
-
* StackItem won't be merged.
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
* @example
|
|
319
|
-
* // without stopCapturing
|
|
320
|
-
* ytext.insert(0, 'a')
|
|
321
|
-
* ytext.insert(1, 'b')
|
|
322
|
-
* um.undo()
|
|
323
|
-
* ytext.toString() // => '' (note that 'ab' was removed)
|
|
324
|
-
* // with stopCapturing
|
|
325
|
-
* ytext.insert(0, 'a')
|
|
326
|
-
* um.stopCapturing()
|
|
327
|
-
* ytext.insert(0, 'b')
|
|
328
|
-
* um.undo()
|
|
329
|
-
* ytext.toString() // => 'a' (note that only 'b' was removed)
|
|
330
|
-
*
|
|
331
|
-
*/
|
|
332
|
-
stopCapturing () {
|
|
333
|
-
this.lastChange = 0
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* Undo last changes on type.
|
|
338
|
-
*
|
|
339
|
-
* @return {StackItem?} Returns StackItem if a change was applied
|
|
340
|
-
*/
|
|
341
|
-
undo () {
|
|
342
|
-
this.undoing = true
|
|
343
|
-
let res
|
|
344
|
-
try {
|
|
345
|
-
res = popStackItem(this, this.undoStack, 'undo')
|
|
346
|
-
} finally {
|
|
347
|
-
this.undoing = false
|
|
348
|
-
}
|
|
349
|
-
return res
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Redo last undo operation.
|
|
354
|
-
*
|
|
355
|
-
* @return {StackItem?} Returns StackItem if a change was applied
|
|
356
|
-
*/
|
|
357
|
-
redo () {
|
|
358
|
-
this.redoing = true
|
|
359
|
-
let res
|
|
360
|
-
try {
|
|
361
|
-
res = popStackItem(this, this.redoStack, 'redo')
|
|
362
|
-
} finally {
|
|
363
|
-
this.redoing = false
|
|
364
|
-
}
|
|
365
|
-
return res
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Are undo steps available?
|
|
370
|
-
*
|
|
371
|
-
* @return {boolean} `true` if undo is possible
|
|
372
|
-
*/
|
|
373
|
-
canUndo () {
|
|
374
|
-
return this.undoStack.length > 0
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Are redo steps available?
|
|
379
|
-
*
|
|
380
|
-
* @return {boolean} `true` if redo is possible
|
|
381
|
-
*/
|
|
382
|
-
canRedo () {
|
|
383
|
-
return this.redoStack.length > 0
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
destroy () {
|
|
387
|
-
this.trackedOrigins.delete(this)
|
|
388
|
-
this.doc.off('afterTransaction', this.afterTransactionHandler)
|
|
389
|
-
super.destroy()
|
|
390
|
-
}
|
|
391
|
-
}
|
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
import * as buffer from 'lib0/buffer'
|
|
2
|
-
import * as decoding from 'lib0/decoding'
|
|
3
|
-
import {
|
|
4
|
-
ID, createID
|
|
5
|
-
} from '../internals.js'
|
|
6
|
-
|
|
7
|
-
export class DSDecoderV1 {
|
|
8
|
-
/**
|
|
9
|
-
* @param {decoding.Decoder} decoder
|
|
10
|
-
*/
|
|
11
|
-
constructor (decoder) {
|
|
12
|
-
this.restDecoder = decoder
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
resetDsCurVal () {
|
|
16
|
-
// nop
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @return {number}
|
|
21
|
-
*/
|
|
22
|
-
readDsClock () {
|
|
23
|
-
return decoding.readVarUint(this.restDecoder)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @return {number}
|
|
28
|
-
*/
|
|
29
|
-
readDsLen () {
|
|
30
|
-
return decoding.readVarUint(this.restDecoder)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class UpdateDecoderV1 extends DSDecoderV1 {
|
|
35
|
-
/**
|
|
36
|
-
* @return {ID}
|
|
37
|
-
*/
|
|
38
|
-
readLeftID () {
|
|
39
|
-
return createID(decoding.readVarUint(this.restDecoder), decoding.readVarUint(this.restDecoder))
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @return {ID}
|
|
44
|
-
*/
|
|
45
|
-
readRightID () {
|
|
46
|
-
return createID(decoding.readVarUint(this.restDecoder), decoding.readVarUint(this.restDecoder))
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Read the next client id.
|
|
51
|
-
* Use this in favor of readID whenever possible to reduce the number of objects created.
|
|
52
|
-
*/
|
|
53
|
-
readClient () {
|
|
54
|
-
return decoding.readVarUint(this.restDecoder)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* @return {number} info An unsigned 8-bit integer
|
|
59
|
-
*/
|
|
60
|
-
readInfo () {
|
|
61
|
-
return decoding.readUint8(this.restDecoder)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* @return {string}
|
|
66
|
-
*/
|
|
67
|
-
readString () {
|
|
68
|
-
return decoding.readVarString(this.restDecoder)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* @return {boolean} isKey
|
|
73
|
-
*/
|
|
74
|
-
readParentInfo () {
|
|
75
|
-
return decoding.readVarUint(this.restDecoder) === 1
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* @return {number} info An unsigned 8-bit integer
|
|
80
|
-
*/
|
|
81
|
-
readTypeRef () {
|
|
82
|
-
return decoding.readVarUint(this.restDecoder)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Write len of a struct - well suited for Opt RLE encoder.
|
|
87
|
-
*
|
|
88
|
-
* @return {number} len
|
|
89
|
-
*/
|
|
90
|
-
readLen () {
|
|
91
|
-
return decoding.readVarUint(this.restDecoder)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* @return {any}
|
|
96
|
-
*/
|
|
97
|
-
readAny () {
|
|
98
|
-
return decoding.readAny(this.restDecoder)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* @return {Uint8Array}
|
|
103
|
-
*/
|
|
104
|
-
readBuf () {
|
|
105
|
-
return buffer.copyUint8Array(decoding.readVarUint8Array(this.restDecoder))
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Legacy implementation uses JSON parse. We use any-decoding in v2.
|
|
110
|
-
*
|
|
111
|
-
* @return {any}
|
|
112
|
-
*/
|
|
113
|
-
readJSON () {
|
|
114
|
-
return JSON.parse(decoding.readVarString(this.restDecoder))
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* @return {string}
|
|
119
|
-
*/
|
|
120
|
-
readKey () {
|
|
121
|
-
return decoding.readVarString(this.restDecoder)
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export class DSDecoderV2 {
|
|
126
|
-
/**
|
|
127
|
-
* @param {decoding.Decoder} decoder
|
|
128
|
-
*/
|
|
129
|
-
constructor (decoder) {
|
|
130
|
-
/**
|
|
131
|
-
* @private
|
|
132
|
-
*/
|
|
133
|
-
this.dsCurrVal = 0
|
|
134
|
-
this.restDecoder = decoder
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
resetDsCurVal () {
|
|
138
|
-
this.dsCurrVal = 0
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* @return {number}
|
|
143
|
-
*/
|
|
144
|
-
readDsClock () {
|
|
145
|
-
this.dsCurrVal += decoding.readVarUint(this.restDecoder)
|
|
146
|
-
return this.dsCurrVal
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* @return {number}
|
|
151
|
-
*/
|
|
152
|
-
readDsLen () {
|
|
153
|
-
const diff = decoding.readVarUint(this.restDecoder) + 1
|
|
154
|
-
this.dsCurrVal += diff
|
|
155
|
-
return diff
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export class UpdateDecoderV2 extends DSDecoderV2 {
|
|
160
|
-
/**
|
|
161
|
-
* @param {decoding.Decoder} decoder
|
|
162
|
-
*/
|
|
163
|
-
constructor (decoder) {
|
|
164
|
-
super(decoder)
|
|
165
|
-
/**
|
|
166
|
-
* List of cached keys. If the keys[id] does not exist, we read a new key
|
|
167
|
-
* from stringEncoder and push it to keys.
|
|
168
|
-
*
|
|
169
|
-
* @type {Array<string>}
|
|
170
|
-
*/
|
|
171
|
-
this.keys = []
|
|
172
|
-
decoding.readVarUint(decoder) // read feature flag - currently unused
|
|
173
|
-
this.keyClockDecoder = new decoding.IntDiffOptRleDecoder(decoding.readVarUint8Array(decoder))
|
|
174
|
-
this.clientDecoder = new decoding.UintOptRleDecoder(decoding.readVarUint8Array(decoder))
|
|
175
|
-
this.leftClockDecoder = new decoding.IntDiffOptRleDecoder(decoding.readVarUint8Array(decoder))
|
|
176
|
-
this.rightClockDecoder = new decoding.IntDiffOptRleDecoder(decoding.readVarUint8Array(decoder))
|
|
177
|
-
this.infoDecoder = new decoding.RleDecoder(decoding.readVarUint8Array(decoder), decoding.readUint8)
|
|
178
|
-
this.stringDecoder = new decoding.StringDecoder(decoding.readVarUint8Array(decoder))
|
|
179
|
-
this.parentInfoDecoder = new decoding.RleDecoder(decoding.readVarUint8Array(decoder), decoding.readUint8)
|
|
180
|
-
this.typeRefDecoder = new decoding.UintOptRleDecoder(decoding.readVarUint8Array(decoder))
|
|
181
|
-
this.lenDecoder = new decoding.UintOptRleDecoder(decoding.readVarUint8Array(decoder))
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* @return {ID}
|
|
186
|
-
*/
|
|
187
|
-
readLeftID () {
|
|
188
|
-
return new ID(this.clientDecoder.read(), this.leftClockDecoder.read())
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* @return {ID}
|
|
193
|
-
*/
|
|
194
|
-
readRightID () {
|
|
195
|
-
return new ID(this.clientDecoder.read(), this.rightClockDecoder.read())
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Read the next client id.
|
|
200
|
-
* Use this in favor of readID whenever possible to reduce the number of objects created.
|
|
201
|
-
*/
|
|
202
|
-
readClient () {
|
|
203
|
-
return this.clientDecoder.read()
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* @return {number} info An unsigned 8-bit integer
|
|
208
|
-
*/
|
|
209
|
-
readInfo () {
|
|
210
|
-
return /** @type {number} */ (this.infoDecoder.read())
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* @return {string}
|
|
215
|
-
*/
|
|
216
|
-
readString () {
|
|
217
|
-
return this.stringDecoder.read()
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* @return {boolean}
|
|
222
|
-
*/
|
|
223
|
-
readParentInfo () {
|
|
224
|
-
return this.parentInfoDecoder.read() === 1
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* @return {number} An unsigned 8-bit integer
|
|
229
|
-
*/
|
|
230
|
-
readTypeRef () {
|
|
231
|
-
return this.typeRefDecoder.read()
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Write len of a struct - well suited for Opt RLE encoder.
|
|
236
|
-
*
|
|
237
|
-
* @return {number}
|
|
238
|
-
*/
|
|
239
|
-
readLen () {
|
|
240
|
-
return this.lenDecoder.read()
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* @return {any}
|
|
245
|
-
*/
|
|
246
|
-
readAny () {
|
|
247
|
-
return decoding.readAny(this.restDecoder)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* @return {Uint8Array}
|
|
252
|
-
*/
|
|
253
|
-
readBuf () {
|
|
254
|
-
return decoding.readVarUint8Array(this.restDecoder)
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* This is mainly here for legacy purposes.
|
|
259
|
-
*
|
|
260
|
-
* Initial we incoded objects using JSON. Now we use the much faster lib0/any-encoder. This method mainly exists for legacy purposes for the v1 encoder.
|
|
261
|
-
*
|
|
262
|
-
* @return {any}
|
|
263
|
-
*/
|
|
264
|
-
readJSON () {
|
|
265
|
-
return decoding.readAny(this.restDecoder)
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* @return {string}
|
|
270
|
-
*/
|
|
271
|
-
readKey () {
|
|
272
|
-
const keyClock = this.keyClockDecoder.read()
|
|
273
|
-
if (keyClock < this.keys.length) {
|
|
274
|
-
return this.keys[keyClock]
|
|
275
|
-
} else {
|
|
276
|
-
const key = this.stringDecoder.read()
|
|
277
|
-
this.keys.push(key)
|
|
278
|
-
return key
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|