@y/y 14.0.0-19 → 14.0.0-21

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 (135) 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 +16 -14
  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 +22 -19
  15. package/dist/src/utils/IdMap.d.ts.map +1 -1
  16. package/dist/src/utils/IdSet.d.ts +6 -6
  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/Snapshot.d.ts +3 -3
  21. package/dist/src/utils/Snapshot.d.ts.map +1 -1
  22. package/dist/src/utils/Transaction.d.ts +9 -5
  23. package/dist/src/utils/Transaction.d.ts.map +1 -1
  24. package/dist/src/utils/UndoManager.d.ts +14 -12
  25. package/dist/src/utils/UndoManager.d.ts.map +1 -1
  26. package/dist/src/utils/UpdateDecoder.d.ts +8 -4
  27. package/dist/src/utils/UpdateDecoder.d.ts.map +1 -1
  28. package/dist/src/utils/UpdateEncoder.d.ts +2 -0
  29. package/dist/src/utils/UpdateEncoder.d.ts.map +1 -1
  30. package/dist/src/utils/YEvent.d.ts +21 -42
  31. package/dist/src/utils/YEvent.d.ts.map +1 -1
  32. package/dist/src/utils/encoding.d.ts +3 -3
  33. package/dist/src/utils/encoding.d.ts.map +1 -1
  34. package/dist/src/utils/isParentOf.d.ts +1 -1
  35. package/dist/src/utils/isParentOf.d.ts.map +1 -1
  36. package/dist/src/utils/logging.d.ts +2 -2
  37. package/dist/src/utils/logging.d.ts.map +1 -1
  38. package/dist/src/utils/meta.d.ts +71 -0
  39. package/dist/src/utils/meta.d.ts.map +1 -0
  40. package/dist/src/utils/ts.d.ts +4 -0
  41. package/dist/src/utils/ts.d.ts.map +1 -0
  42. package/dist/src/utils/updates.d.ts +11 -11
  43. package/dist/src/utils/updates.d.ts.map +1 -1
  44. package/dist/src/ytype.d.ts +498 -0
  45. package/dist/src/ytype.d.ts.map +1 -0
  46. package/dist/tests/IdMap.tests.d.ts.map +1 -1
  47. package/dist/tests/attribution.tests.d.ts +1 -0
  48. package/dist/tests/attribution.tests.d.ts.map +1 -1
  49. package/dist/tests/compatibility.tests.d.ts.map +1 -1
  50. package/dist/tests/doc.tests.d.ts.map +1 -1
  51. package/dist/tests/relativePositions.tests.d.ts +9 -9
  52. package/dist/tests/relativePositions.tests.d.ts.map +1 -1
  53. package/dist/tests/snapshot.tests.d.ts.map +1 -1
  54. package/dist/tests/testHelper.d.ts +28 -27
  55. package/dist/tests/testHelper.d.ts.map +1 -1
  56. package/dist/tests/undo-redo.tests.d.ts.map +1 -1
  57. package/dist/tests/updates.tests.d.ts +2 -1
  58. package/dist/tests/updates.tests.d.ts.map +1 -1
  59. package/dist/tests/y-array.tests.d.ts +0 -2
  60. package/dist/tests/y-array.tests.d.ts.map +1 -1
  61. package/dist/tests/y-map.tests.d.ts +0 -3
  62. package/dist/tests/y-map.tests.d.ts.map +1 -1
  63. package/dist/tests/y-text.tests.d.ts +1 -1
  64. package/dist/tests/y-text.tests.d.ts.map +1 -1
  65. package/dist/tests/y-xml.tests.d.ts +0 -1
  66. package/dist/tests/y-xml.tests.d.ts.map +1 -1
  67. package/package.json +16 -16
  68. package/src/index.js +156 -0
  69. package/src/internals.js +35 -0
  70. package/src/structs/AbstractStruct.js +59 -0
  71. package/src/structs/ContentAny.js +115 -0
  72. package/src/structs/ContentBinary.js +93 -0
  73. package/src/structs/ContentDeleted.js +101 -0
  74. package/src/structs/ContentDoc.js +141 -0
  75. package/src/structs/ContentEmbed.js +98 -0
  76. package/src/structs/ContentFormat.js +105 -0
  77. package/src/structs/ContentJSON.js +119 -0
  78. package/src/structs/ContentString.js +113 -0
  79. package/src/structs/ContentType.js +152 -0
  80. package/src/structs/GC.js +80 -0
  81. package/src/structs/Item.js +841 -0
  82. package/src/structs/Skip.js +75 -0
  83. package/src/utils/AttributionManager.js +653 -0
  84. package/src/utils/Doc.js +266 -0
  85. package/src/utils/EventHandler.js +87 -0
  86. package/src/utils/ID.js +89 -0
  87. package/src/utils/IdMap.js +673 -0
  88. package/src/utils/IdSet.js +825 -0
  89. package/src/utils/RelativePosition.js +352 -0
  90. package/src/utils/Snapshot.js +220 -0
  91. package/src/utils/StructSet.js +137 -0
  92. package/src/utils/StructStore.js +289 -0
  93. package/src/utils/Transaction.js +671 -0
  94. package/src/utils/UndoManager.js +406 -0
  95. package/src/utils/UpdateDecoder.js +285 -0
  96. package/src/utils/UpdateEncoder.js +327 -0
  97. package/src/utils/YEvent.js +189 -0
  98. package/src/utils/delta-helpers.js +54 -0
  99. package/src/utils/encoding.js +623 -0
  100. package/src/utils/isParentOf.js +21 -0
  101. package/src/utils/logging.js +21 -0
  102. package/src/utils/meta.js +190 -0
  103. package/src/utils/ts.js +3 -0
  104. package/src/utils/updates.js +802 -0
  105. package/src/ytype.js +1962 -0
  106. package/dist/Skip-CE05BUF8.js +0 -11875
  107. package/dist/Skip-CE05BUF8.js.map +0 -1
  108. package/dist/index-C21sDQ5u.js +0 -163
  109. package/dist/index-C21sDQ5u.js.map +0 -1
  110. package/dist/internals.js +0 -25
  111. package/dist/internals.js.map +0 -1
  112. package/dist/src/types/AbstractType.d.ts +0 -239
  113. package/dist/src/types/AbstractType.d.ts.map +0 -1
  114. package/dist/src/types/YArray.d.ts +0 -128
  115. package/dist/src/types/YArray.d.ts.map +0 -1
  116. package/dist/src/types/YMap.d.ts +0 -112
  117. package/dist/src/types/YMap.d.ts.map +0 -1
  118. package/dist/src/types/YText.d.ts +0 -216
  119. package/dist/src/types/YText.d.ts.map +0 -1
  120. package/dist/src/types/YXmlElement.d.ts +0 -106
  121. package/dist/src/types/YXmlElement.d.ts.map +0 -1
  122. package/dist/src/types/YXmlFragment.d.ts +0 -143
  123. package/dist/src/types/YXmlFragment.d.ts.map +0 -1
  124. package/dist/src/types/YXmlHook.d.ts +0 -32
  125. package/dist/src/types/YXmlHook.d.ts.map +0 -1
  126. package/dist/src/types/YXmlText.d.ts +0 -34
  127. package/dist/src/types/YXmlText.d.ts.map +0 -1
  128. package/dist/src/utils/AbstractConnector.d.ts +0 -20
  129. package/dist/src/utils/AbstractConnector.d.ts.map +0 -1
  130. package/dist/src/utils/types.d.ts +0 -7
  131. package/dist/src/utils/types.d.ts.map +0 -1
  132. package/dist/testHelper.js +0 -617
  133. package/dist/testHelper.js.map +0 -1
  134. package/dist/yjs.js +0 -26
  135. package/dist/yjs.js.map +0 -1
