@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 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
@@ -21,6 +21,9 @@
21
21
  {
22
22
  "path": "../../adf-schema/afm-cc/tsconfig.json"
23
23
  },
24
+ {
25
+ "path": "../../editor-plugin-limited-mode/afm-cc/tsconfig.json"
26
+ },
24
27
  {
25
28
  "path": "../../editor-prosemirror/afm-cc/tsconfig.json"
26
29
  },
@@ -21,6 +21,9 @@
21
21
  {
22
22
  "path": "../../adf-schema/afm-jira/tsconfig.json"
23
23
  },
24
+ {
25
+ "path": "../../editor-plugin-limited-mode/afm-jira/tsconfig.json"
26
+ },
24
27
  {
25
28
  "path": "../../editor-prosemirror/afm-jira/tsconfig.json"
26
29
  },
@@ -21,6 +21,9 @@
21
21
  {
22
22
  "path": "../../adf-schema/afm-products/tsconfig.json"
23
23
  },
24
+ {
25
+ "path": "../../editor-plugin-limited-mode/afm-products/tsconfig.json"
26
+ },
24
27
  {
25
28
  "path": "../../editor-prosemirror/afm-products/tsconfig.json"
26
29
  },
@@ -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
  });