@atlaskit/editor-plugin-block-menu 5.0.24 → 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 +15 -0
- package/dist/cjs/editor-commands/transform-node-utils/utils.js +4 -2
- package/dist/cjs/editor-commands/transformNode.js +41 -20
- package/dist/es2019/editor-commands/transform-node-utils/utils.js +4 -2
- package/dist/es2019/editor-commands/transformNode.js +35 -15
- package/dist/esm/editor-commands/transform-node-utils/utils.js +4 -2
- package/dist/esm/editor-commands/transformNode.js +41 -20
- package/dist/types/blockMenuPluginType.d.ts +2 -2
- package/dist/types/editor-commands/transformNode.d.ts +3 -3
- package/dist/types/editor-commands/transforms/types.d.ts +4 -0
- package/dist/types-ts4.5/blockMenuPluginType.d.ts +2 -2
- package/dist/types-ts4.5/editor-commands/transformNode.d.ts +3 -3
- package/dist/types-ts4.5/editor-commands/transforms/types.d.ts +4 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-block-menu
|
|
2
2
|
|
|
3
|
+
## 5.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`55bf82f6468ac`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/55bf82f6468ac) -
|
|
8
|
+
Update transformNode command to work with preservedSelection
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
|
|
11
|
+
## 5.1.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- [`bd911d5eca1cb`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/bd911d5eca1cb) -
|
|
16
|
+
Use new transfromNode command in existing block menu items. Update transformNode analytics type.
|
|
17
|
+
|
|
3
18
|
## 5.0.24
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
@@ -16,10 +16,12 @@ var getSelectedNode = exports.getSelectedNode = function getSelectedNode(selecti
|
|
|
16
16
|
// ?
|
|
17
17
|
depth: selection.$from.depth
|
|
18
18
|
};
|
|
19
|
-
}
|
|
19
|
+
}
|
|
20
|
+
if (selection instanceof _editorTables.CellSelection) {
|
|
20
21
|
var tableSelected = (0, _utils.findParentNodeOfType)(selection.$from.doc.type.schema.nodes.table)(selection);
|
|
21
22
|
return tableSelected;
|
|
22
|
-
}
|
|
23
|
+
}
|
|
24
|
+
if (selection instanceof _state.TextSelection) {
|
|
23
25
|
var _selection$$from$doc$ = selection.$from.doc.type.schema.nodes,
|
|
24
26
|
blockquote = _selection$$from$doc$.blockquote,
|
|
25
27
|
bulletList = _selection$$from$doc$.bulletList,
|
|
@@ -4,27 +4,48 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.transformNode = void 0;
|
|
7
|
-
var
|
|
7
|
+
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
8
8
|
var _transform = require("./transform-node-utils/transform");
|
|
9
9
|
var transformNode = exports.transformNode = function transformNode(api) {
|
|
10
|
-
return
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
return (
|
|
11
|
+
// eslint-disable-next-line no-unused-vars
|
|
12
|
+
function (targetType, analyticsAttrs) {
|
|
13
|
+
return function (_ref) {
|
|
14
|
+
var _api$blockControls;
|
|
15
|
+
var tr = _ref.tr;
|
|
16
|
+
var preservedSelection = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.sharedState.currentState()) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.preservedSelection;
|
|
17
|
+
if (!preservedSelection) {
|
|
18
|
+
return tr;
|
|
19
|
+
}
|
|
20
|
+
var from = preservedSelection.from,
|
|
21
|
+
to = preservedSelection.to,
|
|
22
|
+
$from = preservedSelection.$from;
|
|
23
|
+
var selectedParent = $from.parent;
|
|
24
|
+
var fragment = _model.Fragment.empty;
|
|
25
|
+
// top level selections can safely be transformed without checking for depth
|
|
26
|
+
var isWithinSelectedRange = $from.depth === 0;
|
|
27
|
+
tr.doc.nodesBetween(from, to, function (node) {
|
|
28
|
+
// need to only transform selected content, for nested selections nodesBetween includes the path to the selected parent
|
|
29
|
+
if (!isWithinSelectedRange && node.eq(selectedParent)) {
|
|
30
|
+
isWithinSelectedRange = true;
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
if (isWithinSelectedRange) {
|
|
34
|
+
var outputNode = (0, _transform.getOutputNodes)({
|
|
35
|
+
sourceNode: node,
|
|
36
|
+
targetNodeType: targetType,
|
|
37
|
+
schema: tr.doc.type.schema
|
|
38
|
+
});
|
|
39
|
+
if (outputNode) {
|
|
40
|
+
fragment = fragment.append(_model.Fragment.fromArray(outputNode));
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
});
|
|
46
|
+
tr.replaceWith(preservedSelection.from, preservedSelection.to, fragment);
|
|
16
47
|
return tr;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
targetNodeType: targetType,
|
|
21
|
-
schema: selection.$from.doc.type.schema
|
|
22
|
-
});
|
|
23
|
-
if (!outputNodes) {
|
|
24
|
-
return tr;
|
|
25
|
-
}
|
|
26
|
-
tr.replaceWith(source.pos, source.pos + source.node.nodeSize, outputNodes);
|
|
27
|
-
return tr;
|
|
28
|
-
};
|
|
29
|
-
};
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
);
|
|
30
51
|
};
|
|
@@ -10,10 +10,12 @@ export const getSelectedNode = selection => {
|
|
|
10
10
|
// ?
|
|
11
11
|
depth: selection.$from.depth
|
|
12
12
|
};
|
|
13
|
-
}
|
|
13
|
+
}
|
|
14
|
+
if (selection instanceof CellSelection) {
|
|
14
15
|
const tableSelected = findParentNodeOfType(selection.$from.doc.type.schema.nodes.table)(selection);
|
|
15
16
|
return tableSelected;
|
|
16
|
-
}
|
|
17
|
+
}
|
|
18
|
+
if (selection instanceof TextSelection) {
|
|
17
19
|
const {
|
|
18
20
|
blockquote,
|
|
19
21
|
bulletList,
|
|
@@ -1,25 +1,45 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
2
|
import { getOutputNodes } from './transform-node-utils/transform';
|
|
3
|
-
export const transformNode = api =>
|
|
3
|
+
export const transformNode = api =>
|
|
4
|
+
// eslint-disable-next-line no-unused-vars
|
|
5
|
+
(targetType, analyticsAttrs) => {
|
|
4
6
|
return ({
|
|
5
7
|
tr
|
|
6
8
|
}) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const source = getSelectedNode(selection);
|
|
11
|
-
if (!source) {
|
|
9
|
+
var _api$blockControls, _api$blockControls$sh;
|
|
10
|
+
const preservedSelection = api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : (_api$blockControls$sh = _api$blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.preservedSelection;
|
|
11
|
+
if (!preservedSelection) {
|
|
12
12
|
return tr;
|
|
13
13
|
}
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
const {
|
|
15
|
+
from,
|
|
16
|
+
to,
|
|
17
|
+
$from
|
|
18
|
+
} = preservedSelection;
|
|
19
|
+
const selectedParent = $from.parent;
|
|
20
|
+
let fragment = Fragment.empty;
|
|
21
|
+
// top level selections can safely be transformed without checking for depth
|
|
22
|
+
let isWithinSelectedRange = $from.depth === 0;
|
|
23
|
+
tr.doc.nodesBetween(from, to, node => {
|
|
24
|
+
// need to only transform selected content, for nested selections nodesBetween includes the path to the selected parent
|
|
25
|
+
if (!isWithinSelectedRange && node.eq(selectedParent)) {
|
|
26
|
+
isWithinSelectedRange = true;
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
if (isWithinSelectedRange) {
|
|
30
|
+
const outputNode = getOutputNodes({
|
|
31
|
+
sourceNode: node,
|
|
32
|
+
targetNodeType: targetType,
|
|
33
|
+
schema: tr.doc.type.schema
|
|
34
|
+
});
|
|
35
|
+
if (outputNode) {
|
|
36
|
+
fragment = fragment.append(Fragment.fromArray(outputNode));
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
18
41
|
});
|
|
19
|
-
|
|
20
|
-
return tr;
|
|
21
|
-
}
|
|
22
|
-
tr.replaceWith(source.pos, source.pos + source.node.nodeSize, outputNodes);
|
|
42
|
+
tr.replaceWith(preservedSelection.from, preservedSelection.to, fragment);
|
|
23
43
|
return tr;
|
|
24
44
|
};
|
|
25
45
|
};
|
|
@@ -10,10 +10,12 @@ export var getSelectedNode = function getSelectedNode(selection) {
|
|
|
10
10
|
// ?
|
|
11
11
|
depth: selection.$from.depth
|
|
12
12
|
};
|
|
13
|
-
}
|
|
13
|
+
}
|
|
14
|
+
if (selection instanceof CellSelection) {
|
|
14
15
|
var tableSelected = findParentNodeOfType(selection.$from.doc.type.schema.nodes.table)(selection);
|
|
15
16
|
return tableSelected;
|
|
16
|
-
}
|
|
17
|
+
}
|
|
18
|
+
if (selection instanceof TextSelection) {
|
|
17
19
|
var _selection$$from$doc$ = selection.$from.doc.type.schema.nodes,
|
|
18
20
|
blockquote = _selection$$from$doc$.blockquote,
|
|
19
21
|
bulletList = _selection$$from$doc$.bulletList,
|
|
@@ -1,24 +1,45 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
2
|
import { getOutputNodes } from './transform-node-utils/transform';
|
|
3
3
|
export var transformNode = function transformNode(api) {
|
|
4
|
-
return
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
return (
|
|
5
|
+
// eslint-disable-next-line no-unused-vars
|
|
6
|
+
function (targetType, analyticsAttrs) {
|
|
7
|
+
return function (_ref) {
|
|
8
|
+
var _api$blockControls;
|
|
9
|
+
var tr = _ref.tr;
|
|
10
|
+
var preservedSelection = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.sharedState.currentState()) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.preservedSelection;
|
|
11
|
+
if (!preservedSelection) {
|
|
12
|
+
return tr;
|
|
13
|
+
}
|
|
14
|
+
var from = preservedSelection.from,
|
|
15
|
+
to = preservedSelection.to,
|
|
16
|
+
$from = preservedSelection.$from;
|
|
17
|
+
var selectedParent = $from.parent;
|
|
18
|
+
var fragment = Fragment.empty;
|
|
19
|
+
// top level selections can safely be transformed without checking for depth
|
|
20
|
+
var isWithinSelectedRange = $from.depth === 0;
|
|
21
|
+
tr.doc.nodesBetween(from, to, function (node) {
|
|
22
|
+
// need to only transform selected content, for nested selections nodesBetween includes the path to the selected parent
|
|
23
|
+
if (!isWithinSelectedRange && node.eq(selectedParent)) {
|
|
24
|
+
isWithinSelectedRange = true;
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (isWithinSelectedRange) {
|
|
28
|
+
var outputNode = getOutputNodes({
|
|
29
|
+
sourceNode: node,
|
|
30
|
+
targetNodeType: targetType,
|
|
31
|
+
schema: tr.doc.type.schema
|
|
32
|
+
});
|
|
33
|
+
if (outputNode) {
|
|
34
|
+
fragment = fragment.append(Fragment.fromArray(outputNode));
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
});
|
|
40
|
+
tr.replaceWith(preservedSelection.from, preservedSelection.to, fragment);
|
|
10
41
|
return tr;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
targetNodeType: targetType,
|
|
15
|
-
schema: selection.$from.doc.type.schema
|
|
16
|
-
});
|
|
17
|
-
if (!outputNodes) {
|
|
18
|
-
return tr;
|
|
19
|
-
}
|
|
20
|
-
tr.replaceWith(source.pos, source.pos + source.node.nodeSize, outputNodes);
|
|
21
|
-
return tr;
|
|
22
|
-
};
|
|
23
|
-
};
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
);
|
|
24
45
|
};
|
|
@@ -5,12 +5,12 @@ import type { DecorationsPlugin } from '@atlaskit/editor-plugin-decorations';
|
|
|
5
5
|
import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
|
|
6
6
|
import type { UserIntentPlugin } from '@atlaskit/editor-plugin-user-intent';
|
|
7
7
|
import type { NodeType } from '@atlaskit/editor-prosemirror/model';
|
|
8
|
-
import type { FormatNodeTargetType,
|
|
8
|
+
import type { FormatNodeAnalyticsAttrs, FormatNodeTargetType, TransformNodeAnalyticsAttrs } from './editor-commands/transforms/types';
|
|
9
9
|
export declare enum FLAG_ID {
|
|
10
10
|
LINK_COPIED_TO_CLIPBOARD = "link-copied-to-clipboard"
|
|
11
11
|
}
|
|
12
12
|
type FormatNodeCommand = (targetType: FormatNodeTargetType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
|
|
13
|
-
type TransformNodeCommand = (targetType: NodeType, analyticsAttrs?:
|
|
13
|
+
type TransformNodeCommand = (targetType: NodeType, analyticsAttrs?: TransformNodeAnalyticsAttrs) => EditorCommand;
|
|
14
14
|
export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
|
|
15
15
|
actions: {
|
|
16
16
|
getBlockMenuComponents: () => Array<RegisterBlockMenuComponent>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EditorCommand, ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
2
|
-
import type
|
|
2
|
+
import { type NodeType } from '@atlaskit/editor-prosemirror/model';
|
|
3
3
|
import type { BlockMenuPlugin } from '../blockMenuPluginType';
|
|
4
|
-
import type {
|
|
5
|
-
export declare const transformNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: NodeType, analyticsAttrs?:
|
|
4
|
+
import type { TransformNodeAnalyticsAttrs } from './transforms/types';
|
|
5
|
+
export declare const transformNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: NodeType, analyticsAttrs?: TransformNodeAnalyticsAttrs) => EditorCommand;
|
|
@@ -2,8 +2,12 @@ import type { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
|
2
2
|
import type { TransformContext } from '@atlaskit/editor-common/transforms';
|
|
3
3
|
import type { Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
4
4
|
export type FormatNodeTargetType = 'heading1' | 'heading2' | 'heading3' | 'heading4' | 'heading5' | 'heading6' | 'paragraph' | 'blockquote' | 'expand' | 'layoutSection' | 'panel' | 'codeBlock' | 'bulletList' | 'orderedList' | 'taskList';
|
|
5
|
+
export type TransfromNodeTargetType = FormatNodeTargetType;
|
|
5
6
|
export type FormatNodeAnalyticsAttrs = {
|
|
6
7
|
inputMethod: INPUT_METHOD.BLOCK_MENU;
|
|
7
8
|
triggeredFrom: INPUT_METHOD.MOUSE | INPUT_METHOD.KEYBOARD;
|
|
8
9
|
};
|
|
10
|
+
export type TransformNodeAnalyticsAttrs = FormatNodeAnalyticsAttrs & {
|
|
11
|
+
targetTypeName: TransfromNodeTargetType;
|
|
12
|
+
};
|
|
9
13
|
export type TransformFunction = (context: TransformContext) => Transaction | null;
|
|
@@ -5,12 +5,12 @@ import type { DecorationsPlugin } from '@atlaskit/editor-plugin-decorations';
|
|
|
5
5
|
import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
|
|
6
6
|
import type { UserIntentPlugin } from '@atlaskit/editor-plugin-user-intent';
|
|
7
7
|
import type { NodeType } from '@atlaskit/editor-prosemirror/model';
|
|
8
|
-
import type { FormatNodeTargetType,
|
|
8
|
+
import type { FormatNodeAnalyticsAttrs, FormatNodeTargetType, TransformNodeAnalyticsAttrs } from './editor-commands/transforms/types';
|
|
9
9
|
export declare enum FLAG_ID {
|
|
10
10
|
LINK_COPIED_TO_CLIPBOARD = "link-copied-to-clipboard"
|
|
11
11
|
}
|
|
12
12
|
type FormatNodeCommand = (targetType: FormatNodeTargetType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
|
|
13
|
-
type TransformNodeCommand = (targetType: NodeType, analyticsAttrs?:
|
|
13
|
+
type TransformNodeCommand = (targetType: NodeType, analyticsAttrs?: TransformNodeAnalyticsAttrs) => EditorCommand;
|
|
14
14
|
export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
|
|
15
15
|
actions: {
|
|
16
16
|
getBlockMenuComponents: () => Array<RegisterBlockMenuComponent>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EditorCommand, ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
2
|
-
import type
|
|
2
|
+
import { type NodeType } from '@atlaskit/editor-prosemirror/model';
|
|
3
3
|
import type { BlockMenuPlugin } from '../blockMenuPluginType';
|
|
4
|
-
import type {
|
|
5
|
-
export declare const transformNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: NodeType, analyticsAttrs?:
|
|
4
|
+
import type { TransformNodeAnalyticsAttrs } from './transforms/types';
|
|
5
|
+
export declare const transformNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: NodeType, analyticsAttrs?: TransformNodeAnalyticsAttrs) => EditorCommand;
|
|
@@ -2,8 +2,12 @@ import type { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
|
2
2
|
import type { TransformContext } from '@atlaskit/editor-common/transforms';
|
|
3
3
|
import type { Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
4
4
|
export type FormatNodeTargetType = 'heading1' | 'heading2' | 'heading3' | 'heading4' | 'heading5' | 'heading6' | 'paragraph' | 'blockquote' | 'expand' | 'layoutSection' | 'panel' | 'codeBlock' | 'bulletList' | 'orderedList' | 'taskList';
|
|
5
|
+
export type TransfromNodeTargetType = FormatNodeTargetType;
|
|
5
6
|
export type FormatNodeAnalyticsAttrs = {
|
|
6
7
|
inputMethod: INPUT_METHOD.BLOCK_MENU;
|
|
7
8
|
triggeredFrom: INPUT_METHOD.MOUSE | INPUT_METHOD.KEYBOARD;
|
|
8
9
|
};
|
|
10
|
+
export type TransformNodeAnalyticsAttrs = FormatNodeAnalyticsAttrs & {
|
|
11
|
+
targetTypeName: TransfromNodeTargetType;
|
|
12
|
+
};
|
|
9
13
|
export type TransformFunction = (context: TransformContext) => Transaction | null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-block-menu",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.1.1",
|
|
4
4
|
"description": "BlockMenu plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@atlaskit/css": "^0.17.0",
|
|
32
32
|
"@atlaskit/dropdown-menu": "^16.3.0",
|
|
33
33
|
"@atlaskit/editor-plugin-analytics": "^6.2.0",
|
|
34
|
-
"@atlaskit/editor-plugin-block-controls": "^7.
|
|
34
|
+
"@atlaskit/editor-plugin-block-controls": "^7.11.0",
|
|
35
35
|
"@atlaskit/editor-plugin-decorations": "^6.1.0",
|
|
36
36
|
"@atlaskit/editor-plugin-selection": "^6.1.0",
|
|
37
37
|
"@atlaskit/editor-plugin-user-intent": "^4.0.0",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
45
45
|
"@atlaskit/platform-feature-flags-react": "^0.4.0",
|
|
46
46
|
"@atlaskit/primitives": "^16.4.0",
|
|
47
|
-
"@atlaskit/tmp-editor-statsig": "^14.
|
|
47
|
+
"@atlaskit/tmp-editor-statsig": "^14.3.0",
|
|
48
48
|
"@atlaskit/tokens": "^8.4.0",
|
|
49
49
|
"@babel/runtime": "^7.0.0"
|
|
50
50
|
},
|