@manuscripts/track-changes-plugin 2.0.10 → 2.0.12
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/cjs/ChangeSet.js +17 -0
- package/dist/cjs/actions.js +2 -0
- package/dist/cjs/change-steps/processChangeSteps.js +16 -9
- package/dist/cjs/changes/applyChanges.js +56 -12
- package/dist/cjs/changes/updateChangeAttrs.js +7 -0
- package/dist/cjs/changes/updateChangesStatus.js +2 -2
- package/dist/cjs/compute/setFragmentAsInserted.js +2 -2
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/mutate/deleteNode.js +20 -2
- package/dist/cjs/mutate/dropStructureChange.js +106 -0
- package/dist/cjs/steps/trackReplaceStep.js +13 -8
- package/dist/cjs/steps/trackTransaction.js +30 -7
- package/dist/cjs/types/change.js +1 -0
- package/dist/cjs/utils/track-utils.js +35 -4
- package/dist/es/ChangeSet.js +17 -0
- package/dist/es/actions.js +2 -0
- package/dist/es/change-steps/processChangeSteps.js +16 -9
- package/dist/es/changes/applyChanges.js +58 -14
- package/dist/es/changes/updateChangeAttrs.js +6 -0
- package/dist/es/changes/updateChangesStatus.js +2 -2
- package/dist/es/compute/setFragmentAsInserted.js +2 -2
- package/dist/es/index.js +1 -1
- package/dist/es/mutate/deleteNode.js +18 -2
- package/dist/es/mutate/dropStructureChange.js +100 -0
- package/dist/es/steps/trackReplaceStep.js +14 -9
- package/dist/es/steps/trackTransaction.js +31 -8
- package/dist/es/types/change.js +1 -0
- package/dist/es/utils/track-utils.js +31 -3
- package/dist/types/ChangeSet.d.ts +2 -1
- package/dist/types/actions.d.ts +8 -2
- package/dist/types/changes/updateChangeAttrs.d.ts +1 -0
- package/dist/types/compute/setFragmentAsInserted.d.ts +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/mutate/deleteNode.d.ts +1 -0
- package/dist/types/mutate/dropStructureChange.d.ts +6 -0
- package/dist/types/types/change.d.ts +8 -2
- package/dist/types/types/track.d.ts +6 -2
- package/dist/types/utils/track-utils.d.ts +6 -3
- package/package.json +1 -1
|
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.filterMeaninglessMoveSteps = exports.handleDirectPendingMoveDeletions = exports.isDirectPendingMoveDeletion = exports.isDeletingPendingMovedNode = exports.isPendingChange = exports.HasMoveOperations = exports.trFromHistory = exports.isLiftStep = exports.isWrapStep = exports.isSplitStep = void 0;
|
|
14
|
+
exports.updateBlockNodesAttrs = exports.filterMeaninglessMoveSteps = exports.handleDirectPendingMoveDeletions = exports.isDirectPendingMoveDeletion = exports.isDeletingPendingMovedNode = exports.isPendingChange = exports.HasMoveOperations = exports.trFromHistory = exports.isStructureSteps = exports.isLiftStep = exports.isWrapStep = exports.isSplitStep = void 0;
|
|
15
15
|
exports.createNewInsertAttrs = createNewInsertAttrs;
|
|
16
16
|
exports.createNewWrapAttrs = createNewWrapAttrs;
|
|
17
17
|
exports.createNewSplitAttrs = createNewSplitAttrs;
|
|
@@ -19,8 +19,11 @@ exports.createNewReferenceAttrs = createNewReferenceAttrs;
|
|
|
19
19
|
exports.createNewDeleteAttrs = createNewDeleteAttrs;
|
|
20
20
|
exports.createNewMoveAttrs = createNewMoveAttrs;
|
|
21
21
|
exports.createNewUpdateAttrs = createNewUpdateAttrs;
|
|
22
|
+
exports.createNewStructureAttrs = createNewStructureAttrs;
|
|
22
23
|
exports.stepIsLift = stepIsLift;
|
|
24
|
+
const prosemirror_model_1 = require("prosemirror-model");
|
|
23
25
|
const prosemirror_transform_1 = require("prosemirror-transform");
|
|
26
|
+
const actions_1 = require("../actions");
|
|
24
27
|
const change_1 = require("../types/change");
|
|
25
28
|
const uuidv4_1 = require("./uuidv4");
|
|
26
29
|
function createNewInsertAttrs(attrs) {
|
|
@@ -38,13 +41,16 @@ function createNewReferenceAttrs(attrs, id) {
|
|
|
38
41
|
function createNewDeleteAttrs(attrs) {
|
|
39
42
|
return Object.assign(Object.assign({}, attrs), { operation: change_1.CHANGE_OPERATION.delete });
|
|
40
43
|
}
|
|
41
|
-
function createNewMoveAttrs(attrs) {
|
|
42
|
-
return Object.assign(Object.assign({}, attrs), { operation: change_1.CHANGE_OPERATION.move });
|
|
44
|
+
function createNewMoveAttrs(attrs, indentationType) {
|
|
45
|
+
return Object.assign(Object.assign(Object.assign({}, attrs), { operation: change_1.CHANGE_OPERATION.move }), (indentationType && { indentationType }));
|
|
43
46
|
}
|
|
44
47
|
function createNewUpdateAttrs(attrs, oldAttrs) {
|
|
45
48
|
const { dataTracked } = oldAttrs, restAttrs = __rest(oldAttrs, ["dataTracked"]);
|
|
46
49
|
return Object.assign(Object.assign({}, attrs), { operation: change_1.CHANGE_OPERATION.set_node_attributes, oldAttrs: JSON.parse(JSON.stringify(restAttrs)) });
|
|
47
50
|
}
|
|
51
|
+
function createNewStructureAttrs(attrs) {
|
|
52
|
+
return Object.assign(Object.assign({}, attrs), { operation: change_1.CHANGE_OPERATION.structure });
|
|
53
|
+
}
|
|
48
54
|
const isSplitStep = (step, selection, uiEvent) => {
|
|
49
55
|
var _a, _b, _c, _d;
|
|
50
56
|
const { from, to, slice } = step;
|
|
@@ -89,6 +95,11 @@ exports.isLiftStep = isLiftStep;
|
|
|
89
95
|
function stepIsLift(gap, node, to) {
|
|
90
96
|
return gap.start < gap.end && gap.insert === 0 && gap.end === to && !node.isText;
|
|
91
97
|
}
|
|
98
|
+
const isStructureSteps = (tr) => tr.getMeta(actions_1.TrackChangesAction.structuralChangeAction) &&
|
|
99
|
+
tr.steps.length === 2 &&
|
|
100
|
+
tr.steps[0] instanceof prosemirror_transform_1.ReplaceStep &&
|
|
101
|
+
tr.steps[1] instanceof prosemirror_transform_1.ReplaceStep;
|
|
102
|
+
exports.isStructureSteps = isStructureSteps;
|
|
92
103
|
const trFromHistory = (tr) => Object.keys(tr.meta).find((s) => s.startsWith('history$'));
|
|
93
104
|
exports.trFromHistory = trFromHistory;
|
|
94
105
|
const HasMoveOperations = (tr) => {
|
|
@@ -96,6 +107,12 @@ const HasMoveOperations = (tr) => {
|
|
|
96
107
|
if (tr.steps.length < 2) {
|
|
97
108
|
return movingAssoc;
|
|
98
109
|
}
|
|
110
|
+
if (tr.getMeta(actions_1.TrackChangesAction.structuralChangeAction)) {
|
|
111
|
+
const commonID = (0, uuidv4_1.uuidv4)();
|
|
112
|
+
movingAssoc.set(tr.steps[0], commonID);
|
|
113
|
+
movingAssoc.set(tr.steps[1], commonID);
|
|
114
|
+
return movingAssoc;
|
|
115
|
+
}
|
|
99
116
|
const matched = [];
|
|
100
117
|
for (let i = 0; i < tr.steps.length; i++) {
|
|
101
118
|
if (matched.includes(i)) {
|
|
@@ -211,7 +228,7 @@ const filterMeaninglessMoveSteps = (tr, movingSteps) => {
|
|
|
211
228
|
});
|
|
212
229
|
continue;
|
|
213
230
|
}
|
|
214
|
-
if (step instanceof prosemirror_transform_1.ReplaceStep) {
|
|
231
|
+
if (step instanceof prosemirror_transform_1.ReplaceStep && !tr.getMeta(actions_1.TrackChangesAction.structuralChangeAction)) {
|
|
215
232
|
const { slice } = step;
|
|
216
233
|
if ((_a = slice === null || slice === void 0 ? void 0 : slice.content) === null || _a === void 0 ? void 0 : _a.firstChild) {
|
|
217
234
|
const insertedNode = slice.content.firstChild;
|
|
@@ -229,3 +246,17 @@ const filterMeaninglessMoveSteps = (tr, movingSteps) => {
|
|
|
229
246
|
return cleanSteps;
|
|
230
247
|
};
|
|
231
248
|
exports.filterMeaninglessMoveSteps = filterMeaninglessMoveSteps;
|
|
249
|
+
const updateBlockNodesAttrs = (fragment, predicate) => {
|
|
250
|
+
const updatedNodes = [];
|
|
251
|
+
fragment.forEach((child) => {
|
|
252
|
+
if (!child.isBlock) {
|
|
253
|
+
updatedNodes.push(child);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const newContent = child.content.size ? (0, exports.updateBlockNodesAttrs)(child.content, predicate) : child.content;
|
|
257
|
+
const newAttrs = predicate(child.attrs, child);
|
|
258
|
+
updatedNodes.push(child.type.create(newAttrs, newContent, child.marks));
|
|
259
|
+
});
|
|
260
|
+
return prosemirror_model_1.Fragment.fromArray(updatedNodes);
|
|
261
|
+
};
|
|
262
|
+
exports.updateBlockNodesAttrs = updateBlockNodesAttrs;
|
package/dist/es/ChangeSet.js
CHANGED
|
@@ -86,6 +86,9 @@ export class ChangeSet {
|
|
|
86
86
|
currentInlineChange = undefined;
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
|
+
if (this.joinRelatedStructuralChanges(rootNodes, change)) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
89
92
|
rootNodes.push([change]);
|
|
90
93
|
});
|
|
91
94
|
return rootNodes.filter((changes) => changes.filter((c) => c.dataTracked.operation !== CHANGE_OPERATION.reference &&
|
|
@@ -158,6 +161,20 @@ export class ChangeSet {
|
|
|
158
161
|
change.to === nextChange.from &&
|
|
159
162
|
hasMatchingOperation(change, nextChange));
|
|
160
163
|
}
|
|
164
|
+
joinRelatedStructuralChanges(rootNodes, change) {
|
|
165
|
+
if (change.dataTracked.operation !== CHANGE_OPERATION.structure) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const index = rootNodes.findIndex((c) => c[0].dataTracked.operation === CHANGE_OPERATION.structure &&
|
|
169
|
+
c[0].dataTracked.moveNodeId === change.dataTracked.moveNodeId);
|
|
170
|
+
if (index !== -1) {
|
|
171
|
+
rootNodes[index] = [...rootNodes[index], change];
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
rootNodes.push([change]);
|
|
175
|
+
}
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
161
178
|
static flattenTreeToIds(changes) {
|
|
162
179
|
return changes.flatMap((c) => (this.isNodeChange(c) ? [c.id, ...c.children.map((c) => c.id)] : c.id));
|
|
163
180
|
}
|
package/dist/es/actions.js
CHANGED
|
@@ -6,6 +6,8 @@ export var TrackChangesAction;
|
|
|
6
6
|
TrackChangesAction["setChangeStatuses"] = "track-changes-set-change-statuses";
|
|
7
7
|
TrackChangesAction["refreshChanges"] = "track-changes-refresh-changes";
|
|
8
8
|
TrackChangesAction["updateMetaNode"] = "track-changes-update-meta-node";
|
|
9
|
+
TrackChangesAction["structuralChangeAction"] = "track-changes-structural-change-action";
|
|
10
|
+
TrackChangesAction["indentationAction"] = "track-changes-indentation-action";
|
|
9
11
|
})(TrackChangesAction || (TrackChangesAction = {}));
|
|
10
12
|
export function hasAction(tr) {
|
|
11
13
|
return Object.values(TrackChangesAction).some((action) => !!tr.getMeta(action));
|
|
@@ -23,7 +23,7 @@ export function processChangeSteps(changes, startPos, newTr, emptyAttrs, schema,
|
|
|
23
23
|
let selectionPos = startPos;
|
|
24
24
|
let deletesCounter = 0;
|
|
25
25
|
let isInserted = false;
|
|
26
|
-
let
|
|
26
|
+
let prevDelete;
|
|
27
27
|
changes.forEach((c) => {
|
|
28
28
|
let step = newTr.steps[newTr.steps.length - 1];
|
|
29
29
|
switch (c.type) {
|
|
@@ -32,10 +32,12 @@ export function processChangeSteps(changes, startPos, newTr, emptyAttrs, schema,
|
|
|
32
32
|
const prevDeletedNodeInserted = isInserted;
|
|
33
33
|
const trackedData = getBlockInlineTrackedData(c.node);
|
|
34
34
|
const inserted = trackedData === null || trackedData === void 0 ? void 0 : trackedData.find((d) => d.operation === CHANGE_OPERATION.insert);
|
|
35
|
-
|
|
35
|
+
const structure = trackedData === null || trackedData === void 0 ? void 0 : trackedData.find((c) => c.operation === CHANGE_OPERATION.structure &&
|
|
36
|
+
deleteAttrs.moveNodeId &&
|
|
37
|
+
c.moveNodeId !== deleteAttrs.moveNodeId);
|
|
36
38
|
let childOfDeleted = false;
|
|
37
|
-
if (
|
|
38
|
-
|
|
39
|
+
if (prevDelete) {
|
|
40
|
+
prevDelete.node.descendants((node) => {
|
|
39
41
|
if (childOfDeleted) {
|
|
40
42
|
return false;
|
|
41
43
|
}
|
|
@@ -44,15 +46,20 @@ export function processChangeSteps(changes, startPos, newTr, emptyAttrs, schema,
|
|
|
44
46
|
}
|
|
45
47
|
});
|
|
46
48
|
}
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
const isMoveOperation = !!emptyAttrs.moveNodeId;
|
|
50
|
+
if ((prevDelete &&
|
|
51
|
+
c.pos < prevDelete.nodeEnd &&
|
|
52
|
+
isInserted &&
|
|
53
|
+
deletesCounter > 1 &&
|
|
54
|
+
!isMoveOperation) ||
|
|
55
|
+
(childOfDeleted && prevDeletedNodeInserted)) {
|
|
50
56
|
return false;
|
|
51
57
|
}
|
|
52
58
|
deleteOrSetNodeDeleted(c.node, mapping.map(c.pos), newTr, deleteAttrs);
|
|
53
|
-
|
|
59
|
+
prevDelete = c;
|
|
60
|
+
isInserted = !!inserted || !!structure || (!trackedData && isInserted);
|
|
54
61
|
const newestStep = newTr.steps[newTr.steps.length - 1];
|
|
55
|
-
if (isInserted) {
|
|
62
|
+
if (isInserted || structure) {
|
|
56
63
|
deletedNodeMapping.appendMap(newestStep.getMap());
|
|
57
64
|
}
|
|
58
65
|
if (step !== newestStep) {
|
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
import { Mapping } from 'prosemirror-transform';
|
|
2
2
|
import { ChangeSet } from '../ChangeSet';
|
|
3
|
-
import { deleteNode } from '../mutate/deleteNode';
|
|
3
|
+
import { deleteNode, keepDeleteWithMoveNodeId } from '../mutate/deleteNode';
|
|
4
4
|
import { mergeNode } from '../mutate/mergeNode';
|
|
5
5
|
import { CHANGE_OPERATION, CHANGE_STATUS } from '../types/change';
|
|
6
6
|
import { log } from '../utils/logger';
|
|
7
7
|
import { revertSplitNodeChange, revertWrapNodeChange } from './revertChange';
|
|
8
|
-
import { updateChangeChildrenAttributes } from './updateChangeAttrs';
|
|
8
|
+
import { restoreNode, updateChangeChildrenAttributes } from './updateChangeAttrs';
|
|
9
|
+
function collectMoveNodeIds(containerNode, primaryMoveNodeId) {
|
|
10
|
+
const moveNodeIds = new Set();
|
|
11
|
+
moveNodeIds.add(primaryMoveNodeId);
|
|
12
|
+
containerNode.descendants((childNode) => {
|
|
13
|
+
const dataTracked = childNode.attrs.dataTracked;
|
|
14
|
+
if (Array.isArray(dataTracked)) {
|
|
15
|
+
dataTracked.forEach((trackingData) => {
|
|
16
|
+
if (trackingData.moveNodeId) {
|
|
17
|
+
moveNodeIds.add(trackingData.moveNodeId);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
return moveNodeIds;
|
|
23
|
+
}
|
|
9
24
|
export function getUpdatedDataTracked(dataTracked, changeId) {
|
|
10
25
|
if (!dataTracked) {
|
|
11
26
|
return null;
|
|
@@ -22,7 +37,11 @@ export function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, del
|
|
|
22
37
|
return c1.dataTracked.updatedAt - c2.dataTracked.updatedAt;
|
|
23
38
|
});
|
|
24
39
|
changes.forEach((change) => {
|
|
25
|
-
if (change.dataTracked.operation === CHANGE_OPERATION.move
|
|
40
|
+
if (change.dataTracked.operation === CHANGE_OPERATION.move ||
|
|
41
|
+
change.dataTracked.operation === CHANGE_OPERATION.structure) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (change.dataTracked.operation === CHANGE_OPERATION.delete && change.dataTracked.moveNodeId) {
|
|
26
45
|
return;
|
|
27
46
|
}
|
|
28
47
|
const { pos: from, deleted } = deleteMap.mapResult(change.from);
|
|
@@ -52,7 +71,7 @@ export function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, del
|
|
|
52
71
|
deleteMap.appendMap(tr.steps[tr.steps.length - 1].getMap());
|
|
53
72
|
}
|
|
54
73
|
else if (ChangeSet.isNodeChange(change) && noChangeNeeded) {
|
|
55
|
-
const attrs = Object.assign(Object.assign({}, node.attrs), { dataTracked:
|
|
74
|
+
const attrs = Object.assign(Object.assign({}, node.attrs), { dataTracked: keepDeleteWithMoveNodeId(node) });
|
|
56
75
|
tr.setNodeMarkup(from, undefined, attrs, node.marks);
|
|
57
76
|
if (node.isAtom) {
|
|
58
77
|
tr.removeMark(from, deleteMap.map(change.to), schema.marks.tracked_insert);
|
|
@@ -78,7 +97,8 @@ export function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, del
|
|
|
78
97
|
}
|
|
79
98
|
});
|
|
80
99
|
changes.forEach((change) => {
|
|
81
|
-
if (change.dataTracked.operation !== CHANGE_OPERATION.move
|
|
100
|
+
if (change.dataTracked.operation !== CHANGE_OPERATION.move &&
|
|
101
|
+
change.dataTracked.operation !== CHANGE_OPERATION.structure) {
|
|
82
102
|
return;
|
|
83
103
|
}
|
|
84
104
|
const { pos: from, deleted } = deleteMap.mapResult(change.from);
|
|
@@ -90,25 +110,49 @@ export function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, del
|
|
|
90
110
|
return;
|
|
91
111
|
}
|
|
92
112
|
if (change.dataTracked.status === CHANGE_STATUS.accepted) {
|
|
93
|
-
const
|
|
113
|
+
const attrs = Object.assign(Object.assign({}, node.attrs), { dataTracked: getUpdatedDataTracked(node.attrs.dataTracked, change.id) });
|
|
114
|
+
tr.setNodeMarkup(from, undefined, attrs, node.marks);
|
|
115
|
+
const originalChanges = changeSet.changes.filter((c) => c.dataTracked.moveNodeId === change.dataTracked.moveNodeId &&
|
|
94
116
|
c.dataTracked.operation === CHANGE_OPERATION.delete);
|
|
95
|
-
if (
|
|
96
|
-
|
|
117
|
+
if (originalChanges.length === 0) {
|
|
118
|
+
log.warn('No original change found for move operation', { change });
|
|
119
|
+
}
|
|
120
|
+
originalChanges.forEach((originalChange) => {
|
|
121
|
+
const { pos: originalFrom, deleted } = deleteMap.mapResult(originalChange.from);
|
|
122
|
+
if (deleted) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
97
125
|
const originalNode = tr.doc.nodeAt(originalFrom);
|
|
98
|
-
const attrs = Object.assign(Object.assign({}, node.attrs), { dataTracked: getUpdatedDataTracked(node.attrs.dataTracked, change.id) });
|
|
99
|
-
tr.setNodeMarkup(from, undefined, attrs, node.marks);
|
|
100
126
|
if (originalNode) {
|
|
101
127
|
tr.delete(originalFrom, originalFrom + originalNode.nodeSize);
|
|
102
128
|
deleteMap.appendMap(tr.steps[tr.steps.length - 1].getMap());
|
|
103
129
|
}
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
log.warn('No original change found for move operation', { change });
|
|
107
|
-
}
|
|
130
|
+
});
|
|
108
131
|
}
|
|
109
132
|
else if (change.dataTracked.status === CHANGE_STATUS.rejected) {
|
|
133
|
+
const moveNodeIdsToRestore = collectMoveNodeIds(node, change.dataTracked.moveNodeId);
|
|
110
134
|
tr.delete(from, from + node.nodeSize);
|
|
111
135
|
deleteMap.appendMap(tr.steps[tr.steps.length - 1].getMap());
|
|
136
|
+
changeSet.changes
|
|
137
|
+
.filter((c) => c.dataTracked.operation === CHANGE_OPERATION.delete &&
|
|
138
|
+
c.dataTracked.moveNodeId &&
|
|
139
|
+
moveNodeIdsToRestore.has(c.dataTracked.moveNodeId) &&
|
|
140
|
+
ChangeSet.isNodeChange(c))
|
|
141
|
+
.forEach((orig) => {
|
|
142
|
+
const { pos } = deleteMap.mapResult(orig.from);
|
|
143
|
+
const node = tr.doc.nodeAt(pos);
|
|
144
|
+
if (!node) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const dataTracked = node.attrs.dataTracked || [];
|
|
148
|
+
const hasMoved = dataTracked.some((d) => d.operation === CHANGE_OPERATION.move && d.status === CHANGE_STATUS.pending);
|
|
149
|
+
if (hasMoved) {
|
|
150
|
+
tr.delete(pos, pos + node.nodeSize);
|
|
151
|
+
deleteMap.appendMap(tr.steps[tr.steps.length - 1].getMap());
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
restoreNode(tr, node, pos, schema);
|
|
155
|
+
});
|
|
112
156
|
}
|
|
113
157
|
});
|
|
114
158
|
return deleteMap;
|
|
@@ -79,3 +79,9 @@ export function updateChangeChildrenAttributes(changes, tr, mapping) {
|
|
|
79
79
|
}
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
|
+
export function restoreNode(tr, node, pos, schema) {
|
|
83
|
+
const updatedAttrs = Object.assign(Object.assign({}, node.attrs), { dataTracked: null });
|
|
84
|
+
tr.setNodeMarkup(pos, undefined, updatedAttrs, node.marks);
|
|
85
|
+
tr.removeMark(pos, pos + node.nodeSize, schema.marks.tracked_insert);
|
|
86
|
+
tr.removeMark(pos, pos + node.nodeSize, schema.marks.tracked_delete);
|
|
87
|
+
}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { closeHistory } from 'prosemirror-history';
|
|
17
17
|
import { ChangeSet } from '../ChangeSet';
|
|
18
|
+
import { dropOrphanChanges } from '../mutate/dropStructureChange';
|
|
18
19
|
import { CHANGE_OPERATION, CHANGE_STATUS } from '../types/change';
|
|
19
20
|
import { applyAcceptedRejectedChanges } from './applyChanges';
|
|
20
21
|
import { updateChangeAttrs } from './updateChangeAttrs';
|
|
@@ -43,9 +44,7 @@ export function updateChangesStatus(createdTr, changeSet, ids, status, userID, o
|
|
|
43
44
|
c.dataTracked.operation === 'delete' &&
|
|
44
45
|
c.dataTracked.moveNodeId === change.dataTracked.moveNodeId);
|
|
45
46
|
if (oldChange && ChangeSet.isNodeChange(oldChange)) {
|
|
46
|
-
createdTr = updateChangeAttrs(createdTr, oldChange, Object.assign(Object.assign({}, oldChange.dataTracked), { status, statusUpdateAt: changeTime, reviewedByID: userID }), oldState.schema);
|
|
47
47
|
oldChange.children.forEach((child) => {
|
|
48
|
-
createdTr = updateChangeAttrs(createdTr, child, Object.assign(Object.assign({}, child.dataTracked), { status, statusUpdateAt: changeTime, reviewedByID: userID }), oldState.schema);
|
|
49
48
|
if (ChangeSet.isTextChange(child)) {
|
|
50
49
|
textChanges.push(child);
|
|
51
50
|
}
|
|
@@ -61,6 +60,7 @@ export function updateChangesStatus(createdTr, changeSet, ids, status, userID, o
|
|
|
61
60
|
});
|
|
62
61
|
const mapping = applyAcceptedRejectedChanges(createdTr, oldState.schema, nonTextChanges, changeSet);
|
|
63
62
|
applyAcceptedRejectedChanges(createdTr, oldState.schema, textChanges, changeSet, mapping);
|
|
63
|
+
dropOrphanChanges(createdTr);
|
|
64
64
|
}
|
|
65
65
|
else {
|
|
66
66
|
ids.forEach((changeId) => {
|
|
@@ -56,10 +56,10 @@ export function setFragmentAsWrapChange(inserted, attrs, schema) {
|
|
|
56
56
|
});
|
|
57
57
|
return Fragment.from(content);
|
|
58
58
|
}
|
|
59
|
-
export function setFragmentAsMoveChange(fragment,
|
|
59
|
+
export function setFragmentAsMoveChange(fragment, moveAttrs) {
|
|
60
60
|
const content = [];
|
|
61
61
|
fragment.forEach((node) => {
|
|
62
|
-
content.push(node.type.create(Object.assign(Object.assign({}, node.attrs), { dataTracked: [addTrackIdIfDoesntExist(
|
|
62
|
+
content.push(node.type.create(Object.assign(Object.assign({}, node.attrs), { dataTracked: [addTrackIdIfDoesntExist(moveAttrs)] }), node.content, node.marks));
|
|
63
63
|
});
|
|
64
64
|
return Fragment.from(content);
|
|
65
65
|
}
|
package/dist/es/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { trackChangesPluginKey, trackChangesPlugin } from './plugin';
|
|
2
|
-
export { skipTracking } from './actions';
|
|
2
|
+
export { skipTracking, setAction, TrackChangesAction } from './actions';
|
|
3
3
|
export * as trackCommands from './commands';
|
|
4
4
|
export { enableDebug } from './utils/logger';
|
|
5
5
|
export { ChangeSet } from './ChangeSet';
|
|
@@ -2,6 +2,7 @@ import { Fragment } from 'prosemirror-model';
|
|
|
2
2
|
import { addTrackIdIfDoesntExist, getBlockInlineTrackedData } from '../compute/nodeHelpers';
|
|
3
3
|
import { CHANGE_OPERATION, CHANGE_STATUS } from '../types/change';
|
|
4
4
|
import { log } from '../utils/logger';
|
|
5
|
+
import { dropStructuralChangeShadow } from './dropStructureChange';
|
|
5
6
|
export function deleteNode(node, pos, tr) {
|
|
6
7
|
var _a;
|
|
7
8
|
const startPos = tr.doc.resolve(pos + 1);
|
|
@@ -18,7 +19,14 @@ export function deleteOrSetNodeDeleted(node, pos, newTr, deleteAttrs) {
|
|
|
18
19
|
const dataTracked = getBlockInlineTrackedData(node);
|
|
19
20
|
const inserted = dataTracked === null || dataTracked === void 0 ? void 0 : dataTracked.find((d) => (d.operation === CHANGE_OPERATION.insert || d.operation === CHANGE_OPERATION.wrap_with_node) &&
|
|
20
21
|
(d.status === CHANGE_STATUS.pending || d.status === CHANGE_STATUS.accepted));
|
|
21
|
-
const updated = dataTracked === null || dataTracked === void 0 ? void 0 : dataTracked.find((d) => d.operation === CHANGE_OPERATION.set_node_attributes ||
|
|
22
|
+
const updated = dataTracked === null || dataTracked === void 0 ? void 0 : dataTracked.find((d) => d.operation === CHANGE_OPERATION.set_node_attributes ||
|
|
23
|
+
d.operation === CHANGE_OPERATION.reference ||
|
|
24
|
+
(d.operation === CHANGE_OPERATION.delete && d.moveNodeId));
|
|
25
|
+
const structure = dataTracked === null || dataTracked === void 0 ? void 0 : dataTracked.find((c) => c.operation === CHANGE_OPERATION.structure);
|
|
26
|
+
if (deleteAttrs.moveNodeId && structure && structure.moveNodeId !== deleteAttrs.moveNodeId) {
|
|
27
|
+
return newTr.delete(pos, pos + node.nodeSize);
|
|
28
|
+
}
|
|
29
|
+
const moved = dataTracked === null || dataTracked === void 0 ? void 0 : dataTracked.find((d) => d.operation === CHANGE_OPERATION.move && d.status === CHANGE_STATUS.pending);
|
|
22
30
|
if (inserted) {
|
|
23
31
|
return deleteNode(node, pos, newTr);
|
|
24
32
|
}
|
|
@@ -31,5 +39,13 @@ export function deleteOrSetNodeDeleted(node, pos, newTr, deleteAttrs) {
|
|
|
31
39
|
return;
|
|
32
40
|
}
|
|
33
41
|
const newDeleted = addTrackIdIfDoesntExist(deleteAttrs);
|
|
34
|
-
newTr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, node.attrs), { dataTracked: updated ? [newDeleted, updated] : [newDeleted] }), node.marks);
|
|
42
|
+
newTr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, node.attrs), { dataTracked: updated ? [newDeleted, updated] : moved ? [newDeleted, moved] : [newDeleted] }), node.marks);
|
|
43
|
+
if (!deleteAttrs.moveNodeId && (structure === null || structure === void 0 ? void 0 : structure.moveNodeId)) {
|
|
44
|
+
dropStructuralChangeShadow(structure.moveNodeId, newTr);
|
|
45
|
+
}
|
|
35
46
|
}
|
|
47
|
+
export const keepDeleteWithMoveNodeId = (node) => {
|
|
48
|
+
var _a;
|
|
49
|
+
const dataTracked = (_a = getBlockInlineTrackedData(node)) === null || _a === void 0 ? void 0 : _a.filter((c) => c.operation === CHANGE_OPERATION.delete && c.moveNodeId);
|
|
50
|
+
return (dataTracked === null || dataTracked === void 0 ? void 0 : dataTracked.length) ? dataTracked : null;
|
|
51
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { Fragment } from 'prosemirror-model';
|
|
13
|
+
import { EditorState } from 'prosemirror-state';
|
|
14
|
+
import { findChanges } from '../changes/findChanges';
|
|
15
|
+
import { updateChangeAttrs } from '../changes/updateChangeAttrs';
|
|
16
|
+
import { addTrackIdIfDoesntExist, getBlockInlineTrackedData } from '../compute/nodeHelpers';
|
|
17
|
+
import { setFragmentAsInserted } from '../compute/setFragmentAsInserted';
|
|
18
|
+
import { CHANGE_OPERATION } from '../types/change';
|
|
19
|
+
import { createNewInsertAttrs, createNewStructureAttrs, updateBlockNodesAttrs } from '../utils/track-utils';
|
|
20
|
+
export const dropStructuralChangeShadow = (moveNodeId, tr) => {
|
|
21
|
+
const changeSet = findChanges(EditorState.create({ doc: tr.doc }));
|
|
22
|
+
const changes = changeSet.changes.filter((c) => c.type === 'node-change' && c.dataTracked.moveNodeId === moveNodeId);
|
|
23
|
+
const shadow = changes.filter((c) => c.dataTracked.operation === CHANGE_OPERATION.delete);
|
|
24
|
+
const structures = changes.filter((c) => c.dataTracked.operation === CHANGE_OPERATION.structure);
|
|
25
|
+
structures.map((c) => {
|
|
26
|
+
tr.setNodeMarkup(c.from, undefined, Object.assign(Object.assign({}, c.node.attrs), { dataTracked: null }));
|
|
27
|
+
});
|
|
28
|
+
if (shadow.length > 0) {
|
|
29
|
+
tr.delete(shadow[0].from, shadow[shadow.length - 1].to);
|
|
30
|
+
}
|
|
31
|
+
return tr;
|
|
32
|
+
};
|
|
33
|
+
export const dropOrphanChanges = (newTr, dropDataTracked) => {
|
|
34
|
+
const changeSet = findChanges(EditorState.create({ doc: newTr.doc }));
|
|
35
|
+
const shadowIds = new Set();
|
|
36
|
+
const changesIds = new Set();
|
|
37
|
+
changeSet.changes.forEach((c) => {
|
|
38
|
+
if (c.dataTracked.moveNodeId && c.dataTracked.operation === CHANGE_OPERATION.delete) {
|
|
39
|
+
shadowIds.add(c.dataTracked.moveNodeId);
|
|
40
|
+
}
|
|
41
|
+
if (c.dataTracked.operation === CHANGE_OPERATION.structure ||
|
|
42
|
+
c.dataTracked.operation === CHANGE_OPERATION.move) {
|
|
43
|
+
changesIds.add(c.dataTracked.moveNodeId);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
if (!shadowIds.size && !changesIds.size) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
changeSet.changes.forEach((c) => {
|
|
50
|
+
if (c.dataTracked.moveNodeId &&
|
|
51
|
+
!(shadowIds.has(c.dataTracked.moveNodeId) && changesIds.has(c.dataTracked.moveNodeId))) {
|
|
52
|
+
if (c.dataTracked.operation === CHANGE_OPERATION.delete || dropDataTracked) {
|
|
53
|
+
if (c.type === 'text-change') {
|
|
54
|
+
newTr.removeMark(c.from, c.to, newTr.doc.type.schema.marks.tracked_delete);
|
|
55
|
+
}
|
|
56
|
+
else if (c.type === 'node-change') {
|
|
57
|
+
newTr.setNodeMarkup(c.from, undefined, Object.assign(Object.assign({}, c.node.attrs), { dataTracked: null }));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (c.type === 'node-change') {
|
|
61
|
+
const _a = c.dataTracked, { id, moveNodeId } = _a, attrs = __rest(_a, ["id", "moveNodeId"]);
|
|
62
|
+
newTr.replaceWith(c.from, c.to, setFragmentAsInserted(Fragment.from(c.node), createNewInsertAttrs(attrs), newTr.doc.type.schema));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
const groupStructureChanges = (tr, toNode) => {
|
|
68
|
+
const moveNodeIds = new Set();
|
|
69
|
+
const [insertStep, deleteStep] = tr.steps;
|
|
70
|
+
const fromNodes = tr.docs[1].slice(deleteStep.from, deleteStep.to).content;
|
|
71
|
+
const ignoredNode = tr.docs[1].nodeAt(deleteStep.from);
|
|
72
|
+
Fragment.from(toNode)
|
|
73
|
+
.append(insertStep.slice.content)
|
|
74
|
+
.append(fromNodes)
|
|
75
|
+
.descendants((node) => {
|
|
76
|
+
var _a;
|
|
77
|
+
const moveNodeId = (_a = (getBlockInlineTrackedData(node) || []).find((c) => c.operation === CHANGE_OPERATION.structure)) === null || _a === void 0 ? void 0 : _a.moveNodeId;
|
|
78
|
+
moveNodeId && moveNodeIds.add(moveNodeId);
|
|
79
|
+
});
|
|
80
|
+
return moveNodeIds;
|
|
81
|
+
};
|
|
82
|
+
export const joinStructureChanges = (attrs, sliceContent, content, tr, newTr) => {
|
|
83
|
+
var _a, _b, _c;
|
|
84
|
+
const moveNodeId = attrs.moveNodeId;
|
|
85
|
+
let toNode = tr.docs[0].resolve(tr.steps[0].from).node();
|
|
86
|
+
toNode = ((_a = toNode === null || toNode === void 0 ? void 0 : toNode.type.spec.attrs) === null || _a === void 0 ? void 0 : _a.dataTracked) ? toNode : null;
|
|
87
|
+
const idsSet = groupStructureChanges(tr, toNode);
|
|
88
|
+
const changeSet = findChanges(EditorState.create({ doc: newTr.doc }));
|
|
89
|
+
const relatedChanges = changeSet.changes.filter((c) => c.dataTracked.moveNodeId && idsSet.has(c.dataTracked.moveNodeId));
|
|
90
|
+
relatedChanges.map((c) => updateChangeAttrs(newTr, c, Object.assign(Object.assign({}, c.dataTracked), { moveNodeId }), newTr.doc.type.schema));
|
|
91
|
+
const toInsertChange = toNode && ((_b = getBlockInlineTrackedData(toNode)) === null || _b === void 0 ? void 0 : _b.find((c) => c.operation === CHANGE_OPERATION.insert));
|
|
92
|
+
const fromInsertChange = sliceContent.firstChild &&
|
|
93
|
+
((_c = getBlockInlineTrackedData(sliceContent.firstChild)) === null || _c === void 0 ? void 0 : _c.find((c) => c.operation === CHANGE_OPERATION.insert));
|
|
94
|
+
if (toInsertChange || fromInsertChange) {
|
|
95
|
+
return setFragmentAsInserted(content, createNewInsertAttrs(attrs), newTr.doc.type.schema);
|
|
96
|
+
}
|
|
97
|
+
return updateBlockNodesAttrs(sliceContent, (_, node) => {
|
|
98
|
+
return Object.assign(Object.assign({}, _), { dataTracked: [addTrackIdIfDoesntExist(createNewStructureAttrs(Object.assign(Object.assign({}, attrs), { moveNodeId })))] });
|
|
99
|
+
});
|
|
100
|
+
};
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { Slice } from 'prosemirror-model';
|
|
2
|
+
import { getAction, TrackChangesAction } from '../actions';
|
|
2
3
|
import { setFragmentAsInserted, setFragmentAsMoveChange, setFragmentAsNodeSplit, } from '../compute/setFragmentAsInserted';
|
|
3
4
|
import { deleteAndMergeSplitNodes } from '../mutate/deleteAndMergeSplitNodes';
|
|
5
|
+
import { joinStructureChanges } from '../mutate/dropStructureChange';
|
|
4
6
|
import { log } from '../utils/logger';
|
|
5
7
|
import * as trackUtils from '../utils/track-utils';
|
|
6
|
-
import { isSplitStep } from '../utils/track-utils';
|
|
8
|
+
import { isSplitStep, isStructureSteps } from '../utils/track-utils';
|
|
7
9
|
export function trackReplaceStep(step, oldState, newTr, attrsTemplate, stepResult, currentStepDoc, tr, moveID) {
|
|
8
10
|
log.info('###### ReplaceStep ######');
|
|
9
11
|
let selectionPos = 0;
|
|
10
12
|
const changeSteps = [];
|
|
11
13
|
const attrs = Object.assign({}, attrsTemplate);
|
|
12
14
|
if (moveID) {
|
|
13
|
-
console.log('Detected Node Moving ReplaceStep and assigning the following movenodeID: ' + moveID);
|
|
14
15
|
attrs.moveNodeId = moveID;
|
|
15
16
|
}
|
|
16
17
|
step.getMap().forEach((fromA, toA, fromB, toB) => {
|
|
17
|
-
var _a, _b, _c;
|
|
18
|
+
var _a, _b, _c, _d;
|
|
18
19
|
log.info(`changed ranges: ${fromA} ${toA} ${fromB} ${toB}`);
|
|
19
20
|
const { slice } = step;
|
|
20
21
|
log.info('TR: steps before applying delete', [...newTr.steps]);
|
|
@@ -41,16 +42,20 @@ export function trackReplaceStep(step, oldState, newTr, attrsTemplate, stepResul
|
|
|
41
42
|
if (!backSpacedText && newSliceContent.size > 0) {
|
|
42
43
|
log.info('newSliceContent', newSliceContent);
|
|
43
44
|
let fragment = setFragmentAsInserted(newSliceContent, trackUtils.createNewInsertAttrs(attrs), oldState.schema);
|
|
44
|
-
if (
|
|
45
|
+
if (isStructureSteps(tr)) {
|
|
46
|
+
fragment = joinStructureChanges(attrs, newSliceContent, fragment, tr, newTr);
|
|
47
|
+
}
|
|
48
|
+
else if (isSplitStep(step, oldState.selection, tr.getMeta('uiEvent'))) {
|
|
45
49
|
fragment = setFragmentAsNodeSplit(newTr.doc.resolve(step.from), newTr, fragment, attrs);
|
|
46
50
|
}
|
|
47
|
-
if (moveID) {
|
|
48
|
-
|
|
51
|
+
else if (moveID) {
|
|
52
|
+
const indentationType = (_a = getAction(tr, TrackChangesAction.indentationAction)) === null || _a === void 0 ? void 0 : _a.action;
|
|
53
|
+
fragment = setFragmentAsMoveChange(newSliceContent, trackUtils.createNewMoveAttrs(attrs, indentationType));
|
|
49
54
|
}
|
|
50
55
|
const openStart = slice.openStart !== slice.openEnd ? 0 : slice.openStart;
|
|
51
56
|
const openEnd = slice.openStart !== slice.openEnd ? 0 : slice.openEnd;
|
|
52
57
|
const textWasDeleted = !!changeSteps.length && !(fromA === fromB);
|
|
53
|
-
const isBlock = !!((
|
|
58
|
+
const isBlock = !!((_b = fragment.firstChild) === null || _b === void 0 ? void 0 : _b.isBlock);
|
|
54
59
|
changeSteps.push({
|
|
55
60
|
type: 'insert-slice',
|
|
56
61
|
from: textWasDeleted ? fromB : isBlock ? toA : fromA,
|
|
@@ -60,8 +65,8 @@ export function trackReplaceStep(step, oldState, newTr, attrsTemplate, stepResul
|
|
|
60
65
|
});
|
|
61
66
|
}
|
|
62
67
|
else {
|
|
63
|
-
const isDeleteEvent = ((
|
|
64
|
-
const isDeleteContentForward = ((
|
|
68
|
+
const isDeleteEvent = ((_c = window.event) === null || _c === void 0 ? void 0 : _c.code) === 'Delete';
|
|
69
|
+
const isDeleteContentForward = ((_d = window.event) === null || _d === void 0 ? void 0 : _d.inputType) === 'deleteContentForward';
|
|
65
70
|
selectionPos = isDeleteEvent || isDeleteContentForward ? toA : fromA;
|
|
66
71
|
}
|
|
67
72
|
});
|