@manuscripts/track-changes-plugin 1.7.0-LEAN-2850 → 1.7.0-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 +77 -49
- package/dist/index.js +77 -49
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -162,14 +162,13 @@ const enableDebug = (enabled) => {
|
|
|
162
162
|
}
|
|
163
163
|
};
|
|
164
164
|
|
|
165
|
-
var
|
|
165
|
+
var _ChangeSet_changes;
|
|
166
166
|
/**
|
|
167
167
|
* ChangeSet is a data structure to contain the tracked changes with some utility methods and computed
|
|
168
168
|
* values to allow easier operability.
|
|
169
169
|
*/
|
|
170
170
|
class ChangeSet {
|
|
171
171
|
constructor(changes = []) {
|
|
172
|
-
_ChangeSet_instances.add(this);
|
|
173
172
|
_ChangeSet_changes.set(this, void 0);
|
|
174
173
|
__classPrivateFieldSet(this, _ChangeSet_changes, changes, "f");
|
|
175
174
|
}
|
|
@@ -200,10 +199,7 @@ class ChangeSet {
|
|
|
200
199
|
rootNodes.push(currentNodeChange);
|
|
201
200
|
currentNodeChange = undefined;
|
|
202
201
|
}
|
|
203
|
-
if (currentNodeChange &&
|
|
204
|
-
c.from < currentNodeChange.to &&
|
|
205
|
-
!(__classPrivateFieldGet(this, _ChangeSet_instances, "m", _ChangeSet_isSameNodeChange).call(this, currentNodeChange, c) &&
|
|
206
|
-
__classPrivateFieldGet(this, _ChangeSet_instances, "m", _ChangeSet_isNotPendingOrDeleted).call(this, currentNodeChange))) {
|
|
202
|
+
if (currentNodeChange && c.from < currentNodeChange.to) {
|
|
207
203
|
currentNodeChange.children.push(c);
|
|
208
204
|
}
|
|
209
205
|
else if (c.type === 'node-change') {
|
|
@@ -325,12 +321,7 @@ class ChangeSet {
|
|
|
325
321
|
return change.type === 'node-attr-change';
|
|
326
322
|
}
|
|
327
323
|
}
|
|
328
|
-
_ChangeSet_changes = new WeakMap()
|
|
329
|
-
return currentChange.from === nextChange.from && currentChange.to === nextChange.to;
|
|
330
|
-
}, _ChangeSet_isNotPendingOrDeleted = function _ChangeSet_isNotPendingOrDeleted(change) {
|
|
331
|
-
return (change.dataTracked.operation !== exports.CHANGE_OPERATION.delete &&
|
|
332
|
-
change.dataTracked.status !== exports.CHANGE_STATUS.pending);
|
|
333
|
-
};
|
|
324
|
+
_ChangeSet_changes = new WeakMap();
|
|
334
325
|
|
|
335
326
|
/*!
|
|
336
327
|
* © 2021 Atypon Systems LLC
|
|
@@ -540,9 +531,7 @@ function updateChangeAttrs(tr, change, trackedAttrs, schema) {
|
|
|
540
531
|
return tr;
|
|
541
532
|
}
|
|
542
533
|
const { operation } = trackedAttrs;
|
|
543
|
-
const oldTrackData = change.type === 'text-change'
|
|
544
|
-
? getTextNodeTrackedMarkData(node, schema)
|
|
545
|
-
: getBlockInlineTrackedData(node);
|
|
534
|
+
const oldTrackData = change.type === 'text-change' ? getTextNodeTrackedMarkData(node, schema) : getBlockInlineTrackedData(node);
|
|
546
535
|
if (!operation) {
|
|
547
536
|
log.warn('updateChangeAttrs: unable to determine operation of change ', change);
|
|
548
537
|
}
|
|
@@ -563,7 +552,15 @@ function updateChangeAttrs(tr, change, trackedAttrs, schema) {
|
|
|
563
552
|
tr.setNodeMarkup(change.from, undefined, { ...node.attrs, dataTracked: null }, node.marks);
|
|
564
553
|
}
|
|
565
554
|
else if (change.type === 'node-change' || change.type === 'node-attr-change') {
|
|
566
|
-
const
|
|
555
|
+
const trackedDataSource = getBlockInlineTrackedData(node) || [];
|
|
556
|
+
const targetDataTracked = trackedDataSource.find((t) => change.id === t.id);
|
|
557
|
+
const newDataTracked = trackedDataSource.map((oldTrack) => {
|
|
558
|
+
if (targetDataTracked) {
|
|
559
|
+
if (oldTrack.id === targetDataTracked.id) {
|
|
560
|
+
return { ...oldTrack, ...trackedAttrs };
|
|
561
|
+
}
|
|
562
|
+
return oldTrack;
|
|
563
|
+
}
|
|
567
564
|
if (oldTrack.operation === operation) {
|
|
568
565
|
return { ...oldTrack, ...trackedAttrs };
|
|
569
566
|
}
|
|
@@ -587,6 +584,13 @@ function updateChangeChildrenAttributes(changes, tr, mapping) {
|
|
|
587
584
|
});
|
|
588
585
|
}
|
|
589
586
|
|
|
587
|
+
function getUpdatedDataTracked(dataTracked, changeId) {
|
|
588
|
+
if (!dataTracked) {
|
|
589
|
+
return null;
|
|
590
|
+
}
|
|
591
|
+
const newDataTracked = dataTracked.filter((c) => c.id !== changeId);
|
|
592
|
+
return newDataTracked.length ? newDataTracked : null;
|
|
593
|
+
}
|
|
590
594
|
/**
|
|
591
595
|
* Applies the accepted/rejected changes in the current document and sets them untracked
|
|
592
596
|
*
|
|
@@ -596,10 +600,12 @@ function updateChangeChildrenAttributes(changes, tr, mapping) {
|
|
|
596
600
|
* @param deleteMap
|
|
597
601
|
*/
|
|
598
602
|
function applyAcceptedRejectedChanges(tr, schema, changes, deleteMap = new prosemirrorTransform.Mapping()) {
|
|
603
|
+
const attrsChangesLog = new Map(); // map of node ids and applied change updatedAt timestamp
|
|
604
|
+
function addAttrLog(nodeId, changeId) {
|
|
605
|
+
const arr = attrsChangesLog.get(nodeId) || attrsChangesLog.set(nodeId, []).get(nodeId);
|
|
606
|
+
arr.push(changeId);
|
|
607
|
+
}
|
|
599
608
|
changes.forEach((change) => {
|
|
600
|
-
if (change.dataTracked.status === exports.CHANGE_STATUS.pending) {
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
609
|
// Map change.from and skip those which dont need to be applied
|
|
604
610
|
// or were already deleted by an applied block delete
|
|
605
611
|
const { pos: from, deleted } = deleteMap.mapResult(change.from), node = tr.doc.nodeAt(from), noChangeNeeded = deleted || !ChangeSet.shouldDeleteChange(change);
|
|
@@ -607,6 +613,24 @@ function applyAcceptedRejectedChanges(tr, schema, changes, deleteMap = new prose
|
|
|
607
613
|
!deleted && log.warn('no node found to update for change', change);
|
|
608
614
|
return;
|
|
609
615
|
}
|
|
616
|
+
if (change.dataTracked.status === exports.CHANGE_STATUS.pending) {
|
|
617
|
+
if (ChangeSet.isNodeAttrChange(change)) {
|
|
618
|
+
/*
|
|
619
|
+
Apply pending changes for attributes as well because applying accepted/rejected changes may override
|
|
620
|
+
pending because we store the most recent change directly on the node attributes. But in case of pending attributes
|
|
621
|
+
we don't need to remove dataTracked record. We need, however, to make sure we don't restore dataTracked records for
|
|
622
|
+
the previously applied changes. To check for already applied changes we log them into "attrsChangesLog" Map.
|
|
623
|
+
*/
|
|
624
|
+
const { dataTracked, attrs } = change.newAttrs;
|
|
625
|
+
const changeLog = attrsChangesLog.get(node.attrs.id);
|
|
626
|
+
const newDataTracked = (changeLog === null || changeLog === void 0 ? void 0 : changeLog.length)
|
|
627
|
+
? dataTracked.filter((c) => !changeLog.includes(c.id))
|
|
628
|
+
: dataTracked;
|
|
629
|
+
tr.setNodeMarkup(from, undefined, { ...attrs, dataTracked: newDataTracked.length ? newDataTracked : null }, node.marks);
|
|
630
|
+
// default is "null" for dataTracked in attrs in pm schema, so codebase generally relies on it being null when empty
|
|
631
|
+
}
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
610
634
|
if (ChangeSet.isTextChange(change) && noChangeNeeded) {
|
|
611
635
|
tr.removeMark(from, deleteMap.map(change.to), schema.marks.tracked_insert);
|
|
612
636
|
tr.removeMark(from, deleteMap.map(change.to), schema.marks.tracked_delete);
|
|
@@ -630,13 +654,13 @@ function applyAcceptedRejectedChanges(tr, schema, changes, deleteMap = new prose
|
|
|
630
654
|
}
|
|
631
655
|
deleteMap.appendMap(tr.steps[tr.steps.length - 1].getMap());
|
|
632
656
|
}
|
|
633
|
-
else if (ChangeSet.isNodeAttrChange(change) &&
|
|
634
|
-
change.dataTracked.
|
|
635
|
-
|
|
657
|
+
else if (ChangeSet.isNodeAttrChange(change) && change.dataTracked.status === exports.CHANGE_STATUS.accepted) {
|
|
658
|
+
tr.setNodeMarkup(from, undefined, { ...change.newAttrs, dataTracked: getUpdatedDataTracked(node.attrs.dataTracked, change.id) }, node.marks);
|
|
659
|
+
addAttrLog(node.attrs.id, change.dataTracked.id);
|
|
636
660
|
}
|
|
637
|
-
else if (ChangeSet.isNodeAttrChange(change) &&
|
|
638
|
-
change.dataTracked.
|
|
639
|
-
|
|
661
|
+
else if (ChangeSet.isNodeAttrChange(change) && change.dataTracked.status === exports.CHANGE_STATUS.rejected) {
|
|
662
|
+
tr.setNodeMarkup(from, undefined, { ...change.oldAttrs, dataTracked: getUpdatedDataTracked(node.attrs.dataTracked, change.id) }, node.marks);
|
|
663
|
+
addAttrLog(node.attrs.id, change.dataTracked.id);
|
|
640
664
|
}
|
|
641
665
|
});
|
|
642
666
|
return deleteMap;
|
|
@@ -961,7 +985,7 @@ function createNewUpdateAttrs(attrs, oldAttrs) {
|
|
|
961
985
|
return {
|
|
962
986
|
...attrs,
|
|
963
987
|
operation: exports.CHANGE_OPERATION.set_node_attributes,
|
|
964
|
-
oldAttrs: restAttrs,
|
|
988
|
+
oldAttrs: JSON.parse(JSON.stringify(restAttrs)),
|
|
965
989
|
};
|
|
966
990
|
}
|
|
967
991
|
|
|
@@ -1212,7 +1236,8 @@ function trackReplaceAroundStep(step, oldState, tr, newTr, attrs) {
|
|
|
1212
1236
|
*/
|
|
1213
1237
|
function trackReplaceStep(step, oldState, newTr, attrs, stepResult, currentStepDoc) {
|
|
1214
1238
|
log.info('###### ReplaceStep ######');
|
|
1215
|
-
let selectionPos = 0
|
|
1239
|
+
let selectionPos = 0;
|
|
1240
|
+
const changeSteps = [];
|
|
1216
1241
|
// Invert the transaction step to prevent it from actually deleting or inserting anything
|
|
1217
1242
|
step.getMap().forEach((fromA, toA, fromB, toB) => {
|
|
1218
1243
|
var _a, _b;
|
|
@@ -1436,21 +1461,32 @@ function processChangeSteps(changes, startPos, newTr, emptyAttrs, schema) {
|
|
|
1436
1461
|
}
|
|
1437
1462
|
else if (c.type === 'update-node-attrs') {
|
|
1438
1463
|
const oldDataTracked = getBlockInlineTrackedData(c.node) || [];
|
|
1439
|
-
const oldUpdate = oldDataTracked.find((d) =>
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1464
|
+
const oldUpdate = oldDataTracked.reverse().find((d) => {
|
|
1465
|
+
// reversing to start from the most recent change
|
|
1466
|
+
if (d.operation === exports.CHANGE_OPERATION.set_node_attributes &&
|
|
1467
|
+
(d.status === exports.CHANGE_STATUS.pending || d.status === exports.CHANGE_STATUS.rejected)) {
|
|
1468
|
+
return true;
|
|
1469
|
+
}
|
|
1470
|
+
return false;
|
|
1471
|
+
});
|
|
1472
|
+
// if the selected last change is with status "rejected" we need to use oldAttrs from it because
|
|
1473
|
+
// node's actual attributes represent the "rejected" values
|
|
1474
|
+
const lastChangeRejected = oldUpdate && oldUpdate.status === exports.CHANGE_STATUS.rejected;
|
|
1475
|
+
const sourceAttrs = (oldUpdate === null || oldUpdate === void 0 ? void 0 : oldUpdate.oldAttrs) || c.node.attrs;
|
|
1476
|
+
const { dataTracked, ...restAttrs } = sourceAttrs;
|
|
1477
|
+
const oldAttrs = lastChangeRejected ? oldUpdate.oldAttrs : restAttrs;
|
|
1478
|
+
const newDataTracked = [
|
|
1479
|
+
...oldDataTracked.filter((d) => !oldUpdate || d.id !== oldUpdate.id || lastChangeRejected),
|
|
1480
|
+
];
|
|
1481
|
+
const newUpdate = oldUpdate && oldUpdate.status !== exports.CHANGE_STATUS.rejected
|
|
1443
1482
|
? {
|
|
1444
1483
|
...oldUpdate,
|
|
1445
1484
|
updatedAt: emptyAttrs.updatedAt,
|
|
1446
1485
|
}
|
|
1447
|
-
: addTrackIdIfDoesntExist(createNewUpdateAttrs(emptyAttrs, c.node.attrs));
|
|
1486
|
+
: addTrackIdIfDoesntExist(createNewUpdateAttrs(emptyAttrs, lastChangeRejected ? oldAttrs : c.node.attrs));
|
|
1448
1487
|
// Dont add update changes if there exists already an insert change for this node
|
|
1449
|
-
if (
|
|
1450
|
-
|
|
1451
|
-
!oldDataTracked.find((d) => (d.operation === exports.CHANGE_OPERATION.insert ||
|
|
1452
|
-
d.operation === exports.CHANGE_OPERATION.set_node_attributes) &&
|
|
1453
|
-
d.status === exports.CHANGE_STATUS.pending)) {
|
|
1488
|
+
if (JSON.stringify(oldAttrs) !== JSON.stringify(c.newAttrs) &&
|
|
1489
|
+
!oldDataTracked.find((d) => d.operation === exports.CHANGE_OPERATION.insert)) {
|
|
1454
1490
|
newDataTracked.push(newUpdate);
|
|
1455
1491
|
}
|
|
1456
1492
|
newTr.setNodeMarkup(mapping.map(c.pos), undefined, {
|
|
@@ -1861,9 +1897,7 @@ const trackChangesPlugin = (opts = { userID: 'anonymous:Anonymous' }) => {
|
|
|
1861
1897
|
},
|
|
1862
1898
|
appendTransaction(trs, oldState, newState) {
|
|
1863
1899
|
const pluginState = trackChangesPluginKey.getState(newState);
|
|
1864
|
-
if (!pluginState ||
|
|
1865
|
-
pluginState.status === exports.TrackChangesStatus.disabled ||
|
|
1866
|
-
!(editorView === null || editorView === void 0 ? void 0 : editorView.editable)) {
|
|
1900
|
+
if (!pluginState || pluginState.status === exports.TrackChangesStatus.disabled || !(editorView === null || editorView === void 0 ? void 0 : editorView.editable)) {
|
|
1867
1901
|
return null;
|
|
1868
1902
|
}
|
|
1869
1903
|
const { userID, changeSet } = pluginState;
|
|
@@ -1872,13 +1906,8 @@ const trackChangesPlugin = (opts = { userID: 'anonymous:Anonymous' }) => {
|
|
|
1872
1906
|
trs.forEach((tr) => {
|
|
1873
1907
|
const wasAppended = tr.getMeta('appendedTransaction');
|
|
1874
1908
|
const skipMetaUsed = skipTrsWithMetas.some((m) => tr.getMeta(m) || (wasAppended === null || wasAppended === void 0 ? void 0 : wasAppended.getMeta(m)));
|
|
1875
|
-
const skipTrackUsed = getAction(tr, TrackChangesAction.skipTrack) ||
|
|
1876
|
-
|
|
1877
|
-
if (tr.docChanged &&
|
|
1878
|
-
!skipMetaUsed &&
|
|
1879
|
-
!skipTrackUsed &&
|
|
1880
|
-
!tr.getMeta('history$') &&
|
|
1881
|
-
!(wasAppended && tr.getMeta('origin') === 'paragraphs')) {
|
|
1909
|
+
const skipTrackUsed = getAction(tr, TrackChangesAction.skipTrack) || (wasAppended && getAction(wasAppended, TrackChangesAction.skipTrack));
|
|
1910
|
+
if (tr.docChanged && !skipMetaUsed && !skipTrackUsed && !tr.getMeta('history$') && !(wasAppended && tr.getMeta('origin') === 'paragraphs')) {
|
|
1882
1911
|
createdTr = trackTransaction(tr, oldState, createdTr, userID);
|
|
1883
1912
|
}
|
|
1884
1913
|
docChanged = docChanged || tr.docChanged;
|
|
@@ -1898,8 +1927,7 @@ const trackChangesPlugin = (opts = { userID: 'anonymous:Anonymous' }) => {
|
|
|
1898
1927
|
setAction(createdTr, TrackChangesAction.refreshChanges, true);
|
|
1899
1928
|
}
|
|
1900
1929
|
});
|
|
1901
|
-
const changed = pluginState.changeSet.hasInconsistentData &&
|
|
1902
|
-
fixInconsistentChanges(pluginState.changeSet, userID, createdTr, oldState.schema);
|
|
1930
|
+
const changed = pluginState.changeSet.hasInconsistentData && fixInconsistentChanges(pluginState.changeSet, userID, createdTr, oldState.schema);
|
|
1903
1931
|
if (changed) {
|
|
1904
1932
|
log.warn('had to fix inconsistent changes in', createdTr);
|
|
1905
1933
|
}
|
package/dist/index.js
CHANGED
|
@@ -154,14 +154,13 @@ const enableDebug = (enabled) => {
|
|
|
154
154
|
}
|
|
155
155
|
};
|
|
156
156
|
|
|
157
|
-
var
|
|
157
|
+
var _ChangeSet_changes;
|
|
158
158
|
/**
|
|
159
159
|
* ChangeSet is a data structure to contain the tracked changes with some utility methods and computed
|
|
160
160
|
* values to allow easier operability.
|
|
161
161
|
*/
|
|
162
162
|
class ChangeSet {
|
|
163
163
|
constructor(changes = []) {
|
|
164
|
-
_ChangeSet_instances.add(this);
|
|
165
164
|
_ChangeSet_changes.set(this, void 0);
|
|
166
165
|
__classPrivateFieldSet(this, _ChangeSet_changes, changes, "f");
|
|
167
166
|
}
|
|
@@ -192,10 +191,7 @@ class ChangeSet {
|
|
|
192
191
|
rootNodes.push(currentNodeChange);
|
|
193
192
|
currentNodeChange = undefined;
|
|
194
193
|
}
|
|
195
|
-
if (currentNodeChange &&
|
|
196
|
-
c.from < currentNodeChange.to &&
|
|
197
|
-
!(__classPrivateFieldGet(this, _ChangeSet_instances, "m", _ChangeSet_isSameNodeChange).call(this, currentNodeChange, c) &&
|
|
198
|
-
__classPrivateFieldGet(this, _ChangeSet_instances, "m", _ChangeSet_isNotPendingOrDeleted).call(this, currentNodeChange))) {
|
|
194
|
+
if (currentNodeChange && c.from < currentNodeChange.to) {
|
|
199
195
|
currentNodeChange.children.push(c);
|
|
200
196
|
}
|
|
201
197
|
else if (c.type === 'node-change') {
|
|
@@ -317,12 +313,7 @@ class ChangeSet {
|
|
|
317
313
|
return change.type === 'node-attr-change';
|
|
318
314
|
}
|
|
319
315
|
}
|
|
320
|
-
_ChangeSet_changes = new WeakMap()
|
|
321
|
-
return currentChange.from === nextChange.from && currentChange.to === nextChange.to;
|
|
322
|
-
}, _ChangeSet_isNotPendingOrDeleted = function _ChangeSet_isNotPendingOrDeleted(change) {
|
|
323
|
-
return (change.dataTracked.operation !== CHANGE_OPERATION.delete &&
|
|
324
|
-
change.dataTracked.status !== CHANGE_STATUS.pending);
|
|
325
|
-
};
|
|
316
|
+
_ChangeSet_changes = new WeakMap();
|
|
326
317
|
|
|
327
318
|
/*!
|
|
328
319
|
* © 2021 Atypon Systems LLC
|
|
@@ -532,9 +523,7 @@ function updateChangeAttrs(tr, change, trackedAttrs, schema) {
|
|
|
532
523
|
return tr;
|
|
533
524
|
}
|
|
534
525
|
const { operation } = trackedAttrs;
|
|
535
|
-
const oldTrackData = change.type === 'text-change'
|
|
536
|
-
? getTextNodeTrackedMarkData(node, schema)
|
|
537
|
-
: getBlockInlineTrackedData(node);
|
|
526
|
+
const oldTrackData = change.type === 'text-change' ? getTextNodeTrackedMarkData(node, schema) : getBlockInlineTrackedData(node);
|
|
538
527
|
if (!operation) {
|
|
539
528
|
log.warn('updateChangeAttrs: unable to determine operation of change ', change);
|
|
540
529
|
}
|
|
@@ -555,7 +544,15 @@ function updateChangeAttrs(tr, change, trackedAttrs, schema) {
|
|
|
555
544
|
tr.setNodeMarkup(change.from, undefined, { ...node.attrs, dataTracked: null }, node.marks);
|
|
556
545
|
}
|
|
557
546
|
else if (change.type === 'node-change' || change.type === 'node-attr-change') {
|
|
558
|
-
const
|
|
547
|
+
const trackedDataSource = getBlockInlineTrackedData(node) || [];
|
|
548
|
+
const targetDataTracked = trackedDataSource.find((t) => change.id === t.id);
|
|
549
|
+
const newDataTracked = trackedDataSource.map((oldTrack) => {
|
|
550
|
+
if (targetDataTracked) {
|
|
551
|
+
if (oldTrack.id === targetDataTracked.id) {
|
|
552
|
+
return { ...oldTrack, ...trackedAttrs };
|
|
553
|
+
}
|
|
554
|
+
return oldTrack;
|
|
555
|
+
}
|
|
559
556
|
if (oldTrack.operation === operation) {
|
|
560
557
|
return { ...oldTrack, ...trackedAttrs };
|
|
561
558
|
}
|
|
@@ -579,6 +576,13 @@ function updateChangeChildrenAttributes(changes, tr, mapping) {
|
|
|
579
576
|
});
|
|
580
577
|
}
|
|
581
578
|
|
|
579
|
+
function getUpdatedDataTracked(dataTracked, changeId) {
|
|
580
|
+
if (!dataTracked) {
|
|
581
|
+
return null;
|
|
582
|
+
}
|
|
583
|
+
const newDataTracked = dataTracked.filter((c) => c.id !== changeId);
|
|
584
|
+
return newDataTracked.length ? newDataTracked : null;
|
|
585
|
+
}
|
|
582
586
|
/**
|
|
583
587
|
* Applies the accepted/rejected changes in the current document and sets them untracked
|
|
584
588
|
*
|
|
@@ -588,10 +592,12 @@ function updateChangeChildrenAttributes(changes, tr, mapping) {
|
|
|
588
592
|
* @param deleteMap
|
|
589
593
|
*/
|
|
590
594
|
function applyAcceptedRejectedChanges(tr, schema, changes, deleteMap = new Mapping()) {
|
|
595
|
+
const attrsChangesLog = new Map(); // map of node ids and applied change updatedAt timestamp
|
|
596
|
+
function addAttrLog(nodeId, changeId) {
|
|
597
|
+
const arr = attrsChangesLog.get(nodeId) || attrsChangesLog.set(nodeId, []).get(nodeId);
|
|
598
|
+
arr.push(changeId);
|
|
599
|
+
}
|
|
591
600
|
changes.forEach((change) => {
|
|
592
|
-
if (change.dataTracked.status === CHANGE_STATUS.pending) {
|
|
593
|
-
return;
|
|
594
|
-
}
|
|
595
601
|
// Map change.from and skip those which dont need to be applied
|
|
596
602
|
// or were already deleted by an applied block delete
|
|
597
603
|
const { pos: from, deleted } = deleteMap.mapResult(change.from), node = tr.doc.nodeAt(from), noChangeNeeded = deleted || !ChangeSet.shouldDeleteChange(change);
|
|
@@ -599,6 +605,24 @@ function applyAcceptedRejectedChanges(tr, schema, changes, deleteMap = new Mappi
|
|
|
599
605
|
!deleted && log.warn('no node found to update for change', change);
|
|
600
606
|
return;
|
|
601
607
|
}
|
|
608
|
+
if (change.dataTracked.status === CHANGE_STATUS.pending) {
|
|
609
|
+
if (ChangeSet.isNodeAttrChange(change)) {
|
|
610
|
+
/*
|
|
611
|
+
Apply pending changes for attributes as well because applying accepted/rejected changes may override
|
|
612
|
+
pending because we store the most recent change directly on the node attributes. But in case of pending attributes
|
|
613
|
+
we don't need to remove dataTracked record. We need, however, to make sure we don't restore dataTracked records for
|
|
614
|
+
the previously applied changes. To check for already applied changes we log them into "attrsChangesLog" Map.
|
|
615
|
+
*/
|
|
616
|
+
const { dataTracked, attrs } = change.newAttrs;
|
|
617
|
+
const changeLog = attrsChangesLog.get(node.attrs.id);
|
|
618
|
+
const newDataTracked = (changeLog === null || changeLog === void 0 ? void 0 : changeLog.length)
|
|
619
|
+
? dataTracked.filter((c) => !changeLog.includes(c.id))
|
|
620
|
+
: dataTracked;
|
|
621
|
+
tr.setNodeMarkup(from, undefined, { ...attrs, dataTracked: newDataTracked.length ? newDataTracked : null }, node.marks);
|
|
622
|
+
// default is "null" for dataTracked in attrs in pm schema, so codebase generally relies on it being null when empty
|
|
623
|
+
}
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
602
626
|
if (ChangeSet.isTextChange(change) && noChangeNeeded) {
|
|
603
627
|
tr.removeMark(from, deleteMap.map(change.to), schema.marks.tracked_insert);
|
|
604
628
|
tr.removeMark(from, deleteMap.map(change.to), schema.marks.tracked_delete);
|
|
@@ -622,13 +646,13 @@ function applyAcceptedRejectedChanges(tr, schema, changes, deleteMap = new Mappi
|
|
|
622
646
|
}
|
|
623
647
|
deleteMap.appendMap(tr.steps[tr.steps.length - 1].getMap());
|
|
624
648
|
}
|
|
625
|
-
else if (ChangeSet.isNodeAttrChange(change) &&
|
|
626
|
-
change.dataTracked.
|
|
627
|
-
|
|
649
|
+
else if (ChangeSet.isNodeAttrChange(change) && change.dataTracked.status === CHANGE_STATUS.accepted) {
|
|
650
|
+
tr.setNodeMarkup(from, undefined, { ...change.newAttrs, dataTracked: getUpdatedDataTracked(node.attrs.dataTracked, change.id) }, node.marks);
|
|
651
|
+
addAttrLog(node.attrs.id, change.dataTracked.id);
|
|
628
652
|
}
|
|
629
|
-
else if (ChangeSet.isNodeAttrChange(change) &&
|
|
630
|
-
change.dataTracked.
|
|
631
|
-
|
|
653
|
+
else if (ChangeSet.isNodeAttrChange(change) && change.dataTracked.status === CHANGE_STATUS.rejected) {
|
|
654
|
+
tr.setNodeMarkup(from, undefined, { ...change.oldAttrs, dataTracked: getUpdatedDataTracked(node.attrs.dataTracked, change.id) }, node.marks);
|
|
655
|
+
addAttrLog(node.attrs.id, change.dataTracked.id);
|
|
632
656
|
}
|
|
633
657
|
});
|
|
634
658
|
return deleteMap;
|
|
@@ -953,7 +977,7 @@ function createNewUpdateAttrs(attrs, oldAttrs) {
|
|
|
953
977
|
return {
|
|
954
978
|
...attrs,
|
|
955
979
|
operation: CHANGE_OPERATION.set_node_attributes,
|
|
956
|
-
oldAttrs: restAttrs,
|
|
980
|
+
oldAttrs: JSON.parse(JSON.stringify(restAttrs)),
|
|
957
981
|
};
|
|
958
982
|
}
|
|
959
983
|
|
|
@@ -1204,7 +1228,8 @@ function trackReplaceAroundStep(step, oldState, tr, newTr, attrs) {
|
|
|
1204
1228
|
*/
|
|
1205
1229
|
function trackReplaceStep(step, oldState, newTr, attrs, stepResult, currentStepDoc) {
|
|
1206
1230
|
log.info('###### ReplaceStep ######');
|
|
1207
|
-
let selectionPos = 0
|
|
1231
|
+
let selectionPos = 0;
|
|
1232
|
+
const changeSteps = [];
|
|
1208
1233
|
// Invert the transaction step to prevent it from actually deleting or inserting anything
|
|
1209
1234
|
step.getMap().forEach((fromA, toA, fromB, toB) => {
|
|
1210
1235
|
var _a, _b;
|
|
@@ -1428,21 +1453,32 @@ function processChangeSteps(changes, startPos, newTr, emptyAttrs, schema) {
|
|
|
1428
1453
|
}
|
|
1429
1454
|
else if (c.type === 'update-node-attrs') {
|
|
1430
1455
|
const oldDataTracked = getBlockInlineTrackedData(c.node) || [];
|
|
1431
|
-
const oldUpdate = oldDataTracked.find((d) =>
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1456
|
+
const oldUpdate = oldDataTracked.reverse().find((d) => {
|
|
1457
|
+
// reversing to start from the most recent change
|
|
1458
|
+
if (d.operation === CHANGE_OPERATION.set_node_attributes &&
|
|
1459
|
+
(d.status === CHANGE_STATUS.pending || d.status === CHANGE_STATUS.rejected)) {
|
|
1460
|
+
return true;
|
|
1461
|
+
}
|
|
1462
|
+
return false;
|
|
1463
|
+
});
|
|
1464
|
+
// if the selected last change is with status "rejected" we need to use oldAttrs from it because
|
|
1465
|
+
// node's actual attributes represent the "rejected" values
|
|
1466
|
+
const lastChangeRejected = oldUpdate && oldUpdate.status === CHANGE_STATUS.rejected;
|
|
1467
|
+
const sourceAttrs = (oldUpdate === null || oldUpdate === void 0 ? void 0 : oldUpdate.oldAttrs) || c.node.attrs;
|
|
1468
|
+
const { dataTracked, ...restAttrs } = sourceAttrs;
|
|
1469
|
+
const oldAttrs = lastChangeRejected ? oldUpdate.oldAttrs : restAttrs;
|
|
1470
|
+
const newDataTracked = [
|
|
1471
|
+
...oldDataTracked.filter((d) => !oldUpdate || d.id !== oldUpdate.id || lastChangeRejected),
|
|
1472
|
+
];
|
|
1473
|
+
const newUpdate = oldUpdate && oldUpdate.status !== CHANGE_STATUS.rejected
|
|
1435
1474
|
? {
|
|
1436
1475
|
...oldUpdate,
|
|
1437
1476
|
updatedAt: emptyAttrs.updatedAt,
|
|
1438
1477
|
}
|
|
1439
|
-
: addTrackIdIfDoesntExist(createNewUpdateAttrs(emptyAttrs, c.node.attrs));
|
|
1478
|
+
: addTrackIdIfDoesntExist(createNewUpdateAttrs(emptyAttrs, lastChangeRejected ? oldAttrs : c.node.attrs));
|
|
1440
1479
|
// Dont add update changes if there exists already an insert change for this node
|
|
1441
|
-
if (
|
|
1442
|
-
|
|
1443
|
-
!oldDataTracked.find((d) => (d.operation === CHANGE_OPERATION.insert ||
|
|
1444
|
-
d.operation === CHANGE_OPERATION.set_node_attributes) &&
|
|
1445
|
-
d.status === CHANGE_STATUS.pending)) {
|
|
1480
|
+
if (JSON.stringify(oldAttrs) !== JSON.stringify(c.newAttrs) &&
|
|
1481
|
+
!oldDataTracked.find((d) => d.operation === CHANGE_OPERATION.insert)) {
|
|
1446
1482
|
newDataTracked.push(newUpdate);
|
|
1447
1483
|
}
|
|
1448
1484
|
newTr.setNodeMarkup(mapping.map(c.pos), undefined, {
|
|
@@ -1853,9 +1889,7 @@ const trackChangesPlugin = (opts = { userID: 'anonymous:Anonymous' }) => {
|
|
|
1853
1889
|
},
|
|
1854
1890
|
appendTransaction(trs, oldState, newState) {
|
|
1855
1891
|
const pluginState = trackChangesPluginKey.getState(newState);
|
|
1856
|
-
if (!pluginState ||
|
|
1857
|
-
pluginState.status === TrackChangesStatus.disabled ||
|
|
1858
|
-
!(editorView === null || editorView === void 0 ? void 0 : editorView.editable)) {
|
|
1892
|
+
if (!pluginState || pluginState.status === TrackChangesStatus.disabled || !(editorView === null || editorView === void 0 ? void 0 : editorView.editable)) {
|
|
1859
1893
|
return null;
|
|
1860
1894
|
}
|
|
1861
1895
|
const { userID, changeSet } = pluginState;
|
|
@@ -1864,13 +1898,8 @@ const trackChangesPlugin = (opts = { userID: 'anonymous:Anonymous' }) => {
|
|
|
1864
1898
|
trs.forEach((tr) => {
|
|
1865
1899
|
const wasAppended = tr.getMeta('appendedTransaction');
|
|
1866
1900
|
const skipMetaUsed = skipTrsWithMetas.some((m) => tr.getMeta(m) || (wasAppended === null || wasAppended === void 0 ? void 0 : wasAppended.getMeta(m)));
|
|
1867
|
-
const skipTrackUsed = getAction(tr, TrackChangesAction.skipTrack) ||
|
|
1868
|
-
|
|
1869
|
-
if (tr.docChanged &&
|
|
1870
|
-
!skipMetaUsed &&
|
|
1871
|
-
!skipTrackUsed &&
|
|
1872
|
-
!tr.getMeta('history$') &&
|
|
1873
|
-
!(wasAppended && tr.getMeta('origin') === 'paragraphs')) {
|
|
1901
|
+
const skipTrackUsed = getAction(tr, TrackChangesAction.skipTrack) || (wasAppended && getAction(wasAppended, TrackChangesAction.skipTrack));
|
|
1902
|
+
if (tr.docChanged && !skipMetaUsed && !skipTrackUsed && !tr.getMeta('history$') && !(wasAppended && tr.getMeta('origin') === 'paragraphs')) {
|
|
1874
1903
|
createdTr = trackTransaction(tr, oldState, createdTr, userID);
|
|
1875
1904
|
}
|
|
1876
1905
|
docChanged = docChanged || tr.docChanged;
|
|
@@ -1890,8 +1919,7 @@ const trackChangesPlugin = (opts = { userID: 'anonymous:Anonymous' }) => {
|
|
|
1890
1919
|
setAction(createdTr, TrackChangesAction.refreshChanges, true);
|
|
1891
1920
|
}
|
|
1892
1921
|
});
|
|
1893
|
-
const changed = pluginState.changeSet.hasInconsistentData &&
|
|
1894
|
-
fixInconsistentChanges(pluginState.changeSet, userID, createdTr, oldState.schema);
|
|
1922
|
+
const changed = pluginState.changeSet.hasInconsistentData && fixInconsistentChanges(pluginState.changeSet, userID, createdTr, oldState.schema);
|
|
1895
1923
|
if (changed) {
|
|
1896
1924
|
log.warn('had to fix inconsistent changes in', createdTr);
|
|
1897
1925
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manuscripts/track-changes-plugin",
|
|
3
|
-
"version": "1.7.0-LEAN-
|
|
3
|
+
"version": "1.7.0-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",
|