Merge pull request #22650 from overleaf/em-tracked-deletes-at-same-position

Handle multiple tracked deletes at same position

GitOrigin-RevId: 3cbf1c418bcd50cf08e1b90ce6ba3bc480236079
This commit is contained in:
Eric Mc Sween
2025-01-13 09:20:57 -05:00
committed by Copybot
parent 39d1ba7fe0
commit e9c1c0f9c8
5 changed files with 261 additions and 6 deletions

View File

@@ -352,6 +352,12 @@ function getHistoryOpForInsert(op, comments, changes) {
}
}
// If it's determined that the op is a tracked delete rejection, we have to
// calculate its proper history position. If multiple tracked deletes are
// found at the same position as the insert, the tracked deletes that come
// before the tracked delete that was actually rejected offset the history
// position.
let trackedDeleteRejectionOffset = 0
for (const change of changes) {
if (!isDelete(change.op)) {
// We're only interested in tracked deletes
@@ -362,14 +368,25 @@ function getHistoryOpForInsert(op, comments, changes) {
// Tracked delete is before the op. Move the op forward.
hpos += change.op.d.length
} else if (change.op.p === op.p) {
// Tracked delete is at the same position as the op. The insert comes before
// the tracked delete so it doesn't move.
// Tracked delete is at the same position as the op.
if (op.u && change.op.d.startsWith(op.i)) {
// We're undoing and the insert matches the start of the tracked
// delete. RangesManager treats this as a tracked delete rejection. We
// will note this in the op so that project-history can take the
// appropriate action.
trackedDeleteRejection = true
// The history must be updated to take into account all preceding
// tracked deletes at the same position
hpos += trackedDeleteRejectionOffset
// No need to continue. All subsequent tracked deletes are after the
// insert.
break
} else {
// This tracked delete does not match the insert. Note its length in
// case we find a tracked delete that matches later.
trackedDeleteRejectionOffset += change.op.d.length
}
} else {
// Tracked delete is after the insert. Tracked deletes are ordered, so

View File

@@ -323,6 +323,44 @@ describe('RangesManager', function () {
})
})
describe('tracked delete rejections with multiple tracked deletes at the same position', function () {
beforeEach(function () {
// original text is "one [two ][three ][four ]five"
// [] denotes tracked deletes
this.ranges = {
changes: makeRanges([
{ d: 'two ', p: 4 },
{ d: 'three ', p: 4 },
{ d: 'four ', p: 4 },
]),
}
this.updates = makeUpdates([{ i: 'three ', p: 4, u: true }])
this.newDocLines = ['one three five']
this.result = this.RangesManager.applyUpdate(
this.project_id,
this.doc_id,
this.ranges,
this.updates,
this.newDocLines,
{ historyRangesSupport: true }
)
})
it('should insert the text at the right history position', function () {
expect(this.result.historyUpdates.map(x => x.op)).to.deep.equal([
[
{
i: 'three ',
p: 4,
hpos: 8,
u: true,
trackedDeleteRejection: true,
},
],
])
})
})
describe('deletes over tracked changes', function () {
beforeEach(function () {
// original text is "on[1]e [22](three) f[333]ou[4444]r [55555]five"