@atlaskit/editor-plugin-synced-block 10.4.5 → 10.4.7

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/AGENTS.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **For workflow guidance, debugging, and cross-package task guides, load the `synced-blocks`
4
4
  > skill:**
5
- > `get_skill(skill_name_or_path="platform/packages/editor/.rovodev/skills/synced-blocks/SKILL.md")`
5
+ > `get_skill(skill_name_or_path="platform/packages/editor/.agents/skills/synced-blocks/SKILL.md")`
6
6
 
7
7
  ---
8
8
 
@@ -31,7 +31,8 @@ src/
31
31
  │ discardUnpublishedSyncBlocks (EDITOR-6473)
32
32
  ├── editor-commands/
33
33
  │ └── index.ts # createSyncedBlock, copySyncedBlockReferenceToClipboardEditorCommand,
34
- │ removeSyncedBlockAtPos, unsyncSyncBlock
34
+ │ copySyncedBlockReferenceToClipboard, editSyncedBlockSource,
35
+ │ removeSyncedBlock, removeSyncedBlockAtPos, unsync
35
36
  ├── nodeviews/
36
37
  │ ├── syncedBlock.tsx # NodeView for reference (syncBlock) — read-only, fetches from BE
37
38
  │ ├── lazySyncedBlock.tsx # Lazy-loaded wrapper for syncedBlock (EDITOR-6928)
@@ -50,13 +51,18 @@ src/
50
51
  │ ├── rebase-transaction.ts # Rebase helpers used by main.ts
51
52
  │ ├── ignore-dom-event.ts # DOM event guard
52
53
  │ └── utils.ts # Misc shared helpers
53
- ├── ui/
54
+ ├── ui/ # (grep the dir for the full current list — it grows often)
54
55
  │ ├── toolbar-components.tsx # Primary toolbar button ("Create Synced Block")
56
+ │ ├── CreateSyncedBlockButton.tsx / CreateSyncedBlockDropdownItem.tsx # Toolbar/menu entry points
55
57
  │ ├── floating-toolbar.tsx # Node-level actions: delete, unsync, copy link, view locations
56
58
  │ ├── block-menu-components.tsx # Block menu entry
57
59
  │ ├── quick-insert.tsx # Slash command / quick insert config
60
+ │ ├── SyncedLocationDropdown.tsx # "View synced locations" dropdown
58
61
  │ ├── DeleteConfirmationModal.tsx # Deletion confirmation dialog
59
62
  │ ├── SyncBlockRefresher.tsx # Periodic data refresh from backend
63
+ │ ├── SyncBlockLabel.tsx # Source/reference label chrome
64
+ │ ├── BodiedSyncBlockWrapper.tsx / SyncBlockRendererWrapper.tsx # Node-view wrappers
65
+ │ ├── SyncBlockSSRReactContextsProvider.tsx # Supplies React contexts during SSR
60
66
  │ └── Flag.tsx # Error/info flags (offline, copy notifications)
61
67
  └── types/
62
68
  └── index.ts # FLAG_ID, SyncedBlockSharedState, BodiedSyncBlockDeletionStatus
@@ -89,14 +95,18 @@ Behind the `editor_synced_block_perf` experiment, `main.ts`:
89
95
 
90
96
  1. User triggers via toolbar/block menu/slash command → `ui/toolbar-components.tsx` or
91
97
  `ui/block-menu-components.tsx`
92
- 2. Calls `editor-commands/createSyncedBlock` → inserts `bodiedSyncBlock` node into document
93
- 3. `pm-plugins/main.ts` detects new node → `handle-bodied-sync-block-creation.ts` → calls
94
- `SyncBlockStoreManager.create()` → Block Service API
95
- 4. `menu-and-toolbar-experiences.ts` fires experience event
98
+ 2. Calls `editor-commands/createSyncedBlock` → inserts `bodiedSyncBlock` node into document (marked
99
+ as **pending creation** — it is not persisted yet)
100
+ 3. `pm-plugins/main.ts` detects new node → `handle-bodied-sync-block-creation.ts` updates
101
+ `sourceManager` state. Persistence happens later when the product layer calls `flush()`
102
+ (via `flushBodiedSyncBlocks`), which creates the block in the Block Service and then reconciles
103
+ identifiers via `commitPendingCreation()`
104
+ 4. `menu-and-toolbar-experiences.ts` fires the experience event
96
105
 
