@y/y 14.0.0-18 → 14.0.0-20

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.
Files changed (129) hide show
  1. package/README.md +7 -5
  2. package/dist/src/index.d.ts +2 -1
  3. package/dist/src/internals.d.ts +2 -9
  4. package/dist/src/structs/ContentType.d.ts +6 -12
  5. package/dist/src/structs/ContentType.d.ts.map +1 -1
  6. package/dist/src/structs/Item.d.ts +5 -6
  7. package/dist/src/structs/Item.d.ts.map +1 -1
  8. package/dist/src/utils/AttributionManager.d.ts +20 -6
  9. package/dist/src/utils/AttributionManager.d.ts.map +1 -1
  10. package/dist/src/utils/Doc.d.ts +7 -70
  11. package/dist/src/utils/Doc.d.ts.map +1 -1
  12. package/dist/src/utils/ID.d.ts +2 -2
  13. package/dist/src/utils/ID.d.ts.map +1 -1
  14. package/dist/src/utils/IdMap.d.ts +19 -16
  15. package/dist/src/utils/IdMap.d.ts.map +1 -1
  16. package/dist/src/utils/IdSet.d.ts +2 -2
  17. package/dist/src/utils/IdSet.d.ts.map +1 -1
  18. package/dist/src/utils/RelativePosition.d.ts +8 -8
  19. package/dist/src/utils/RelativePosition.d.ts.map +1 -1
  20. package/dist/src/utils/Transaction.d.ts +9 -5
  21. package/dist/src/utils/Transaction.d.ts.map +1 -1
  22. package/dist/src/utils/UndoManager.d.ts +14 -12
  23. package/dist/src/utils/UndoManager.d.ts.map +1 -1
  24. package/dist/src/utils/UpdateEncoder.d.ts +2 -0
  25. package/dist/src/utils/UpdateEncoder.d.ts.map +1 -1
  26. package/dist/src/utils/YEvent.d.ts +21 -42
  27. package/dist/src/utils/YEvent.d.ts.map +1 -1
  28. package/dist/src/utils/isParentOf.d.ts +1 -1
  29. package/dist/src/utils/isParentOf.d.ts.map +1 -1
  30. package/dist/src/utils/logging.d.ts +2 -2
  31. package/dist/src/utils/logging.d.ts.map +1 -1
  32. package/dist/src/utils/meta.d.ts +43 -0
  33. package/dist/src/utils/meta.d.ts.map +1 -0
  34. package/dist/src/utils/ts.d.ts +4 -0
  35. package/dist/src/utils/ts.d.ts.map +1 -0
  36. package/dist/src/utils/updates.d.ts +3 -9
  37. package/dist/src/utils/updates.d.ts.map +1 -1
  38. package/dist/src/ytype.d.ts +498 -0
  39. package/dist/src/ytype.d.ts.map +1 -0
  40. package/dist/tests/IdMap.tests.d.ts.map +1 -1
  41. package/dist/tests/attribution.tests.d.ts +1 -0
  42. package/dist/tests/attribution.tests.d.ts.map +1 -1
  43. package/dist/tests/compatibility.tests.d.ts.map +1 -1
  44. package/dist/tests/doc.tests.d.ts.map +1 -1
  45. package/dist/tests/relativePositions.tests.d.ts +9 -9
  46. package/dist/tests/relativePositions.tests.d.ts.map +1 -1
  47. package/dist/tests/snapshot.tests.d.ts.map +1 -1
  48. package/dist/tests/testHelper.d.ts +28 -27
  49. package/dist/tests/testHelper.d.ts.map +1 -1
  50. package/dist/tests/undo-redo.tests.d.ts.map +1 -1
  51. package/dist/tests/updates.tests.d.ts +1 -1
  52. package/dist/tests/updates.tests.d.ts.map +1 -1
  53. package/dist/tests/y-array.tests.d.ts +0 -2
  54. package/dist/tests/y-array.tests.d.ts.map +1 -1
  55. package/dist/tests/y-map.tests.d.ts +0 -3
  56. package/dist/tests/y-map.tests.d.ts.map +1 -1
  57. package/dist/tests/y-text.tests.d.ts +1 -1
  58. package/dist/tests/y-text.tests.d.ts.map +1 -1
  59. package/dist/tests/y-xml.tests.d.ts +0 -1
  60. package/dist/tests/y-xml.tests.d.ts.map +1 -1
  61. package/package.json +16 -16
  62. package/src/index.js +152 -0
  63. package/src/internals.js +35 -0
  64. package/src/structs/AbstractStruct.js +59 -0
  65. package/src/structs/ContentAny.js +115 -0
  66. package/src/structs/ContentBinary.js +93 -0
  67. package/src/structs/ContentDeleted.js +101 -0
  68. package/src/structs/ContentDoc.js +141 -0
  69. package/src/structs/ContentEmbed.js +98 -0
  70. package/src/structs/ContentFormat.js +105 -0
  71. package/src/structs/ContentJSON.js +119 -0
  72. package/src/structs/ContentString.js +113 -0
  73. package/src/structs/ContentType.js +152 -0
  74. package/src/structs/GC.js +80 -0
  75. package/src/structs/Item.js +841 -0
  76. package/src/structs/Skip.js +75 -0
  77. package/src/utils/AttributionManager.js +653 -0
  78. package/src/utils/Doc.js +266 -0
  79. package/src/utils/EventHandler.js +87 -0
  80. package/src/utils/ID.js +89 -0
  81. package/src/utils/IdMap.js +673 -0
  82. package/src/utils/IdSet.js +825 -0
  83. package/src/utils/RelativePosition.js +352 -0
  84. package/src/utils/Snapshot.js +220 -0
  85. package/src/utils/StructSet.js +137 -0
  86. package/src/utils/StructStore.js +289 -0
  87. package/src/utils/Transaction.js +671 -0
  88. package/src/utils/UndoManager.js +406 -0
  89. package/src/utils/UpdateDecoder.js +281 -0
  90. package/src/utils/UpdateEncoder.js +327 -0
  91. package/src/utils/YEvent.js +189 -0
  92. package/src/utils/delta-helpers.js +54 -0
  93. package/src/utils/encoding.js +623 -0
  94. package/src/utils/isParentOf.js +21 -0
  95. package/src/utils/logging.js +21 -0
  96. package/src/utils/meta.js +97 -0
  97. package/src/utils/ts.js +3 -0
  98. package/src/utils/updates.js +711 -0
  99. package/src/ytype.js +1962 -0
  100. package/dist/Skip-wRT7BKFP.js +0 -11877
  101. package/dist/Skip-wRT7BKFP.js.map +0 -1
  102. package/dist/index-BV-j5wdP.js +0 -163
  103. package/dist/index-BV-j5wdP.js.map +0 -1
  104. package/dist/internals.js +0 -25
  105. package/dist/internals.js.map +0 -1
  106. package/dist/src/types/AbstractType.d.ts +0 -239
  107. package/dist/src/types/AbstractType.d.ts.map +0 -1
  108. package/dist/src/types/YArray.d.ts +0 -128
  109. package/dist/src/types/YArray.d.ts.map +0 -1
  110. package/dist/src/types/YMap.d.ts +0 -112
  111. package/dist/src/types/YMap.d.ts.map +0 -1
  112. package/dist/src/types/YText.d.ts +0 -216
  113. package/dist/src/types/YText.d.ts.map +0 -1
  114. package/dist/src/types/YXmlElement.d.ts +0 -106
  115. package/dist/src/types/YXmlElement.d.ts.map +0 -1
  116. package/dist/src/types/YXmlFragment.d.ts +0 -143
  117. package/dist/src/types/YXmlFragment.d.ts.map +0 -1
  118. package/dist/src/types/YXmlHook.d.ts +0 -32
  119. package/dist/src/types/YXmlHook.d.ts.map +0 -1
  120. package/dist/src/types/YXmlText.d.ts +0 -34
  121. package/dist/src/types/YXmlText.d.ts.map +0 -1
  122. package/dist/src/utils/AbstractConnector.d.ts +0 -20
  123. package/dist/src/utils/AbstractConnector.d.ts.map +0 -1
  124. package/dist/src/utils/types.d.ts +0 -7
  125. package/dist/src/utils/types.d.ts.map +0 -1
  126. package/dist/testHelper.js +0 -617
  127. package/dist/testHelper.js.map +0 -1
  128. package/dist/yjs.js +0 -26
  129. package/dist/yjs.js.map +0 -1
