@atlaskit/editor-plugin-block-menu 1.0.2 → 1.0.3

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.
Files changed (21) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/editor-commands/formatNode.js +1 -1
  3. package/dist/cjs/editor-commands/transforms/container-transforms.js +60 -4
  4. package/dist/cjs/editor-commands/transforms/list/transformBetweenListTypes.js +22 -26
  5. package/dist/cjs/editor-commands/transforms/list/transformToTaskList.js +44 -0
  6. package/dist/cjs/editor-commands/transforms/list-transforms.js +3 -3
  7. package/dist/es2019/editor-commands/formatNode.js +1 -1
  8. package/dist/es2019/editor-commands/transforms/container-transforms.js +64 -4
  9. package/dist/es2019/editor-commands/transforms/list/transformBetweenListTypes.js +24 -26
  10. package/dist/es2019/editor-commands/transforms/list/transformToTaskList.js +38 -0
  11. package/dist/es2019/editor-commands/transforms/list-transforms.js +3 -3
  12. package/dist/esm/editor-commands/formatNode.js +1 -1
  13. package/dist/esm/editor-commands/transforms/container-transforms.js +60 -4
  14. package/dist/esm/editor-commands/transforms/list/transformBetweenListTypes.js +22 -26
  15. package/dist/esm/editor-commands/transforms/list/transformToTaskList.js +37 -0
  16. package/dist/esm/editor-commands/transforms/list-transforms.js +3 -3
  17. package/dist/types/editor-commands/transforms/container-transforms.d.ts +1 -1
  18. package/dist/types/editor-commands/transforms/list/transformToTaskList.d.ts +10 -0
  19. package/dist/types-ts4.5/editor-commands/transforms/container-transforms.d.ts +1 -1
  20. package/dist/types-ts4.5/editor-commands/transforms/list/transformToTaskList.d.ts +10 -0
  21. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/editor-plugin-block-menu
2
2
 
3
+ ## 1.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [`3db18eece6c2f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/3db18eece6c2f) -
8
+ [ux] Adds basic conversion from expand, panel, blockquote to bulled, numbered or task list.
9
+ - Updated dependencies
10
+
3
11
  ## 1.0.2
4
12
 
5
13
  ### Patch Changes
@@ -40,7 +40,7 @@ var formatNode = exports.formatNode = function formatNode(targetType) {
40
40
  nodeToFormat = listParent.node;
41
41
  nodePos = listParent.pos;
42
42
  }
43
- } else if (paragraphOrHeadingNode) {
43
+ } else if (parentNode.node.type !== nodes.blockquote && paragraphOrHeadingNode) {
44
44
  nodeToFormat = paragraphOrHeadingNode.node;
45
45
  nodePos = paragraphOrHeadingNode.pos;
46
46
  }
@@ -50,6 +50,7 @@ var transformToContainer = exports.transformToContainer = function transformToCo
50
50
  */