97
106
  **Reference rendering** (flow through the code):
98
107
 
99
- 1. `nodeviews/syncedBlock.tsx` mounts for each `syncBlock` node
100
- 2. Calls `ReferenceSyncBlockStoreManager.fetch(resourceId)` → Block Service API
108
+ 1. `nodeviews/syncedBlock.tsx` (or `lazySyncedBlock.tsx`) mounts for each `syncBlock` node
109
+ 2. Calls `referenceManager.fetchSyncBlocksData(nodes)` → batched/deduped Block Service fetch
101
110
  3. Renders content via nested renderer from `editor-synced-block-renderer`
102
- 4. Subscribes to AGG WebSocket for real-time updates
111
+ 4. Subscribes via `referenceManager.subscribeToSyncBlock(...)` — AGG WebSocket (Confluence) or Relay
112
+ (Jira) — for real-time updates
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @atlaskit/editor-plugin-synced-block
2
2
 
3
+ ## 10.4.7
4
+
5
+ ### Patch Changes
6
+
7
+ - [`d9e8a63a60b63`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d9e8a63a60b63) -
8
+ Keep the placeholder visible in empty source synced blocks for the sync block activation treatment
9
+ while preserving the existing placeholder behavior in the control.
10
+
11
+ ## 10.4.6
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies
16
+
3
17
  ## 10.4.5
4
18
 
5
19
  ### Patch Changes
@@ -21,6 +21,7 @@ var _DeleteConfirmationModal = require("./ui/DeleteConfirmationModal");
21
21
  var _Flag = require("./ui/Flag");
22
22
  var _floatingToolbar = require("./ui/floating-toolbar");
23
23
  var _quickInsert = require("./ui/quick-insert");
24
+ var _SourceSyncBlockPlaceholder = require("./ui/SourceSyncBlockPlaceholder");
24
25
  var _SyncBlockRefresher = require("./ui/SyncBlockRefresher");
25
26
  var _toolbarComponents = require("./ui/toolbar-components");
26
27
  /**
@@ -157,10 +158,10 @@ var syncedBlockPlugin = exports.syncedBlockPlugin = function syncedBlockPlugin(_
157
158
  refs.containerElement = containerElement || undefined;
158
159
  refs.popupsMountPoint = popupsMountPoint || undefined;
159
160
  refs.wrapperElement = wrapperElement || undefined;
160
- return /*#__PURE__*/_react.default.createElement(LazySyncedBlockUI, {
161
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _expValEquals.expValEquals)('platform_editor_sync_block_activation', 'isEnabled', true) && /*#__PURE__*/_react.default.createElement(_SourceSyncBlockPlaceholder.SourceSyncBlockPlaceholder, null), /*#__PURE__*/_react.default.createElement(LazySyncedBlockUI, {
161
162
  syncBlockStore: syncBlockStore,
162
163
  api: api
163
- });
164
+ }));
164
165
  },
