@atlaskit/editor-plugin-local-id 5.0.2 → 5.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/CHANGELOG.md +19 -0
- package/afm-cc/tsconfig.json +3 -0
- package/afm-jira/tsconfig.json +3 -0
- package/afm-products/tsconfig.json +3 -0
- package/dist/cjs/localIdPlugin.js +17 -0
- package/dist/cjs/pm-plugins/watchmen.js +519 -0
- package/dist/es2019/localIdPlugin.js +15 -0
- package/dist/es2019/pm-plugins/watchmen.js +497 -0
- package/dist/esm/localIdPlugin.js +17 -0
- package/dist/esm/pm-plugins/watchmen.js +512 -0
- package/dist/types/localIdPluginType.d.ts +12 -1
- package/dist/types/pm-plugins/watchmen.d.ts +32 -0
- package/dist/types-ts4.5/localIdPluginType.d.ts +9 -1
- package/dist/types-ts4.5/pm-plugins/watchmen.d.ts +32 -0
- package/package.json +7 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-local-id
|
|
2
2
|
|
|
3
|
+
## 5.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 5.1.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`c082975fb2a0c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/c082975fb2a0c) -
|
|
14
|
+
Added a new watchment plugin to the localId editror plugin for it to keep track of all localIds
|
|
15
|
+
created/updated since the start of the editor session. This is needed so the orchestrator is able
|
|
16
|
+
to identify when it cant lookup a localId, what the reason is for the localId being missing.
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
|
|
3
22
|
## 5.0.2
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/afm-cc/tsconfig.json
CHANGED
package/afm-jira/tsconfig.json
CHANGED
|
@@ -4,8 +4,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.localIdPlugin = void 0;
|
|
7
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
7
8
|
var _editorActions = require("./editor-actions");
|
|
8
9
|
var _main = require("./pm-plugins/main");
|
|
10
|
+
var _watchmen = require("./pm-plugins/watchmen");
|
|
9
11
|
var localIdPlugin = exports.localIdPlugin = function localIdPlugin(_ref) {
|
|
10
12
|
var api = _ref.api;
|
|
11
13
|
return {
|
|
@@ -20,7 +22,22 @@ var localIdPlugin = exports.localIdPlugin = function localIdPlugin(_ref) {
|
|
|
20
22
|
plugin: function plugin() {
|
|
21
23
|
return (0, _main.createPlugin)(api);
|
|
22
24
|
}
|
|
25
|
+
}, {
|
|
26
|
+
name: 'localId-watchmen',
|
|
27
|
+
plugin: function plugin() {
|
|
28
|
+
return (0, _platformFeatureFlags.fg)('platform_editor_ai_aifc_localid_error_reporting') ? (0, _watchmen.createWatchmenPlugin)(api) : undefined;
|
|
29
|
+
}
|
|
23
30
|
}];
|
|
31
|
+
},
|
|
32
|
+
getSharedState: function getSharedState(editorState) {
|
|
33
|
+
if (!editorState) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
var watchmentPluginState = _watchmen.localIdWatchmenPluginKey.getState(editorState);
|
|
37
|
+
return {
|
|
38
|
+
localIdWatchmenEnabled: !!(watchmentPluginState !== null && watchmentPluginState !== void 0 && watchmentPluginState.enabled),
|
|
39
|
+
localIdStatus: new Map(watchmentPluginState === null || watchmentPluginState === void 0 ? void 0 : watchmentPluginState.localIdStatus)
|
|
40
|
+
};
|
|
24
41
|
}
|
|
25
42
|
};
|
|
26
43
|
};
|
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.localIdWatchmenPluginKey = exports.createWatchmenPlugin = void 0;
|
|
8
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
9
|
+
var _steps = require("@atlaskit/adf-schema/steps");
|
|
10
|
+
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
11
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
12
|
+
var _transform = require("@atlaskit/editor-prosemirror/transform");
|
|
13
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
14
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
15
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
16
|
+
/**
|
|
17
|
+
* This is a safeguard limit to avoid tracking localIds in extremely large documents with too many localIds.
|
|
18
|
+
* If the number of unique localIds exceeds this limit, the watchmen plugin will disable itself to avoid performance issues.
|
|
19
|
+
* Reminder: The Map has a hard limit of 2^24 (16 million) entries in V8, please keep this value well below that
|
|
20
|
+
* to avoid any potential memory issues.
|
|
21
|
+
*/
|
|
22
|
+
var MAX_LOCAL_ID_MAP_SIZE = 2097152; // 2^21
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Plugin state tracking all localIds in the document
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
var localIdWatchmenPluginKey = exports.localIdWatchmenPluginKey = new _state.PluginKey('localIdWatchmenPlugin');
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Scans the entire document to find all active localIds
|
|
32
|
+
*/
|
|
33
|
+
var scanDocumentForLocalIds = function scanDocumentForLocalIds(doc) {
|
|
34
|
+
var localIds = new Set();
|
|
35
|
+
doc.descendants(function (node) {
|
|
36
|
+
var _node$attrs;
|
|
37
|
+
if ((_node$attrs = node.attrs) !== null && _node$attrs !== void 0 && _node$attrs.localId) {
|
|
38
|
+
localIds.add(node.attrs.localId);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Check marks for localIds
|
|
42
|
+
if (node.marks) {
|
|
43
|
+
node.marks.forEach(function (mark) {
|
|
44
|
+
var _mark$attrs;
|
|
45
|
+
if ((_mark$attrs = mark.attrs) !== null && _mark$attrs !== void 0 && _mark$attrs.localId) {
|
|
46
|
+
localIds.add(mark.attrs.localId);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return localIds.size < MAX_LOCAL_ID_MAP_SIZE; // Continue traversing
|
|
51
|
+
});
|
|
52
|
+
return localIds;
|
|
53
|
+
};
|
|
54
|
+
var getReplacementStatusCode = function getReplacementStatusCode(tr, step) {
|
|
55
|
+
var method;
|
|
56
|
+
if (step instanceof _transform.AttrStep || step instanceof _transform.DocAttrStep) {
|
|
57
|
+
method = 'ByAttr';
|
|
58
|
+
} else if (step instanceof _steps.SetAttrsStep) {
|
|
59
|
+
method = 'BySetAttrs';
|
|
60
|
+
} else if (step instanceof _steps.BatchAttrsStep) {
|
|
61
|
+
method = 'ByBatchAttrs';
|
|
62
|
+
} else if (step instanceof _transform.ReplaceStep) {
|
|
63
|
+
var isDeleting = step.from < step.to; // range has content to remove
|
|
64
|
+
var isInserting = step.slice.content.size > 0; // slice has content to insert
|
|
65
|
+
if (isDeleting && !isInserting) {
|
|
66
|
+
method = 'ByDelete'; // removing content, inserting nothing
|
|
67
|
+
//} else if (!isDeleting && isInserting) {
|
|
68
|
+
//method = 'ByInsert'; // This situation cannot be tracked since this would be part of the "current" status
|
|
69
|
+
} else {
|
|
70
|
+
// isDeleting && isInserting
|
|
71
|
+
method = 'ByReplace';
|
|
72
|
+
}
|
|
73
|
+
} else if (step instanceof _transform.ReplaceAroundStep) {
|
|
74
|
+
method = 'ByReplaceAround';
|
|
75
|
+
} else {
|
|
76
|
+
method = 'ByUnknown';
|
|
77
|
+
}
|
|
78
|
+
if (tr.getMeta('isAIStreamingTransformation')) {
|
|
79
|
+
return "AIChange".concat(method);
|
|
80
|
+
}
|
|
81
|
+
if (tr.getMeta('replaceDocument')) {
|
|
82
|
+
return "docChange".concat(method);
|
|
83
|
+
}
|
|
84
|
+
if (tr.getMeta('isRemote')) {
|
|
85
|
+
return "remoteChange".concat(method);
|
|
86
|
+
}
|
|
87
|
+
return "localChange".concat(method);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Handles AttrStep and DocAttrStep which modify a single attribute
|
|
92
|
+
*/
|
|
93
|
+
var handleAttrStep = function handleAttrStep(tr, step, localIdStatus, preDoc) {
|
|
94
|
+
if (step.attr !== 'localId') {
|
|
95
|
+
return {
|
|
96
|
+
localIdStatus: localIdStatus,
|
|
97
|
+
modified: false
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
var modified = false;
|
|
101
|
+
var newlocalIdStatus = new Map(localIdStatus);
|
|
102
|
+
|
|
103
|
+
// Get the old value if it exists
|
|
104
|
+
var oldLocalId;
|
|
105
|
+
if (step instanceof _transform.AttrStep) {
|
|
106
|
+
try {
|
|
107
|
+
var _node$attrs2;
|
|
108
|
+
var node = preDoc.nodeAt(step.pos);
|
|
109
|
+
oldLocalId = node === null || node === void 0 || (_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.localId;
|
|
110
|
+
} catch (_unused) {
|
|
111
|
+
// Position might be invalid
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Handle the new value
|
|
116
|
+
var newLocalId = step.value;
|
|
117
|
+
if (oldLocalId && oldLocalId !== newLocalId) {
|
|
118
|
+
// Old localId is being replaced or removed
|
|
119
|
+
newlocalIdStatus.set(oldLocalId, getReplacementStatusCode(tr, step));
|
|
120
|
+
modified = true;
|
|
121
|
+
}
|
|
122
|
+
if (newLocalId) {
|
|
123
|
+
newlocalIdStatus.set(newLocalId, 'current');
|
|
124
|
+
modified = true;
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
localIdStatus: newlocalIdStatus,
|
|
128
|
+
modified: modified
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Handles SetAttrsStep which sets multiple attributes at once
|
|
134
|
+
*/
|
|
135
|
+
var handleSetAttrsStep = function handleSetAttrsStep(tr, step, localIdStatus, preDoc) {
|
|
136
|
+
var attrs = step.attrs;
|
|
137
|
+
if (!attrs || !attrs.hasOwnProperty('localId')) {
|
|
138
|
+
return {
|
|
139
|
+
localIdStatus: localIdStatus,
|
|
140
|
+
modified: false
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
var modified = false;
|
|
144
|
+
var newlocalIdStatus = new Map(localIdStatus);
|
|
145
|
+
|
|
146
|
+
// Get old localId from the node being modified
|
|
147
|
+
try {
|
|
148
|
+
var _node$attrs3;
|
|
149
|
+
var node = preDoc.nodeAt(step.pos);
|
|
150
|
+
var oldLocalId = node === null || node === void 0 || (_node$attrs3 = node.attrs) === null || _node$attrs3 === void 0 ? void 0 : _node$attrs3.localId;
|
|
151
|
+
if (oldLocalId && oldLocalId !== attrs.localId) {
|
|
152
|
+
newlocalIdStatus.set(oldLocalId, getReplacementStatusCode(tr, step));
|
|
153
|
+
modified = true;
|
|
154
|
+
}
|
|
155
|
+
} catch (_unused2) {
|
|
156
|
+
// Position might be invalid
|
|
157
|
+
}
|
|
158
|
+
var newLocalId = attrs.localId;
|
|
159
|
+
if (newLocalId) {
|
|
160
|
+
newlocalIdStatus.set(newLocalId, 'current');
|
|
161
|
+
modified = true;
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
localIdStatus: newlocalIdStatus,
|
|
165
|
+
modified: modified
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Handles BatchAttrsStep which applies multiple attribute changes
|
|
171
|
+
*/
|
|
172
|
+
var handleBatchAttrsStep = function handleBatchAttrsStep(tr, step, localIdStatus, preDoc) {
|
|
173
|
+
var modified = false;
|
|
174
|
+
var newlocalIdStatus = new Map(localIdStatus);
|
|
175
|
+
step.data.forEach(function (change) {
|
|
176
|
+
var _change$attrs;
|
|
177
|
+
if (!((_change$attrs = change.attrs) !== null && _change$attrs !== void 0 && _change$attrs.hasOwnProperty('localId'))) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Get old localId from the node being modified
|
|
182
|
+
try {
|
|
183
|
+
var _node$attrs4;
|
|
184
|
+
var node = preDoc.nodeAt(change.position);
|
|
185
|
+
var oldLocalId = node === null || node === void 0 || (_node$attrs4 = node.attrs) === null || _node$attrs4 === void 0 ? void 0 : _node$attrs4.localId;
|
|
186
|
+
var newLocalId = change.attrs.localId;
|
|
187
|
+
if (oldLocalId && oldLocalId !== newLocalId) {
|
|
188
|
+
newlocalIdStatus.set(oldLocalId, getReplacementStatusCode(tr, step));
|
|
189
|
+
modified = true;
|
|
190
|
+
}
|
|
191
|
+
if (newLocalId) {
|
|
192
|
+
newlocalIdStatus.set(newLocalId, 'current');
|
|
193
|
+
modified = true;
|
|
194
|
+
}
|
|
195
|
+
} catch (_unused3) {
|
|
196
|
+
// Position might be invalid
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
return {
|
|
200
|
+
localIdStatus: newlocalIdStatus,
|
|
201
|
+
modified: modified
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Handles ReplaceStep which inserts or deletes content
|
|
207
|
+
*/
|
|
208
|
+
var handleReplaceStep = function handleReplaceStep(tr, step, localIdStatus, preDoc, postDoc) {
|
|
209
|
+
var modified = false;
|
|
210
|
+
try {
|
|
211
|
+
// Create a temporary set to collect new localIds
|
|
212
|
+
var changedLocaleIds = new Map();
|
|
213
|
+
var replaceCode = getReplacementStatusCode(tr, step);
|
|
214
|
+
step.getMap().forEach(function (oldStart, oldEnd, newStart, newEnd) {
|
|
215
|
+
// For each step map item we can just look at the nodes in the old doc and mark them as "inactive" and then
|
|
216
|
+
// look at the nodes in the doc after the step has been applied and mark them as "active"
|
|
217
|
+
// then lastly we can compare these to the current states and only update what's different.
|
|
218
|
+
preDoc.nodesBetween(oldStart, oldEnd, function (node) {
|
|
219
|
+
var _node$attrs5;
|
|
220
|
+
if ((_node$attrs5 = node.attrs) !== null && _node$attrs5 !== void 0 && _node$attrs5.localId) {
|
|
221
|
+
changedLocaleIds.set(node.attrs.localId, replaceCode);
|
|
222
|
+
}
|
|
223
|
+
if (node.marks) {
|
|
224
|
+
node.marks.forEach(function (mark) {
|
|
225
|
+
var _mark$attrs2;
|
|
226
|
+
if ((_mark$attrs2 = mark.attrs) !== null && _mark$attrs2 !== void 0 && _mark$attrs2.localId) {
|
|
227
|
+
changedLocaleIds.set(node.attrs.localId, replaceCode);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
postDoc.nodesBetween(newStart, newEnd, function (node) {
|
|
233
|
+
var _node$attrs6;
|
|
234
|
+
if ((_node$attrs6 = node.attrs) !== null && _node$attrs6 !== void 0 && _node$attrs6.localId) {
|
|
235
|
+
changedLocaleIds.set(node.attrs.localId, 'current');
|
|
236
|
+
}
|
|
237
|
+
if (node.marks) {
|
|
238
|
+
node.marks.forEach(function (mark) {
|
|
239
|
+
var _mark$attrs3;
|
|
240
|
+
if ((_mark$attrs3 = mark.attrs) !== null && _mark$attrs3 !== void 0 && _mark$attrs3.localId) {
|
|
241
|
+
changedLocaleIds.set(node.attrs.localId, 'current');
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
if (!!changedLocaleIds.size) {
|
|
248
|
+
var newlocalIdStatus = new Map(localIdStatus);
|
|
249
|
+
var _iterator = _createForOfIteratorHelper(changedLocaleIds),
|
|
250
|
+
_step;
|
|
251
|
+
try {
|
|
252
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
253
|
+
var _step$value = (0, _slicedToArray2.default)(_step.value, 2),
|
|
254
|
+
key = _step$value[0],
|
|
255
|
+
value = _step$value[1];
|
|
256
|
+
if (!localIdStatus.has(key) || localIdStatus.get(key) !== value) {
|
|
257
|
+
modified = true;
|
|
258
|
+
newlocalIdStatus.set(key, value);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
} catch (err) {
|
|
262
|
+
_iterator.e(err);
|
|
263
|
+
} finally {
|
|
264
|
+
_iterator.f();
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
localIdStatus: newlocalIdStatus,
|
|
268
|
+
modified: modified
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
} catch (_unused4) {
|
|
272
|
+
// If position calculation fails, do a full document rescan as fallback
|
|
273
|
+
// This shouldn't happen often but provides safety
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
localIdStatus: localIdStatus,
|
|
277
|
+
modified: modified
|
|
278
|
+
};
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Handles ReplaceAroundStep which wraps or unwraps content
|
|
283
|
+
*/
|
|
284
|
+
var handleReplaceAroundStep = function handleReplaceAroundStep(tr, step, localIdStatus, preDoc, postDoc) {
|
|
285
|
+
var modified = false;
|
|
286
|
+
var newlocalIdStatus = new Map(localIdStatus);
|
|
287
|
+
|
|
288
|
+
// Scan the affected region before and after the step
|
|
289
|
+
var from = step.from;
|
|
290
|
+
var to = step.to;
|
|
291
|
+
try {
|
|
292
|
+
// Collect localIds from the old region
|
|
293
|
+
var oldLocalIds = new Set();
|
|
294
|
+
if (from < to && from >= 0 && to <= preDoc.content.size) {
|
|
295
|
+
preDoc.nodesBetween(from, to, function (node) {
|
|
296
|
+
var _node$attrs7;
|
|
297
|
+
if ((_node$attrs7 = node.attrs) !== null && _node$attrs7 !== void 0 && _node$attrs7.localId) {
|
|
298
|
+
oldLocalIds.add(node.attrs.localId);
|
|
299
|
+
}
|
|
300
|
+
if (node.marks) {
|
|
301
|
+
node.marks.forEach(function (mark) {
|
|
302
|
+
var _mark$attrs4;
|
|
303
|
+
if ((_mark$attrs4 = mark.attrs) !== null && _mark$attrs4 !== void 0 && _mark$attrs4.localId) {
|
|
304
|
+
oldLocalIds.add(mark.attrs.localId);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Collect localIds from the new region
|
|
312
|
+
var map = step.getMap();
|
|
313
|
+
var newFrom = map.map(from, -1);
|
|
314
|
+
var newTo = map.map(to, 1);
|
|
315
|
+
var newLocalIds = new Set();
|
|
316
|
+
if (newFrom < newTo && newFrom >= 0 && newTo <= postDoc.content.size) {
|
|
317
|
+
postDoc.nodesBetween(newFrom, newTo, function (node) {
|
|
318
|
+
var _node$attrs8;
|
|
319
|
+
if ((_node$attrs8 = node.attrs) !== null && _node$attrs8 !== void 0 && _node$attrs8.localId) {
|
|
320
|
+
newLocalIds.add(node.attrs.localId);
|
|
321
|
+
}
|
|
322
|
+
if (node.marks) {
|
|
323
|
+
node.marks.forEach(function (mark) {
|
|
324
|
+
var _mark$attrs5;
|
|
325
|
+
if ((_mark$attrs5 = mark.attrs) !== null && _mark$attrs5 !== void 0 && _mark$attrs5.localId) {
|
|
326
|
+
newLocalIds.add(mark.attrs.localId);
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Find localIds that were removed
|
|
334
|
+
oldLocalIds.forEach(function (localId) {
|
|
335
|
+
if (!newLocalIds.has(localId) && newlocalIdStatus.get(localId) === 'current') {
|
|
336
|
+
newlocalIdStatus.set(localId, getReplacementStatusCode(tr, step));
|
|
337
|
+
modified = true;
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
// Find localIds that were added
|
|
342
|
+
newLocalIds.forEach(function (localId) {
|
|
343
|
+
if (!oldLocalIds.has(localId)) {
|
|
344
|
+
newlocalIdStatus.set(localId, 'current');
|
|
345
|
+
modified = true;
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
} catch (_unused5) {
|
|
349
|
+
// Position might be invalid, skip this step
|
|
350
|
+
}
|
|
351
|
+
return {
|
|
352
|
+
localIdStatus: newlocalIdStatus,
|
|
353
|
+
modified: modified
|
|
354
|
+
};
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Processes a transaction to update localId tracking state
|
|
359
|
+
*/
|
|
360
|
+
var processTransaction = function processTransaction(tr, currentState) {
|
|
361
|
+
var localIdStatus = currentState.localIdStatus;
|
|
362
|
+
var modified = false;
|
|
363
|
+
|
|
364
|
+
// Process each step in the transaction
|
|
365
|
+
try {
|
|
366
|
+
tr.steps.forEach(function (step, index) {
|
|
367
|
+
var _tr$docs$index, _tr$docs, _tr$docs2, _tr$docs3;
|
|
368
|
+
var result;
|
|
369
|
+
// steps are relative to their docs, so we ensure we reference the doc before/after the step was applied.
|
|
370
|
+
var preDoc = (_tr$docs$index = (_tr$docs = tr.docs) === null || _tr$docs === void 0 ? void 0 : _tr$docs[index]) !== null && _tr$docs$index !== void 0 ? _tr$docs$index : tr.doc;
|
|
371
|
+
var postDoc = (_tr$docs2 = (_tr$docs3 = tr.docs) === null || _tr$docs3 === void 0 ? void 0 : _tr$docs3[index + 1]) !== null && _tr$docs2 !== void 0 ? _tr$docs2 : tr.doc;
|
|
372
|
+
if (step instanceof _transform.AttrStep || step instanceof _transform.DocAttrStep) {
|
|
373
|
+
result = handleAttrStep(tr, step, localIdStatus, preDoc);
|
|
374
|
+
} else if (step instanceof _steps.SetAttrsStep) {
|
|
375
|
+
result = handleSetAttrsStep(tr, step, localIdStatus, preDoc);
|
|
376
|
+
} else if (step instanceof _steps.BatchAttrsStep) {
|
|
377
|
+
result = handleBatchAttrsStep(tr, step, localIdStatus, preDoc);
|
|
378
|
+
} else if (step instanceof _transform.ReplaceStep) {
|
|
379
|
+
result = handleReplaceStep(tr, step, localIdStatus, preDoc, postDoc);
|
|
380
|
+
} else if (step instanceof _transform.ReplaceAroundStep) {
|
|
381
|
+
result = handleReplaceAroundStep(tr, step, localIdStatus, preDoc, postDoc);
|
|
382
|
+
} else {
|
|
383
|
+
// Unknown step type, no changes
|
|
384
|
+
result = {
|
|
385
|
+
localIdStatus: localIdStatus,
|
|
386
|
+
modified: false
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
localIdStatus = result.localIdStatus;
|
|
390
|
+
modified = modified || result.modified;
|
|
391
|
+
});
|
|
392
|
+
} catch (_unused6) {
|
|
393
|
+
// If any error occurs during step processing, we fallback to disabling the plugin
|
|
394
|
+
return {
|
|
395
|
+
enabled: false,
|
|
396
|
+
initLocalIdSize: currentState.initLocalIdSize,
|
|
397
|
+
localIdStatus: new Map(),
|
|
398
|
+
lastUpdated: Date.now()
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// If nothing changed, return the same state object
|
|
403
|
+
if (!modified) {
|
|
404
|
+
return currentState;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// If we exceeded the max size while processing the steps, we need to disable the watchmen from further processing.
|
|
408
|
+
// If a Map size limit of 2^24 is exceeded then it's more than likely an error would have been thrown during processing
|
|
409
|
+
// which would also disable this plugin.
|
|
410
|
+
if (localIdStatus.size >= MAX_LOCAL_ID_MAP_SIZE) {
|
|
411
|
+
return {
|
|
412
|
+
enabled: false,
|
|
413
|
+
initLocalIdSize: currentState.initLocalIdSize,
|
|
414
|
+
localIdStatus: new Map(),
|
|
415
|
+
lastUpdated: Date.now()
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Return new state with updated sets
|
|
420
|
+
return {
|
|
421
|
+
enabled: true,
|
|
422
|
+
initLocalIdSize: currentState.initLocalIdSize,
|
|
423
|
+
localIdStatus: localIdStatus,
|
|
424
|
+
lastUpdated: Date.now()
|
|
425
|
+
};
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Creates the localId watchmen plugin
|
|
430
|
+
*/
|
|
431
|
+
var createWatchmenPlugin = exports.createWatchmenPlugin = function createWatchmenPlugin(api) {
|
|
432
|
+
// Ensure limited mode is initialized
|
|
433
|
+
return new _safePlugin.SafePlugin({
|
|
434
|
+
key: localIdWatchmenPluginKey,
|
|
435
|
+
state: {
|
|
436
|
+
init: function init(_config, state) {
|
|
437
|
+
var _api$limitedMode$shar, _api$limitedMode;
|
|
438
|
+
var isLimitedModeEnabled = (_api$limitedMode$shar = api === null || api === void 0 || (_api$limitedMode = api.limitedMode) === null || _api$limitedMode === void 0 || (_api$limitedMode = _api$limitedMode.sharedState.currentState()) === null || _api$limitedMode === void 0 ? void 0 : _api$limitedMode.enabled) !== null && _api$limitedMode$shar !== void 0 ? _api$limitedMode$shar : false;
|
|
439
|
+
if (isLimitedModeEnabled) {
|
|
440
|
+
return {
|
|
441
|
+
enabled: false,
|
|
442
|
+
initLocalIdSize: -1,
|
|
443
|
+
localIdStatus: new Map(),
|
|
444
|
+
lastUpdated: Date.now()
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Initialize by scanning the entire document
|
|
449
|
+
var activeLocalIds = scanDocumentForLocalIds(state.doc);
|
|
450
|
+
if (activeLocalIds.size >= MAX_LOCAL_ID_MAP_SIZE) {
|
|
451
|
+
return {
|
|
452
|
+
enabled: false,
|
|
453
|
+
initLocalIdSize: activeLocalIds.size,
|
|
454
|
+
localIdStatus: new Map(),
|
|
455
|
+
lastUpdated: Date.now()
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
return {
|
|
459
|
+
enabled: true,
|
|
460
|
+
initLocalIdSize: activeLocalIds.size,
|
|
461
|
+
localIdStatus: new Map(Array.from(activeLocalIds).map(function (key) {
|
|
462
|
+
return [key, 'current'];
|
|
463
|
+
})),
|
|
464
|
+
lastUpdated: Date.now()
|
|
465
|
+
};
|
|
466
|
+
},
|
|
467
|
+
apply: function apply(tr, currentPluginState) {
|
|
468
|
+
var _ref = tr.getMeta(localIdWatchmenPluginKey) || {
|
|
469
|
+
enabled: currentPluginState.enabled
|
|
470
|
+
},
|
|
471
|
+
enabled = _ref.enabled;
|
|
472
|
+
var newPluginState = currentPluginState;
|
|
473
|
+
if (enabled !== currentPluginState.enabled) {
|
|
474
|
+
// If this plugin enabled state is changing and it's being disabled at runtime then we will kill this plugin
|
|
475
|
+
// to avoid tracking localIds when in limited mode or there after.
|
|
476
|
+
// Once disabled it cannot be re-enabled without a full editor reload.
|
|
477
|
+
if (!enabled) {
|
|
478
|
+
return {
|
|
479
|
+
enabled: false,
|
|
480
|
+
initLocalIdSize: currentPluginState.initLocalIdSize,
|
|
481
|
+
localIdStatus: currentPluginState.localIdStatus,
|
|
482
|
+
lastUpdated: Date.now()
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
if (!newPluginState.enabled) {
|
|
487
|
+
// If this plugin has been disabled, do not track localIds.
|
|
488
|
+
return newPluginState;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// If no steps, nothing changed
|
|
492
|
+
if (tr.steps.length === 0 || !tr.docChanged) {
|
|
493
|
+
return newPluginState;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// Process the transaction to update state
|
|
497
|
+
return processTransaction(tr, newPluginState);
|
|
498
|
+
}
|
|
499
|
+
},
|
|
500
|
+
view: function view(editorView) {
|
|
501
|
+
var _api$limitedMode2;
|
|
502
|
+
// If limited mode changes, for example if we start not limited but then all of a sudden become limited, we kill
|
|
503
|
+
// the watchment plugin to avoid tracking localIds when in limited mode. We also don't want/need to re-enable it once it's disabled.
|
|
504
|
+
var unsub = api === null || api === void 0 || (_api$limitedMode2 = api.limitedMode) === null || _api$limitedMode2 === void 0 ? void 0 : _api$limitedMode2.sharedState.onChange(function (_ref2) {
|
|
505
|
+
var nextSharedState = _ref2.nextSharedState;
|
|
506
|
+
var watchmentPluginState = localIdWatchmenPluginKey.getState(editorView.state);
|
|
507
|
+
if (nextSharedState.enabled && (watchmentPluginState === null || watchmentPluginState === void 0 ? void 0 : watchmentPluginState.enabled) === true) {
|
|
508
|
+
// if nextSharedState.enabled === true, then we need to disable the watchmen plugin, if not already disabled
|
|
509
|
+
editorView.dispatch(editorView.state.tr.setMeta(localIdWatchmenPluginKey, {
|
|
510
|
+
enabled: false
|
|
511
|
+
}));
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
return {
|
|
515
|
+
destroy: unsub
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
1
2
|
import { replaceNode, getNode } from './editor-actions';
|
|
2
3
|
import { createPlugin } from './pm-plugins/main';
|
|
4
|
+
import { createWatchmenPlugin, localIdWatchmenPluginKey } from './pm-plugins/watchmen';
|
|
3
5
|
export const localIdPlugin = ({
|
|
4
6
|
api
|
|
5
7
|
}) => ({
|
|
@@ -12,6 +14,19 @@ export const localIdPlugin = ({
|
|
|
12
14
|
return [{
|
|
13
15
|
name: 'localIdPlugin',
|
|
14
16
|
plugin: () => createPlugin(api)
|
|
17
|
+
}, {
|
|
18
|
+
name: 'localId-watchmen',
|
|
19
|
+
plugin: () => fg('platform_editor_ai_aifc_localid_error_reporting') ? createWatchmenPlugin(api) : undefined
|
|
15
20
|
}];
|
|
21
|
+
},
|
|
22
|
+
getSharedState(editorState) {
|
|
23
|
+
if (!editorState) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const watchmentPluginState = localIdWatchmenPluginKey.getState(editorState);
|
|
27
|
+
return {
|
|
28
|
+
localIdWatchmenEnabled: !!(watchmentPluginState !== null && watchmentPluginState !== void 0 && watchmentPluginState.enabled),
|
|
29
|
+
localIdStatus: new Map(watchmentPluginState === null || watchmentPluginState === void 0 ? void 0 : watchmentPluginState.localIdStatus)
|
|
30
|
+
};
|
|
16
31
|
}
|
|
17
32
|
});
|