@@ -0,0 +1,327 @@
1
+ import * as error from 'lib0/error'
2
+ import * as encoding from 'lib0/encoding'
3
+
4
+ import {
5
+ ID // eslint-disable-line
6
+ } from '../internals.js'
7
+
8
+ export class IdSetEncoderV1 {
9
+ constructor () {
10
+ this.restEncoder = encoding.createEncoder()
11
+ }
12
+
13
+ toUint8Array () {
14
+ return encoding.toUint8Array(this.restEncoder)
15
+ }
16
+
17
+ resetIdSetCurVal () {
18
+ // nop
19
+ }
20
+
21
+ /**
22
+ * @param {number} clock
23
+ */
24
+ writeIdSetClock (clock) {
25
+ encoding.writeVarUint(this.restEncoder, clock)
26
+ }
27
+
28
+ /**
29
+ * @param {number} len
30
+ */
31
+ writeIdSetLen (len) {
32
+ encoding.writeVarUint(this.restEncoder, len)
33
+ }
34
+ }
35
+
36
+ export class UpdateEncoderV1 extends IdSetEncoderV1 {
37
+ /**
38
+ * @param {ID} id
39
+ */
40
+ writeLeftID (id) {
41
+ encoding.writeVarUint(this.restEncoder, id.client)
42
+ encoding.writeVarUint(this.restEncoder, id.clock)
43
+ }
44
+
45
+ /**
46
+ * @param {ID} id
47
+ */
48
+ writeRightID (id) {
49
+ encoding.writeVarUint(this.restEncoder, id.client)
50
+ encoding.writeVarUint(this.restEncoder, id.clock)
51
+ }
52
+
53
+ /**
54
+ * Use writeClient and writeClock instead of writeID if possible.
55
+ * @param {number} client
56
+ */
57
+ writeClient (client) {
58
+ encoding.writeVarUint(this.restEncoder, client)
59
+ }
60
+
61
+ /**
62
+ * @param {number} info An unsigned 8-bit integer
63
+ */
64
+ writeInfo (info) {
65
+ encoding.writeUint8(this.restEncoder, info)
66
+ }
67
+
68
+ /**
69
+ * @param {string} s
70
+ */
71
+ writeString (s) {
72
+ encoding.writeVarString(this.restEncoder, s)
73
+ }
74
+
75
+ /**
76
+ * @param {boolean} isYKey
77
+ */
78
+ writeParentInfo (isYKey) {
79
+ encoding.writeVarUint(this.restEncoder, isYKey ? 1 : 0)
80
+ }
81
+
82
+ /**
83
+ * @param {number} info An unsigned 8-bit integer
84
+ */
85
+ writeTypeRef (info) {
86
+ encoding.writeVarUint(this.restEncoder, info)
87
+ }
88
+
89
+ /**
90
+ * Write len of a struct - well suited for Opt RLE encoder.
91
+ *
92
+ * @param {number} len
93
+ */
94
+ writeLen (len) {
95
+ encoding.writeVarUint(this.restEncoder, len)
96
+ }
97
+
98
+ /**
99
+ * @param {any} any
100
+ */
101
+ writeAny (any) {
102
+ encoding.writeAny(this.restEncoder, any)
103
+ }
104
+
105
+ /**
106
+ * @param {Uint8Array} buf
107
+ */
108
+ writeBuf (buf) {
109
+ encoding.writeVarUint8Array(this.restEncoder, buf)
110
+ }
111
+
112
+ /**
113
+ * @param {any} embed
114
+ */
115
+ writeJSON (embed) {
116
+ encoding.writeVarString(this.restEncoder, JSON.stringify(embed))
117
+ }
118
+
119
+ /**
120
+ * @param {string} key
121
+ */
122
+ writeKey (key) {
123
+ encoding.writeVarString(this.restEncoder, key)
124
+ }
125
+ }
126
+
127
+ export class IdSetEncoderV2 {
128
+ constructor () {
129
+ this.restEncoder = encoding.createEncoder() // encodes all the rest / non-optimized
130
+ this.dsCurrVal = 0
131
+ }
132
+
133
+ toUint8Array () {
134
+ return encoding.toUint8Array(this.restEncoder)
135
+ }
136
+
137
+ resetIdSetCurVal () {
138
+ this.dsCurrVal = 0
139
+ }
140
+
141
+ /**
142
+ * @param {number} clock
143
+ */
144
+ writeIdSetClock (clock) {
145
+ const diff = clock - this.dsCurrVal
146
+ this.dsCurrVal = clock
147
+ encoding.writeVarUint(this.restEncoder, diff)
148
+ }
149
+
150
+ /**
151
+ * @param {number} len
152
+ */
153
+ writeIdSetLen (len) {
154
+ if (len === 0) {
155
+ error.unexpectedCase()
156
+ }
157
+ encoding.writeVarUint(this.restEncoder, len - 1)
158
+ this.dsCurrVal += len
159
+ }
160
+ }
161
+
162
+ export class UpdateEncoderV2 extends IdSetEncoderV2 {
163
+ constructor () {
164
+ super()
165
+ /**
166
+ * @type {Map<string,number>}
167
+ */
168
+ this.keyMap = new Map()
169
+ /**
170
+ * Refers to the next unique key-identifier to me used.
171
+ * See writeKey method for more information.
172
+ *
173
+ * @type {number}
174
+ */
175
+ this.keyClock = 0
176
+ this.keyClockEncoder = new encoding.IntDiffOptRleEncoder()
177
+ this.clientEncoder = new encoding.UintOptRleEncoder()
178
+ this.leftClockEncoder = new encoding.IntDiffOptRleEncoder()
179
+ this.rightClockEncoder = new encoding.IntDiffOptRleEncoder()
180
+ this.infoEncoder = new encoding.RleEncoder(encoding.writeUint8)
181
+ this.stringEncoder = new encoding.StringEncoder()
182
+ this.parentInfoEncoder = new encoding.RleEncoder(encoding.writeUint8)
183
+ this.typeRefEncoder = new encoding.UintOptRleEncoder()
184
+ this.lenEncoder = new encoding.UintOptRleEncoder()
185
+ }
186
+
187
+ toUint8Array () {
188
+ const encoder = encoding.createEncoder()
189
+ encoding.writeVarUint(encoder, 0) // this is a feature flag that we might use in the future
190
+ encoding.writeVarUint8Array(encoder, this.keyClockEncoder.toUint8Array())
191
+ encoding.writeVarUint8Array(encoder, this.clientEncoder.toUint8Array())
192
+ encoding.writeVarUint8Array(encoder, this.leftClockEncoder.toUint8Array())
193
+ encoding.writeVarUint8Array(encoder, this.rightClockEncoder.toUint8Array())
194
+ encoding.writeVarUint8Array(encoder, encoding.toUint8Array(this.infoEncoder))
195
+ encoding.writeVarUint8Array(encoder, this.stringEncoder.toUint8Array())
196
+ encoding.writeVarUint8Array(encoder, encoding.toUint8Array(this.parentInfoEncoder))
197
+ encoding.writeVarUint8Array(encoder, this.typeRefEncoder.toUint8Array())
198
+ encoding.writeVarUint8Array(encoder, this.lenEncoder.toUint8Array())
199
+ // @note The rest encoder is appended! (note the missing var)
200
+ encoding.writeUint8Array(encoder, encoding.toUint8Array(this.restEncoder))
201
+ return encoding.toUint8Array(encoder)
202
+ }
203
+
204
+ /**
205
+ * @param {ID} id
206
+ */
207
+ writeLeftID (id) {
208
+ this.clientEncoder.write(id.client)
209
+ this.leftClockEncoder.write(id.clock)
210
+ }
211
+
212
+ /**
213
+ * @param {ID} id
214
+ */
215
+ writeRightID (id) {
216
+ this.clientEncoder.write(id.client)
217
+ this.rightClockEncoder.write(id.clock)
218
+ }
219
+
220
+ /**
221
+ * @param {number} client
222
+ */
223
+ writeClient (client) {
224
+ this.clientEncoder.write(client)
225
+ }
226
+
227
+ /**
228
+ * @param {number} info An unsigned 8-bit integer
229
+ */
230
+ writeInfo (info) {
231
+ this.infoEncoder.write(info)
232
+ }
233
+
234
+ /**
235
+ * @param {string} s
236
+ */
237
+ writeString (s) {
238
+ this.stringEncoder.write(s)
239
+ }
240
+
241
+ /**
242
+ * @param {boolean} isYKey
243
+ */
244
+ writeParentInfo (isYKey) {
245
+ this.parentInfoEncoder.write(isYKey ? 1 : 0)
246
+ }
247
+
248
+ /**
249
+ * @param {number} info An unsigned 8-bit integer
250
+ */
251
+ writeTypeRef (info) {
252
+ this.typeRefEncoder.write(info)
253
+ }
254
+
255
+ /**
256
+ * Write len of a struct - well suited for Opt RLE encoder.
257
+ *
258
+ * @param {number} len
259
+ */
260
+ writeLen (len) {
261
+ this.lenEncoder.write(len)
262
+ }
263
+
264
+ /**
265
+ * @param {any} any
266
+ */
267
+ writeAny (any) {
268
+ encoding.writeAny(this.restEncoder, any)
269
+ }
270
+
271
+ /**
272
+ * @param {Uint8Array} buf
273
+ */
274
+ writeBuf (buf) {
275
+ encoding.writeVarUint8Array(this.restEncoder, buf)
276
+ }
277
+
278
+ /**
279
+ * This is mainly here for legacy purposes.
280
+ *
281
+ * 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.
282
+ *
283
+ * @param {any} embed
284
+ */
285
+ writeJSON (embed) {
286
+ encoding.writeAny(this.restEncoder, embed)
287
+ }
288
+
289
+ /**
290
+ * Property keys are often reused. For example, in y-prosemirror the key `bold` might
291
+ * occur very often. For a 3d application, the key `position` might occur very often.
292
+ *
293
+ * We cache these keys in a Map and refer to them via a unique number.
294
+ *
295
+ * @param {string} key
296
+ */
297
+ writeKey (key) {
298
+ const clock = this.keyMap.get(key)
299
+ if (clock === undefined) {
300
+ /**
301
+ * @todo uncomment to introduce this feature finally
302
+ *
303
+ * Background. The ContentFormat object was always encoded using writeKey, but the decoder used to use readString.
304
+ * Furthermore, I forgot to set the keyclock. So everything was working fine.
305
+ *
306
+ * However, this feature here is basically useless as it is not being used (it actually only consumes extra memory).
307
+ *
308
+ * I don't know yet how to reintroduce this feature..
309
+ *
310
+ * Older clients won't be able to read updates when we reintroduce this feature. So this should probably be done using a flag.
311
+ *
312
+ */
313
+ // this.keyMap.set(key, this.keyClock)
314
+ this.keyClockEncoder.write(this.keyClock++)
315
+ this.stringEncoder.write(key)
316
+ } else {
317
+ this.keyClockEncoder.write(clock)
318
+ }
319
+ }
320
+ }
321
+
322
+ /**
323
+ * @typedef {IdSetEncoderV1 | IdSetEncoderV2} IdSetEncoder
324
+ */
325
+ /**
326
+ * @typedef {UpdateEncoderV1 | UpdateEncoderV2} UpdateEncoder
327
+ */
@@ -0,0 +1,189 @@
1
+ import {
2
+ diffIdSet,
3
+ mergeIdSets,
4
+ noAttributionsManager,
5
+ YType, Doc, AbstractAttributionManager, Item, Transaction, AbstractStruct, // eslint-disable-line
6
+ createAbsolutePositionFromRelativePosition,
7
+ createRelativePosition
8
+ } from '../internals.js'
9
+
10
+ import * as map from 'lib0/map'
11
+ import * as delta from 'lib0/delta' // eslint-disable-line
12
+ import * as set from 'lib0/set'
13
+
14
+ /**
15
+ * @template {delta.DeltaConf} DConf
16
+ * YEvent describes the changes on a YType.
17
+ */
18
+ export class YEvent {
19
+ /**
20
+ * @param {YType<DConf>} target The changed type.
21
+ * @param {Transaction} transaction
22
+ * @param {Set<any>?} subs The keys that changed
23
+ */
24
+ constructor (target, transaction, subs) {
25
+ /**
26
+ * The type on which this event was created on.
27
+ * @type {YType<DConf>}
28
+ */
29
+ this.target = target
30
+ /**
31
+ * The current target on which the observe callback is called.
32
+ * @type {YType<any>}
33
+ */
34
+ this.currentTarget = target
35
+ /**
36
+ * The transaction that triggered this event.
37
+ * @type {Transaction}
38
+ */
39
+ this.transaction = transaction
40
+ /**
41
+ * @type {delta.Delta<import('../ytype.js').DeltaConfDeltaToYType<DConf>>|null}
42
+ */
43
+ this._delta = null
44
+ /**
45
+ * @type {delta.Delta<DConf>|null}
46
+ */
47
+ this._deltaDeep = null
48
+ /**
49
+ * Whether the children changed.
50
+ * @type {Boolean}
51
+ * @private
52
+ */
53
+ this.childListChanged = false
54
+ /**
55
+ * Set of all changed attributes.
56
+ * @type {Set<string>}
57
+ */
58
+ this.keysChanged = new Set()
59
+ subs?.forEach((sub) => {
60
+ if (sub === null) {
61
+ this.childListChanged = true
62
+ } else {
63
+ this.keysChanged.add(sub)
64
+ }
65
+ })
66
+ }
67
+
68
+ /**
69
+ * Check if a struct is deleted by this event.
70
+ *
71
+ * In contrast to change.deleted, this method also returns true if the struct was added and then deleted.
72
+ *
73
+ * @param {AbstractStruct} struct
74
+ * @return {boolean}
75
+ */
76
+ deletes (struct) {
77
+ return this.transaction.deleteSet.hasId(struct.id)
78
+ }
79
+
80
+ /**
81
+ * Check if a struct is added by this event.
82
+ *
83
+ * In contrast to change.deleted, this method also returns true if the struct was added and then deleted.
84
+ *
85
+ * @param {AbstractStruct} struct
86
+ * @return {boolean}
87
+ */
88
+ adds (struct) {
89
+ return this.transaction.insertSet.hasId(struct.id)
90
+ }
91
+
92
+ /**
93
+ * @template {boolean} [Deep=false]
94
+ * @param {AbstractAttributionManager} am
95
+ * @param {object} [opts]
96
+ * @param {Deep} [opts.deep]
97
+ * @return {Deep extends true ? delta.Delta<DConf> : delta.Delta<import('../internals.js').DeltaConfDeltaToYType<DConf>>} The Delta representation of this type.
98
+ *
99
+ * @public
100
+ */
101
+ getDelta (am = noAttributionsManager, { deep } = {}) {
102
+ const itemsToRender = mergeIdSets([diffIdSet(this.transaction.insertSet, this.transaction.deleteSet), diffIdSet(this.transaction.deleteSet, this.transaction.insertSet)])
103
+ /**
104
+ * @todo this should be done only one in the transaction step
105
+ *
106
+ * @type {Map<YType,Set<string|null>>|null}
107
+ */
108
+ let modified = this.transaction.changed
109
+ if (deep) {
110
+ // need to add deep changes to copy of modified
111
+ const dchanged = new Map()
112
+ modified.forEach((attrs, type) => {
113
+ dchanged.set(type, new Set(attrs))
114
+ })
115
+ for (let m of modified.keys()) {
116
+ while (m._item != null) {
117
+ const item = m._item
118
+ const ms = map.setIfUndefined(dchanged, item?.parent, set.create)
119
+ if (item && !ms.has(item.parentSub)) {
120
+ ms.add(item.parentSub)
121
+ m = /** @type {any} */ (item.parent)
122
+ } else {
123
+ break
124
+ }
125
+ }
126
+ }
127
+ modified = dchanged
128
+ }
129
+ return /** @type {any} */ (this.target.toDelta(am, { itemsToRender, retainDeletes: true, deletedItems: this.transaction.deleteSet, deep: !!deep, modified }))
130
+ }
131
+
132
+ /**
133
+ * Compute the changes in the delta format.
134
+ * A {@link https://quilljs.com/docs/delta/|Quill Delta}) that represents the changes on the document.
135
+ *
136
+ * @type {delta.Delta<import('../internals.js').DeltaConfDeltaToYType<DConf>>} The Delta representation of this type.
137
+ * @public
138
+ */
139
+ get delta () {
140
+ return /** @type {any} */ (this._delta ?? (this._delta = this.getDelta().done()))
141
+ }
142
+
143
+ /**
144
+ * Compute the changes in the delta format.
145
+ * A {@link https://quilljs.com/docs/delta/|Quill Delta}) that represents the changes on the document.
146
+ *
147
+ * @type {delta.Delta<DConf>} The Delta representation of this type.
148
+ * @public
149
+ */
150
+ get deltaDeep () {
151
+ return /** @type {any} */ (this._deltaDeep ?? (this._deltaDeep = /** @type {any} */ (this.getDelta(noAttributionsManager, { deep: true }))))
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Compute the path from this type to the specified target.
157
+ *
158
+ * @example
159
+ * // `child` should be accessible via `type.get(path[0]).get(path[1])..`
160
+ * const path = type.getPathTo(child)
161
+ * // assuming `type instanceof YArray`
162
+ * console.log(path) // might look like => [2, 'key1']
163
+ * child === type.get(path[0]).get(path[1])
164
+ *
165
+ * @param {YType} parent
166
+ * @param {YType} child target
167
+ * @param {AbstractAttributionManager} am
168
+ * @return {Array<string|number>} Path to the target
169
+ *
170
+ * @private
171
+ * @function
172
+ */
173
+ export const getPathTo = (parent, child, am = noAttributionsManager) => {
174
+ const path = []
175
+ const doc = /** @type {Doc} */ (parent.doc)
176
+ while (child._item !== null && child !== parent) {
177
+ if (child._item.parentSub !== null) {
178
+ // parent is map-ish
179
+ path.unshift(child._item.parentSub)
180
+ } else {
181
+ const parent = /** @type {import('../ytype.js').YType} */ (child._item.parent)
182
+ // parent is array-ish
183
+ const apos = /** @type {import('../utils/RelativePosition.js').AbsolutePosition} */ (createAbsolutePositionFromRelativePosition(createRelativePosition(parent, child._item.id), doc, false, am))
184
+ path.unshift(apos.index)
185
+ }
186
+ child = /** @type {YType} */ (child._item.parent)
187
+ }
188
+ return path
189
+ }
@@ -0,0 +1,54 @@
1
+ import {
2
+ createInsertSetFromStructStore,
3
+ createDeleteSetFromStructStore,
4
+ createAttributionManagerFromDiff,
5
+ diffIdSet,
6
+ mergeIdSets,
7
+ Item,
8
+ YType, Doc, // eslint-disable-line
9
+ iterateStructsByIdSet
10
+ } from '../internals.js'
11
+ import * as delta from 'lib0/delta'
12
+ import * as map from 'lib0/map'
13
+ import * as set from 'lib0/set'
14
+
15
+ /**
16
+ * @param {Doc} v1
17
+ * @param {Doc} v2
18
+ * @return {delta.DeltaBuilderAny}
19
+ */
20
+ export const diffDocsToDelta = (v1, v2, { am = createAttributionManagerFromDiff(v1, v2) } = {}) => {
21
+ const d = delta.create()
22
+ v2.transact(tr => {
23
+ v2.share.forEach((type, typename) => {
24
+ const insertDiff = diffIdSet(createInsertSetFromStructStore(v2.store, false), createInsertSetFromStructStore(v1.store, false))
25
+ const deleteDiff = diffIdSet(createDeleteSetFromStructStore(v2.store), createDeleteSetFromStructStore(v1.store))
26
+ // don't render items that have been inserted and then deleted
27
+ const insertsOnly = diffIdSet(insertDiff, deleteDiff)
28
+ const deletesOnly = diffIdSet(deleteDiff, insertDiff)
29
+ const itemsToRender = mergeIdSets([insertsOnly, deleteDiff])
30
+ /**
31
+ * @type {Map<YType, Set<string|null>>}
32
+ */
33
+ const changedTypes = new Map()
34
+ iterateStructsByIdSet(tr, itemsToRender, /** @param {any} item */ item => {
35
+ while (item instanceof Item) {
36
+ const parent = /** @type {YType} */ (item.parent)
37
+ const conf = map.setIfUndefined(changedTypes, parent, set.create)
38
+ if (conf.has(item.parentSub)) break // has already been marked as modified
39
+ conf.add(item.parentSub)
40
+ item = parent._item
41
+ }
42
+ })
43
+ const typeConf = changedTypes.get(type)
44
+ if (typeConf) {
45
+ // @ts-ignore
46
+ const shareDelta = type.toDelta(am, {
47
+ itemsToRender, retainDeletes: true, deletedItems: deletesOnly, modified: changedTypes, deep: true
48
+ })
49
+ d.modifyAttr(typename, shareDelta)
50
+ }
51
+ })
52
+ })
53
+ return d
54
+ }