lib0 0.2.115-1 → 0.2.115-3
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/coverage/tmp/{coverage-27668-1761218485882-0.json → coverage-32703-1763495370274-0.json} +1 -1
- package/delta/abstract.d.ts +2 -2
- package/delta/abstract.d.ts.map +1 -1
- package/delta/d2.d.ts +318 -112
- package/delta/d2.d.ts.map +1 -1
- package/delta/d2.js +837 -155
- package/delta/d2.test.d.ts +6 -1
- package/delta/d2.test.d.ts.map +1 -1
- package/delta/map.d.ts +19 -23
- package/delta/map.d.ts.map +1 -1
- package/delta/map.js +1 -1
- package/delta/node.d.ts +8 -10
- package/delta/node.d.ts.map +1 -1
- package/delta/ops.d.ts +26 -28
- package/delta/ops.d.ts.map +1 -1
- package/delta/t2.d.ts +184 -0
- package/delta/t2.d.ts.map +1 -0
- package/delta/t2.js +890 -0
- package/delta/t3.test.d.ts +19 -0
- package/delta/t3.test.d.ts.map +1 -0
- package/dist/aes-gcm.cjs +2 -2
- package/dist/binding.cjs +1 -1
- package/dist/{broadcastchannel-b4eaea6e.cjs → broadcastchannel-d0c108a2.cjs} +2 -2
- package/dist/{broadcastchannel-b4eaea6e.cjs.map → broadcastchannel-d0c108a2.cjs.map} +1 -1
- package/dist/broadcastchannel.cjs +4 -4
- package/dist/{buffer-adc4e6ea.cjs → buffer-7f6fa8fa.cjs} +3 -3
- package/dist/{buffer-adc4e6ea.cjs.map → buffer-7f6fa8fa.cjs.map} +1 -1
- package/dist/buffer.cjs +3 -3
- package/dist/component.cjs +1 -1
- package/dist/d2.cjs +845 -159
- package/dist/d2.cjs.map +1 -1
- package/dist/{decoding-50b9ce38.cjs → decoding-76e75827.cjs} +2 -2
- package/dist/{decoding-50b9ce38.cjs.map → decoding-76e75827.cjs.map} +1 -1
- package/dist/decoding.cjs +2 -2
- package/dist/delta/abstract.d.ts +2 -2
- package/dist/delta/abstract.d.ts.map +1 -1
- package/dist/delta/d2.d.ts +318 -112
- package/dist/delta/d2.d.ts.map +1 -1
- package/dist/delta/d2.test.d.ts +6 -1
- package/dist/delta/d2.test.d.ts.map +1 -1
- package/dist/delta/map.d.ts +19 -23
- package/dist/delta/map.d.ts.map +1 -1
- package/dist/delta/node.d.ts +8 -10
- package/dist/delta/node.d.ts.map +1 -1
- package/dist/delta/ops.d.ts +26 -28
- package/dist/delta/ops.d.ts.map +1 -1
- package/dist/delta/t2.d.ts +184 -0
- package/dist/delta/t2.d.ts.map +1 -0
- package/dist/delta/t3.test.d.ts +19 -0
- package/dist/delta/t3.test.d.ts.map +1 -0
- package/dist/{dom-2b123630.cjs → dom-f5047a64.cjs} +1 -1
- package/dist/{dom-2b123630.cjs.map → dom-f5047a64.cjs.map} +1 -1
- package/dist/dom.cjs +1 -1
- package/dist/{encoding-7f85922c.cjs → encoding-1a745c43.cjs} +10 -2
- package/dist/encoding-1a745c43.cjs.map +1 -0
- package/dist/encoding.cjs +1 -1
- package/dist/encoding.d.ts +5 -3
- package/dist/encoding.d.ts.map +1 -1
- package/dist/encoding.test.d.ts.map +1 -1
- package/dist/index.cjs +6 -6
- package/dist/jwt.cjs +3 -3
- package/dist/list.test.d.ts +1 -0
- package/dist/list.test.d.ts.map +1 -1
- package/dist/logging.cjs +1 -1
- package/dist/map.cjs +1 -1
- package/dist/map.cjs.map +1 -1
- package/dist/mutex.test.d.ts +3 -0
- package/dist/mutex.test.d.ts.map +1 -0
- package/dist/{prng-004c76e8.cjs → prng-99204216.cjs} +2 -2
- package/dist/{prng-004c76e8.cjs.map → prng-99204216.cjs.map} +1 -1
- package/dist/prng.cjs +4 -4
- package/dist/rabin-gf2-polynomial.cjs +3 -3
- package/dist/rabin-uncached.cjs +3 -3
- package/dist/rabin.cjs +3 -3
- package/dist/schema.cjs +72 -11
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.ts +21 -13
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.test.d.ts +2 -0
- package/dist/schema.test.d.ts.map +1 -1
- package/dist/t2.cjs +932 -0
- package/dist/t2.cjs.map +1 -0
- package/dist/testing.cjs +4 -4
- package/encoding.d.ts +5 -3
- package/encoding.d.ts.map +1 -1
- package/encoding.js +9 -1
- package/encoding.test.d.ts.map +1 -1
- package/list.test.d.ts +1 -0
- package/list.test.d.ts.map +1 -1
- package/mutex.test.d.ts +3 -0
- package/mutex.test.d.ts.map +1 -0
- package/package.json +1 -1
- package/schema.d.ts +21 -13
- package/schema.d.ts.map +1 -1
- package/schema.js +68 -11
- package/schema.test.d.ts +2 -0
- package/schema.test.d.ts.map +1 -1
- package/test.js +3 -1
- package/coverage/tmp/coverage-27667-1761218530660-0.json +0 -1
- package/dist/encoding-7f85922c.cjs.map +0 -1
package/delta/d2.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @beta this API is about to change
|
|
3
|
+
*
|
|
4
|
+
* ## Mutability
|
|
5
|
+
*
|
|
6
|
+
* Deltas are mutable by default. But references are often shared, by marking a Delta as "done". You
|
|
7
|
+
* may only modify deltas by applying other deltas to them. Casting a Delta to a DeltaBuilder
|
|
8
|
+
* manually, will likely modify "shared" state.
|
|
3
9
|
*/
|
|
4
10
|
|
|
5
11
|
import * as list from '../list.js'
|
|
@@ -10,6 +16,10 @@ import * as fun from '../function.js'
|
|
|
10
16
|
import * as s from '../schema.js'
|
|
11
17
|
import * as error from '../error.js'
|
|
12
18
|
import * as math from '../math.js'
|
|
19
|
+
import * as rabin from '../hash/rabin.js'
|
|
20
|
+
import * as encoding from '../encoding.js'
|
|
21
|
+
import * as buffer from '../buffer.js'
|
|
22
|
+
import * as patience from '../diff/patience.js'
|
|
13
23
|
|
|
14
24
|
/**
|
|
15
25
|
* @typedef {{
|
|
@@ -44,8 +54,9 @@ export const $attribution = s.$object({
|
|
|
44
54
|
|
|
45
55
|
/**
|
|
46
56
|
* @typedef {{
|
|
47
|
-
*
|
|
48
|
-
*
|
|
57
|
+
* type: 'delta',
|
|
58
|
+
* name?: string,
|
|
59
|
+
* attrs?: { [Key in string|number]: DeltaAttrOpJSON },
|
|
49
60
|
* children?: Array<DeltaListOpJSON>
|
|
50
61
|
* }} DeltaJSON
|
|
51
62
|
*/
|
|
@@ -58,6 +69,18 @@ export const $attribution = s.$object({
|
|
|
58
69
|
* @typedef {{ type: 'insert', value: any, prevValue?: any, attribution?: Attribution } | { type: 'delete', prevValue?: any, attribution?: Attribution } | { type: 'modify', value: DeltaJSON }} DeltaAttrOpJSON
|
|
59
70
|
*/
|
|
60
71
|
|
|
72
|
+
/**
|
|
73
|
+
* @typedef {TextOp|InsertOp<any>|DeleteOp|RetainOp|ModifyOp<any>} ChildrenOpAny
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @typedef {AttrInsertOp<any>|AttrDeleteOp<any>|AttrModifyOp} AttrOpAny
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @typedef {ChildrenOpAny|AttrOpAny} _OpAny
|
|
82
|
+
*/
|
|
83
|
+
|
|
61
84
|
/**
|
|
62
85
|
* @type {s.Schema<DeltaAttrOpJSON>}
|
|
63
86
|
*/
|
|
@@ -78,7 +101,11 @@ const _cloneAttrs = attrs => attrs == null ? attrs : { ...attrs }
|
|
|
78
101
|
* @param {MaybeDelta} maybeDelta
|
|
79
102
|
* @return {MaybeDelta}
|
|
80
103
|
*/
|
|
81
|
-
const
|
|
104
|
+
const _markMaybeDeltaAsDone = maybeDelta => $deltaAny.check(maybeDelta) ? /** @type {MaybeDelta} */ (maybeDelta.done()) : maybeDelta
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @typedef {unknown & DeltaAny} Q
|
|
108
|
+
*/
|
|
82
109
|
|
|
83
110
|
export class TextOp extends list.ListNode {
|
|
84
111
|
/**
|
|
@@ -88,9 +115,31 @@ export class TextOp extends list.ListNode {
|
|
|
88
115
|
*/
|
|
89
116
|
constructor (insert, format, attribution) {
|
|
90
117
|
super()
|
|
118
|
+
// Whenever this is modified, make sure to clear _fingerprint
|
|
119
|
+
/**
|
|
120
|
+
* @readonly
|
|
121
|
+
* @type {string}
|
|
122
|
+
*/
|
|
91
123
|
this.insert = insert
|
|
124
|
+
/**
|
|
125
|
+
* @readonly
|
|
126
|
+
* @type {FormattingAttributes|null}
|
|
127
|
+
*/
|
|
92
128
|
this.format = format
|
|
93
129
|
this.attribution = attribution
|
|
130
|
+
/**
|
|
131
|
+
* @type {string?}
|
|
132
|
+
*/
|
|
133
|
+
this._fingerprint = null
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @param {string} newVal
|
|
138
|
+
*/
|
|
139
|
+
_updateInsert (newVal) {
|
|
140
|
+
// @ts-ignore
|
|
141
|
+
this.insert = newVal
|
|
142
|
+
this._fingerprint = null
|
|
94
143
|
}
|
|
95
144
|
|
|
96
145
|
/**
|
|
@@ -104,6 +153,14 @@ export class TextOp extends list.ListNode {
|
|
|
104
153
|
return this.insert.length
|
|
105
154
|
}
|
|
106
155
|
|
|
156
|
+
get fingerprint () {
|
|
157
|
+
return this._fingerprint || (this._fingerprint = buffer.toBase64(encoding.encode(encoder => {
|
|
158
|
+
encoding.writeVarUint(encoder, 0) // textOp type: 0
|
|
159
|
+
encoding.writeVarString(encoder, this.insert)
|
|
160
|
+
encoding.writeAny(encoder, this.format)
|
|
161
|
+
})))
|
|
162
|
+
}
|
|
163
|
+
|
|
107
164
|
/**
|
|
108
165
|
* Remove a part of the operation (similar to Array.splice)
|
|
109
166
|
*
|
|
@@ -111,7 +168,10 @@ export class TextOp extends list.ListNode {
|
|
|
111
168
|
* @param {number} len
|
|
112
169
|
*/
|
|
113
170
|
_splice (offset, len) {
|
|
171
|
+
this._fingerprint = null
|
|
172
|
+
// @ts-ignore
|
|
114
173
|
this.insert = this.insert.slice(0, offset) + this.insert.slice(offset + len)
|
|
174
|
+
return this
|
|
115
175
|
}
|
|
116
176
|
|
|
117
177
|
/**
|
|
@@ -132,13 +192,13 @@ export class TextOp extends list.ListNode {
|
|
|
132
192
|
/**
|
|
133
193
|
* @return {TextOp}
|
|
134
194
|
*/
|
|
135
|
-
clone () {
|
|
136
|
-
return new TextOp(this.insert, _cloneAttrs(this.format), _cloneAttrs(this.attribution))
|
|
195
|
+
clone (start = 0, end = this.length) {
|
|
196
|
+
return new TextOp(this.insert.slice(start, end), _cloneAttrs(this.format), _cloneAttrs(this.attribution))
|
|
137
197
|
}
|
|
138
198
|
}
|
|
139
199
|
|
|
140
200
|
/**
|
|
141
|
-
* @template ArrayContent
|
|
201
|
+
* @template {encoding.AnyEncodable|DeltaAny} ArrayContent
|
|
142
202
|
*/
|
|
143
203
|
export class InsertOp extends list.ListNode {
|
|
144
204
|
/**
|
|
@@ -148,9 +208,34 @@ export class InsertOp extends list.ListNode {
|
|
|
148
208
|
*/
|
|
149
209
|
constructor (insert, format, attribution) {
|
|
150
210
|
super()
|
|
211
|
+
/**
|
|
212
|
+
* @readonly
|
|
213
|
+
* @type {Array<ArrayContent>}
|
|
214
|
+
*/
|
|
151
215
|
this.insert = insert
|
|
216
|
+
/**
|
|
217
|
+
* @readonly
|
|
218
|
+
* @type {FormattingAttributes?}
|
|
219
|
+
*/
|
|
152
220
|
this.format = format
|
|
221
|
+
/**
|
|
222
|
+
* @readonly
|
|
223
|
+
* @type {Attribution?}
|
|
224
|
+
*/
|
|
153
225
|
this.attribution = attribution
|
|
226
|
+
/**
|
|
227
|
+
* @type {string?}
|
|
228
|
+
*/
|
|
229
|
+
this._fingerprint = null
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* @param {ArrayContent} newVal
|
|
234
|
+
*/
|
|
235
|
+
_updateInsert (newVal) {
|
|
236
|
+
// @ts-ignore
|
|
237
|
+
this.insert = newVal
|
|
238
|
+
this._fingerprint = null
|
|
154
239
|
}
|
|
155
240
|
|
|
156
241
|
/**
|
|
@@ -164,6 +249,42 @@ export class InsertOp extends list.ListNode {
|
|
|
164
249
|
return this.insert.length
|
|
165
250
|
}
|
|
166
251
|
|
|
252
|
+
/**
|
|
253
|
+
* @param {number} i
|
|
254
|
+
* @return {Extract<ArrayContent,DeltaAny>}
|
|
255
|
+
*/
|
|
256
|
+
_modValue (i) {
|
|
257
|
+
/**
|
|
258
|
+
* @type {any}
|
|
259
|
+
*/
|
|
260
|
+
let d = this.insert[i]
|
|
261
|
+
this._fingerprint = null
|
|
262
|
+
$deltaAny.expect(d)
|
|
263
|
+
if (d.isDone) {
|
|
264
|
+
// @ts-ignore
|
|
265
|
+
this.insert[i] = (d = clone(d))
|
|
266
|
+
return d
|
|
267
|
+
}
|
|
268
|
+
return d
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
get fingerprint () {
|
|
272
|
+
return this._fingerprint || (this._fingerprint = buffer.toBase64(encoding.encode(encoder => {
|
|
273
|
+
encoding.writeVarUint(encoder, 1) // insertOp type: 1
|
|
274
|
+
encoding.writeVarUint(encoder, this.insert.length)
|
|
275
|
+
this.insert.forEach(ins => {
|
|
276
|
+
if ($deltaAny.check(ins)) {
|
|
277
|
+
encoding.writeUint8(encoder, 0)
|
|
278
|
+
encoding.writeVarString(encoder, ins.fingerprint)
|
|
279
|
+
} else {
|
|
280
|
+
encoding.writeUint8(encoder, 1)
|
|
281
|
+
encoding.writeAny(encoder, ins)
|
|
282
|
+
}
|
|
283
|
+
})
|
|
284
|
+
encoding.writeAny(encoder, this.format)
|
|
285
|
+
})))
|
|
286
|
+
}
|
|
287
|
+
|
|
167
288
|
/**
|
|
168
289
|
* Remove a part of the operation (similar to Array.splice)
|
|
169
290
|
*
|
|
@@ -171,7 +292,9 @@ export class InsertOp extends list.ListNode {
|
|
|
171
292
|
* @param {number} len
|
|
172
293
|
*/
|
|
173
294
|
_splice (offset, len) {
|
|
295
|
+
this._fingerprint = null
|
|
174
296
|
this.insert.splice(offset, len)
|
|
297
|
+
return this
|
|
175
298
|
}
|
|
176
299
|
|
|
177
300
|
/**
|
|
@@ -192,11 +315,15 @@ export class InsertOp extends list.ListNode {
|
|
|
192
315
|
/**
|
|
193
316
|
* @return {InsertOp<ArrayContent>}
|
|
194
317
|
*/
|
|
195
|
-
clone () {
|
|
196
|
-
return new InsertOp(this.insert.slice(), _cloneAttrs(this.format), _cloneAttrs(this.attribution))
|
|
318
|
+
clone (start = 0, end = this.length) {
|
|
319
|
+
return new InsertOp(this.insert.slice(start, end).map(_markMaybeDeltaAsDone), _cloneAttrs(this.format), _cloneAttrs(this.attribution))
|
|
197
320
|
}
|
|
198
321
|
}
|
|
199
322
|
|
|
323
|
+
/**
|
|
324
|
+
* @template {encoding.AnyEncodable|DeltaAny} [Children=never]
|
|
325
|
+
* @template {string} [Text=never]
|
|
326
|
+
*/
|
|
200
327
|
export class DeleteOp extends list.ListNode {
|
|
201
328
|
/**
|
|
202
329
|
* @param {number} len
|
|
@@ -204,6 +331,14 @@ export class DeleteOp extends list.ListNode {
|
|
|
204
331
|
constructor (len) {
|
|
205
332
|
super()
|
|
206
333
|
this.delete = len
|
|
334
|
+
/**
|
|
335
|
+
* @type {(Children|Text) extends never ? null : (Delta<any,{},Children,Text>?)}
|
|
336
|
+
*/
|
|
337
|
+
this.prevValue = null
|
|
338
|
+
/**
|
|
339
|
+
* @type {string|null}
|
|
340
|
+
*/
|
|
341
|
+
this._fingerprint = null
|
|
207
342
|
}
|
|
208
343
|
|
|
209
344
|
/**
|
|
@@ -217,6 +352,13 @@ export class DeleteOp extends list.ListNode {
|
|
|
217
352
|
return 0
|
|
218
353
|
}
|
|
219
354
|
|
|
355
|
+
get fingerprint () {
|
|
356
|
+
return this._fingerprint || (this._fingerprint = buffer.toBase64(encoding.encode(encoder => {
|
|
357
|
+
encoding.writeVarUint(encoder, 2) // deleteOp type: 2
|
|
358
|
+
encoding.writeVarUint(encoder, this.delete)
|
|
359
|
+
})))
|
|
360
|
+
}
|
|
361
|
+
|
|
220
362
|
/**
|
|
221
363
|
* Remove a part of the operation (similar to Array.splice)
|
|
222
364
|
*
|
|
@@ -224,7 +366,10 @@ export class DeleteOp extends list.ListNode {
|
|
|
224
366
|
* @param {number} len
|
|
225
367
|
*/
|
|
226
368
|
_splice (_offset, len) {
|
|
369
|
+
this.prevValue = /** @type {any} */ (this.prevValue?.slice(_offset, len) || null)
|
|
370
|
+
this._fingerprint = null
|
|
227
371
|
this.delete -= len
|
|
372
|
+
return this
|
|
228
373
|
}
|
|
229
374
|
|
|
230
375
|
/**
|
|
@@ -241,8 +386,8 @@ export class DeleteOp extends list.ListNode {
|
|
|
241
386
|
return this.delete === other.delete
|
|
242
387
|
}
|
|
243
388
|
|
|
244
|
-
clone () {
|
|
245
|
-
return new DeleteOp(
|
|
389
|
+
clone (start = 0, end = this.delete) {
|
|
390
|
+
return new DeleteOp(end - start)
|
|
246
391
|
}
|
|
247
392
|
}
|
|
248
393
|
|
|
@@ -254,9 +399,25 @@ export class RetainOp extends list.ListNode {
|
|
|
254
399
|
*/
|
|
255
400
|
constructor (retain, format, attribution) {
|
|
256
401
|
super()
|
|
402
|
+
/**
|
|
403
|
+
* @readonly
|
|
404
|
+
* @type {number}
|
|
405
|
+
*/
|
|
257
406
|
this.retain = retain
|
|
407
|
+
/**
|
|
408
|
+
* @readonly
|
|
409
|
+
* @type {FormattingAttributes?}
|
|
410
|
+
*/
|
|
258
411
|
this.format = format
|
|
412
|
+
/**
|
|
413
|
+
* @readonly
|
|
414
|
+
* @type {Attribution?}
|
|
415
|
+
*/
|
|
259
416
|
this.attribution = attribution
|
|
417
|
+
/**
|
|
418
|
+
* @type {string|null}
|
|
419
|
+
*/
|
|
420
|
+
this._fingerprint = null
|
|
260
421
|
}
|
|
261
422
|
|
|
262
423
|
/**
|
|
@@ -270,6 +431,14 @@ export class RetainOp extends list.ListNode {
|
|
|
270
431
|
return this.retain
|
|
271
432
|
}
|
|
272
433
|
|
|
434
|
+
get fingerprint () {
|
|
435
|
+
return this._fingerprint || (this._fingerprint = buffer.toBase64(encoding.encode(encoder => {
|
|
436
|
+
encoding.writeVarUint(encoder, 3) // retainOp type: 3
|
|
437
|
+
encoding.writeVarUint(encoder, this.retain)
|
|
438
|
+
encoding.writeAny(encoder, this.format)
|
|
439
|
+
})))
|
|
440
|
+
}
|
|
441
|
+
|
|
273
442
|
/**
|
|
274
443
|
* Remove a part of the operation (similar to Array.splice)
|
|
275
444
|
*
|
|
@@ -277,7 +446,10 @@ export class RetainOp extends list.ListNode {
|
|
|
277
446
|
* @param {number} len
|
|
278
447
|
*/
|
|
279
448
|
_splice (_offset, len) {
|
|
449
|
+
// @ts-ignore
|
|
280
450
|
this.retain -= len
|
|
451
|
+
this._fingerprint = null
|
|
452
|
+
return this
|
|
281
453
|
}
|
|
282
454
|
|
|
283
455
|
/**
|
|
@@ -295,15 +467,15 @@ export class RetainOp extends list.ListNode {
|
|
|
295
467
|
return this.retain === other.retain && fun.equalityDeep(this.format, other.format) && fun.equalityDeep(this.attribution, other.attribution)
|
|
296
468
|
}
|
|
297
469
|
|
|
298
|
-
clone () {
|
|
299
|
-
return new RetainOp(
|
|
470
|
+
clone (start = 0, end = this.retain) {
|
|
471
|
+
return new RetainOp(end - start, _cloneAttrs(this.format), _cloneAttrs(this.attribution))
|
|
300
472
|
}
|
|
301
473
|
}
|
|
302
474
|
|
|
303
475
|
/**
|
|
304
476
|
* Delta that can be applied on a YType Embed
|
|
305
477
|
*
|
|
306
|
-
* @template {
|
|
478
|
+
* @template {DeltaAny} [DTypes=DeltaAny]
|
|
307
479
|
*/
|
|
308
480
|
export class ModifyOp extends list.ListNode {
|
|
309
481
|
/**
|
|
@@ -313,9 +485,25 @@ export class ModifyOp extends list.ListNode {
|
|
|
313
485
|
*/
|
|
314
486
|
constructor (delta, format, attribution) {
|
|
315
487
|
super()
|
|
488
|
+
/**
|
|
489
|
+
* @readonly
|
|
490
|
+
* @type {DTypes}
|
|
491
|
+
*/
|
|
316
492
|
this.value = delta
|
|
493
|
+
/**
|
|
494
|
+
* @readonly
|
|
495
|
+
* @type {FormattingAttributes?}
|
|
496
|
+
*/
|
|
317
497
|
this.format = format
|
|
498
|
+
/**
|
|
499
|
+
* @readonly
|
|
500
|
+
* @type {Attribution?}
|
|
501
|
+
*/
|
|
318
502
|
this.attribution = attribution
|
|
503
|
+
/**
|
|
504
|
+
* @type {string|null}
|
|
505
|
+
*/
|
|
506
|
+
this._fingerprint = null
|
|
319
507
|
}
|
|
320
508
|
|
|
321
509
|
/**
|
|
@@ -329,6 +517,31 @@ export class ModifyOp extends list.ListNode {
|
|
|
329
517
|
return 1
|
|
330
518
|
}
|
|
331
519
|
|
|
520
|
+
/**
|
|
521
|
+
* @type {DeltaBuilderAny}
|
|
522
|
+
*/
|
|
523
|
+
get _modValue () {
|
|
524
|
+
/**
|
|
525
|
+
* @type {any}
|
|
526
|
+
*/
|
|
527
|
+
const d = this.value
|
|
528
|
+
this._fingerprint = null
|
|
529
|
+
if (d.isDone) {
|
|
530
|
+
// @ts-ignore
|
|
531
|
+
return (this.value = clone(d))
|
|
532
|
+
}
|
|
533
|
+
return d
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
get fingerprint () {
|
|
537
|
+
// don't cache fingerprint because we don't know when delta changes
|
|
538
|
+
return this._fingerprint || (this._fingerprint = buffer.toBase64(encoding.encode(encoder => {
|
|
539
|
+
encoding.writeVarUint(encoder, 4) // modifyOp type: 4
|
|
540
|
+
encoding.writeVarString(encoder, this.value.fingerprint)
|
|
541
|
+
encoding.writeAny(encoder, this.format)
|
|
542
|
+
})))
|
|
543
|
+
}
|
|
544
|
+
|
|
332
545
|
/**
|
|
333
546
|
* Remove a part of the operation (similar to Array.splice)
|
|
334
547
|
*
|
|
@@ -336,6 +549,7 @@ export class ModifyOp extends list.ListNode {
|
|
|
336
549
|
* @param {number} _len
|
|
337
550
|
*/
|
|
338
551
|
_splice (_offset, _len) {
|
|
552
|
+
return this
|
|
339
553
|
}
|
|
340
554
|
|
|
341
555
|
/**
|
|
@@ -357,15 +571,15 @@ export class ModifyOp extends list.ListNode {
|
|
|
357
571
|
* @return {ModifyOp<DTypes>}
|
|
358
572
|
*/
|
|
359
573
|
clone () {
|
|
360
|
-
return new ModifyOp(this.value.
|
|
574
|
+
return new ModifyOp(/** @type {DTypes} */ (this.value.done()), _cloneAttrs(this.format), _cloneAttrs(this.attribution))
|
|
361
575
|
}
|
|
362
576
|
}
|
|
363
577
|
|
|
364
578
|
/**
|
|
365
|
-
* @template V
|
|
366
|
-
* @template {string|number
|
|
579
|
+
* @template {encoding.AnyEncodable|DeltaAny} V
|
|
580
|
+
* @template {string|number} [K=any]
|
|
367
581
|
*/
|
|
368
|
-
export class
|
|
582
|
+
export class AttrInsertOp {
|
|
369
583
|
/**
|
|
370
584
|
* @param {K} key
|
|
371
585
|
* @param {V} value
|
|
@@ -374,18 +588,29 @@ export class MapInsertOp {
|
|
|
374
588
|
*/
|
|
375
589
|
constructor (key, value, prevValue, attribution) {
|
|
376
590
|
/**
|
|
591
|
+
* @readonly
|
|
377
592
|
* @type {K}
|
|
378
593
|
*/
|
|
379
594
|
this.key = key
|
|
380
595
|
/**
|
|
596
|
+
* @readonly
|
|
381
597
|
* @type {V}
|
|
382
598
|
*/
|
|
383
599
|
this.value = value
|
|
384
600
|
/**
|
|
601
|
+
* @readonly
|
|
385
602
|
* @type {V|undefined}
|
|
386
603
|
*/
|
|
387
604
|
this.prevValue = prevValue
|
|
605
|
+
/**
|
|
606
|
+
* @readonly
|
|
607
|
+
* @type {Attribution?}
|
|
608
|
+
*/
|
|
388
609
|
this.attribution = attribution
|
|
610
|
+
/**
|
|
611
|
+
* @type {string|null}
|
|
612
|
+
*/
|
|
613
|
+
this._fingerprint = null
|
|
389
614
|
}
|
|
390
615
|
|
|
391
616
|
/**
|
|
@@ -393,6 +618,36 @@ export class MapInsertOp {
|
|
|
393
618
|
*/
|
|
394
619
|
get type () { return 'insert' }
|
|
395
620
|
|
|
621
|
+
/**
|
|
622
|
+
* @type {DeltaBuilderAny}
|
|
623
|
+
*/
|
|
624
|
+
get _modValue () {
|
|
625
|
+
/**
|
|
626
|
+
* @type {any}
|
|
627
|
+
*/
|
|
628
|
+
const v = this.value
|
|
629
|
+
this._fingerprint = null
|
|
630
|
+
if ($deltaAny.check(v) && v.isDone) {
|
|
631
|
+
// @ts-ignore
|
|
632
|
+
return (this.value = clone(v))
|
|
633
|
+
}
|
|
634
|
+
return v
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
get fingerprint () {
|
|
638
|
+
return this._fingerprint || (this._fingerprint = buffer.toBase64(encoding.encode(encoder => {
|
|
639
|
+
encoding.writeVarUint(encoder, 5) // map insert type: 5
|
|
640
|
+
encoding.writeAny(encoder, this.key)
|
|
641
|
+
if ($deltaAny.check(this.value)) {
|
|
642
|
+
encoding.writeUint8(encoder, 0)
|
|
643
|
+
encoding.writeVarString(encoder, this.value.fingerprint)
|
|
644
|
+
} else {
|
|
645
|
+
encoding.writeUint8(encoder, 1)
|
|
646
|
+
encoding.writeAny(encoder, this.value)
|
|
647
|
+
}
|
|
648
|
+
})))
|
|
649
|
+
}
|
|
650
|
+
|
|
396
651
|
toJSON () {
|
|
397
652
|
const v = this.value
|
|
398
653
|
const prevValue = this.prevValue
|
|
@@ -404,25 +659,25 @@ export class MapInsertOp {
|
|
|
404
659
|
}
|
|
405
660
|
|
|
406
661
|
/**
|
|
407
|
-
* @param {
|
|
662
|
+
* @param {AttrInsertOp<V>} other
|
|
408
663
|
*/
|
|
409
664
|
[traits.EqualityTraitSymbol] (other) {
|
|
410
665
|
return this.key === other.key && fun.equalityDeep(this.value, other.value) && fun.equalityDeep(this.attribution, other.attribution)
|
|
411
666
|
}
|
|
412
667
|
|
|
413
668
|
/**
|
|
414
|
-
* @return {
|
|
669
|
+
* @return {AttrInsertOp<V,K>}
|
|
415
670
|
*/
|
|
416
671
|
clone () {
|
|
417
|
-
return new
|
|
672
|
+
return new AttrInsertOp(this.key, _markMaybeDeltaAsDone(this.value), _markMaybeDeltaAsDone(this.prevValue), _cloneAttrs(this.attribution))
|
|
418
673
|
}
|
|
419
674
|
}
|
|
420
675
|
|
|
421
676
|
/**
|
|
422
677
|
* @template V
|
|
423
|
-
* @template [K=string]
|
|
678
|
+
* @template {string|number} [K=string]
|
|
424
679
|
*/
|
|
425
|
-
export class
|
|
680
|
+
export class AttrDeleteOp {
|
|
426
681
|
/**
|
|
427
682
|
* @param {K} key
|
|
428
683
|
* @param {V|undefined} prevValue
|
|
@@ -438,6 +693,10 @@ export class MapDeleteOp {
|
|
|
438
693
|
*/
|
|
439
694
|
this.prevValue = prevValue
|
|
440
695
|
this.attribution = attribution
|
|
696
|
+
/**
|
|
697
|
+
* @type {string|null}
|
|
698
|
+
*/
|
|
699
|
+
this._fingerprint = null
|
|
441
700
|
}
|
|
442
701
|
|
|
443
702
|
get value () { return undefined }
|
|
@@ -447,6 +706,13 @@ export class MapDeleteOp {
|
|
|
447
706
|
*/
|
|
448
707
|
get type () { return 'delete' }
|
|
449
708
|
|
|
709
|
+
get fingerprint () {
|
|
710
|
+
return this._fingerprint || (this._fingerprint = buffer.toBase64(encoding.encode(encoder => {
|
|
711
|
+
encoding.writeVarUint(encoder, 6) // map delete type: 6
|
|
712
|
+
encoding.writeAny(encoder, this.key)
|
|
713
|
+
})))
|
|
714
|
+
}
|
|
715
|
+
|
|
450
716
|
/**
|
|
451
717
|
* @return {DeltaAttrOpJSON}
|
|
452
718
|
*/
|
|
@@ -458,35 +724,41 @@ export class MapDeleteOp {
|
|
|
458
724
|
}
|
|
459
725
|
|
|
460
726
|
/**
|
|
461
|
-
* @param {
|
|
727
|
+
* @param {AttrDeleteOp<V>} other
|
|
462
728
|
*/
|
|
463
729
|
[traits.EqualityTraitSymbol] (other) {
|
|
464
730
|
return this.key === other.key && fun.equalityDeep(this.attribution, other.attribution)
|
|
465
731
|
}
|
|
466
732
|
|
|
467
733
|
clone () {
|
|
468
|
-
return new
|
|
734
|
+
return new AttrDeleteOp(this.key, _markMaybeDeltaAsDone(this.prevValue), _cloneAttrs(this.attribution))
|
|
469
735
|
}
|
|
470
736
|
}
|
|
471
737
|
|
|
472
738
|
/**
|
|
473
|
-
* @template {DeltaAny} Modifier
|
|
474
|
-
* @template [K=string]
|
|
739
|
+
* @template {DeltaAny} [Modifier=DeltaAny]
|
|
740
|
+
* @template {string|number} [K=string]
|
|
475
741
|
*/
|
|
476
|
-
export class
|
|
742
|
+
export class AttrModifyOp {
|
|
477
743
|
/**
|
|
478
744
|
* @param {K} key
|
|
479
745
|
* @param {Modifier} delta
|
|
480
746
|
*/
|
|
481
747
|
constructor (key, delta) {
|
|
482
748
|
/**
|
|
749
|
+
* @readonly
|
|
483
750
|
* @type {K}
|
|
484
751
|
*/
|
|
485
752
|
this.key = key
|
|
486
753
|
/**
|
|
754
|
+
* @readonly
|
|
487
755
|
* @type {Modifier}
|
|
488
756
|
*/
|
|
489
757
|
this.value = delta
|
|
758
|
+
/**
|
|
759
|
+
* @type {string|null}
|
|
760
|
+
*/
|
|
761
|
+
this._fingerprint = null
|
|
490
762
|
}
|
|
491
763
|
|
|
492
764
|
/**
|
|
@@ -494,6 +766,27 @@ export class MapModifyOp {
|
|
|
494
766
|
*/
|
|
495
767
|
get type () { return 'modify' }
|
|
496
768
|
|
|
769
|
+
get fingerprint () {
|
|
770
|
+
return this._fingerprint || (this._fingerprint = buffer.toBase64(encoding.encode(encoder => {
|
|
771
|
+
encoding.writeVarUint(encoder, 7) // map modify type: 7
|
|
772
|
+
encoding.writeAny(encoder, this.key)
|
|
773
|
+
encoding.writeVarString(encoder, this.value.fingerprint)
|
|
774
|
+
})))
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* @return {DeltaBuilder}
|
|
779
|
+
*/
|
|
780
|
+
get _modValue () {
|
|
781
|
+
this._fingerprint = null
|
|
782
|
+
if (this.value.isDone) {
|
|
783
|
+
// @ts-ignore
|
|
784
|
+
this.value = /** @type {any} */ (clone(this.value))
|
|
785
|
+
}
|
|
786
|
+
// @ts-ignore
|
|
787
|
+
return this.value
|
|
788
|
+
}
|
|
789
|
+
|
|
497
790
|
/**
|
|
498
791
|
* @return {DeltaAttrOpJSON}
|
|
499
792
|
*/
|
|
@@ -505,38 +798,38 @@ export class MapModifyOp {
|
|
|
505
798
|
}
|
|
506
799
|
|
|
507
800
|
/**
|
|
508
|
-
* @param {
|
|
801
|
+
* @param {AttrModifyOp<Modifier>} other
|
|
509
802
|
*/
|
|
510
803
|
[traits.EqualityTraitSymbol] (other) {
|
|
511
804
|
return this.key === other.key && this.value[traits.EqualityTraitSymbol](other.value)
|
|
512
805
|
}
|
|
513
806
|
|
|
514
807
|
/**
|
|
515
|
-
* @return {
|
|
808
|
+
* @return {AttrModifyOp<Modifier,K>}
|
|
516
809
|
*/
|
|
517
810
|
clone () {
|
|
518
|
-
return new
|
|
811
|
+
return new AttrModifyOp(this.key, /** @type {Modifier} */ (this.value.done()))
|
|
519
812
|
}
|
|
520
813
|
}
|
|
521
814
|
|
|
522
815
|
/**
|
|
523
|
-
* @type {s.Schema<
|
|
816
|
+
* @type {s.Schema<AttrDeleteOp<any> | DeleteOp>}
|
|
524
817
|
*/
|
|
525
|
-
export const $deleteOp = s.$custom(o => o != null && (o.constructor === DeleteOp || o.constructor ===
|
|
818
|
+
export const $deleteOp = s.$custom(o => o != null && (o.constructor === DeleteOp || o.constructor === AttrDeleteOp))
|
|
526
819
|
|
|
527
820
|
/**
|
|
528
|
-
* @type {s.Schema<
|
|
821
|
+
* @type {s.Schema<AttrInsertOp<any> | InsertOp<any>>}
|
|
529
822
|
*/
|
|
530
|
-
export const $insertOp = s.$custom(o => o != null && (o.constructor ===
|
|
823
|
+
export const $insertOp = s.$custom(o => o != null && (o.constructor === AttrInsertOp || o.constructor === InsertOp))
|
|
531
824
|
|
|
532
825
|
/**
|
|
533
|
-
* @template Content
|
|
826
|
+
* @template {encoding.AnyEncodable|DeltaAny} Content
|
|
534
827
|
* @param {s.Schema<Content>} $content
|
|
535
|
-
* @return {s.Schema<
|
|
828
|
+
* @return {s.Schema<AttrInsertOp<Content> | InsertOp<Content>>}
|
|
536
829
|
*/
|
|
537
830
|
export const $insertOpWith = $content => s.$custom(o =>
|
|
538
831
|
o != null && (
|
|
539
|
-
(o.constructor ===
|
|
832
|
+
(o.constructor === AttrInsertOp && $content.check(/** @type {AttrInsertOp<Content>} */ (o).value)) ||
|
|
540
833
|
(o.constructor === InsertOp && /** @type {InsertOp<Content>} */ (o).insert.every(ins => $content.check(ins)))
|
|
541
834
|
)
|
|
542
835
|
)
|
|
@@ -552,18 +845,18 @@ export const $textOp = s.$constructedBy(TextOp)
|
|
|
552
845
|
export const $retainOp = s.$constructedBy(RetainOp)
|
|
553
846
|
|
|
554
847
|
/**
|
|
555
|
-
* @type {s.Schema<
|
|
848
|
+
* @type {s.Schema<AttrModifyOp | ModifyOp>}
|
|
556
849
|
*/
|
|
557
|
-
export const $modifyOp = s.$custom(o => o != null && (o.constructor ===
|
|
850
|
+
export const $modifyOp = s.$custom(o => o != null && (o.constructor === AttrModifyOp || o.constructor === ModifyOp))
|
|
558
851
|
|
|
559
852
|
/**
|
|
560
853
|
* @template {DeltaAny} Modify
|
|
561
854
|
* @param {s.Schema<Modify>} $content
|
|
562
|
-
* @return {s.Schema<
|
|
855
|
+
* @return {s.Schema<AttrModifyOp<Modify> | ModifyOp<Modify>>}
|
|
563
856
|
*/
|
|
564
857
|
export const $modifyOpWith = $content => s.$custom(o =>
|
|
565
858
|
o != null && (
|
|
566
|
-
(o.constructor ===
|
|
859
|
+
(o.constructor === AttrModifyOp && $content.check(/** @type {AttrModifyOp<Modify>} */ (o).value)) ||
|
|
567
860
|
(o.constructor === ModifyOp && $content.check(/** @type {ModifyOp<Modify>} */ (o).value))
|
|
568
861
|
)
|
|
569
862
|
)
|
|
@@ -579,8 +872,8 @@ export const $anyOp = s.$union($insertOp, $deleteOp, $textOp, $modifyOp)
|
|
|
579
872
|
*/
|
|
580
873
|
|
|
581
874
|
/**
|
|
582
|
-
* @template {{[Key in string|number
|
|
583
|
-
* @template {string|number
|
|
875
|
+
* @template {{[Key in string|number]: any}} Attrs
|
|
876
|
+
* @template {string|number} Key
|
|
584
877
|
* @template {any} Val
|
|
585
878
|
* @typedef {{ [K in (Key | keyof Attrs)]: (unknown extends Attrs[K] ? never : Attrs[K]) | (Key extends K ? Val : never) }} AddToAttrs
|
|
586
879
|
*/
|
|
@@ -598,29 +891,20 @@ export const $anyOp = s.$union($insertOp, $deleteOp, $textOp, $modifyOp)
|
|
|
598
891
|
|
|
599
892
|
/**
|
|
600
893
|
* @template {s.Schema<Delta<any,any,any,any,any>>|null} Schema
|
|
601
|
-
* @typedef {_AnyToNull<Schema> extends null ? Delta<any,{[key:string|number
|
|
894
|
+
* @typedef {_AnyToNull<Schema> extends null ? Delta<any,{[key:string|number]:any},any,string> : (Schema extends s.Schema<infer D> ? D : never)} AllowedDeltaFromSchema
|
|
602
895
|
*/
|
|
603
896
|
|
|
604
897
|
/**
|
|
605
|
-
* @typedef {Delta<any,{ [k:string]: any },any,any,any>} DeltaAny
|
|
898
|
+
* @typedef {Delta<any,{ [k:string|number]: any },any,any,any>} DeltaAny
|
|
606
899
|
*/
|
|
607
|
-
|
|
608
|
-
// note: simply copy the values from Delta.attrs as the parameter of the function
|
|
609
900
|
/**
|
|
610
|
-
* @
|
|
611
|
-
* @param {Delta<any,Attrs,any,any,any>} d
|
|
612
|
-
* @param {(v:{ [K in keyof Attrs]: MapInsertOp<Attrs[K],K>|MapDeleteOp<Attrs[K],K>|(Delta extends Attrs[K] ? MapModifyOp<Extract<Attrs[K],Delta>,K> : never) }[keyof Attrs])=>any} handler
|
|
901
|
+
* @typedef {DeltaBuilder<any,{ [k:string|number]: any },any,any,any>} DeltaBuilderAny
|
|
613
902
|
*/
|
|
614
|
-
export const forEachAttr = (d, handler) => {
|
|
615
|
-
for (const k in d.attrs) {
|
|
616
|
-
handler(/** @type {any} */ (d.attrs[k]))
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
903
|
|
|
620
904
|
/**
|
|
621
905
|
* @template {string} [NodeName=any]
|
|
622
|
-
* @template {{[
|
|
623
|
-
* @template {
|
|
906
|
+
* @template {{[k:string|number]:any}} [Attrs={}]
|
|
907
|
+
* @template {encoding.AnyEncodable|DeltaAny|never} [Children=never]
|
|
624
908
|
* @template {string|never} [Text=never]
|
|
625
909
|
* @template {s.Schema<Delta<any,any,any,any,any>>|null} [Schema=any]
|
|
626
910
|
*/
|
|
@@ -633,7 +917,9 @@ export class Delta {
|
|
|
633
917
|
this.name = name || null
|
|
634
918
|
this.$schema = $schema || null
|
|
635
919
|
/**
|
|
636
|
-
* @type {{ [K in keyof Attrs]?:
|
|
920
|
+
* @type {{ [K in keyof Attrs]?: K extends string|number ? (AttrInsertOp<Attrs[K],K>|AttrDeleteOp<Attrs[K],K>|(Delta extends Attrs[K] ? AttrModifyOp<Extract<Attrs[K],DeltaAny>,K> : never)) : never }
|
|
921
|
+
* & { [Symbol.iterator]: () => Iterator<{ [K in keyof Attrs]: K extends string|number ? (AttrInsertOp<Attrs[K],K>|AttrDeleteOp<Attrs[K],K>|(Delta extends Attrs[K] ? AttrModifyOp<Extract<Attrs[K],DeltaAny>,K> : never)) : never }[keyof Attrs]> }
|
|
922
|
+
* }
|
|
637
923
|
*/
|
|
638
924
|
this.attrs = /** @type {any} */ ({
|
|
639
925
|
* [Symbol.iterator] () {
|
|
@@ -653,10 +939,50 @@ export class Delta {
|
|
|
653
939
|
* >}
|
|
654
940
|
*/
|
|
655
941
|
this.children = /** @type {any} */ (list.create())
|
|
942
|
+
this.childCnt = 0
|
|
656
943
|
/**
|
|
657
944
|
* @type {any}
|
|
658
945
|
*/
|
|
659
946
|
this.origin = null
|
|
947
|
+
/**
|
|
948
|
+
* @type {string|null}
|
|
949
|
+
*/
|
|
950
|
+
this._fingerprint = null
|
|
951
|
+
this.isDone = false
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* @type {string}
|
|
956
|
+
*/
|
|
957
|
+
get fingerprint () {
|
|
958
|
+
return this._fingerprint || (this._fingerprint = buffer.toBase64(encoding.encode(encoder => {
|
|
959
|
+
encoding.writeAny(encoder, this.name)
|
|
960
|
+
/**
|
|
961
|
+
* @type {Array<number|string>}
|
|
962
|
+
*/
|
|
963
|
+
const keys = []
|
|
964
|
+
for (const attr of this.attrs) {
|
|
965
|
+
keys.push(attr.key)
|
|
966
|
+
}
|
|
967
|
+
keys.sort((a, b) => {
|
|
968
|
+
const aIsString = s.$string.check(a)
|
|
969
|
+
const bIsString = s.$string.check(b)
|
|
970
|
+
// numbers first
|
|
971
|
+
// in ascending order
|
|
972
|
+
return (aIsString && bIsString)
|
|
973
|
+
? a.localeCompare(b)
|
|
974
|
+
: (aIsString ? 1 : (bIsString ? -1 : (a - b)))
|
|
975
|
+
})
|
|
976
|
+
encoding.writeVarUint(encoder, keys.length)
|
|
977
|
+
for (const key of keys) {
|
|
978
|
+
encoding.writeVarString(encoder, /** @type {any} */ (this.attrs[/** @type {keyof Attrs} */ (key)]).fingerprint)
|
|
979
|
+
}
|
|
980
|
+
encoding.writeVarUint(encoder, this.children.len)
|
|
981
|
+
for (const child of this.children) {
|
|
982
|
+
encoding.writeVarString(encoder, child.fingerprint)
|
|
983
|
+
}
|
|
984
|
+
return buffer.toBase64(rabin.fingerprint(rabin.StandardIrreducible128, encoding.toUint8Array(encoder)))
|
|
985
|
+
})))
|
|
660
986
|
}
|
|
661
987
|
|
|
662
988
|
isEmpty () {
|
|
@@ -667,6 +993,7 @@ export class Delta {
|
|
|
667
993
|
* @return {DeltaJSON}
|
|
668
994
|
*/
|
|
669
995
|
toJSON () {
|
|
996
|
+
const name = this.name
|
|
670
997
|
/**
|
|
671
998
|
* @type {any}
|
|
672
999
|
*/
|
|
@@ -675,14 +1002,15 @@ export class Delta {
|
|
|
675
1002
|
* @type {any}
|
|
676
1003
|
*/
|
|
677
1004
|
const children = []
|
|
678
|
-
|
|
1005
|
+
for (const attr of this.attrs) {
|
|
679
1006
|
attrs[attr.key] = attr.toJSON()
|
|
680
|
-
}
|
|
1007
|
+
}
|
|
681
1008
|
this.children.forEach(val => {
|
|
682
1009
|
children.push(val.toJSON())
|
|
683
1010
|
})
|
|
684
1011
|
return object.assign(
|
|
685
|
-
|
|
1012
|
+
{ type: /** @type {'delta'} */ ('delta') },
|
|
1013
|
+
(name != null ? { name } : {}),
|
|
686
1014
|
(object.isEmpty(attrs) ? {} : { attrs }),
|
|
687
1015
|
(children.length > 0 ? { children } : {})
|
|
688
1016
|
)
|
|
@@ -697,36 +1025,139 @@ export class Delta {
|
|
|
697
1025
|
}
|
|
698
1026
|
|
|
699
1027
|
/**
|
|
700
|
-
* @
|
|
1028
|
+
* @param {any} other
|
|
1029
|
+
* @return {boolean}
|
|
701
1030
|
*/
|
|
702
|
-
|
|
1031
|
+
[traits.EqualityTraitSymbol] (other) {
|
|
1032
|
+
// @todo it is only necessary to compare finrerprints OR do a deep equality check
|
|
1033
|
+
return this.name === other.name && fun.equalityDeep(this.attrs, other.attrs) && fun.equalityDeep(this.children, other.children) && this.childCnt === other.childCnt && this.fingerprint === other.fingerprint
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/**
|
|
1037
|
+
* @param {number} start
|
|
1038
|
+
* @param {number} end
|
|
1039
|
+
* @return {Delta<NodeName,Attrs,Children,Text,Schema>}
|
|
1040
|
+
*/
|
|
1041
|
+
slice (start = 0, end = this.childCnt) {
|
|
1042
|
+
const cpy = /** @type {DeltaAny} */ (new DeltaBuilder(/** @type {any} */ (this.name), this.$schema))
|
|
1043
|
+
cpy.origin = this.origin
|
|
1044
|
+
// copy attrs
|
|
1045
|
+
for (const op of this.attrs) {
|
|
1046
|
+
cpy.attrs[op.key] = /** @type {any} */ (op.clone())
|
|
1047
|
+
}
|
|
1048
|
+
// copy children
|
|
1049
|
+
const slicedLen = end - start
|
|
1050
|
+
let remainingLen = slicedLen
|
|
703
1051
|
/**
|
|
704
|
-
* @type {
|
|
1052
|
+
* @type {ChildrenOpAny?}
|
|
705
1053
|
*/
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
1054
|
+
let currNode = this.children.start
|
|
1055
|
+
let currNodeOffset = 0
|
|
1056
|
+
while (start > 0 && currNode != null) {
|
|
1057
|
+
if (currNode.length <= start) {
|
|
1058
|
+
start -= currNode.length
|
|
1059
|
+
currNode = currNode.next
|
|
1060
|
+
} else {
|
|
1061
|
+
currNodeOffset = start
|
|
1062
|
+
start = 0
|
|
1063
|
+
}
|
|
710
1064
|
}
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
1065
|
+
if (currNodeOffset > 0 && currNode) {
|
|
1066
|
+
const ncpy = currNode.clone(currNodeOffset, currNodeOffset + math.min(remainingLen, currNode.length - currNodeOffset))
|
|
1067
|
+
list.pushEnd(cpy.children, ncpy)
|
|
1068
|
+
remainingLen -= ncpy.length
|
|
1069
|
+
currNode = currNode.next
|
|
1070
|
+
}
|
|
1071
|
+
while (currNode != null && currNode.length <= remainingLen) {
|
|
1072
|
+
list.pushEnd(cpy.children, currNode.clone())
|
|
1073
|
+
currNode = currNode.next
|
|
1074
|
+
}
|
|
1075
|
+
if (currNode != null && remainingLen > 0) {
|
|
1076
|
+
list.pushEnd(cpy.children, currNode.clone(0, remainingLen))
|
|
1077
|
+
}
|
|
1078
|
+
cpy.childCnt = slicedLen - remainingLen
|
|
1079
|
+
// @ts-ignore
|
|
1080
|
+
return cpy
|
|
715
1081
|
}
|
|
716
1082
|
|
|
717
1083
|
/**
|
|
718
|
-
*
|
|
719
|
-
*
|
|
1084
|
+
* Mark this delta as done and perform some cleanup (e.g. remove appended retains without
|
|
1085
|
+
* formats&attributions). In the future, there might be additional merge operations that can be
|
|
1086
|
+
* performed to result in smaller deltas. Set `markAsDone=false` to only perform the cleanup.
|
|
1087
|
+
*
|
|
1088
|
+
* @return {Delta<NodeName,Attrs,Children,Text,Schema>}
|
|
720
1089
|
*/
|
|
721
|
-
|
|
722
|
-
|
|
1090
|
+
done (markAsDone = true) {
|
|
1091
|
+
if (!this.isDone) {
|
|
1092
|
+
this.isDone = markAsDone
|
|
1093
|
+
const cs = this.children
|
|
1094
|
+
for (let end = cs.end; end !== null && $retainOp.check(end) && end.format == null && end.attribution == null; end = cs.end) {
|
|
1095
|
+
this.childCnt -= end.length
|
|
1096
|
+
list.popEnd(cs)
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
return this
|
|
723
1100
|
}
|
|
724
1101
|
}
|
|
725
1102
|
|
|
1103
|
+
/**
|
|
1104
|
+
* @template {DeltaAny} D
|
|
1105
|
+
* @param {D} d
|
|
1106
|
+
* @return {D extends Delta<infer NodeName,infer Attrs,infer Children,infer Text,infer Schema> ? DeltaBuilder<NodeName,Attrs,Children,Text,Schema> : never}
|
|
1107
|
+
*/
|
|
1108
|
+
export const clone = d => /** @type {any} */ (d.slice(0, d.childCnt))
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* Try merging this op with the previous op
|
|
1112
|
+
* @param {list.List<any>} parent
|
|
1113
|
+
* @param {InsertOp<any>|RetainOp|DeleteOp|TextOp|ModifyOp<any>} op
|
|
1114
|
+
*/
|
|
1115
|
+
const tryMergeWithPrev = (parent, op) => {
|
|
1116
|
+
const prevOp = op.prev
|
|
1117
|
+
if (
|
|
1118
|
+
prevOp?.constructor !== op.constructor ||
|
|
1119
|
+
(
|
|
1120
|
+
(!$deleteOp.check(op) && !$modifyOp.check(op)) && (!fun.equalityDeep(op.format, /** @type {InsertOp<any>} */ (prevOp).format) || !fun.equalityDeep(op.attribution, /** @type {InsertOp<any>} */ (prevOp).attribution))
|
|
1121
|
+
)
|
|
1122
|
+
) {
|
|
1123
|
+
// constructor mismatch or format/attribution mismatch
|
|
1124
|
+
return
|
|
1125
|
+
}
|
|
1126
|
+
// can be merged
|
|
1127
|
+
if ($insertOp.check(op)) {
|
|
1128
|
+
/** @type {InsertOp<any>} */ (prevOp).insert.push(...op.insert)
|
|
1129
|
+
} else if ($retainOp.check(op)) {
|
|
1130
|
+
// @ts-ignore
|
|
1131
|
+
/** @type {RetainOp} */ (prevOp).retain += op.retain
|
|
1132
|
+
} else if ($deleteOp.check(op)) {
|
|
1133
|
+
/** @type {DeleteOp} */ (prevOp).delete += op.delete
|
|
1134
|
+
} else if ($textOp.check(op)) {
|
|
1135
|
+
/** @type {TextOp} */ (prevOp)._updateInsert(/** @type {TextOp} */ (prevOp).insert + op.insert)
|
|
1136
|
+
} else {
|
|
1137
|
+
error.unexpectedCase()
|
|
1138
|
+
}
|
|
1139
|
+
list.remove(parent, op)
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/**
|
|
1143
|
+
* Ensures that the delta can be edited. clears _fingerprint cache.
|
|
1144
|
+
*
|
|
1145
|
+
* @param {any} d
|
|
1146
|
+
*/
|
|
1147
|
+
const modDeltaCheck = d => {
|
|
1148
|
+
if (d.isDone) {
|
|
1149
|
+
/**
|
|
1150
|
+
* You tried to modify a delta after it has been marked as "done".
|
|
1151
|
+
*/
|
|
1152
|
+
throw error.create("Readonly Delta can't be modified")
|
|
1153
|
+
}
|
|
1154
|
+
d._fingerprint = null
|
|
1155
|
+
}
|
|
1156
|
+
|
|
726
1157
|
/**
|
|
727
1158
|
* @template {string} [NodeName=any]
|
|
728
|
-
* @template {{[key:string|number
|
|
729
|
-
* @template {
|
|
1159
|
+
* @template {{[key:string|number]:any}} [Attrs={}]
|
|
1160
|
+
* @template {encoding.AnyEncodable|DeltaAny|never} [Children=never]
|
|
730
1161
|
* @template {string|never} [Text=never]
|
|
731
1162
|
* @template {s.Schema<Delta<any,any,any,any,any>>|null} [Schema=any]
|
|
732
1163
|
* @extends {Delta<NodeName,Attrs,Children,Text,Schema>}
|
|
@@ -752,6 +1183,7 @@ export class DeltaBuilder extends Delta {
|
|
|
752
1183
|
* @param {Attribution?} attribution
|
|
753
1184
|
*/
|
|
754
1185
|
useAttribution (attribution) {
|
|
1186
|
+
modDeltaCheck(this)
|
|
755
1187
|
this.usedAttribution = attribution
|
|
756
1188
|
return this
|
|
757
1189
|
}
|
|
@@ -761,6 +1193,7 @@ export class DeltaBuilder extends Delta {
|
|
|
761
1193
|
* @return {this}
|
|
762
1194
|
*/
|
|
763
1195
|
useAttributes (attributes) {
|
|
1196
|
+
modDeltaCheck(this)
|
|
764
1197
|
this.usedAttributes = attributes
|
|
765
1198
|
return this
|
|
766
1199
|
}
|
|
@@ -770,6 +1203,7 @@ export class DeltaBuilder extends Delta {
|
|
|
770
1203
|
* @param {any} value
|
|
771
1204
|
*/
|
|
772
1205
|
updateUsedAttributes (name, value) {
|
|
1206
|
+
modDeltaCheck(this)
|
|
773
1207
|
if (value == null) {
|
|
774
1208
|
this.usedAttributes = object.assign({}, this.usedAttributes)
|
|
775
1209
|
delete this.usedAttributes?.[name]
|
|
@@ -789,6 +1223,7 @@ export class DeltaBuilder extends Delta {
|
|
|
789
1223
|
* @param {Attribution[NAME]?} value
|
|
790
1224
|
*/
|
|
791
1225
|
updateUsedAttribution (name, value) {
|
|
1226
|
+
modDeltaCheck(this)
|
|
792
1227
|
if (value == null) {
|
|
793
1228
|
this.usedAttribution = object.assign({}, this.usedAttribution)
|
|
794
1229
|
delete this.usedAttribution?.[name]
|
|
@@ -811,11 +1246,12 @@ export class DeltaBuilder extends Delta {
|
|
|
811
1246
|
* NodeName,
|
|
812
1247
|
* Attrs,
|
|
813
1248
|
* Exclude<NewContent,string>[number]|Children,
|
|
814
|
-
* (Extract<NewContent,string>|Text) extends
|
|
1249
|
+
* (Extract<NewContent,string>|Text) extends never ? never : string,
|
|
815
1250
|
* Schema
|
|
816
1251
|
* >}
|
|
817
1252
|
*/
|
|
818
1253
|
insert (insert, formatting = null, attribution = null) {
|
|
1254
|
+
modDeltaCheck(this)
|
|
819
1255
|
const mergedAttributes = mergeAttrs(this.usedAttributes, formatting)
|
|
820
1256
|
const mergedAttribution = mergeAttrs(this.usedAttribution, attribution)
|
|
821
1257
|
/**
|
|
@@ -825,16 +1261,20 @@ export class DeltaBuilder extends Delta {
|
|
|
825
1261
|
const end = this.children.end
|
|
826
1262
|
if (s.$string.check(insert)) {
|
|
827
1263
|
if ($textOp.check(end) && checkMergedEquals(end)) {
|
|
828
|
-
end.insert
|
|
1264
|
+
end._updateInsert(end.insert + insert)
|
|
829
1265
|
} else if (insert.length > 0) {
|
|
830
1266
|
list.pushEnd(this.children, new TextOp(insert, object.isEmpty(mergedAttributes) ? null : mergedAttributes, object.isEmpty(mergedAttribution) ? null : mergedAttribution))
|
|
831
1267
|
}
|
|
1268
|
+
this.childCnt += insert.length
|
|
832
1269
|
} else if (arr.isArray(insert)) {
|
|
833
1270
|
if ($insertOp.check(end) && checkMergedEquals(end)) {
|
|
1271
|
+
// @ts-ignore
|
|
834
1272
|
end.insert.push(...insert)
|
|
1273
|
+
end._fingerprint = null
|
|
835
1274
|
} else if (insert.length > 0) {
|
|
836
1275
|
list.pushEnd(this.children, new InsertOp(insert, object.isEmpty(mergedAttributes) ? null : mergedAttributes, object.isEmpty(mergedAttribution) ? null : mergedAttribution))
|
|
837
1276
|
}
|
|
1277
|
+
this.childCnt += insert.length
|
|
838
1278
|
}
|
|
839
1279
|
return /** @type {any} */ (this)
|
|
840
1280
|
}
|
|
@@ -853,9 +1293,11 @@ export class DeltaBuilder extends Delta {
|
|
|
853
1293
|
* >}
|
|
854
1294
|
*/
|
|
855
1295
|
modify (modify, formatting = null, attribution = null) {
|
|
1296
|
+
modDeltaCheck(this)
|
|
856
1297
|
const mergedAttributes = mergeAttrs(this.usedAttributes, formatting)
|
|
857
1298
|
const mergedAttribution = mergeAttrs(this.usedAttribution, attribution)
|
|
858
1299
|
list.pushEnd(this.children, new ModifyOp(modify, object.isEmpty(mergedAttributes) ? null : mergedAttributes, object.isEmpty(mergedAttribution) ? null : mergedAttribution))
|
|
1300
|
+
this.childCnt += 1
|
|
859
1301
|
return /** @type {any} */ (this)
|
|
860
1302
|
}
|
|
861
1303
|
|
|
@@ -865,14 +1307,17 @@ export class DeltaBuilder extends Delta {
|
|
|
865
1307
|
* @param {Attribution?} [attribution]
|
|
866
1308
|
*/
|
|
867
1309
|
retain (len, format = null, attribution = null) {
|
|
1310
|
+
modDeltaCheck(this)
|
|
868
1311
|
const mergedFormats = mergeAttrs(this.usedAttributes, format)
|
|
869
1312
|
const mergedAttribution = mergeAttrs(this.usedAttribution, attribution)
|
|
870
1313
|
const lastOp = /** @type {RetainOp|InsertOp<any>} */ (this.children.end)
|
|
871
1314
|
if (lastOp instanceof RetainOp && fun.equalityDeep(mergedFormats, lastOp.format) && fun.equalityDeep(mergedAttribution, lastOp.attribution)) {
|
|
1315
|
+
// @ts-ignore
|
|
872
1316
|
lastOp.retain += len
|
|
873
1317
|
} else if (len > 0) {
|
|
874
1318
|
list.pushEnd(this.children, new RetainOp(len, mergedFormats, mergedAttribution))
|
|
875
1319
|
}
|
|
1320
|
+
this.childCnt += len
|
|
876
1321
|
return this
|
|
877
1322
|
}
|
|
878
1323
|
|
|
@@ -880,12 +1325,14 @@ export class DeltaBuilder extends Delta {
|
|
|
880
1325
|
* @param {number} len
|
|
881
1326
|
*/
|
|
882
1327
|
delete (len) {
|
|
1328
|
+
modDeltaCheck(this)
|
|
883
1329
|
const lastOp = /** @type {DeleteOp|InsertOp<any>} */ (this.children.end)
|
|
884
1330
|
if (lastOp instanceof DeleteOp) {
|
|
885
1331
|
lastOp.delete += len
|
|
886
1332
|
} else if (len > 0) {
|
|
887
1333
|
list.pushEnd(this.children, new DeleteOp(len))
|
|
888
1334
|
}
|
|
1335
|
+
this.childCnt += len
|
|
889
1336
|
return this
|
|
890
1337
|
}
|
|
891
1338
|
|
|
@@ -905,7 +1352,8 @@ export class DeltaBuilder extends Delta {
|
|
|
905
1352
|
* >}
|
|
906
1353
|
*/
|
|
907
1354
|
set (key, val, attribution = null, prevValue) {
|
|
908
|
-
|
|
1355
|
+
modDeltaCheck(this)
|
|
1356
|
+
this.attrs[key] = /** @type {any} */ (new AttrInsertOp(key, val, prevValue, mergeAttrs(this.usedAttribution, attribution)))
|
|
909
1357
|
return /** @type {any} */ (this)
|
|
910
1358
|
}
|
|
911
1359
|
|
|
@@ -922,6 +1370,7 @@ export class DeltaBuilder extends Delta {
|
|
|
922
1370
|
* >}
|
|
923
1371
|
*/
|
|
924
1372
|
setMany (attrs, attribution = null) {
|
|
1373
|
+
modDeltaCheck(this)
|
|
925
1374
|
for (const k in attrs) {
|
|
926
1375
|
this.set(/** @type {any} */ (k), attrs[k], attribution)
|
|
927
1376
|
}
|
|
@@ -942,7 +1391,8 @@ export class DeltaBuilder extends Delta {
|
|
|
942
1391
|
* >}
|
|
943
1392
|
*/
|
|
944
1393
|
unset (key, attribution = null, prevValue) {
|
|
945
|
-
|
|
1394
|
+
modDeltaCheck(this)
|
|
1395
|
+
this.attrs[key] = /** @type {any} */ (new AttrDeleteOp(key, prevValue, mergeAttrs(this.usedAttribution, attribution)))
|
|
946
1396
|
return /** @type {any} */ (this)
|
|
947
1397
|
}
|
|
948
1398
|
|
|
@@ -960,7 +1410,8 @@ export class DeltaBuilder extends Delta {
|
|
|
960
1410
|
* >}
|
|
961
1411
|
*/
|
|
962
1412
|
update (key, modify) {
|
|
963
|
-
this
|
|
1413
|
+
modDeltaCheck(this)
|
|
1414
|
+
this.attrs[key] = /** @type {any} */ (new AttrModifyOp(key, modify))
|
|
964
1415
|
return /** @type {any} */ (this)
|
|
965
1416
|
}
|
|
966
1417
|
|
|
@@ -968,37 +1419,64 @@ export class DeltaBuilder extends Delta {
|
|
|
968
1419
|
* @param {Delta<NodeName,Attrs,Children,Text,any>} other
|
|
969
1420
|
*/
|
|
970
1421
|
apply (other) {
|
|
1422
|
+
modDeltaCheck(this)
|
|
971
1423
|
this.$schema?.expect(other)
|
|
972
|
-
|
|
973
|
-
|
|
1424
|
+
// apply attrs
|
|
1425
|
+
for (let op of other.attrs) {
|
|
1426
|
+
const c = /** @type {AttrInsertOp<any,any>|AttrDeleteOp<any>|AttrModifyOp<any,any>} */ (this.attrs[op.key])
|
|
974
1427
|
if ($modifyOp.check(op)) {
|
|
975
1428
|
if ($deltaAny.check(c?.value)) {
|
|
976
|
-
|
|
1429
|
+
c._modValue.apply(op.value)
|
|
977
1430
|
} else {
|
|
978
1431
|
// then this is a simple modify
|
|
979
|
-
|
|
1432
|
+
// @ts-ignore
|
|
1433
|
+
this.attrs[op.key] = op.clone()
|
|
980
1434
|
}
|
|
981
1435
|
} else {
|
|
982
|
-
/** @type {
|
|
983
|
-
|
|
1436
|
+
op = /** @type {any} */ (op.clone())
|
|
1437
|
+
// @ts-ignore
|
|
1438
|
+
op.prevValue = c?.value
|
|
1439
|
+
// @ts-ignore
|
|
1440
|
+
this.attrs[op.key] = op
|
|
984
1441
|
}
|
|
985
|
-
}
|
|
1442
|
+
}
|
|
986
1443
|
// apply children
|
|
1444
|
+
/**
|
|
1445
|
+
* @type {ChildrenOpAny?}
|
|
1446
|
+
*/
|
|
987
1447
|
let opsI = this.children.start
|
|
988
1448
|
let offset = 0
|
|
1449
|
+
/**
|
|
1450
|
+
* At the end, we will try to merge this op, and op.next op with their respective previous op.
|
|
1451
|
+
*
|
|
1452
|
+
* Hence, anytime an op is cloned, deleted, or inserted (anytime list.* api is used) we must add
|
|
1453
|
+
* an op to maybeMergeable.
|
|
1454
|
+
*
|
|
1455
|
+
* @type {Array<InsertOp<any>|RetainOp|DeleteOp|TextOp|ModifyOp<any>>}
|
|
1456
|
+
*/
|
|
1457
|
+
const maybeMergeable = []
|
|
1458
|
+
/**
|
|
1459
|
+
* @template {InsertOp<any>|RetainOp|DeleteOp|TextOp|ModifyOp<any>|null} OP
|
|
1460
|
+
* @param {OP} op
|
|
1461
|
+
* @return {OP}
|
|
1462
|
+
*/
|
|
1463
|
+
const scheduleForMerge = op => {
|
|
1464
|
+
op && maybeMergeable.push(op)
|
|
1465
|
+
return op
|
|
1466
|
+
}
|
|
989
1467
|
other.children.forEach(op => {
|
|
990
1468
|
if ($textOp.check(op) || $insertOp.check(op)) {
|
|
991
1469
|
if (offset === 0) {
|
|
992
|
-
list.insertBetween(this.children, opsI == null ? this.children.end : opsI.prev, opsI, op.clone())
|
|
1470
|
+
list.insertBetween(this.children, opsI == null ? this.children.end : opsI.prev, opsI, scheduleForMerge(op.clone()))
|
|
993
1471
|
} else {
|
|
994
1472
|
if (opsI == null) error.unexpectedCase()
|
|
995
|
-
const cpy = opsI.clone()
|
|
996
|
-
cpy._splice(0, offset)
|
|
1473
|
+
const cpy = scheduleForMerge(opsI.clone(offset))
|
|
997
1474
|
opsI._splice(offset, opsI.length - offset)
|
|
998
1475
|
list.insertBetween(this.children, opsI, opsI.next || null, cpy)
|
|
999
|
-
list.insertBetween(this.children, opsI, cpy || null, op)
|
|
1476
|
+
list.insertBetween(this.children, opsI, cpy || null, scheduleForMerge(op.clone()))
|
|
1000
1477
|
offset = 0
|
|
1001
1478
|
}
|
|
1479
|
+
this.childCnt += op.insert.length
|
|
1002
1480
|
} else if ($retainOp.check(op)) {
|
|
1003
1481
|
let skipLen = op.length
|
|
1004
1482
|
while (opsI != null && opsI.length - offset <= skipLen) {
|
|
@@ -1009,13 +1487,15 @@ export class DeltaBuilder extends Delta {
|
|
|
1009
1487
|
if (opsI != null) {
|
|
1010
1488
|
offset += skipLen
|
|
1011
1489
|
} else {
|
|
1012
|
-
list.pushEnd(this.children, new RetainOp(skipLen, op.format, op.attribution))
|
|
1490
|
+
list.pushEnd(this.children, scheduleForMerge(new RetainOp(skipLen, op.format, op.attribution)))
|
|
1491
|
+
this.childCnt += skipLen
|
|
1013
1492
|
}
|
|
1014
1493
|
} else if ($deleteOp.check(op)) {
|
|
1015
1494
|
let remainingLen = op.delete
|
|
1016
1495
|
while (remainingLen > 0) {
|
|
1017
1496
|
if (opsI == null) {
|
|
1018
|
-
list.pushEnd(this.children, new DeleteOp(remainingLen))
|
|
1497
|
+
list.pushEnd(this.children, scheduleForMerge(new DeleteOp(remainingLen)))
|
|
1498
|
+
this.childCnt += remainingLen
|
|
1019
1499
|
break
|
|
1020
1500
|
} else if (opsI instanceof DeleteOp) {
|
|
1021
1501
|
const delLen = opsI.length - offset
|
|
@@ -1033,9 +1513,11 @@ export class DeltaBuilder extends Delta {
|
|
|
1033
1513
|
// case3: delete some part of end
|
|
1034
1514
|
// case4: delete some part of center
|
|
1035
1515
|
const delLen = math.min(opsI.length - offset, remainingLen)
|
|
1516
|
+
this.childCnt -= delLen
|
|
1036
1517
|
if (opsI.length === delLen) {
|
|
1037
1518
|
// case 1
|
|
1038
1519
|
offset = 0
|
|
1520
|
+
scheduleForMerge(opsI.next)
|
|
1039
1521
|
list.remove(this.children, opsI)
|
|
1040
1522
|
} else if (offset === 0) {
|
|
1041
1523
|
// case 2
|
|
@@ -1056,32 +1538,26 @@ export class DeltaBuilder extends Delta {
|
|
|
1056
1538
|
} else if ($modifyOp.check(op)) {
|
|
1057
1539
|
if (opsI == null) {
|
|
1058
1540
|
list.pushEnd(this.children, op.clone())
|
|
1541
|
+
this.childCnt += 1
|
|
1059
1542
|
return
|
|
1060
1543
|
}
|
|
1061
1544
|
if ($modifyOp.check(opsI)) {
|
|
1062
|
-
|
|
1063
|
-
} else if ($
|
|
1064
|
-
|
|
1065
|
-
if (!$deltaAny.check(d)) {
|
|
1066
|
-
// probably incompatible delta. can only modify deltas
|
|
1067
|
-
error.unexpectedCase()
|
|
1068
|
-
}
|
|
1069
|
-
/** @type {any} */ (d).apply(op.value)
|
|
1545
|
+
opsI._modValue.apply(op.value)
|
|
1546
|
+
} else if ($insertOp.check(opsI)) {
|
|
1547
|
+
opsI._modValue(offset).apply(op.value)
|
|
1070
1548
|
} else if ($retainOp.check(opsI)) {
|
|
1071
1549
|
if (offset > 0) {
|
|
1072
|
-
const cpy = opsI.clone()
|
|
1073
|
-
cpy._splice(offset, opsI.length - offset) // skipped len
|
|
1550
|
+
const cpy = scheduleForMerge(opsI.clone(0, offset)) // skipped len
|
|
1074
1551
|
opsI._splice(0, offset) // new remainder
|
|
1075
1552
|
list.insertBetween(this.children, opsI.prev, opsI, cpy) // insert skipped len
|
|
1076
1553
|
offset = 0
|
|
1077
1554
|
}
|
|
1078
|
-
|
|
1079
|
-
// advance content
|
|
1080
|
-
list.insertBetween(this.children, opsI.prev, opsI, op.clone()) // insert skipped len
|
|
1555
|
+
list.insertBetween(this.children, opsI.prev, opsI, scheduleForMerge(op.clone())) // insert skipped len
|
|
1081
1556
|
if (opsI.length === 1) {
|
|
1082
1557
|
list.remove(this.children, opsI)
|
|
1083
1558
|
} else {
|
|
1084
1559
|
opsI._splice(0, 1)
|
|
1560
|
+
scheduleForMerge(opsI)
|
|
1085
1561
|
}
|
|
1086
1562
|
} else if ($deleteOp.check(opsI)) {
|
|
1087
1563
|
// nop
|
|
@@ -1092,15 +1568,22 @@ export class DeltaBuilder extends Delta {
|
|
|
1092
1568
|
error.unexpectedCase()
|
|
1093
1569
|
}
|
|
1094
1570
|
})
|
|
1571
|
+
maybeMergeable.forEach(op => {
|
|
1572
|
+
// check if this is still integrated
|
|
1573
|
+
if (op.prev?.next === op) {
|
|
1574
|
+
tryMergeWithPrev(this.children, op)
|
|
1575
|
+
op.next && tryMergeWithPrev(this.children, op.next)
|
|
1576
|
+
}
|
|
1577
|
+
})
|
|
1095
1578
|
return this
|
|
1096
1579
|
}
|
|
1097
1580
|
|
|
1098
1581
|
/**
|
|
1099
|
-
* @param {
|
|
1582
|
+
* @param {DeltaAny} other
|
|
1100
1583
|
* @param {boolean} priority
|
|
1101
1584
|
*/
|
|
1102
1585
|
rebase (other, priority) {
|
|
1103
|
-
|
|
1586
|
+
modDeltaCheck(this)
|
|
1104
1587
|
/**
|
|
1105
1588
|
* Rebase attributes
|
|
1106
1589
|
*
|
|
@@ -1111,7 +1594,7 @@ export class DeltaBuilder extends Delta {
|
|
|
1111
1594
|
* - delete vs delete ⇒ current delete op is removed because item has already been deleted
|
|
1112
1595
|
* - modify vs modify ⇒ rebase using priority
|
|
1113
1596
|
*/
|
|
1114
|
-
|
|
1597
|
+
for (const op of this.attrs) {
|
|
1115
1598
|
if ($insertOp.check(op)) {
|
|
1116
1599
|
if ($insertOp.check(other.attrs[op.key]) && !priority) {
|
|
1117
1600
|
delete this.attrs[op.key]
|
|
@@ -1126,77 +1609,182 @@ export class DeltaBuilder extends Delta {
|
|
|
1126
1609
|
if (otherOp == null) {
|
|
1127
1610
|
// nop
|
|
1128
1611
|
} else if ($modifyOp.check(otherOp)) {
|
|
1129
|
-
op.
|
|
1612
|
+
op._modValue.rebase(otherOp.value, priority)
|
|
1130
1613
|
} else {
|
|
1131
1614
|
delete this.attrs[otherOp.key]
|
|
1132
1615
|
}
|
|
1133
1616
|
}
|
|
1134
|
-
}
|
|
1617
|
+
}
|
|
1618
|
+
/**
|
|
1619
|
+
* Rebase children.
|
|
1620
|
+
*
|
|
1621
|
+
* Precedence: insert with higher priority comes first. Op with less priority is transformed to
|
|
1622
|
+
* be inserted later.
|
|
1623
|
+
*
|
|
1624
|
+
* @todo always check if inser OR text
|
|
1625
|
+
*/
|
|
1626
|
+
/**
|
|
1627
|
+
* @type {ChildrenOpAny?}
|
|
1628
|
+
*/
|
|
1629
|
+
let currChild = this.children.start
|
|
1630
|
+
let currOffset = 0
|
|
1631
|
+
/**
|
|
1632
|
+
* @type {ChildrenOpAny?}
|
|
1633
|
+
*/
|
|
1634
|
+
let otherChild = other.children.start
|
|
1635
|
+
let otherOffset = 0
|
|
1636
|
+
while (currChild != null && otherChild != null) {
|
|
1637
|
+
if ($insertOp.check(currChild) || $textOp.check(currChild)) {
|
|
1638
|
+
/**
|
|
1639
|
+
* Transforming *insert*. If other is..
|
|
1640
|
+
* - insert: transform based on priority
|
|
1641
|
+
* - retain/delete/modify: transform next op against other
|
|
1642
|
+
*/
|
|
1643
|
+
if ($insertOp.check(otherChild) || $modifyOp.check(otherChild) || $textOp.check(otherChild)) {
|
|
1644
|
+
if (!priority) {
|
|
1645
|
+
list.insertBetween(this.children, currChild.prev, currChild, new RetainOp(otherChild.length, null, null))
|
|
1646
|
+
this.childCnt += otherChild.length
|
|
1647
|
+
// curr is transformed against other, transform curr against next
|
|
1648
|
+
otherOffset = otherChild.length
|
|
1649
|
+
} else {
|
|
1650
|
+
// curr stays as is, transform next op
|
|
1651
|
+
currOffset = currChild.length
|
|
1652
|
+
}
|
|
1653
|
+
} else { // otherChild = delete | retain | modify - curr stays as is, transform next op
|
|
1654
|
+
currOffset = currChild.length
|
|
1655
|
+
}
|
|
1656
|
+
} else if ($modifyOp.check(currChild)) {
|
|
1657
|
+
/**
|
|
1658
|
+
* Transforming *modify*. If other is..
|
|
1659
|
+
* - insert: adjust position
|
|
1660
|
+
* - modify: rebase curr modify on other modify
|
|
1661
|
+
* - delete: remove modify
|
|
1662
|
+
* - retain: adjust offset
|
|
1663
|
+
*/
|
|
1664
|
+
if ($insertOp.check(otherChild) || $textOp.check(otherChild)) {
|
|
1665
|
+
// @todo: with all list changes (retain insertions, removal), try to merge the surrounding
|
|
1666
|
+
// ops later
|
|
1667
|
+
list.insertBetween(this.children, currChild.prev, currChild, new RetainOp(otherChild.length, null, null))
|
|
1668
|
+
this.childCnt += otherChild.length
|
|
1669
|
+
// curr is transformed against other, transform curr against next
|
|
1670
|
+
otherOffset = otherChild.length
|
|
1671
|
+
} else {
|
|
1672
|
+
if ($modifyOp.check(otherChild)) {
|
|
1673
|
+
/** @type {any} */ (currChild.value).rebase(otherChild, priority)
|
|
1674
|
+
} else if ($deleteOp.check(otherChild)) {
|
|
1675
|
+
list.remove(this.children, currChild)
|
|
1676
|
+
this.childCnt -= 1
|
|
1677
|
+
}
|
|
1678
|
+
currOffset += 1
|
|
1679
|
+
otherOffset += 1
|
|
1680
|
+
}
|
|
1681
|
+
} else { // DeleteOp | RetainOp
|
|
1682
|
+
const maxCommonLen = math.min(currChild.length - currOffset, otherChild.length - otherOffset)
|
|
1683
|
+
/**
|
|
1684
|
+
* Transforming *retain* OR *delete*. If other is..
|
|
1685
|
+
* - retain / modify: adjust offsets
|
|
1686
|
+
* - delete: shorten curr op
|
|
1687
|
+
* - insert: split curr op and insert retain
|
|
1688
|
+
*/
|
|
1689
|
+
if ($retainOp.check(otherChild) || $modifyOp.check(otherChild)) {
|
|
1690
|
+
currOffset += maxCommonLen
|
|
1691
|
+
otherOffset += maxCommonLen
|
|
1692
|
+
} else if ($deleteOp.check(otherChild)) {
|
|
1693
|
+
if ($retainOp.check(currChild)) {
|
|
1694
|
+
// @ts-ignore
|
|
1695
|
+
currChild.retain -= maxCommonLen
|
|
1696
|
+
} else if ($deleteOp.check(currChild)) {
|
|
1697
|
+
currChild.delete -= maxCommonLen
|
|
1698
|
+
}
|
|
1699
|
+
this.childCnt -= maxCommonLen
|
|
1700
|
+
} else { // insert/text.check(currOp)
|
|
1701
|
+
if (currOffset > 0) {
|
|
1702
|
+
const leftPart = currChild.clone(currOffset)
|
|
1703
|
+
list.insertBetween(this.children, currChild.prev, currChild, leftPart)
|
|
1704
|
+
currChild._splice(currOffset, currChild.length - currOffset)
|
|
1705
|
+
currOffset = 0
|
|
1706
|
+
}
|
|
1707
|
+
list.insertBetween(this.children, currChild.prev, currChild, new RetainOp(otherChild.length, null, null))
|
|
1708
|
+
this.childCnt += otherChild.length
|
|
1709
|
+
otherOffset = otherChild.length
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
if (currOffset >= currChild.length) {
|
|
1713
|
+
currChild = currChild.next
|
|
1714
|
+
currOffset = 0
|
|
1715
|
+
}
|
|
1716
|
+
if (otherOffset >= otherChild.length) {
|
|
1717
|
+
otherChild = otherChild.next
|
|
1718
|
+
otherOffset = 0
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1135
1721
|
return this
|
|
1136
1722
|
}
|
|
1137
1723
|
|
|
1138
1724
|
/**
|
|
1139
|
-
*
|
|
1725
|
+
* Same as doing `delta.rebase(other.inverse())`, without creating a temporary delta.
|
|
1726
|
+
*
|
|
1727
|
+
* @param {DeltaAny} other
|
|
1728
|
+
* @param {boolean} priority
|
|
1140
1729
|
*/
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
}
|
|
1730
|
+
rebaseOnInverse (other, priority) {
|
|
1731
|
+
modDeltaCheck(this)
|
|
1732
|
+
// @todo
|
|
1733
|
+
console.info('method rebaseOnInverse unimplemented')
|
|
1146
1734
|
return this
|
|
1147
1735
|
}
|
|
1148
1736
|
}
|
|
1149
1737
|
|
|
1150
1738
|
/**
|
|
1151
1739
|
* @template {string} NodeName
|
|
1152
|
-
* @template {{ [key: string|number
|
|
1153
|
-
* @template {
|
|
1740
|
+
* @template {{ [key: string|number]: any }} [Attrs={}]
|
|
1741
|
+
* @template {encoding.AnyEncodable|DeltaAny|never} [Children=never]
|
|
1154
1742
|
* @template {string|never} [Text=never]
|
|
1155
1743
|
* @typedef {Delta<NodeName,Attrs,Children|Delta<NodeName,Attrs,Children,Text>|RecursiveDelta<NodeName,Attrs,Children,Text>,Text>} RecursiveDelta
|
|
1156
1744
|
*/
|
|
1157
1745
|
|
|
1158
1746
|
/**
|
|
1159
|
-
* @template {string} [
|
|
1160
|
-
* @template {{ [key: string|number
|
|
1161
|
-
* @template {any} [
|
|
1747
|
+
* @template {s.Schema<string>|string|Array<string>} [NodeNameSchema=s.Schema<any>]
|
|
1748
|
+
* @template {s.Schema<{ [key: string|number]: any }>|{ [key:string|number]:any }} [AttrsSchema=s.Schema<{}>]
|
|
1749
|
+
* @template {any} [ChildrenSchema=s.Schema<never>]
|
|
1162
1750
|
* @template {boolean} [HasText=false]
|
|
1163
1751
|
* @template {boolean} [Recursive=false]
|
|
1164
1752
|
* @param {object} opts
|
|
1165
|
-
* @param {
|
|
1166
|
-
* @param {
|
|
1167
|
-
* @param {
|
|
1168
|
-
* @param {HasText} [opts.
|
|
1753
|
+
* @param {NodeNameSchema?} [opts.name]
|
|
1754
|
+
* @param {AttrsSchema?} [opts.attrs]
|
|
1755
|
+
* @param {ChildrenSchema?} [opts.children]
|
|
1756
|
+
* @param {HasText} [opts.text]
|
|
1169
1757
|
* @param {Recursive} [opts.recursive]
|
|
1170
|
-
* @return {s.Schema<Delta<
|
|
1758
|
+
* @return {[s.Unwrap<s.ReadSchema<NodeNameSchema>>,s.Unwrap<s.ReadSchema<AttrsSchema>>,s.Unwrap<s.ReadSchema<ChildrenSchema>>] extends [infer NodeName, infer Attrs, infer Children] ? s.Schema<Delta<
|
|
1171
1759
|
* NodeName,
|
|
1172
1760
|
* Attrs,
|
|
1173
1761
|
* Children|(Recursive extends true ? RecursiveDelta<NodeName,Attrs,Children,HasText extends true ? string : never> : never),
|
|
1174
1762
|
* HasText extends true ? string : never
|
|
1175
|
-
* >>}
|
|
1763
|
+
* >> : never}
|
|
1176
1764
|
*/
|
|
1177
|
-
export const $delta = ({ name, attrs, children,
|
|
1178
|
-
name = name == null ? s.$any : name
|
|
1765
|
+
export const $delta = ({ name, attrs, children, text, recursive }) => {
|
|
1179
1766
|
/**
|
|
1180
1767
|
* @type {s.Schema<Array<any>>}
|
|
1181
1768
|
*/
|
|
1182
|
-
let $arrContent = children == null ? s.$never : s.$array(children)
|
|
1183
|
-
const $
|
|
1769
|
+
let $arrContent = children == null ? s.$never : s.$array(s.$(children))
|
|
1770
|
+
const $name = name == null ? s.$any : s.$(name)
|
|
1771
|
+
const $attrsPartial = attrs == null ? s.$object({}) : (s.$$record.check(attrs) ? attrs : /** @type {any} */ (s.$(attrs)).partial)
|
|
1184
1772
|
const $d = s.$instanceOf(Delta, /** @param {Delta<any,any,any,any,any>} d */ d => {
|
|
1185
1773
|
if (
|
|
1186
|
-
|
|
1774
|
+
!$name.check(d.name) ||
|
|
1187
1775
|
object.some(d.attrs,
|
|
1188
1776
|
(op, k) => $insertOp.check(op) && !$attrsPartial.check({ [k]: op.value })
|
|
1189
1777
|
)
|
|
1190
1778
|
) return false
|
|
1191
1779
|
for (const op of d.children) {
|
|
1192
|
-
if ((!
|
|
1780
|
+
if ((!text && $textOp.check(op)) || ($insertOp.check(op) && !$arrContent.check(op.insert))) {
|
|
1193
1781
|
return false
|
|
1194
1782
|
}
|
|
1195
1783
|
}
|
|
1196
1784
|
return true
|
|
1197
1785
|
})
|
|
1198
1786
|
if (recursive) {
|
|
1199
|
-
$arrContent = children == null ? s.$array($d) : s.$array(children, $d)
|
|
1787
|
+
$arrContent = children == null ? s.$array($d) : s.$array(s.$(children), $d)
|
|
1200
1788
|
}
|
|
1201
1789
|
return /** @type {any} */ ($d)
|
|
1202
1790
|
}
|
|
@@ -1216,16 +1804,16 @@ export const $deltaAny = /** @type {any} */ (s.$instanceOf(Delta))
|
|
|
1216
1804
|
export const mergeAttrs = (a, b) => object.isEmpty(a) ? b : (object.isEmpty(b) ? a : object.assign({}, a, b))
|
|
1217
1805
|
|
|
1218
1806
|
/**
|
|
1219
|
-
* @template {
|
|
1807
|
+
* @template {DeltaAny|null} D
|
|
1220
1808
|
* @param {D} a
|
|
1221
1809
|
* @param {D} b
|
|
1222
1810
|
* @return {D}
|
|
1223
1811
|
*/
|
|
1224
1812
|
export const mergeDeltas = (a, b) => {
|
|
1225
1813
|
if (a != null && b != null) {
|
|
1226
|
-
const c =
|
|
1814
|
+
const c = clone(a)
|
|
1227
1815
|
c.apply(b)
|
|
1228
|
-
return c
|
|
1816
|
+
return /** @type {any} */ (c)
|
|
1229
1817
|
}
|
|
1230
1818
|
return a == null ? b : (a || null)
|
|
1231
1819
|
}
|
|
@@ -1256,8 +1844,8 @@ export const mergeDeltas = (a, b) => {
|
|
|
1256
1844
|
*/
|
|
1257
1845
|
/**
|
|
1258
1846
|
* @template {string|null} NodeName
|
|
1259
|
-
* @template {{[k:string|number
|
|
1260
|
-
* @template {Array<any>|string} Children
|
|
1847
|
+
* @template {{[k:string|number]:any}|null} Attrs
|
|
1848
|
+
* @template {Array<any>|string} [Children=never]
|
|
1261
1849
|
* @overload
|
|
1262
1850
|
* @param {NodeName} nodeName
|
|
1263
1851
|
* @param {Attrs} attrs
|
|
@@ -1272,7 +1860,7 @@ export const mergeDeltas = (a, b) => {
|
|
|
1272
1860
|
*/
|
|
1273
1861
|
/**
|
|
1274
1862
|
* @param {string|s.Schema<DeltaAny>} [nodeNameOrSchema]
|
|
1275
|
-
* @param {{[K:string|number
|
|
1863
|
+
* @param {{[K:string|number]:any}|s.Schema<DeltaAny>} [attrsOrSchema]
|
|
1276
1864
|
* @param {(Array<any>|string)} [children]
|
|
1277
1865
|
* @return {DeltaBuilder<any,any,any,any,any>}
|
|
1278
1866
|
*/
|
|
@@ -1290,12 +1878,12 @@ export const create = (nodeNameOrSchema, attrsOrSchema, children) => {
|
|
|
1290
1878
|
// DELTA TEXT
|
|
1291
1879
|
|
|
1292
1880
|
/**
|
|
1293
|
-
* @template [Embeds=never]
|
|
1881
|
+
* @template {encoding.AnyEncodable|DeltaAny} [Embeds=never]
|
|
1294
1882
|
* @typedef {Delta<any,{},Embeds,string>} TextDelta
|
|
1295
1883
|
*/
|
|
1296
1884
|
|
|
1297
1885
|
/**
|
|
1298
|
-
* @template [Embeds=never]
|
|
1886
|
+
* @template {encoding.AnyEncodable|DeltaAny} [Embeds=never]
|
|
1299
1887
|
* @typedef {DeltaBuilder<any,{},Embeds,string>} TextDeltaBuilder
|
|
1300
1888
|
*/
|
|
1301
1889
|
|
|
@@ -1304,7 +1892,7 @@ export const create = (nodeNameOrSchema, attrsOrSchema, children) => {
|
|
|
1304
1892
|
* @param {$Embeds} $embeds
|
|
1305
1893
|
* @return {s.Schema<TextDelta<_AnyToNull<$Embeds> extends null ? never : ($Embeds extends Array<s.Schema<infer $C>> ? $C : never)>>}
|
|
1306
1894
|
*/
|
|
1307
|
-
export const $text = (...$embeds) => /** @type {any} */ ($delta({ children: s.$union(...$embeds),
|
|
1895
|
+
export const $text = (...$embeds) => /** @type {any} */ ($delta({ children: s.$union(...$embeds), text: true }))
|
|
1308
1896
|
export const $textOnly = $text()
|
|
1309
1897
|
|
|
1310
1898
|
/**
|
|
@@ -1315,21 +1903,21 @@ export const $textOnly = $text()
|
|
|
1315
1903
|
export const text = $schema => /** @type {any} */ (create($schema || $textOnly))
|
|
1316
1904
|
|
|
1317
1905
|
/**
|
|
1318
|
-
* @template {
|
|
1906
|
+
* @template {encoding.AnyEncodable|DeltaAny} Children
|
|
1319
1907
|
* @typedef {Delta<any,{},Children,never>} ArrayDelta
|
|
1320
1908
|
*/
|
|
1321
1909
|
|
|
1322
1910
|
/**
|
|
1323
|
-
* @template {
|
|
1911
|
+
* @template {encoding.AnyEncodable|DeltaAny} Children
|
|
1324
1912
|
* @typedef {DeltaBuilder<any,{},Children,never>} ArrayDeltaBuilder
|
|
1325
1913
|
*/
|
|
1326
1914
|
|
|
1327
1915
|
/**
|
|
1328
|
-
* @template {s.Schema<any>} $Children
|
|
1916
|
+
* @template {any|s.Schema<any>} $Children
|
|
1329
1917
|
* @param {$Children} [$children]
|
|
1330
|
-
* @return {s.Schema<ArrayDelta<$Children
|
|
1918
|
+
* @return {s.Schema<ArrayDelta<s.Unwrap<s.ReadSchema<$Children>>>>}
|
|
1331
1919
|
*/
|
|
1332
|
-
export const $array = $children => $delta({ children: $children })
|
|
1920
|
+
export const $array = $children => /** @type {any} */ ($delta({ children: $children }))
|
|
1333
1921
|
|
|
1334
1922
|
/**
|
|
1335
1923
|
* @template {s.Schema<ArrayDelta<any>>} [$Schema=never]
|
|
@@ -1339,17 +1927,17 @@ export const $array = $children => $delta({ children: $children })
|
|
|
1339
1927
|
export const array = $schema => /** @type {any} */ ($schema ? create($schema) : create())
|
|
1340
1928
|
|
|
1341
1929
|
/**
|
|
1342
|
-
* @template {{ [K: string|number
|
|
1930
|
+
* @template {{ [K: string|number]: any }} Attrs
|
|
1343
1931
|
* @typedef {Delta<any,Attrs,never,never>} MapDelta
|
|
1344
1932
|
*/
|
|
1345
1933
|
|
|
1346
1934
|
/**
|
|
1347
|
-
* @template {{ [K: string|number
|
|
1935
|
+
* @template {{ [K: string|number]: any }} Attrs
|
|
1348
1936
|
* @typedef {DeltaBuilder<any,Attrs,never,never>} MapDeltaBuilder
|
|
1349
1937
|
*/
|
|
1350
1938
|
|
|
1351
1939
|
/**
|
|
1352
|
-
* @template {{ [K: string|number
|
|
1940
|
+
* @template {{ [K: string|number]: any }} $Attrs
|
|
1353
1941
|
* @param {s.Schema<$Attrs>} $attrs
|
|
1354
1942
|
* @return {s.Schema<MapDelta<$Attrs>>}
|
|
1355
1943
|
*/
|
|
@@ -1361,3 +1949,97 @@ export const $map = $attrs => /** @type {any} */ ($delta({ attrs: $attrs }))
|
|
|
1361
1949
|
* @return {$Schema extends s.Schema<MapDelta<infer Attrs>> ? DeltaBuilder<any,Attrs,never,never,$Schema> : MapDeltaBuilder<{}>}
|
|
1362
1950
|
*/
|
|
1363
1951
|
export const map = $schema => /** @type {any} */ (create(/** @type {any} */ ($schema)))
|
|
1952
|
+
|
|
1953
|
+
/**
|
|
1954
|
+
* @template {DeltaAny} D
|
|
1955
|
+
* @param {D} d1
|
|
1956
|
+
* @param {NoInfer<D>} d2
|
|
1957
|
+
* @return {D}
|
|
1958
|
+
*/
|
|
1959
|
+
export const diff = (d1, d2) => {
|
|
1960
|
+
/**
|
|
1961
|
+
* @type {DeltaBuilderAny}
|
|
1962
|
+
*/
|
|
1963
|
+
const d = create()
|
|
1964
|
+
if (d1.fingerprint !== d2.fingerprint) {
|
|
1965
|
+
let left1 = d1.children.start
|
|
1966
|
+
let left2 = d2.children.start
|
|
1967
|
+
let right1 = d1.children.end
|
|
1968
|
+
let right2 = d2.children.end
|
|
1969
|
+
let commonPrefixOffset = 0
|
|
1970
|
+
// perform a patience sort
|
|
1971
|
+
// 1) remove common prefix and suffix
|
|
1972
|
+
while (left1 != null && left1.fingerprint === left2?.fingerprint) {
|
|
1973
|
+
if (!$deleteOp.check(left1)) {
|
|
1974
|
+
commonPrefixOffset += left1.length
|
|
1975
|
+
}
|
|
1976
|
+
left1 = left1.next
|
|
1977
|
+
left2 = left2.next
|
|
1978
|
+
}
|
|
1979
|
+
while (right1 !== null && right1 !== left1 && right1.fingerprint === right2?.fingerprint) {
|
|
1980
|
+
right1 = right1.prev
|
|
1981
|
+
right2 = right2.prev
|
|
1982
|
+
}
|
|
1983
|
+
/**
|
|
1984
|
+
* @type {Array<ChildrenOpAny>}
|
|
1985
|
+
*/
|
|
1986
|
+
const ops1 = []
|
|
1987
|
+
/**
|
|
1988
|
+
* @type {Array<ChildrenOpAny>}
|
|
1989
|
+
*/
|
|
1990
|
+
const ops2 = []
|
|
1991
|
+
while (left1 !== null && left1 !== right1?.next) {
|
|
1992
|
+
ops1.push(left1)
|
|
1993
|
+
left1 = left1.next
|
|
1994
|
+
}
|
|
1995
|
+
while (left2 !== null && left2 !== right2?.next) {
|
|
1996
|
+
ops2.push(left2)
|
|
1997
|
+
left2 = left2.next
|
|
1998
|
+
}
|
|
1999
|
+
const fprints1 = ops1.map(op => op.fingerprint)
|
|
2000
|
+
const fprints2 = ops2.map(op => op.fingerprint)
|
|
2001
|
+
const changeset = patience.diff(fprints1, fprints2)
|
|
2002
|
+
d.retain(commonPrefixOffset)
|
|
2003
|
+
for (let i = 0, lastIndex1 = 0, currIndexOffset2 = 0; i < changeset.length; i++) {
|
|
2004
|
+
const change = changeset[i]
|
|
2005
|
+
d.retain(change.index - lastIndex1)
|
|
2006
|
+
// insert minimal diff at curred position in d
|
|
2007
|
+
/**
|
|
2008
|
+
* @param {DeltaBuilderAny} d
|
|
2009
|
+
* @param {ChildrenOpAny[]} opsIs
|
|
2010
|
+
* @param {ChildrenOpAny[]} opsShould
|
|
2011
|
+
*
|
|
2012
|
+
*/
|
|
2013
|
+
const diffAndApply = (d, opsIs, opsShould) => {
|
|
2014
|
+
// naive implementation
|
|
2015
|
+
d.delete(opsIs.reduce((currLen, op) => currLen + op.length, 0))
|
|
2016
|
+
opsShould.forEach(newIns => {
|
|
2017
|
+
if ($insertOp.check(newIns) || $textOp.check(newIns)) {
|
|
2018
|
+
d.insert(newIns.insert)
|
|
2019
|
+
} else {
|
|
2020
|
+
error.unexpectedCase()
|
|
2021
|
+
}
|
|
2022
|
+
})
|
|
2023
|
+
}
|
|
2024
|
+
diffAndApply(d, ops1.slice(change.index, change.index + change.remove.length), ops2.slice(change.index + currIndexOffset2, change.insert.length))
|
|
2025
|
+
lastIndex1 = change.index + change.remove.length
|
|
2026
|
+
currIndexOffset2 += change.insert.length - change.remove.length
|
|
2027
|
+
}
|
|
2028
|
+
for (const attr2 of d2.attrs) {
|
|
2029
|
+
const attr1 = d1.attrs[attr2.key]
|
|
2030
|
+
if (attr1 == null || (attr1.fingerprint !== attr2.fingerprint)) {
|
|
2031
|
+
if ($insertOp.check(attr2)) {
|
|
2032
|
+
d.set(attr2.key, attr2.value)
|
|
2033
|
+
} else {
|
|
2034
|
+
error.unexpectedCase()
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
for (const attr1 of d1.attrs) {
|
|
2039
|
+
if (d2.attrs[attr1.key] == null) {
|
|
2040
|
+
d.unset(attr1.key)
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
return /** @type {D} */ (d.done())
|
|
2045
|
+
}
|