@atlaskit/editor-plugin-block-menu 5.1.6 → 5.1.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/CHANGELOG.md +8 -0
- package/dist/cjs/editor-commands/transform-node-utils/flattenListStep.js +9 -32
- package/dist/cjs/editor-commands/transform-node-utils/unwrapListStep.js +16 -1
- package/dist/cjs/editor-commands/transform-node-utils/utils.js +30 -1
- package/dist/cjs/editor-commands/transformNode.js +6 -6
- package/dist/cjs/ui/utils/suggested-items-rank.js +107 -0
- package/dist/es2019/editor-commands/transform-node-utils/flattenListStep.js +9 -32
- package/dist/es2019/editor-commands/transform-node-utils/unwrapListStep.js +16 -1
- package/dist/es2019/editor-commands/transform-node-utils/utils.js +29 -1
- package/dist/es2019/editor-commands/transformNode.js +2 -2
- package/dist/es2019/ui/utils/suggested-items-rank.js +223 -0
- package/dist/esm/editor-commands/transform-node-utils/flattenListStep.js +9 -32
- package/dist/esm/editor-commands/transform-node-utils/unwrapListStep.js +16 -1
- package/dist/esm/editor-commands/transform-node-utils/utils.js +30 -1
- package/dist/esm/editor-commands/transformNode.js +4 -4
- package/dist/esm/ui/utils/suggested-items-rank.js +101 -0
- package/dist/types/editor-commands/transform-node-utils/flattenListStep.d.ts +0 -18
- package/dist/types/editor-commands/transform-node-utils/unwrapListStep.d.ts +16 -1
- package/dist/types/editor-commands/transform-node-utils/utils.d.ts +12 -0
- package/dist/types/ui/utils/suggested-items-rank.d.ts +81 -0
- package/dist/types-ts4.5/editor-commands/transform-node-utils/flattenListStep.d.ts +0 -18
- package/dist/types-ts4.5/editor-commands/transform-node-utils/unwrapListStep.d.ts +16 -1
- package/dist/types-ts4.5/editor-commands/transform-node-utils/utils.d.ts +12 -0
- package/dist/types-ts4.5/ui/utils/suggested-items-rank.d.ts +81 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-block-menu
|
|
2
2
|
|
|
3
|
+
## 5.1.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`65ef204463ce4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/65ef204463ce4) -
|
|
8
|
+
Add predicate param to expandBlockRange, add logic to cater for selection being broken in lists
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
|
|
3
11
|
## 5.1.6
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
|
@@ -5,39 +5,34 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.flattenListStep = void 0;
|
|
7
7
|
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
8
|
-
var extractNestedLists = function extractNestedLists(node, listTypes, itemTypes) {
|
|
8
|
+
var extractNestedLists = function extractNestedLists(node, listTypes, itemTypes, schema) {
|
|
9
9
|
var items = [];
|
|
10
|
+
var paragraph = schema.nodes.paragraph;
|
|
10
11
|
var _extract = function extract(currentNode) {
|
|
11
12
|
currentNode.forEach(function (child) {
|
|
12
|
-
// list item -> take content without nested lists, then recurse into nested lists
|
|
13
13
|
if (itemTypes.some(function (type) {
|
|
14
14
|
return child.type === type;
|
|
15
15
|
})) {
|
|
16
|
-
// Filter out nested list nodes from the list item's content
|
|
17
16
|
var contentWithoutNestedLists = [];
|
|
18
17
|
var nestedLists = [];
|
|
19
18
|
child.forEach(function (grandChild) {
|
|
20
19
|
if (listTypes.some(function (type) {
|
|
21
20
|
return grandChild.type === type;
|
|
22
21
|
})) {
|
|
23
|
-
// This is a nested list - collect it for later processing
|
|
24
22
|
nestedLists.push(grandChild);
|
|
25
23
|
} else {
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
if (grandChild.isText) {
|
|
25
|
+
contentWithoutNestedLists.push(paragraph.createAndFill({}, grandChild));
|
|
26
|
+
} else {
|
|
27
|
+
contentWithoutNestedLists.push(grandChild);
|
|
28
|
+
}
|
|
28
29
|
}
|
|
29
30
|
});
|
|
30
|
-
|
|
31
|
-
// Add the list item with only its non-list content
|
|
32
31
|
items.push(child.copy(_model.Fragment.from(contentWithoutNestedLists)));
|
|
33
|
-
|
|
34
|
-
// Now process nested lists to maintain document order
|
|
35
32
|
nestedLists.forEach(function (nestedList) {
|
|
36
33
|
_extract(nestedList);
|
|
37
34
|
});
|
|
38
|
-
}
|
|
39
|
-
// lists -> keep operating
|
|
40
|
-
else if (listTypes.some(function (type) {
|
|
35
|
+
} else if (listTypes.some(function (type) {
|
|
41
36
|
return child.type === type;
|
|
42
37
|
})) {
|
|
43
38
|
_extract(child);
|
|
@@ -53,24 +48,6 @@ var extractNestedLists = function extractNestedLists(node, listTypes, itemTypes)
|
|
|
53
48
|
* to it's first ancestor list, maintaining document order.
|
|
54
49
|
*
|
|
55
50
|
* @example
|
|
56
|
-
* Input:
|
|
57
|
-
* - bulletList
|
|
58
|
-
* - listItem "A"
|
|
59
|
-
* - listItem "B"
|
|
60
|
-
* - bulletList
|
|
61
|
-
* - listItem "C"
|
|
62
|
-
* - listItem "D"
|
|
63
|
-
* - listItem "E"
|
|
64
|
-
*
|
|
65
|
-
* Output:
|
|
66
|
-
* - bulletList
|
|
67
|
-
* - listItem "A"
|
|
68
|
-
* - listItem "B"
|
|
69
|
-
* - listItem "C"
|
|
70
|
-
* - listItem "D"
|
|
71
|
-
* - listItem "E"
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
51
|
* Input (deeply nested):
|
|
75
52
|
* - bulletList
|
|
76
53
|
* - listItem "1"
|
|
@@ -101,7 +78,7 @@ var flattenListStep = exports.flattenListStep = function flattenListStep(nodes,
|
|
|
101
78
|
if (listTypes.some(function (type) {
|
|
102
79
|
return node.type === type;
|
|
103
80
|
})) {
|
|
104
|
-
return node.copy(_model.Fragment.from(extractNestedLists(node, listTypes, [context.schema.nodes.listItem, context.schema.nodes.taskItem])));
|
|
81
|
+
return node.copy(_model.Fragment.from(extractNestedLists(node, listTypes, [context.schema.nodes.listItem, context.schema.nodes.taskItem], context.schema)));
|
|
105
82
|
}
|
|
106
83
|
return node;
|
|
107
84
|
});
|
|
@@ -7,8 +7,23 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.unwrapListStep = void 0;
|
|
8
8
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
9
|
/**
|
|
10
|
-
* Given an array of nodes,
|
|
10
|
+
* Given an array of nodes, processes each list removing all parent list nodes and
|
|
11
|
+
* just returning their child contents.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* Input:
|
|
15
|
+
* - bulletList
|
|
16
|
+
* - listItem "1"
|
|
17
|
+
* - paragraph "1"
|
|
18
|
+
* - listItem "2"
|
|
19
|
+
* - paragraph "2"
|
|
20
|
+
*
|
|
21
|
+
* Output:
|
|
22
|
+
* - paragraph "1"
|
|
23
|
+
* - paragraph "2"
|
|
24
|
+
*
|
|
11
25
|
* @param nodes
|
|
26
|
+
* @param context
|
|
12
27
|
* @returns
|
|
13
28
|
*/
|
|
14
29
|
var unwrapListStep = exports.unwrapListStep = function unwrapListStep(nodes, context) {
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.getTargetNodeTypeNameInContext = exports.getSelectedNode = void 0;
|
|
6
|
+
exports.getTargetNodeTypeNameInContext = exports.getSelectedNode = exports.expandSelectionToBlockRange = void 0;
|
|
7
|
+
var _selection = require("@atlaskit/editor-common/selection");
|
|
7
8
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
8
9
|
var _utils = require("@atlaskit/editor-prosemirror/utils");
|
|
9
10
|
var _editorTables = require("@atlaskit/editor-tables");
|
|
@@ -54,4 +55,32 @@ var getTargetNodeTypeNameInContext = exports.getTargetNodeTypeNameInContext = fu
|
|
|
54
55
|
return 'nestedExpand';
|
|
55
56
|
}
|
|
56
57
|
return nodeTypeName;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Use common expandToBlockRange function, but account for edge cases with lists.
|
|
62
|
+
*
|
|
63
|
+
* @param selection
|
|
64
|
+
* @param schema
|
|
65
|
+
* @returns
|
|
66
|
+
*/
|
|
67
|
+
var expandSelectionToBlockRange = exports.expandSelectionToBlockRange = function expandSelectionToBlockRange(selection, schema) {
|
|
68
|
+
var isListInSelection = (0, _utils.hasParentNode)(function (node) {
|
|
69
|
+
return node.type === schema.nodes.bulletList || node.type === schema.nodes.orderedList;
|
|
70
|
+
})(selection);
|
|
71
|
+
var _expandToBlockRange = (0, _selection.expandToBlockRange)(selection.$from, selection.$to, function (node) {
|
|
72
|
+
if (!isListInSelection) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
if (node.type === schema.nodes.bulletList || node.type === schema.nodes.orderedList) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}),
|
|
80
|
+
$from = _expandToBlockRange.$from,
|
|
81
|
+
$to = _expandToBlockRange.$to;
|
|
82
|
+
return {
|
|
83
|
+
$from: $from,
|
|
84
|
+
$to: $to
|
|
85
|
+
};
|
|
57
86
|
};
|
|
@@ -4,11 +4,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.transformNode = void 0;
|
|
7
|
-
var _selection = require("@atlaskit/editor-common/selection");
|
|
8
7
|
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
9
8
|
var _isNestedNode = require("../ui/utils/isNestedNode");
|
|
10
9
|
var _transform = require("./transform-node-utils/transform");
|
|
11
|
-
var _utils = require("./
|
|
10
|
+
var _utils = require("./transform-node-utils/utils");
|
|
11
|
+
var _utils2 = require("./transforms/utils");
|
|
12
12
|
var transformNode = exports.transformNode = function transformNode(api) {
|
|
13
13
|
return (
|
|
14
14
|
// eslint-disable-next-line no-unused-vars
|
|
@@ -20,13 +20,13 @@ var transformNode = exports.transformNode = function transformNode(api) {
|
|
|
20
20
|
if (!preservedSelection) {
|
|
21
21
|
return tr;
|
|
22
22
|
}
|
|
23
|
-
var
|
|
24
|
-
$from =
|
|
25
|
-
$to =
|
|
23
|
+
var _expandSelectionToBlo = (0, _utils.expandSelectionToBlockRange)(preservedSelection, tr.doc.type.schema),
|
|
24
|
+
$from = _expandSelectionToBlo.$from,
|
|
25
|
+
$to = _expandSelectionToBlo.$to;
|
|
26
26
|
var isNested = (0, _isNestedNode.isNestedNode)(preservedSelection, '');
|
|
27
27
|
var selectedParent = $from.parent;
|
|
28
28
|
var fragment = _model.Fragment.empty;
|
|
29
|
-
var isList = (0,
|
|
29
|
+
var isList = (0, _utils2.isListNode)(selectedParent);
|
|
30
30
|
var slice = tr.doc.slice(isList ? $from.pos - 1 : $from.pos, isList ? $to.pos + 1 : $to.pos);
|
|
31
31
|
slice.content.forEach(function (node) {
|
|
32
32
|
var outputNode = (0, _transform.getOutputNodes)({
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.getSuggestedItemsForNodeType = exports.getSortedSuggestedItems = exports.TRANSFORM_SUGGESTED_ITEMS_RANK = exports.BLOCK_MENU_NODE_TYPES = void 0;
|
|
8
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
9
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
10
|
+
var _blockMenu = require("@atlaskit/editor-common/block-menu");
|
|
11
|
+
var _TRANSFORM_SUGGESTED_;
|
|
12
|
+
/**
|
|
13
|
+
* Suggested transformations mapping for each block type.
|
|
14
|
+
* Based on the Block Menu Compatibility Matrix:
|
|
15
|
+
* https://hello.atlassian.net/wiki/spaces/egcuc/pages/5868774224/Block+Menu+Compatibility+Matrix#Suggested-for-each-block-type
|
|
16
|
+
*
|
|
17
|
+
* This mapping defines which transform items should appear in the TRANSFORM_SUGGESTED_MENU_SECTION
|
|
18
|
+
* for each block type, ranked by priority (lower rank = higher priority).
|
|
19
|
+
*
|
|
20
|
+
* Structure:
|
|
21
|
+
* {
|
|
22
|
+
* [sourceNodeType]: {
|
|
23
|
+
* [targetMenuItemKey]: rank
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Node type keys that map to ProseMirror node types from the ADF schema.
|
|
29
|
+
* These values must match the NodeTypeName type.
|
|
30
|
+
*
|
|
31
|
+
* TypeScript will enforce that all values are valid NodeTypeName values.
|
|
32
|
+
* If a new node type is added, it must be added to NodeTypeName first.
|
|
33
|
+
*
|
|
34
|
+
* Reference: packages/editor/editor-plugin-block-menu/src/editor-commands/transform-node-utils/types.ts
|
|
35
|
+
*
|
|
36
|
+
* Note: 'heading' represents all heading levels (1-6) as a single node type.
|
|
37
|
+
* The specific level is determined by the node's `attrs.level` property at runtime.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* // Usage:
|
|
41
|
+
* const nodeType = BLOCK_MENU_NODE_TYPES.PARAGRAPH; // Type: "paragraph"
|
|
42
|
+
*/
|
|
43
|
+
var BLOCK_MENU_NODE_TYPES = exports.BLOCK_MENU_NODE_TYPES = {
|
|
44
|
+
PARAGRAPH: 'paragraph',
|
|
45
|
+
EXPAND: 'expand',
|
|
46
|
+
BLOCKQUOTE: 'blockquote',
|
|
47
|
+
LAYOUT_SECTION: 'layoutSection',
|
|
48
|
+
PANEL: 'panel',
|
|
49
|
+
CODE_BLOCK: 'codeBlock',
|
|
50
|
+
DECISION: 'decisionList',
|
|
51
|
+
BULLET_LIST: 'bulletList',
|
|
52
|
+
ORDERED_LIST: 'orderedList',
|
|
53
|
+
HEADING: 'heading',
|
|
54
|
+
TASK_LIST: 'taskList',
|
|
55
|
+
MEDIA_SINGLE: 'mediaSingle',
|
|
56
|
+
EXTENSION: 'extension',
|
|
57
|
+
BODIED_EXTENSION: 'bodiedExtension',
|
|
58
|
+
BLOCK_CARD: 'blockCard',
|
|
59
|
+
EMBED_CARD: 'embedCard',
|
|
60
|
+
TABLE: 'table'
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Type for node type values extracted from BLOCK_MENU_NODE_TYPES
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Type for the suggested items rank mapping
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Mapping of source node types to suggested transformation menu items with their ranks.
|
|
73
|
+
* Lower rank number = higher priority in the suggested menu section.
|
|
74
|
+
*/
|
|
75
|
+
var TRANSFORM_SUGGESTED_ITEMS_RANK = exports.TRANSFORM_SUGGESTED_ITEMS_RANK = (_TRANSFORM_SUGGESTED_ = {}, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)(_TRANSFORM_SUGGESTED_, BLOCK_MENU_NODE_TYPES.PARAGRAPH, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_HEADINGS_H2_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_HEADINGS_H3_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.EXPAND, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.BLOCKQUOTE, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.LAYOUT_SECTION, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_HEADINGS_H2_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.PANEL, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_QUOTE_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_STRUCTURE_CODE_BLOCK_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.CODE_BLOCK, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.DECISION, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_STRUCTURE_TASK_LIST_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.BULLET_LIST, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_NUMBERED_LIST_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_QUOTE_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.ORDERED_LIST, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_BULLETED_LIST_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_TASK_LIST_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.HEADING, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_HEADINGS_H2_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 300)), (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)(_TRANSFORM_SUGGESTED_, BLOCK_MENU_NODE_TYPES.TASK_LIST, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_NUMBERED_LIST_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_STRUCTURE_CODE_BLOCK_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.MEDIA_SINGLE, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.EXTENSION, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.BODIED_EXTENSION, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 200), _blockMenu.TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.BLOCK_CARD, (0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 200)), BLOCK_MENU_NODE_TYPES.EMBED_CARD, (0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 200)), BLOCK_MENU_NODE_TYPES.TABLE, (0, _defineProperty2.default)((0, _defineProperty2.default)({}, _blockMenu.TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key, 100), _blockMenu.TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key, 200)));
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get suggested menu items for a given node type
|
|
79
|
+
* @param nodeType - The source node type (e.g., 'paragraph', 'heading')
|
|
80
|
+
* @returns Object mapping menu item keys to their ranks, or undefined if no suggestions
|
|
81
|
+
*/
|
|
82
|
+
var getSuggestedItemsForNodeType = exports.getSuggestedItemsForNodeType = function getSuggestedItemsForNodeType(nodeType) {
|
|
83
|
+
return TRANSFORM_SUGGESTED_ITEMS_RANK[nodeType];
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get sorted suggested menu item keys for a given node type
|
|
88
|
+
* @param nodeType - The source node type
|
|
89
|
+
* @returns Array of menu item keys sorted by rank (highest priority first)
|
|
90
|
+
*/
|
|
91
|
+
var getSortedSuggestedItems = exports.getSortedSuggestedItems = function getSortedSuggestedItems(nodeType) {
|
|
92
|
+
var suggestions = getSuggestedItemsForNodeType(nodeType);
|
|
93
|
+
if (!suggestions) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
return Object.entries(suggestions).sort(function (_ref, _ref2) {
|
|
97
|
+
var _ref3 = (0, _slicedToArray2.default)(_ref, 2),
|
|
98
|
+
rankA = _ref3[1];
|
|
99
|
+
var _ref4 = (0, _slicedToArray2.default)(_ref2, 2),
|
|
100
|
+
rankB = _ref4[1];
|
|
101
|
+
return rankA - rankB;
|
|
102
|
+
}).map(function (_ref5) {
|
|
103
|
+
var _ref6 = (0, _slicedToArray2.default)(_ref5, 1),
|
|
104
|
+
key = _ref6[0];
|
|
105
|
+
return key;
|
|
106
|
+
});
|
|
107
|
+
};
|
|
@@ -1,33 +1,28 @@
|
|
|
1
1
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
-
const extractNestedLists = (node, listTypes, itemTypes) => {
|
|
2
|
+
const extractNestedLists = (node, listTypes, itemTypes, schema) => {
|
|
3
3
|
const items = [];
|
|
4
|
+
const paragraph = schema.nodes.paragraph;
|
|
4
5
|
const extract = currentNode => {
|
|
5
6
|
currentNode.forEach(child => {
|
|
6
|
-
// list item -> take content without nested lists, then recurse into nested lists
|
|
7
7
|
if (itemTypes.some(type => child.type === type)) {
|
|
8
|
-
// Filter out nested list nodes from the list item's content
|
|
9
8
|
const contentWithoutNestedLists = [];
|
|
10
9
|
const nestedLists = [];
|
|
11
10
|
child.forEach(grandChild => {
|
|
12
11
|
if (listTypes.some(type => grandChild.type === type)) {
|
|
13
|
-
// This is a nested list - collect it for later processing
|
|
14
12
|
nestedLists.push(grandChild);
|
|
15
13
|
} else {
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
if (grandChild.isText) {
|
|
15
|
+
contentWithoutNestedLists.push(paragraph.createAndFill({}, grandChild));
|
|
16
|
+
} else {
|
|
17
|
+
contentWithoutNestedLists.push(grandChild);
|
|
18
|
+
}
|
|
18
19
|
}
|
|
19
20
|
});
|
|
20
|
-
|
|
21
|
-
// Add the list item with only its non-list content
|
|
22
21
|
items.push(child.copy(Fragment.from(contentWithoutNestedLists)));
|
|
23
|
-
|
|
24
|
-
// Now process nested lists to maintain document order
|
|
25
22
|
nestedLists.forEach(nestedList => {
|
|
26
23
|
extract(nestedList);
|
|
27
24
|
});
|
|
28
|
-
}
|
|
29
|
-
// lists -> keep operating
|
|
30
|
-
else if (listTypes.some(type => child.type === type)) {
|
|
25
|
+
} else if (listTypes.some(type => child.type === type)) {
|
|
31
26
|
extract(child);
|
|
32
27
|
}
|
|
33
28
|
});
|
|
@@ -41,24 +36,6 @@ const extractNestedLists = (node, listTypes, itemTypes) => {
|
|
|
41
36
|
* to it's first ancestor list, maintaining document order.
|
|
42
37
|
*
|
|
43
38
|
* @example
|
|
44
|
-
* Input:
|
|
45
|
-
* - bulletList
|
|
46
|
-
* - listItem "A"
|
|
47
|
-
* - listItem "B"
|
|
48
|
-
* - bulletList
|
|
49
|
-
* - listItem "C"
|
|
50
|
-
* - listItem "D"
|
|
51
|
-
* - listItem "E"
|
|
52
|
-
*
|
|
53
|
-
* Output:
|
|
54
|
-
* - bulletList
|
|
55
|
-
* - listItem "A"
|
|
56
|
-
* - listItem "B"
|
|
57
|
-
* - listItem "C"
|
|
58
|
-
* - listItem "D"
|
|
59
|
-
* - listItem "E"
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
39
|
* Input (deeply nested):
|
|
63
40
|
* - bulletList
|
|
64
41
|
* - listItem "1"
|
|
@@ -87,7 +64,7 @@ export const flattenListStep = (nodes, context) => {
|
|
|
87
64
|
const listTypes = [context.schema.nodes.bulletList, context.schema.nodes.orderedList, context.schema.nodes.taskList];
|
|
88
65
|
return nodes.map(node => {
|
|
89
66
|
if (listTypes.some(type => node.type === type)) {
|
|
90
|
-
return node.copy(Fragment.from(extractNestedLists(node, listTypes, [context.schema.nodes.listItem, context.schema.nodes.taskItem])));
|
|
67
|
+
return node.copy(Fragment.from(extractNestedLists(node, listTypes, [context.schema.nodes.listItem, context.schema.nodes.taskItem], context.schema)));
|
|
91
68
|
}
|
|
92
69
|
return node;
|
|
93
70
|
});
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Given an array of nodes,
|
|
2
|
+
* Given an array of nodes, processes each list removing all parent list nodes and
|
|
3
|
+
* just returning their child contents.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* Input:
|
|
7
|
+
* - bulletList
|
|
8
|
+
* - listItem "1"
|
|
9
|
+
* - paragraph "1"
|
|
10
|
+
* - listItem "2"
|
|
11
|
+
* - paragraph "2"
|
|
12
|
+
*
|
|
13
|
+
* Output:
|
|
14
|
+
* - paragraph "1"
|
|
15
|
+
* - paragraph "2"
|
|
16
|
+
*
|
|
3
17
|
* @param nodes
|
|
18
|
+
* @param context
|
|
4
19
|
* @returns
|
|
5
20
|
*/
|
|
6
21
|
export const unwrapListStep = (nodes, context) => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { expandToBlockRange } from '@atlaskit/editor-common/selection';
|
|
1
2
|
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
-
import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
3
|
+
import { findParentNodeOfType, hasParentNode } from '@atlaskit/editor-prosemirror/utils';
|
|
3
4
|
import { CellSelection } from '@atlaskit/editor-tables';
|
|
4
5
|
export const getSelectedNode = selection => {
|
|
5
6
|
if (selection instanceof NodeSelection) {
|
|
@@ -49,4 +50,31 @@ export const getTargetNodeTypeNameInContext = (nodeTypeName, isNested) => {
|
|
|
49
50
|
return 'nestedExpand';
|
|
50
51
|
}
|
|
51
52
|
return nodeTypeName;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Use common expandToBlockRange function, but account for edge cases with lists.
|
|
57
|
+
*
|
|
58
|
+
* @param selection
|
|
59
|
+
* @param schema
|
|
60
|
+
* @returns
|
|
61
|
+
*/
|
|
62
|
+
export const expandSelectionToBlockRange = (selection, schema) => {
|
|
63
|
+
const isListInSelection = hasParentNode(node => node.type === schema.nodes.bulletList || node.type === schema.nodes.orderedList)(selection);
|
|
64
|
+
const {
|
|
65
|
+
$from,
|
|
66
|
+
$to
|
|
67
|
+
} = expandToBlockRange(selection.$from, selection.$to, node => {
|
|
68
|
+
if (!isListInSelection) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (node.type === schema.nodes.bulletList || node.type === schema.nodes.orderedList) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
$from,
|
|
78
|
+
$to
|
|
79
|
+
};
|
|
52
80
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { expandToBlockRange } from '@atlaskit/editor-common/selection';
|
|
2
1
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
3
2
|
import { isNestedNode } from '../ui/utils/isNestedNode';
|
|
4
3
|
import { getOutputNodes } from './transform-node-utils/transform';
|
|
4
|
+
import { expandSelectionToBlockRange } from './transform-node-utils/utils';
|
|
5
5
|
import { isListNode } from './transforms/utils';
|
|
6
6
|
export const transformNode = api =>
|
|
7
7
|
// eslint-disable-next-line no-unused-vars
|
|
@@ -17,7 +17,7 @@ export const transformNode = api =>
|
|
|
17
17
|
const {
|
|
18
18
|
$from,
|
|
19
19
|
$to
|
|
20
|
-
} =
|
|
20
|
+
} = expandSelectionToBlockRange(preservedSelection, tr.doc.type.schema);
|
|
21
21
|
const isNested = isNestedNode(preservedSelection, '');
|
|
22
22
|
const selectedParent = $from.parent;
|
|
23
23
|
let fragment = Fragment.empty;
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suggested transformations mapping for each block type.
|
|
3
|
+
* Based on the Block Menu Compatibility Matrix:
|
|
4
|
+
* https://hello.atlassian.net/wiki/spaces/egcuc/pages/5868774224/Block+Menu+Compatibility+Matrix#Suggested-for-each-block-type
|
|
5
|
+
*
|
|
6
|
+
* This mapping defines which transform items should appear in the TRANSFORM_SUGGESTED_MENU_SECTION
|
|
7
|
+
* for each block type, ranked by priority (lower rank = higher priority).
|
|
8
|
+
*
|
|
9
|
+
* Structure:
|
|
10
|
+
* {
|
|
11
|
+
* [sourceNodeType]: {
|
|
12
|
+
* [targetMenuItemKey]: rank
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { TRANSFORM_STRUCTURE_PANEL_MENU_ITEM, TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM, TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM, TRANSFORM_STRUCTURE_QUOTE_MENU_ITEM, TRANSFORM_STRUCTURE_CODE_BLOCK_MENU_ITEM, TRANSFORM_STRUCTURE_BULLETED_LIST_MENU_ITEM, TRANSFORM_STRUCTURE_NUMBERED_LIST_MENU_ITEM, TRANSFORM_STRUCTURE_TASK_LIST_MENU_ITEM, TRANSFORM_HEADINGS_H2_MENU_ITEM, TRANSFORM_HEADINGS_H3_MENU_ITEM, TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM } from '@atlaskit/editor-common/block-menu';
|
|
18
|
+
/**
|
|
19
|
+
* Node type keys that map to ProseMirror node types from the ADF schema.
|
|
20
|
+
* These values must match the NodeTypeName type.
|
|
21
|
+
*
|
|
22
|
+
* TypeScript will enforce that all values are valid NodeTypeName values.
|
|
23
|
+
* If a new node type is added, it must be added to NodeTypeName first.
|
|
24
|
+
*
|
|
25
|
+
* Reference: packages/editor/editor-plugin-block-menu/src/editor-commands/transform-node-utils/types.ts
|
|
26
|
+
*
|
|
27
|
+
* Note: 'heading' represents all heading levels (1-6) as a single node type.
|
|
28
|
+
* The specific level is determined by the node's `attrs.level` property at runtime.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // Usage:
|
|
32
|
+
* const nodeType = BLOCK_MENU_NODE_TYPES.PARAGRAPH; // Type: "paragraph"
|
|
33
|
+
*/
|
|
34
|
+
export const BLOCK_MENU_NODE_TYPES = {
|
|
35
|
+
PARAGRAPH: 'paragraph',
|
|
36
|
+
EXPAND: 'expand',
|
|
37
|
+
BLOCKQUOTE: 'blockquote',
|
|
38
|
+
LAYOUT_SECTION: 'layoutSection',
|
|
39
|
+
PANEL: 'panel',
|
|
40
|
+
CODE_BLOCK: 'codeBlock',
|
|
41
|
+
DECISION: 'decisionList',
|
|
42
|
+
BULLET_LIST: 'bulletList',
|
|
43
|
+
ORDERED_LIST: 'orderedList',
|
|
44
|
+
HEADING: 'heading',
|
|
45
|
+
TASK_LIST: 'taskList',
|
|
46
|
+
MEDIA_SINGLE: 'mediaSingle',
|
|
47
|
+
EXTENSION: 'extension',
|
|
48
|
+
BODIED_EXTENSION: 'bodiedExtension',
|
|
49
|
+
BLOCK_CARD: 'blockCard',
|
|
50
|
+
EMBED_CARD: 'embedCard',
|
|
51
|
+
TABLE: 'table'
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Type for node type values extracted from BLOCK_MENU_NODE_TYPES
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Type for the suggested items rank mapping
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Mapping of source node types to suggested transformation menu items with their ranks.
|
|
64
|
+
* Lower rank number = higher priority in the suggested menu section.
|
|
65
|
+
*/
|
|
66
|
+
export const TRANSFORM_SUGGESTED_ITEMS_RANK = {
|
|
67
|
+
// Paragraph suggestions
|
|
68
|
+
[BLOCK_MENU_NODE_TYPES.PARAGRAPH]: {
|
|
69
|
+
[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key]: 100,
|
|
70
|
+
// Turn into Panel
|
|
71
|
+
[TRANSFORM_HEADINGS_H2_MENU_ITEM.key]: 200,
|
|
72
|
+
// Turn into Heading 2
|
|
73
|
+
[TRANSFORM_HEADINGS_H3_MENU_ITEM.key]: 300 // Turn into Heading 3
|
|
74
|
+
},
|
|
75
|
+
// Expand suggestions
|
|
76
|
+
[BLOCK_MENU_NODE_TYPES.EXPAND]: {
|
|
77
|
+
[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key]: 100,
|
|
78
|
+
// Turn into Panel (wrap content)
|
|
79
|
+
[TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key]: 200,
|
|
80
|
+
// Turn into Layout
|
|
81
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 300 // Turn into Paragraph
|
|
82
|
+
},
|
|
83
|
+
// Quote block (blockquote) suggestions
|
|
84
|
+
[BLOCK_MENU_NODE_TYPES.BLOCKQUOTE]: {
|
|
85
|
+
[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key]: 100,
|
|
86
|
+
// Turn into Panel
|
|
87
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 200,
|
|
88
|
+
// Turn into Paragraph
|
|
89
|
+
[TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key]: 300 // Turn into Layout
|
|
90
|
+
},
|
|
91
|
+
// Layout suggestions
|
|
92
|
+
[BLOCK_MENU_NODE_TYPES.LAYOUT_SECTION]: {
|
|
93
|
+
[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key]: 100,
|
|
94
|
+
// Wrap layout in panel
|
|
95
|
+
[TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key]: 200,
|
|
96
|
+
// Make layout collapsible
|
|
97
|
+
[TRANSFORM_HEADINGS_H2_MENU_ITEM.key]: 300 // doesn't meet compatibility matrix, needs to be updated
|
|
98
|
+
},
|
|
99
|
+
// Panel suggestions
|
|
100
|
+
[BLOCK_MENU_NODE_TYPES.PANEL]: {
|
|
101
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 100,
|
|
102
|
+
// Turn into Paragraph
|
|
103
|
+
[TRANSFORM_STRUCTURE_QUOTE_MENU_ITEM.key]: 200,
|
|
104
|
+
// Turn into Blockquote
|
|
105
|
+
[TRANSFORM_STRUCTURE_CODE_BLOCK_MENU_ITEM.key]: 300 // Turn into Code Block
|
|
106
|
+
},
|
|
107
|
+
// Code block suggestions
|
|
108
|
+
[BLOCK_MENU_NODE_TYPES.CODE_BLOCK]: {
|
|
109
|
+
[TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key]: 100,
|
|
110
|
+
// Turn into Expand
|
|
111
|
+
[TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key]: 200,
|
|
112
|
+
// Turn into Layout
|
|
113
|
+
[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key]: 300 // Turn into Panel
|
|
114
|
+
},
|
|
115
|
+
// Decision suggestions
|
|
116
|
+
[BLOCK_MENU_NODE_TYPES.DECISION]: {
|
|
117
|
+
[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key]: 100,
|
|
118
|
+
// Wrap in Panel (Decision style)
|
|
119
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 200,
|
|
120
|
+
// Turn into Paragraph
|
|
121
|
+
[TRANSFORM_STRUCTURE_TASK_LIST_MENU_ITEM.key]: 300 // Convert to Task List
|
|
122
|
+
},
|
|
123
|
+
// Bulleted list suggestions
|
|
124
|
+
[BLOCK_MENU_NODE_TYPES.BULLET_LIST]: {
|
|
125
|
+
[TRANSFORM_STRUCTURE_NUMBERED_LIST_MENU_ITEM.key]: 100,
|
|
126
|
+
// Turn into Numbered list
|
|
127
|
+
[TRANSFORM_STRUCTURE_QUOTE_MENU_ITEM.key]: 200,
|
|
128
|
+
// Turn into Blockquote
|
|
129
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 300 // Turn into Paragraph
|
|
130
|
+
},
|
|
131
|
+
// Numbered list (ordered list) suggestions
|
|
132
|
+
[BLOCK_MENU_NODE_TYPES.ORDERED_LIST]: {
|
|
133
|
+
[TRANSFORM_STRUCTURE_BULLETED_LIST_MENU_ITEM.key]: 100,
|
|
134
|
+
// Turn into Bulleted list
|
|
135
|
+
[TRANSFORM_STRUCTURE_TASK_LIST_MENU_ITEM.key]: 200,
|
|
136
|
+
// Turn into Task List
|
|
137
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 300 // Turn into Paragraph
|
|
138
|
+
},
|
|
139
|
+
// Heading suggestions
|
|
140
|
+
// Note: For headings, the specific heading level would need to be determined at runtime
|
|
141
|
+
// This provides a general mapping, but actual implementation should consider current heading level
|
|
142
|
+
[BLOCK_MENU_NODE_TYPES.HEADING]: {
|
|
143
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 100,
|
|
144
|
+
// Turn into Paragraph
|
|
145
|
+
[TRANSFORM_HEADINGS_H2_MENU_ITEM.key]: 200,
|
|
146
|
+
// Turn into Heading 2
|
|
147
|
+
[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key]: 300 // Wrap in Panel
|
|
148
|
+
},
|
|
149
|
+
// Task list suggestions
|
|
150
|
+
[BLOCK_MENU_NODE_TYPES.TASK_LIST]: {
|
|
151
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 100,
|
|
152
|
+
// Turn into Paragraph
|
|
153
|
+
[TRANSFORM_STRUCTURE_NUMBERED_LIST_MENU_ITEM.key]: 200,
|
|
154
|
+
// Turn into Ordered list
|
|
155
|
+
[TRANSFORM_STRUCTURE_CODE_BLOCK_MENU_ITEM.key]: 300 // Turn into Code Block (for technical TODOs)
|
|
156
|
+
},
|
|
157
|
+
// Media (mediaSingle) suggestions
|
|
158
|
+
[BLOCK_MENU_NODE_TYPES.MEDIA_SINGLE]: {
|
|
159
|
+
[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key]: 100,
|
|
160
|
+
// Wrap in Panel
|
|
161
|
+
[TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key]: 200,
|
|
162
|
+
// Place into Layout
|
|
163
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 300 // doesn't meet compatibility matrix, needs to be updated
|
|
164
|
+
},
|
|
165
|
+
// Extension (app/macro) suggestions
|
|
166
|
+
[BLOCK_MENU_NODE_TYPES.EXTENSION]: {
|
|
167
|
+
[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key]: 100,
|
|
168
|
+
// Wrap in Panel
|
|
169
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 200,
|
|
170
|
+
// doesn't meet compatibility matrix, needs to be updated
|
|
171
|
+
[TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key]: 300 // Collapse in Expand
|
|
172
|
+
},
|
|
173
|
+
// Bodied Extension suggestions (same as Extension)
|
|
174
|
+
[BLOCK_MENU_NODE_TYPES.BODIED_EXTENSION]: {
|
|
175
|
+
[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key]: 100,
|
|
176
|
+
// Wrap in Panel
|
|
177
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 200,
|
|
178
|
+
// doesn't meet compatibility matrix, needs to be updated
|
|
179
|
+
[TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key]: 300 // Collapse in Expand
|
|
180
|
+
},
|
|
181
|
+
// Smart link Card suggestions
|
|
182
|
+
[BLOCK_MENU_NODE_TYPES.BLOCK_CARD]: {
|
|
183
|
+
// Note: Smart link card conversion would be rank 100 (demote to card)
|
|
184
|
+
[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key]: 100,
|
|
185
|
+
// Wrap in Panel
|
|
186
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 200 // doesn't meet compatibility matrix, needs to be updated
|
|
187
|
+
},
|
|
188
|
+
// Smart link Embed suggestions
|
|
189
|
+
[BLOCK_MENU_NODE_TYPES.EMBED_CARD]: {
|
|
190
|
+
// Note: Smart link embed conversion would be rank 100 (promote to embed)
|
|
191
|
+
[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key]: 100,
|
|
192
|
+
// Wrap in Panel
|
|
193
|
+
[TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key]: 200 // doesn't meet compatibility matrix, needs to be updated
|
|
194
|
+
},
|
|
195
|
+
// Table suggestions
|
|
196
|
+
[BLOCK_MENU_NODE_TYPES.TABLE]: {
|
|
197
|
+
[TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key]: 100,
|
|
198
|
+
// Turn into Expand
|
|
199
|
+
[TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key]: 200 // Turn into Layout
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get suggested menu items for a given node type
|
|
205
|
+
* @param nodeType - The source node type (e.g., 'paragraph', 'heading')
|
|
206
|
+
* @returns Object mapping menu item keys to their ranks, or undefined if no suggestions
|
|
207
|
+
*/
|
|
208
|
+
export const getSuggestedItemsForNodeType = nodeType => {
|
|
209
|
+
return TRANSFORM_SUGGESTED_ITEMS_RANK[nodeType];
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Get sorted suggested menu item keys for a given node type
|
|
214
|
+
* @param nodeType - The source node type
|
|
215
|
+
* @returns Array of menu item keys sorted by rank (highest priority first)
|
|
216
|
+
*/
|
|
217
|
+
export const getSortedSuggestedItems = nodeType => {
|
|
218
|
+
const suggestions = getSuggestedItemsForNodeType(nodeType);
|
|
219
|
+
if (!suggestions) {
|
|
220
|
+
return [];
|
|
221
|
+
}
|
|
222
|
+
return Object.entries(suggestions).sort(([, rankA], [, rankB]) => rankA - rankB).map(([key]) => key);
|
|
223
|
+
};
|
|
@@ -1,37 +1,32 @@
|
|
|
1
1
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
-
var extractNestedLists = function extractNestedLists(node, listTypes, itemTypes) {
|
|
2
|
+
var extractNestedLists = function extractNestedLists(node, listTypes, itemTypes, schema) {
|
|
3
3
|
var items = [];
|
|
4
|
+
var paragraph = schema.nodes.paragraph;
|
|
4
5
|
var _extract = function extract(currentNode) {
|
|
5
6
|
currentNode.forEach(function (child) {
|
|
6
|
-
// list item -> take content without nested lists, then recurse into nested lists
|
|
7
7
|
if (itemTypes.some(function (type) {
|
|
8
8
|
return child.type === type;
|
|
9
9
|
})) {
|
|
10
|
-
// Filter out nested list nodes from the list item's content
|
|
11
10
|
var contentWithoutNestedLists = [];
|
|
12
11
|
var nestedLists = [];
|
|
13
12
|
child.forEach(function (grandChild) {
|
|
14
13
|
if (listTypes.some(function (type) {
|
|
15
14
|
return grandChild.type === type;
|
|
16
15
|
})) {
|
|
17
|
-
// This is a nested list - collect it for later processing
|
|
18
16
|
nestedLists.push(grandChild);
|
|
19
17
|
} else {
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
if (grandChild.isText) {
|
|
19
|
+
contentWithoutNestedLists.push(paragraph.createAndFill({}, grandChild));
|
|
20
|
+
} else {
|
|
21
|
+
contentWithoutNestedLists.push(grandChild);
|
|
22
|
+
}
|
|
22
23
|
}
|
|
23
24
|
});
|
|
24
|
-
|
|
25
|
-
// Add the list item with only its non-list content
|
|
26
25
|
items.push(child.copy(Fragment.from(contentWithoutNestedLists)));
|
|
27
|
-
|
|
28
|
-
// Now process nested lists to maintain document order
|
|
29
26
|
nestedLists.forEach(function (nestedList) {
|
|
30
27
|
_extract(nestedList);
|
|
31
28
|
});
|
|
32
|
-
}
|
|
33
|
-
// lists -> keep operating
|
|
34
|
-
else if (listTypes.some(function (type) {
|
|
29
|
+
} else if (listTypes.some(function (type) {
|
|
35
30
|
return child.type === type;
|
|
36
31
|
})) {
|
|
37
32
|
_extract(child);
|
|
@@ -47,24 +42,6 @@ var extractNestedLists = function extractNestedLists(node, listTypes, itemTypes)
|
|
|
47
42
|
* to it's first ancestor list, maintaining document order.
|
|
48
43
|
*
|
|
49
44
|
* @example
|
|
50
|
-
* Input:
|
|
51
|
-
* - bulletList
|
|
52
|
-
* - listItem "A"
|
|
53
|
-
* - listItem "B"
|
|
54
|
-
* - bulletList
|
|
55
|
-
* - listItem "C"
|
|
56
|
-
* - listItem "D"
|
|
57
|
-
* - listItem "E"
|
|
58
|
-
*
|
|
59
|
-
* Output:
|
|
60
|
-
* - bulletList
|
|
61
|
-
* - listItem "A"
|
|
62
|
-
* - listItem "B"
|
|
63
|
-
* - listItem "C"
|
|
64
|
-
* - listItem "D"
|
|
65
|
-
* - listItem "E"
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
45
|
* Input (deeply nested):
|
|
69
46
|
* - bulletList
|
|
70
47
|
* - listItem "1"
|
|
@@ -95,7 +72,7 @@ export var flattenListStep = function flattenListStep(nodes, context) {
|
|
|
95
72
|
if (listTypes.some(function (type) {
|
|
96
73
|
return node.type === type;
|
|
97
74
|
})) {
|
|
98
|
-
return node.copy(Fragment.from(extractNestedLists(node, listTypes, [context.schema.nodes.listItem, context.schema.nodes.taskItem])));
|
|
75
|
+
return node.copy(Fragment.from(extractNestedLists(node, listTypes, [context.schema.nodes.listItem, context.schema.nodes.taskItem], context.schema)));
|
|
99
76
|
}
|
|
100
77
|
return node;
|
|
101
78
|
});
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
2
|
/**
|
|
3
|
-
* Given an array of nodes,
|
|
3
|
+
* Given an array of nodes, processes each list removing all parent list nodes and
|
|
4
|
+
* just returning their child contents.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* Input:
|
|
8
|
+
* - bulletList
|
|
9
|
+
* - listItem "1"
|
|
10
|
+
* - paragraph "1"
|
|
11
|
+
* - listItem "2"
|
|
12
|
+
* - paragraph "2"
|
|
13
|
+
*
|
|
14
|
+
* Output:
|
|
15
|
+
* - paragraph "1"
|
|
16
|
+
* - paragraph "2"
|
|
17
|
+
*
|
|
4
18
|
* @param nodes
|
|
19
|
+
* @param context
|
|
5
20
|
* @returns
|
|
6
21
|
*/
|
|
7
22
|
export var unwrapListStep = function unwrapListStep(nodes, context) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { expandToBlockRange } from '@atlaskit/editor-common/selection';
|
|
1
2
|
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
-
import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
3
|
+
import { findParentNodeOfType, hasParentNode } from '@atlaskit/editor-prosemirror/utils';
|
|
3
4
|
import { CellSelection } from '@atlaskit/editor-tables';
|
|
4
5
|
export var getSelectedNode = function getSelectedNode(selection) {
|
|
5
6
|
if (selection instanceof NodeSelection) {
|
|
@@ -48,4 +49,32 @@ export var getTargetNodeTypeNameInContext = function getTargetNodeTypeNameInCont
|
|
|
48
49
|
return 'nestedExpand';
|
|
49
50
|
}
|
|
50
51
|
return nodeTypeName;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Use common expandToBlockRange function, but account for edge cases with lists.
|
|
56
|
+
*
|
|
57
|
+
* @param selection
|
|
58
|
+
* @param schema
|
|
59
|
+
* @returns
|
|
60
|
+
*/
|
|
61
|
+
export var expandSelectionToBlockRange = function expandSelectionToBlockRange(selection, schema) {
|
|
62
|
+
var isListInSelection = hasParentNode(function (node) {
|
|
63
|
+
return node.type === schema.nodes.bulletList || node.type === schema.nodes.orderedList;
|
|
64
|
+
})(selection);
|
|
65
|
+
var _expandToBlockRange = expandToBlockRange(selection.$from, selection.$to, function (node) {
|
|
66
|
+
if (!isListInSelection) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
if (node.type === schema.nodes.bulletList || node.type === schema.nodes.orderedList) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
}),
|
|
74
|
+
$from = _expandToBlockRange.$from,
|
|
75
|
+
$to = _expandToBlockRange.$to;
|
|
76
|
+
return {
|
|
77
|
+
$from: $from,
|
|
78
|
+
$to: $to
|
|
79
|
+
};
|
|
51
80
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { expandToBlockRange } from '@atlaskit/editor-common/selection';
|
|
2
1
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
3
2
|
import { isNestedNode } from '../ui/utils/isNestedNode';
|
|
4
3
|
import { getOutputNodes } from './transform-node-utils/transform';
|
|
4
|
+
import { expandSelectionToBlockRange } from './transform-node-utils/utils';
|
|
5
5
|
import { isListNode } from './transforms/utils';
|
|
6
6
|
export var transformNode = function transformNode(api) {
|
|
7
7
|
return (
|
|
@@ -14,9 +14,9 @@ export var transformNode = function transformNode(api) {
|
|
|
14
14
|
if (!preservedSelection) {
|
|
15
15
|
return tr;
|
|
16
16
|
}
|
|
17
|
-
var
|
|
18
|
-
$from =
|
|
19
|
-
$to =
|
|
17
|
+
var _expandSelectionToBlo = expandSelectionToBlockRange(preservedSelection, tr.doc.type.schema),
|
|
18
|
+
$from = _expandSelectionToBlo.$from,
|
|
19
|
+
$to = _expandSelectionToBlo.$to;
|
|
20
20
|
var isNested = isNestedNode(preservedSelection, '');
|
|
21
21
|
var selectedParent = $from.parent;
|
|
22
22
|
var fragment = Fragment.empty;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
|
+
var _TRANSFORM_SUGGESTED_;
|
|
4
|
+
/**
|
|
5
|
+
* Suggested transformations mapping for each block type.
|
|
6
|
+
* Based on the Block Menu Compatibility Matrix:
|
|
7
|
+
* https://hello.atlassian.net/wiki/spaces/egcuc/pages/5868774224/Block+Menu+Compatibility+Matrix#Suggested-for-each-block-type
|
|
8
|
+
*
|
|
9
|
+
* This mapping defines which transform items should appear in the TRANSFORM_SUGGESTED_MENU_SECTION
|
|
10
|
+
* for each block type, ranked by priority (lower rank = higher priority).
|
|
11
|
+
*
|
|
12
|
+
* Structure:
|
|
13
|
+
* {
|
|
14
|
+
* [sourceNodeType]: {
|
|
15
|
+
* [targetMenuItemKey]: rank
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { TRANSFORM_STRUCTURE_PANEL_MENU_ITEM, TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM, TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM, TRANSFORM_STRUCTURE_QUOTE_MENU_ITEM, TRANSFORM_STRUCTURE_CODE_BLOCK_MENU_ITEM, TRANSFORM_STRUCTURE_BULLETED_LIST_MENU_ITEM, TRANSFORM_STRUCTURE_NUMBERED_LIST_MENU_ITEM, TRANSFORM_STRUCTURE_TASK_LIST_MENU_ITEM, TRANSFORM_HEADINGS_H2_MENU_ITEM, TRANSFORM_HEADINGS_H3_MENU_ITEM, TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM } from '@atlaskit/editor-common/block-menu';
|
|
21
|
+
/**
|
|
22
|
+
* Node type keys that map to ProseMirror node types from the ADF schema.
|
|
23
|
+
* These values must match the NodeTypeName type.
|
|
24
|
+
*
|
|
25
|
+
* TypeScript will enforce that all values are valid NodeTypeName values.
|
|
26
|
+
* If a new node type is added, it must be added to NodeTypeName first.
|
|
27
|
+
*
|
|
28
|
+
* Reference: packages/editor/editor-plugin-block-menu/src/editor-commands/transform-node-utils/types.ts
|
|
29
|
+
*
|
|
30
|
+
* Note: 'heading' represents all heading levels (1-6) as a single node type.
|
|
31
|
+
* The specific level is determined by the node's `attrs.level` property at runtime.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Usage:
|
|
35
|
+
* const nodeType = BLOCK_MENU_NODE_TYPES.PARAGRAPH; // Type: "paragraph"
|
|
36
|
+
*/
|
|
37
|
+
export var BLOCK_MENU_NODE_TYPES = {
|
|
38
|
+
PARAGRAPH: 'paragraph',
|
|
39
|
+
EXPAND: 'expand',
|
|
40
|
+
BLOCKQUOTE: 'blockquote',
|
|
41
|
+
LAYOUT_SECTION: 'layoutSection',
|
|
42
|
+
PANEL: 'panel',
|
|
43
|
+
CODE_BLOCK: 'codeBlock',
|
|
44
|
+
DECISION: 'decisionList',
|
|
45
|
+
BULLET_LIST: 'bulletList',
|
|
46
|
+
ORDERED_LIST: 'orderedList',
|
|
47
|
+
HEADING: 'heading',
|
|
48
|
+
TASK_LIST: 'taskList',
|
|
49
|
+
MEDIA_SINGLE: 'mediaSingle',
|
|
50
|
+
EXTENSION: 'extension',
|
|
51
|
+
BODIED_EXTENSION: 'bodiedExtension',
|
|
52
|
+
BLOCK_CARD: 'blockCard',
|
|
53
|
+
EMBED_CARD: 'embedCard',
|
|
54
|
+
TABLE: 'table'
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Type for node type values extracted from BLOCK_MENU_NODE_TYPES
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Type for the suggested items rank mapping
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Mapping of source node types to suggested transformation menu items with their ranks.
|
|
67
|
+
* Lower rank number = higher priority in the suggested menu section.
|
|
68
|
+
*/
|
|
69
|
+
export var TRANSFORM_SUGGESTED_ITEMS_RANK = (_TRANSFORM_SUGGESTED_ = {}, _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_TRANSFORM_SUGGESTED_, BLOCK_MENU_NODE_TYPES.PARAGRAPH, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), TRANSFORM_HEADINGS_H2_MENU_ITEM.key, 200), TRANSFORM_HEADINGS_H3_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.EXPAND, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key, 200), TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.BLOCKQUOTE, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 200), TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.LAYOUT_SECTION, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key, 200), TRANSFORM_HEADINGS_H2_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.PANEL, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_QUOTE_MENU_ITEM.key, 200), TRANSFORM_STRUCTURE_CODE_BLOCK_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.CODE_BLOCK, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key, 200), TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.DECISION, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 200), TRANSFORM_STRUCTURE_TASK_LIST_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.BULLET_LIST, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_NUMBERED_LIST_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_QUOTE_MENU_ITEM.key, 200), TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.ORDERED_LIST, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_BULLETED_LIST_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_TASK_LIST_MENU_ITEM.key, 200), TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.HEADING, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 100), TRANSFORM_HEADINGS_H2_MENU_ITEM.key, 200), TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 300)), _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_TRANSFORM_SUGGESTED_, BLOCK_MENU_NODE_TYPES.TASK_LIST, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_NUMBERED_LIST_MENU_ITEM.key, 200), TRANSFORM_STRUCTURE_CODE_BLOCK_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.MEDIA_SINGLE, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key, 200), TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.EXTENSION, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 200), TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.BODIED_EXTENSION, _defineProperty(_defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 200), TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key, 300)), BLOCK_MENU_NODE_TYPES.BLOCK_CARD, _defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 200)), BLOCK_MENU_NODE_TYPES.EMBED_CARD, _defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_PARAGRAPH_MENU_ITEM.key, 200)), BLOCK_MENU_NODE_TYPES.TABLE, _defineProperty(_defineProperty({}, TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM.key, 100), TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key, 200)));
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get suggested menu items for a given node type
|
|
73
|
+
* @param nodeType - The source node type (e.g., 'paragraph', 'heading')
|
|
74
|
+
* @returns Object mapping menu item keys to their ranks, or undefined if no suggestions
|
|
75
|
+
*/
|
|
76
|
+
export var getSuggestedItemsForNodeType = function getSuggestedItemsForNodeType(nodeType) {
|
|
77
|
+
return TRANSFORM_SUGGESTED_ITEMS_RANK[nodeType];
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get sorted suggested menu item keys for a given node type
|
|
82
|
+
* @param nodeType - The source node type
|
|
83
|
+
* @returns Array of menu item keys sorted by rank (highest priority first)
|
|
84
|
+
*/
|
|
85
|
+
export var getSortedSuggestedItems = function getSortedSuggestedItems(nodeType) {
|
|
86
|
+
var suggestions = getSuggestedItemsForNodeType(nodeType);
|
|
87
|
+
if (!suggestions) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
return Object.entries(suggestions).sort(function (_ref, _ref2) {
|
|
91
|
+
var _ref3 = _slicedToArray(_ref, 2),
|
|
92
|
+
rankA = _ref3[1];
|
|
93
|
+
var _ref4 = _slicedToArray(_ref2, 2),
|
|
94
|
+
rankB = _ref4[1];
|
|
95
|
+
return rankA - rankB;
|
|
96
|
+
}).map(function (_ref5) {
|
|
97
|
+
var _ref6 = _slicedToArray(_ref5, 1),
|
|
98
|
+
key = _ref6[0];
|
|
99
|
+
return key;
|
|
100
|
+
});
|
|
101
|
+
};
|
|
@@ -4,24 +4,6 @@ import type { TransformStep } from './types';
|
|
|
4
4
|
* to it's first ancestor list, maintaining document order.
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
|
-
* Input:
|
|
8
|
-
* - bulletList
|
|
9
|
-
* - listItem "A"
|
|
10
|
-
* - listItem "B"
|
|
11
|
-
* - bulletList
|
|
12
|
-
* - listItem "C"
|
|
13
|
-
* - listItem "D"
|
|
14
|
-
* - listItem "E"
|
|
15
|
-
*
|
|
16
|
-
* Output:
|
|
17
|
-
* - bulletList
|
|
18
|
-
* - listItem "A"
|
|
19
|
-
* - listItem "B"
|
|
20
|
-
* - listItem "C"
|
|
21
|
-
* - listItem "D"
|
|
22
|
-
* - listItem "E"
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
7
|
* Input (deeply nested):
|
|
26
8
|
* - bulletList
|
|
27
9
|
* - listItem "1"
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import type { TransformStep } from './types';
|
|
2
2
|
/**
|
|
3
|
-
* Given an array of nodes,
|
|
3
|
+
* Given an array of nodes, processes each list removing all parent list nodes and
|
|
4
|
+
* just returning their child contents.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* Input:
|
|
8
|
+
* - bulletList
|
|
9
|
+
* - listItem "1"
|
|
10
|
+
* - paragraph "1"
|
|
11
|
+
* - listItem "2"
|
|
12
|
+
* - paragraph "2"
|
|
13
|
+
*
|
|
14
|
+
* Output:
|
|
15
|
+
* - paragraph "1"
|
|
16
|
+
* - paragraph "2"
|
|
17
|
+
*
|
|
4
18
|
* @param nodes
|
|
19
|
+
* @param context
|
|
5
20
|
* @returns
|
|
6
21
|
*/
|
|
7
22
|
export declare const unwrapListStep: TransformStep;
|
|
@@ -1,5 +1,17 @@
|
|
|
1
|
+
import type { Schema } from '@atlaskit/editor-prosemirror/model';
|
|
1
2
|
import type { Selection } from '@atlaskit/editor-prosemirror/state';
|
|
2
3
|
import { type ContentNodeWithPos } from '@atlaskit/editor-prosemirror/utils';
|
|
3
4
|
import type { NodeTypeName } from './types';
|
|
4
5
|
export declare const getSelectedNode: (selection: Selection) => ContentNodeWithPos | undefined;
|
|
5
6
|
export declare const getTargetNodeTypeNameInContext: (nodeTypeName: NodeTypeName | null, isNested?: boolean) => NodeTypeName | null;
|
|
7
|
+
/**
|
|
8
|
+
* Use common expandToBlockRange function, but account for edge cases with lists.
|
|
9
|
+
*
|
|
10
|
+
* @param selection
|
|
11
|
+
* @param schema
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
export declare const expandSelectionToBlockRange: (selection: Selection, schema: Schema) => {
|
|
15
|
+
$from: import("prosemirror-model").ResolvedPos;
|
|
16
|
+
$to: import("prosemirror-model").ResolvedPos;
|
|
17
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suggested transformations mapping for each block type.
|
|
3
|
+
* Based on the Block Menu Compatibility Matrix:
|
|
4
|
+
* https://hello.atlassian.net/wiki/spaces/egcuc/pages/5868774224/Block+Menu+Compatibility+Matrix#Suggested-for-each-block-type
|
|
5
|
+
*
|
|
6
|
+
* This mapping defines which transform items should appear in the TRANSFORM_SUGGESTED_MENU_SECTION
|
|
7
|
+
* for each block type, ranked by priority (lower rank = higher priority).
|
|
8
|
+
*
|
|
9
|
+
* Structure:
|
|
10
|
+
* {
|
|
11
|
+
* [sourceNodeType]: {
|
|
12
|
+
* [targetMenuItemKey]: rank
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Node type keys that map to ProseMirror node types from the ADF schema.
|
|
18
|
+
* These values must match the NodeTypeName type.
|
|
19
|
+
*
|
|
20
|
+
* TypeScript will enforce that all values are valid NodeTypeName values.
|
|
21
|
+
* If a new node type is added, it must be added to NodeTypeName first.
|
|
22
|
+
*
|
|
23
|
+
* Reference: packages/editor/editor-plugin-block-menu/src/editor-commands/transform-node-utils/types.ts
|
|
24
|
+
*
|
|
25
|
+
* Note: 'heading' represents all heading levels (1-6) as a single node type.
|
|
26
|
+
* The specific level is determined by the node's `attrs.level` property at runtime.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // Usage:
|
|
30
|
+
* const nodeType = BLOCK_MENU_NODE_TYPES.PARAGRAPH; // Type: "paragraph"
|
|
31
|
+
*/
|
|
32
|
+
export declare const BLOCK_MENU_NODE_TYPES: {
|
|
33
|
+
readonly PARAGRAPH: "paragraph";
|
|
34
|
+
readonly EXPAND: "expand";
|
|
35
|
+
readonly BLOCKQUOTE: "blockquote";
|
|
36
|
+
readonly LAYOUT_SECTION: "layoutSection";
|
|
37
|
+
readonly PANEL: "panel";
|
|
38
|
+
readonly CODE_BLOCK: "codeBlock";
|
|
39
|
+
readonly DECISION: "decisionList";
|
|
40
|
+
readonly BULLET_LIST: "bulletList";
|
|
41
|
+
readonly ORDERED_LIST: "orderedList";
|
|
42
|
+
readonly HEADING: "heading";
|
|
43
|
+
readonly TASK_LIST: "taskList";
|
|
44
|
+
readonly MEDIA_SINGLE: "mediaSingle";
|
|
45
|
+
readonly EXTENSION: "extension";
|
|
46
|
+
readonly BODIED_EXTENSION: "bodiedExtension";
|
|
47
|
+
readonly BLOCK_CARD: "blockCard";
|
|
48
|
+
readonly EMBED_CARD: "embedCard";
|
|
49
|
+
readonly TABLE: "table";
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Type for node type values extracted from BLOCK_MENU_NODE_TYPES
|
|
53
|
+
*/
|
|
54
|
+
export type BlockMenuNodeType = (typeof BLOCK_MENU_NODE_TYPES)[keyof typeof BLOCK_MENU_NODE_TYPES];
|
|
55
|
+
/**
|
|
56
|
+
* Type for the suggested items rank mapping
|
|
57
|
+
*/
|
|
58
|
+
export type SuggestedItemsRankMap = {
|
|
59
|
+
[nodeType: string]: {
|
|
60
|
+
[menuItemKey: string]: number;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Mapping of source node types to suggested transformation menu items with their ranks.
|
|
65
|
+
* Lower rank number = higher priority in the suggested menu section.
|
|
66
|
+
*/
|
|
67
|
+
export declare const TRANSFORM_SUGGESTED_ITEMS_RANK: SuggestedItemsRankMap;
|
|
68
|
+
/**
|
|
69
|
+
* Get suggested menu items for a given node type
|
|
70
|
+
* @param nodeType - The source node type (e.g., 'paragraph', 'heading')
|
|
71
|
+
* @returns Object mapping menu item keys to their ranks, or undefined if no suggestions
|
|
72
|
+
*/
|
|
73
|
+
export declare const getSuggestedItemsForNodeType: (nodeType: string) => {
|
|
74
|
+
[menuItemKey: string]: number;
|
|
75
|
+
} | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* Get sorted suggested menu item keys for a given node type
|
|
78
|
+
* @param nodeType - The source node type
|
|
79
|
+
* @returns Array of menu item keys sorted by rank (highest priority first)
|
|
80
|
+
*/
|
|
81
|
+
export declare const getSortedSuggestedItems: (nodeType: string) => string[];
|
|
@@ -4,24 +4,6 @@ import type { TransformStep } from './types';
|
|
|
4
4
|
* to it's first ancestor list, maintaining document order.
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
|
-
* Input:
|
|
8
|
-
* - bulletList
|
|
9
|
-
* - listItem "A"
|
|
10
|
-
* - listItem "B"
|
|
11
|
-
* - bulletList
|
|
12
|
-
* - listItem "C"
|
|
13
|
-
* - listItem "D"
|
|
14
|
-
* - listItem "E"
|
|
15
|
-
*
|
|
16
|
-
* Output:
|
|
17
|
-
* - bulletList
|
|
18
|
-
* - listItem "A"
|
|
19
|
-
* - listItem "B"
|
|
20
|
-
* - listItem "C"
|
|
21
|
-
* - listItem "D"
|
|
22
|
-
* - listItem "E"
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
7
|
* Input (deeply nested):
|
|
26
8
|
* - bulletList
|
|
27
9
|
* - listItem "1"
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import type { TransformStep } from './types';
|
|
2
2
|
/**
|
|
3
|
-
* Given an array of nodes,
|
|
3
|
+
* Given an array of nodes, processes each list removing all parent list nodes and
|
|
4
|
+
* just returning their child contents.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* Input:
|
|
8
|
+
* - bulletList
|
|
9
|
+
* - listItem "1"
|
|
10
|
+
* - paragraph "1"
|
|
11
|
+
* - listItem "2"
|
|
12
|
+
* - paragraph "2"
|
|
13
|
+
*
|
|
14
|
+
* Output:
|
|
15
|
+
* - paragraph "1"
|
|
16
|
+
* - paragraph "2"
|
|
17
|
+
*
|
|
4
18
|
* @param nodes
|
|
19
|
+
* @param context
|
|
5
20
|
* @returns
|
|
6
21
|
*/
|
|
7
22
|
export declare const unwrapListStep: TransformStep;
|
|
@@ -1,5 +1,17 @@
|
|
|
1
|
+
import type { Schema } from '@atlaskit/editor-prosemirror/model';
|
|
1
2
|
import type { Selection } from '@atlaskit/editor-prosemirror/state';
|
|
2
3
|
import { type ContentNodeWithPos } from '@atlaskit/editor-prosemirror/utils';
|
|
3
4
|
import type { NodeTypeName } from './types';
|
|
4
5
|
export declare const getSelectedNode: (selection: Selection) => ContentNodeWithPos | undefined;
|
|
5
6
|
export declare const getTargetNodeTypeNameInContext: (nodeTypeName: NodeTypeName | null, isNested?: boolean) => NodeTypeName | null;
|
|
7
|
+
/**
|
|
8
|
+
* Use common expandToBlockRange function, but account for edge cases with lists.
|
|
9
|
+
*
|
|
10
|
+
* @param selection
|
|
11
|
+
* @param schema
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
export declare const expandSelectionToBlockRange: (selection: Selection, schema: Schema) => {
|
|
15
|
+
$from: import("prosemirror-model").ResolvedPos;
|
|
16
|
+
$to: import("prosemirror-model").ResolvedPos;
|
|
17
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suggested transformations mapping for each block type.
|
|
3
|
+
* Based on the Block Menu Compatibility Matrix:
|
|
4
|
+
* https://hello.atlassian.net/wiki/spaces/egcuc/pages/5868774224/Block+Menu+Compatibility+Matrix#Suggested-for-each-block-type
|
|
5
|
+
*
|
|
6
|
+
* This mapping defines which transform items should appear in the TRANSFORM_SUGGESTED_MENU_SECTION
|
|
7
|
+
* for each block type, ranked by priority (lower rank = higher priority).
|
|
8
|
+
*
|
|
9
|
+
* Structure:
|
|
10
|
+
* {
|
|
11
|
+
* [sourceNodeType]: {
|
|
12
|
+
* [targetMenuItemKey]: rank
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Node type keys that map to ProseMirror node types from the ADF schema.
|
|
18
|
+
* These values must match the NodeTypeName type.
|
|
19
|
+
*
|
|
20
|
+
* TypeScript will enforce that all values are valid NodeTypeName values.
|
|
21
|
+
* If a new node type is added, it must be added to NodeTypeName first.
|
|
22
|
+
*
|
|
23
|
+
* Reference: packages/editor/editor-plugin-block-menu/src/editor-commands/transform-node-utils/types.ts
|
|
24
|
+
*
|
|
25
|
+
* Note: 'heading' represents all heading levels (1-6) as a single node type.
|
|
26
|
+
* The specific level is determined by the node's `attrs.level` property at runtime.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // Usage:
|
|
30
|
+
* const nodeType = BLOCK_MENU_NODE_TYPES.PARAGRAPH; // Type: "paragraph"
|
|
31
|
+
*/
|
|
32
|
+
export declare const BLOCK_MENU_NODE_TYPES: {
|
|
33
|
+
readonly PARAGRAPH: "paragraph";
|
|
34
|
+
readonly EXPAND: "expand";
|
|
35
|
+
readonly BLOCKQUOTE: "blockquote";
|
|
36
|
+
readonly LAYOUT_SECTION: "layoutSection";
|
|
37
|
+
readonly PANEL: "panel";
|
|
38
|
+
readonly CODE_BLOCK: "codeBlock";
|
|
39
|
+
readonly DECISION: "decisionList";
|
|
40
|
+
readonly BULLET_LIST: "bulletList";
|
|
41
|
+
readonly ORDERED_LIST: "orderedList";
|
|
42
|
+
readonly HEADING: "heading";
|
|
43
|
+
readonly TASK_LIST: "taskList";
|
|
44
|
+
readonly MEDIA_SINGLE: "mediaSingle";
|
|
45
|
+
readonly EXTENSION: "extension";
|
|
46
|
+
readonly BODIED_EXTENSION: "bodiedExtension";
|
|
47
|
+
readonly BLOCK_CARD: "blockCard";
|
|
48
|
+
readonly EMBED_CARD: "embedCard";
|
|
49
|
+
readonly TABLE: "table";
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Type for node type values extracted from BLOCK_MENU_NODE_TYPES
|
|
53
|
+
*/
|
|
54
|
+
export type BlockMenuNodeType = (typeof BLOCK_MENU_NODE_TYPES)[keyof typeof BLOCK_MENU_NODE_TYPES];
|
|
55
|
+
/**
|
|
56
|
+
* Type for the suggested items rank mapping
|
|
57
|
+
*/
|
|
58
|
+
export type SuggestedItemsRankMap = {
|
|
59
|
+
[nodeType: string]: {
|
|
60
|
+
[menuItemKey: string]: number;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Mapping of source node types to suggested transformation menu items with their ranks.
|
|
65
|
+
* Lower rank number = higher priority in the suggested menu section.
|
|
66
|
+
*/
|
|
67
|
+
export declare const TRANSFORM_SUGGESTED_ITEMS_RANK: SuggestedItemsRankMap;
|
|
68
|
+
/**
|
|
69
|
+
* Get suggested menu items for a given node type
|
|
70
|
+
* @param nodeType - The source node type (e.g., 'paragraph', 'heading')
|
|
71
|
+
* @returns Object mapping menu item keys to their ranks, or undefined if no suggestions
|
|
72
|
+
*/
|
|
73
|
+
export declare const getSuggestedItemsForNodeType: (nodeType: string) => {
|
|
74
|
+
[menuItemKey: string]: number;
|
|
75
|
+
} | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* Get sorted suggested menu item keys for a given node type
|
|
78
|
+
* @param nodeType - The source node type
|
|
79
|
+
* @returns Array of menu item keys sorted by rank (highest priority first)
|
|
80
|
+
*/
|
|
81
|
+
export declare const getSortedSuggestedItems: (nodeType: string) => string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-block-menu",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.7",
|
|
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.13.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",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@babel/runtime": "^7.0.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@atlaskit/editor-common": "^110.
|
|
52
|
+
"@atlaskit/editor-common": "^110.39.0",
|
|
53
53
|
"react": "^18.2.0",
|
|
54
54
|
"react-intl-next": "npm:react-intl@^5.18.1"
|
|
55
55
|
},
|