From a5e390160ca8686b9a54b3d924f37041e89407b3 Mon Sep 17 00:00:00 2001 From: Kevin Jahns Date: Thu, 1 May 2025 14:44:24 +0200 Subject: [PATCH] fix nicks test --- src/utils/AttributionManager.js | 19 +++++++++---------- src/utils/IdSet.js | 8 +++++--- tests/y-text.tests.js | 4 ++-- tests/y-xml.tests.js | 4 ++++ 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/utils/AttributionManager.js b/src/utils/AttributionManager.js index e85f7a56..f363d98f 100644 --- a/src/utils/AttributionManager.js +++ b/src/utils/AttributionManager.js @@ -153,29 +153,28 @@ export class DiffAttributionManager { * @param {Doc} nextDoc */ constructor (prevDoc, nextDoc) { - const nextDocInserts = createInsertionSetFromStructStore(nextDoc.store) - const prevDocInserts = createInsertionSetFromStructStore(prevDoc.store) - const nextDocDeletes = createDeleteSetFromStructStore(nextDoc.store) - const prevDocDeletes = createDeleteSetFromStructStore(prevDoc.store) - this.inserts = createIdMapFromIdSet(diffIdSet(nextDocInserts, prevDocInserts), []) + const _nextDocInserts = createInsertionSetFromStructStore(nextDoc.store, false) // unmaintained + const _prevDocInserts = createInsertionSetFromStructStore(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._prevDoc = prevDoc this._prevDocStore = prevDoc.store this._nextDoc = nextDoc // update before observer calls fired this._nextBOH = nextDoc.on('beforeObserverCalls', tr => { // update inserts - insertIntoIdSet(nextDocInserts, tr.insertSet) - const diffInserts = diffIdSet(tr.insertSet, prevDocInserts) + const diffInserts = diffIdSet(tr.insertSet, _prevDocInserts) insertIntoIdMap(this.inserts, createIdMapFromIdSet(diffInserts, [])) // update deletes - insertIntoIdSet(nextDocDeletes, tr.deleteSet) const diffDeletes = diffIdSet(tr.deleteSet, prevDocDeletes) insertIntoIdMap(this.deletes, createIdMapFromIdSet(diffDeletes, [])) // @todo fire update ranges on `diffInserts` and `diffDeletes` }) this._prevBOH = prevDoc.on('beforeObserverCalls', tr => { + insertIntoIdSet(_prevDocInserts, tr.insertSet) + insertIntoIdSet(prevDocDeletes, tr.deleteSet) this.inserts = diffIdMap(this.inserts, tr.insertSet) this.deletes = diffIdMap(this.deletes, tr.deleteSet) // @todo fire update ranges on `tr.insertSet` and `tr.deleteSet` @@ -199,7 +198,7 @@ export class DiffAttributionManager { 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) { + if (content instanceof ContentDeleted && slice[0].attrs != null && !this.inserts.hasId(item.id)) { // 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 diff --git a/src/utils/IdSet.js b/src/utils/IdSet.js index 37472bb5..9ef35e6d 100644 --- a/src/utils/IdSet.js +++ b/src/utils/IdSet.js @@ -452,8 +452,9 @@ export const createDeleteSetFromStructStore = ss => { /** * @param {import('../internals.js').StructStore} ss + * @param {boolean} filterDeleted */ -export const createInsertionSetFromStructStore = ss => { +export const createInsertionSetFromStructStore = (ss, filterDeleted) => { const idset = createIdSet() ss.clients.forEach((structs, client) => { /** @@ -462,11 +463,12 @@ export const createInsertionSetFromStructStore = ss => { const iditems = [] for (let i = 0; i < structs.length; i++) { const struct = structs[i] - if (!struct.deleted) { + if (!(filterDeleted && struct.deleted)) { const clock = struct.id.clock let len = struct.length if (i + 1 < structs.length) { - for (let next = structs[i + 1]; i + 1 < structs.length && !next.deleted; next = structs[++i + 1]) { + // eslint-disable-next-line + for (let next = structs[i + 1]; i + 1 < structs.length && !(filterDeleted && next.deleted); next = structs[++i + 1]) { len += next.length } } diff --git a/tests/y-text.tests.js b/tests/y-text.tests.js index 95bb3837..50c5f6e6 100644 --- a/tests/y-text.tests.js +++ b/tests/y-text.tests.js @@ -2343,10 +2343,10 @@ export const testAttributedDiffing = _tc => { const ytext = ydoc.getText() ytext.applyDelta([{ retain: 4, attributes: { italic: true } }, { retain: 2 }, { delete: 5 }, { insert: 'attributions' }]) // this represents to all insertions of ydoc - const insertionSet = Y.createInsertionSetFromStructStore(ydoc.store) + const insertionSet = Y.createInsertionSetFromStructStore(ydoc.store, false) const deleteSet = Y.createDeleteSetFromStructStore(ydoc.store) // exclude the changes from `ydocVersion0` - const insertionSetDiff = Y.diffIdSet(insertionSet, Y.createInsertionSetFromStructStore(ydocVersion0.store)) + const insertionSetDiff = Y.diffIdSet(insertionSet, Y.createInsertionSetFromStructStore(ydocVersion0.store, false)) const deleteSetDiff = Y.diffIdSet(deleteSet, Y.createDeleteSetFromStructStore(ydocVersion0.store)) // assign attributes to the diff const attributedInsertions = createIdMapFromIdSet(insertionSetDiff, [new Y.Attribution('insert', 'Bob')]) diff --git a/tests/y-xml.tests.js b/tests/y-xml.tests.js index 121e289b..74b56358 100644 --- a/tests/y-xml.tests.js +++ b/tests/y-xml.tests.js @@ -380,9 +380,11 @@ export const testElementAttributedContentViaDiffer = _tc => { */ export const testAttributionManagerSimpleExample = _tc => { const ydoc = new Y.Doc() + ydoc.clientID = 0 // create some initial content ydoc.getXmlFragment().insert(0, [new Y.XmlText('hello world')]) const ydocFork = new Y.Doc() + ydocFork.clientID = 1 Y.applyUpdate(ydocFork, Y.encodeStateAsUpdate(ydoc)) // modify the fork // append a span element @@ -390,6 +392,8 @@ export const testAttributionManagerSimpleExample = _tc => { const ytext = /** @type {Y.XmlText} */ (ydocFork.getXmlFragment().get(0)) // make "hello" italic ytext.format(0, 5, { italic: true }) + ytext.insert(11, 'deleteme') + ytext.delete(11, 8) ytext.insert(11, '!') // highlight the changes console.log(JSON.stringify(ydocFork.getXmlFragment().getContentDeep(Y.createAttributionManagerFromDiff(ydoc, ydocFork)), null, 2))