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