165
166
  getSharedState: function getSharedState(editorState) {
166
167
  if (!editorState) {
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.SourceSyncBlockPlaceholder = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _react = require("react");
10
+ var _react2 = require("@emotion/react");
11
+ var _reactIntl = require("react-intl");
12
+ var _messages = require("@atlaskit/editor-common/messages");
13
+ var _syncBlock = require("@atlaskit/editor-common/sync-block");
14
+ /**
15
+ * @jsxRuntime classic
16
+ * @jsx jsx
17
+ */
18
+
19
+ // Plugin content components need a global selector because the ProseMirror content is not a child
20
+ // of this component. This follows the existing layout placeholder pattern.
21
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-global-styles, @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports
22
+
23
+ var getSourceSyncBlockPlaceholderStyles = function getSourceSyncBlockPlaceholderStyles(placeholderText) {
24
+ return (0, _react2.css)((0, _defineProperty2.default)({}, ".ProseMirror .".concat(_syncBlock.BodiedSyncBlockSharedCssClassName.prefix, " .").concat(_syncBlock.BodiedSyncBlockSharedCssClassName.content, "[contenteditable=\"true\"] > p:only-child:has(.ProseMirror-trailingBreak:only-child)"), {
25
+ position: 'relative',
26
+ '&::before': {
27
+ // JSON.stringify produces a quoted and escaped CSS string.
28
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
29
+ content: placeholderText,
30
+ position: 'absolute',
31
+ boxSizing: 'border-box',
32
+ color: "var(--ds-text-subtlest, #6B6E76)",
33
+ font: 'inherit',
34
+ insetInlineStart: 0,
35
+ width: '100%',
36
+ pointerEvents: 'none',
37
+ userSelect: 'none'
38
+ }
39
+ }));
40
+ };
41
+ var SourceSyncBlockPlaceholder = exports.SourceSyncBlockPlaceholder = function SourceSyncBlockPlaceholder() {
42
+ var _useIntl = (0, _reactIntl.useIntl)(),
43
+ formatMessage = _useIntl.formatMessage;
44
+ var placeholderStyles = (0, _react.useMemo)(function () {
45
+ return getSourceSyncBlockPlaceholderStyles(JSON.stringify(formatMessage(_messages.placeholderTextMessages.sourceSyncBlockPlaceholderText)));
46
+ }, [formatMessage]);
47
+ return (0, _react2.jsx)(_react2.Global, {
48
+ styles: placeholderStyles
49
+ });
50
+ };
@@ -14,6 +14,7 @@ import { DeleteConfirmationModal } from './ui/DeleteConfirmationModal';
14
14
  import { Flag } from './ui/Flag';
15
15
  import { getToolbarConfig } from './ui/floating-toolbar';
16
16
  import { getQuickInsertConfig } from './ui/quick-insert';
17
+ import { SourceSyncBlockPlaceholder } from './ui/SourceSyncBlockPlaceholder';
17
18
  import { SyncBlockRefresher } from './ui/SyncBlockRefresher';
18
19
  import { getToolbarComponents } from './ui/toolbar-components';
19
20
 
@@ -147,10 +148,10 @@ export const syncedBlockPlugin = ({
147
148
  refs.containerElement = containerElement || undefined;
148
149
  refs.popupsMountPoint = popupsMountPoint || undefined;
149
150
  refs.wrapperElement = wrapperElement || undefined;
150
- return /*#__PURE__*/React.createElement(LazySyncedBlockUI, {
151
+ return /*#__PURE__*/React.createElement(React.Fragment, null, expValEquals('platform_editor_sync_block_activation', 'isEnabled', true) && /*#__PURE__*/React.createElement(SourceSyncBlockPlaceholder, null), /*#__PURE__*/React.createElement(LazySyncedBlockUI, {
151
152
  syncBlockStore: syncBlockStore,
152
153
  api: api
153
- });
154
+ }));
154
155
  },
155
156
  getSharedState: editorState => {
156
157
  if (!editorState) {
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @jsxRuntime classic
3
+ * @jsx jsx
4
+ */
5
+ import { useMemo } from 'react';
6
+
7
+ // Plugin content components need a global selector because the ProseMirror content is not a child
8
+ // of this component. This follows the existing layout placeholder pattern.
9
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-global-styles, @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports
10
+ import { css, Global, jsx } from '@emotion/react';
11
+ import { useIntl } from 'react-intl';
12
+ import { placeholderTextMessages } from '@atlaskit/editor-common/messages';
13
+ import { BodiedSyncBlockSharedCssClassName } from '@atlaskit/editor-common/sync-block';
14
+ const getSourceSyncBlockPlaceholderStyles = placeholderText => css({
15
+ // ProseMirror represents an empty paragraph with a trailing break. Keeping this visual state
16
+ // in CSS means typing, deletion, undo/redo, and remote changes update it without decorations.
17
+ // :has() ensures the placeholder only appears when that trailing break is the paragraph's
18
+ // only child, rather than when the paragraph contains editable content.
19
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors, @atlaskit/ui-styling-standard/no-unsafe-values
20
+ [`.ProseMirror .${BodiedSyncBlockSharedCssClassName.prefix} .${BodiedSyncBlockSharedCssClassName.content}[contenteditable="true"] > p:only-child:has(.ProseMirror-trailingBreak:only-child)`]: {
21
+ position: 'relative',
22
+ '&::before': {
23
+ // JSON.stringify produces a quoted and escaped CSS string.
24
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
25
+ content: placeholderText,
26
+ position: 'absolute',
27
+ boxSizing: 'border-box',
28
+ color: "var(--ds-text-subtlest, #6B6E76)",
29
+ font: 'inherit',
30
+ insetInlineStart: 0,
31
+ width: '100%',
32
+ pointerEvents: 'none',
33
+ userSelect: 'none'
34
+ }
35
+ }
36
+ });
37
+ export const SourceSyncBlockPlaceholder = () => {
38
+ const {
39
+ formatMessage
40
+ } = useIntl();
41
+ const placeholderStyles = useMemo(() => getSourceSyncBlockPlaceholderStyles(JSON.stringify(formatMessage(placeholderTextMessages.sourceSyncBlockPlaceholderText))), [formatMessage]);
42
+ return jsx(Global, {
43
+ styles: placeholderStyles
44
+ });
45
+ };
@@ -14,6 +14,7 @@ import { DeleteConfirmationModal } from './ui/DeleteConfirmationModal';
14
14
  import { Flag } from './ui/Flag';
15
15
  import { getToolbarConfig } from './ui/floating-toolbar';
16
16
  import { getQuickInsertConfig } from './ui/quick-insert';
17
+ import { SourceSyncBlockPlaceholder } from './ui/SourceSyncBlockPlaceholder';
17
18
  import { SyncBlockRefresher } from './ui/SyncBlockRefresher';
18
19
  import { getToolbarComponents } from './ui/toolbar-components';
19
20
 
@@ -151,10 +152,10 @@ export var syncedBlockPlugin = function syncedBlockPlugin(_ref2) {
151
152
  refs.containerElement = containerElement || undefined;
152
153
  refs.popupsMountPoint = popupsMountPoint || undefined;
153
154
  refs.wrapperElement = wrapperElement || undefined;
154
- return /*#__PURE__*/React.createElement(LazySyncedBlockUI, {
155
+ return /*#__PURE__*/React.createElement(React.Fragment, null, expValEquals('platform_editor_sync_block_activation', 'isEnabled', true) && /*#__PURE__*/React.createElement(SourceSyncBlockPlaceholder, null), /*#__PURE__*/React.createElement(LazySyncedBlockUI, {
155
156
  syncBlockStore: syncBlockStore,
156
157
  api: api
157
- });
158
+ }));
158
159
  },
159
160
  getSharedState: function getSharedState(editorState) {
160
161
  if (!editorState) {
@@ -0,0 +1,42 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ /**
3
+ * @jsxRuntime classic
4
+ * @jsx jsx
5
+ */
6
+ import { useMemo } from 'react';
7
+
8
+ // Plugin content components need a global selector because the ProseMirror content is not a child
9
+ // of this component. This follows the existing layout placeholder pattern.
10
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-global-styles, @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports
11
+ import { css, Global, jsx } from '@emotion/react';
12
+ import { useIntl } from 'react-intl';
13
+ import { placeholderTextMessages } from '@atlaskit/editor-common/messages';
14
+ import { BodiedSyncBlockSharedCssClassName } from '@atlaskit/editor-common/sync-block';
15
+ var getSourceSyncBlockPlaceholderStyles = function getSourceSyncBlockPlaceholderStyles(placeholderText) {
16
+ return css(_defineProperty({}, ".ProseMirror .".concat(BodiedSyncBlockSharedCssClassName.prefix, " .").concat(BodiedSyncBlockSharedCssClassName.content, "[contenteditable=\"true\"] > p:only-child:has(.ProseMirror-trailingBreak:only-child)"), {
17
+ position: 'relative',
18
+ '&::before': {
19
+ // JSON.stringify produces a quoted and escaped CSS string.
20
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
21
+ content: placeholderText,
22
+ position: 'absolute',
23
+ boxSizing: 'border-box',
24
+ color: "var(--ds-text-subtlest, #6B6E76)",
25
+ font: 'inherit',
26
+ insetInlineStart: 0,
27
+ width: '100%',
28
+ pointerEvents: 'none',
29
+ userSelect: 'none'
30
+ }
31
+ }));
32
+ };
33
+ export var SourceSyncBlockPlaceholder = function SourceSyncBlockPlaceholder() {
34
+ var _useIntl = useIntl(),
35
+ formatMessage = _useIntl.formatMessage;
36
+ var placeholderStyles = useMemo(function () {
37
+ return getSourceSyncBlockPlaceholderStyles(JSON.stringify(formatMessage(placeholderTextMessages.sourceSyncBlockPlaceholderText)));
38
+ }, [formatMessage]);
39
+ return jsx(Global, {
40
+ styles: placeholderStyles
41
+ });
42
+ };
@@ -83,16 +83,16 @@ export type SyncBlockMap = {
83
83
  [key: string]: SyncBlockInfo;
84
84
  };
85
85
  export declare const SYNCED_BLOCK_BUTTON_TEST_ID: {
86
- readonly primaryToolbarCreate: "create-synced-block-toolbar-btn";
87
- readonly blockMenuCreate: "create-synced-block-block-menu-btn";
88
- readonly quickInsertCreate: "create-synced-block-quick-insert-btn";
89
- readonly syncedBlockToolbarCopy: "synced-block-copy-btn";
90
- readonly syncedBlockToolbarReferenceDelete: "reference-synced-block-delete-btn";
91
- readonly syncedBlockToolbarSourceDelete: "source-synced-block-delete-btn";
92
- readonly syncedBlockToolbarReferenceUnsync: "reference-synced-block-unsync-btn";
93
- readonly syncedBlockToolbarSourceUnsync: "source-synced-block-unsync-btn";
94
- readonly syncedBlockToolbarSyncedLocationsTrigger: "synced-block-synced-locations-dropdown--trigger";
95
- readonly syncedBlockToolbarReferenceOverflowTrigger: "reference-synced-block-overflow-dropdown--trigger";
96
- readonly syncedBlockToolbarSourceOverflowTrigger: "source-synced-block-overflow-dropdown--trigger";
86
+ readonly primaryToolbarCreate: 'create-synced-block-toolbar-btn';
87
+ readonly blockMenuCreate: 'create-synced-block-block-menu-btn';
88
+ readonly quickInsertCreate: 'create-synced-block-quick-insert-btn';
89
+ readonly syncedBlockToolbarCopy: 'synced-block-copy-btn';
90
+ readonly syncedBlockToolbarReferenceDelete: 'reference-synced-block-delete-btn';
91
+ readonly syncedBlockToolbarSourceDelete: 'source-synced-block-delete-btn';
92
+ readonly syncedBlockToolbarReferenceUnsync: 'reference-synced-block-unsync-btn';
93
+ readonly syncedBlockToolbarSourceUnsync: 'source-synced-block-unsync-btn';
94
+ readonly syncedBlockToolbarSyncedLocationsTrigger: 'synced-block-synced-locations-dropdown--trigger';
95
+ readonly syncedBlockToolbarReferenceOverflowTrigger: 'reference-synced-block-overflow-dropdown--trigger';
96
+ readonly syncedBlockToolbarSourceOverflowTrigger: 'source-synced-block-overflow-dropdown--trigger';
97
97
  };
98
98
  export {};
@@ -0,0 +1 @@
1
+ export declare const SourceSyncBlockPlaceholder: () => JSX.Element;
@@ -11,7 +11,7 @@ interface Props {
11
11
  resourceId: string;
12
12
  syncBlockStore: SyncBlockStoreManager;
13
13
  }
14
- export declare const processReferenceData: (referenceData: ReferencesSourceInfo["references"], intl: IntlShape) => SyncBlockSourceInfo[];
14
+ export declare const processReferenceData: (referenceData: ReferencesSourceInfo['references'], intl: IntlShape) => SyncBlockSourceInfo[];
15
15
  export declare const SyncedLocationDropdown: ({ syncBlockStore, resourceId, intl, isSource, localId, api, floatingToolbarRenderContext, }: Props) => JSX.Element;
16
16
  export declare const SyncedLocationDropdownWithCount: ({ syncBlockStore, resourceId, intl, isSource, localId, api, floatingToolbarRenderContext, }: Props) => JSX.Element;
17
17
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-synced-block",
3
- "version": "10.4.5",
3
+ "version": "10.4.7",
4
4
  "description": "SyncedBlock plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -22,7 +22,7 @@
22
22
  "dependencies": {
23
23
  "@atlaskit/adf-schema": "^56.1.0",
24
24
  "@atlaskit/button": "24.3.7",
25
- "@atlaskit/dropdown-menu": "17.1.7",
25
+ "@atlaskit/dropdown-menu": "17.2.0",
26
26
  "@atlaskit/editor-json-transformer": "^9.1.0",
27
27
  "@atlaskit/editor-plugin-analytics": "^12.0.0",
28
28
  "@atlaskit/editor-plugin-block-menu": "^11.1.0",
@@ -42,22 +42,23 @@
42
42
  "@atlaskit/icon-lab": "^7.4.0",
43
43
  "@atlaskit/logo": "^21.4.0",
44
44
  "@atlaskit/lozenge": "^14.1.0",
45
- "@atlaskit/modal-dialog": "^16.1.0",
45
+ "@atlaskit/modal-dialog": "^16.2.0",
46
46
  "@atlaskit/platform-feature-flags": "^2.1.0",
47
47
  "@atlaskit/primitives": "^22.2.0",
48
48
  "@atlaskit/spinner": "20.1.1",
49
- "@atlaskit/tmp-editor-statsig": "^134.0.0",
49
+ "@atlaskit/tmp-editor-statsig": "^135.2.0",
50
50
  "@atlaskit/tokens": "16.3.0",
51
- "@atlaskit/tooltip": "^23.1.0",
51
+ "@atlaskit/tooltip": "^23.2.0",
52
52
  "@atlaskit/visually-hidden": "^4.2.0",
53
53
  "@babel/runtime": "^7.0.0",
54
54
  "@compiled/react": "^1.0.0",
55
+ "@emotion/react": "^11.7.1",
55
56
  "bind-event-listener": "^3.0.0",
56
57
  "date-fns": "^2.17.0",
57
58
  "memoize-one": "^6.0.0"
58
59
  },
59
60
  "peerDependencies": {
60
- "@atlaskit/editor-common": "^116.40.0",
61
+ "@atlaskit/editor-common": "^116.43.0",
61
62
  "react": "^18.2.0",
62
63
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
63
64
  },