mirror of
https://github.com/yjs/yjs.git
synced 2025-12-16 11:47:46 +01:00
implement diffDocsToDelta
This commit is contained in:
@@ -120,7 +120,8 @@ export {
|
||||
mergeIdMaps,
|
||||
readIdMap,
|
||||
readIdSet,
|
||||
decodeIdMap
|
||||
decodeIdMap,
|
||||
diffDocsToDelta
|
||||
} from './internals.js'
|
||||
|
||||
const glo = /** @type {any} */ (typeof globalThis !== 'undefined'
|
||||
|
||||
@@ -18,6 +18,7 @@ export * from './utils/YEvent.js'
|
||||
export * from './utils/StructSet.js'
|
||||
export * from './utils/IdMap.js'
|
||||
export * from './utils/AttributionManager.js'
|
||||
export * from './utils/delta-helpers.js'
|
||||
|
||||
export * from './types/AbstractType.js'
|
||||
export * from './types/YArray.js'
|
||||
|
||||
@@ -1351,7 +1351,7 @@ export const typeMapGetDelta = (d, parent, attrsToRender, am, deep, modified, de
|
||||
if (attrsToRender == null) {
|
||||
parent._map.forEach(renderAttrs)
|
||||
} else {
|
||||
attrsToRender.forEach(key => renderAttrs(/** @type {Item} */ (parent._map.get(key)), key))
|
||||
attrsToRender.forEach(key => key != null && renderAttrs(/** @type {Item} */ (parent._map.get(key)), key))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
54
src/utils/delta-helpers.js
Normal file
54
src/utils/delta-helpers.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import {
|
||||
createInsertSetFromStructStore,
|
||||
createDeleteSetFromStructStore,
|
||||
createAttributionManagerFromDiff,
|
||||
diffIdSet,
|
||||
mergeIdSets,
|
||||
Item,
|
||||
AbstractType, Doc, // eslint-disable-line
|
||||
iterateStructsByIdSet
|
||||
} from '../internals.js'
|
||||
import * as delta from 'lib0/delta'
|
||||
import * as map from 'lib0/map'
|
||||
import * as set from 'lib0/set'
|
||||
|
||||
/**
|
||||
* @param {Doc} v1
|
||||
* @param {Doc} v2
|
||||
* @return {delta.DeltaBuilderAny}
|
||||
*/
|
||||
export const diffDocsToDelta = (v1, v2, { am = createAttributionManagerFromDiff(v1, v2) } = {}) => {
|
||||
const d = delta.create()
|
||||
v2.transact(tr => {
|
||||
v2.share.forEach((type, typename) => {
|
||||
const insertDiff = diffIdSet(createInsertSetFromStructStore(v2.store, false), createInsertSetFromStructStore(v1.store, false))
|
||||
const deleteDiff = diffIdSet(createDeleteSetFromStructStore(v2.store), createDeleteSetFromStructStore(v1.store))
|
||||
// don't render items that have been inserted and then deleted
|
||||
const insertsOnly = diffIdSet(insertDiff, deleteDiff)
|
||||
const deletesOnly = diffIdSet(deleteDiff, insertDiff)
|
||||
const itemsToRender = mergeIdSets([insertsOnly, deleteDiff])
|
||||
/**
|
||||
* @type {Map<AbstractType, Set<string|null>>}
|
||||
*/
|
||||
const changedTypes = new Map()
|
||||
iterateStructsByIdSet(tr, itemsToRender, /** @param {any} item */ item => {
|
||||
while (item instanceof Item) {
|
||||
const parent = /** @type {AbstractType} */ (item.parent)
|
||||
const conf = map.setIfUndefined(changedTypes, parent, set.create)
|
||||
if (conf.has(item.parentSub)) break // has already been marked as modified
|
||||
conf.add(item.parentSub)
|
||||
item = parent._item
|
||||
}
|
||||
})
|
||||
const typeConf = changedTypes.get(type)
|
||||
if (typeConf) {
|
||||
// @ts-ignore
|
||||
const shareDelta = type.getContent(am, {
|
||||
itemsToRender, retainDeletes: true, renderAttrs: /** @type {Set<string>} */ (changedTypes.get(type)), renderChildren: typeConf.has(null), deletedItems: deletesOnly, modified: changedTypes, deep: true
|
||||
})
|
||||
d.update(typename, shareDelta)
|
||||
}
|
||||
})
|
||||
})
|
||||
return d
|
||||
}
|
||||
@@ -86,3 +86,25 @@ export const testInsertionsIntoAttributedContent = _tc => {
|
||||
ytext.applyDelta(delta.text().retain(9).insert('l'), am)
|
||||
t.assert(ytext.toString() === 'hello world')
|
||||
}
|
||||
|
||||
export const testYdocDiff = () => {
|
||||
const ydocStart = new Y.Doc()
|
||||
ydocStart.getText('text').insert(0, 'hello')
|
||||
ydocStart.getArray('array').insert(0, [1, 2, 3])
|
||||
ydocStart.getMap('map').set('k', 42)
|
||||
ydocStart.getMap('map').set('nested', new Y.Array())
|
||||
const ydocUpdated = Y.cloneDoc(ydocStart)
|
||||
ydocUpdated.getText('text').insert(5, ' world')
|
||||
ydocUpdated.getArray('array').insert(1, ['x'])
|
||||
ydocUpdated.getMap('map').set('newk', 42)
|
||||
ydocUpdated.getMap('map').get('nested').insert(0, [1])
|
||||
// @todo add custom attribution
|
||||
const d = Y.diffDocsToDelta(ydocStart, ydocUpdated)
|
||||
t.compare(d, delta.create()
|
||||
.update('text', delta.create().retain(5).insert('world'))
|
||||
.update('array', delta.create().retain(1).insert(['x']))
|
||||
.update('map', delta.create().set('newk', 42).update('nested', delta.create().insert([1])))
|
||||
)
|
||||
console.log(d.toJSON())
|
||||
debugger
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user