@atlaskit/editor-plugin-local-id 13.0.3 → 13.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/afm-cc/tsconfig.json +3 -0
- package/dist/cjs/editor-commands/index.js +20 -0
- package/dist/cjs/localIdPlugin.js +4 -0
- package/dist/cjs/pm-plugins/add-missing-local-ids.js +71 -0
- package/dist/cjs/pm-plugins/main.js +11 -30
- package/dist/es2019/editor-commands/index.js +13 -0
- package/dist/es2019/localIdPlugin.js +4 -0
- package/dist/es2019/pm-plugins/add-missing-local-ids.js +57 -0
- package/dist/es2019/pm-plugins/main.js +9 -24
- package/dist/esm/editor-commands/index.js +15 -0
- package/dist/esm/localIdPlugin.js +4 -0
- package/dist/esm/pm-plugins/add-missing-local-ids.js +64 -0
- package/dist/esm/pm-plugins/main.js +9 -28
- package/dist/types/editor-commands/index.d.ts +6 -0
- package/dist/types/localIdPluginType.d.ts +12 -1
- package/dist/types/pm-plugins/add-missing-local-ids.d.ts +10 -0
- package/dist/types/pm-plugins/main.d.ts +1 -7
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-local-id
|
|
2
2
|
|
|
3
|
+
## 13.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`bbd0908b16b23`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/bbd0908b16b23) -
|
|
8
|
+
Under `platform_editor_local_id_reliability`, improve local ID reliability by validating blank IDs
|
|
9
|
+
and rescanning the document before Rovo reads it.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
|
|
3
15
|
## 13.0.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/afm-cc/tsconfig.json
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.addMissingLocalIds = void 0;
|
|
7
|
+
var _addMissingLocalIds = require("../pm-plugins/add-missing-local-ids");
|
|
8
|
+
/**
|
|
9
|
+
* Scans the current document and adds missing local IDs.
|
|
10
|
+
*/
|
|
11
|
+
var addMissingLocalIds = exports.addMissingLocalIds = function addMissingLocalIds() {
|
|
12
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
13
|
+
return function (_ref) {
|
|
14
|
+
var tr = _ref.tr;
|
|
15
|
+
if (!(0, _addMissingLocalIds.addMissingLocalIdsToDocument)(tr, options)) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return tr;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.localIdPlugin = void 0;
|
|
7
7
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
8
8
|
var _editorActions = require("./editor-actions");
|
|
9
|
+
var _editorCommands = require("./editor-commands");
|
|
9
10
|
var _main = require("./pm-plugins/main");
|
|
10
11
|
var _watchmen = require("./pm-plugins/watchmen");
|
|
11
12
|
var localIdPlugin = exports.localIdPlugin = function localIdPlugin(_ref) {
|
|
@@ -16,6 +17,9 @@ var localIdPlugin = exports.localIdPlugin = function localIdPlugin(_ref) {
|
|
|
16
17
|
replaceNode: (0, _editorActions.replaceNode)(api),
|
|
17
18
|
getNode: (0, _editorActions.getNode)(api)
|
|
18
19
|
},
|
|
20
|
+
commands: {
|
|
21
|
+
addMissingLocalIds: _editorCommands.addMissingLocalIds
|
|
22
|
+
},
|
|
19
23
|
pmPlugins: function pmPlugins() {
|
|
20
24
|
return [{
|
|
21
25
|
name: 'localIdPlugin',
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.localIdNotEmpty = exports.batchAddLocalIdToNodes = exports.addMissingLocalIdsToDocument = void 0;
|
|
8
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
9
|
+
var _steps = require("@atlaskit/adf-schema/steps");
|
|
10
|
+
var _collab = require("@atlaskit/editor-common/collab");
|
|
11
|
+
var _generateShortUUID = require("./generateShortUUID");
|
|
12
|
+
var localIdNotEmpty = exports.localIdNotEmpty = function localIdNotEmpty(localId) {
|
|
13
|
+
return typeof localId === 'string' && localId.trim().length > 0;
|
|
14
|
+
};
|
|
15
|
+
var addMissingLocalIdsToDocument = exports.addMissingLocalIdsToDocument = function addMissingLocalIdsToDocument(tr) {
|
|
16
|
+
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
17
|
+
onRepaired = _ref.onRepaired;
|
|
18
|
+
var missingLocalIdPositions = [];
|
|
19
|
+
var _tr$doc$type$schema$n = tr.doc.type.schema.nodes,
|
|
20
|
+
text = _tr$doc$type$schema$n.text,
|
|
21
|
+
hardBreak = _tr$doc$type$schema$n.hardBreak,
|
|
22
|
+
mediaGroup = _tr$doc$type$schema$n.mediaGroup;
|
|
23
|
+
var ignoredNodeTypes = [text === null || text === void 0 ? void 0 : text.name, hardBreak === null || hardBreak === void 0 ? void 0 : hardBreak.name, mediaGroup === null || mediaGroup === void 0 ? void 0 : mediaGroup.name];
|
|
24
|
+
tr.doc.descendants(function (node, pos) {
|
|
25
|
+
var _node$type$spec$attrs;
|
|
26
|
+
if (localIdNotEmpty(node.attrs.localId)) {
|
|
27
|
+
_generateShortUUID.generatedShortUUIDs.add(node.attrs.localId);
|
|
28
|
+
} else if (!ignoredNodeTypes.includes(node.type.name) && !!((_node$type$spec$attrs = node.type.spec.attrs) !== null && _node$type$spec$attrs !== void 0 && _node$type$spec$attrs.localId)) {
|
|
29
|
+
missingLocalIdPositions.push(pos);
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
});
|
|
33
|
+
var nodesToUpdate = new Map(missingLocalIdPositions.map(function (pos) {
|
|
34
|
+
return [pos, (0, _generateShortUUID.generateShortUUID)()];
|
|
35
|
+
}));
|
|
36
|
+
if (nodesToUpdate.size === 0) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
batchAddLocalIdToNodes(nodesToUpdate, tr);
|
|
40
|
+
(0, _collab.tintDirtyTransaction)(tr);
|
|
41
|
+
onRepaired === null || onRepaired === void 0 || onRepaired({
|
|
42
|
+
repairedNodeCount: nodesToUpdate.size
|
|
43
|
+
});
|
|
44
|
+
return true;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Batch adds local IDs to nodes using a BatchAttrsStep
|
|
49
|
+
* @param nodesToUpdate Map of position -> localId for nodes that need updates
|
|
50
|
+
* @param tr
|
|
51
|
+
*/
|
|
52
|
+
var batchAddLocalIdToNodes = exports.batchAddLocalIdToNodes = function batchAddLocalIdToNodes(nodesToUpdate, tr) {
|
|
53
|
+
var batchData = Array.from(nodesToUpdate.entries()).map(function (_ref2) {
|
|
54
|
+
var _ref3 = (0, _slicedToArray2.default)(_ref2, 2),
|
|
55
|
+
pos = _ref3[0],
|
|
56
|
+
localId = _ref3[1];
|
|
57
|
+
var node = tr.doc.nodeAt(pos);
|
|
58
|
+
if (!node) {
|
|
59
|
+
throw new Error("Node does not exist at position ".concat(pos));
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
position: pos,
|
|
63
|
+
attrs: {
|
|
64
|
+
localId: localId
|
|
65
|
+
},
|
|
66
|
+
nodeType: node.type.name
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
tr.step(new _steps.BatchAttrsStep(batchData));
|
|
70
|
+
tr.setMeta('addToHistory', false);
|
|
71
|
+
};
|
|
@@ -4,15 +4,17 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.localIdPluginKey = exports.createPlugin =
|
|
8
|
-
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
7
|
+
exports.localIdPluginKey = exports.createPlugin = void 0;
|
|
9
8
|
var _toArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toArray"));
|
|
10
9
|
var _steps = require("@atlaskit/adf-schema/steps");
|
|
11
10
|
var _collab = require("@atlaskit/editor-common/collab");
|
|
12
11
|
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
13
12
|
var _utils = require("@atlaskit/editor-common/utils");
|
|
14
13
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
14
|
+
var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
|
|
15
15
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
16
|
+
var _editorCommands = require("../editor-commands");
|
|
17
|
+
var _addMissingLocalIds = require("./add-missing-local-ids");
|
|
16
18
|
var _generateShortUUID = require("./generateShortUUID");
|
|
17
19
|
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; } } }; }
|
|
18
20
|
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; } }
|
|
@@ -48,6 +50,10 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
48
50
|
};
|
|
49
51
|
}
|
|
50
52
|
requestIdleCallbackWithFallback(function () {
|
|
53
|
+
if ((0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_local_id_reliability')) {
|
|
54
|
+
api === null || api === void 0 || api.core.actions.execute((0, _editorCommands.addMissingLocalIds)());
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
51
57
|
var tr = editorView.state.tr;
|
|
52
58
|
var nodesToUpdate = new Map(); // position -> localId
|
|
53
59
|
|
|
@@ -66,7 +72,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
66
72
|
return true; // Continue traversing
|
|
67
73
|
});
|
|
68
74
|
if (nodesToUpdate.size > 0) {
|
|
69
|
-
batchAddLocalIdToNodes(nodesToUpdate, tr);
|
|
75
|
+
(0, _addMissingLocalIds.batchAddLocalIdToNodes)(nodesToUpdate, tr);
|
|
70
76
|
(0, _collab.tintDirtyTransaction)(tr);
|
|
71
77
|
editorView.dispatch(tr);
|
|
72
78
|
}
|
|
@@ -190,7 +196,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
190
196
|
continue;
|
|
191
197
|
}
|
|
192
198
|
var existingId = node.attrs.localId;
|
|
193
|
-
var needsNewIds = !existingId || localIds.has(existingId) || seenIds.has(existingId);
|
|
199
|
+
var needsNewIds = ((0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_local_id_reliability') ? !(0, _addMissingLocalIds.localIdNotEmpty)(existingId) : !existingId) || localIds.has(existingId) || seenIds.has(existingId);
|
|
194
200
|
if (needsNewIds) {
|
|
195
201
|
// No usable localId: assign a fresh unique one to every position.
|
|
196
202
|
var _iterator2 = _createForOfIteratorHelper(positions),
|
|
@@ -245,34 +251,9 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
245
251
|
// - When enabled: Batch all updates into a single BatchAttrsStep
|
|
246
252
|
// - When disabled: Individual steps were already applied above during node processing
|
|
247
253
|
if (modified && nodesToUpdate.size > 0) {
|
|
248
|
-
batchAddLocalIdToNodes(nodesToUpdate, tr);
|
|
254
|
+
(0, _addMissingLocalIds.batchAddLocalIdToNodes)(nodesToUpdate, tr);
|
|
249
255
|
}
|
|
250
256
|
return modified ? tr : undefined;
|
|
251
257
|
}
|
|
252
258
|
});
|
|
253
|
-
};
|
|
254
|
-
/**
|
|
255
|
-
* Batch adds local IDs to nodes using a BatchAttrsStep
|
|
256
|
-
* @param nodesToUpdate Map of position -> localId for nodes that need updates
|
|
257
|
-
* @param tr
|
|
258
|
-
*/
|
|
259
|
-
var batchAddLocalIdToNodes = exports.batchAddLocalIdToNodes = function batchAddLocalIdToNodes(nodesToUpdate, tr) {
|
|
260
|
-
var batchData = Array.from(nodesToUpdate.entries()).map(function (_ref) {
|
|
261
|
-
var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
|
|
262
|
-
pos = _ref2[0],
|
|
263
|
-
localId = _ref2[1];
|
|
264
|
-
var node = tr.doc.nodeAt(pos);
|
|
265
|
-
if (!node) {
|
|
266
|
-
throw new Error("Node does not exist at position ".concat(pos));
|
|
267
|
-
}
|
|
268
|
-
return {
|
|
269
|
-
position: pos,
|
|
270
|
-
attrs: {
|
|
271
|
-
localId: localId
|
|
272
|
-
},
|
|
273
|
-
nodeType: node.type.name
|
|
274
|
-
};
|
|
275
|
-
});
|
|
276
|
-
tr.step(new _steps.BatchAttrsStep(batchData));
|
|
277
|
-
tr.setMeta('addToHistory', false);
|
|
278
259
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { addMissingLocalIdsToDocument } from '../pm-plugins/add-missing-local-ids';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Scans the current document and adds missing local IDs.
|
|
5
|
+
*/
|
|
6
|
+
export const addMissingLocalIds = (options = {}) => ({
|
|
7
|
+
tr
|
|
8
|
+
}) => {
|
|
9
|
+
if (!addMissingLocalIdsToDocument(tr, options)) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return tr;
|
|
13
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
2
2
|
import { replaceNode, getNode } from './editor-actions';
|
|
3
|
+
import { addMissingLocalIds } from './editor-commands';
|
|
3
4
|
import { createPlugin } from './pm-plugins/main';
|
|
4
5
|
import { createWatchmenPlugin, localIdWatchmenPluginKey } from './pm-plugins/watchmen';
|
|
5
6
|
export const localIdPlugin = ({
|
|
@@ -10,6 +11,9 @@ export const localIdPlugin = ({
|
|
|
10
11
|
replaceNode: replaceNode(api),
|
|
11
12
|
getNode: getNode(api)
|
|
12
13
|
},
|
|
14
|
+
commands: {
|
|
15
|
+
addMissingLocalIds
|
|
16
|
+
},
|
|
13
17
|
pmPlugins() {
|
|
14
18
|
return [{
|
|
15
19
|
name: 'localIdPlugin',
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { BatchAttrsStep } from '@atlaskit/adf-schema/steps';
|
|
2
|
+
import { tintDirtyTransaction } from '@atlaskit/editor-common/collab';
|
|
3
|
+
import { generateShortUUID, generatedShortUUIDs } from './generateShortUUID';
|
|
4
|
+
export const localIdNotEmpty = localId => typeof localId === 'string' && localId.trim().length > 0;
|
|
5
|
+
export const addMissingLocalIdsToDocument = (tr, {
|
|
6
|
+
onRepaired
|
|
7
|
+
} = {}) => {
|
|
8
|
+
const missingLocalIdPositions = [];
|
|
9
|
+
const {
|
|
10
|
+
text,
|
|
11
|
+
hardBreak,
|
|
12
|
+
mediaGroup
|
|
13
|
+
} = tr.doc.type.schema.nodes;
|
|
14
|
+
const ignoredNodeTypes = [text === null || text === void 0 ? void 0 : text.name, hardBreak === null || hardBreak === void 0 ? void 0 : hardBreak.name, mediaGroup === null || mediaGroup === void 0 ? void 0 : mediaGroup.name];
|
|
15
|
+
tr.doc.descendants((node, pos) => {
|
|
16
|
+
var _node$type$spec$attrs;
|
|
17
|
+
if (localIdNotEmpty(node.attrs.localId)) {
|
|
18
|
+
generatedShortUUIDs.add(node.attrs.localId);
|
|
19
|
+
} else if (!ignoredNodeTypes.includes(node.type.name) && !!((_node$type$spec$attrs = node.type.spec.attrs) !== null && _node$type$spec$attrs !== void 0 && _node$type$spec$attrs.localId)) {
|
|
20
|
+
missingLocalIdPositions.push(pos);
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
});
|
|
24
|
+
const nodesToUpdate = new Map(missingLocalIdPositions.map(pos => [pos, generateShortUUID()]));
|
|
25
|
+
if (nodesToUpdate.size === 0) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
batchAddLocalIdToNodes(nodesToUpdate, tr);
|
|
29
|
+
tintDirtyTransaction(tr);
|
|
30
|
+
onRepaired === null || onRepaired === void 0 ? void 0 : onRepaired({
|
|
31
|
+
repairedNodeCount: nodesToUpdate.size
|
|
32
|
+
});
|
|
33
|
+
return true;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Batch adds local IDs to nodes using a BatchAttrsStep
|
|
38
|
+
* @param nodesToUpdate Map of position -> localId for nodes that need updates
|
|
39
|
+
* @param tr
|
|
40
|
+
*/
|
|
41
|
+
export const batchAddLocalIdToNodes = (nodesToUpdate, tr) => {
|
|
42
|
+
const batchData = Array.from(nodesToUpdate.entries()).map(([pos, localId]) => {
|
|
43
|
+
const node = tr.doc.nodeAt(pos);
|
|
44
|
+
if (!node) {
|
|
45
|
+
throw new Error(`Node does not exist at position ${pos}`);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
position: pos,
|
|
49
|
+
attrs: {
|
|
50
|
+
localId
|
|
51
|
+
},
|
|
52
|
+
nodeType: node.type.name
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
tr.step(new BatchAttrsStep(batchData));
|
|
56
|
+
tr.setMeta('addToHistory', false);
|
|
57
|
+
};
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OverrideDocumentStep } from '@atlaskit/adf-schema/steps';
|
|
2
2
|
import { tintDirtyTransaction } from '@atlaskit/editor-common/collab';
|
|
3
3
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
4
4
|
import { stepHasSlice } from '@atlaskit/editor-common/utils';
|
|
5
5
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
6
|
+
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
6
7
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
8
|
+
import { addMissingLocalIds } from '../editor-commands';
|
|
9
|
+
import { batchAddLocalIdToNodes, localIdNotEmpty } from './add-missing-local-ids';
|
|
7
10
|
import { generateShortUUID, generatedShortUUIDs } from './generateShortUUID';
|
|
8
11
|
export const localIdPluginKey = new PluginKey('localIdPlugin');
|
|
9
12
|
const generateUUID = () => {
|
|
@@ -36,6 +39,10 @@ export const createPlugin = api => {
|
|
|
36
39
|
};
|
|
37
40
|
}
|
|
38
41
|
requestIdleCallbackWithFallback(() => {
|
|
42
|
+
if (isExperimentEnabled('platform_editor_local_id_reliability')) {
|
|
43
|
+
api === null || api === void 0 ? void 0 : api.core.actions.execute(addMissingLocalIds());
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
39
46
|
const tr = editorView.state.tr;
|
|
40
47
|
const nodesToUpdate = new Map(); // position -> localId
|
|
41
48
|
|
|
@@ -174,7 +181,7 @@ export const createPlugin = api => {
|
|
|
174
181
|
continue;
|
|
175
182
|
}
|
|
176
183
|
const existingId = node.attrs.localId;
|
|
177
|
-
const needsNewIds = !existingId || localIds.has(existingId) || seenIds.has(existingId);
|
|
184
|
+
const needsNewIds = (isExperimentEnabled('platform_editor_local_id_reliability') ? !localIdNotEmpty(existingId) : !existingId) || localIds.has(existingId) || seenIds.has(existingId);
|
|
178
185
|
if (needsNewIds) {
|
|
179
186
|
// No usable localId: assign a fresh unique one to every position.
|
|
180
187
|
for (const pos of positions) {
|
|
@@ -208,26 +215,4 @@ export const createPlugin = api => {
|
|
|
208
215
|
return modified ? tr : undefined;
|
|
209
216
|
}
|
|
210
217
|
});
|
|
211
|
-
};
|
|
212
|
-
/**
|
|
213
|
-
* Batch adds local IDs to nodes using a BatchAttrsStep
|
|
214
|
-
* @param nodesToUpdate Map of position -> localId for nodes that need updates
|
|
215
|
-
* @param tr
|
|
216
|
-
*/
|
|
217
|
-
export const batchAddLocalIdToNodes = (nodesToUpdate, tr) => {
|
|
218
|
-
const batchData = Array.from(nodesToUpdate.entries()).map(([pos, localId]) => {
|
|
219
|
-
const node = tr.doc.nodeAt(pos);
|
|
220
|
-
if (!node) {
|
|
221
|
-
throw new Error(`Node does not exist at position ${pos}`);
|
|
222
|
-
}
|
|
223
|
-
return {
|
|
224
|
-
position: pos,
|
|
225
|
-
attrs: {
|
|
226
|
-
localId
|
|
227
|
-
},
|
|
228
|
-
nodeType: node.type.name
|
|
229
|
-
};
|
|
230
|
-
});
|
|
231
|
-
tr.step(new BatchAttrsStep(batchData));
|
|
232
|
-
tr.setMeta('addToHistory', false);
|
|
233
218
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { addMissingLocalIdsToDocument } from '../pm-plugins/add-missing-local-ids';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Scans the current document and adds missing local IDs.
|
|
5
|
+
*/
|
|
6
|
+
export var addMissingLocalIds = function addMissingLocalIds() {
|
|
7
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
8
|
+
return function (_ref) {
|
|
9
|
+
var tr = _ref.tr;
|
|
10
|
+
if (!addMissingLocalIdsToDocument(tr, options)) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
return tr;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
2
2
|
import { replaceNode, getNode } from './editor-actions';
|
|
3
|
+
import { addMissingLocalIds } from './editor-commands';
|
|
3
4
|
import { createPlugin } from './pm-plugins/main';
|
|
4
5
|
import { createWatchmenPlugin, localIdWatchmenPluginKey } from './pm-plugins/watchmen';
|
|
5
6
|
export var localIdPlugin = function localIdPlugin(_ref) {
|
|
@@ -10,6 +11,9 @@ export var localIdPlugin = function localIdPlugin(_ref) {
|
|
|
10
11
|
replaceNode: replaceNode(api),
|
|
11
12
|
getNode: getNode(api)
|
|
12
13
|
},
|
|
14
|
+
commands: {
|
|
15
|
+
addMissingLocalIds: addMissingLocalIds
|
|
16
|
+
},
|
|
13
17
|
pmPlugins: function pmPlugins() {
|
|
14
18
|
return [{
|
|
15
19
|
name: 'localIdPlugin',
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
import { BatchAttrsStep } from '@atlaskit/adf-schema/steps';
|
|
3
|
+
import { tintDirtyTransaction } from '@atlaskit/editor-common/collab';
|
|
4
|
+
import { generateShortUUID, generatedShortUUIDs } from './generateShortUUID';
|
|
5
|
+
export var localIdNotEmpty = function localIdNotEmpty(localId) {
|
|
6
|
+
return typeof localId === 'string' && localId.trim().length > 0;
|
|
7
|
+
};
|
|
8
|
+
export var addMissingLocalIdsToDocument = function addMissingLocalIdsToDocument(tr) {
|
|
9
|
+
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
10
|
+
onRepaired = _ref.onRepaired;
|
|
11
|
+
var missingLocalIdPositions = [];
|
|
12
|
+
var _tr$doc$type$schema$n = tr.doc.type.schema.nodes,
|
|
13
|
+
text = _tr$doc$type$schema$n.text,
|
|
14
|
+
hardBreak = _tr$doc$type$schema$n.hardBreak,
|
|
15
|
+
mediaGroup = _tr$doc$type$schema$n.mediaGroup;
|
|
16
|
+
var ignoredNodeTypes = [text === null || text === void 0 ? void 0 : text.name, hardBreak === null || hardBreak === void 0 ? void 0 : hardBreak.name, mediaGroup === null || mediaGroup === void 0 ? void 0 : mediaGroup.name];
|
|
17
|
+
tr.doc.descendants(function (node, pos) {
|
|
18
|
+
var _node$type$spec$attrs;
|
|
19
|
+
if (localIdNotEmpty(node.attrs.localId)) {
|
|
20
|
+
generatedShortUUIDs.add(node.attrs.localId);
|
|
21
|
+
} else if (!ignoredNodeTypes.includes(node.type.name) && !!((_node$type$spec$attrs = node.type.spec.attrs) !== null && _node$type$spec$attrs !== void 0 && _node$type$spec$attrs.localId)) {
|
|
22
|
+
missingLocalIdPositions.push(pos);
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
});
|
|
26
|
+
var nodesToUpdate = new Map(missingLocalIdPositions.map(function (pos) {
|
|
27
|
+
return [pos, generateShortUUID()];
|
|
28
|
+
}));
|
|
29
|
+
if (nodesToUpdate.size === 0) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
batchAddLocalIdToNodes(nodesToUpdate, tr);
|
|
33
|
+
tintDirtyTransaction(tr);
|
|
34
|
+
onRepaired === null || onRepaired === void 0 || onRepaired({
|
|
35
|
+
repairedNodeCount: nodesToUpdate.size
|
|
36
|
+
});
|
|
37
|
+
return true;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Batch adds local IDs to nodes using a BatchAttrsStep
|
|
42
|
+
* @param nodesToUpdate Map of position -> localId for nodes that need updates
|
|
43
|
+
* @param tr
|
|
44
|
+
*/
|
|
45
|
+
export var batchAddLocalIdToNodes = function batchAddLocalIdToNodes(nodesToUpdate, tr) {
|
|
46
|
+
var batchData = Array.from(nodesToUpdate.entries()).map(function (_ref2) {
|
|
47
|
+
var _ref3 = _slicedToArray(_ref2, 2),
|
|
48
|
+
pos = _ref3[0],
|
|
49
|
+
localId = _ref3[1];
|
|
50
|
+
var node = tr.doc.nodeAt(pos);
|
|
51
|
+
if (!node) {
|
|
52
|
+
throw new Error("Node does not exist at position ".concat(pos));
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
position: pos,
|
|
56
|
+
attrs: {
|
|
57
|
+
localId: localId
|
|
58
|
+
},
|
|
59
|
+
nodeType: node.type.name
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
tr.step(new BatchAttrsStep(batchData));
|
|
63
|
+
tr.setMeta('addToHistory', false);
|
|
64
|
+
};
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
1
|
import _toArray from "@babel/runtime/helpers/toArray";
|
|
3
2
|
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; } } }; }
|
|
4
3
|
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; } }
|
|
5
4
|
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; }
|
|
6
|
-
import {
|
|
5
|
+
import { OverrideDocumentStep } from '@atlaskit/adf-schema/steps';
|
|
7
6
|
import { tintDirtyTransaction } from '@atlaskit/editor-common/collab';
|
|
8
7
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
9
8
|
import { stepHasSlice } from '@atlaskit/editor-common/utils';
|
|
10
9
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
10
|
+
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
11
11
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
12
|
+
import { addMissingLocalIds } from '../editor-commands';
|
|
13
|
+
import { batchAddLocalIdToNodes, localIdNotEmpty } from './add-missing-local-ids';
|
|
12
14
|
import { generateShortUUID, generatedShortUUIDs } from './generateShortUUID';
|
|
13
15
|
export var localIdPluginKey = new PluginKey('localIdPlugin');
|
|
14
16
|
var generateUUID = function generateUUID() {
|
|
@@ -41,6 +43,10 @@ export var createPlugin = function createPlugin(api) {
|
|
|
41
43
|
};
|
|
42
44
|
}
|
|
43
45
|
requestIdleCallbackWithFallback(function () {
|
|
46
|
+
if (isExperimentEnabled('platform_editor_local_id_reliability')) {
|
|
47
|
+
api === null || api === void 0 || api.core.actions.execute(addMissingLocalIds());
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
44
50
|
var tr = editorView.state.tr;
|
|
45
51
|
var nodesToUpdate = new Map(); // position -> localId
|
|
46
52
|
|
|
@@ -183,7 +189,7 @@ export var createPlugin = function createPlugin(api) {
|
|
|
183
189
|
continue;
|
|
184
190
|
}
|
|
185
191
|
var existingId = node.attrs.localId;
|
|
186
|
-
var needsNewIds = !existingId || localIds.has(existingId) || seenIds.has(existingId);
|
|
192
|
+
var needsNewIds = (isExperimentEnabled('platform_editor_local_id_reliability') ? !localIdNotEmpty(existingId) : !existingId) || localIds.has(existingId) || seenIds.has(existingId);
|
|
187
193
|
if (needsNewIds) {
|
|
188
194
|
// No usable localId: assign a fresh unique one to every position.
|
|
189
195
|
var _iterator2 = _createForOfIteratorHelper(positions),
|
|
@@ -243,29 +249,4 @@ export var createPlugin = function createPlugin(api) {
|
|
|
243
249
|
return modified ? tr : undefined;
|
|
244
250
|
}
|
|
245
251
|
});
|
|
246
|
-
};
|
|
247
|
-
/**
|
|
248
|
-
* Batch adds local IDs to nodes using a BatchAttrsStep
|
|
249
|
-
* @param nodesToUpdate Map of position -> localId for nodes that need updates
|
|
250
|
-
* @param tr
|
|
251
|
-
*/
|
|
252
|
-
export var batchAddLocalIdToNodes = function batchAddLocalIdToNodes(nodesToUpdate, tr) {
|
|
253
|
-
var batchData = Array.from(nodesToUpdate.entries()).map(function (_ref) {
|
|
254
|
-
var _ref2 = _slicedToArray(_ref, 2),
|
|
255
|
-
pos = _ref2[0],
|
|
256
|
-
localId = _ref2[1];
|
|
257
|
-
var node = tr.doc.nodeAt(pos);
|
|
258
|
-
if (!node) {
|
|
259
|
-
throw new Error("Node does not exist at position ".concat(pos));
|
|
260
|
-
}
|
|
261
|
-
return {
|
|
262
|
-
position: pos,
|
|
263
|
-
attrs: {
|
|
264
|
-
localId: localId
|
|
265
|
-
},
|
|
266
|
-
nodeType: node.type.name
|
|
267
|
-
};
|
|
268
|
-
});
|
|
269
|
-
tr.step(new BatchAttrsStep(batchData));
|
|
270
|
-
tr.setMeta('addToHistory', false);
|
|
271
252
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { EditorCommand } from '@atlaskit/editor-common/types';
|
|
2
|
+
import type { AddMissingLocalIdsOptions } from '../localIdPluginType';
|
|
3
|
+
/**
|
|
4
|
+
* Scans the current document and adds missing local IDs.
|
|
5
|
+
*/
|
|
6
|
+
export declare const addMissingLocalIds: (options?: AddMissingLocalIdsOptions) => EditorCommand;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
|
|
1
|
+
import type { EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
|
|
2
2
|
import type { CollabEditPlugin } from '@atlaskit/editor-plugin-collab-edit';
|
|
3
3
|
import type { CompositionPlugin } from '@atlaskit/editor-plugin-composition';
|
|
4
4
|
import type { LimitedModePlugin } from '@atlaskit/editor-plugin-limited-mode';
|
|
@@ -7,6 +7,11 @@ import type { NodeWithPos } from '@atlaskit/editor-prosemirror/utils';
|
|
|
7
7
|
export type ActionProps = {
|
|
8
8
|
localId: string;
|
|
9
9
|
};
|
|
10
|
+
export type AddMissingLocalIdsOptions = {
|
|
11
|
+
onRepaired?: (payload: {
|
|
12
|
+
repairedNodeCount: number;
|
|
13
|
+
}) => void;
|
|
14
|
+
};
|
|
10
15
|
export type LocalIdStatusCode = 'current' | 'localChangeByAttr' | 'localChangeBySetAttrs' | 'localChangeByBatchAttrs' | 'localChangeByReplace' | 'localChangeByDelete' | 'localChangeByReplaceAround' | 'localChangeByUnknown' | 'remoteChangeByAttr' | 'remoteChangeBySetAttrs' | 'remoteChangeByBatchAttrs' | 'remoteChangeByReplace' | 'remoteChangeByDelete' | 'remoteChangeByReplaceAround' | 'remoteChangeByUnknown' | 'AIChangeByAttr' | 'AIChangeBySetAttrs' | 'AIChangeByBatchAttrs' | 'AIChangeByReplace' | 'AIChangeByDelete' | 'AIChangeByReplaceAround' | 'AIChangeByUnknown' | 'docChangeByAttr' | 'docChangeBySetAttrs' | 'docChangeByBatchAttrs' | 'docChangeByReplace' | 'docChangeByDelete' | 'docChangeByReplaceAround' | 'docChangeByUnknown';
|
|
11
16
|
export interface LocalIdSharedState {
|
|
12
17
|
localIdStatus: Map<string, LocalIdStatusCode> | undefined;
|
|
@@ -32,6 +37,12 @@ export type LocalIdPlugin = NextEditorPlugin<'localId', {
|
|
|
32
37
|
value: Node;
|
|
33
38
|
}) => boolean;
|
|
34
39
|
};
|
|
40
|
+
commands: {
|
|
41
|
+
/**
|
|
42
|
+
* Scans the current document and adds local IDs to eligible nodes that are missing them.
|
|
43
|
+
*/
|
|
44
|
+
addMissingLocalIds: (options?: AddMissingLocalIdsOptions) => EditorCommand;
|
|
45
|
+
};
|
|
35
46
|
dependencies: [
|
|
36
47
|
CompositionPlugin,
|
|
37
48
|
OptionalPlugin<CollabEditPlugin>,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import type { AddMissingLocalIdsOptions } from '../localIdPluginType';
|
|
3
|
+
export declare const localIdNotEmpty: (localId: unknown) => boolean;
|
|
4
|
+
export declare const addMissingLocalIdsToDocument: (tr: Transaction, { onRepaired }?: AddMissingLocalIdsOptions) => boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Batch adds local IDs to nodes using a BatchAttrsStep
|
|
7
|
+
* @param nodesToUpdate Map of position -> localId for nodes that need updates
|
|
8
|
+
* @param tr
|
|
9
|
+
*/
|
|
10
|
+
export declare const batchAddLocalIdToNodes: (nodesToUpdate: Map<number, string>, tr: Transaction) => void;
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
2
|
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
3
|
-
import { PluginKey
|
|
3
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
4
|
import type { LocalIdPlugin } from '../localIdPluginType';
|
|
5
5
|
export declare const localIdPluginKey: PluginKey;
|
|
6
6
|
export declare const createPlugin: (api: ExtractInjectionAPI<LocalIdPlugin> | undefined) => SafePlugin;
|
|
7
|
-
/**
|
|
8
|
-
* Batch adds local IDs to nodes using a BatchAttrsStep
|
|
9
|
-
* @param nodesToUpdate Map of position -> localId for nodes that need updates
|
|
10
|
-
* @param tr
|
|
11
|
-
*/
|
|
12
|
-
export declare const batchAddLocalIdToNodes: (nodesToUpdate: Map<number, string>, tr: Transaction) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-local-id",
|
|
3
|
-
"version": "13.0
|
|
3
|
+
"version": "13.1.0",
|
|
4
4
|
"description": "LocalId plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -25,13 +25,14 @@
|
|
|
25
25
|
"@atlaskit/editor-plugin-composition": "^14.0.0",
|
|
26
26
|
"@atlaskit/editor-plugin-limited-mode": "^12.0.0",
|
|
27
27
|
"@atlaskit/editor-prosemirror": "^8.0.0",
|
|
28
|
+
"@atlaskit/platform-feature-experiments": "^0.3.0",
|
|
28
29
|
"@atlaskit/platform-feature-flags": "^2.1.0",
|
|
29
30
|
"@atlaskit/tmp-editor-statsig": "^149.0.0",
|
|
30
31
|
"@babel/runtime": "^7.0.0",
|
|
31
32
|
"raf-schd": "^4.0.3"
|
|
32
33
|
},
|
|
33
34
|
"peerDependencies": {
|
|
34
|
-
"@atlaskit/editor-common": "^119.
|
|
35
|
+
"@atlaskit/editor-common": "^119.8.0",
|
|
35
36
|
"react": "^18.2.0 || ^19.2.0"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|