mirror of
https://github.com/yjs/yjs.git
synced 2025-12-16 19:57:45 +01:00
implement createAttributionsManagerFromDiff that automatically handles gc
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
import {
|
||||
Item, AbstractContent, IdMap // eslint-disable-line
|
||||
getItem,
|
||||
diffIdSet,
|
||||
createInsertionSetFromStructStore,
|
||||
createDeleteSetFromStructStore,
|
||||
createIdMapFromIdSet,
|
||||
ContentDeleted,
|
||||
Doc, Item, AbstractContent, IdMap, // eslint-disable-line
|
||||
findIndexCleanStart
|
||||
} from '../internals.js'
|
||||
|
||||
import * as error from 'lib0/error'
|
||||
@@ -21,7 +28,7 @@ import * as error from 'lib0/error'
|
||||
* @param {boolean} deleted - whether the attributed item is deleted
|
||||
* @return {Attribution?}
|
||||
*/
|
||||
export const createAttributionFromAttrs = (attrs, deleted) => {
|
||||
export const createAttributionFromAttributionItems = (attrs, deleted) => {
|
||||
/**
|
||||
* @type {Attribution?}
|
||||
*/
|
||||
@@ -84,8 +91,6 @@ export class AbstractAttributionManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract class for associating Attributions to content / changes
|
||||
*
|
||||
* @implements AbstractAttributionManager
|
||||
*/
|
||||
export class TwosetAttributionManager {
|
||||
@@ -136,3 +141,71 @@ export class NoAttributionsManager {
|
||||
}
|
||||
|
||||
export const noAttributionsManager = new NoAttributionsManager()
|
||||
|
||||
/**
|
||||
* @implements AbstractAttributionManager
|
||||
*/
|
||||
export class DiffAttributionManager {
|
||||
/**
|
||||
* @param {IdMap<any>} inserts
|
||||
* @param {IdMap<any>} deletes
|
||||
* @param {Doc} prevDoc
|
||||
* @param {Doc} nextDoc
|
||||
*/
|
||||
constructor (inserts, deletes, prevDoc, nextDoc) {
|
||||
this.inserts = inserts
|
||||
this.deletes = deletes
|
||||
this._prevDocStore = prevDoc.store
|
||||
this._nextDoc = nextDoc
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<AttributedContent<any>>} contents
|
||||
* @param {Item} item
|
||||
*/
|
||||
readContent (contents, item) {
|
||||
const deleted = item.deleted || /** @type {any} */ (item.parent).doc !== this._nextDoc
|
||||
const slice = (deleted ? this.deletes : this.inserts).slice(item.id, item.length)
|
||||
let content = slice.length === 1 ? item.content : item.content.copy()
|
||||
if (content instanceof ContentDeleted && slice[0].attrs != null) {
|
||||
// Retrieved item is never more fragmented than the newer item.
|
||||
const prevItem = getItem(this._prevDocStore, item.id)
|
||||
content = prevItem.length > 1 ? prevItem.content.copy() : prevItem.content
|
||||
// trim itemContent to the correct size.
|
||||
const diffStart = prevItem.id.clock - item.id.clock
|
||||
const diffEnd = prevItem.id.clock + prevItem.length - item.id.clock - item.length
|
||||
if (diffStart > 0) {
|
||||
content = content.splice(diffStart)
|
||||
}
|
||||
if (diffEnd > 0) {
|
||||
content.splice(content.getLength() - diffEnd)
|
||||
}
|
||||
}
|
||||
slice.forEach(s => {
|
||||
const c = content
|
||||
if (s.len < c.getLength()) {
|
||||
content = c.splice(s.len)
|
||||
}
|
||||
if (!deleted || s.attrs != null) {
|
||||
contents.push(new AttributedContent(c, deleted, s.attrs))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Attribute changes from ydoc1 to ydoc2.
|
||||
*
|
||||
* @param {Doc} prevDoc
|
||||
* @param {Doc} nextDoc
|
||||
*/
|
||||
export const createAttributionManagerFromDiff = (prevDoc, nextDoc) => {
|
||||
const inserts = diffIdSet(createInsertionSetFromStructStore(nextDoc.store), createInsertionSetFromStructStore(prevDoc.store))
|
||||
const deletes = diffIdSet(createDeleteSetFromStructStore(nextDoc.store), createDeleteSetFromStructStore(prevDoc.store))
|
||||
const insertMap = createIdMapFromIdSet(inserts, [])
|
||||
const deleteMap = createIdMapFromIdSet(deletes, [])
|
||||
// @todo, get deletes from the older doc
|
||||
return new DiffAttributionManager(insertMap, deleteMap, prevDoc, nextDoc)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user