@manuscripts/track-changes-plugin 2.1.1 → 2.2.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.
Files changed (122) hide show
  1. package/dist/cjs/ChangeSet.js +23 -9
  2. package/dist/cjs/actions.js +3 -1
  3. package/dist/cjs/{changes/applyChanges.js → applyChanges.js} +16 -16
  4. package/dist/cjs/{changes → changeHelpers}/revertChange.js +3 -4
  5. package/dist/cjs/{mutate/dropStructureChange.js → changeHelpers/structureChange.js} +23 -17
  6. package/dist/cjs/{changes → changeHelpers}/updateChangeAttrs.js +4 -5
  7. package/dist/cjs/{changes → changeHelpers}/updateChangesStatus.js +5 -5
  8. package/dist/cjs/{changes/findChanges.js → findChanges.js} +5 -5
  9. package/dist/cjs/helpers/attributes.js +157 -0
  10. package/dist/cjs/{compute/setFragmentAsInserted.js → helpers/fragment.js} +71 -79
  11. package/dist/cjs/helpers/mark.js +19 -0
  12. package/dist/cjs/plugin.js +13 -22
  13. package/dist/cjs/trackChanges.js +47 -0
  14. package/dist/cjs/{change-steps → tracking/change-step}/diffChangeSteps.js +23 -28
  15. package/dist/cjs/{utils/mapChangeStep.js → tracking/change-step/mapChangeSteps.js} +1 -1
  16. package/dist/cjs/{change-steps → tracking/change-step}/processChangeSteps.js +14 -48
  17. package/dist/cjs/tracking/fixAndHandleSelection.js +54 -0
  18. package/dist/cjs/{mutate → tracking/lib}/deleteAndMergeSplitNodes.js +7 -40
  19. package/dist/cjs/{mutate → tracking/lib}/deleteNode.js +8 -9
  20. package/dist/cjs/{mutate/deleteText.js → tracking/lib/deleteTextIfInserted.js} +4 -4
  21. package/dist/cjs/{change-steps → tracking/lib}/matchInserted.js +15 -23
  22. package/dist/cjs/{mutate → tracking/lib}/mergeTrackedMarks.js +3 -3
  23. package/dist/cjs/tracking/lib/processStepsBeforeTracking.js +17 -0
  24. package/dist/cjs/{steps/utils.js → tracking/steps-trackers/qualifiers.js} +37 -10
  25. package/dist/cjs/{steps/trackAttrsChange.js → tracking/steps-trackers/trackAttrsChangeStep.js} +3 -3
  26. package/dist/cjs/{steps → tracking/steps-trackers}/trackMarkSteps.js +14 -11
  27. package/dist/cjs/{steps → tracking/steps-trackers}/trackReplaceAroundStep.js +12 -46
  28. package/dist/cjs/tracking/steps-trackers/trackReplaceStep.js +85 -0
  29. package/dist/cjs/tracking/trackTransaction.js +93 -0
  30. package/dist/cjs/tracking/transactionProcessing.js +164 -0
  31. package/dist/cjs/tracking/types.js +17 -0
  32. package/dist/es/ChangeSet.js +23 -9
  33. package/dist/es/actions.js +1 -0
  34. package/dist/es/{changes/applyChanges.js → applyChanges.js} +10 -10
  35. package/dist/es/{changes → changeHelpers}/revertChange.js +1 -2
  36. package/dist/es/{mutate/dropStructureChange.js → changeHelpers/structureChange.js} +10 -5
  37. package/dist/es/{changes → changeHelpers}/updateChangeAttrs.js +2 -3
  38. package/dist/es/{changes → changeHelpers}/updateChangesStatus.js +4 -4
  39. package/dist/es/{changes/findChanges.js → findChanges.js} +3 -3
  40. package/dist/es/helpers/attributes.js +136 -0
  41. package/dist/es/{compute/setFragmentAsInserted.js → helpers/fragment.js} +66 -42
  42. package/dist/es/helpers/mark.js +15 -0
  43. package/dist/es/plugin.js +12 -21
  44. package/dist/es/trackChanges.js +44 -0
  45. package/dist/es/{change-steps → tracking/change-step}/diffChangeSteps.js +23 -28
  46. package/dist/es/{utils/mapChangeStep.js → tracking/change-step/mapChangeSteps.js} +1 -1
  47. package/dist/es/{change-steps → tracking/change-step}/processChangeSteps.js +10 -11
  48. package/dist/es/tracking/fixAndHandleSelection.js +49 -0
  49. package/dist/es/{mutate → tracking/lib}/deleteAndMergeSplitNodes.js +7 -7
  50. package/dist/es/{mutate → tracking/lib}/deleteNode.js +4 -5
  51. package/dist/es/{mutate/deleteText.js → tracking/lib/deleteTextIfInserted.js} +1 -1
  52. package/dist/es/{change-steps → tracking/lib}/matchInserted.js +15 -23
  53. package/dist/es/{mutate → tracking/lib}/mergeTrackedMarks.js +2 -2
  54. package/dist/es/tracking/lib/processStepsBeforeTracking.js +14 -0
  55. package/dist/es/{steps/utils.js → tracking/steps-trackers/qualifiers.js} +32 -7
  56. package/dist/es/{steps/trackAttrsChange.js → tracking/steps-trackers/trackAttrsChangeStep.js} +3 -3
  57. package/dist/es/{steps → tracking/steps-trackers}/trackMarkSteps.js +6 -3
  58. package/dist/es/{steps → tracking/steps-trackers}/trackReplaceAroundStep.js +9 -10
  59. package/dist/es/{steps → tracking/steps-trackers}/trackReplaceStep.js +34 -26
  60. package/dist/es/tracking/trackTransaction.js +87 -0
  61. package/dist/es/tracking/transactionProcessing.js +153 -0
  62. package/dist/es/tracking/types.js +16 -0
  63. package/dist/types/ChangeSet.d.ts +4 -1
  64. package/dist/types/actions.d.ts +1 -0
  65. package/dist/types/applyChanges.d.ts +6 -0
  66. package/dist/types/{mutate/dropStructureChange.d.ts → changeHelpers/structureChange.d.ts} +2 -1
  67. package/dist/types/{changes/findChanges.d.ts → findChanges.d.ts} +1 -1
  68. package/dist/types/helpers/attributes.d.ts +47 -0
  69. package/dist/types/{compute/setFragmentAsInserted.d.ts → helpers/fragment.d.ts} +3 -1
  70. package/dist/types/helpers/mark.d.ts +3 -0
  71. package/dist/types/trackChanges.d.ts +17 -0
  72. package/dist/types/tracking/change-step/diffChangeSteps.d.ts +17 -0
  73. package/dist/types/{utils/mapChangeStep.d.ts → tracking/change-step/mapChangeSteps.d.ts} +2 -2
  74. package/dist/types/tracking/change-step/processChangeSteps.d.ts +6 -0
  75. package/dist/types/tracking/fixAndHandleSelection.d.ts +20 -0
  76. package/dist/types/{mutate → tracking/lib}/deleteAndMergeSplitNodes.d.ts +4 -5
  77. package/dist/types/{mutate → tracking/lib}/deleteNode.d.ts +2 -2
  78. package/dist/types/{mutate/deleteText.d.ts → tracking/lib/deleteTextIfInserted.d.ts} +1 -1
  79. package/dist/types/tracking/lib/matchInserted.d.ts +18 -0
  80. package/dist/types/tracking/lib/processStepsBeforeTracking.d.ts +4 -0
  81. package/dist/types/{compute → tracking/lib}/splitSliceIntoMergedParts.d.ts +1 -1
  82. package/dist/types/{steps/utils.d.ts → tracking/steps-trackers/qualifiers.d.ts} +5 -3
  83. package/dist/types/{steps/trackAttrsChange.d.ts → tracking/steps-trackers/trackAttrsChangeStep.d.ts} +4 -4
  84. package/dist/types/{steps → tracking/steps-trackers}/trackMarkSteps.d.ts +1 -1
  85. package/dist/types/{steps → tracking/steps-trackers}/trackReplaceAroundStep.d.ts +2 -2
  86. package/dist/types/tracking/steps-trackers/trackReplaceStep.d.ts +5 -0
  87. package/dist/types/tracking/trackTransaction.d.ts +4 -0
  88. package/dist/types/tracking/transactionProcessing.d.ts +12 -0
  89. package/dist/types/tracking/types.d.ts +65 -0
  90. package/dist/types/types/change.d.ts +1 -1
  91. package/dist/types/types/track.d.ts +0 -30
  92. package/package.json +17 -14
  93. package/dist/cjs/compute/nodeHelpers.js +0 -83
  94. package/dist/cjs/steps/trackReplaceStep.js +0 -110
  95. package/dist/cjs/steps/trackTransaction.js +0 -162
  96. package/dist/cjs/types/step.js +0 -2
  97. package/dist/cjs/utils/track-utils.js +0 -239
  98. package/dist/es/compute/nodeHelpers.js +0 -73
  99. package/dist/es/steps/trackTransaction.js +0 -156
  100. package/dist/es/types/step.js +0 -1
  101. package/dist/es/utils/track-utils.js +0 -217
  102. package/dist/types/change-steps/diffChangeSteps.d.ts +0 -2
  103. package/dist/types/change-steps/matchInserted.d.ts +0 -3
  104. package/dist/types/change-steps/processChangeSteps.d.ts +0 -6
  105. package/dist/types/changes/applyChanges.d.ts +0 -6
  106. package/dist/types/compute/nodeHelpers.d.ts +0 -14
  107. package/dist/types/steps/trackReplaceStep.d.ts +0 -6
  108. package/dist/types/steps/trackTransaction.d.ts +0 -3
  109. package/dist/types/types/step.d.ts +0 -40
  110. package/dist/types/utils/track-utils.d.ts +0 -24
  111. /package/dist/cjs/{changes → changeHelpers}/fixInconsistentChanges.js +0 -0
  112. /package/dist/cjs/{mutate → tracking/lib}/mergeNode.js +0 -0
  113. /package/dist/cjs/{compute → tracking/lib}/splitSliceIntoMergedParts.js +0 -0
  114. /package/dist/es/{changes → changeHelpers}/fixInconsistentChanges.js +0 -0
  115. /package/dist/es/{mutate → tracking/lib}/mergeNode.js +0 -0
  116. /package/dist/es/{compute → tracking/lib}/splitSliceIntoMergedParts.js +0 -0
  117. /package/dist/types/{changes → changeHelpers}/fixInconsistentChanges.d.ts +0 -0
  118. /package/dist/types/{changes → changeHelpers}/revertChange.d.ts +0 -0
  119. /package/dist/types/{changes → changeHelpers}/updateChangeAttrs.d.ts +0 -0
  120. /package/dist/types/{changes → changeHelpers}/updateChangesStatus.d.ts +0 -0
  121. /package/dist/types/{mutate → tracking/lib}/mergeNode.d.ts +0 -0
  122. /package/dist/types/{mutate → tracking/lib}/mergeTrackedMarks.d.ts +0 -0
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.trFromHistory = exports.filterMeaninglessMoveSteps = exports.changeMovedToInsertsOnSourceDeletion = exports.getMoveOperationsSteps = exports.excludeFromTracking = void 0;
4
+ exports.getIndentationOperationSteps = getIndentationOperationSteps;
5
+ exports.passThroughMeta = passThroughMeta;
6
+ exports.iterationIsValid = iterationIsValid;
7
+ const prosemirror_transform_1 = require("prosemirror-transform");
8
+ const actions_1 = require("../actions");
9
+ const ChangeSet_1 = require("../ChangeSet");
10
+ const change_1 = require("../types/change");
11
+ const uuidv4_1 = require("../utils/uuidv4");
12
+ const qualifiers_1 = require("./steps-trackers/qualifiers");
13
+ function getIndentationOperationSteps(tr, trContext) {
14
+ if ((0, actions_1.isIndentationAction)(trContext.action)) {
15
+ const moveId = (0, uuidv4_1.uuidv4)();
16
+ for (let i = 0; i < tr.steps.length; i++) {
17
+ const step = tr.steps[i];
18
+ if (step instanceof prosemirror_transform_1.ReplaceStep) {
19
+ trContext.stepsByGroupIDMap.set(step, moveId);
20
+ }
21
+ }
22
+ }
23
+ }
24
+ const excludeFromTracking = (node) => {
25
+ var _a;
26
+ if (node.isText) {
27
+ return false;
28
+ }
29
+ return node && !((_a = node.type.spec.attrs) === null || _a === void 0 ? void 0 : _a.dataTracked);
30
+ };
31
+ exports.excludeFromTracking = excludeFromTracking;
32
+ function passThroughMeta(oldTr, newTr) {
33
+ oldTr.getMeta('inputType') && newTr.setMeta('inputType', oldTr.getMeta('inputType'));
34
+ oldTr.getMeta('uiEvent') && newTr.setMeta('uiEvent', oldTr.getMeta('uiEvent'));
35
+ return newTr;
36
+ }
37
+ function iterationIsValid(iterations, oldTr, newTr, step) {
38
+ const uiEvent = oldTr.getMeta('uiEvent');
39
+ const isMassReplace = oldTr.getMeta('massSearchReplace');
40
+ if (iterations > 20 && uiEvent != 'cut' && !isMassReplace) {
41
+ console.error('@manuscripts/track-changes-plugin: Possible infinite loop in iterating tr.steps, tracking skipped!\n' +
42
+ 'This is probably an error with the library, please report back to maintainers with a reproduction if possible', newTr);
43
+ return false;
44
+ }
45
+ else if (!(step instanceof prosemirror_transform_1.ReplaceStep) && step.constructor.name === 'ReplaceStep') {
46
+ console.error('@manuscripts/track-changes-plugin: Multiple prosemirror-transform packages imported, alias/dedupe them ' +
47
+ 'or instanceof checks fail as well as creating new steps');
48
+ return false;
49
+ }
50
+ return true;
51
+ }
52
+ const getMoveOperationsSteps = (tr, context) => {
53
+ const movingAssoc = context.stepsByGroupIDMap;
54
+ if (tr.steps.length < 2) {
55
+ return movingAssoc;
56
+ }
57
+ if (tr.getMeta(actions_1.TrackChangesAction.structuralChangeAction)) {
58
+ const commonID = (0, uuidv4_1.uuidv4)();
59
+ movingAssoc.set(tr.steps[0], commonID);
60
+ movingAssoc.set(tr.steps[1], commonID);
61
+ return movingAssoc;
62
+ }
63
+ const matched = [];
64
+ for (let i = 0; i < tr.steps.length; i++) {
65
+ if (matched.includes(i)) {
66
+ continue;
67
+ }
68
+ const step = tr.steps[i];
69
+ const doc = tr.docs[i];
70
+ if (!step.slice) {
71
+ continue;
72
+ }
73
+ const stepDeletesContent = step.from !== step.to && step.slice.size === 0;
74
+ const stepInsertsContent = step.slice.size && step.slice.content.firstChild ? true : false;
75
+ for (let g = 0; g < tr.steps.length; g++) {
76
+ if (g === i || matched.includes(g)) {
77
+ continue;
78
+ }
79
+ const peerStep = tr.steps[g];
80
+ if (!peerStep.slice) {
81
+ continue;
82
+ }
83
+ const peerStepInsertsContent = peerStep.slice.size && peerStep.slice.content.firstChild;
84
+ const peerStepDeletesContent = peerStep.from !== peerStep.to && peerStep.slice.size === 0;
85
+ if (stepDeletesContent) {
86
+ const deletedContent = doc.slice(step.from, step.to);
87
+ if (peerStepInsertsContent &&
88
+ deletedContent.content.firstChild &&
89
+ peerStep.slice.content.firstChild.toString() === deletedContent.content.firstChild.toString()) {
90
+ const commonID = (0, uuidv4_1.uuidv4)();
91
+ movingAssoc.set(peerStep, commonID);
92
+ movingAssoc.set(step, commonID);
93
+ matched.push(i, g);
94
+ }
95
+ continue;
96
+ }
97
+ if (stepInsertsContent && peerStepDeletesContent) {
98
+ const insertedContent = step.slice;
99
+ const deletedPeerContent = tr.docs[g].slice(peerStep.from, peerStep.to);
100
+ if (insertedContent.content.firstChild &&
101
+ deletedPeerContent.content.firstChild &&
102
+ insertedContent.content.firstChild.toString() === deletedPeerContent.content.firstChild.toString()) {
103
+ const commonID = (0, uuidv4_1.uuidv4)();
104
+ movingAssoc.set(peerStep, commonID);
105
+ movingAssoc.set(step, commonID);
106
+ }
107
+ matched.push(i, g);
108
+ }
109
+ }
110
+ }
111
+ };
112
+ exports.getMoveOperationsSteps = getMoveOperationsSteps;
113
+ const changeMovedToInsertsOnSourceDeletion = (tr, newTr, trContext) => {
114
+ for (let i = 0; i < tr.steps.length; i++) {
115
+ const step = tr.steps[i];
116
+ if (step instanceof prosemirror_transform_1.ReplaceStep) {
117
+ const doc = tr.docs[tr.steps.indexOf(step)];
118
+ if ((0, qualifiers_1.isDirectPendingMoveDeletion)(step, doc, trContext.stepsByGroupIDMap)) {
119
+ const node = doc.nodeAt(step.from);
120
+ if (node === null || node === void 0 ? void 0 : node.attrs.dataTracked) {
121
+ newTr.setNodeMarkup(step.from, undefined, Object.assign(Object.assign({}, node.attrs), { dataTracked: node.attrs.dataTracked.filter((t) => !(t.operation === change_1.CHANGE_OPERATION.move && t.status === change_1.CHANGE_STATUS.pending)) }));
122
+ }
123
+ }
124
+ }
125
+ }
126
+ };
127
+ exports.changeMovedToInsertsOnSourceDeletion = changeMovedToInsertsOnSourceDeletion;
128
+ const filterMeaninglessMoveSteps = (tr, context) => {
129
+ var _a;
130
+ const cleanSteps = [];
131
+ for (let i = 0; i < tr.steps.length; i++) {
132
+ const step = tr.steps[i];
133
+ const moveID = context.stepsByGroupIDMap.get(step);
134
+ if (moveID) {
135
+ const prevMoveID = (0, qualifiers_1.isDeletingPendingMovedNode)(step, tr.docs[i]);
136
+ if (prevMoveID) {
137
+ context.stepsByGroupIDMap.forEach((replaceStepMoveID, replaceStep) => {
138
+ if (replaceStep !== step && moveID === replaceStepMoveID) {
139
+ context.stepsByGroupIDMap.set(replaceStep, prevMoveID);
140
+ }
141
+ });
142
+ cleanSteps.push(null);
143
+ continue;
144
+ }
145
+ if (step instanceof prosemirror_transform_1.ReplaceStep && !tr.getMeta(actions_1.TrackChangesAction.structuralChangeAction)) {
146
+ const { slice } = step;
147
+ if ((_a = slice === null || slice === void 0 ? void 0 : slice.content) === null || _a === void 0 ? void 0 : _a.firstChild) {
148
+ const insertedNode = slice.content.firstChild;
149
+ if (insertedNode.attrs.dataTracked) {
150
+ const isPendingInsert = ChangeSet_1.ChangeSet.isPendingChange(insertedNode.attrs.dataTracked, change_1.CHANGE_OPERATION.insert);
151
+ if (isPendingInsert) {
152
+ continue;
153
+ }
154
+ }
155
+ }
156
+ }
157
+ }
158
+ cleanSteps.push(step);
159
+ }
160
+ return cleanSteps;
161
+ };
162
+ exports.filterMeaninglessMoveSteps = filterMeaninglessMoveSteps;
163
+ const trFromHistory = (tr) => Object.keys(tr.meta).find((s) => s.startsWith('history$'));
164
+ exports.trFromHistory = trFromHistory;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2025 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 });
@@ -12,7 +12,6 @@ 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';
16
15
  export class ChangeSet {
17
16
  constructor(changes = []) {
18
17
  _ChangeSet_instances.add(this);
@@ -169,9 +168,8 @@ export class ChangeSet {
169
168
  if (!nextChange) {
170
169
  return false;
171
170
  }
172
- const isInline = (c) => c.type === 'text-change' || (c.type === 'node-change' && c.node.isInline) || isInlineMarkChange(c);
173
- return (isInline(change) &&
174
- isInline(nextChange) &&
171
+ return (ChangeSet.isInline(change) &&
172
+ ChangeSet.isInline(nextChange) &&
175
173
  change.to === nextChange.from &&
176
174
  (change.dataTracked.operation === nextChange.dataTracked.operation ||
177
175
  this.areMatchingWrapOperations(change, nextChange) ||
@@ -196,11 +194,13 @@ export class ChangeSet {
196
194
  }
197
195
  static shouldDeleteChange(change) {
198
196
  const { status, operation } = change.dataTracked;
199
- return (((operation === CHANGE_OPERATION.insert ||
200
- operation === CHANGE_OPERATION.node_split ||
201
- operation === CHANGE_OPERATION.wrap_with_node ||
202
- operation === CHANGE_OPERATION.move) &&
203
- status === CHANGE_STATUS.rejected) ||
197
+ const allowedRejectedForDeletion = [
198
+ CHANGE_OPERATION.insert,
199
+ CHANGE_OPERATION.node_split,
200
+ CHANGE_OPERATION.wrap_with_node,
201
+ CHANGE_OPERATION.move,
202
+ ];
203
+ return ((allowedRejectedForDeletion.includes(operation) && status === CHANGE_STATUS.rejected) ||
204
204
  (operation === CHANGE_OPERATION.delete && status === CHANGE_STATUS.accepted));
205
205
  }
206
206
  static isValidDataTracked(dataTracked = {}) {
@@ -223,6 +223,17 @@ export class ChangeSet {
223
223
  optionalEntries.every(([key, val]) => optionalKeys.includes(key) && val !== undefined) &&
224
224
  (dataTracked.id || '').length > 0);
225
225
  }
226
+ static isInlineMarkChange(change) {
227
+ if (ChangeSet.isMarkChange(change)) {
228
+ return change.nodeType.isInline || change.nodeType.isText;
229
+ }
230
+ return false;
231
+ }
232
+ static isInline(c) {
233
+ return (c.type === 'text-change' ||
234
+ (c.type === 'node-change' && c.node.isInline) ||
235
+ ChangeSet.isInlineMarkChange(c));
236
+ }
226
237
  static isTextChange(change) {
227
238
  return change.type === 'text-change';
228
239
  }
@@ -238,6 +249,9 @@ export class ChangeSet {
238
249
  static isReferenceChange(change) {
239
250
  return change.type === 'reference-change';
240
251
  }
252
+ static isPendingChange(trackedAttrs, operation) {
253
+ return !!(trackedAttrs === null || trackedAttrs === void 0 ? void 0 : trackedAttrs.some((t) => t.operation === operation));
254
+ }
241
255
  }
242
256
  _ChangeSet_changes = new WeakMap(), _ChangeSet_instances = new WeakSet(), _ChangeSet_isSameNodeChange = function _ChangeSet_isSameNodeChange(currentChange, nextChange) {
243
257
  return currentChange.from === nextChange.from && currentChange.to === nextChange.to;
@@ -19,3 +19,4 @@ export function setAction(tr, action, payload) {
19
19
  return tr.setMeta(action, payload);
20
20
  }
21
21
  export const skipTracking = (tr) => setAction(tr, TrackChangesAction.skipTrack, true);
22
+ export const isIndentationAction = (action) => action === 'indent' || action === 'unindent';
@@ -1,12 +1,12 @@
1
1
  import { Mapping } from 'prosemirror-transform';
2
- import { ChangeSet } from '../ChangeSet';
3
- import { deleteNode, keepPairedChanges } from '../mutate/deleteNode';
4
- import { mergeNode } from '../mutate/mergeNode';
5
- import { CHANGE_OPERATION, CHANGE_STATUS } from '../types/change';
6
- import { log } from '../utils/logger';
7
- import { excludeFromTracked, isInlineMarkChange } from '../utils/track-utils';
8
- import { revertSplitNodeChange, revertWrapNodeChange } from './revertChange';
9
- import { restoreNode, updateChangeChildrenAttributes } from './updateChangeAttrs';
2
+ import { revertSplitNodeChange, revertWrapNodeChange } from './changeHelpers/revertChange';
3
+ import { restoreNode, updateChangeChildrenAttributes } from './changeHelpers/updateChangeAttrs';
4
+ import { ChangeSet } from './ChangeSet';
5
+ import { excludeFromTracked } from './helpers/attributes';
6
+ import { deleteNode, keepPairedChanges } from './tracking/lib/deleteNode';
7
+ import { mergeNode } from './tracking/lib/mergeNode';
8
+ import { CHANGE_OPERATION, CHANGE_STATUS } from './types/change';
9
+ import { log } from './utils/logger';
10
10
  function collectMoveNodeIds(containerNode, primaryMoveNodeId) {
11
11
  const moveNodeIds = new Set();
12
12
  moveNodeIds.add(primaryMoveNodeId);
@@ -22,7 +22,7 @@ function collectMoveNodeIds(containerNode, primaryMoveNodeId) {
22
22
  });
23
23
  return moveNodeIds;
24
24
  }
25
- export function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, deleteMap = new Mapping()) {
25
+ export function applyChanges(tr, schema, changes, changeSet, deleteMap = new Mapping()) {
26
26
  changes.sort((c1, c2) => {
27
27
  if ((c1.type === 'node-change' && c1.node.type === schema.nodes.list) ||
28
28
  (c2.type === 'node-change' && c2.node.type === schema.nodes.list)) {
@@ -97,7 +97,7 @@ export function applyAcceptedRejectedChanges(tr, schema, changes, changeSet, del
97
97
  const isDelete = change.dataTracked.operation === CHANGE_OPERATION.delete;
98
98
  const toBeRestored = (change.dataTracked.status === CHANGE_STATUS.accepted && isInsert) ||
99
99
  (change.dataTracked.status === CHANGE_STATUS.rejected && isDelete);
100
- if (isInlineMarkChange(change)) {
100
+ if (ChangeSet.isInlineMarkChange(change)) {
101
101
  tr.removeMark(change.from, change.to, change.mark);
102
102
  if (toBeRestored) {
103
103
  tr.addMark(change.from, change.to, newMark);
@@ -1,7 +1,6 @@
1
1
  import { Slice } from 'prosemirror-model';
2
2
  import { liftTarget, ReplaceAroundStep } from 'prosemirror-transform';
3
- import { getBlockInlineTrackedData } from '../compute/nodeHelpers';
4
- import { excludeFromTracked } from '../utils/track-utils';
3
+ import { excludeFromTracked, getBlockInlineTrackedData } from '../helpers/attributes';
5
4
  export function revertSplitNodeChange(tr, change, changeSet) {
6
5
  const sourceChange = changeSet.changes.find((c) => c.dataTracked.operation === 'reference' && c.dataTracked.referenceId === change.id);
7
6
  const node = tr.doc.nodeAt(tr.mapping.map(change.from));
@@ -11,12 +11,13 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  };
12
12
  import { Fragment } from 'prosemirror-model';
13
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';
14
+ import { ReplaceStep } from 'prosemirror-transform';
15
+ import { TrackChangesAction } from '../actions';
16
+ import { findChanges } from '../findChanges';
17
+ import { addTrackIdIfDoesntExist, createNewInsertAttrs, createNewStructureAttrs, getBlockInlineTrackedData, updateBlockNodesAttrs, } from '../helpers/attributes';
18
+ import { setFragmentAsInserted } from '../helpers/fragment';
18
19
  import { CHANGE_OPERATION } from '../types/change';
19
- import { createNewInsertAttrs, createNewStructureAttrs, updateBlockNodesAttrs } from '../utils/track-utils';
20
+ import { updateChangeAttrs } from './updateChangeAttrs';
20
21
  export const dropStructuralChangeShadow = (moveNodeId, tr) => {
21
22
  const changeSet = findChanges(EditorState.create({ doc: tr.doc }));
22
23
  const changes = changeSet.changes.filter((c) => c.type === 'node-change' && c.dataTracked.moveNodeId === moveNodeId);
@@ -123,3 +124,7 @@ export const joinStructureChanges = (attrs, sliceContent, content, tr, newTr) =>
123
124
  return Object.assign(Object.assign({}, _), { dataTracked: [addTrackIdIfDoesntExist(createNewStructureAttrs(Object.assign(Object.assign({}, attrs), { moveNodeId })))] });
124
125
  });
125
126
  };
127
+ export const isStructuralChange = (tr) => tr.getMeta(TrackChangesAction.structuralChangeAction) &&
128
+ tr.steps.length === 2 &&
129
+ tr.steps[0] instanceof ReplaceStep &&
130
+ tr.steps[1] instanceof ReplaceStep;
@@ -1,8 +1,7 @@
1
1
  import { ChangeSet } from '../ChangeSet';
2
- import { getBlockInlineTrackedData, getTextNodeTrackedMarkData } from '../compute/nodeHelpers';
2
+ import { getBlockInlineTrackedData, getTextNodeTrackedMarkData } from '../helpers/attributes';
3
3
  import { CHANGE_OPERATION, CHANGE_STATUS, } from '../types/change';
4
4
  import { log } from '../utils/logger';
5
- import { isInlineMarkChange } from '../utils/track-utils';
6
5
  export function updateChangeAttrs(tr, change, trackedAttrs, schema) {
7
6
  const node = tr.doc.nodeAt(change.from);
8
7
  if (!node) {
@@ -78,7 +77,7 @@ export function updateChangeAttrs(tr, change, trackedAttrs, schema) {
78
77
  return dt;
79
78
  });
80
79
  const newMark = markChange.mark.type.create(Object.assign(Object.assign({}, markChange.mark.attrs), { dataTracked: newDT }));
81
- if (isInlineMarkChange(markChange)) {
80
+ if (ChangeSet.isInlineMarkChange(markChange)) {
82
81
  tr.removeMark(markChange.from, markChange.to, markChange.mark);
83
82
  tr.addMark(markChange.from, markChange.to, newMark);
84
83
  }
@@ -14,10 +14,10 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { closeHistory } from 'prosemirror-history';
17
+ import { applyChanges } from '../applyChanges';
17
18
  import { ChangeSet } from '../ChangeSet';
18
- import { dropOrphanChanges } from '../mutate/dropStructureChange';
19
19
  import { CHANGE_OPERATION, CHANGE_STATUS } from '../types/change';
20
- import { applyAcceptedRejectedChanges } from './applyChanges';
20
+ import { dropOrphanChanges } from './structureChange';
21
21
  import { updateChangeAttrs } from './updateChangeAttrs';
22
22
  export function updateChangesStatus(createdTr, changeSet, ids, status, userID, oldState) {
23
23
  const change = changeSet.get(ids[0]);
@@ -58,8 +58,8 @@ export function updateChangesStatus(createdTr, changeSet, ids, status, userID, o
58
58
  }
59
59
  }
60
60
  });
61
- const mapping = applyAcceptedRejectedChanges(createdTr, oldState.schema, nonTextChanges, changeSet);
62
- applyAcceptedRejectedChanges(createdTr, oldState.schema, textChanges, changeSet, mapping);
61
+ const mapping = applyChanges(createdTr, oldState.schema, nonTextChanges, changeSet);
62
+ applyChanges(createdTr, oldState.schema, textChanges, changeSet, mapping);
63
63
  dropOrphanChanges(createdTr);
64
64
  }
65
65
  else {
@@ -1,6 +1,6 @@
1
- import { ChangeSet } from '../ChangeSet';
2
- import { getMarkTrackedData, getNodeTrackedData } from '../compute/nodeHelpers';
3
- import { CHANGE_OPERATION, } from '../types/change';
1
+ import { ChangeSet } from './ChangeSet';
2
+ import { getMarkTrackedData, getNodeTrackedData } from './helpers/attributes';
3
+ import { CHANGE_OPERATION, } from './types/change';
4
4
  export function findChanges(state) {
5
5
  const changes = [];
6
6
  let current;
@@ -0,0 +1,136 @@
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 { CHANGE_OPERATION, CHANGE_STATUS } from '../types/change';
14
+ import { log } from '../utils/logger';
15
+ import { uuidv4 } from '../utils/uuidv4';
16
+ import { isValidTrackableMark } from './mark';
17
+ export function createNewInsertAttrs(attrs) {
18
+ return Object.assign(Object.assign({}, attrs), { operation: CHANGE_OPERATION.insert });
19
+ }
20
+ export function createNewWrapAttrs(attrs) {
21
+ return Object.assign(Object.assign({}, attrs), { operation: CHANGE_OPERATION.wrap_with_node });
22
+ }
23
+ export function createNewSplitAttrs(attrs) {
24
+ return Object.assign(Object.assign({}, attrs), { operation: CHANGE_OPERATION.node_split });
25
+ }
26
+ export function createNewReferenceAttrs(attrs, id) {
27
+ return Object.assign(Object.assign({}, attrs), { operation: CHANGE_OPERATION.reference, referenceId: id });
28
+ }
29
+ export function createNewDeleteAttrs(attrs) {
30
+ return Object.assign(Object.assign({}, attrs), { operation: CHANGE_OPERATION.delete });
31
+ }
32
+ export function createNewMoveAttrs(attrs, indentationType) {
33
+ return Object.assign(Object.assign(Object.assign({}, attrs), { operation: CHANGE_OPERATION.move }), (indentationType && { indentationType }));
34
+ }
35
+ export function createNewUpdateAttrs(attrs, oldAttrs) {
36
+ const { dataTracked } = oldAttrs, restAttrs = __rest(oldAttrs, ["dataTracked"]);
37
+ return Object.assign(Object.assign({}, attrs), { operation: CHANGE_OPERATION.set_node_attributes, oldAttrs: JSON.parse(JSON.stringify(restAttrs)) });
38
+ }
39
+ export function createNewStructureAttrs(attrs) {
40
+ return Object.assign(Object.assign({}, attrs), { operation: CHANGE_OPERATION.structure });
41
+ }
42
+ export function createNewPendingAttrs(time, authorID) {
43
+ return {
44
+ authorID,
45
+ reviewedByID: null,
46
+ createdAt: time,
47
+ updatedAt: time,
48
+ statusUpdateAt: 0,
49
+ status: CHANGE_STATUS.pending,
50
+ };
51
+ }
52
+ export function addTrackIdIfDoesntExist(attrs) {
53
+ if (!attrs.id) {
54
+ return Object.assign({ id: uuidv4() }, attrs);
55
+ }
56
+ return attrs;
57
+ }
58
+ export function getTextNodeTrackedMarkData(node, schema) {
59
+ if (!node || !node.isText) {
60
+ return undefined;
61
+ }
62
+ const marksTrackedData = [];
63
+ node.marks.forEach((mark) => {
64
+ if (mark.type === schema.marks.tracked_insert || mark.type === schema.marks.tracked_delete) {
65
+ const operation = mark.type === schema.marks.tracked_insert ? CHANGE_OPERATION.insert : CHANGE_OPERATION.delete;
66
+ marksTrackedData.push(Object.assign(Object.assign({}, mark.attrs.dataTracked), { operation }));
67
+ }
68
+ });
69
+ if (marksTrackedData.length > 1) {
70
+ log.warn('inline node with more than 1 of tracked marks', marksTrackedData);
71
+ }
72
+ return marksTrackedData[0] || undefined;
73
+ }
74
+ export function getBlockInlineTrackedData(node) {
75
+ const { dataTracked } = node.attrs;
76
+ if (dataTracked && !Array.isArray(dataTracked)) {
77
+ return [dataTracked];
78
+ }
79
+ return dataTracked || [];
80
+ }
81
+ export function getMarkTrackedData(node) {
82
+ const tracked = node === null || node === void 0 ? void 0 : node.marks.reduce((acc, current) => {
83
+ if (isValidTrackableMark(current) && current.attrs.dataTracked) {
84
+ acc.set(current, current.attrs.dataTracked);
85
+ }
86
+ return acc;
87
+ }, new Map());
88
+ return tracked || new Map();
89
+ }
90
+ export function getNodeTrackedData(node, schema) {
91
+ let tracked;
92
+ if (node && !node.isText) {
93
+ tracked = getBlockInlineTrackedData(node);
94
+ }
95
+ else if (node === null || node === void 0 ? void 0 : node.isText) {
96
+ tracked = getTextNodeTrackedMarkData(node, schema);
97
+ }
98
+ if (tracked && !Array.isArray(tracked)) {
99
+ tracked = [tracked];
100
+ }
101
+ return tracked;
102
+ }
103
+ export function shouldMergeTrackedAttributes(left, right) {
104
+ if (!left || !right) {
105
+ log.warn('passed undefined dataTracked attributes to shouldMergeTrackedAttributes', {
106
+ left,
107
+ right,
108
+ });
109
+ return false;
110
+ }
111
+ return (left.status === right.status && left.operation === right.operation && left.authorID === right.authorID);
112
+ }
113
+ export function getMergeableMarkTrackedAttrs(node, attrs, schema) {
114
+ const nodeAttrs = getTextNodeTrackedMarkData(node, schema);
115
+ return nodeAttrs && shouldMergeTrackedAttributes(nodeAttrs, attrs) ? nodeAttrs : null;
116
+ }
117
+ export const updateBlockNodesAttrs = (fragment, predicate) => {
118
+ const updatedNodes = [];
119
+ fragment.forEach((child) => {
120
+ if (!child.isBlock) {
121
+ updatedNodes.push(child);
122
+ return;
123
+ }
124
+ const newContent = child.content.size ? updateBlockNodesAttrs(child.content, predicate) : child.content;
125
+ const newAttrs = predicate(child.attrs, child);
126
+ updatedNodes.push(child.type.create(newAttrs, newContent, child.marks));
127
+ });
128
+ return Fragment.fromArray(updatedNodes);
129
+ };
130
+ export function excludeFromTracked(dataTracked, changeIdToExclude) {
131
+ if (!dataTracked) {
132
+ return null;
133
+ }
134
+ const newDataTracked = dataTracked.filter((c) => c.id !== changeIdToExclude);
135
+ return newDataTracked.length ? newDataTracked : null;
136
+ }
@@ -1,9 +1,73 @@
1
1
  import { Fragment } from 'prosemirror-model';
2
2
  import { CHANGE_OPERATION, CHANGE_STATUS } from '../types/change';
3
3
  import { log } from '../utils/logger';
4
- import * as trackUtils from '../utils/track-utils';
5
4
  import { uuidv4 } from '../utils/uuidv4';
6
- import { addTrackIdIfDoesntExist, equalMarks, getBlockInlineTrackedData, getTextNodeTrackedMarkData, } from './nodeHelpers';
5
+ import { addTrackIdIfDoesntExist, createNewInsertAttrs, createNewReferenceAttrs, createNewSplitAttrs, createNewWrapAttrs, getBlockInlineTrackedData, getTextNodeTrackedMarkData, } from './attributes';
6
+ import { equalMarks } from './mark';
7
+ export function setFragmentAsInserted(inserted, insertAttrs, schema) {
8
+ const updatedInserted = loopContentAndMergeText(inserted, insertAttrs, schema);
9
+ return updatedInserted.length === 0 ? Fragment.empty : Fragment.fromArray(updatedInserted);
10
+ }
11
+ export function setFragmentAsWrapChange(inserted, attrs, schema) {
12
+ const content = [];
13
+ inserted.forEach((node) => {
14
+ content.push(node.type.create(Object.assign(Object.assign({}, node.attrs), { dataTracked: [addTrackIdIfDoesntExist(createNewWrapAttrs(attrs))] }), setFragmentAsInserted(node.content, createNewInsertAttrs(attrs), schema), node.marks));
15
+ });
16
+ return Fragment.from(content);
17
+ }
18
+ export function setFragmentAsMoveChange(fragment, moveAttrs) {
19
+ const content = [];
20
+ fragment.forEach((node) => {
21
+ content.push(node.type.create(Object.assign(Object.assign({}, node.attrs), { dataTracked: [addTrackIdIfDoesntExist(moveAttrs)] }), node.content, node.marks));
22
+ });
23
+ return Fragment.from(content);
24
+ }
25
+ export function setFragmentAsNodeSplit($pos, newTr, inserted, attrs) {
26
+ const lastChild = inserted.lastChild;
27
+ const referenceId = uuidv4();
28
+ const parentPos = $pos.before($pos.depth);
29
+ const parent = $pos.node($pos.depth);
30
+ const oldDataTracked = getBlockInlineTrackedData(parent) || [];
31
+ newTr.setNodeMarkup(parentPos, undefined, Object.assign(Object.assign({}, parent.attrs), { dataTracked: [
32
+ ...oldDataTracked.filter((c) => c.operation !== 'reference'),
33
+ Object.assign({}, addTrackIdIfDoesntExist(createNewReferenceAttrs(Object.assign(Object.assign({}, attrs), { status: CHANGE_STATUS.pending }), referenceId))),
34
+ ] }));
35
+ const splitSource = oldDataTracked.find((c) => c.operation === 'reference');
36
+ const dataTracked = Object.assign(Object.assign({}, createNewSplitAttrs(Object.assign({}, attrs))), { id: referenceId });
37
+ if (lastChild.type.name === 'list_item') {
38
+ let firstChild = lastChild.content.firstChild;
39
+ firstChild = firstChild.type.create(Object.assign(Object.assign({}, lastChild.attrs), { dataTracked: splitSource ? [dataTracked, splitSource] : [dataTracked] }), firstChild.content);
40
+ inserted = inserted.replaceChild(inserted.childCount - 1, lastChild.type.create(lastChild.attrs, lastChild.content.cut(firstChild.nodeSize).addToStart(firstChild)));
41
+ }
42
+ else {
43
+ inserted = inserted.replaceChild(inserted.childCount - 1, lastChild.type.create(Object.assign(Object.assign({}, lastChild.attrs), { dataTracked: splitSource ? [dataTracked, splitSource] : [dataTracked] }), lastChild.content));
44
+ }
45
+ return inserted;
46
+ }
47
+ export function cutFragment(matched, deleted, content) {
48
+ const newContent = [];
49
+ for (let i = 0; matched <= deleted && i < content.childCount; i += 1) {
50
+ const child = content.child(i);
51
+ if (!child.isText && child.content.size > 0) {
52
+ const cut = cutFragment(matched + 1, deleted, child.content);
53
+ matched = cut[0];
54
+ newContent.push(...cut[1].content);
55
+ }
56
+ else if (child.isText && matched + child.nodeSize > deleted) {
57
+ if (deleted - matched > 0) {
58
+ newContent.push(child.cut(deleted - matched));
59
+ }
60
+ else {
61
+ newContent.push(child);
62
+ }
63
+ matched = deleted + 1;
64
+ }
65
+ else {
66
+ matched += child.nodeSize;
67
+ }
68
+ }
69
+ return [matched, Fragment.fromArray(newContent)];
70
+ }
7
71
  function markInlineNodeChange(node, newTrackAttrs, schema) {
8
72
  const filtered = node.marks.filter((m) => m.type !== schema.marks.tracked_insert && m.type !== schema.marks.tracked_delete);
9
73
  const mark = newTrackAttrs.operation === CHANGE_OPERATION.insert
@@ -45,43 +109,3 @@ function recurseNodeContent(node, newTrackAttrs, schema) {
45
109
  return node;
46
110
  }
47
111
  }
48
- export function setFragmentAsInserted(inserted, insertAttrs, schema) {
49
- const updatedInserted = loopContentAndMergeText(inserted, insertAttrs, schema);
50
- return updatedInserted.length === 0 ? Fragment.empty : Fragment.fromArray(updatedInserted);
51
- }
52
- export function setFragmentAsWrapChange(inserted, attrs, schema) {
53
- const content = [];
54
- inserted.forEach((node) => {
55
- content.push(node.type.create(Object.assign(Object.assign({}, node.attrs), { dataTracked: [addTrackIdIfDoesntExist(trackUtils.createNewWrapAttrs(attrs))] }), setFragmentAsInserted(node.content, trackUtils.createNewInsertAttrs(attrs), schema), node.marks));
56
- });
57
- return Fragment.from(content);
58
- }
59
- export function setFragmentAsMoveChange(fragment, moveAttrs) {
60
- const content = [];
61
- fragment.forEach((node) => {
62
- content.push(node.type.create(Object.assign(Object.assign({}, node.attrs), { dataTracked: [addTrackIdIfDoesntExist(moveAttrs)] }), node.content, node.marks));
63
- });
64
- return Fragment.from(content);
65
- }
66
- export function setFragmentAsNodeSplit($pos, newTr, inserted, attrs) {
67
- const lastChild = inserted.lastChild;
68
- const referenceId = uuidv4();
69
- const parentPos = $pos.before($pos.depth);
70
- const parent = $pos.node($pos.depth);
71
- const oldDataTracked = getBlockInlineTrackedData(parent) || [];
72
- newTr.setNodeMarkup(parentPos, undefined, Object.assign(Object.assign({}, parent.attrs), { dataTracked: [
73
- ...oldDataTracked.filter((c) => c.operation !== 'reference'),
74
- Object.assign({}, addTrackIdIfDoesntExist(trackUtils.createNewReferenceAttrs(Object.assign(Object.assign({}, attrs), { status: CHANGE_STATUS.pending }), referenceId))),
75
- ] }));
76
- const splitSource = oldDataTracked.find((c) => c.operation === 'reference');
77
- const dataTracked = Object.assign(Object.assign({}, trackUtils.createNewSplitAttrs(Object.assign({}, attrs))), { id: referenceId });
78
- if (lastChild.type.name === 'list_item') {
79
- let firstChild = lastChild.content.firstChild;
80
- firstChild = firstChild.type.create(Object.assign(Object.assign({}, lastChild.attrs), { dataTracked: splitSource ? [dataTracked, splitSource] : [dataTracked] }), firstChild.content);
81
- inserted = inserted.replaceChild(inserted.childCount - 1, lastChild.type.create(lastChild.attrs, lastChild.content.cut(firstChild.nodeSize).addToStart(firstChild)));
82
- }
83
- else {
84
- inserted = inserted.replaceChild(inserted.childCount - 1, lastChild.type.create(Object.assign(Object.assign({}, lastChild.attrs), { dataTracked: splitSource ? [dataTracked, splitSource] : [dataTracked] }), lastChild.content));
85
- }
86
- return inserted;
87
- }