@manuscripts/track-changes-plugin 1.6.0 → 1.6.1-LEAN-2752

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -530,9 +530,7 @@ function updateChangeAttrs(tr, change, trackedAttrs, schema) {
530
530
  return tr;
531
531
  }
532
532
  const { operation } = trackedAttrs;
533
- const oldTrackData = change.type === 'text-change'
534
- ? getTextNodeTrackedMarkData(node, schema)
535
- : getBlockInlineTrackedData(node);
533
+ const oldTrackData = change.type === 'text-change' ? getTextNodeTrackedMarkData(node, schema) : getBlockInlineTrackedData(node);
536
534
  if (!operation) {
537
535
  log.warn('updateChangeAttrs: unable to determine operation of change ', change);
538
536
  }
@@ -553,7 +551,15 @@ function updateChangeAttrs(tr, change, trackedAttrs, schema) {
553
551
  tr.setNodeMarkup(change.from, undefined, { ...node.attrs, dataTracked: null }, node.marks);
554
552
  }
555
553
  else if (change.type === 'node-change' || change.type === 'node-attr-change') {
556
- const newDataTracked = (getBlockInlineTrackedData(node) || []).map((oldTrack) => {
554
+ const trackedDataSource = getBlockInlineTrackedData(node) || [];
555
+ const targetDataTracked = trackedDataSource.find((t) => change.id === t.id);
556
+ const newDataTracked = trackedDataSource.map((oldTrack) => {
557
+ if (targetDataTracked) {
558
+ if (oldTrack.id === targetDataTracked.id) {
559
+ return { ...oldTrack, ...trackedAttrs };
560
+ }
561
+ return oldTrack;
562
+ }
557
563
  if (oldTrack.operation === operation) {
558
564
  return { ...oldTrack, ...trackedAttrs };
559
565
  }
@@ -951,7 +957,7 @@ function createNewUpdateAttrs(attrs, oldAttrs) {
951
957
  return {
952
958
  ...attrs,
953
959
  operation: exports.CHANGE_OPERATION.set_node_attributes,
954
- oldAttrs: restAttrs,
960
+ oldAttrs: JSON.parse(JSON.stringify(restAttrs)),
955
961
  };
956
962
  }
957
963
 
@@ -1198,9 +1204,11 @@ function trackReplaceAroundStep(step, oldState, newTr, attrs) {
1198
1204
  */
1199
1205
  function trackReplaceStep(step, oldState, newTr, attrs, stepResult, currentStepDoc) {
1200
1206
  log.info('###### ReplaceStep ######');
1201
- let selectionPos = 0, changeSteps = [];
1207
+ let selectionPos = 0;
1208
+ const changeSteps = [];
1202
1209
  // Invert the transaction step to prevent it from actually deleting or inserting anything
1203
1210
  step.getMap().forEach((fromA, toA, fromB, toB) => {
1211
+ var _a, _b;
1204
1212
  log.info(`changed ranges: ${fromA} ${toA} ${fromB} ${toB}`);
1205
1213
  const { slice } = step;
1206
1214
  log.info('TR: steps before applying delete', [...newTr.steps]);
@@ -1248,9 +1256,6 @@ function trackReplaceStep(step, oldState, newTr, attrs, stepResult, currentStepD
1248
1256
  type: 'insert-slice',
1249
1257
  from: textWasDeleted ? fromB : toA,
1250
1258
  to: textWasDeleted ? toB - 1 : toA,
1251
- /* it's not entirely clear why using "fromB" is needed at all but in cases where there areno content deleted before
1252
- - it will gointo infinite loop if toB -1 is used
1253
- */
1254
1259
  sliceWasSplit,
1255
1260
  slice: new prosemirrorModel.Slice(setFragmentAsInserted(newSliceContent, createNewInsertAttrs(attrs), oldState.schema), openStart, openEnd),
1256
1261
  });
@@ -1258,7 +1263,10 @@ function trackReplaceStep(step, oldState, newTr, attrs, stepResult, currentStepD
1258
1263
  else {
1259
1264
  // Incase only deletion was applied, check whether tracked marks around deleted content can be merged
1260
1265
  // mergeTrackedMarks(adjustedInsertPos, newTr.doc, newTr, oldState.schema)
1261
- selectionPos = fromA;
1266
+ // When DEL is used, the selection is set to the end of the deleted content
1267
+ // TODO: 'window.event' is deprecated, find a better way to detect the key used for deletion
1268
+ // @ts-ignore
1269
+ selectionPos = ((_a = window.event) === null || _a === void 0 ? void 0 : _a.code) === 'Delete' || ((_b = window.event) === null || _b === void 0 ? void 0 : _b.inputType) === 'deleteContentForward' ? toA : fromA;
1262
1270
  }
1263
1271
  });
1264
1272
  return [changeSteps, selectionPos];
@@ -1421,15 +1429,29 @@ function processChangeSteps(changes, startPos, newTr, emptyAttrs, schema) {
1421
1429
  }
1422
1430
  else if (c.type === 'update-node-attrs') {
1423
1431
  const oldDataTracked = getBlockInlineTrackedData(c.node) || [];
1424
- const oldUpdate = oldDataTracked.find((d) => d.operation === exports.CHANGE_OPERATION.set_node_attributes && d.status === exports.CHANGE_STATUS.pending);
1425
- const { dataTracked, ...oldAttrs } = (oldUpdate === null || oldUpdate === void 0 ? void 0 : oldUpdate.oldAttrs) || c.node.attrs;
1426
- const newDataTracked = [...oldDataTracked.filter((d) => !oldUpdate || d.id !== oldUpdate.id)];
1427
- const newUpdate = oldUpdate
1432
+ const oldUpdate = oldDataTracked.reverse().find((d) => {
1433
+ // reversing to start from the most recent change
1434
+ if (d.operation === exports.CHANGE_OPERATION.set_node_attributes &&
1435
+ (d.status === exports.CHANGE_STATUS.pending || d.status === exports.CHANGE_STATUS.rejected)) {
1436
+ return true;
1437
+ }
1438
+ return false;
1439
+ });
1440
+ // if the selected last change is with status "rejected" we need to use oldAttrs from it because
1441
+ // node's actual attributes represent the "rejected" values
1442
+ const lastChangeRejected = oldUpdate && oldUpdate.status === exports.CHANGE_STATUS.rejected;
1443
+ const sourceAttrs = (oldUpdate === null || oldUpdate === void 0 ? void 0 : oldUpdate.oldAttrs) || c.node.attrs;
1444
+ const { dataTracked, ...restAttrs } = sourceAttrs;
1445
+ const oldAttrs = lastChangeRejected ? oldUpdate.oldAttrs : restAttrs;
1446
+ const newDataTracked = [
1447
+ ...oldDataTracked.filter((d) => !oldUpdate || d.id !== oldUpdate.id || lastChangeRejected),
1448
+ ];
1449
+ const newUpdate = oldUpdate && oldUpdate.status !== exports.CHANGE_STATUS.rejected
1428
1450
  ? {
1429
1451
  ...oldUpdate,
1430
1452
  updatedAt: emptyAttrs.updatedAt,
1431
1453
  }
1432
- : addTrackIdIfDoesntExist(createNewUpdateAttrs(emptyAttrs, c.node.attrs));
1454
+ : addTrackIdIfDoesntExist(createNewUpdateAttrs(emptyAttrs, lastChangeRejected ? oldAttrs : c.node.attrs));
1433
1455
  // Dont add update changes if there exists already an insert change for this node
1434
1456
  if (JSON.stringify(oldAttrs) !== JSON.stringify(c.newAttrs) &&
1435
1457
  !oldDataTracked.find((d) => d.operation === exports.CHANGE_OPERATION.insert)) {
package/dist/index.js CHANGED
@@ -522,9 +522,7 @@ function updateChangeAttrs(tr, change, trackedAttrs, schema) {
522
522
  return tr;
523
523
  }
524
524
  const { operation } = trackedAttrs;
525
- const oldTrackData = change.type === 'text-change'
526
- ? getTextNodeTrackedMarkData(node, schema)
527
- : getBlockInlineTrackedData(node);
525
+ const oldTrackData = change.type === 'text-change' ? getTextNodeTrackedMarkData(node, schema) : getBlockInlineTrackedData(node);
528
526
  if (!operation) {
529
527
  log.warn('updateChangeAttrs: unable to determine operation of change ', change);
530
528
  }
@@ -545,7 +543,15 @@ function updateChangeAttrs(tr, change, trackedAttrs, schema) {
545
543
  tr.setNodeMarkup(change.from, undefined, { ...node.attrs, dataTracked: null }, node.marks);
546
544
  }
547
545
  else if (change.type === 'node-change' || change.type === 'node-attr-change') {
548
- const newDataTracked = (getBlockInlineTrackedData(node) || []).map((oldTrack) => {
546
+ const trackedDataSource = getBlockInlineTrackedData(node) || [];
547
+ const targetDataTracked = trackedDataSource.find((t) => change.id === t.id);
548
+ const newDataTracked = trackedDataSource.map((oldTrack) => {
549
+ if (targetDataTracked) {
550
+ if (oldTrack.id === targetDataTracked.id) {
551
+ return { ...oldTrack, ...trackedAttrs };
552
+ }
553
+ return oldTrack;
554
+ }
549
555
  if (oldTrack.operation === operation) {
550
556
  return { ...oldTrack, ...trackedAttrs };
551
557
  }
@@ -943,7 +949,7 @@ function createNewUpdateAttrs(attrs, oldAttrs) {
943
949
  return {
944
950
  ...attrs,
945
951
  operation: CHANGE_OPERATION.set_node_attributes,
946
- oldAttrs: restAttrs,
952
+ oldAttrs: JSON.parse(JSON.stringify(restAttrs)),
947
953
  };
948
954
  }
949
955
 
@@ -1190,9 +1196,11 @@ function trackReplaceAroundStep(step, oldState, newTr, attrs) {
1190
1196
  */
1191
1197
  function trackReplaceStep(step, oldState, newTr, attrs, stepResult, currentStepDoc) {
1192
1198
  log.info('###### ReplaceStep ######');
1193
- let selectionPos = 0, changeSteps = [];
1199
+ let selectionPos = 0;
1200
+ const changeSteps = [];
1194
1201
  // Invert the transaction step to prevent it from actually deleting or inserting anything
1195
1202
  step.getMap().forEach((fromA, toA, fromB, toB) => {
1203
+ var _a, _b;
1196
1204
  log.info(`changed ranges: ${fromA} ${toA} ${fromB} ${toB}`);
1197
1205
  const { slice } = step;
1198
1206
  log.info('TR: steps before applying delete', [...newTr.steps]);
@@ -1240,9 +1248,6 @@ function trackReplaceStep(step, oldState, newTr, attrs, stepResult, currentStepD
1240
1248
  type: 'insert-slice',
1241
1249
  from: textWasDeleted ? fromB : toA,
1242
1250
  to: textWasDeleted ? toB - 1 : toA,
1243
- /* it's not entirely clear why using "fromB" is needed at all but in cases where there areno content deleted before
1244
- - it will gointo infinite loop if toB -1 is used
1245
- */
1246
1251
  sliceWasSplit,
1247
1252
  slice: new Slice(setFragmentAsInserted(newSliceContent, createNewInsertAttrs(attrs), oldState.schema), openStart, openEnd),
1248
1253
  });
@@ -1250,7 +1255,10 @@ function trackReplaceStep(step, oldState, newTr, attrs, stepResult, currentStepD
1250
1255
  else {
1251
1256
  // Incase only deletion was applied, check whether tracked marks around deleted content can be merged
1252
1257
  // mergeTrackedMarks(adjustedInsertPos, newTr.doc, newTr, oldState.schema)
1253
- selectionPos = fromA;
1258
+ // When DEL is used, the selection is set to the end of the deleted content
1259
+ // TODO: 'window.event' is deprecated, find a better way to detect the key used for deletion
1260
+ // @ts-ignore
1261
+ selectionPos = ((_a = window.event) === null || _a === void 0 ? void 0 : _a.code) === 'Delete' || ((_b = window.event) === null || _b === void 0 ? void 0 : _b.inputType) === 'deleteContentForward' ? toA : fromA;
1254
1262
  }
1255
1263
  });
1256
1264
  return [changeSteps, selectionPos];
@@ -1413,15 +1421,29 @@ function processChangeSteps(changes, startPos, newTr, emptyAttrs, schema) {
1413
1421
  }
1414
1422
  else if (c.type === 'update-node-attrs') {
1415
1423
  const oldDataTracked = getBlockInlineTrackedData(c.node) || [];
1416
- const oldUpdate = oldDataTracked.find((d) => d.operation === CHANGE_OPERATION.set_node_attributes && d.status === CHANGE_STATUS.pending);
1417
- const { dataTracked, ...oldAttrs } = (oldUpdate === null || oldUpdate === void 0 ? void 0 : oldUpdate.oldAttrs) || c.node.attrs;
1418
- const newDataTracked = [...oldDataTracked.filter((d) => !oldUpdate || d.id !== oldUpdate.id)];
1419
- const newUpdate = oldUpdate
1424
+ const oldUpdate = oldDataTracked.reverse().find((d) => {
1425
+ // reversing to start from the most recent change
1426
+ if (d.operation === CHANGE_OPERATION.set_node_attributes &&
1427
+ (d.status === CHANGE_STATUS.pending || d.status === CHANGE_STATUS.rejected)) {
1428
+ return true;
1429
+ }
1430
+ return false;
1431
+ });
1432
+ // if the selected last change is with status "rejected" we need to use oldAttrs from it because
1433
+ // node's actual attributes represent the "rejected" values
1434
+ const lastChangeRejected = oldUpdate && oldUpdate.status === CHANGE_STATUS.rejected;
1435
+ const sourceAttrs = (oldUpdate === null || oldUpdate === void 0 ? void 0 : oldUpdate.oldAttrs) || c.node.attrs;
1436
+ const { dataTracked, ...restAttrs } = sourceAttrs;
1437
+ const oldAttrs = lastChangeRejected ? oldUpdate.oldAttrs : restAttrs;
1438
+ const newDataTracked = [
1439
+ ...oldDataTracked.filter((d) => !oldUpdate || d.id !== oldUpdate.id || lastChangeRejected),
1440
+ ];
1441
+ const newUpdate = oldUpdate && oldUpdate.status !== CHANGE_STATUS.rejected
1420
1442
  ? {
1421
1443
  ...oldUpdate,
1422
1444
  updatedAt: emptyAttrs.updatedAt,
1423
1445
  }
1424
- : addTrackIdIfDoesntExist(createNewUpdateAttrs(emptyAttrs, c.node.attrs));
1446
+ : addTrackIdIfDoesntExist(createNewUpdateAttrs(emptyAttrs, lastChangeRejected ? oldAttrs : c.node.attrs));
1425
1447
  // Dont add update changes if there exists already an insert change for this node
1426
1448
  if (JSON.stringify(oldAttrs) !== JSON.stringify(c.newAttrs) &&
1427
1449
  !oldDataTracked.find((d) => d.operation === CHANGE_OPERATION.insert)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manuscripts/track-changes-plugin",
3
- "version": "1.6.0",
3
+ "version": "1.6.1-LEAN-2752",
4
4
  "author": "Atypon Systems LLC",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/Atypon-OpenSource/manuscripts-quarterback/tree/main/quarterback-packages/track-changes-plugin",
@@ -61,6 +61,7 @@
61
61
  "scripts": {
62
62
  "build": "rollup -c",
63
63
  "watch": "rollup -cw",
64
+ "dev": "yarn run watch",
64
65
  "test": "jest --runInBand",
65
66
  "format": "prettier --write \"*.+(js|json|yml|yaml|ts|md|graphql|mdx)\" src/ test/",
66
67
  "typecheck": "tsc --project tsconfig.test.json --noEmit",