mirror of
https://github.com/yjs/yjs.git
synced 2026-02-23 19:49:59 +01:00
Merge pull request #753 from nperez0111/attrs
Support attributing content in `DiffAttributionManager` & `SnapshotAttributionManager`
This commit is contained in:
@@ -9,7 +9,6 @@ import {
|
||||
insertIntoIdSet,
|
||||
diffIdMap,
|
||||
createIdMap,
|
||||
createAttributionItem,
|
||||
mergeIdMaps,
|
||||
createID,
|
||||
mergeIdSets,
|
||||
@@ -349,15 +348,17 @@ export class DiffAttributionManager extends ObservableV2 {
|
||||
/**
|
||||
* @param {Doc} prevDoc
|
||||
* @param {Doc} nextDoc
|
||||
* @param {Object} [options] - options for the attribution manager
|
||||
* @param {Array<import('./IdMap.js').AttributionItem<any>>} [options.attrs] - the attributes to apply to the diff
|
||||
*/
|
||||
constructor (prevDoc, nextDoc) {
|
||||
constructor (prevDoc, nextDoc, { attrs = [] } = {}) {
|
||||
super()
|
||||
const _nextDocInserts = createInsertSetFromStructStore(nextDoc.store, false) // unmaintained
|
||||
const _prevDocInserts = createInsertSetFromStructStore(prevDoc.store, false) // unmaintained
|
||||
const nextDocDeletes = createDeleteSetFromStructStore(nextDoc.store) // maintained
|
||||
const prevDocDeletes = createDeleteSetFromStructStore(prevDoc.store) // maintained
|
||||
this.inserts = createIdMapFromIdSet(diffIdSet(_nextDocInserts, _prevDocInserts), [])
|
||||
this.deletes = createIdMapFromIdSet(diffIdSet(nextDocDeletes, prevDocDeletes), [])
|
||||
this.inserts = createIdMapFromIdSet(diffIdSet(_nextDocInserts, _prevDocInserts), attrs)
|
||||
this.deletes = createIdMapFromIdSet(diffIdSet(nextDocDeletes, prevDocDeletes), attrs)
|
||||
this._prevDoc = prevDoc
|
||||
this._prevDocStore = prevDoc.store
|
||||
this._nextDoc = nextDoc
|
||||
@@ -365,10 +366,10 @@ export class DiffAttributionManager extends ObservableV2 {
|
||||
this._nextBOH = nextDoc.on('beforeObserverCalls', tr => {
|
||||
// update inserts
|
||||
const diffInserts = diffIdSet(tr.insertSet, _prevDocInserts)
|
||||
insertIntoIdMap(this.inserts, createIdMapFromIdSet(diffInserts, []))
|
||||
insertIntoIdMap(this.inserts, createIdMapFromIdSet(diffInserts, attrs))
|
||||
// update deletes
|
||||
const diffDeletes = diffIdSet(diffIdSet(tr.deleteSet, prevDocDeletes), this.inserts)
|
||||
insertIntoIdMap(this.deletes, createIdMapFromIdSet(diffDeletes, []))
|
||||
insertIntoIdMap(this.deletes, createIdMapFromIdSet(diffDeletes, attrs))
|
||||
// @todo fire update ranges on `diffInserts` and `diffDeletes`
|
||||
})
|
||||
this._prevBOH = prevDoc.on('beforeObserverCalls', tr => {
|
||||
@@ -538,8 +539,10 @@ export class DiffAttributionManager extends ObservableV2 {
|
||||
*
|
||||
* @param {Doc} prevDoc
|
||||
* @param {Doc} nextDoc
|
||||
* @param {Object} [options] - options for the attribution manager
|
||||
* @param {Array<import('./IdMap.js').AttributionItem<any>>} [options.attrs] - the attributes to apply to the diff
|
||||
*/
|
||||
export const createAttributionManagerFromDiff = (prevDoc, nextDoc) => new DiffAttributionManager(prevDoc, nextDoc)
|
||||
export const createAttributionManagerFromDiff = (prevDoc, nextDoc, options) => new DiffAttributionManager(prevDoc, nextDoc, options)
|
||||
|
||||
/**
|
||||
* Intended for projects that used the v13 snapshot feature. With this AttributionManager you can
|
||||
@@ -553,17 +556,19 @@ export class SnapshotAttributionManager extends ObservableV2 {
|
||||
/**
|
||||
* @param {Snapshot} prevSnapshot
|
||||
* @param {Snapshot} nextSnapshot
|
||||
* @param {Object} [options] - options for the attribution manager
|
||||
* @param {Array<import('./IdMap.js').AttributionItem<any>>} [options.attrs] - the attributes to apply to the diff
|
||||
*/
|
||||
constructor (prevSnapshot, nextSnapshot) {
|
||||
constructor (prevSnapshot, nextSnapshot, { attrs = [] } = {}) {
|
||||
super()
|
||||
this.prevSnapshot = prevSnapshot
|
||||
this.nextSnapshot = nextSnapshot
|
||||
const inserts = createIdMap()
|
||||
const deletes = createIdMapFromIdSet(diffIdSet(nextSnapshot.ds, prevSnapshot.ds), [createAttributionItem('change', '')])
|
||||
const deletes = createIdMapFromIdSet(diffIdSet(nextSnapshot.ds, prevSnapshot.ds), attrs)
|
||||
nextSnapshot.sv.forEach((clock, client) => {
|
||||
const prevClock = prevSnapshot.sv.get(client) || 0
|
||||
inserts.add(client, 0, prevClock, []) // content is included in prevSnapshot is rendered without attributes
|
||||
inserts.add(client, prevClock, clock - prevClock, [createAttributionItem('change', '')]) // content is rendered as "inserted"
|
||||
inserts.add(client, prevClock, clock - prevClock, attrs) // content is rendered as "inserted"
|
||||
})
|
||||
this.attrs = mergeIdMaps([diffIdMap(inserts, prevSnapshot.ds), deletes])
|
||||
}
|
||||
@@ -615,5 +620,7 @@ export class SnapshotAttributionManager extends ObservableV2 {
|
||||
/**
|
||||
* @param {Snapshot} prevSnapshot
|
||||
* @param {Snapshot} nextSnapshot
|
||||
* @param {Object} [options] - options for the attribution manager
|
||||
* @param {Array<import('./IdMap.js').AttributionItem<any>>} [options.attrs] - the attributes to apply to the diff
|
||||
*/
|
||||
export const createAttributionManagerFromSnapshots = (prevSnapshot, nextSnapshot = prevSnapshot) => new SnapshotAttributionManager(prevSnapshot, nextSnapshot)
|
||||
export const createAttributionManagerFromSnapshots = (prevSnapshot, nextSnapshot = prevSnapshot, options) => new SnapshotAttributionManager(prevSnapshot, nextSnapshot, options)
|
||||
|
||||
@@ -37,16 +37,6 @@ export class AttributionItem {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AttributionItem<any>} attr
|
||||
*/
|
||||
const _hashAttribution = attr => {
|
||||
const encoder = encoding.createEncoder()
|
||||
encoding.writeVarString(encoder, attr.name)
|
||||
encoding.writeAny(encoder, attr.val)
|
||||
return buf.toBase64(rabin.fingerprint(rabin.StandardIrreducible128, encoding.toUint8Array(encoder)))
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo rename this to `createAttribute`
|
||||
* @template V
|
||||
@@ -596,7 +586,7 @@ export const decodeIdMap = data => readIdMap(new DSDecoderV2(decoding.createDeco
|
||||
const _ensureAttrs = (idmap, attrs) => attrs.map(attr =>
|
||||
idmap.attrs.has(attr)
|
||||
? attr
|
||||
: map.setIfUndefined(idmap.attrsH, _hashAttribution(attr), () => {
|
||||
: map.setIfUndefined(idmap.attrsH, attr.hash(), () => {
|
||||
idmap.attrs.add(attr)
|
||||
return attr
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user