@atlaskit/editor-plugin-local-id 1.0.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 +13 -0
- package/LICENSE.md +11 -0
- package/README.md +39 -0
- package/afm-cc/tsconfig.json +24 -0
- package/afm-dev-agents/tsconfig.json +24 -0
- package/afm-jira/tsconfig.json +24 -0
- package/afm-post-office/tsconfig.json +24 -0
- package/afm-rovo-extension/tsconfig.json +24 -0
- package/afm-townsquare/tsconfig.json +24 -0
- package/build/tsconfig.json +17 -0
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/localIdPlugin.js +18 -0
- package/dist/cjs/localIdPluginType.js +5 -0
- package/dist/cjs/pm-plugins/main.js +78 -0
- package/dist/es2019/index.js +4 -0
- package/dist/es2019/localIdPlugin.js +10 -0
- package/dist/es2019/localIdPluginType.js +1 -0
- package/dist/es2019/pm-plugins/main.js +70 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/localIdPlugin.js +12 -0
- package/dist/esm/localIdPluginType.js +1 -0
- package/dist/esm/pm-plugins/main.js +71 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/localIdPlugin.d.ts +2 -0
- package/dist/types/localIdPluginType.d.ts +2 -0
- package/dist/types/pm-plugins/main.d.ts +17 -0
- package/dist/types-ts4.5/index.d.ts +2 -0
- package/dist/types-ts4.5/localIdPlugin.d.ts +2 -0
- package/dist/types-ts4.5/localIdPluginType.d.ts +2 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +17 -0
- package/docs/0-intro.tsx +43 -0
- package/package.json +82 -0
- package/tsconfig.json +8 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @atlaskit/editor-plugin-local-id
|
|
2
|
+
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [#197573](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/197573)
|
|
8
|
+
[`65dfe86479bb2`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/65dfe86479bb2) -
|
|
9
|
+
EDITOR-1101 Setup new package scaffold
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Copyright 2019 Atlassian Pty Ltd
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
|
|
4
|
+
compliance with the License. You may obtain a copy of the License at
|
|
5
|
+
|
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
|
|
8
|
+
Unless required by applicable law or agreed to in writing, software distributed under the License is
|
|
9
|
+
distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
10
|
+
implied. See the License for the specific language governing permissions and limitations under the
|
|
11
|
+
License.
|
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Editor Plugin: `editor-plugin-local-id`
|
|
2
|
+
|
|
3
|
+
## 🧠 Overview
|
|
4
|
+
|
|
5
|
+
This plugin ensures that all non-ignored nodes in the document have unique `localId` attributes. It performs a **one-time scan** of the document when the editor is initialized to add missing local IDs to existing nodes.
|
|
6
|
+
|
|
7
|
+
The plugin is designed to run only once per editor instance to avoid performance issues and prevent duplicate ID generation. It's optimized by using idle time scheduling and avoiding unnecessary transactions.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## ⚙️ How It Works
|
|
12
|
+
|
|
13
|
+
### Core Mechanism
|
|
14
|
+
- **Trigger**: Uses the editor view's initialization lifecycle to schedule the scan
|
|
15
|
+
- **Execution**: Performs a single document traversal during browser idle time
|
|
16
|
+
- **Scheduling**: Uses `requestIdleCallback` with `requestAnimationFrame` fallback for Safari
|
|
17
|
+
|
|
18
|
+
### Node Processing
|
|
19
|
+
For each node in the document:
|
|
20
|
+
- **Ignored nodes**: Always skipped (no local IDs needed)
|
|
21
|
+
- **Nodes with existing localId**: Left unchanged
|
|
22
|
+
- **Nodes without localId**: New UUID generated and assigned
|
|
23
|
+
|
|
24
|
+
### Transaction Handling
|
|
25
|
+
- All node updates are batched into a single transaction (only when needed)
|
|
26
|
+
- Transaction is marked with `addToHistory: false` to prevent undo/redo issues
|
|
27
|
+
- No transactions are dispatched if no local IDs need to be added
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## ✅ Behavior
|
|
32
|
+
|
|
33
|
+
| Case | Action Taken | Transaction Impact |
|
|
34
|
+
|------|-------------|-------------------|
|
|
35
|
+
| Node has no `localId` and is not ignored | `localId` is added | Single transaction with all changes |
|
|
36
|
+
| Node already has a `localId` | Left unchanged | No transaction |
|
|
37
|
+
| Plugin has already run | No action taken | No transaction |
|
|
38
|
+
| Document has no applicable nodes | No action taken | No transaction |
|
|
39
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../../../tsconfig.entry-points.confluence.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "es5",
|
|
5
|
+
"composite": true,
|
|
6
|
+
"outDir": "../../../../../confluence/tsDist/@atlaskit__editor-plugin-local-id",
|
|
7
|
+
"rootDir": "../"
|
|
8
|
+
},
|
|
9
|
+
"include": [
|
|
10
|
+
"../src/**/*.ts",
|
|
11
|
+
"../src/**/*.tsx"
|
|
12
|
+
],
|
|
13
|
+
"exclude": [
|
|
14
|
+
"../src/**/__tests__/*",
|
|
15
|
+
"../src/**/*.test.*",
|
|
16
|
+
"../src/**/test.*",
|
|
17
|
+
"../src/**/examples.*"
|
|
18
|
+
],
|
|
19
|
+
"references": [
|
|
20
|
+
{
|
|
21
|
+
"path": "../../editor-common/afm-cc/tsconfig.json"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../../../tsconfig.entry-points.dev-agents.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "es5",
|
|
5
|
+
"outDir": "../../../../../dev-agents/tsDist/@atlaskit__editor-plugin-local-id/app",
|
|
6
|
+
"rootDir": "../",
|
|
7
|
+
"composite": true
|
|
8
|
+
},
|
|
9
|
+
"include": [
|
|
10
|
+
"../src/**/*.ts",
|
|
11
|
+
"../src/**/*.tsx"
|
|
12
|
+
],
|
|
13
|
+
"exclude": [
|
|
14
|
+
"../src/**/__tests__/*",
|
|
15
|
+
"../src/**/*.test.*",
|
|
16
|
+
"../src/**/test.*",
|
|
17
|
+
"../src/**/examples.*"
|
|
18
|
+
],
|
|
19
|
+
"references": [
|
|
20
|
+
{
|
|
21
|
+
"path": "../../editor-common/afm-dev-agents/tsconfig.json"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../../../tsconfig.entry-points.jira.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "es5",
|
|
5
|
+
"outDir": "../../../../../tsDist/@atlaskit__editor-plugin-local-id/app",
|
|
6
|
+
"rootDir": "../",
|
|
7
|
+
"composite": true
|
|
8
|
+
},
|
|
9
|
+
"include": [
|
|
10
|
+
"../src/**/*.ts",
|
|
11
|
+
"../src/**/*.tsx"
|
|
12
|
+
],
|
|
13
|
+
"exclude": [
|
|
14
|
+
"../src/**/__tests__/*",
|
|
15
|
+
"../src/**/*.test.*",
|
|
16
|
+
"../src/**/test.*",
|
|
17
|
+
"../src/**/examples.*"
|
|
18
|
+
],
|
|
19
|
+
"references": [
|
|
20
|
+
{
|
|
21
|
+
"path": "../../editor-common/afm-jira/tsconfig.json"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../../../tsconfig.entry-points.post-office.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "es5",
|
|
5
|
+
"outDir": "../../../../../post-office/tsDist/@atlaskit__editor-plugin-local-id/app",
|
|
6
|
+
"rootDir": "../",
|
|
7
|
+
"composite": true
|
|
8
|
+
},
|
|
9
|
+
"include": [
|
|
10
|
+
"../src/**/*.ts",
|
|
11
|
+
"../src/**/*.tsx"
|
|
12
|
+
],
|
|
13
|
+
"exclude": [
|
|
14
|
+
"../src/**/__tests__/*",
|
|
15
|
+
"../src/**/*.test.*",
|
|
16
|
+
"../src/**/test.*",
|
|
17
|
+
"../src/**/examples.*"
|
|
18
|
+
],
|
|
19
|
+
"references": [
|
|
20
|
+
{
|
|
21
|
+
"path": "../../editor-common/afm-post-office/tsconfig.json"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../../../tsconfig.entry-points.rovo-extension.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "es5",
|
|
5
|
+
"outDir": "../../../../../rovo-extension/tsDist/@atlaskit__editor-plugin-local-id/app",
|
|
6
|
+
"rootDir": "../",
|
|
7
|
+
"composite": true
|
|
8
|
+
},
|
|
9
|
+
"include": [
|
|
10
|
+
"../src/**/*.ts",
|
|
11
|
+
"../src/**/*.tsx"
|
|
12
|
+
],
|
|
13
|
+
"exclude": [
|
|
14
|
+
"../src/**/__tests__/*",
|
|
15
|
+
"../src/**/*.test.*",
|
|
16
|
+
"../src/**/test.*",
|
|
17
|
+
"../src/**/examples.*"
|
|
18
|
+
],
|
|
19
|
+
"references": [
|
|
20
|
+
{
|
|
21
|
+
"path": "../../editor-common/afm-rovo-extension/tsconfig.json"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../../../tsconfig.entry-points.townsquare.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "es5",
|
|
5
|
+
"outDir": "../../../../../townsquare/tsDist/@atlaskit__editor-plugin-local-id/app",
|
|
6
|
+
"rootDir": "../",
|
|
7
|
+
"composite": true
|
|
8
|
+
},
|
|
9
|
+
"include": [
|
|
10
|
+
"../src/**/*.ts",
|
|
11
|
+
"../src/**/*.tsx"
|
|
12
|
+
],
|
|
13
|
+
"exclude": [
|
|
14
|
+
"../src/**/__tests__/*",
|
|
15
|
+
"../src/**/*.test.*",
|
|
16
|
+
"../src/**/test.*",
|
|
17
|
+
"../src/**/examples.*"
|
|
18
|
+
],
|
|
19
|
+
"references": [
|
|
20
|
+
{
|
|
21
|
+
"path": "../../editor-common/afm-townsquare/tsconfig.json"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "es5",
|
|
5
|
+
"paths": {}
|
|
6
|
+
},
|
|
7
|
+
"include": [
|
|
8
|
+
"../src/**/*.ts",
|
|
9
|
+
"../src/**/*.tsx"
|
|
10
|
+
],
|
|
11
|
+
"exclude": [
|
|
12
|
+
"../src/**/__tests__/*",
|
|
13
|
+
"../src/**/*.test.*",
|
|
14
|
+
"../src/**/test.*",
|
|
15
|
+
"../src/**/examples.*"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "localIdPlugin", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function get() {
|
|
9
|
+
return _localIdPlugin.localIdPlugin;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
var _localIdPlugin = require("./localIdPlugin");
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.localIdPlugin = void 0;
|
|
7
|
+
var _main = require("./pm-plugins/main");
|
|
8
|
+
var localIdPlugin = exports.localIdPlugin = function localIdPlugin() {
|
|
9
|
+
return {
|
|
10
|
+
name: 'localId',
|
|
11
|
+
pmPlugins: function pmPlugins() {
|
|
12
|
+
return [{
|
|
13
|
+
name: 'localIdPlugin',
|
|
14
|
+
plugin: _main.createPlugin
|
|
15
|
+
}];
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.localIdPluginKey = exports.createPlugin = exports.addLocalIdToNode = void 0;
|
|
8
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
+
var _adfSchema = require("@atlaskit/adf-schema");
|
|
10
|
+
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
11
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
12
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
13
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
14
|
+
var localIdPluginKey = exports.localIdPluginKey = new _state.PluginKey('localIdPlugin');
|
|
15
|
+
|
|
16
|
+
// Fallback for Safari which doesn't support requestIdleCallback
|
|
17
|
+
var requestIdleCallbackWithFallback = function requestIdleCallbackWithFallback(callback) {
|
|
18
|
+
if (typeof requestIdleCallback !== 'undefined') {
|
|
19
|
+
requestIdleCallback(callback);
|
|
20
|
+
} else {
|
|
21
|
+
// Fallback to requestAnimationFrame for Safari
|
|
22
|
+
requestAnimationFrame(callback);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var createPlugin = exports.createPlugin = function createPlugin() {
|
|
26
|
+
return new _safePlugin.SafePlugin({
|
|
27
|
+
key: localIdPluginKey,
|
|
28
|
+
view: function view(editorView) {
|
|
29
|
+
/**
|
|
30
|
+
* This performs a one-time scan of the document to add local IDs
|
|
31
|
+
* to nodes that don't have them. It's designed to run only once per
|
|
32
|
+
* editor instance to avoid performance issues.
|
|
33
|
+
*/
|
|
34
|
+
requestIdleCallbackWithFallback(function () {
|
|
35
|
+
var tr = editorView.state.tr;
|
|
36
|
+
var localIdWasAdded = false;
|
|
37
|
+
var _editorView$state$sch = editorView.state.schema.nodes,
|
|
38
|
+
text = _editorView$state$sch.text,
|
|
39
|
+
hardBreak = _editorView$state$sch.hardBreak;
|
|
40
|
+
var ignoredNodeTypes = [text.name, hardBreak.name];
|
|
41
|
+
editorView.state.doc.descendants(function (node, pos) {
|
|
42
|
+
// Skip text nodes, hard breaks and nodes that already have local IDs
|
|
43
|
+
if (!ignoredNodeTypes.includes(node.type.name) && !node.attrs.localId) {
|
|
44
|
+
localIdWasAdded = true;
|
|
45
|
+
addLocalIdToNode(node, pos, tr);
|
|
46
|
+
}
|
|
47
|
+
return true; // Continue traversing
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Only dispatch the transaction if we actually added local IDs
|
|
51
|
+
if (localIdWasAdded) {
|
|
52
|
+
tr.setMeta('addToHistory', false);
|
|
53
|
+
editorView.dispatch(tr);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
update: function update() {}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Adds a local ID to a ProseMirror node
|
|
65
|
+
*
|
|
66
|
+
* This utility function updates a node's attributes to include a unique local ID.
|
|
67
|
+
* It preserves all existing attributes and marks while adding the new localId.
|
|
68
|
+
*
|
|
69
|
+
* @param node - The ProseMirror node to add a local ID to
|
|
70
|
+
* @param pos - The position of the node in the document
|
|
71
|
+
* @param tr - The transaction to apply the change to
|
|
72
|
+
* @returns The updated transaction with the node markup change
|
|
73
|
+
*/
|
|
74
|
+
var addLocalIdToNode = exports.addLocalIdToNode = function addLocalIdToNode(node, pos, tr) {
|
|
75
|
+
tr = tr.setNodeMarkup(pos, node.type, _objectSpread(_objectSpread({}, node.attrs), {}, {
|
|
76
|
+
localId: _adfSchema.uuid.generate()
|
|
77
|
+
}), node.marks);
|
|
78
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { uuid } from '@atlaskit/adf-schema';
|
|
2
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
export const localIdPluginKey = new PluginKey('localIdPlugin');
|
|
5
|
+
|
|
6
|
+
// Fallback for Safari which doesn't support requestIdleCallback
|
|
7
|
+
const requestIdleCallbackWithFallback = callback => {
|
|
8
|
+
if (typeof requestIdleCallback !== 'undefined') {
|
|
9
|
+
requestIdleCallback(callback);
|
|
10
|
+
} else {
|
|
11
|
+
// Fallback to requestAnimationFrame for Safari
|
|
12
|
+
requestAnimationFrame(callback);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
export const createPlugin = () => {
|
|
16
|
+
return new SafePlugin({
|
|
17
|
+
key: localIdPluginKey,
|
|
18
|
+
view: editorView => {
|
|
19
|
+
/**
|
|
20
|
+
* This performs a one-time scan of the document to add local IDs
|
|
21
|
+
* to nodes that don't have them. It's designed to run only once per
|
|
22
|
+
* editor instance to avoid performance issues.
|
|
23
|
+
*/
|
|
24
|
+
requestIdleCallbackWithFallback(() => {
|
|
25
|
+
const tr = editorView.state.tr;
|
|
26
|
+
let localIdWasAdded = false;
|
|
27
|
+
const {
|
|
28
|
+
text,
|
|
29
|
+
hardBreak
|
|
30
|
+
} = editorView.state.schema.nodes;
|
|
31
|
+
const ignoredNodeTypes = [text.name, hardBreak.name];
|
|
32
|
+
editorView.state.doc.descendants((node, pos) => {
|
|
33
|
+
// Skip text nodes, hard breaks and nodes that already have local IDs
|
|
34
|
+
if (!ignoredNodeTypes.includes(node.type.name) && !node.attrs.localId) {
|
|
35
|
+
localIdWasAdded = true;
|
|
36
|
+
addLocalIdToNode(node, pos, tr);
|
|
37
|
+
}
|
|
38
|
+
return true; // Continue traversing
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Only dispatch the transaction if we actually added local IDs
|
|
42
|
+
if (localIdWasAdded) {
|
|
43
|
+
tr.setMeta('addToHistory', false);
|
|
44
|
+
editorView.dispatch(tr);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
update: () => {}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Adds a local ID to a ProseMirror node
|
|
56
|
+
*
|
|
57
|
+
* This utility function updates a node's attributes to include a unique local ID.
|
|
58
|
+
* It preserves all existing attributes and marks while adding the new localId.
|
|
59
|
+
*
|
|
60
|
+
* @param node - The ProseMirror node to add a local ID to
|
|
61
|
+
* @param pos - The position of the node in the document
|
|
62
|
+
* @param tr - The transaction to apply the change to
|
|
63
|
+
* @returns The updated transaction with the node markup change
|
|
64
|
+
*/
|
|
65
|
+
export const addLocalIdToNode = (node, pos, tr) => {
|
|
66
|
+
tr = tr.setNodeMarkup(pos, node.type, {
|
|
67
|
+
...node.attrs,
|
|
68
|
+
localId: uuid.generate()
|
|
69
|
+
}, node.marks);
|
|
70
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
import { uuid } from '@atlaskit/adf-schema';
|
|
5
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
6
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
7
|
+
export var localIdPluginKey = new PluginKey('localIdPlugin');
|
|
8
|
+
|
|
9
|
+
// Fallback for Safari which doesn't support requestIdleCallback
|
|
10
|
+
var requestIdleCallbackWithFallback = function requestIdleCallbackWithFallback(callback) {
|
|
11
|
+
if (typeof requestIdleCallback !== 'undefined') {
|
|
12
|
+
requestIdleCallback(callback);
|
|
13
|
+
} else {
|
|
14
|
+
// Fallback to requestAnimationFrame for Safari
|
|
15
|
+
requestAnimationFrame(callback);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
export var createPlugin = function createPlugin() {
|
|
19
|
+
return new SafePlugin({
|
|
20
|
+
key: localIdPluginKey,
|
|
21
|
+
view: function view(editorView) {
|
|
22
|
+
/**
|
|
23
|
+
* This performs a one-time scan of the document to add local IDs
|
|
24
|
+
* to nodes that don't have them. It's designed to run only once per
|
|
25
|
+
* editor instance to avoid performance issues.
|
|
26
|
+
*/
|
|
27
|
+
requestIdleCallbackWithFallback(function () {
|
|
28
|
+
var tr = editorView.state.tr;
|
|
29
|
+
var localIdWasAdded = false;
|
|
30
|
+
var _editorView$state$sch = editorView.state.schema.nodes,
|
|
31
|
+
text = _editorView$state$sch.text,
|
|
32
|
+
hardBreak = _editorView$state$sch.hardBreak;
|
|
33
|
+
var ignoredNodeTypes = [text.name, hardBreak.name];
|
|
34
|
+
editorView.state.doc.descendants(function (node, pos) {
|
|
35
|
+
// Skip text nodes, hard breaks and nodes that already have local IDs
|
|
36
|
+
if (!ignoredNodeTypes.includes(node.type.name) && !node.attrs.localId) {
|
|
37
|
+
localIdWasAdded = true;
|
|
38
|
+
addLocalIdToNode(node, pos, tr);
|
|
39
|
+
}
|
|
40
|
+
return true; // Continue traversing
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Only dispatch the transaction if we actually added local IDs
|
|
44
|
+
if (localIdWasAdded) {
|
|
45
|
+
tr.setMeta('addToHistory', false);
|
|
46
|
+
editorView.dispatch(tr);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
update: function update() {}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Adds a local ID to a ProseMirror node
|
|
58
|
+
*
|
|
59
|
+
* This utility function updates a node's attributes to include a unique local ID.
|
|
60
|
+
* It preserves all existing attributes and marks while adding the new localId.
|
|
61
|
+
*
|
|
62
|
+
* @param node - The ProseMirror node to add a local ID to
|
|
63
|
+
* @param pos - The position of the node in the document
|
|
64
|
+
* @param tr - The transaction to apply the change to
|
|
65
|
+
* @returns The updated transaction with the node markup change
|
|
66
|
+
*/
|
|
67
|
+
export var addLocalIdToNode = function addLocalIdToNode(node, pos, tr) {
|
|
68
|
+
tr = tr.setNodeMarkup(pos, node.type, _objectSpread(_objectSpread({}, node.attrs), {}, {
|
|
69
|
+
localId: uuid.generate()
|
|
70
|
+
}), node.marks);
|
|
71
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
+
import { PluginKey, type Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
export declare const localIdPluginKey: PluginKey<any>;
|
|
5
|
+
export declare const createPlugin: () => SafePlugin<any>;
|
|
6
|
+
/**
|
|
7
|
+
* Adds a local ID to a ProseMirror node
|
|
8
|
+
*
|
|
9
|
+
* This utility function updates a node's attributes to include a unique local ID.
|
|
10
|
+
* It preserves all existing attributes and marks while adding the new localId.
|
|
11
|
+
*
|
|
12
|
+
* @param node - The ProseMirror node to add a local ID to
|
|
13
|
+
* @param pos - The position of the node in the document
|
|
14
|
+
* @param tr - The transaction to apply the change to
|
|
15
|
+
* @returns The updated transaction with the node markup change
|
|
16
|
+
*/
|
|
17
|
+
export declare const addLocalIdToNode: (node: PMNode, pos: number, tr: Transaction) => void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
+
import { PluginKey, type Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
export declare const localIdPluginKey: PluginKey<any>;
|
|
5
|
+
export declare const createPlugin: () => SafePlugin<any>;
|
|
6
|
+
/**
|
|
7
|
+
* Adds a local ID to a ProseMirror node
|
|
8
|
+
*
|
|
9
|
+
* This utility function updates a node's attributes to include a unique local ID.
|
|
10
|
+
* It preserves all existing attributes and marks while adding the new localId.
|
|
11
|
+
*
|
|
12
|
+
* @param node - The ProseMirror node to add a local ID to
|
|
13
|
+
* @param pos - The position of the node in the document
|
|
14
|
+
* @param tr - The transaction to apply the change to
|
|
15
|
+
* @returns The updated transaction with the node markup change
|
|
16
|
+
*/
|
|
17
|
+
export declare const addLocalIdToNode: (node: PMNode, pos: number, tr: Transaction) => void;
|
package/docs/0-intro.tsx
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { AtlassianInternalWarning, code, md } from '@atlaskit/docs';
|
|
4
|
+
// eslint-disable-next-line @atlassian/tangerine/import/entry-points
|
|
5
|
+
import { createEditorUseOnlyNotice } from '@atlaskit/editor-common/doc-utils';
|
|
6
|
+
import { token } from '@atlaskit/tokens';
|
|
7
|
+
|
|
8
|
+
export default md`
|
|
9
|
+
|
|
10
|
+
${createEditorUseOnlyNotice('Editor Plugin Local Id', [
|
|
11
|
+
{ name: 'Editor Core', link: '/packages/editor/editor-core' },
|
|
12
|
+
])}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
${
|
|
16
|
+
(
|
|
17
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
|
|
18
|
+
<div style={{ marginTop: token('space.100', '8px') }}>
|
|
19
|
+
<AtlassianInternalWarning />
|
|
20
|
+
</div>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
This package includes the local id plugin used by \`@atlaskit/editor-core\`.
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
The \`dependencies\`, \`configuration\`, \`state\`, \`actions\`, and \`commands\` of the plugin are defined
|
|
30
|
+
below:
|
|
31
|
+
|
|
32
|
+
${code`
|
|
33
|
+
type LocalIdPlugin = NextEditorPlugin<'localId'>
|
|
34
|
+
`}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## Support
|
|
38
|
+
---
|
|
39
|
+
For internal Atlassian, visit the slack channel [#help-editor](https://atlassian.slack.com/archives/CFG3PSQ9E) for support or visit [go/editor-help](https://go/editor-help) to submit a bug.
|
|
40
|
+
## License
|
|
41
|
+
---
|
|
42
|
+
Please see [Atlassian Frontend - License](https://hello.atlassian.net/wiki/spaces/AF/pages/2589099144/Documentation#License) for more licensing information.
|
|
43
|
+
`;
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/editor-plugin-local-id",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "LocalId plugin for @atlaskit/editor-core",
|
|
5
|
+
"author": "Atlassian Pty Ltd",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"registry": "https://registry.npmjs.org/"
|
|
9
|
+
},
|
|
10
|
+
"atlassian": {
|
|
11
|
+
"team": "Editor: Lego",
|
|
12
|
+
"releaseModel": "continuous",
|
|
13
|
+
"singleton": true
|
|
14
|
+
},
|
|
15
|
+
"repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
|
|
16
|
+
"main": "dist/cjs/index.js",
|
|
17
|
+
"module": "dist/esm/index.js",
|
|
18
|
+
"module:es2019": "dist/es2019/index.js",
|
|
19
|
+
"types": "dist/types/index.d.ts",
|
|
20
|
+
"typesVersions": {
|
|
21
|
+
">=4.5 <4.9": {
|
|
22
|
+
"*": [
|
|
23
|
+
"dist/types-ts4.5/*",
|
|
24
|
+
"dist/types-ts4.5/index.d.ts"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"atlaskit:src": "src/index.ts",
|
|
30
|
+
"af:exports": {
|
|
31
|
+
".": "./src/index.ts"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@atlaskit/adf-schema": "^50.2.0",
|
|
35
|
+
"@atlaskit/editor-prosemirror": "7.0.0",
|
|
36
|
+
"@babel/runtime": "^7.0.0",
|
|
37
|
+
"raf-schd": "^4.0.3"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@atlaskit/editor-common": "^107.18.0",
|
|
41
|
+
"react": "^18.2.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"typescript": "~5.4.2"
|
|
45
|
+
},
|
|
46
|
+
"techstack": {
|
|
47
|
+
"@atlassian/frontend": {
|
|
48
|
+
"code-structure": [
|
|
49
|
+
"editor-plugin"
|
|
50
|
+
],
|
|
51
|
+
"import-structure": [
|
|
52
|
+
"atlassian-conventions"
|
|
53
|
+
],
|
|
54
|
+
"circular-dependencies": [
|
|
55
|
+
"file-and-folder-level"
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
"@repo/internal": {
|
|
59
|
+
"dom-events": "use-bind-event-listener",
|
|
60
|
+
"analytics": [
|
|
61
|
+
"analytics-next"
|
|
62
|
+
],
|
|
63
|
+
"design-tokens": [
|
|
64
|
+
"color"
|
|
65
|
+
],
|
|
66
|
+
"theming": [
|
|
67
|
+
"react-context"
|
|
68
|
+
],
|
|
69
|
+
"ui-components": [
|
|
70
|
+
"lite-mode"
|
|
71
|
+
],
|
|
72
|
+
"deprecation": "no-deprecated-imports",
|
|
73
|
+
"styling": [
|
|
74
|
+
"emotion",
|
|
75
|
+
"emotion"
|
|
76
|
+
],
|
|
77
|
+
"imports": [
|
|
78
|
+
"import-no-extraneous-disable-for-examples-and-docs"
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|