51
51
  var transformContainerNode = exports.transformContainerNode = function transformContainerNode(_ref2) {
52
52
  var tr = _ref2.tr,
53
+ sourceNode = _ref2.sourceNode,
53
54
  sourcePos = _ref2.sourcePos,
54
55
  targetNodeType = _ref2.targetNodeType,
55
56
  targetAttrs = _ref2.targetAttrs;
@@ -64,7 +65,13 @@ var transformContainerNode = exports.transformContainerNode = function transform
64
65
 
65
66
  // Transform container to list type
66
67
  if ((0, _utils.isListNodeType)(targetNodeType)) {
67
- return unwrapAndConvertToList();
68
+ return unwrapAndConvertToList({
69
+ tr: tr,
70
+ sourceNode: sourceNode,
71
+ sourcePos: sourcePos,
72
+ targetNodeType: targetNodeType,
73
+ targetAttrs: targetAttrs
74
+ });
68
75
  }
69
76
 
70
77
  // Transform between container types
@@ -86,7 +93,56 @@ var unwrapAndConvertToBlockType = exports.unwrapAndConvertToBlockType = function
86
93
  /**
87
94
  * Unwrap container node and convert content to list
88
95
  */
89
- var unwrapAndConvertToList = exports.unwrapAndConvertToList = function unwrapAndConvertToList() {
90
- // Convert to list directly
91
- return null;
96
+ var unwrapAndConvertToList = exports.unwrapAndConvertToList = function unwrapAndConvertToList(_ref3) {
97
+ var tr = _ref3.tr,
98
+ sourceNode = _ref3.sourceNode,
99
+ sourcePos = _ref3.sourcePos,
100
+ targetNodeType = _ref3.targetNodeType,
101
+ targetAttrs = _ref3.targetAttrs;
102
+ if (sourcePos === null) {
103
+ return tr;
104
+ }
105
+ var schema = tr.doc.type.schema;
106
+ var _schema$nodes = schema.nodes,
107
+ listItem = _schema$nodes.listItem,
108
+ paragraph = _schema$nodes.paragraph,
109
+ taskList = _schema$nodes.taskList,
110
+ taskItem = _schema$nodes.taskItem;
111
+ var isTargetTaskList = targetNodeType === taskList;
112
+ var createListItemFromInline = function createListItemFromInline(inlineFrag) {
113
+ return isTargetTaskList ? taskItem.create(null, inlineFrag) : listItem.create(null, paragraph.create(null, inlineFrag));
114
+ };
115
+ var getInlineContent = function getInlineContent(textblock) {
116
+ var inlineContent = [];
117
+ textblock.forEach(function (inline) {
118
+ inlineContent.push(inline);
119
+ });
120
+ return inlineContent;
121
+ };
122
+ var items = [];
123
+
124
+ // Expand's title should become the first item of the list
125
+ if (sourceNode.type.name === 'expand') {
126
+ var _sourceNode$attrs;
127
+ var title = (_sourceNode$attrs = sourceNode.attrs) === null || _sourceNode$attrs === void 0 ? void 0 : _sourceNode$attrs.title;
128
+ if (title) {
129
+ var titleContent = schema.text(title);
130
+ items.push(isTargetTaskList ? taskItem.create(null, titleContent) : listItem.create(null, paragraph.create(null, titleContent)));
131
+ }
132
+ }
133
+ for (var i = 0; i < sourceNode.childCount; i++) {
134
+ var node = sourceNode.child(i);
135
+
136
+ // Abort early if unsupported content (e.g. table) encounted inside of the container
137
+ if (!node.isTextblock) {
138
+ return tr;
139
+ }
140
+ var inline = _model.Fragment.from(getInlineContent(node));
141
+ items.push(createListItemFromInline(inline));
142
+ }
143
+ if (!items.length) {
144
+ return tr;
145
+ }
146
+ var list = targetNodeType.create(targetAttrs || null, _model.Fragment.from(items));
147
+ return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, list);
92
148
  };
@@ -7,14 +7,25 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.transformListStructure = void 0;
8
8
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
9
  /**
10
- * Extract all inline content from a node
10
+ * Convert a block node to inline content suitable for task items
11
11
  */
12
- var extractInlineContent = function extractInlineContent(node) {
13
- var inlineContent = [];
14
- for (var i = 0; i < node.childCount; i++) {
15
- inlineContent.push(node.child(i));
12
+ var convertBlockToInlineContent = function convertBlockToInlineContent(node, schema) {
13
+ var paragraph = schema.nodes.paragraph;
14
+ if (node.type === paragraph) {
15
+ // Extract inline content from paragraphs
16
+ return (0, _toConsumableArray2.default)(node.content.content);
17
+ } else if (node.isBlock) {
18
+ // For other block content types eg. codeBlock, extract their text content and create text nodes
19
+ var textContent = node.textContent;
20
+ if (textContent) {
21
+ var textNode = schema.text(textContent);
22
+ return [textNode];
23
+ }
24
+ } else {
25
+ // Already inline content, add directly
26
+ return [node];
16
27
  }
17
- return inlineContent;
28
+ return [];
18
29
  };
19
30
 
20
31
  /**
@@ -48,25 +59,10 @@ var transformListStructure = exports.transformListStructure = function transform
48
59
  // Extract inline content from all children within listItem
49
60
  if (node.type === listItem) {
50
61
  var inlineContent = [];
51
-
52
- // Extract all inline content from all child nodes
53
- for (var i = 0; i < node.childCount; i++) {
54
- var child = node.child(i);
55
- if (child.type === paragraph) {
56
- // Extract inline content from paragraphs
57
- inlineContent.push.apply(inlineContent, (0, _toConsumableArray2.default)(extractInlineContent(child)));
58
- } else if (child.isBlock) {
59
- // For other block content types eg. codeBlock, extract their text content and create text nodes
60
- var textContent = child.textContent;
61
- if (textContent) {
62
- var textNode = tr.doc.type.schema.text(textContent);
63
- inlineContent.push(textNode);
64
- }
65
- } else {
66
- // Already inline content, add directly
67
- inlineContent.push(child);
68
- }
69
- }
62
+ // Extract inline content from all child nodes
63
+ node.forEach(function (child) {
64
+ inlineContent.push.apply(inlineContent, (0, _toConsumableArray2.default)(convertBlockToInlineContent(child, tr.doc.type.schema)));
65
+ });
70
66
  if (inlineContent.length > 0) {
71
67
  var newItem = taskItem.create(null, inlineContent);
72
68
  newListItems.push(newItem);
@@ -76,7 +72,7 @@ var transformListStructure = exports.transformListStructure = function transform
76
72
  // Converting from task list to bullet/ordered list
77
73
  // Structure: taskItem > inline content -> listItem > paragraph > inline content
78
74
  if (node.type === taskItem) {
79
- var _inlineContent = extractInlineContent(node);
75
+ var _inlineContent = (0, _toConsumableArray2.default)(node.content.content);
80
76
  if (_inlineContent.length > 0) {
81
77
  var paragraphNode = paragraph.create(null, _inlineContent);
82
78
  var newListItem = listItem.create(null, paragraphNode);
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.transformToTaskList = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ /**
10
+ * Transform selection to task list
11
+ * Handles the special structure where taskItem contains text directly (no paragraph wrapper)
12
+ */
13
+ var transformToTaskList = exports.transformToTaskList = function transformToTaskList(tr, range, targetNodeType, targetAttrs, nodes) {
14
+ try {
15
+ var taskItem = nodes.taskItem;
16
+ var listItems = [];
17
+
18
+ // Process each block in the range
19
+ tr.doc.nodesBetween(range.start, range.end, function (node) {
20
+ if (node.isBlock) {
21
+ // For block nodes like paragraphs, directly use their inline content
22
+ var inlineContent = (0, _toConsumableArray2.default)(node.content.content);
23
+ if (inlineContent.length > 0) {
24
+ // Create task item with inline content directly
25
+ var listItem = taskItem.create(targetAttrs, inlineContent);
26
+ listItems.push(listItem);
27
+ }
28
+ }
29
+ return false; // Don't traverse into children
30
+ });
31
+ if (listItems.length === 0) {
32
+ return null;
33
+ }
34
+
35
+ // Create the new task list
36
+ var newList = targetNodeType.create(targetAttrs, listItems);
37
+
38
+ // Replace the range with the new list
39
+ tr.replaceWith(range.start, range.end, newList);
40
+ return tr;
41
+ } catch (_unused) {
42
+ return null;
43
+ }
44
+ };
@@ -9,12 +9,14 @@ var _utils = require("@atlaskit/editor-prosemirror/utils");
9
9
  var _transformBetweenListTypes = require("./list/transformBetweenListTypes");
10
10
  var _transformOrderedUnorderedListToBlockNodes = require("./list/transformOrderedUnorderedListToBlockNodes");
11
11
  var _transformTaskListToBlockNodes = require("./list/transformTaskListToBlockNodes");
12
+ var _transformToTaskList = require("./list/transformToTaskList");
12
13
  var _utils2 = require("./utils");
13
14
  /**
14
15
  * Transform selection to list type
15
16
  */
16
17
  var transformBlockToList = exports.transformBlockToList = function transformBlockToList(context) {
17
18
  var tr = context.tr,
19
+ sourceNode = context.sourceNode,
18
20
  targetNodeType = context.targetNodeType,
19
21
  targetAttrs = context.targetAttrs;
20
22
  var _tr$selection = tr.selection,
@@ -28,13 +30,11 @@ var transformBlockToList = exports.transformBlockToList = function transformBloc
28
30
  var isTargetTask = targetNodeType === nodes.taskList;
29
31
 
30
32
  // Handle task lists differently due to their structure
31
- // TODO: ED-29152 - Implement task list transformation
32
33
  if (isTargetTask) {
33
- return null;
34
+ return (0, _transformToTaskList.transformToTaskList)(tr, range, targetNodeType, targetAttrs, nodes);
34
35
  }
35
36
 
36
37
  // For headings, convert to paragraph first since headings cannot be direct children of list items
37
- var sourceNode = tr.doc.nodeAt(range.start);
38
38
  if (sourceNode && sourceNode.type.name.startsWith('heading')) {
39
39
  tr.setBlockType(range.start, range.end, nodes.paragraph);
40
40
  }
@@ -39,7 +39,7 @@ export const formatNode = targetType => {
39
39
  nodeToFormat = listParent.node;
40
40
  nodePos = listParent.pos;
41
41
  }
42
- } else if (paragraphOrHeadingNode) {
42
+ } else if (parentNode.node.type !== nodes.blockquote && paragraphOrHeadingNode) {
43
43
  nodeToFormat = paragraphOrHeadingNode.node;
44
44
  nodePos = paragraphOrHeadingNode.pos;
45
45
  }
@@ -45,6 +45,7 @@ export const transformToContainer = ({
45
45
  */
46
46
  export const transformContainerNode = ({
47
47
  tr,
48
+ sourceNode,
48
49
  sourcePos,
49
50
  targetNodeType,
50
51
  targetAttrs
@@ -60,7 +61,13 @@ export const transformContainerNode = ({
60
61
 
61
62
  // Transform container to list type
62
63
  if (isListNodeType(targetNodeType)) {
63
- return unwrapAndConvertToList();
64
+ return unwrapAndConvertToList({
65
+ tr,
66
+ sourceNode,
67
+ sourcePos,
68
+ targetNodeType,
69
+ targetAttrs
70
+ });
64
71
  }
65
72
 
66
73
  // Transform between container types
@@ -82,7 +89,60 @@ export const unwrapAndConvertToBlockType = () => {
82
89
  /**
83
90
  * Unwrap container node and convert content to list
84
91
  */
85
- export const unwrapAndConvertToList = () => {
86
- // Convert to list directly
87
- return null;
92
+ export const unwrapAndConvertToList = ({
93
+ tr,
94
+ sourceNode,
95
+ sourcePos,
96
+ targetNodeType,
97
+ targetAttrs
98
+ }) => {
99
+ if (sourcePos === null) {
100
+ return tr;
101
+ }
102
+ const {
103
+ schema
104
+ } = tr.doc.type;
105
+ const {
106
+ listItem,
107
+ paragraph,
108
+ taskList,
109
+ taskItem
110
+ } = schema.nodes;
111
+ const isTargetTaskList = targetNodeType === taskList;
112
+ const createListItemFromInline = inlineFrag => {
113
+ return isTargetTaskList ? taskItem.create(null, inlineFrag) : listItem.create(null, paragraph.create(null, inlineFrag));
114
+ };
115
+ const getInlineContent = textblock => {
116
+ const inlineContent = [];
117
+ textblock.forEach(inline => {
118
+ inlineContent.push(inline);
119
+ });
120
+ return inlineContent;
121
+ };
122
+ const items = [];
123
+
124
+ // Expand's title should become the first item of the list
125
+ if (sourceNode.type.name === 'expand') {
126
+ var _sourceNode$attrs;
127
+ const title = (_sourceNode$attrs = sourceNode.attrs) === null || _sourceNode$attrs === void 0 ? void 0 : _sourceNode$attrs.title;
128
+ if (title) {
129
+ const titleContent = schema.text(title);
130
+ items.push(isTargetTaskList ? taskItem.create(null, titleContent) : listItem.create(null, paragraph.create(null, titleContent)));
131
+ }
132
+ }
133
+ for (let i = 0; i < sourceNode.childCount; i++) {
134
+ const node = sourceNode.child(i);
135
+
136
+ // Abort early if unsupported content (e.g. table) encounted inside of the container
137
+ if (!node.isTextblock) {
138
+ return tr;
139
+ }
140
+ const inline = Fragment.from(getInlineContent(node));
141
+ items.push(createListItemFromInline(inline));
142
+ }
143
+ if (!items.length) {
144
+ return tr;
145
+ }
146
+ const list = targetNodeType.create(targetAttrs || null, Fragment.from(items));
147
+ return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, list);
88
148
  };
@@ -1,12 +1,25 @@
1
1
  /**
2
- * Extract all inline content from a node
2
+ * Convert a block node to inline content suitable for task items
3
3
  */
4
- const extractInlineContent = node => {
5
- const inlineContent = [];
6
- for (let i = 0; i < node.childCount; i++) {
7
- inlineContent.push(node.child(i));
4
+ const convertBlockToInlineContent = (node, schema) => {
5
+ const {
6
+ paragraph
7
+ } = schema.nodes;
8
+ if (node.type === paragraph) {
9
+ // Extract inline content from paragraphs
10
+ return [...node.content.content];
11
+ } else if (node.isBlock) {
12
+ // For other block content types eg. codeBlock, extract their text content and create text nodes
13
+ const textContent = node.textContent;
14
+ if (textContent) {
15
+ const textNode = schema.text(textContent);
16
+ return [textNode];
17
+ }
18
+ } else {
19
+ // Already inline content, add directly
20
+ return [node];
8
21
  }
9
- return inlineContent;
22
+ return [];
10
23
  };
11
24
 
12
25
  /**
@@ -44,25 +57,10 @@ export const transformListStructure = (tr, listNode, targetNodeType, nodes) => {
44
57
  // Extract inline content from all children within listItem
45
58
  if (node.type === listItem) {
46
59
  const inlineContent = [];
47
-
48
- // Extract all inline content from all child nodes
49
- for (let i = 0; i < node.childCount; i++) {
50
- const child = node.child(i);
51
- if (child.type === paragraph) {
52
- // Extract inline content from paragraphs
53
- inlineContent.push(...extractInlineContent(child));
54
- } else if (child.isBlock) {
55
- // For other block content types eg. codeBlock, extract their text content and create text nodes
56
- const textContent = child.textContent;
57
- if (textContent) {
58
- const textNode = tr.doc.type.schema.text(textContent);
59
- inlineContent.push(textNode);
60
- }
61
- } else {
62
- // Already inline content, add directly
63
- inlineContent.push(child);
64
- }
65
- }
60
+ // Extract inline content from all child nodes
61
+ node.forEach(child => {
62
+ inlineContent.push(...convertBlockToInlineContent(child, tr.doc.type.schema));
63
+ });
66
64
  if (inlineContent.length > 0) {
67
65
  const newItem = taskItem.create(null, inlineContent);
68
66
  newListItems.push(newItem);
@@ -72,7 +70,7 @@ export const transformListStructure = (tr, listNode, targetNodeType, nodes) => {
72
70
  // Converting from task list to bullet/ordered list
73
71
  // Structure: taskItem > inline content -> listItem > paragraph > inline content
74
72
  if (node.type === taskItem) {
75
- const inlineContent = extractInlineContent(node);
73
+ const inlineContent = [...node.content.content];
76
74
  if (inlineContent.length > 0) {
77
75
  const paragraphNode = paragraph.create(null, inlineContent);
78
76
  const newListItem = listItem.create(null, paragraphNode);
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Transform selection to task list
3
+ * Handles the special structure where taskItem contains text directly (no paragraph wrapper)
4
+ */
5
+ export const transformToTaskList = (tr, range, targetNodeType, targetAttrs, nodes) => {
6
+ try {
7
+ const {
8
+ taskItem
9
+ } = nodes;
10
+ const listItems = [];
11
+
12
+ // Process each block in the range
13
+ tr.doc.nodesBetween(range.start, range.end, node => {
14
+ if (node.isBlock) {
15
+ // For block nodes like paragraphs, directly use their inline content
16
+ const inlineContent = [...node.content.content];
17
+ if (inlineContent.length > 0) {
18
+ // Create task item with inline content directly
19
+ const listItem = taskItem.create(targetAttrs, inlineContent);
20
+ listItems.push(listItem);
21
+ }
22
+ }
23
+ return false; // Don't traverse into children
24
+ });
25
+ if (listItems.length === 0) {
26
+ return null;
27
+ }
28
+
29
+ // Create the new task list
30
+ const newList = targetNodeType.create(targetAttrs, listItems);
31
+
32
+ // Replace the range with the new list
33
+ tr.replaceWith(range.start, range.end, newList);
34
+ return tr;
35
+ } catch {
36
+ return null;
37
+ }
38
+ };
@@ -3,6 +3,7 @@ import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
3
3
  import { transformListStructure } from './list/transformBetweenListTypes';
4
4
  import { transformOrderedUnorderedListToBlockNodes } from './list/transformOrderedUnorderedListToBlockNodes';
5
5
  import { transformTaskListToBlockNodes } from './list/transformTaskListToBlockNodes';
6
+ import { transformToTaskList } from './list/transformToTaskList';
6
7
  import { isBlockNodeType, isContainerNodeType, isListNodeType } from './utils';
7
8
 
8
9
  /**
@@ -11,6 +12,7 @@ import { isBlockNodeType, isContainerNodeType, isListNodeType } from './utils';
11
12
  export const transformBlockToList = context => {
12
13
  const {
13
14
  tr,
15
+ sourceNode,
14
16
  targetNodeType,
15
17
  targetAttrs
16
18
  } = context;
@@ -28,13 +30,11 @@ export const transformBlockToList = context => {
28
30
  const isTargetTask = targetNodeType === nodes.taskList;
29
31
 
30
32
  // Handle task lists differently due to their structure
31
- // TODO: ED-29152 - Implement task list transformation
32
33
  if (isTargetTask) {
33
- return null;
34
+ return transformToTaskList(tr, range, targetNodeType, targetAttrs, nodes);
34
35
  }
35
36
 
36
37
  // For headings, convert to paragraph first since headings cannot be direct children of list items
37
- const sourceNode = tr.doc.nodeAt(range.start);
38
38
  if (sourceNode && sourceNode.type.name.startsWith('heading')) {
39
39
  tr.setBlockType(range.start, range.end, nodes.paragraph);
40
40
  }
@@ -34,7 +34,7 @@ export var formatNode = function formatNode(targetType) {
34
34
  nodeToFormat = listParent.node;
35
35
  nodePos = listParent.pos;
36
36
  }
37
- } else if (paragraphOrHeadingNode) {
37
+ } else if (parentNode.node.type !== nodes.blockquote && paragraphOrHeadingNode) {
38
38
  nodeToFormat = paragraphOrHeadingNode.node;
39
39
  nodePos = paragraphOrHeadingNode.pos;
40
40
  }
@@ -44,6 +44,7 @@ export var transformToContainer = function transformToContainer(_ref) {
44
44
  */
45
45
  export var transformContainerNode = function transformContainerNode(_ref2) {
46
46
  var tr = _ref2.tr,
47
+ sourceNode = _ref2.sourceNode,
47
48
  sourcePos = _ref2.sourcePos,
48
49
  targetNodeType = _ref2.targetNodeType,
49
50
  targetAttrs = _ref2.targetAttrs;
@@ -58,7 +59,13 @@ export var transformContainerNode = function transformContainerNode(_ref2) {
58
59
 
59
60
  // Transform container to list type
60
61
  if (isListNodeType(targetNodeType)) {
61
- return unwrapAndConvertToList();
62
+ return unwrapAndConvertToList({
63
+ tr: tr,
64
+ sourceNode: sourceNode,
65
+ sourcePos: sourcePos,
66
+ targetNodeType: targetNodeType,
67
+ targetAttrs: targetAttrs
68
+ });
62
69
  }
63
70
 
64
71
  // Transform between container types
@@ -80,7 +87,56 @@ export var unwrapAndConvertToBlockType = function unwrapAndConvertToBlockType()
80
87
  /**
81
88
  * Unwrap container node and convert content to list
82
89
  */
83
- export var unwrapAndConvertToList = function unwrapAndConvertToList() {
84
- // Convert to list directly
85
- return null;
90
+ export var unwrapAndConvertToList = function unwrapAndConvertToList(_ref3) {
91
+ var tr = _ref3.tr,
92
+ sourceNode = _ref3.sourceNode,
93
+ sourcePos = _ref3.sourcePos,
94
+ targetNodeType = _ref3.targetNodeType,
95
+ targetAttrs = _ref3.targetAttrs;
96
+ if (sourcePos === null) {
97
+ return tr;
98
+ }
99
+ var schema = tr.doc.type.schema;
100
+ var _schema$nodes = schema.nodes,
101
+ listItem = _schema$nodes.listItem,
102
+ paragraph = _schema$nodes.paragraph,
103
+ taskList = _schema$nodes.taskList,
104
+ taskItem = _schema$nodes.taskItem;
105
+ var isTargetTaskList = targetNodeType === taskList;
106
+ var createListItemFromInline = function createListItemFromInline(inlineFrag) {
107
+ return isTargetTaskList ? taskItem.create(null, inlineFrag) : listItem.create(null, paragraph.create(null, inlineFrag));
108
+ };
109
+ var getInlineContent = function getInlineContent(textblock) {
110
+ var inlineContent = [];
111
+ textblock.forEach(function (inline) {
112
+ inlineContent.push(inline);
113
+ });
114
+ return inlineContent;
115
+ };
116
+ var items = [];
117
+
118
+ // Expand's title should become the first item of the list
119
+ if (sourceNode.type.name === 'expand') {
120
+ var _sourceNode$attrs;
121
+ var title = (_sourceNode$attrs = sourceNode.attrs) === null || _sourceNode$attrs === void 0 ? void 0 : _sourceNode$attrs.title;
122
+ if (title) {
123
+ var titleContent = schema.text(title);
124
+ items.push(isTargetTaskList ? taskItem.create(null, titleContent) : listItem.create(null, paragraph.create(null, titleContent)));
125
+ }
126
+ }
127
+ for (var i = 0; i < sourceNode.childCount; i++) {
128
+ var node = sourceNode.child(i);
129
+
130
+ // Abort early if unsupported content (e.g. table) encounted inside of the container
131
+ if (!node.isTextblock) {
132
+ return tr;
133
+ }
134
+ var inline = Fragment.from(getInlineContent(node));
135
+ items.push(createListItemFromInline(inline));
136
+ }
137
+ if (!items.length) {
138
+ return tr;
139
+ }
140
+ var list = targetNodeType.create(targetAttrs || null, Fragment.from(items));
141
+ return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, list);
86
142
  };
@@ -1,13 +1,24 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  /**
3
- * Extract all inline content from a node
3
+ * Convert a block node to inline content suitable for task items
4
4
  */
5
- var extractInlineContent = function extractInlineContent(node) {
6
- var inlineContent = [];
7
- for (var i = 0; i < node.childCount; i++) {
8
- inlineContent.push(node.child(i));
5
+ var convertBlockToInlineContent = function convertBlockToInlineContent(node, schema) {
6
+ var paragraph = schema.nodes.paragraph;
7
+ if (node.type === paragraph) {
8
+ // Extract inline content from paragraphs
9
+ return _toConsumableArray(node.content.content);
10
+ } else if (node.isBlock) {
11
+ // For other block content types eg. codeBlock, extract their text content and create text nodes
12
+ var textContent = node.textContent;
13
+ if (textContent) {
14
+ var textNode = schema.text(textContent);
15
+ return [textNode];
16
+ }
17
+ } else {
18
+ // Already inline content, add directly
19
+ return [node];
9
20
  }
10
- return inlineContent;
21
+ return [];
11
22
  };
12
23
 
13
24
  /**
@@ -41,25 +52,10 @@ export var transformListStructure = function transformListStructure(tr, listNode
41
52
  // Extract inline content from all children within listItem
42
53
  if (node.type === listItem) {
43
54
  var inlineContent = [];
44
-
45
- // Extract all inline content from all child nodes
46
- for (var i = 0; i < node.childCount; i++) {
47
- var child = node.child(i);
48
- if (child.type === paragraph) {
49
- // Extract inline content from paragraphs
50
- inlineContent.push.apply(inlineContent, _toConsumableArray(extractInlineContent(child)));
51
- } else if (child.isBlock) {
52
- // For other block content types eg. codeBlock, extract their text content and create text nodes
53
- var textContent = child.textContent;
54
- if (textContent) {
55
- var textNode = tr.doc.type.schema.text(textContent);
56
- inlineContent.push(textNode);
57
- }
58
- } else {
59
- // Already inline content, add directly
60
- inlineContent.push(child);
61
- }
62
- }
55
+ // Extract inline content from all child nodes
56
+ node.forEach(function (child) {
57
+ inlineContent.push.apply(inlineContent, _toConsumableArray(convertBlockToInlineContent(child, tr.doc.type.schema)));
58
+ });
63
59
  if (inlineContent.length > 0) {
64
60
  var newItem = taskItem.create(null, inlineContent);
65
61
  newListItems.push(newItem);
@@ -69,7 +65,7 @@ export var transformListStructure = function transformListStructure(tr, listNode
69
65
  // Converting from task list to bullet/ordered list
70
66
  // Structure: taskItem > inline content -> listItem > paragraph > inline content
71
67
  if (node.type === taskItem) {
72
- var _inlineContent = extractInlineContent(node);
68
+ var _inlineContent = _toConsumableArray(node.content.content);
73
69
  if (_inlineContent.length > 0) {
74
70
  var paragraphNode = paragraph.create(null, _inlineContent);
75
71
  var newListItem = listItem.create(null, paragraphNode);
@@ -0,0 +1,37 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ /**
3
+ * Transform selection to task list
4
+ * Handles the special structure where taskItem contains text directly (no paragraph wrapper)
5
+ */
6
+ export var transformToTaskList = function transformToTaskList(tr, range, targetNodeType, targetAttrs, nodes) {
7
+ try {
8
+ var taskItem = nodes.taskItem;
9
+ var listItems = [];
10
+
11
+ // Process each block in the range
12
+ tr.doc.nodesBetween(range.start, range.end, function (node) {
13
+ if (node.isBlock) {
14
+ // For block nodes like paragraphs, directly use their inline content
15
+ var inlineContent = _toConsumableArray(node.content.content);
16
+ if (inlineContent.length > 0) {
17
+ // Create task item with inline content directly
18
+ var listItem = taskItem.create(targetAttrs, inlineContent);
19
+ listItems.push(listItem);
20
+ }
21
+ }
22
+ return false; // Don't traverse into children
23
+ });
24
+ if (listItems.length === 0) {
25
+ return null;
26
+ }
27
+
28
+ // Create the new task list
29
+ var newList = targetNodeType.create(targetAttrs, listItems);
30
+
31
+ // Replace the range with the new list
32
+ tr.replaceWith(range.start, range.end, newList);
33
+ return tr;
34
+ } catch (_unused) {
35
+ return null;
36
+ }
37
+ };
@@ -3,6 +3,7 @@ import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
3
3
  import { transformListStructure } from './list/transformBetweenListTypes';
4
4
  import { transformOrderedUnorderedListToBlockNodes } from './list/transformOrderedUnorderedListToBlockNodes';
5
5
  import { transformTaskListToBlockNodes } from './list/transformTaskListToBlockNodes';
6
+ import { transformToTaskList } from './list/transformToTaskList';
6
7
  import { isBlockNodeType, isContainerNodeType, isListNodeType } from './utils';
7
8
 
8
9
  /**
@@ -10,6 +11,7 @@ import { isBlockNodeType, isContainerNodeType, isListNodeType } from './utils';
10
11
  */
11
12
  export var transformBlockToList = function transformBlockToList(context) {
12
13
  var tr = context.tr,
14
+ sourceNode = context.sourceNode,
13
15
  targetNodeType = context.targetNodeType,
14
16
  targetAttrs = context.targetAttrs;
15
17
  var _tr$selection = tr.selection,
@@ -23,13 +25,11 @@ export var transformBlockToList = function transformBlockToList(context) {
23
25
  var isTargetTask = targetNodeType === nodes.taskList;
24
26
 
25
27
  // Handle task lists differently due to their structure
26
- // TODO: ED-29152 - Implement task list transformation
27
28
  if (isTargetTask) {
28
- return null;
29
+ return transformToTaskList(tr, range, targetNodeType, targetAttrs, nodes);
29
30
  }
30
31
 
31
32
  // For headings, convert to paragraph first since headings cannot be direct children of list items
32
- var sourceNode = tr.doc.nodeAt(range.start);
33
33
  if (sourceNode && sourceNode.type.name.startsWith('heading')) {
34
34
  tr.setBlockType(range.start, range.end, nodes.paragraph);
35
35
  }
@@ -14,4 +14,4 @@ export declare const unwrapAndConvertToBlockType: () => null;
14
14
  /**
15
15
  * Unwrap container node and convert content to list
16
16
  */
17
- export declare const unwrapAndConvertToList: () => null;
17
+ export declare const unwrapAndConvertToList: ({ tr, sourceNode, sourcePos, targetNodeType, targetAttrs, }: TransformContext) => import("prosemirror-state").Transaction;
@@ -0,0 +1,10 @@
1
+ import type { NodeType } from '@atlaskit/editor-prosemirror/model';
2
+ import type { Transaction } from '@atlaskit/editor-prosemirror/state';
3
+ /**
4
+ * Transform selection to task list
5
+ * Handles the special structure where taskItem contains text directly (no paragraph wrapper)
6
+ */
7
+ export declare const transformToTaskList: (tr: Transaction, range: {
8
+ end: number;
9
+ start: number;
10
+ }, targetNodeType: NodeType, targetAttrs: Record<string, unknown> | undefined, nodes: Record<string, NodeType>) => Transaction | null;
@@ -14,4 +14,4 @@ export declare const unwrapAndConvertToBlockType: () => null;
14
14
  /**
15
15
  * Unwrap container node and convert content to list
16
16
  */
17
- export declare const unwrapAndConvertToList: () => null;
17
+ export declare const unwrapAndConvertToList: ({ tr, sourceNode, sourcePos, targetNodeType, targetAttrs, }: TransformContext) => import("prosemirror-state").Transaction;
@@ -0,0 +1,10 @@
1
+ import type { NodeType } from '@atlaskit/editor-prosemirror/model';
2
+ import type { Transaction } from '@atlaskit/editor-prosemirror/state';
3
+ /**
4
+ * Transform selection to task list
5
+ * Handles the special structure where taskItem contains text directly (no paragraph wrapper)
6
+ */
7
+ export declare const transformToTaskList: (tr: Transaction, range: {
8
+ end: number;
9
+ start: number;
10
+ }, targetNodeType: NodeType, targetAttrs: Record<string, unknown> | undefined, nodes: Record<string, NodeType>) => Transaction | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-menu",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "BlockMenu plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",