mirror of
https://github.com/overleaf/overleaf.git
synced 2025-02-18 06:52:44 +00:00
Merge pull request #18716 from overleaf/em-tracked-delete-undo
Fix translation of tracked deletes GitOrigin-RevId: 4124db6953cbed46eea61f62118fc8e1ddfff4a0
This commit is contained in:
parent
06607b5c51
commit
6c9d4fb522
6 changed files with 45 additions and 14 deletions
|
@ -346,11 +346,18 @@ const UpdateManager = {
|
||||||
}
|
}
|
||||||
if (isDelete(op)) {
|
if (isDelete(op)) {
|
||||||
docLength -= op.d.length
|
docLength -= op.d.length
|
||||||
if (!update.meta.tc || op.u) {
|
if (update.meta.tc) {
|
||||||
// This is either a regular delete or a tracked insert rejection.
|
// This is a tracked delete. It will be translated into a retain in
|
||||||
// It will be translated to a delete in history. Tracked deletes
|
// history, except any enclosed tracked inserts, which will be
|
||||||
// are translated into retains and don't change the history doc
|
// translated into regular deletes.
|
||||||
// length.
|
for (const change of op.trackedChanges ?? []) {
|
||||||
|
if (change.type === 'insert') {
|
||||||
|
historyDocLength -= change.length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This is a regular delete. It will be translated to a delete in
|
||||||
|
// history.
|
||||||
historyDocLength -= op.d.length
|
historyDocLength -= op.d.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -540,7 +540,11 @@ describe('UpdateManager', function () {
|
||||||
op: [
|
op: [
|
||||||
{ d: 'qux', p: 4 },
|
{ d: 'qux', p: 4 },
|
||||||
{ i: 'bazbaz', p: 14 },
|
{ i: 'bazbaz', p: 14 },
|
||||||
{ d: 'bong', p: 28, u: true },
|
{
|
||||||
|
d: 'bong',
|
||||||
|
p: 28,
|
||||||
|
trackedChanges: [{ type: 'insert', offset: 0, length: 4 }],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
tc: 'tracking-info',
|
tc: 'tracking-info',
|
||||||
|
@ -589,7 +593,11 @@ describe('UpdateManager', function () {
|
||||||
op: [
|
op: [
|
||||||
{ d: 'qux', p: 4 },
|
{ d: 'qux', p: 4 },
|
||||||
{ i: 'bazbaz', p: 14 },
|
{ i: 'bazbaz', p: 14 },
|
||||||
{ d: 'bong', p: 28, u: true },
|
{
|
||||||
|
d: 'bong',
|
||||||
|
p: 28,
|
||||||
|
trackedChanges: [{ type: 'insert', offset: 0, length: 4 }],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
pathname: this.pathname,
|
pathname: this.pathname,
|
||||||
|
@ -647,7 +655,11 @@ describe('UpdateManager', function () {
|
||||||
op: [
|
op: [
|
||||||
{ d: 'qux', p: 4 },
|
{ d: 'qux', p: 4 },
|
||||||
{ i: 'bazbaz', p: 14 },
|
{ i: 'bazbaz', p: 14 },
|
||||||
{ d: 'bong', p: 28, u: true },
|
{
|
||||||
|
d: 'bong',
|
||||||
|
p: 28,
|
||||||
|
trackedChanges: [{ type: 'insert', offset: 0, length: 4 }],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
pathname: this.pathname,
|
pathname: this.pathname,
|
||||||
|
|
|
@ -60,7 +60,7 @@ function adjustLengthByOp(length, op, opts = {}) {
|
||||||
return length + op.i.length
|
return length + op.i.length
|
||||||
}
|
}
|
||||||
} else if ('d' in op && op.d != null) {
|
} else if ('d' in op && op.d != null) {
|
||||||
if (opts.tracked && op.u == null) {
|
if (opts.tracked) {
|
||||||
// Tracked delete: will be translated into a retain, except where it overlaps tracked inserts.
|
// Tracked delete: will be translated into a retain, except where it overlaps tracked inserts.
|
||||||
for (const change of op.trackedChanges ?? []) {
|
for (const change of op.trackedChanges ?? []) {
|
||||||
if (change.type === 'insert') {
|
if (change.type === 'insert') {
|
||||||
|
|
|
@ -357,7 +357,7 @@ class OperationsBuilder {
|
||||||
for (const change of changes) {
|
for (const change of changes) {
|
||||||
if (change.offset > offset) {
|
if (change.offset > offset) {
|
||||||
// Handle the portion before the tracked change
|
// Handle the portion before the tracked change
|
||||||
if (update.meta.tc != null && op.u == null) {
|
if (update.meta.tc != null) {
|
||||||
// This is a tracked delete
|
// This is a tracked delete
|
||||||
this.retain(change.offset - offset, {
|
this.retain(change.offset - offset, {
|
||||||
tracking: {
|
tracking: {
|
||||||
|
@ -385,7 +385,7 @@ class OperationsBuilder {
|
||||||
}
|
}
|
||||||
if (offset < op.d.length) {
|
if (offset < op.d.length) {
|
||||||
// Handle the portion after the last tracked change
|
// Handle the portion after the last tracked change
|
||||||
if (update.meta.tc != null && op.u == null) {
|
if (update.meta.tc != null) {
|
||||||
// This is a tracked delete
|
// This is a tracked delete
|
||||||
this.retain(op.d.length - offset, {
|
this.retain(op.d.length - offset, {
|
||||||
tracking: {
|
tracking: {
|
||||||
|
|
|
@ -199,7 +199,11 @@ describe('UpdateCompressor', function () {
|
||||||
{ p: 22, d: 'apple' }, // doc_length doesn't change
|
{ p: 22, d: 'apple' }, // doc_length doesn't change
|
||||||
{ p: 12, i: 'melon', u: true }, // doc_length += 5
|
{ p: 12, i: 'melon', u: true }, // doc_length += 5
|
||||||
{ p: 18, i: 'banana', u: true, trackedDeleteRejection: true }, // doc_length doesn't change
|
{ p: 18, i: 'banana', u: true, trackedDeleteRejection: true }, // doc_length doesn't change
|
||||||
{ p: 8, d: 'pineapple', u: true }, // doc_length -= 9
|
{
|
||||||
|
p: 8,
|
||||||
|
d: 'pineapple',
|
||||||
|
trackedChanges: [{ type: 'insert', offset: 0, length: 9 }],
|
||||||
|
}, // doc_length -= 9
|
||||||
{ p: 11, i: 'fruit salad' },
|
{ p: 11, i: 'fruit salad' },
|
||||||
],
|
],
|
||||||
meta: { ...meta, doc_length: 20, history_doc_length: 30 },
|
meta: { ...meta, doc_length: 20, history_doc_length: 30 },
|
||||||
|
@ -228,7 +232,11 @@ describe('UpdateCompressor', function () {
|
||||||
v: 42,
|
v: 42,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
op: { p: 8, d: 'pineapple', u: true },
|
op: {
|
||||||
|
p: 8,
|
||||||
|
d: 'pineapple',
|
||||||
|
trackedChanges: [{ type: 'insert', offset: 0, length: 9 }],
|
||||||
|
},
|
||||||
meta: { ...meta, doc_length: 41 },
|
meta: { ...meta, doc_length: 41 },
|
||||||
v: 42,
|
v: 42,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1069,7 +1069,11 @@ describe('UpdateTranslator', function () {
|
||||||
{ i: 'inserted', p: 5 },
|
{ i: 'inserted', p: 5 },
|
||||||
{ d: 'deleted', p: 20 },
|
{ d: 'deleted', p: 20 },
|
||||||
{ i: 'rejected deletion', p: 30, trackedDeleteRejection: true },
|
{ i: 'rejected deletion', p: 30, trackedDeleteRejection: true },
|
||||||
{ d: 'rejected insertion', p: 50, u: true },
|
{
|
||||||
|
d: 'rejected insertion',
|
||||||
|
p: 50,
|
||||||
|
trackedChanges: [{ type: 'insert', offset: 0, length: 18 }],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
v: this.version,
|
v: this.version,
|
||||||
meta: {
|
meta: {
|
||||||
|
|
Loading…
Reference in a new issue