@manuscripts/track-changes-plugin 2.0.12 → 2.1.0
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/README.md +3 -3
- package/dist/cjs/ChangeSet.js +27 -8
- package/dist/cjs/changes/applyChanges.js +27 -13
- package/dist/cjs/changes/findChanges.js +16 -0
- package/dist/cjs/changes/revertChange.js +2 -2
- package/dist/cjs/changes/updateChangeAttrs.js +27 -0
- package/dist/cjs/compute/nodeHelpers.js +11 -0
- package/dist/cjs/mutate/deleteAndMergeSplitNodes.js +2 -1
- package/dist/cjs/mutate/deleteNode.js +4 -4
- package/dist/cjs/mutate/dropStructureChange.js +29 -4
- package/dist/cjs/steps/trackMarkSteps.js +140 -0
- package/dist/cjs/steps/trackReplaceAroundStep.js +3 -3
- package/dist/cjs/steps/trackReplaceStep.js +3 -3
- package/dist/cjs/steps/trackTransaction.js +14 -2
- package/dist/cjs/steps/utils.js +70 -0
- package/dist/cjs/utils/track-utils.js +28 -51
- package/dist/cjs/utils/uuidv4.js +3 -0
- package/dist/es/ChangeSet.js +27 -8
- package/dist/es/changes/applyChanges.js +28 -13
- package/dist/es/changes/findChanges.js +17 -1
- package/dist/es/changes/revertChange.js +2 -2
- package/dist/es/changes/updateChangeAttrs.js +27 -0
- package/dist/es/compute/nodeHelpers.js +10 -0
- package/dist/es/mutate/deleteAndMergeSplitNodes.js +2 -1
- package/dist/es/mutate/deleteNode.js +2 -2
- package/dist/es/mutate/dropStructureChange.js +29 -4
- package/dist/es/steps/trackMarkSteps.js +134 -0
- package/dist/es/steps/trackReplaceAroundStep.js +1 -1
- package/dist/es/steps/trackReplaceStep.js +1 -1
- package/dist/es/steps/trackTransaction.js +14 -2
- package/dist/es/steps/utils.js +62 -0
- package/dist/es/utils/track-utils.js +24 -45
- package/dist/es/utils/uuidv4.js +3 -0
- package/dist/types/ChangeSet.d.ts +5 -2
- package/dist/types/changes/applyChanges.d.ts +1 -2
- package/dist/types/compute/nodeHelpers.d.ts +2 -1
- package/dist/types/mutate/deleteNode.d.ts +1 -1
- package/dist/types/mutate/dropStructureChange.d.ts +1 -1
- package/dist/types/steps/trackMarkSteps.d.ts +8 -0
- package/dist/types/steps/utils.d.ts +28 -0
- package/dist/types/types/change.d.ts +4 -1
- package/dist/types/utils/track-utils.d.ts +7 -14
- package/package.json +1 -1
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* © 2023 Atypon Systems LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.isStructureSteps = exports.isLiftStep = exports.isWrapStep = exports.isSplitStep = void 0;
|
|
19
|
+
exports.stepIsLift = stepIsLift;
|
|
20
|
+
const prosemirror_transform_1 = require("prosemirror-transform");
|
|
21
|
+
const actions_1 = require("../actions");
|
|
22
|
+
const isSplitStep = (step, selection, uiEvent) => {
|
|
23
|
+
var _a, _b, _c, _d;
|
|
24
|
+
const { from, to, slice } = step;
|
|
25
|
+
if (from !== to ||
|
|
26
|
+
slice.content.childCount < 2 ||
|
|
27
|
+
(((_a = slice.content.firstChild) === null || _a === void 0 ? void 0 : _a.isInline) && ((_b = slice.content.lastChild) === null || _b === void 0 ? void 0 : _b.isInline))) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
const { $anchor: { parentOffset: startOffset }, $head: { parentOffset: endOffset }, $from, } = selection;
|
|
31
|
+
const parentSize = $from.node().content.size;
|
|
32
|
+
if (uiEvent === 'paste') {
|
|
33
|
+
return !((startOffset === 0 && endOffset === 0) ||
|
|
34
|
+
(startOffset === parentSize && endOffset === parentSize));
|
|
35
|
+
}
|
|
36
|
+
const { content: { firstChild, lastChild }, openStart, openEnd, } = slice;
|
|
37
|
+
if ((((_c = window.event) === null || _c === void 0 ? void 0 : _c.code) === 'Enter' || ((_d = window.event) === null || _d === void 0 ? void 0 : _d.code) === 'NumpadEnter') &&
|
|
38
|
+
(firstChild === null || firstChild === void 0 ? void 0 : firstChild.type.name) === 'list_item') {
|
|
39
|
+
return !(parentSize === startOffset && parentSize === endOffset) && (lastChild === null || lastChild === void 0 ? void 0 : lastChild.type.name) === 'list_item';
|
|
40
|
+
}
|
|
41
|
+
return (openStart === openEnd &&
|
|
42
|
+
firstChild.type === lastChild.type &&
|
|
43
|
+
firstChild.inlineContent &&
|
|
44
|
+
lastChild.inlineContent &&
|
|
45
|
+
!(startOffset === parentSize && endOffset === parentSize));
|
|
46
|
+
};
|
|
47
|
+
exports.isSplitStep = isSplitStep;
|
|
48
|
+
const isWrapStep = (step) => step.from === step.gapFrom &&
|
|
49
|
+
step.to === step.gapTo &&
|
|
50
|
+
step.slice.openStart === 0 &&
|
|
51
|
+
step.slice.openEnd === 0;
|
|
52
|
+
exports.isWrapStep = isWrapStep;
|
|
53
|
+
const isLiftStep = (step) => {
|
|
54
|
+
if (step.from < step.gapFrom &&
|
|
55
|
+
step.to > step.gapTo &&
|
|
56
|
+
step.slice.size === 0 &&
|
|
57
|
+
step.gapTo - step.gapFrom > 0) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
};
|
|
62
|
+
exports.isLiftStep = isLiftStep;
|
|
63
|
+
function stepIsLift(gap, node, to) {
|
|
64
|
+
return gap.start < gap.end && gap.insert === 0 && gap.end === to && !node.isText;
|
|
65
|
+
}
|
|
66
|
+
const isStructureSteps = (tr) => tr.getMeta(actions_1.TrackChangesAction.structuralChangeAction) &&
|
|
67
|
+
tr.steps.length === 2 &&
|
|
68
|
+
tr.steps[0] instanceof prosemirror_transform_1.ReplaceStep &&
|
|
69
|
+
tr.steps[1] instanceof prosemirror_transform_1.ReplaceStep;
|
|
70
|
+
exports.isStructureSteps = isStructureSteps;
|
|
@@ -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.updateBlockNodesAttrs = exports.filterMeaninglessMoveSteps = exports.handleDirectPendingMoveDeletions = exports.isDirectPendingMoveDeletion = exports.isDeletingPendingMovedNode = exports.isPendingChange = exports.HasMoveOperations = exports.trFromHistory =
|
|
14
|
+
exports.updateBlockNodesAttrs = exports.filterMeaninglessMoveSteps = exports.handleDirectPendingMoveDeletions = exports.isDirectPendingMoveDeletion = exports.isDeletingPendingMovedNode = exports.isPendingChange = exports.HasMoveOperations = exports.trFromHistory = void 0;
|
|
15
15
|
exports.createNewInsertAttrs = createNewInsertAttrs;
|
|
16
16
|
exports.createNewWrapAttrs = createNewWrapAttrs;
|
|
17
17
|
exports.createNewSplitAttrs = createNewSplitAttrs;
|
|
@@ -20,7 +20,9 @@ exports.createNewDeleteAttrs = createNewDeleteAttrs;
|
|
|
20
20
|
exports.createNewMoveAttrs = createNewMoveAttrs;
|
|
21
21
|
exports.createNewUpdateAttrs = createNewUpdateAttrs;
|
|
22
22
|
exports.createNewStructureAttrs = createNewStructureAttrs;
|
|
23
|
-
exports.
|
|
23
|
+
exports.isValidTrackableMark = isValidTrackableMark;
|
|
24
|
+
exports.excludeFromTracked = excludeFromTracked;
|
|
25
|
+
exports.isInlineMarkChange = isInlineMarkChange;
|
|
24
26
|
const prosemirror_model_1 = require("prosemirror-model");
|
|
25
27
|
const prosemirror_transform_1 = require("prosemirror-transform");
|
|
26
28
|
const actions_1 = require("../actions");
|
|
@@ -51,55 +53,6 @@ function createNewUpdateAttrs(attrs, oldAttrs) {
|
|
|
51
53
|
function createNewStructureAttrs(attrs) {
|
|
52
54
|
return Object.assign(Object.assign({}, attrs), { operation: change_1.CHANGE_OPERATION.structure });
|
|
53
55
|
}
|
|
54
|
-
const isSplitStep = (step, selection, uiEvent) => {
|
|
55
|
-
var _a, _b, _c, _d;
|
|
56
|
-
const { from, to, slice } = step;
|
|
57
|
-
if (from !== to ||
|
|
58
|
-
slice.content.childCount < 2 ||
|
|
59
|
-
(((_a = slice.content.firstChild) === null || _a === void 0 ? void 0 : _a.isInline) && ((_b = slice.content.lastChild) === null || _b === void 0 ? void 0 : _b.isInline))) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
const { $anchor: { parentOffset: startOffset }, $head: { parentOffset: endOffset }, $from, } = selection;
|
|
63
|
-
const parentSize = $from.node().content.size;
|
|
64
|
-
if (uiEvent === 'paste') {
|
|
65
|
-
return !((startOffset === 0 && endOffset === 0) ||
|
|
66
|
-
(startOffset === parentSize && endOffset === parentSize));
|
|
67
|
-
}
|
|
68
|
-
const { content: { firstChild, lastChild }, openStart, openEnd, } = slice;
|
|
69
|
-
if ((((_c = window.event) === null || _c === void 0 ? void 0 : _c.code) === 'Enter' || ((_d = window.event) === null || _d === void 0 ? void 0 : _d.code) === 'NumpadEnter') &&
|
|
70
|
-
(firstChild === null || firstChild === void 0 ? void 0 : firstChild.type.name) === 'list_item') {
|
|
71
|
-
return !(parentSize === startOffset && parentSize === endOffset) && (lastChild === null || lastChild === void 0 ? void 0 : lastChild.type.name) === 'list_item';
|
|
72
|
-
}
|
|
73
|
-
return (openStart === openEnd &&
|
|
74
|
-
firstChild.type === lastChild.type &&
|
|
75
|
-
firstChild.inlineContent &&
|
|
76
|
-
lastChild.inlineContent &&
|
|
77
|
-
!(startOffset === parentSize && endOffset === parentSize));
|
|
78
|
-
};
|
|
79
|
-
exports.isSplitStep = isSplitStep;
|
|
80
|
-
const isWrapStep = (step) => step.from === step.gapFrom &&
|
|
81
|
-
step.to === step.gapTo &&
|
|
82
|
-
step.slice.openStart === 0 &&
|
|
83
|
-
step.slice.openEnd === 0;
|
|
84
|
-
exports.isWrapStep = isWrapStep;
|
|
85
|
-
const isLiftStep = (step) => {
|
|
86
|
-
if (step.from < step.gapFrom &&
|
|
87
|
-
step.to > step.gapTo &&
|
|
88
|
-
step.slice.size === 0 &&
|
|
89
|
-
step.gapTo - step.gapFrom > 0) {
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
return false;
|
|
93
|
-
};
|
|
94
|
-
exports.isLiftStep = isLiftStep;
|
|
95
|
-
function stepIsLift(gap, node, to) {
|
|
96
|
-
return gap.start < gap.end && gap.insert === 0 && gap.end === to && !node.isText;
|
|
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;
|
|
103
56
|
const trFromHistory = (tr) => Object.keys(tr.meta).find((s) => s.startsWith('history$'));
|
|
104
57
|
exports.trFromHistory = trFromHistory;
|
|
105
58
|
const HasMoveOperations = (tr) => {
|
|
@@ -260,3 +213,27 @@ const updateBlockNodesAttrs = (fragment, predicate) => {
|
|
|
260
213
|
return prosemirror_model_1.Fragment.fromArray(updatedNodes);
|
|
261
214
|
};
|
|
262
215
|
exports.updateBlockNodesAttrs = updateBlockNodesAttrs;
|
|
216
|
+
function isValidTrackableMark(mark) {
|
|
217
|
+
var _a, _b;
|
|
218
|
+
const spec = mark.type.spec;
|
|
219
|
+
const name = mark.type.name;
|
|
220
|
+
if (!name.startsWith('tracked_') &&
|
|
221
|
+
((_a = spec.attrs) === null || _a === void 0 ? void 0 : _a.dataTracked) &&
|
|
222
|
+
typeof ((_b = spec.attrs) === null || _b === void 0 ? void 0 : _b.dataTracked) === 'object') {
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
function excludeFromTracked(dataTracked, changeIdToExclude) {
|
|
228
|
+
if (!dataTracked) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
const newDataTracked = dataTracked.filter((c) => c.id !== changeIdToExclude);
|
|
232
|
+
return newDataTracked.length ? newDataTracked : null;
|
|
233
|
+
}
|
|
234
|
+
function isInlineMarkChange(change) {
|
|
235
|
+
if (change.type == 'mark-change') {
|
|
236
|
+
return change.nodeType.isInline || change.nodeType.isText;
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
239
|
+
}
|
package/dist/cjs/utils/uuidv4.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.uuidv4 = uuidv4;
|
|
4
4
|
function uuidv4() {
|
|
5
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
6
|
+
return crypto.randomUUID();
|
|
7
|
+
}
|
|
5
8
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
6
9
|
const r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
|
|
7
10
|
return v.toString(16);
|
package/dist/es/ChangeSet.js
CHANGED
|
@@ -12,6 +12,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
12
12
|
var _ChangeSet_instances, _ChangeSet_changes, _ChangeSet_isSameNodeChange, _ChangeSet_isNotPendingOrDeleted;
|
|
13
13
|
import { CHANGE_OPERATION, CHANGE_STATUS, } from './types/change';
|
|
14
14
|
import { log } from './utils/logger';
|
|
15
|
+
import { isInlineMarkChange } from './utils/track-utils';
|
|
15
16
|
export class ChangeSet {
|
|
16
17
|
constructor(changes = []) {
|
|
17
18
|
_ChangeSet_instances.add(this);
|
|
@@ -147,19 +148,34 @@ export class ChangeSet {
|
|
|
147
148
|
}
|
|
148
149
|
}
|
|
149
150
|
}
|
|
151
|
+
areMatchingWrapOperations(c1, c2) {
|
|
152
|
+
const op1 = c1.dataTracked.operation;
|
|
153
|
+
const op2 = c2.dataTracked.operation;
|
|
154
|
+
return ((op1 === 'wrap_with_node' && (op2 === 'insert' || op2 === 'set_attrs')) ||
|
|
155
|
+
(op2 === 'wrap_with_node' && (op1 === 'insert' || op1 === 'set_attrs')));
|
|
156
|
+
}
|
|
157
|
+
areMatchingMarkOperations(c1, c2) {
|
|
158
|
+
if (ChangeSet.isMarkChange(c1) && ChangeSet.isMarkChange(c2)) {
|
|
159
|
+
const op1 = c1.dataTracked.operation;
|
|
160
|
+
const op2 = c2.dataTracked.operation;
|
|
161
|
+
if (op1 == op2 && c1.mark.type === c2.mark.type) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
150
167
|
canJoinAdjacentInlineChanges(change, index) {
|
|
151
168
|
const nextChange = this.changeTree.at(index + 1);
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
(c2.dataTracked.operation === 'wrap_with_node' &&
|
|
157
|
-
(c1.dataTracked.operation === 'insert' || c1.dataTracked.operation === 'set_attrs'));
|
|
169
|
+
if (!nextChange) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
const isInline = (c) => c.type === 'text-change' || (c.type === 'node-change' && c.node.isInline) || isInlineMarkChange(c);
|
|
158
173
|
return (isInline(change) &&
|
|
159
|
-
nextChange &&
|
|
160
174
|
isInline(nextChange) &&
|
|
161
175
|
change.to === nextChange.from &&
|
|
162
|
-
|
|
176
|
+
(change.dataTracked.operation === nextChange.dataTracked.operation ||
|
|
177
|
+
this.areMatchingWrapOperations(change, nextChange) ||
|
|
178
|
+
this.areMatchingMarkOperations(change, nextChange)));
|
|
163
179
|
}
|
|
164
180
|
joinRelatedStructuralChanges(rootNodes, change) {
|
|
165
181
|
if (change.dataTracked.operation !== CHANGE_OPERATION.structure) {
|
|
@@ -210,6 +226,9 @@ export class ChangeSet {
|
|
|
210
226
|
static isTextChange(change) {
|
|
211
227
|
return change.type === 'text-change';
|
|
212
228
|
}
|
|
229
|
+
static isMarkChange(change) {
|
|
230
|
+
return change.type === 'mark-change';
|
|
231
|
+
}
|
|
213
232
|
static isNodeChange(change) {
|
|
214
233
|
return change.type === 'node-change';
|
|
215
234
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Mapping } from 'prosemirror-transform';
|
|
2
2
|
import { ChangeSet } from '../ChangeSet';
|
|
3
|
-
import { deleteNode,
|
|
3
|
+
import { deleteNode, keepPairedChanges } 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
|
+
import { excludeFromTracked, isInlineMarkChange } from '../utils/track-utils';
|
|
7
8
|
import { revertSplitNodeChange, revertWrapNodeChange } from './revertChange';
|
|
8
9
|
import { restoreNode, updateChangeChildrenAttributes } from './updateChangeAttrs';
|
|
9
10
|
function collectMoveNodeIds(containerNode, primaryMoveNodeId) {
|
|
@@ -21,13 +22,6 @@ function collectMoveNodeIds(containerNode, primaryMoveNodeId) {
|
|
|
21
22
|
});
|
|
22
23
|
return moveNodeIds;
|
|
23
24
|
}
|
|
24
|
-
export function getUpdatedDataTracked(dataTracked, changeId) {
|
|
25
|
-
if (!dataTracked) {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
const newDataTracked = dataTracked.filter((c) => c.id !== changeId);
|
|
29
|
-
return newDataTracked.length ? newDataTracked : null;
|
|
30
|
-
}
|
|
31
25
|
export function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, deleteMap = new Mapping()) {
|
|
32
26
|
changes.sort((c1, c2) => {
|
|
33
27
|
if ((c1.type === 'node-change' && c1.node.type === schema.nodes.list) ||
|
|
@@ -71,7 +65,7 @@ export function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, del
|
|
|
71
65
|
deleteMap.appendMap(tr.steps[tr.steps.length - 1].getMap());
|
|
72
66
|
}
|
|
73
67
|
else if (ChangeSet.isNodeChange(change) && noChangeNeeded) {
|
|
74
|
-
const attrs = Object.assign(Object.assign({}, node.attrs), { dataTracked:
|
|
68
|
+
const attrs = Object.assign(Object.assign({}, node.attrs), { dataTracked: keepPairedChanges(node) });
|
|
75
69
|
tr.setNodeMarkup(from, undefined, attrs, node.marks);
|
|
76
70
|
if (node.isAtom) {
|
|
77
71
|
tr.removeMark(from, deleteMap.map(change.to), schema.marks.tracked_insert);
|
|
@@ -87,13 +81,34 @@ export function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, del
|
|
|
87
81
|
deleteMap.appendMap(tr.steps[tr.steps.length - 1].getMap());
|
|
88
82
|
}
|
|
89
83
|
else if (ChangeSet.isNodeAttrChange(change) && change.dataTracked.status === CHANGE_STATUS.accepted) {
|
|
90
|
-
tr.setNodeMarkup(from, undefined, Object.assign(Object.assign({}, change.newAttrs), { dataTracked:
|
|
84
|
+
tr.setNodeMarkup(from, undefined, Object.assign(Object.assign({}, change.newAttrs), { dataTracked: excludeFromTracked(node.attrs.dataTracked, change.id) }), node.marks);
|
|
91
85
|
}
|
|
92
86
|
else if (ChangeSet.isNodeAttrChange(change) && change.dataTracked.status === CHANGE_STATUS.rejected) {
|
|
93
|
-
tr.setNodeMarkup(from, undefined, Object.assign(Object.assign({}, change.oldAttrs), { dataTracked:
|
|
87
|
+
tr.setNodeMarkup(from, undefined, Object.assign(Object.assign({}, change.oldAttrs), { dataTracked: excludeFromTracked(node.attrs.dataTracked, change.id) }), node.marks);
|
|
94
88
|
}
|
|
95
89
|
else if (ChangeSet.isReferenceChange(change)) {
|
|
96
|
-
tr.setNodeMarkup(from, undefined, Object.assign(Object.assign({}, node.attrs), { dataTracked:
|
|
90
|
+
tr.setNodeMarkup(from, undefined, Object.assign(Object.assign({}, node.attrs), { dataTracked: excludeFromTracked(node.attrs.dataTracked, change.id) }), node.marks);
|
|
91
|
+
}
|
|
92
|
+
else if (ChangeSet.isMarkChange(change)) {
|
|
93
|
+
const newMark = change.mark.type.create({
|
|
94
|
+
dataTracked: excludeFromTracked(change.mark.attrs.dataTracked, change.id),
|
|
95
|
+
});
|
|
96
|
+
const isInsert = change.dataTracked.operation === CHANGE_OPERATION.insert;
|
|
97
|
+
const isDelete = change.dataTracked.operation === CHANGE_OPERATION.delete;
|
|
98
|
+
const toBeRestored = (change.dataTracked.status === CHANGE_STATUS.accepted && isInsert) ||
|
|
99
|
+
(change.dataTracked.status === CHANGE_STATUS.rejected && isDelete);
|
|
100
|
+
if (isInlineMarkChange(change)) {
|
|
101
|
+
tr.removeMark(change.from, change.to, change.mark);
|
|
102
|
+
if (toBeRestored) {
|
|
103
|
+
tr.addMark(change.from, change.to, newMark);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
tr.removeNodeMark(change.from, change.mark);
|
|
108
|
+
if (toBeRestored) {
|
|
109
|
+
tr.addNodeMark(change.from, newMark);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
97
112
|
}
|
|
98
113
|
});
|
|
99
114
|
changes.forEach((change) => {
|
|
@@ -110,7 +125,7 @@ export function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, del
|
|
|
110
125
|
return;
|
|
111
126
|
}
|
|
112
127
|
if (change.dataTracked.status === CHANGE_STATUS.accepted) {
|
|
113
|
-
const attrs = Object.assign(Object.assign({}, node.attrs), { dataTracked:
|
|
128
|
+
const attrs = Object.assign(Object.assign({}, node.attrs), { dataTracked: excludeFromTracked(node.attrs.dataTracked, change.id) });
|
|
114
129
|
tr.setNodeMarkup(from, undefined, attrs, node.marks);
|
|
115
130
|
const originalChanges = changeSet.changes.filter((c) => c.dataTracked.moveNodeId === change.dataTracked.moveNodeId &&
|
|
116
131
|
c.dataTracked.operation === CHANGE_OPERATION.delete);
|
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { ChangeSet } from '../ChangeSet';
|
|
2
|
-
import { getNodeTrackedData } from '../compute/nodeHelpers';
|
|
2
|
+
import { getMarkTrackedData, getNodeTrackedData } from '../compute/nodeHelpers';
|
|
3
3
|
import { CHANGE_OPERATION, } from '../types/change';
|
|
4
4
|
export function findChanges(state) {
|
|
5
5
|
const changes = [];
|
|
6
6
|
let current;
|
|
7
7
|
state.doc.descendants((node, pos) => {
|
|
8
8
|
const tracked = getNodeTrackedData(node, state.schema) || [];
|
|
9
|
+
const marksWithTrackChanges = getMarkTrackedData(node);
|
|
10
|
+
marksWithTrackChanges === null || marksWithTrackChanges === void 0 ? void 0 : marksWithTrackChanges.forEach((trackAttrs, mark) => {
|
|
11
|
+
trackAttrs.forEach((c) => {
|
|
12
|
+
const ch = {
|
|
13
|
+
id: c.id,
|
|
14
|
+
type: 'mark-change',
|
|
15
|
+
from: pos,
|
|
16
|
+
to: pos + node.nodeSize,
|
|
17
|
+
dataTracked: Object.assign({}, c),
|
|
18
|
+
nodeType: node.type,
|
|
19
|
+
node: node,
|
|
20
|
+
mark: mark,
|
|
21
|
+
};
|
|
22
|
+
changes.push(ch);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
9
25
|
for (let i = 0; i < tracked.length; i += 1) {
|
|
10
26
|
const dataTracked = tracked[i];
|
|
11
27
|
const id = dataTracked.id || '';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Slice } from 'prosemirror-model';
|
|
2
2
|
import { liftTarget, ReplaceAroundStep } from 'prosemirror-transform';
|
|
3
3
|
import { getBlockInlineTrackedData } from '../compute/nodeHelpers';
|
|
4
|
-
import {
|
|
4
|
+
import { excludeFromTracked } from '../utils/track-utils';
|
|
5
5
|
export function revertSplitNodeChange(tr, change, changeSet) {
|
|
6
6
|
const sourceChange = changeSet.changes.find((c) => c.dataTracked.operation === 'reference' && c.dataTracked.referenceId === change.id);
|
|
7
7
|
const node = tr.doc.nodeAt(tr.mapping.map(change.from));
|
|
@@ -20,7 +20,7 @@ export function revertSplitNodeChange(tr, change, changeSet) {
|
|
|
20
20
|
const deleteChange = changeSet.changes.find((c) => c.dataTracked.operation == 'delete' && c.from === sourceChange.from);
|
|
21
21
|
if (deleteChange) {
|
|
22
22
|
const node = tr.doc.nodeAt(tr.mapping.map(deleteChange.from));
|
|
23
|
-
tr.setNodeMarkup(tr.mapping.map(deleteChange.from), undefined,
|
|
23
|
+
tr.setNodeMarkup(tr.mapping.map(deleteChange.from), undefined, excludeFromTracked(node.attrs.dataTracked, deleteChange.id));
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
export function revertWrapNodeChange(tr, change, deleteMap) {
|
|
@@ -2,6 +2,7 @@ import { ChangeSet } from '../ChangeSet';
|
|
|
2
2
|
import { getBlockInlineTrackedData, getTextNodeTrackedMarkData } from '../compute/nodeHelpers';
|
|
3
3
|
import { CHANGE_OPERATION, CHANGE_STATUS, } from '../types/change';
|
|
4
4
|
import { log } from '../utils/logger';
|
|
5
|
+
import { isInlineMarkChange } from '../utils/track-utils';
|
|
5
6
|
export function updateChangeAttrs(tr, change, trackedAttrs, schema) {
|
|
6
7
|
const node = tr.doc.nodeAt(change.from);
|
|
7
8
|
if (!node) {
|
|
@@ -64,6 +65,32 @@ export function updateChangeAttrs(tr, change, trackedAttrs, schema) {
|
|
|
64
65
|
.filter(Boolean);
|
|
65
66
|
tr.setNodeMarkup(change.from, undefined, Object.assign(Object.assign({}, (restoredAttrs || node.attrs)), { dataTracked: newDataTracked.length === 0 ? null : newDataTracked }), node.marks);
|
|
66
67
|
}
|
|
68
|
+
else if (change.type === 'mark-change') {
|
|
69
|
+
const markChange = change;
|
|
70
|
+
if (markChange.mark && markChange.from && markChange.to) {
|
|
71
|
+
const markDataTracked = Array.isArray(markChange.mark.attrs.dataTracked)
|
|
72
|
+
? markChange.mark.attrs.dataTracked
|
|
73
|
+
: [];
|
|
74
|
+
const newDT = markDataTracked === null || markDataTracked === void 0 ? void 0 : markDataTracked.map((dt) => {
|
|
75
|
+
if (dt.createdAt === change.dataTracked.createdAt && dt.operation === change.dataTracked.operation) {
|
|
76
|
+
return Object.assign(Object.assign({}, dt), trackedAttrs);
|
|
77
|
+
}
|
|
78
|
+
return dt;
|
|
79
|
+
});
|
|
80
|
+
const newMark = markChange.mark.type.create(Object.assign(Object.assign({}, markChange.mark.attrs), { dataTracked: newDT }));
|
|
81
|
+
if (isInlineMarkChange(markChange)) {
|
|
82
|
+
tr.removeMark(markChange.from, markChange.to, markChange.mark);
|
|
83
|
+
tr.addMark(markChange.from, markChange.to, newMark);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
tr.removeNodeMark(markChange.from, markChange.mark);
|
|
87
|
+
tr.addNodeMark(markChange.from, newMark);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
console.warn('Unable to update a mark change because the mark change data are incomplete');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
67
94
|
return tr;
|
|
68
95
|
}
|
|
69
96
|
export function updateChangeChildrenAttributes(changes, tr, mapping) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CHANGE_OPERATION } from '../types/change';
|
|
2
2
|
import { log } from '../utils/logger';
|
|
3
|
+
import { isValidTrackableMark } from '../utils/track-utils';
|
|
3
4
|
import { uuidv4 } from '../utils/uuidv4';
|
|
4
5
|
export function addTrackIdIfDoesntExist(attrs) {
|
|
5
6
|
if (!attrs.id) {
|
|
@@ -30,6 +31,15 @@ export function getBlockInlineTrackedData(node) {
|
|
|
30
31
|
}
|
|
31
32
|
return dataTracked || [];
|
|
32
33
|
}
|
|
34
|
+
export function getMarkTrackedData(node) {
|
|
35
|
+
const tracked = node === null || node === void 0 ? void 0 : node.marks.reduce((acc, current) => {
|
|
36
|
+
if (isValidTrackableMark(current) && current.attrs.dataTracked) {
|
|
37
|
+
acc.set(current, current.attrs.dataTracked);
|
|
38
|
+
}
|
|
39
|
+
return acc;
|
|
40
|
+
}, new Map());
|
|
41
|
+
return tracked || new Map();
|
|
42
|
+
}
|
|
33
43
|
export function getNodeTrackedData(node, schema) {
|
|
34
44
|
let tracked;
|
|
35
45
|
if (node && !node.isText) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Fragment } from 'prosemirror-model';
|
|
2
2
|
import { setFragmentAsInserted } from '../compute/setFragmentAsInserted';
|
|
3
3
|
import { splitSliceIntoMergedParts } from '../compute/splitSliceIntoMergedParts';
|
|
4
|
+
import { stepIsLift } from '../steps/utils';
|
|
4
5
|
import * as trackUtils from '../utils/track-utils';
|
|
5
6
|
export function deleteAndMergeSplitNodes(from, to, gap, startDoc, newTr, schema, trackAttrs, insertSlice) {
|
|
6
7
|
const steps = [];
|
|
@@ -33,7 +34,7 @@ export function deleteAndMergeSplitNodes(from, to, gap, startDoc, newTr, schema,
|
|
|
33
34
|
const mergeEndNode = startTokenDeleted && openEnd > 0 && depth === openEnd && mergeContent;
|
|
34
35
|
const mergeEndNodeNotEmpty = mergeEndNode && mergeContent.size;
|
|
35
36
|
if (mergeEndNode && !mergeEndNodeNotEmpty && gap) {
|
|
36
|
-
if (
|
|
37
|
+
if (stepIsLift(gap, node, to)) {
|
|
37
38
|
gap.slice.content.forEach((node, offset) => {
|
|
38
39
|
steps.push({
|
|
39
40
|
type: 'delete-node',
|
|
@@ -44,8 +44,8 @@ export function deleteOrSetNodeDeleted(node, pos, newTr, deleteAttrs) {
|
|
|
44
44
|
dropStructuralChangeShadow(structure.moveNodeId, newTr);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
export const
|
|
47
|
+
export const keepPairedChanges = (node) => {
|
|
48
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);
|
|
49
|
+
const dataTracked = (_a = getBlockInlineTrackedData(node)) === null || _a === void 0 ? void 0 : _a.filter((c) => (c.operation === CHANGE_OPERATION.delete && c.moveNodeId) || c.operation === CHANGE_OPERATION.reference);
|
|
50
50
|
return (dataTracked === null || dataTracked === void 0 ? void 0 : dataTracked.length) ? dataTracked : null;
|
|
51
51
|
};
|
|
@@ -30,9 +30,10 @@ export const dropStructuralChangeShadow = (moveNodeId, tr) => {
|
|
|
30
30
|
}
|
|
31
31
|
return tr;
|
|
32
32
|
};
|
|
33
|
-
export const dropOrphanChanges = (newTr
|
|
33
|
+
export const dropOrphanChanges = (newTr) => {
|
|
34
34
|
const changeSet = findChanges(EditorState.create({ doc: newTr.doc }));
|
|
35
35
|
const shadowIds = new Set();
|
|
36
|
+
const referenceIds = new Set();
|
|
36
37
|
const changesIds = new Set();
|
|
37
38
|
changeSet.changes.forEach((c) => {
|
|
38
39
|
if (c.dataTracked.moveNodeId && c.dataTracked.operation === CHANGE_OPERATION.delete) {
|
|
@@ -42,14 +43,38 @@ export const dropOrphanChanges = (newTr, dropDataTracked) => {
|
|
|
42
43
|
c.dataTracked.operation === CHANGE_OPERATION.move) {
|
|
43
44
|
changesIds.add(c.dataTracked.moveNodeId);
|
|
44
45
|
}
|
|
46
|
+
if (c.dataTracked.operation === CHANGE_OPERATION.node_split) {
|
|
47
|
+
changesIds.add(c.dataTracked.id);
|
|
48
|
+
}
|
|
49
|
+
if (c.dataTracked.operation === CHANGE_OPERATION.reference) {
|
|
50
|
+
referenceIds.add(c.dataTracked.referenceId);
|
|
51
|
+
}
|
|
45
52
|
});
|
|
46
|
-
if (!shadowIds.size && !changesIds.size) {
|
|
53
|
+
if (!shadowIds.size && !referenceIds.size && !changesIds.size) {
|
|
47
54
|
return;
|
|
48
55
|
}
|
|
49
56
|
changeSet.changes.forEach((c) => {
|
|
57
|
+
if (c.dataTracked.operation === CHANGE_OPERATION.reference &&
|
|
58
|
+
!changesIds.has(c.dataTracked.referenceId)) {
|
|
59
|
+
const node = newTr.doc.nodeAt(c.from);
|
|
60
|
+
const dataTracked = node && (getBlockInlineTrackedData(node) || []).filter((d) => d.id !== c.id);
|
|
61
|
+
newTr.setNodeMarkup(c.from, undefined, Object.assign(Object.assign({}, node === null || node === void 0 ? void 0 : node.attrs), { dataTracked }));
|
|
62
|
+
}
|
|
63
|
+
if (c.type === 'node-change' &&
|
|
64
|
+
c.dataTracked.operation === CHANGE_OPERATION.node_split &&
|
|
65
|
+
!referenceIds.has(c.id)) {
|
|
66
|
+
const _a = c.dataTracked, { id } = _a, attrs = __rest(_a, ["id"]);
|
|
67
|
+
newTr.replaceWith(c.from, c.to, setFragmentAsInserted(Fragment.from(c.node), createNewInsertAttrs(attrs), newTr.doc.type.schema));
|
|
68
|
+
const referenceChanges = (getBlockInlineTrackedData(c.node) || []).filter((d) => d.operation === CHANGE_OPERATION.reference);
|
|
69
|
+
if (referenceChanges.length) {
|
|
70
|
+
const node = newTr.doc.nodeAt(c.from);
|
|
71
|
+
const dataTracked = (node && getBlockInlineTrackedData(node)) || [];
|
|
72
|
+
newTr.setNodeMarkup(c.from, undefined, Object.assign(Object.assign({}, node === null || node === void 0 ? void 0 : node.attrs), { dataTracked: [...dataTracked, ...referenceChanges] }));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
50
75
|
if (c.dataTracked.moveNodeId &&
|
|
51
76
|
!(shadowIds.has(c.dataTracked.moveNodeId) && changesIds.has(c.dataTracked.moveNodeId))) {
|
|
52
|
-
if (c.dataTracked.operation === CHANGE_OPERATION.delete
|
|
77
|
+
if (c.dataTracked.operation === CHANGE_OPERATION.delete) {
|
|
53
78
|
if (c.type === 'text-change') {
|
|
54
79
|
newTr.removeMark(c.from, c.to, newTr.doc.type.schema.marks.tracked_delete);
|
|
55
80
|
}
|
|
@@ -58,7 +83,7 @@ export const dropOrphanChanges = (newTr, dropDataTracked) => {
|
|
|
58
83
|
}
|
|
59
84
|
}
|
|
60
85
|
else if (c.type === 'node-change') {
|
|
61
|
-
const
|
|
86
|
+
const _b = c.dataTracked, { id, moveNodeId } = _b, attrs = __rest(_b, ["id", "moveNodeId"]);
|
|
62
87
|
newTr.replaceWith(c.from, c.to, setFragmentAsInserted(Fragment.from(c.node), createNewInsertAttrs(attrs), newTr.doc.type.schema));
|
|
63
88
|
}
|
|
64
89
|
}
|