@@ -0,0 +1,406 @@
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, YType, // eslint-disable-line
12
+ diffIdSet
13
+ } from '../internals.js'
14
+
15
+ import * as time from 'lib0/time'
16
+ import * as array from 'lib0/array'
17
+ import * as logging from 'lib0/logging'
18
+ import { ObservableV2 } from 'lib0/observable'
19
+
20
+ export class StackItem {
21
+ /**
22
+ * @param {IdSet} insertions
23
+ * @param {IdSet} deletions
24
+ */
25
+ constructor (insertions, deletions) {
26
+ this.inserts = insertions
27
+ this.deletes = deletions
28
+ /**
29
+ * Use this to save and restore metadata like selection range
30
+ */
31
+ this.meta = new Map()
32
+ }
33
+ }
34
+ /**
35
+ * @param {Transaction} tr
36
+ * @param {UndoManager} um
37
+ * @param {StackItem} stackItem
38
+ */
39
+ const clearUndoManagerStackItem = (tr, um, stackItem) => {
40
+ iterateStructsByIdSet(tr, stackItem.deletes, item => {
41
+ if (item instanceof Item && um.scope.some(type => type === tr.doc || isParentOf(/** @type {YType} */ (type), item))) {
42
+ keepItem(item, false)
43
+ }
44
+ })
45
+ }
46
+
47
+ /**
48
+ * @param {UndoManager} undoManager
49
+ * @param {Array<StackItem>} stack
50
+ * @param {'undo'|'redo'} eventType
51
+ * @return {StackItem?}
52
+ */
53
+ const popStackItem = (undoManager, stack, eventType) => {
54
+ /**
55
+ * Keep a reference to the transaction so we can fire the event with the changedParentTypes
56
+ * @type {any}
57
+ */
58
+ let _tr = null
59
+ const doc = undoManager.doc
60
+ const scope = undoManager.scope
61
+ transact(doc, transaction => {
62
+ while (stack.length > 0 && undoManager.currStackItem === null) {
63
+ const store = doc.store
64
+ const stackItem = /** @type {StackItem} */ (stack.pop())
65
+ /**
66
+ * @type {Set<Item>}
67
+ */
68
+ const itemsToRedo = new Set()
69
+ /**
70
+ * @type {Array<Item>}
71
+ */
72
+ const itemsToDelete = []
73
+ let performedChange = false
74
+ iterateStructsByIdSet(transaction, stackItem.inserts, struct => {
75
+ if (struct instanceof Item) {
76
+ if (struct.redone !== null) {
77
+ let { item, diff } = followRedone(store, struct.id)
78
+ if (diff > 0) {
79
+ item = getItemCleanStart(transaction, createID(item.id.client, item.id.clock + diff))
80
+ }
81
+ struct = item
82
+ }
83
+ if (!struct.deleted && scope.some(type => type === transaction.doc || isParentOf(/** @type {YType} */ (type), /** @type {Item} */ (struct)))) {
84
+ itemsToDelete.push(struct)
85
+ }
86
+ }
87
+ })
88
+ iterateStructsByIdSet(transaction, stackItem.deletes, struct => {
89
+ if (
90
+ struct instanceof Item &&
91
+ scope.some(type => type === transaction.doc || isParentOf(/** @type {YType} */ (type), struct)) &&
92
+ // Never redo structs in stackItem.insertions because they were created and deleted in the same capture interval.
93
+ !stackItem.inserts.hasId(struct.id)
94
+ ) {
95
+ itemsToRedo.add(struct)
96
+ }
97
+ })
98
+ itemsToRedo.forEach(struct => {
99
+ performedChange = redoItem(transaction, struct, itemsToRedo, stackItem.inserts, undoManager.ignoreRemoteMapChanges, undoManager) !== null || performedChange
100
+ })
101
+ // We want to delete in reverse order so that children are deleted before
102
+ // parents, so we have more information available when items are filtered.
103
+ for (let i = itemsToDelete.length - 1; i >= 0; i--) {
104
+ const item = itemsToDelete[i]
105
+ if (undoManager.deleteFilter(item)) {
106
+ item.delete(transaction)
107
+ performedChange = true
108
+ }
109
+ }
110
+ undoManager.currStackItem = performedChange ? stackItem : null
111
+ }
112
+ transaction.changed.forEach((subProps, type) => {
113
+ // destroy search marker if necessary
114
+ if (subProps.has(null) && type._searchMarker) {
115
+ type._searchMarker.length = 0
116
+ }
117
+ })
118
+ _tr = transaction
119
+ }, undoManager)
120
+ const res = undoManager.currStackItem
121
+ if (res != null) {
122
+ const changedParentTypes = _tr.changedParentTypes
123
+ undoManager.emit('stack-item-popped', [{ stackItem: res, type: eventType, changedParentTypes, origin: undoManager }, undoManager])
124
+ undoManager.currStackItem = null
125
+ }
126
+ return res
127
+ }
128
+
129
+ /**
130
+ * @typedef {Object} UndoManagerOptions
131
+ * @property {number} [UndoManagerOptions.captureTimeout=500]
132
+ * @property {function(Transaction):boolean} [UndoManagerOptions.captureTransaction] Do not capture changes of a Transaction if result false.
133
+ * @property {function(Item):boolean} [UndoManagerOptions.deleteFilter=()=>true] Sometimes
134
+ * it is necessary to filter what an Undo/Redo operation can delete. If this
135
+ * filter returns false, the type/item won't be deleted even it is in the
136
+ * undo/redo scope.
137
+ * @property {Set<any>} [UndoManagerOptions.trackedOrigins=new Set([null])]
138
+ * @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..).
139
+ * @property {Doc} [doc] The document that this UndoManager operates on. Only needed if typeScope is empty.
140
+ */
141
+
142
+ /**
143
+ * @typedef {Object} StackItemEvent
144
+ * @property {StackItem} StackItemEvent.stackItem
145
+ * @property {any} StackItemEvent.origin
146
+ * @property {'undo'|'redo'} StackItemEvent.type
147
+ * @property {Map<YType,Array<YEvent<any>>>} StackItemEvent.changedParentTypes
148
+ */
149
+
150
+ /**
151
+ * Fires 'stack-item-added' event when a stack item was added to either the undo- or
152
+ * the redo-stack. You may store additional stack information via the
153
+ * metadata property on `event.stackItem.meta` (it is a `Map` of metadata properties).
154
+ * Fires 'stack-item-popped' event when a stack item was popped from either the
155
+ * undo- or the redo-stack. You may restore the saved stack information from `event.stackItem.meta`.
156
+ *
157
+ * @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 }>}
158
+ */
159
+ export class UndoManager extends ObservableV2 {
160
+ /**
161
+ * @param {Doc|YType|Array<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.
162
+ * @param {UndoManagerOptions} options
163
+ */
164
+ constructor (typeScope, {
165
+ captureTimeout = 500,
166
+ captureTransaction = _tr => true,
167
+ deleteFilter = () => true,
168
+ trackedOrigins = new Set([null]),
169
+ ignoreRemoteMapChanges = false,
170
+ doc = /** @type {Doc} */ (array.isArray(typeScope) ? typeScope[0].doc : typeScope instanceof Doc ? typeScope : typeScope.doc)
171
+ } = {}) {
172
+ super()
173
+ /**
174
+ * @type {Array<YType | Doc>}
175
+ */
176
+ this.scope = []
177
+ this.doc = doc
178
+ this.addToScope(typeScope)
179
+ this.deleteFilter = deleteFilter
180
+ trackedOrigins.add(this)
181
+ this.trackedOrigins = trackedOrigins
182
+ this.captureTransaction = captureTransaction
183
+ /**
184
+ * @type {Array<StackItem>}
185
+ */
186
+ this.undoStack = []
187
+ /**
188
+ * @type {Array<StackItem>}
189
+ */
190
+ this.redoStack = []
191
+ /**
192
+ * Whether the client is currently undoing (calling UndoManager.undo)
193
+ *
194
+ * @type {boolean}
195
+ */
196
+ this.undoing = false
197
+ this.redoing = false
198
+ /**
199
+ * The currently popped stack item if UndoManager.undoing or UndoManager.redoing
200
+ *
201
+ * @type {StackItem|null}
202
+ */
203
+ this.currStackItem = null
204
+ this.lastChange = 0
205
+ this.ignoreRemoteMapChanges = ignoreRemoteMapChanges
206
+ this.captureTimeout = captureTimeout
207
+ /**
208
+ * @param {Transaction} transaction
209
+ */
210
+ this.afterTransactionHandler = transaction => {
211
+ // Only track certain transactions
212
+ if (
213
+ !this.captureTransaction(transaction) ||
214
+ !this.scope.some(type => transaction.changedParentTypes.has(/** @type {YType} */ (type)) || type === this.doc) ||
215
+ (!this.trackedOrigins.has(transaction.origin) && (!transaction.origin || !this.trackedOrigins.has(transaction.origin.constructor)))
216
+ ) {
217
+ return
218
+ }
219
+ const undoing = this.undoing
220
+ const redoing = this.redoing
221
+ const stack = undoing ? this.redoStack : this.undoStack
222
+ if (undoing) {
223
+ this.stopCapturing() // next undo should not be appended to last stack item
224
+ } else if (!redoing) {
225
+ // neither undoing nor redoing: delete redoStack
226
+ this.clear(false, true)
227
+ }
228
+ const insertions = transaction.insertSet
229
+ const now = time.getUnixTime()
230
+ let didAdd = false
231
+ if (this.lastChange > 0 && now - this.lastChange < this.captureTimeout && stack.length > 0 && !undoing && !redoing) {
232
+ // append change to last stack op
233
+ const lastOp = stack[stack.length - 1]
234
+ lastOp.deletes = mergeIdSets([lastOp.deletes, transaction.deleteSet])
235
+ lastOp.inserts = mergeIdSets([lastOp.inserts, insertions])
236
+ } else {
237
+ // create a new stack op
238
+ stack.push(new StackItem(insertions, transaction.deleteSet))
239
+ didAdd = true
240
+ }
241
+ if (!undoing && !redoing) {
242
+ this.lastChange = now
243
+ }
244
+ // make sure that deleted structs are not gc'd
245
+ iterateStructsByIdSet(transaction, transaction.deleteSet, /** @param {Item|GC} item */ item => {
246
+ if (item instanceof Item && this.scope.some(type => type === transaction.doc || isParentOf(/** @type {YType} */ (type), item))) {
247
+ keepItem(item, true)
248
+ }
249
+ })
250
+ /**
251
+ * @type {[StackItemEvent, UndoManager]}
252
+ */
253
+ const changeEvent = [{ stackItem: stack[stack.length - 1], origin: transaction.origin, type: undoing ? 'redo' : 'undo', changedParentTypes: transaction.changedParentTypes }, this]
254
+ if (didAdd) {
255
+ this.emit('stack-item-added', changeEvent)
256
+ } else {
257
+ this.emit('stack-item-updated', changeEvent)
258
+ }
259
+ }
260
+ this.doc.on('afterTransaction', this.afterTransactionHandler)
261
+ this.doc.on('destroy', () => {
262
+ this.destroy()
263
+ })
264
+ }
265
+
266
+ /**
267
+ * Extend the scope.
268
+ *
269
+ * @param {Array<YType | Doc> | YType | Doc} ytypes
270
+ */
271
+ addToScope (ytypes) {
272
+ const tmpSet = new Set(this.scope)
273
+ ytypes = array.isArray(ytypes) ? ytypes : [ytypes]
274
+ ytypes.forEach(ytype => {
275
+ if (!tmpSet.has(ytype)) {
276
+ tmpSet.add(ytype)
277
+ if (ytype instanceof YType ? 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
278
+ this.scope.push(ytype)
279
+ }
280
+ })
281
+ }
282
+
283
+ /**
284
+ * @param {any} origin
285
+ */
286
+ addTrackedOrigin (origin) {
287
+ this.trackedOrigins.add(origin)
288
+ }
289
+
290
+ /**
291
+ * @param {any} origin
292
+ */
293
+ removeTrackedOrigin (origin) {
294
+ this.trackedOrigins.delete(origin)
295
+ }
296
+
297
+ clear (clearUndoStack = true, clearRedoStack = true) {
298
+ if ((clearUndoStack && this.canUndo()) || (clearRedoStack && this.canRedo())) {
299
+ this.doc.transact(tr => {
300
+ if (clearUndoStack) {
301
+ this.undoStack.forEach(item => clearUndoManagerStackItem(tr, this, item))
302
+ this.undoStack = []
303
+ }
304
+ if (clearRedoStack) {
305
+ this.redoStack.forEach(item => clearUndoManagerStackItem(tr, this, item))
306
+ this.redoStack = []
307
+ }
308
+ this.emit('stack-cleared', [{ undoStackCleared: clearUndoStack, redoStackCleared: clearRedoStack }])
309
+ })
310
+ }
311
+ }
312
+
313
+ /**
314
+ * UndoManager merges Undo-StackItem if they are created within time-gap
315
+ * smaller than `options.captureTimeout`. Call `um.stopCapturing()` so that the next
316
+ * StackItem won't be merged.
317
+ *
318
+ *
319
+ * @example
320
+ * // without stopCapturing
321
+ * ytext.insert(0, 'a')
322
+ * ytext.insert(1, 'b')
323
+ * um.undo()
324
+ * ytext.toString() // => '' (note that 'ab' was removed)
325
+ * // with stopCapturing
326
+ * ytext.insert(0, 'a')
327
+ * um.stopCapturing()
328
+ * ytext.insert(0, 'b')
329
+ * um.undo()
330
+ * ytext.toString() // => 'a' (note that only 'b' was removed)
331
+ *
332
+ */
333
+ stopCapturing () {
334
+ this.lastChange = 0
335
+ }
336
+
337
+ /**
338
+ * Undo last changes on type.
339
+ *
340
+ * @return {StackItem?} Returns StackItem if a change was applied
341
+ */
342
+ undo () {
343
+ this.undoing = true
344
+ let res
345
+ try {
346
+ res = popStackItem(this, this.undoStack, 'undo')
347
+ } finally {
348
+ this.undoing = false
349
+ }
350
+ return res
351
+ }
352
+
353
+ /**
354
+ * Redo last undo operation.
355
+ *
356
+ * @return {StackItem?} Returns StackItem if a change was applied
357
+ */
358
+ redo () {
359
+ this.redoing = true
360
+ let res
361
+ try {
362
+ res = popStackItem(this, this.redoStack, 'redo')
363
+ } finally {
364
+ this.redoing = false
365
+ }
366
+ return res
367
+ }
368
+
369
+ /**
370
+ * Are undo steps available?
371
+ *
372
+ * @return {boolean} `true` if undo is possible
373
+ */
374
+ canUndo () {
375
+ return this.undoStack.length > 0
376
+ }
377
+
378
+ /**
379
+ * Are redo steps available?
380
+ *
381
+ * @return {boolean} `true` if redo is possible
382
+ */
383
+ canRedo () {
384
+ return this.redoStack.length > 0
385
+ }
386
+
387
+ destroy () {
388
+ this.trackedOrigins.delete(this)
389
+ this.doc.off('afterTransaction', this.afterTransactionHandler)
390
+ super.destroy()
391
+ }
392
+ }
393
+
394
+ /**
395
+ * @experimental
396
+ *
397
+ * This is not guaranteed to work on documents with gc enabled!
398
+ *
399
+ * @param {Doc} ydoc
400
+ * @param {import('./meta.js').ContentIds} contentIds
401
+ */
402
+ export const undoContentIds = (ydoc, contentIds) => {
403
+ const um = new UndoManager(ydoc)
404
+ um.undoStack.push(new StackItem(diffIdSet(contentIds.inserts, contentIds.deletes), diffIdSet(contentIds.deletes, contentIds.inserts)))
405
+ um.undo()
406
+ }
@@ -0,0 +1,281 @@
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
+ }