@manuscripts/track-changes-plugin 2.0.13 → 2.1.1
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/change-steps/processChangeSteps.js +1 -1
- package/dist/cjs/changes/applyChanges.js +26 -12
- package/dist/cjs/changes/findChanges.js +16 -0
- package/dist/cjs/changes/revertChange.js +3 -3
- 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/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/change-steps/processChangeSteps.js +1 -1
- package/dist/es/changes/applyChanges.js +26 -11
- package/dist/es/changes/findChanges.js +17 -1
- package/dist/es/changes/revertChange.js +3 -3
- 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/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/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
package/README.md
CHANGED
|
@@ -17,8 +17,8 @@ ProseMirror plugin designed to track changes within a document, similar to the t
|
|
|
17
17
|
Transactions are intercepted and reverted using default plugins lifecycle, unless transaction has meta commanding to skip tracking.
|
|
18
18
|
|
|
19
19
|
- Annotate changes with metadata using node attributes and marks.
|
|
20
|
-
Before transaction is reverted the changes in each step of transaction are processed and created
|
|
21
|
-
with which the inline change is marked on the document. For node changes the dataTracked metadata are assigned to nodes.
|
|
20
|
+
Before transaction is reverted the changes in each step of transaction are processed and metadata are created that describe the changes stored in the dataTracked attributes. For text changes, dataTracked attributes are added to marks,
|
|
21
|
+
with which the inline change is marked on the document. For node changes the dataTracked metadata are assigned to nodes via attributes.
|
|
22
22
|
|
|
23
23
|
- ChangeSet class handles changes interpretation to create a more meaningful representation:
|
|
24
24
|
- Creates a list of top level changes out of a list of nested changed.
|
|
@@ -48,7 +48,7 @@ Nodes that change are extended with dataTracked attributes:
|
|
|
48
48
|
|
|
49
49
|
## Requirements
|
|
50
50
|
|
|
51
|
-
Node schema needs to have { dataTracked: null } attribute declared. Otherwise the node will not be tracked.
|
|
51
|
+
Node or mark schema needs to have { dataTracked: null } attribute declared. Otherwise the node will not be tracked. Plugin also expects schema to support marks for highlighting current changes.
|
|
52
52
|
|
|
53
53
|
## Best practices and caveats
|
|
54
54
|
|
package/dist/cjs/ChangeSet.js
CHANGED
|
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.ChangeSet = void 0;
|
|
16
16
|
const change_1 = require("./types/change");
|
|
17
17
|
const logger_1 = require("./utils/logger");
|
|
18
|
+
const track_utils_1 = require("./utils/track-utils");
|
|
18
19
|
class ChangeSet {
|
|
19
20
|
constructor(changes = []) {
|
|
20
21
|
_ChangeSet_instances.add(this);
|
|
@@ -150,19 +151,34 @@ class ChangeSet {
|
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
153
|
}
|
|
154
|
+
areMatchingWrapOperations(c1, c2) {
|
|
155
|
+
const op1 = c1.dataTracked.operation;
|
|
156
|
+
const op2 = c2.dataTracked.operation;
|
|
157
|
+
return ((op1 === 'wrap_with_node' && (op2 === 'insert' || op2 === 'set_attrs')) ||
|
|
158
|
+
(op2 === 'wrap_with_node' && (op1 === 'insert' || op1 === 'set_attrs')));
|
|
159
|
+
}
|
|
160
|
+
areMatchingMarkOperations(c1, c2) {
|
|
161
|
+
if (ChangeSet.isMarkChange(c1) && ChangeSet.isMarkChange(c2)) {
|
|
162
|
+
const op1 = c1.dataTracked.operation;
|
|
163
|
+
const op2 = c2.dataTracked.operation;
|
|
164
|
+
if (op1 == op2 && c1.mark.type === c2.mark.type) {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
153
170
|
canJoinAdjacentInlineChanges(change, index) {
|
|
154
171
|
const nextChange = this.changeTree.at(index + 1);
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
(c2.dataTracked.operation === 'wrap_with_node' &&
|
|
160
|
-
(c1.dataTracked.operation === 'insert' || c1.dataTracked.operation === 'set_attrs'));
|
|
172
|
+
if (!nextChange) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
const isInline = (c) => c.type === 'text-change' || (c.type === 'node-change' && c.node.isInline) || (0, track_utils_1.isInlineMarkChange)(c);
|
|
161
176
|
return (isInline(change) &&
|
|
162
|
-
nextChange &&
|
|
163
177
|
isInline(nextChange) &&
|
|
164
178
|
change.to === nextChange.from &&
|
|
165
|
-
|
|
179
|
+
(change.dataTracked.operation === nextChange.dataTracked.operation ||
|
|
180
|
+
this.areMatchingWrapOperations(change, nextChange) ||
|
|
181
|
+
this.areMatchingMarkOperations(change, nextChange)));
|
|
166
182
|
}
|
|
167
183
|
joinRelatedStructuralChanges(rootNodes, change) {
|
|
168
184
|
if (change.dataTracked.operation !== change_1.CHANGE_OPERATION.structure) {
|
|
@@ -213,6 +229,9 @@ class ChangeSet {
|
|
|
213
229
|
static isTextChange(change) {
|
|
214
230
|
return change.type === 'text-change';
|
|
215
231
|
}
|
|
232
|
+
static isMarkChange(change) {
|
|
233
|
+
return change.type === 'mark-change';
|
|
234
|
+
}
|
|
216
235
|
static isNodeChange(change) {
|
|
217
236
|
return change.type === 'node-change';
|
|
218
237
|
}
|
|
@@ -67,7 +67,7 @@ function processChangeSteps(changes, startPos, newTr, emptyAttrs, schema, delete
|
|
|
67
67
|
deletesCounter++;
|
|
68
68
|
const prevDeletedNodeInserted = isInserted;
|
|
69
69
|
const trackedData = (0, nodeHelpers_1.getBlockInlineTrackedData)(c.node);
|
|
70
|
-
const inserted = trackedData === null || trackedData === void 0 ? void 0 : trackedData.find((d) => d.operation === change_1.CHANGE_OPERATION.insert);
|
|
70
|
+
const inserted = trackedData === null || trackedData === void 0 ? void 0 : trackedData.find((d) => d.operation === change_1.CHANGE_OPERATION.insert || d.operation === change_1.CHANGE_OPERATION.wrap_with_node);
|
|
71
71
|
const structure = trackedData === null || trackedData === void 0 ? void 0 : trackedData.find((c) => c.operation === change_1.CHANGE_OPERATION.structure &&
|
|
72
72
|
deleteAttrs.moveNodeId &&
|
|
73
73
|
c.moveNodeId !== deleteAttrs.moveNodeId);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getUpdatedDataTracked = getUpdatedDataTracked;
|
|
4
3
|
exports.applyAcceptedRejectedChanges = applyAcceptedRejectedChanges;
|
|
5
4
|
const prosemirror_transform_1 = require("prosemirror-transform");
|
|
6
5
|
const ChangeSet_1 = require("../ChangeSet");
|
|
@@ -8,6 +7,7 @@ const deleteNode_1 = require("../mutate/deleteNode");
|
|
|
8
7
|
const mergeNode_1 = require("../mutate/mergeNode");
|
|
9
8
|
const change_1 = require("../types/change");
|
|
10
9
|
const logger_1 = require("../utils/logger");
|
|
10
|
+
const track_utils_1 = require("../utils/track-utils");
|
|
11
11
|
const revertChange_1 = require("./revertChange");
|
|
12
12
|
const updateChangeAttrs_1 = require("./updateChangeAttrs");
|
|
13
13
|
function collectMoveNodeIds(containerNode, primaryMoveNodeId) {
|
|
@@ -25,13 +25,6 @@ function collectMoveNodeIds(containerNode, primaryMoveNodeId) {
|
|
|
25
25
|
});
|
|
26
26
|
return moveNodeIds;
|
|
27
27
|
}
|
|
28
|
-
function getUpdatedDataTracked(dataTracked, changeId) {
|
|
29
|
-
if (!dataTracked) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
const newDataTracked = dataTracked.filter((c) => c.id !== changeId);
|
|
33
|
-
return newDataTracked.length ? newDataTracked : null;
|
|
34
|
-
}
|
|
35
28
|
function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, deleteMap = new prosemirror_transform_1.Mapping()) {
|
|
36
29
|
changes.sort((c1, c2) => {
|
|
37
30
|
if ((c1.type === 'node-change' && c1.node.type === schema.nodes.list) ||
|
|
@@ -91,13 +84,34 @@ function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, deleteMap
|
|
|
91
84
|
deleteMap.appendMap(tr.steps[tr.steps.length - 1].getMap());
|
|
92
85
|
}
|
|
93
86
|
else if (ChangeSet_1.ChangeSet.isNodeAttrChange(change) && change.dataTracked.status === change_1.CHANGE_STATUS.accepted) {
|
|
94
|
-
tr.setNodeMarkup(from, undefined, Object.assign(Object.assign({}, change.newAttrs), { dataTracked:
|
|
87
|
+
tr.setNodeMarkup(from, undefined, Object.assign(Object.assign({}, change.newAttrs), { dataTracked: (0, track_utils_1.excludeFromTracked)(node.attrs.dataTracked, change.id) }), node.marks);
|
|
95
88
|
}
|
|
96
89
|
else if (ChangeSet_1.ChangeSet.isNodeAttrChange(change) && change.dataTracked.status === change_1.CHANGE_STATUS.rejected) {
|
|
97
|
-
tr.setNodeMarkup(from, undefined, Object.assign(Object.assign({}, change.oldAttrs), { dataTracked:
|
|
90
|
+
tr.setNodeMarkup(from, undefined, Object.assign(Object.assign({}, change.oldAttrs), { dataTracked: (0, track_utils_1.excludeFromTracked)(node.attrs.dataTracked, change.id) }), node.marks);
|
|
98
91
|
}
|
|
99
92
|
else if (ChangeSet_1.ChangeSet.isReferenceChange(change)) {
|
|
100
|
-
tr.setNodeMarkup(from, undefined, Object.assign(Object.assign({}, node.attrs), { dataTracked:
|
|
93
|
+
tr.setNodeMarkup(from, undefined, Object.assign(Object.assign({}, node.attrs), { dataTracked: (0, track_utils_1.excludeFromTracked)(node.attrs.dataTracked, change.id) }), node.marks);
|
|
94
|
+
}
|
|
95
|
+
else if (ChangeSet_1.ChangeSet.isMarkChange(change)) {
|
|
96
|
+
const newMark = change.mark.type.create({
|
|
97
|
+
dataTracked: (0, track_utils_1.excludeFromTracked)(change.mark.attrs.dataTracked, change.id),
|
|
98
|
+
});
|
|
99
|
+
const isInsert = change.dataTracked.operation === change_1.CHANGE_OPERATION.insert;
|
|
100
|
+
const isDelete = change.dataTracked.operation === change_1.CHANGE_OPERATION.delete;
|
|
101
|
+
const toBeRestored = (change.dataTracked.status === change_1.CHANGE_STATUS.accepted && isInsert) ||
|
|
102
|
+
(change.dataTracked.status === change_1.CHANGE_STATUS.rejected && isDelete);
|
|
103
|
+
if ((0, track_utils_1.isInlineMarkChange)(change)) {
|
|
104
|
+
tr.removeMark(change.from, change.to, change.mark);
|
|
105
|
+
if (toBeRestored) {
|
|
106
|
+
tr.addMark(change.from, change.to, newMark);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
tr.removeNodeMark(change.from, change.mark);
|
|
111
|
+
if (toBeRestored) {
|
|
112
|
+
tr.addNodeMark(change.from, newMark);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
101
115
|
}
|
|
102
116
|
});
|
|
103
117
|
changes.forEach((change) => {
|
|
@@ -114,7 +128,7 @@ function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, deleteMap
|
|
|
114
128
|
return;
|
|
115
129
|
}
|
|
116
130
|
if (change.dataTracked.status === change_1.CHANGE_STATUS.accepted) {
|
|
117
|
-
const attrs = Object.assign(Object.assign({}, node.attrs), { dataTracked:
|
|
131
|
+
const attrs = Object.assign(Object.assign({}, node.attrs), { dataTracked: (0, track_utils_1.excludeFromTracked)(node.attrs.dataTracked, change.id) });
|
|
118
132
|
tr.setNodeMarkup(from, undefined, attrs, node.marks);
|
|
119
133
|
const originalChanges = changeSet.changes.filter((c) => c.dataTracked.moveNodeId === change.dataTracked.moveNodeId &&
|
|
120
134
|
c.dataTracked.operation === change_1.CHANGE_OPERATION.delete);
|
|
@@ -9,6 +9,22 @@ function findChanges(state) {
|
|
|
9
9
|
let current;
|
|
10
10
|
state.doc.descendants((node, pos) => {
|
|
11
11
|
const tracked = (0, nodeHelpers_1.getNodeTrackedData)(node, state.schema) || [];
|
|
12
|
+
const marksWithTrackChanges = (0, nodeHelpers_1.getMarkTrackedData)(node);
|
|
13
|
+
marksWithTrackChanges === null || marksWithTrackChanges === void 0 ? void 0 : marksWithTrackChanges.forEach((trackAttrs, mark) => {
|
|
14
|
+
trackAttrs.forEach((c) => {
|
|
15
|
+
const ch = {
|
|
16
|
+
id: c.id,
|
|
17
|
+
type: 'mark-change',
|
|
18
|
+
from: pos,
|
|
19
|
+
to: pos + node.nodeSize,
|
|
20
|
+
dataTracked: Object.assign({}, c),
|
|
21
|
+
nodeType: node.type,
|
|
22
|
+
node: node,
|
|
23
|
+
mark: mark,
|
|
24
|
+
};
|
|
25
|
+
changes.push(ch);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
12
28
|
for (let i = 0; i < tracked.length; i += 1) {
|
|
13
29
|
const dataTracked = tracked[i];
|
|
14
30
|
const id = dataTracked.id || '';
|
|
@@ -5,7 +5,7 @@ exports.revertWrapNodeChange = revertWrapNodeChange;
|
|
|
5
5
|
const prosemirror_model_1 = require("prosemirror-model");
|
|
6
6
|
const prosemirror_transform_1 = require("prosemirror-transform");
|
|
7
7
|
const nodeHelpers_1 = require("../compute/nodeHelpers");
|
|
8
|
-
const
|
|
8
|
+
const track_utils_1 = require("../utils/track-utils");
|
|
9
9
|
function revertSplitNodeChange(tr, change, changeSet) {
|
|
10
10
|
const sourceChange = changeSet.changes.find((c) => c.dataTracked.operation === 'reference' && c.dataTracked.referenceId === change.id);
|
|
11
11
|
const node = tr.doc.nodeAt(tr.mapping.map(change.from));
|
|
@@ -24,7 +24,7 @@ function revertSplitNodeChange(tr, change, changeSet) {
|
|
|
24
24
|
const deleteChange = changeSet.changes.find((c) => c.dataTracked.operation == 'delete' && c.from === sourceChange.from);
|
|
25
25
|
if (deleteChange) {
|
|
26
26
|
const node = tr.doc.nodeAt(tr.mapping.map(deleteChange.from));
|
|
27
|
-
tr.setNodeMarkup(tr.mapping.map(deleteChange.from), undefined, (0,
|
|
27
|
+
tr.setNodeMarkup(tr.mapping.map(deleteChange.from), undefined, (0, track_utils_1.excludeFromTracked)(node.attrs.dataTracked, deleteChange.id));
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
function revertWrapNodeChange(tr, change, deleteMap) {
|
|
@@ -39,7 +39,7 @@ function revertWrapNodeChange(tr, change, deleteMap) {
|
|
|
39
39
|
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
40
40
|
const $fromPos = tr.doc.resolve(tr.mapping.map(pos));
|
|
41
41
|
const $toPos = tr.doc.resolve(tr.mapping.map(pos + node.nodeSize - 1));
|
|
42
|
-
const nodeRange = $fromPos.blockRange($toPos);
|
|
42
|
+
const nodeRange = $fromPos.blockRange($toPos, (node) => { var _a; return !!((_a = change.node) === null || _a === void 0 ? void 0 : _a.type.contentMatch.matchType(node.type)); });
|
|
43
43
|
if (!nodeRange) {
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
@@ -7,6 +7,7 @@ const ChangeSet_1 = require("../ChangeSet");
|
|
|
7
7
|
const nodeHelpers_1 = require("../compute/nodeHelpers");
|
|
8
8
|
const change_1 = require("../types/change");
|
|
9
9
|
const logger_1 = require("../utils/logger");
|
|
10
|
+
const track_utils_1 = require("../utils/track-utils");
|
|
10
11
|
function updateChangeAttrs(tr, change, trackedAttrs, schema) {
|
|
11
12
|
const node = tr.doc.nodeAt(change.from);
|
|
12
13
|
if (!node) {
|
|
@@ -69,6 +70,32 @@ function updateChangeAttrs(tr, change, trackedAttrs, schema) {
|
|
|
69
70
|
.filter(Boolean);
|
|
70
71
|
tr.setNodeMarkup(change.from, undefined, Object.assign(Object.assign({}, (restoredAttrs || node.attrs)), { dataTracked: newDataTracked.length === 0 ? null : newDataTracked }), node.marks);
|
|
71
72
|
}
|
|
73
|
+
else if (change.type === 'mark-change') {
|
|
74
|
+
const markChange = change;
|
|
75
|
+
if (markChange.mark && markChange.from && markChange.to) {
|
|
76
|
+
const markDataTracked = Array.isArray(markChange.mark.attrs.dataTracked)
|
|
77
|
+
? markChange.mark.attrs.dataTracked
|
|
78
|
+
: [];
|
|
79
|
+
const newDT = markDataTracked === null || markDataTracked === void 0 ? void 0 : markDataTracked.map((dt) => {
|
|
80
|
+
if (dt.createdAt === change.dataTracked.createdAt && dt.operation === change.dataTracked.operation) {
|
|
81
|
+
return Object.assign(Object.assign({}, dt), trackedAttrs);
|
|
82
|
+
}
|
|
83
|
+
return dt;
|
|
84
|
+
});
|
|
85
|
+
const newMark = markChange.mark.type.create(Object.assign(Object.assign({}, markChange.mark.attrs), { dataTracked: newDT }));
|
|
86
|
+
if ((0, track_utils_1.isInlineMarkChange)(markChange)) {
|
|
87
|
+
tr.removeMark(markChange.from, markChange.to, markChange.mark);
|
|
88
|
+
tr.addMark(markChange.from, markChange.to, newMark);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
tr.removeNodeMark(markChange.from, markChange.mark);
|
|
92
|
+
tr.addNodeMark(markChange.from, newMark);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
console.warn('Unable to update a mark change because the mark change data are incomplete');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
72
99
|
return tr;
|
|
73
100
|
}
|
|
74
101
|
function updateChangeChildrenAttributes(changes, tr, mapping) {
|
|
@@ -3,12 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.addTrackIdIfDoesntExist = addTrackIdIfDoesntExist;
|
|
4
4
|
exports.getTextNodeTrackedMarkData = getTextNodeTrackedMarkData;
|
|
5
5
|
exports.getBlockInlineTrackedData = getBlockInlineTrackedData;
|
|
6
|
+
exports.getMarkTrackedData = getMarkTrackedData;
|
|
6
7
|
exports.getNodeTrackedData = getNodeTrackedData;
|
|
7
8
|
exports.equalMarks = equalMarks;
|
|
8
9
|
exports.shouldMergeTrackedAttributes = shouldMergeTrackedAttributes;
|
|
9
10
|
exports.getMergeableMarkTrackedAttrs = getMergeableMarkTrackedAttrs;
|
|
10
11
|
const change_1 = require("../types/change");
|
|
11
12
|
const logger_1 = require("../utils/logger");
|
|
13
|
+
const track_utils_1 = require("../utils/track-utils");
|
|
12
14
|
const uuidv4_1 = require("../utils/uuidv4");
|
|
13
15
|
function addTrackIdIfDoesntExist(attrs) {
|
|
14
16
|
if (!attrs.id) {
|
|
@@ -39,6 +41,15 @@ function getBlockInlineTrackedData(node) {
|
|
|
39
41
|
}
|
|
40
42
|
return dataTracked || [];
|
|
41
43
|
}
|
|
44
|
+
function getMarkTrackedData(node) {
|
|
45
|
+
const tracked = node === null || node === void 0 ? void 0 : node.marks.reduce((acc, current) => {
|
|
46
|
+
if ((0, track_utils_1.isValidTrackableMark)(current) && current.attrs.dataTracked) {
|
|
47
|
+
acc.set(current, current.attrs.dataTracked);
|
|
48
|
+
}
|
|
49
|
+
return acc;
|
|
50
|
+
}, new Map());
|
|
51
|
+
return tracked || new Map();
|
|
52
|
+
}
|
|
42
53
|
function getNodeTrackedData(node, schema) {
|
|
43
54
|
let tracked;
|
|
44
55
|
if (node && !node.isText) {
|
|
@@ -37,6 +37,7 @@ exports.deleteAndMergeSplitNodes = deleteAndMergeSplitNodes;
|
|
|
37
37
|
const prosemirror_model_1 = require("prosemirror-model");
|
|
38
38
|
const setFragmentAsInserted_1 = require("../compute/setFragmentAsInserted");
|
|
39
39
|
const splitSliceIntoMergedParts_1 = require("../compute/splitSliceIntoMergedParts");
|
|
40
|
+
const utils_1 = require("../steps/utils");
|
|
40
41
|
const trackUtils = __importStar(require("../utils/track-utils"));
|
|
41
42
|
function deleteAndMergeSplitNodes(from, to, gap, startDoc, newTr, schema, trackAttrs, insertSlice) {
|
|
42
43
|
const steps = [];
|
|
@@ -69,7 +70,7 @@ function deleteAndMergeSplitNodes(from, to, gap, startDoc, newTr, schema, trackA
|
|
|
69
70
|
const mergeEndNode = startTokenDeleted && openEnd > 0 && depth === openEnd && mergeContent;
|
|
70
71
|
const mergeEndNodeNotEmpty = mergeEndNode && mergeContent.size;
|
|
71
72
|
if (mergeEndNode && !mergeEndNodeNotEmpty && gap) {
|
|
72
|
-
if (
|
|
73
|
+
if ((0, utils_1.stepIsLift)(gap, node, to)) {
|
|
73
74
|
gap.slice.content.forEach((node, offset) => {
|
|
74
75
|
steps.push({
|
|
75
76
|
type: 'delete-node',
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.trackRemoveMarkStep = trackRemoveMarkStep;
|
|
4
|
+
exports.trackRemoveNodeMarkStep = trackRemoveNodeMarkStep;
|
|
5
|
+
exports.trackAddMarkStep = trackAddMarkStep;
|
|
6
|
+
exports.trackAddNodeMarkStep = trackAddNodeMarkStep;
|
|
7
|
+
const prosemirror_transform_1 = require("prosemirror-transform");
|
|
8
|
+
const change_1 = require("../types/change");
|
|
9
|
+
const track_utils_1 = require("../utils/track-utils");
|
|
10
|
+
const uuidv4_1 = require("../utils/uuidv4");
|
|
11
|
+
function markHasOp(mark, operation) {
|
|
12
|
+
if (mark.attrs.dataTracked && Array.isArray(mark.attrs.dataTracked)) {
|
|
13
|
+
const dtAttrs = mark.attrs.dataTracked;
|
|
14
|
+
return dtAttrs.some((at) => at.operation === operation);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function trackRemoveMarkStep(step, emptyAttrs, newTr, doc) {
|
|
18
|
+
if ((0, track_utils_1.isValidTrackableMark)(step.mark)) {
|
|
19
|
+
const markName = step.mark.type.name;
|
|
20
|
+
const markSource = step.mark.type.schema.marks[step.mark.type.name];
|
|
21
|
+
let sameMark = null;
|
|
22
|
+
const targetNode = doc.nodeAt(step.from);
|
|
23
|
+
if (targetNode) {
|
|
24
|
+
let targetNodePos = -1;
|
|
25
|
+
doc.descendants((node, pos) => {
|
|
26
|
+
if (node === targetNode) {
|
|
27
|
+
targetNodePos = pos;
|
|
28
|
+
}
|
|
29
|
+
if (targetNodePos >= 0) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
const parentsSameMark = targetNode.marks.find((mark) => {
|
|
34
|
+
var _a;
|
|
35
|
+
if (mark.type.name === markName && ((_a = mark.attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
36
|
+
return mark;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
const nodeEnd = targetNodePos + targetNode.nodeSize;
|
|
40
|
+
if (parentsSameMark && step.from <= nodeEnd && step.to <= nodeEnd) {
|
|
41
|
+
sameMark = parentsSameMark;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const newDataTracked = (0, track_utils_1.createNewDeleteAttrs)(emptyAttrs);
|
|
45
|
+
const newMark = markSource.create({
|
|
46
|
+
dataTracked: [Object.assign(Object.assign({}, newDataTracked), { id: (0, uuidv4_1.uuidv4)() })],
|
|
47
|
+
});
|
|
48
|
+
let newStep = new prosemirror_transform_1.AddMarkStep(step.from, step.to, newMark);
|
|
49
|
+
if (sameMark) {
|
|
50
|
+
if (markHasOp(step.mark, change_1.CHANGE_OPERATION.delete)) {
|
|
51
|
+
newStep = new prosemirror_transform_1.AddMarkStep(step.from, step.to, markSource.create({
|
|
52
|
+
dataTracked: [],
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
if (markHasOp(step.mark, change_1.CHANGE_OPERATION.insert)) {
|
|
56
|
+
newStep = new prosemirror_transform_1.RemoveMarkStep(step.from, step.to, step.mark);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
newTr.step(newStep);
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
console.error('Unable to record a RemoveMarkStep with error: ' + e);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function trackRemoveNodeMarkStep(step, emptyAttrs, newTr, doc) {
|
|
68
|
+
if ((0, track_utils_1.isValidTrackableMark)(step.mark)) {
|
|
69
|
+
const markName = step.mark.type.name;
|
|
70
|
+
const markSource = step.mark.type.schema.marks[markName];
|
|
71
|
+
let sameMark = null;
|
|
72
|
+
const targetNode = doc.nodeAt(step.pos);
|
|
73
|
+
if (targetNode) {
|
|
74
|
+
targetNode.marks.find((mark) => {
|
|
75
|
+
var _a;
|
|
76
|
+
if (mark.type.name === markName && ((_a = mark.attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
77
|
+
sameMark = mark;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const newDataTracked = (0, track_utils_1.createNewDeleteAttrs)(emptyAttrs);
|
|
82
|
+
const newMark = markSource.create({
|
|
83
|
+
dataTracked: [Object.assign(Object.assign({}, newDataTracked), { id: (0, uuidv4_1.uuidv4)() })],
|
|
84
|
+
});
|
|
85
|
+
let newStep = new prosemirror_transform_1.AddNodeMarkStep(step.pos, newMark);
|
|
86
|
+
if (sameMark) {
|
|
87
|
+
if (markHasOp(step.mark, change_1.CHANGE_OPERATION.delete)) {
|
|
88
|
+
newStep = new prosemirror_transform_1.AddNodeMarkStep(step.pos, markSource.create({
|
|
89
|
+
dataTracked: [],
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
if (markHasOp(step.mark, change_1.CHANGE_OPERATION.insert)) {
|
|
93
|
+
newStep = new prosemirror_transform_1.AddNodeMarkStep(step.pos, step.mark);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
newTr.step(newStep);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
console.error('Unable to record a RemoveNodeMarkStep with error: ' + e);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function trackAddMarkStep(step, emptyAttrs, newTr, doc) {
|
|
105
|
+
if ((0, track_utils_1.isValidTrackableMark)(step.mark)) {
|
|
106
|
+
const markName = step.mark.type.name;
|
|
107
|
+
const markSource = step.mark.type.schema.marks[markName];
|
|
108
|
+
const newDataTracked = (0, track_utils_1.createNewInsertAttrs)(emptyAttrs);
|
|
109
|
+
const newMark = markSource.create({
|
|
110
|
+
dataTracked: [Object.assign(Object.assign({}, newDataTracked), { id: (0, uuidv4_1.uuidv4)() })],
|
|
111
|
+
});
|
|
112
|
+
const newStep = new prosemirror_transform_1.AddMarkStep(step.from, step.to, newMark);
|
|
113
|
+
try {
|
|
114
|
+
const inverted = step.invert();
|
|
115
|
+
newTr.step(inverted);
|
|
116
|
+
newTr.step(newStep);
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
console.error('Unable to record a remove node mark step: ' + e);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function trackAddNodeMarkStep(step, emptyAttrs, newTr, stepDoc) {
|
|
124
|
+
if ((0, track_utils_1.isValidTrackableMark)(step.mark)) {
|
|
125
|
+
const newDataTracked = (0, track_utils_1.createNewInsertAttrs)(emptyAttrs);
|
|
126
|
+
const markSource = step.mark.type.schema.marks[step.mark.type.name];
|
|
127
|
+
const newMark = markSource.create({
|
|
128
|
+
dataTracked: [Object.assign(Object.assign({}, newDataTracked), { id: (0, uuidv4_1.uuidv4)() })],
|
|
129
|
+
});
|
|
130
|
+
const newStep = new prosemirror_transform_1.AddNodeMarkStep(step.pos, newMark);
|
|
131
|
+
try {
|
|
132
|
+
const inverted = step.invert(stepDoc);
|
|
133
|
+
newTr.step(inverted);
|
|
134
|
+
newTr.step(newStep);
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
console.error('Unable to record an AddNodeMarkStep with error: ' + e);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -40,7 +40,7 @@ const setFragmentAsInserted_1 = require("../compute/setFragmentAsInserted");
|
|
|
40
40
|
const deleteAndMergeSplitNodes_1 = require("../mutate/deleteAndMergeSplitNodes");
|
|
41
41
|
const logger_1 = require("../utils/logger");
|
|
42
42
|
const trackUtils = __importStar(require("../utils/track-utils"));
|
|
43
|
-
const
|
|
43
|
+
const utils_1 = require("./utils");
|
|
44
44
|
function preserveDataTrackedFromPreviousStep(newTr, step, newStep) {
|
|
45
45
|
const prevDoc = newTr.docs[newTr.docs.length - 2];
|
|
46
46
|
if (prevDoc && (step.slice.openEnd || step.slice.openStart)) {
|
|
@@ -68,7 +68,7 @@ function trackReplaceAroundStep(step, oldState, tr, newTr, attrs, currentStepDoc
|
|
|
68
68
|
logger_1.log.info('RETAINED GAP CONTENT', gap);
|
|
69
69
|
let { sliceWasSplit, newSliceContent, steps: deleteSteps, } = (0, deleteAndMergeSplitNodes_1.deleteAndMergeSplitNodes)(from, to, { start: gapFrom, end: gapTo, slice: gap, insert }, newTr.doc, newTr, oldState.schema, attrs, slice);
|
|
70
70
|
let fragment;
|
|
71
|
-
if ((0,
|
|
71
|
+
if ((0, utils_1.isWrapStep)(step)) {
|
|
72
72
|
fragment = (0, setFragmentAsInserted_1.setFragmentAsWrapChange)(newSliceContent, attrs, oldState.schema);
|
|
73
73
|
}
|
|
74
74
|
else {
|
|
@@ -77,7 +77,7 @@ function trackReplaceAroundStep(step, oldState, tr, newTr, attrs, currentStepDoc
|
|
|
77
77
|
let steps = deleteSteps;
|
|
78
78
|
logger_1.log.info('TR: new steps after applying delete', [...newTr.steps]);
|
|
79
79
|
logger_1.log.info('DELETE STEPS: ', deleteSteps);
|
|
80
|
-
let liftStep = (0,
|
|
80
|
+
let liftStep = (0, utils_1.isLiftStep)(step);
|
|
81
81
|
if (liftStep) {
|
|
82
82
|
logger_1.log.info('DETECTING INIT LIFT STEP: ', step);
|
|
83
83
|
trContext.prevLiftStep = step;
|
|
@@ -41,7 +41,7 @@ const deleteAndMergeSplitNodes_1 = require("../mutate/deleteAndMergeSplitNodes")
|
|
|
41
41
|
const dropStructureChange_1 = require("../mutate/dropStructureChange");
|
|
42
42
|
const logger_1 = require("../utils/logger");
|
|
43
43
|
const trackUtils = __importStar(require("../utils/track-utils"));
|
|
44
|
-
const
|
|
44
|
+
const utils_1 = require("./utils");
|
|
45
45
|
function trackReplaceStep(step, oldState, newTr, attrsTemplate, stepResult, currentStepDoc, tr, moveID) {
|
|
46
46
|
logger_1.log.info('###### ReplaceStep ######');
|
|
47
47
|
let selectionPos = 0;
|
|
@@ -78,10 +78,10 @@ function trackReplaceStep(step, oldState, newTr, attrsTemplate, stepResult, curr
|
|
|
78
78
|
if (!backSpacedText && newSliceContent.size > 0) {
|
|
79
79
|
logger_1.log.info('newSliceContent', newSliceContent);
|
|
80
80
|
let fragment = (0, setFragmentAsInserted_1.setFragmentAsInserted)(newSliceContent, trackUtils.createNewInsertAttrs(attrs), oldState.schema);
|
|
81
|
-
if ((0,
|
|
81
|
+
if ((0, utils_1.isStructureSteps)(tr)) {
|
|
82
82
|
fragment = (0, dropStructureChange_1.joinStructureChanges)(attrs, newSliceContent, fragment, tr, newTr);
|
|
83
83
|
}
|
|
84
|
-
else if ((0,
|
|
84
|
+
else if ((0, utils_1.isSplitStep)(step, oldState.selection, tr.getMeta('uiEvent'))) {
|
|
85
85
|
fragment = (0, setFragmentAsInserted_1.setFragmentAsNodeSplit)(newTr.doc.resolve(step.from), newTr, fragment, attrs);
|
|
86
86
|
}
|
|
87
87
|
else if (moveID) {
|
|
@@ -17,8 +17,10 @@ const mapChangeStep_1 = require("../utils/mapChangeStep");
|
|
|
17
17
|
const track_utils_1 = require("../utils/track-utils");
|
|
18
18
|
const uuidv4_1 = require("../utils/uuidv4");
|
|
19
19
|
const trackAttrsChange_1 = __importDefault(require("./trackAttrsChange"));
|
|
20
|
+
const trackMarkSteps_1 = require("./trackMarkSteps");
|
|
20
21
|
const trackReplaceAroundStep_1 = require("./trackReplaceAroundStep");
|
|
21
22
|
const trackReplaceStep_1 = require("./trackReplaceStep");
|
|
23
|
+
const utils_1 = require("./utils");
|
|
22
24
|
const getSelectionStaticConstructor = (sel) => Object.getPrototypeOf(sel).constructor;
|
|
23
25
|
const isHighlightMarkerNode = (node) => node && node.type === node.type.schema.nodes.highlight_marker;
|
|
24
26
|
function trackTransaction(tr, oldState, newTr, authorID, changeSet) {
|
|
@@ -74,7 +76,7 @@ function trackTransaction(tr, oldState, newTr, authorID, changeSet) {
|
|
|
74
76
|
const invertedStep = step.invert(tr.docs[i]);
|
|
75
77
|
const isDelete = step.from !== step.to && step.slice.content.size < invertedStep.slice.content.size;
|
|
76
78
|
let thisStepMapping = tr.mapping.slice(i + 1, i + 1);
|
|
77
|
-
if (isDelete || (0,
|
|
79
|
+
if (isDelete || (0, utils_1.isStructureSteps)(tr)) {
|
|
78
80
|
thisStepMapping = deletedNodeMapping;
|
|
79
81
|
}
|
|
80
82
|
const newStep = new prosemirror_transform_1.ReplaceStep(thisStepMapping.map(invertedStep.from), thisStepMapping.map(invertedStep.to), invertedStep.slice);
|
|
@@ -115,17 +117,27 @@ function trackTransaction(tr, oldState, newTr, authorID, changeSet) {
|
|
|
115
117
|
const [mapping, selectionPos] = (0, processChangeSteps_1.processChangeSteps)(changeSteps, tr.selection.from, newTr, emptyAttrs, oldState.schema, deletedNodeMapping);
|
|
116
118
|
}
|
|
117
119
|
else if (step instanceof prosemirror_transform_1.AddMarkStep) {
|
|
120
|
+
(0, trackMarkSteps_1.trackAddMarkStep)(step, emptyAttrs, newTr, tr.docs[i]);
|
|
118
121
|
const dataTracked = (_f = (0, nodeHelpers_1.getNodeTrackedData)(newTr.doc.nodeAt(step.from), oldState.schema)) === null || _f === void 0 ? void 0 : _f.pop();
|
|
119
122
|
if (dataTracked) {
|
|
120
123
|
(0, updateChangeAttrs_1.updateChangeAttrs)(newTr, { id: dataTracked.id, from: step.from, to: step.to, type: 'text-change', dataTracked }, Object.assign(Object.assign({}, dataTracked), { id: (0, uuidv4_1.uuidv4)() }), oldState.schema);
|
|
121
124
|
}
|
|
122
125
|
}
|
|
126
|
+
else if (step instanceof prosemirror_transform_1.RemoveMarkStep) {
|
|
127
|
+
(0, trackMarkSteps_1.trackRemoveMarkStep)(step, emptyAttrs, newTr, tr.docs[i]);
|
|
128
|
+
}
|
|
129
|
+
else if (step instanceof prosemirror_transform_1.RemoveNodeMarkStep) {
|
|
130
|
+
(0, trackMarkSteps_1.trackRemoveNodeMarkStep)(step, emptyAttrs, newTr, tr.docs[i]);
|
|
131
|
+
}
|
|
132
|
+
else if (step instanceof prosemirror_transform_1.AddNodeMarkStep) {
|
|
133
|
+
(0, trackMarkSteps_1.trackAddNodeMarkStep)(step, emptyAttrs, newTr, tr.docs[i]);
|
|
134
|
+
}
|
|
123
135
|
tr.getMeta('inputType') && newTr.setMeta('inputType', tr.getMeta('inputType'));
|
|
124
136
|
tr.getMeta('uiEvent') && newTr.setMeta('uiEvent', tr.getMeta('uiEvent'));
|
|
125
137
|
}
|
|
126
138
|
if (setsNewSelection && tr.selection instanceof prosemirror_state_1.TextSelection) {
|
|
127
139
|
let from = tr.selection.from;
|
|
128
|
-
if ((0,
|
|
140
|
+
if ((0, utils_1.isStructureSteps)(tr)) {
|
|
129
141
|
const selectionMapping = new prosemirror_transform_1.Mapping();
|
|
130
142
|
tr.steps.map((step) => {
|
|
131
143
|
const isDeleteStep = step instanceof prosemirror_transform_1.ReplaceStep && step.from !== step.to && step.slice.size === 0;
|
|
@@ -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;
|