@y/y 14.0.0-rc.18 → 14.0.0-rc.19
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/README.md +1 -0
- package/dist/src/index.d.ts +2 -2
- package/dist/src/structs/Item.d.ts +1 -1
- package/dist/src/utils/RelativePosition.d.ts +2 -2
- package/dist/src/utils/RelativePosition.d.ts.map +1 -1
- package/dist/src/utils/{AttributionManager.d.ts → Renderer.d.ts} +21 -21
- package/dist/src/utils/Renderer.d.ts.map +1 -0
- package/dist/src/utils/Transaction.d.ts +5 -5
- package/dist/src/utils/YEvent.d.ts +4 -3
- package/dist/src/utils/YEvent.d.ts.map +1 -1
- package/dist/src/utils/delta-helpers.d.ts +2 -2
- package/dist/src/utils/ids.d.ts +1 -0
- package/dist/src/utils/ids.d.ts.map +1 -1
- package/dist/src/utils/{attribution-manager-helpers.d.ts → renderer-helpers.d.ts} +11 -11
- package/dist/src/utils/renderer-helpers.d.ts.map +1 -0
- package/dist/src/ytype.d.ts +19 -12
- package/dist/src/ytype.d.ts.map +1 -1
- package/global.d.ts +3 -3
- package/package.json +5 -5
- package/src/index.js +2 -2
- package/src/utils/RelativePosition.js +8 -8
- package/src/utils/{AttributionManager.js → Renderer.js} +24 -24
- package/src/utils/Snapshot.js +3 -3
- package/src/utils/Transaction.js +5 -5
- package/src/utils/YEvent.js +8 -8
- package/src/utils/delta-helpers.js +4 -4
- package/src/utils/ids.js +22 -1
- package/src/utils/{attribution-manager-helpers.js → renderer-helpers.js} +8 -8
- package/src/ytype.js +38 -36
- package/dist/src/utils/AttributionManager.d.ts.map +0 -1
- package/dist/src/utils/attribution-manager-helpers.d.ts.map +0 -1
|
@@ -4,7 +4,7 @@ import * as error from 'lib0/error'
|
|
|
4
4
|
|
|
5
5
|
import { Item, followRedone, ContentType } from '../structs/Item.js'
|
|
6
6
|
import { writeID, readID, compareIDs, findRootTypeKey, createID } from './ID.js'
|
|
7
|
-
import {
|
|
7
|
+
import { baseRenderer } from './renderer-helpers.js'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* A relative position is based on the Yjs model and is not affected by document changes.
|
|
@@ -146,12 +146,12 @@ export const createRelativePosition = (type, item, assoc) => {
|
|
|
146
146
|
* @param {YType} type The base type (e.g. YText or YArray).
|
|
147
147
|
* @param {number} index The absolute position.
|
|
148
148
|
* @param {number} [assoc]
|
|
149
|
-
* @param {import('../utils/
|
|
149
|
+
* @param {import('../utils/Renderer.js').AbstractRenderer} renderer
|
|
150
150
|
* @return {RelativePosition}
|
|
151
151
|
*
|
|
152
152
|
* @function
|
|
153
153
|
*/
|
|
154
|
-
export const createRelativePositionFromTypeIndex = (type, index, assoc = 0,
|
|
154
|
+
export const createRelativePositionFromTypeIndex = (type, index, assoc = 0, renderer = baseRenderer) => {
|
|
155
155
|
let t = type._start
|
|
156
156
|
if (assoc < 0) {
|
|
157
157
|
// associated to the left character or the beginning of a type, increment index if possible.
|
|
@@ -161,7 +161,7 @@ export const createRelativePositionFromTypeIndex = (type, index, assoc = 0, attr
|
|
|
161
161
|
index--
|
|
162
162
|
}
|
|
163
163
|
while (t !== null) {
|
|
164
|
-
const len =
|
|
164
|
+
const len = renderer.contentLength(t)
|
|
165
165
|
if (len > index) {
|
|
166
166
|
// case 1: found position somewhere in the linked list
|
|
167
167
|
return createRelativePosition(type, createID(t.id.client, t.id.clock + index), assoc)
|
|
@@ -272,12 +272,12 @@ const getItemWithOffset = (store, id) => {
|
|
|
272
272
|
* @param {RelativePosition} rpos
|
|
273
273
|
* @param {Doc} doc
|
|
274
274
|
* @param {boolean} followUndoneDeletions - whether to follow undone deletions - see https://github.com/yjs/yjs/issues/638
|
|
275
|
-
* @param {import('../utils/
|
|
275
|
+
* @param {import('../utils/Renderer.js').AbstractRenderer} renderer
|
|
276
276
|
* @return {AbsolutePosition|null}
|
|
277
277
|
*
|
|
278
278
|
* @function
|
|
279
279
|
*/
|
|
280
|
-
export const createAbsolutePositionFromRelativePosition = (rpos, doc, followUndoneDeletions = true,
|
|
280
|
+
export const createAbsolutePositionFromRelativePosition = (rpos, doc, followUndoneDeletions = true, renderer = baseRenderer) => {
|
|
281
281
|
const store = doc.store
|
|
282
282
|
const rightID = rpos.item
|
|
283
283
|
const typeID = rpos.type
|
|
@@ -296,10 +296,10 @@ export const createAbsolutePositionFromRelativePosition = (rpos, doc, followUndo
|
|
|
296
296
|
}
|
|
297
297
|
type = /** @type {YType<any>} */ (right.parent)
|
|
298
298
|
if (type._item === null || !type._item.deleted) {
|
|
299
|
-
index =
|
|
299
|
+
index = renderer.contentLength(right) === 0 ? 0 : (res.diff + (assoc >= 0 ? 0 : 1)) // adjust position based on left association if necessary
|
|
300
300
|
let n = right.left
|
|
301
301
|
while (n !== null) {
|
|
302
|
-
index +=
|
|
302
|
+
index += renderer.contentLength(n)
|
|
303
303
|
n = n.left
|
|
304
304
|
}
|
|
305
305
|
}
|
|
@@ -11,16 +11,16 @@ import { UpdateEncoderV1 } from './UpdateEncoder.js'
|
|
|
11
11
|
import { transact } from './Transaction.js'
|
|
12
12
|
import { UndoManager, StackItem } from './UndoManager.js'
|
|
13
13
|
|
|
14
|
-
import { $
|
|
14
|
+
import { $renderer, AttributedContent } from './renderer-helpers.js'
|
|
15
15
|
|
|
16
|
-
export {
|
|
16
|
+
export { baseRenderer, BaseRenderer, AbstractRenderer, $renderer } from './renderer-helpers.js'
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* @implements
|
|
19
|
+
* @implements AbstractRenderer
|
|
20
20
|
*
|
|
21
21
|
* @extends {ObservableV2<{change:(idset:IdSet,origin:any,local:boolean)=>void}>}
|
|
22
22
|
*/
|
|
23
|
-
export class
|
|
23
|
+
export class TwosetRenderer extends ObservableV2 {
|
|
24
24
|
/**
|
|
25
25
|
* @param {IdMap<any>} inserts
|
|
26
26
|
* @param {IdMap<any>} deletes
|
|
@@ -31,7 +31,7 @@ export class TwosetAttributionManager extends ObservableV2 {
|
|
|
31
31
|
this.deletes = deletes
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
get $type () { return $
|
|
34
|
+
get $type () { return $renderer }
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* @param {Array<AttributedContent<any>>} contents - where to write the result
|
|
@@ -93,15 +93,15 @@ const getItemContent = (store, client, clock, len) => {
|
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
95
|
* @param {Transaction?} tr - only specify this if you want to fill the content of deleted content
|
|
96
|
-
* @param {
|
|
96
|
+
* @param {DiffRenderer} renderer
|
|
97
97
|
* @param {ID} start
|
|
98
98
|
* @param {ID} end
|
|
99
99
|
* @param {boolean} collectAll - collect as many items as possible. Accept adding redundant changes.
|
|
100
100
|
*/
|
|
101
|
-
const collectSuggestedChanges = (tr,
|
|
101
|
+
const collectSuggestedChanges = (tr, renderer, start, end, collectAll) => {
|
|
102
102
|
const inserts = createIdSet()
|
|
103
103
|
const deletes = createIdSet()
|
|
104
|
-
const store =
|
|
104
|
+
const store = renderer._nextDoc.store
|
|
105
105
|
/**
|
|
106
106
|
* make sure to collect suggestions until all formats are closed
|
|
107
107
|
* @type {Set<string>}
|
|
@@ -121,7 +121,7 @@ const collectSuggestedChanges = (tr, am, start, end, collectAll) => {
|
|
|
121
121
|
break
|
|
122
122
|
}
|
|
123
123
|
if (!item.deleted) {
|
|
124
|
-
const slice =
|
|
124
|
+
const slice = renderer.inserts.slice(item.id.client, item.id.clock, item.length)
|
|
125
125
|
if (slice.some(s => s.attrs === null)) {
|
|
126
126
|
for (let i = slice.length - 1; i >= 0; i--) {
|
|
127
127
|
const s = slice[i]
|
|
@@ -137,7 +137,7 @@ const collectSuggestedChanges = (tr, am, start, end, collectAll) => {
|
|
|
137
137
|
// eslint-disable-next-line
|
|
138
138
|
itemLoop: while (item != null) {
|
|
139
139
|
const itemClient = item.id.client
|
|
140
|
-
const slice = (item.deleted ?
|
|
140
|
+
const slice = (item.deleted ? renderer.deletes : renderer.inserts).slice(itemClient, item.id.clock, item.length)
|
|
141
141
|
foundEndItem ||= item === endItem
|
|
142
142
|
if (item.deleted) {
|
|
143
143
|
// item probably gc'd content. Need to split item and fill with content again
|
|
@@ -154,7 +154,7 @@ const collectSuggestedChanges = (tr, am, start, end, collectAll) => {
|
|
|
154
154
|
if (tr != null) {
|
|
155
155
|
const splicedItem = getItemCleanStart(tr, createID(itemClient, s.clock))
|
|
156
156
|
if (s.attrs != null) {
|
|
157
|
-
splicedItem.content = getItemContent(
|
|
157
|
+
splicedItem.content = getItemContent(renderer._prevDocStore, itemClient, s.clock, s.len)
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
}
|
|
@@ -197,15 +197,15 @@ export class Attributions {
|
|
|
197
197
|
const extractAttributions = (attrs, slice) => attrs == null ? createIdMapFromIdSet(slice, []) : mergeIdMaps([intersectMaps(attrs, slice), createIdMapFromIdSet(slice, [])])
|
|
198
198
|
|
|
199
199
|
/**
|
|
200
|
-
* @implements
|
|
200
|
+
* @implements AbstractRenderer
|
|
201
201
|
*
|
|
202
202
|
* @extends {ObservableV2<{change:(idset:IdSet,origin:any,local:boolean)=>void}>}
|
|
203
203
|
*/
|
|
204
|
-
export class
|
|
204
|
+
export class DiffRenderer extends ObservableV2 {
|
|
205
205
|
/**
|
|
206
206
|
* @param {Doc} prevDoc
|
|
207
207
|
* @param {Doc} nextDoc
|
|
208
|
-
* @param {Object} [options] - options for the
|
|
208
|
+
* @param {Object} [options] - options for the renderer
|
|
209
209
|
* @param {Attributions?} [options.attrs] - the attributes to apply to the diff
|
|
210
210
|
*/
|
|
211
211
|
constructor (prevDoc, nextDoc, { attrs = null } = {}) {
|
|
@@ -264,7 +264,7 @@ export class DiffAttributionManager extends ObservableV2 {
|
|
|
264
264
|
})
|
|
265
265
|
this._afterTrListener = nextDoc.on('afterTransaction', (tr) => {
|
|
266
266
|
// apply deletes on attributed deletes (content that is already deleted, but is rendered by
|
|
267
|
-
// the
|
|
267
|
+
// the renderer)
|
|
268
268
|
if (!this.suggestionMode && tr.local && (this.suggestionOrigins == null || this.suggestionOrigins.some(o => o === tr.origin))) {
|
|
269
269
|
const attributedDeletes = tr.meta.get('attributedDeletes')
|
|
270
270
|
if (attributedDeletes != null) {
|
|
@@ -290,7 +290,7 @@ export class DiffAttributionManager extends ObservableV2 {
|
|
|
290
290
|
prevDoc.on('destroy', this._destroyHandler)
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
get $type () { return $
|
|
293
|
+
get $type () { return $renderer }
|
|
294
294
|
|
|
295
295
|
destroy () {
|
|
296
296
|
super.destroy()
|
|
@@ -411,24 +411,24 @@ export class DiffAttributionManager extends ObservableV2 {
|
|
|
411
411
|
*
|
|
412
412
|
* @param {Doc} prevDoc
|
|
413
413
|
* @param {Doc} nextDoc
|
|
414
|
-
* @param {Object} [options] - options for the
|
|
414
|
+
* @param {Object} [options] - options for the renderer
|
|
415
415
|
* @param {ContentMap?} [options.attrs] - the attributes to apply to the diff
|
|
416
416
|
*/
|
|
417
|
-
export const
|
|
417
|
+
export const createDiffRenderer = (prevDoc, nextDoc, options) => new DiffRenderer(prevDoc, nextDoc, options)
|
|
418
418
|
|
|
419
419
|
/**
|
|
420
|
-
* Intended for projects that used the v13 snapshot feature. With this
|
|
420
|
+
* Intended for projects that used the v13 snapshot feature. With this renderer you can
|
|
421
421
|
* read content similar to the previous snapshot api. Requires that `ydoc.gc` is turned off.
|
|
422
422
|
*
|
|
423
|
-
* @implements
|
|
423
|
+
* @implements AbstractRenderer
|
|
424
424
|
*
|
|
425
425
|
* @extends {ObservableV2<{change:(idset:IdSet,origin:any,local:boolean)=>void}>}
|
|
426
426
|
*/
|
|
427
|
-
export class
|
|
427
|
+
export class SnapshotRenderer extends ObservableV2 {
|
|
428
428
|
/**
|
|
429
429
|
* @param {Snapshot} prevSnapshot
|
|
430
430
|
* @param {Snapshot} nextSnapshot
|
|
431
|
-
* @param {Object} [options] - options for the
|
|
431
|
+
* @param {Object} [options] - options for the renderer
|
|
432
432
|
* @param {Array<ContentAttribute>} [options.attrs] - the attributes to apply to the diff
|
|
433
433
|
*/
|
|
434
434
|
constructor (prevSnapshot, nextSnapshot) {
|
|
@@ -445,7 +445,7 @@ export class SnapshotAttributionManager extends ObservableV2 {
|
|
|
445
445
|
this.attrs = mergeIdMaps([diffIdMap(inserts, prevSnapshot.ds), deletes])
|
|
446
446
|
}
|
|
447
447
|
|
|
448
|
-
get $type () { return $
|
|
448
|
+
get $type () { return $renderer }
|
|
449
449
|
|
|
450
450
|
/**
|
|
451
451
|
* @param {Array<AttributedContent<any>>} contents - where to write the result
|
|
@@ -495,4 +495,4 @@ export class SnapshotAttributionManager extends ObservableV2 {
|
|
|
495
495
|
* @param {Snapshot} prevSnapshot
|
|
496
496
|
* @param {Snapshot} nextSnapshot
|
|
497
497
|
*/
|
|
498
|
-
export const
|
|
498
|
+
export const createSnapshotRenderer = (prevSnapshot, nextSnapshot = prevSnapshot) => new SnapshotRenderer(prevSnapshot, nextSnapshot)
|
package/src/utils/Snapshot.js
CHANGED
|
@@ -119,11 +119,11 @@ export const splitSnapshotAffectedStructs = (transaction, snapshot) => {
|
|
|
119
119
|
/**
|
|
120
120
|
* @example
|
|
121
121
|
* const ydoc = new Y.Doc({ gc: false })
|
|
122
|
-
* ydoc.
|
|
122
|
+
* ydoc.get().insert(0, 'world!')
|
|
123
123
|
* const snapshot = Y.snapshot(ydoc)
|
|
124
|
-
* ydoc.
|
|
124
|
+
* ydoc.get().insert(0, 'hello ')
|
|
125
125
|
* const restored = Y.createDocFromSnapshot(ydoc, snapshot)
|
|
126
|
-
* assert(restored.
|
|
126
|
+
* assert(restored.get().toString() === 'world!')
|
|
127
127
|
*
|
|
128
128
|
* @param {Doc} originDoc
|
|
129
129
|
* @param {Snapshot} snapshot
|
package/src/utils/Transaction.js
CHANGED
|
@@ -26,18 +26,18 @@ export const generateNewClientId = random.uint53
|
|
|
26
26
|
*
|
|
27
27
|
* @example
|
|
28
28
|
* const ydoc = new Y.Doc()
|
|
29
|
-
* const map = ydoc.
|
|
29
|
+
* const map = ydoc.get('map')
|
|
30
30
|
* // Log content when change is triggered
|
|
31
31
|
* map.observe(() => {
|
|
32
32
|
* console.log('change triggered')
|
|
33
33
|
* })
|
|
34
34
|
* // Each change on the map type triggers a log message:
|
|
35
|
-
* map.
|
|
36
|
-
* map.
|
|
35
|
+
* map.setAttr('a', 0) // => "change triggered"
|
|
36
|
+
* map.setAttr('b', 0) // => "change triggered"
|
|
37
37
|
* // When put in a transaction, it will trigger the log after the transaction:
|
|
38
38
|
* ydoc.transact(() => {
|
|
39
|
-
* map.
|
|
40
|
-
* map.
|
|
39
|
+
* map.setAttr('a', 1)
|
|
40
|
+
* map.setAttr('b', 1)
|
|
41
41
|
* }) // => "change triggered"
|
|
42
42
|
*
|
|
43
43
|
* @public
|
package/src/utils/YEvent.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as map from 'lib0/map'
|
|
|
2
2
|
import * as set from 'lib0/set'
|
|
3
3
|
|
|
4
4
|
import { diffIdSet, mergeIdSets } from './ids.js'
|
|
5
|
-
import {
|
|
5
|
+
import { baseRenderer } from './renderer-helpers.js'
|
|
6
6
|
import { createAbsolutePositionFromRelativePosition, createRelativePosition } from './RelativePosition.js'
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -85,14 +85,14 @@ export class YEvent {
|
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
87
|
* @template {boolean} [Deep=false]
|
|
88
|
-
* @param {AbstractAttributionManager} am
|
|
89
88
|
* @param {object} [opts]
|
|
89
|
+
* @param {AbstractRenderer} [opts.renderer] - renders the content (with attributions); defaults to `baseRenderer`
|
|
90
90
|
* @param {Deep} [opts.deep]
|
|
91
91
|
* @return {Deep extends true ? Delta<DConf> : Delta<import('../ytype.js').DeltaConfDeltaToYType<DConf>>} The Delta representation of this type.
|
|
92
92
|
*
|
|
93
93
|
* @public
|
|
94
94
|
*/
|
|
95
|
-
getDelta (
|
|
95
|
+
getDelta ({ renderer = baseRenderer, deep } = {}) {
|
|
96
96
|
const itemsToRender = mergeIdSets([diffIdSet(this.transaction.insertSet, this.transaction.deleteSet), diffIdSet(this.transaction.deleteSet, this.transaction.insertSet)])
|
|
97
97
|
/**
|
|
98
98
|
* @todo this should be done only one in the transaction step
|
|
@@ -120,7 +120,7 @@ export class YEvent {
|
|
|
120
120
|
}
|
|
121
121
|
modified = dchanged
|
|
122
122
|
}
|
|
123
|
-
return /** @type {any} */ (this.target.toDelta(
|
|
123
|
+
return /** @type {any} */ (this.target.toDelta({ renderer, itemsToRender, retainDeletes: true, deletedItems: this.transaction.deleteSet, deep: !!deep, modified }))
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
/**
|
|
@@ -142,7 +142,7 @@ export class YEvent {
|
|
|
142
142
|
* @public
|
|
143
143
|
*/
|
|
144
144
|
get deltaDeep () {
|
|
145
|
-
return /** @type {any} */ (this._deltaDeep ?? (this._deltaDeep = /** @type {any} */ (this.getDelta(
|
|
145
|
+
return /** @type {any} */ (this._deltaDeep ?? (this._deltaDeep = /** @type {any} */ (this.getDelta({ deep: true }))))
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
|
|
@@ -158,13 +158,13 @@ export class YEvent {
|
|
|
158
158
|
*
|
|
159
159
|
* @param {YType} parent
|
|
160
160
|
* @param {YType} child target
|
|
161
|
-
* @param {
|
|
161
|
+
* @param {AbstractRenderer} renderer
|
|
162
162
|
* @return {Array<string|number>} Path to the target
|
|
163
163
|
*
|
|
164
164
|
* @private
|
|
165
165
|
* @function
|
|
166
166
|
*/
|
|
167
|
-
export const getPathTo = (parent, child,
|
|
167
|
+
export const getPathTo = (parent, child, renderer = baseRenderer) => {
|
|
168
168
|
const path = []
|
|
169
169
|
const doc = /** @type {Doc} */ (parent.doc)
|
|
170
170
|
while (child._item !== null && child !== parent) {
|
|
@@ -174,7 +174,7 @@ export const getPathTo = (parent, child, am = noAttributionsManager) => {
|
|
|
174
174
|
} else {
|
|
175
175
|
const parent = /** @type {import('../ytype.js').YType} */ (child._item.parent)
|
|
176
176
|
// parent is array-ish
|
|
177
|
-
const apos = /** @type {import('../utils/RelativePosition.js').AbsolutePosition} */ (createAbsolutePositionFromRelativePosition(createRelativePosition(parent, child._item.id), doc, false,
|
|
177
|
+
const apos = /** @type {import('../utils/RelativePosition.js').AbsolutePosition} */ (createAbsolutePositionFromRelativePosition(createRelativePosition(parent, child._item.id), doc, false, renderer))
|
|
178
178
|
path.unshift(apos.index)
|
|
179
179
|
}
|
|
180
180
|
child = /** @type {YType} */ (child._item.parent)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as delta from 'lib0/delta'
|
|
2
2
|
import { createInsertSetFromStructStore, createDeleteSetFromStructStore, diffIdSet, mergeIdSets } from './ids.js'
|
|
3
|
-
import {
|
|
3
|
+
import { createDiffRenderer } from './Renderer.js'
|
|
4
4
|
import { computeModifiedFromItems } from '../ytype.js'
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -8,7 +8,7 @@ import { computeModifiedFromItems } from '../ytype.js'
|
|
|
8
8
|
* @param {Doc} v2
|
|
9
9
|
* @return {delta.DeltaBuilderAny}
|
|
10
10
|
*/
|
|
11
|
-
export const diffDocsToDelta = (v1, v2, {
|
|
11
|
+
export const diffDocsToDelta = (v1, v2, { renderer = createDiffRenderer(v1, v2) } = {}) => {
|
|
12
12
|
const insertDiff = diffIdSet(createInsertSetFromStructStore(v2.store, false), createInsertSetFromStructStore(v1.store, false))
|
|
13
13
|
const deleteDiff = diffIdSet(createDeleteSetFromStructStore(v2.store), createDeleteSetFromStructStore(v1.store))
|
|
14
14
|
// don't render items that have been inserted and then deleted
|
|
@@ -23,8 +23,8 @@ export const diffDocsToDelta = (v1, v2, { am = createAttributionManagerFromDiff(
|
|
|
23
23
|
v2.share.forEach((type, typename) => {
|
|
24
24
|
const typeConf = changedTypes.get(type)
|
|
25
25
|
if (typeConf) {
|
|
26
|
-
const shareDelta = type.toDelta(
|
|
27
|
-
itemsToRender, retainDeletes: true, deletedItems: deletesOnly, modified: changedTypes, deep: true
|
|
26
|
+
const shareDelta = type.toDelta({
|
|
27
|
+
renderer, itemsToRender, retainDeletes: true, deletedItems: deletesOnly, modified: changedTypes, deep: true
|
|
28
28
|
})
|
|
29
29
|
d.modifyAttr(typename, shareDelta)
|
|
30
30
|
}
|
package/src/utils/ids.js
CHANGED
|
@@ -7,7 +7,7 @@ import * as rabin from 'lib0/hash/rabin'
|
|
|
7
7
|
import * as array from 'lib0/array'
|
|
8
8
|
import * as map from 'lib0/map'
|
|
9
9
|
|
|
10
|
-
import { iterateStructs, findIndexSS, iterateStructsWithoutSplits } from './transaction-helpers.js'
|
|
10
|
+
import { iterateStructs, findIndexSS, iterateStructsWithoutSplits, tryGc } from './transaction-helpers.js'
|
|
11
11
|
import { UpdateEncoderV2, IdSetEncoderV2 } from './UpdateEncoder.js'
|
|
12
12
|
import { IdSetDecoderV2 } from './UpdateDecoder.js'
|
|
13
13
|
|
|
@@ -369,6 +369,27 @@ export const iterateStructsByIdSet = (transaction, ds, f) =>
|
|
|
369
369
|
}
|
|
370
370
|
})
|
|
371
371
|
|
|
372
|
+
/**
|
|
373
|
+
* Garbage-collect the deleted content referenced by `ids` on `doc`.
|
|
374
|
+
*
|
|
375
|
+
* This is useful to retroactively reclaim memory on a document created with `gc: false`
|
|
376
|
+
* (e.g. once a snapshot, or an UndoManager StackItem, that referenced this content is no
|
|
377
|
+
* longer needed) - without enabling gc for the whole document. Ids that reference live
|
|
378
|
+
* (non-deleted) content, already-collected structs, items flagged with `keep`, or items
|
|
379
|
+
* rejected by `gcFilter` are skipped.
|
|
380
|
+
*
|
|
381
|
+
* @param {Doc} doc
|
|
382
|
+
* @param {IdSet} ids
|
|
383
|
+
* @param {function(Item):boolean} [gcFilter]
|
|
384
|
+
*/
|
|
385
|
+
export const gcIdSet = (doc, ids, gcFilter = doc.gcFilter) =>
|
|
386
|
+
doc.transact(tr => {
|
|
387
|
+
// Split structs exactly at the IdSet boundaries so that only the referenced content is
|
|
388
|
+
// collected - an arbitrary IdSet need not align with struct boundaries.
|
|
389
|
+
iterateStructsByIdSet(tr, ids, () => {})
|
|
390
|
+
tryGc(tr, ids, gcFilter)
|
|
391
|
+
})
|
|
392
|
+
|
|
372
393
|
/**
|
|
373
394
|
* Iterate over all structs that are mentioned by the IdSet, without spliting the items.
|
|
374
395
|
*
|
|
@@ -38,14 +38,14 @@ export class AttributedContent {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* Abstract class for
|
|
41
|
+
* Abstract base class for renderers. A renderer renders Content (with Attributions) to a delta.
|
|
42
42
|
*
|
|
43
43
|
* Should fire an event when the attributions changed _after_ the original change happens. This
|
|
44
44
|
* Event will be used to update the attribution on the current content.
|
|
45
45
|
*
|
|
46
46
|
* @extends {ObservableV2<{change:(idset:IdSet,origin:any,local:boolean)=>void}>}
|
|
47
47
|
*/
|
|
48
|
-
export class
|
|
48
|
+
export class AbstractRenderer extends ObservableV2 {
|
|
49
49
|
/**
|
|
50
50
|
* @param {Array<AttributedContent<any>>} _contents - where to write the result
|
|
51
51
|
* @param {number} _client
|
|
@@ -72,17 +72,17 @@ export class AbstractAttributionManager extends ObservableV2 {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
export const $
|
|
75
|
+
export const $renderer = AbstractRenderer.prototype.$type = s.$type('y:r', AbstractRenderer)
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
|
-
*
|
|
78
|
+
* The default renderer. Renders content as-is, without looking up any attributions.
|
|
79
79
|
*
|
|
80
|
-
* @implements
|
|
80
|
+
* @implements AbstractRenderer
|
|
81
81
|
*
|
|
82
82
|
* @extends {ObservableV2<{change:(idset:IdSet,origin:any,local:boolean)=>void}>}
|
|
83
83
|
*/
|
|
84
|
-
export class
|
|
85
|
-
get $type () { return $
|
|
84
|
+
export class BaseRenderer extends ObservableV2 {
|
|
85
|
+
get $type () { return $renderer }
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
88
|
* @param {Array<AttributedContent<any>>} contents - where to write the result
|
|
@@ -107,4 +107,4 @@ export class NoAttributionsManager extends ObservableV2 {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
export const
|
|
110
|
+
export const baseRenderer = new BaseRenderer()
|