@atlaskit/editor-plugin-block-menu 5.1.11 → 5.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/editor-commands/transform-node-utils/steps/convertBulletListToTextStep.js +34 -0
  3. package/dist/cjs/editor-commands/transform-node-utils/steps/convertOrderedListToTextStep.js +62 -0
  4. package/dist/cjs/editor-commands/transform-node-utils/steps/convertTaskListToTextStep.js +39 -0
  5. package/dist/cjs/editor-commands/transform-node-utils/steps/createListToTextStep.js +90 -0
  6. package/dist/cjs/editor-commands/transform-node-utils/transform.js +27 -2
  7. package/dist/cjs/editor-commands/transform-node-utils/utils.js +25 -19
  8. package/dist/es2019/editor-commands/transform-node-utils/steps/convertBulletListToTextStep.js +27 -0
  9. package/dist/es2019/editor-commands/transform-node-utils/steps/convertOrderedListToTextStep.js +55 -0
  10. package/dist/es2019/editor-commands/transform-node-utils/steps/convertTaskListToTextStep.js +34 -0
  11. package/dist/es2019/editor-commands/transform-node-utils/steps/createListToTextStep.js +86 -0
  12. package/dist/es2019/editor-commands/transform-node-utils/transform.js +27 -2
  13. package/dist/es2019/editor-commands/transform-node-utils/utils.js +25 -16
  14. package/dist/esm/editor-commands/transform-node-utils/steps/convertBulletListToTextStep.js +29 -0
  15. package/dist/esm/editor-commands/transform-node-utils/steps/convertOrderedListToTextStep.js +57 -0
  16. package/dist/esm/editor-commands/transform-node-utils/steps/convertTaskListToTextStep.js +34 -0
  17. package/dist/esm/editor-commands/transform-node-utils/steps/createListToTextStep.js +85 -0
  18. package/dist/esm/editor-commands/transform-node-utils/transform.js +27 -2
  19. package/dist/esm/editor-commands/transform-node-utils/utils.js +26 -20
  20. package/dist/types/editor-commands/transform-node-utils/steps/convertBulletListToTextStep.d.ts +18 -0
  21. package/dist/types/editor-commands/transform-node-utils/steps/convertOrderedListToTextStep.d.ts +19 -0
  22. package/dist/types/editor-commands/transform-node-utils/steps/convertTaskListToTextStep.d.ts +22 -0
  23. package/dist/types/editor-commands/transform-node-utils/steps/createListToTextStep.d.ts +38 -0
  24. package/dist/types/editor-commands/transform-node-utils/utils.d.ts +2 -2
  25. package/dist/types-ts4.5/editor-commands/transform-node-utils/steps/convertBulletListToTextStep.d.ts +18 -0
  26. package/dist/types-ts4.5/editor-commands/transform-node-utils/steps/convertOrderedListToTextStep.d.ts +19 -0
  27. package/dist/types-ts4.5/editor-commands/transform-node-utils/steps/convertTaskListToTextStep.d.ts +22 -0
  28. package/dist/types-ts4.5/editor-commands/transform-node-utils/steps/createListToTextStep.d.ts +38 -0
  29. package/dist/types-ts4.5/editor-commands/transform-node-utils/utils.d.ts +2 -2
  30. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @atlaskit/editor-plugin-block-menu
2
2
 
3
+ ## 5.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`e1a0f13fc5c83`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/e1a0f13fc5c83) -
8
+ Editor-2778: Table transform to expand and layout
9
+ - Updated dependencies
10
+
11
+ ## 5.2.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [`0bff72d37394d`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0bff72d37394d) -
16
+ [ux] Implement steps for bullet, task, and numbered lists transformations to container nodes
17
+
18
+ ### Patch Changes
19
+
20
+ - Updated dependencies
21
+
3
22
  ## 5.1.11
4
23
 
5
24
  ### Patch Changes
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.convertBulletListToTextStep = void 0;
7
+ var _createListToTextStep = require("./createListToTextStep");
8
+ /**
9
+ * Given an array of nodes, processes each bullet list by converting its items
10
+ * to paragraphs with "- " prefix.
11
+ *
12
+ * Handles nested bullet lists recursively with 3-space indentation per level.
13
+ *
14
+ * @example
15
+ * Input:
16
+ * - bulletList()(
17
+ * listItem()(p()('Item 1')),
18
+ * bulletList()(listItem()(p()('Sub item 1')))
19
+ * )
20
+ *
21
+ * Output:
22
+ * - p()('- Item 1')
23
+ * - p()(' - Sub item 1')
24
+ */
25
+ var convertBulletListToTextStep = exports.convertBulletListToTextStep = (0, _createListToTextStep.createListToTextStep)({
26
+ listTypeName: 'bulletList',
27
+ itemTypeName: 'listItem',
28
+ indent: ' ',
29
+ // 3 spaces per nesting level
30
+ getPrefix: function getPrefix() {
31
+ return '- ';
32
+ },
33
+ unwrapParagraphContent: true
34
+ });
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.convertOrderedListToTextStep = void 0;
7
+ var _createListToTextStep = require("./createListToTextStep");
8
+ /**
9
+ * Converts a number to a letter (1=a, 2=b, etc.)
10
+ * For numbers > 26, continues with aa, ab, etc.
11
+ */
12
+ var numberToLetter = function numberToLetter(num) {
13
+ var result = '';
14
+ var n = num;
15
+ while (n > 0) {
16
+ n--;
17
+ result = String.fromCharCode(97 + n % 26) + result;
18
+ n = Math.floor(n / 26);
19
+ }
20
+ return result;
21
+ };
22
+
23
+ /**
24
+ * Gets the appropriate prefix for an ordered list item based on depth and index.
25
+ * - Level 0: "1. ", "2. ", "3. ", etc.
26
+ * - Level 1+: "a. ", "b. ", "c. ", etc.
27
+ */
28
+ var getOrderedListPrefix = function getOrderedListPrefix(depth, index) {
29
+ if (depth === 0) {
30
+ return "".concat(index, ". ");
31
+ }
32
+ return "".concat(numberToLetter(index), ". ");
33
+ };
34
+
35
+ /**
36
+ * Given an array of nodes, processes each ordered list by converting its items
37
+ * to paragraphs with numbered prefixes (1., 2., 3.) at the top level and
38
+ * lettered prefixes (a., b., c.) for nested levels.
39
+ *
40
+ * Handles nested ordered lists recursively with 3-space indentation per level.
41
+ *
42
+ * @example
43
+ * Input:
44
+ * - orderedList({ order: 1 })(
45
+ * listItem()(p()('Item 1')),
46
+ * orderedList({ order: 1 })(listItem()(p()('Sub item 1')))
47
+ * )
48
+ *
49
+ * Output:
50
+ * - p()('1. Item 1')
51
+ * - p()(' a. Sub item 1')
52
+ */
53
+ var convertOrderedListToTextStep = exports.convertOrderedListToTextStep = (0, _createListToTextStep.createListToTextStep)({
54
+ listTypeName: 'orderedList',
55
+ itemTypeName: 'listItem',
56
+ indent: ' ',
57
+ // 3 spaces per nesting level
58
+ getPrefix: function getPrefix(depth, index) {
59
+ return getOrderedListPrefix(depth, index);
60
+ },
61
+ unwrapParagraphContent: true
62
+ });
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.convertTaskListToTextStep = void 0;
7
+ var _createListToTextStep = require("./createListToTextStep");
8
+ /**
9
+ * Given an array of nodes, processes each task list by converting its items
10
+ * to paragraphs with a checkbox prefix. Uses "[] " for unchecked (TODO) tasks
11
+ * and "[x] " for checked (DONE) tasks.
12
+ *
13
+ * Handles nested task lists recursively with 4-space indentation per level.
14
+ *
15
+ * This is used when converting a task list to a container that doesn't support
16
+ * task items (like blockquote).
17
+ *
18
+ * @example
19
+ * Input:
20
+ * - taskList()(
21
+ * taskItem({ state: 'TODO' })('Task list item'),
22
+ * taskList()(taskItem({ state: 'DONE' })('Nested done task'))
23
+ * )
24
+ *
25
+ * Output:
26
+ * - p()('[] Task list item')
27
+ * - p()(' [x] Nested done task')
28
+ */
29
+ var convertTaskListToTextStep = exports.convertTaskListToTextStep = (0, _createListToTextStep.createListToTextStep)({
30
+ listTypeName: 'taskList',
31
+ itemTypeName: 'taskItem',
32
+ indent: ' ',
33
+ // 4 spaces per nesting level
34
+ getPrefix: function getPrefix(_, __, itemNode) {
35
+ var _itemNode$attrs;
36
+ return ((_itemNode$attrs = itemNode.attrs) === null || _itemNode$attrs === void 0 ? void 0 : _itemNode$attrs.state) === 'DONE' ? '[x] ' : '[] ';
37
+ },
38
+ unwrapParagraphContent: false
39
+ });
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createListToTextStep = void 0;
7
+ var _model = require("@atlaskit/editor-prosemirror/model");
8
+ /**
9
+ * Configuration for creating a list-to-text transformation step.
10
+ */
11
+
12
+ /**
13
+ * Recursively extracts list items from a list (including nested lists)
14
+ * and converts them to paragraphs with configurable prefixes and indentation.
15
+ */
16
+ var extractListItemsAsParagraphs = function extractListItemsAsParagraphs(node, schema, config) {
17
+ var paragraphs = [];
18
+ var paragraphType = schema.nodes.paragraph;
19
+ var listType = schema.nodes[config.listTypeName];
20
+ var itemType = schema.nodes[config.itemTypeName];
21
+ var _extract = function extract(currentNode) {
22
+ var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
23
+ var itemIndex = 0;
24
+ currentNode.forEach(function (child) {
25
+ if (child.type === itemType) {
26
+ itemIndex++;
27
+ var indent = config.indent.repeat(depth);
28
+ var prefix = config.getPrefix(depth, itemIndex, child);
29
+ var listPrefix = schema.text("".concat(indent).concat(prefix));
30
+
31
+ // Collect inline content and nested lists separately
32
+ var inlineContent = [];
33
+ var nestedLists = [];
34
+ child.forEach(function (grandChild) {
35
+ if (grandChild.type === listType) {
36
+ nestedLists.push(grandChild);
37
+ } else if (config.unwrapParagraphContent && grandChild.type === paragraphType) {
38
+ // Extract content from paragraph nodes
39
+ grandChild.forEach(function (content) {
40
+ inlineContent.push(content);
41
+ });
42
+ } else {
43
+ inlineContent.push(grandChild);
44
+ }
45
+ });
46
+
47
+ // Create paragraph with prefix + inline content
48
+ if (inlineContent.length > 0) {
49
+ var newContent = _model.Fragment.from(listPrefix).append(_model.Fragment.fromArray(inlineContent));
50
+ var newParagraph = paragraphType.create({}, newContent);
51
+ paragraphs.push(newParagraph);
52
+ }
53
+
54
+ // Recursively process nested lists with increased depth
55
+ nestedLists.forEach(function (nestedList) {
56
+ _extract(nestedList, depth + 1);
57
+ });
58
+ } else if (child.type === listType) {
59
+ // Handle list that appears directly as a sibling
60
+ _extract(child, depth + 1);
61
+ }
62
+ });
63
+ };
64
+ _extract(node, 0);
65
+ return paragraphs;
66
+ };
67
+
68
+ /**
69
+ * Creates a TransformStep that converts a list to paragraphs with text prefixes.
70
+ *
71
+ * Given an array of nodes, processes each list by converting its items
72
+ * to paragraphs with configurable prefixes.
73
+ *
74
+ * Handles nested lists recursively with configurable indentation per level.
75
+ *
76
+ * @param config - Configuration for the list-to-text transformation
77
+ * @returns A TransformStep function
78
+ */
79
+ var createListToTextStep = exports.createListToTextStep = function createListToTextStep(config) {
80
+ return function (nodes, context) {
81
+ var schema = context.schema;
82
+ var listType = schema.nodes[config.listTypeName];
83
+ return nodes.flatMap(function (node) {
84
+ if (node.type === listType) {
85
+ return extractListItemsAsParagraphs(node, schema, config);
86
+ }
87
+ return node;
88
+ });
89
+ };
90
+ };
@@ -7,6 +7,9 @@ exports.getOutputNodes = void 0;
7
7
  var _utils = require("../transform-node-utils/utils");
8
8
  var _flattenListStep = require("./flattenListStep");
9
9
  var _flattenStep = require("./flattenStep");
10
+ var _convertBulletListToTextStep = require("./steps/convertBulletListToTextStep");
11
+ var _convertOrderedListToTextStep = require("./steps/convertOrderedListToTextStep");
12
+ var _convertTaskListToTextStep = require("./steps/convertTaskListToTextStep");
10
13
  var _unwrapLayoutStep = require("./steps/unwrapLayoutStep");
11
14
  var _stubStep = require("./stubStep");
12
15
  var _types = require("./types");
@@ -28,7 +31,7 @@ var wrapIntoPanelStep = function wrapIntoPanelStep(nodes, context) {
28
31
  var TRANSFORM_STEPS = {
29
32
  atomic: {
30
33
  atomic: undefined,
31
- container: [_stubStep.stubStep],
34
+ container: [_wrapStep.wrapStep],
32
35
  list: undefined,
33
36
  text: undefined
34
37
  },
@@ -40,7 +43,7 @@ var TRANSFORM_STEPS = {
40
43
  },
41
44
  list: {
42
45
  atomic: undefined,
43
- container: [_stubStep.stubStep],
46
+ container: [_wrapStep.wrapStep],
44
47
  list: [_stubStep.stubStep],
45
48
  text: [_flattenListStep.flattenListStep, _unwrapListStep.unwrapListStep]
46
49
  },
@@ -94,6 +97,28 @@ var TRANSFORM_STEPS_OVERRIDE = {
94
97
  nestedExpand: [_wrapStep.wrapStep],
95
98
  layoutSection: [_wrapIntoLayoutStep.wrapIntoLayoutStep],
96
99
  panel: [_wrapStep.wrapStep]
100
+ },
101
+ bulletList: {
102
+ // Warning: Actuall transformation logic not complete (Likelly prosemirror-markdown to be used)
103
+ codeBlock: [_convertBulletListToTextStep.convertBulletListToTextStep, _flattenStep.flattenStep, _wrapStep.wrapStep],
104
+ layoutSection: [_wrapIntoLayoutStep.wrapIntoLayoutStep]
105
+ },
106
+ orderedList: {
107
+ // Warning: Actuall transformation logic not complete (Likelly prosemirror-markdown to be used)
108
+ codeBlock: [_convertOrderedListToTextStep.convertOrderedListToTextStep, _flattenStep.flattenStep, _wrapStep.wrapStep],
109
+ // Warning: Actuall transformation logic not complete (Likelly prosemirror-markdown to be used)
110
+ layoutSection: [_wrapIntoLayoutStep.wrapIntoLayoutStep]
111
+ },
112
+ taskList: {
113
+ // Warning: Actuall transformation logic not complete (Skeptical that prosemirror-markdown can be used)
114
+ blockquote: [_convertTaskListToTextStep.convertTaskListToTextStep, _wrapStep.wrapStep],
115
+ // Warning: Actuall transformation logic not complete (Likelly prosemirror-markdown to be used)
116
+ codeBlock: [_convertTaskListToTextStep.convertTaskListToTextStep, _flattenStep.flattenStep, _wrapStep.wrapStep],
117
+ layoutSection: [_wrapIntoLayoutStep.wrapIntoLayoutStep]
118
+ },
119
+ table: {
120
+ expand: [_wrapStep.wrapStep],
121
+ layoutSection: [_wrapIntoLayoutStep.wrapIntoLayoutStep]
97
122
  }
98
123
  };
99
124
  var getTransformStepsForNodeTypes = function getTransformStepsForNodeTypes(selectedNodeTypeName, targetNodeTypeName) {
@@ -8,6 +8,7 @@ var _selection = require("@atlaskit/editor-common/selection");
8
8
  var _state = require("@atlaskit/editor-prosemirror/state");
9
9
  var _utils = require("@atlaskit/editor-prosemirror/utils");
10
10
  var _editorTables = require("@atlaskit/editor-tables");
11
+ var _utils2 = require("@atlaskit/editor-tables/utils");
11
12
  var getSelectedNode = exports.getSelectedNode = function getSelectedNode(selection) {
12
13
  if (selection instanceof _state.NodeSelection) {
13
14
  return {
@@ -58,29 +59,34 @@ var getTargetNodeTypeNameInContext = exports.getTargetNodeTypeNameInContext = fu
58
59
  };
59
60
 
60
61
  /**
61
- * Use common expandToBlockRange function, but account for edge cases with lists.
62
- *
62
+ * Use common expandToBlockRange function to get the correct range for the selection
63
+ * For example, if selection starts in a listItem, go find the bullet list or ordered list, their $from
63
64
  * @param selection
64
65
  * @param schema
65
66
  * @returns
66
67
  */
67
68
  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
- }
69
+ var nodes = schema.nodes;
70
+ var nodesNeedToExpandRange = [nodes.listItem, nodes.taskItem];
71
+
72
+ // when adding nodes.tableRow, tableHeader, tableCell in nodesNeedToExpandRang,
73
+ // expandToBlockRange does not return expected table start position, sometimes even freeze editor
74
+ // so handle table in the below logic
75
+ if ((0, _utils2.isTableSelected)(selection)) {
76
+ var table = (0, _utils2.findTable)(selection);
77
+ if (table) {
78
+ var $from = selection.$from.doc.resolve(table.pos);
79
+ var $to = selection.$from.doc.resolve(table.pos + table.node.nodeSize - 1);
80
+ return {
81
+ $from: $from,
82
+ $to: $to
83
+ };
84
+ }
85
+ }
86
+ return (0, _selection.expandToBlockRange)(selection.$from, selection.$to, function (node) {
87
+ if (nodesNeedToExpandRange.includes(node.type)) {
78
88
  return false;
79
- }),
80
- $from = _expandToBlockRange.$from,
81
- $to = _expandToBlockRange.$to;
82
- return {
83
- $from: $from,
84
- $to: $to
85
- };
89
+ }
90
+ return true;
91
+ });
86
92
  };
@@ -0,0 +1,27 @@
1
+ import { createListToTextStep } from './createListToTextStep';
2
+
3
+ /**
4
+ * Given an array of nodes, processes each bullet list by converting its items
5
+ * to paragraphs with "- " prefix.
6
+ *
7
+ * Handles nested bullet lists recursively with 3-space indentation per level.
8
+ *
9
+ * @example
10
+ * Input:
11
+ * - bulletList()(
12
+ * listItem()(p()('Item 1')),
13
+ * bulletList()(listItem()(p()('Sub item 1')))
14
+ * )
15
+ *
16
+ * Output:
17
+ * - p()('- Item 1')
18
+ * - p()(' - Sub item 1')
19
+ */
20
+ export const convertBulletListToTextStep = createListToTextStep({
21
+ listTypeName: 'bulletList',
22
+ itemTypeName: 'listItem',
23
+ indent: ' ',
24
+ // 3 spaces per nesting level
25
+ getPrefix: () => '- ',
26
+ unwrapParagraphContent: true
27
+ });
@@ -0,0 +1,55 @@
1
+ import { createListToTextStep } from './createListToTextStep';
2
+
3
+ /**
4
+ * Converts a number to a letter (1=a, 2=b, etc.)
5
+ * For numbers > 26, continues with aa, ab, etc.
6
+ */
7
+ const numberToLetter = num => {
8
+ let result = '';
9
+ let n = num;
10
+ while (n > 0) {
11
+ n--;
12
+ result = String.fromCharCode(97 + n % 26) + result;
13
+ n = Math.floor(n / 26);
14
+ }
15
+ return result;
16
+ };
17
+
18
+ /**
19
+ * Gets the appropriate prefix for an ordered list item based on depth and index.
20
+ * - Level 0: "1. ", "2. ", "3. ", etc.
21
+ * - Level 1+: "a. ", "b. ", "c. ", etc.
22
+ */
23
+ const getOrderedListPrefix = (depth, index) => {
24
+ if (depth === 0) {
25
+ return `${index}. `;
26
+ }
27
+ return `${numberToLetter(index)}. `;
28
+ };
29
+
30
+ /**
31
+ * Given an array of nodes, processes each ordered list by converting its items
32
+ * to paragraphs with numbered prefixes (1., 2., 3.) at the top level and
33
+ * lettered prefixes (a., b., c.) for nested levels.
34
+ *
35
+ * Handles nested ordered lists recursively with 3-space indentation per level.
36
+ *
37
+ * @example
38
+ * Input:
39
+ * - orderedList({ order: 1 })(
40
+ * listItem()(p()('Item 1')),
41
+ * orderedList({ order: 1 })(listItem()(p()('Sub item 1')))
42
+ * )
43
+ *
44
+ * Output:
45
+ * - p()('1. Item 1')
46
+ * - p()(' a. Sub item 1')
47
+ */
48
+ export const convertOrderedListToTextStep = createListToTextStep({
49
+ listTypeName: 'orderedList',
50
+ itemTypeName: 'listItem',
51
+ indent: ' ',
52
+ // 3 spaces per nesting level
53
+ getPrefix: (depth, index) => getOrderedListPrefix(depth, index),
54
+ unwrapParagraphContent: true
55
+ });
@@ -0,0 +1,34 @@
1
+ import { createListToTextStep } from './createListToTextStep';
2
+
3
+ /**
4
+ * Given an array of nodes, processes each task list by converting its items
5
+ * to paragraphs with a checkbox prefix. Uses "[] " for unchecked (TODO) tasks
6
+ * and "[x] " for checked (DONE) tasks.
7
+ *
8
+ * Handles nested task lists recursively with 4-space indentation per level.
9
+ *
10
+ * This is used when converting a task list to a container that doesn't support
11
+ * task items (like blockquote).
12
+ *
13
+ * @example
14
+ * Input:
15
+ * - taskList()(
16
+ * taskItem({ state: 'TODO' })('Task list item'),
17
+ * taskList()(taskItem({ state: 'DONE' })('Nested done task'))
18
+ * )
19
+ *
20
+ * Output:
21
+ * - p()('[] Task list item')
22
+ * - p()(' [x] Nested done task')
23
+ */
24
+ export const convertTaskListToTextStep = createListToTextStep({
25
+ listTypeName: 'taskList',
26
+ itemTypeName: 'taskItem',
27
+ indent: ' ',
28
+ // 4 spaces per nesting level
29
+ getPrefix: (_, __, itemNode) => {
30
+ var _itemNode$attrs;
31
+ return ((_itemNode$attrs = itemNode.attrs) === null || _itemNode$attrs === void 0 ? void 0 : _itemNode$attrs.state) === 'DONE' ? '[x] ' : '[] ';
32
+ },
33
+ unwrapParagraphContent: false
34
+ });
@@ -0,0 +1,86 @@
1
+ import { Fragment } from '@atlaskit/editor-prosemirror/model';
2
+
3
+ /**
4
+ * Configuration for creating a list-to-text transformation step.
5
+ */
6
+
7
+ /**
8
+ * Recursively extracts list items from a list (including nested lists)
9
+ * and converts them to paragraphs with configurable prefixes and indentation.
10
+ */
11
+ const extractListItemsAsParagraphs = (node, schema, config) => {
12
+ const paragraphs = [];
13
+ const paragraphType = schema.nodes.paragraph;
14
+ const listType = schema.nodes[config.listTypeName];
15
+ const itemType = schema.nodes[config.itemTypeName];
16
+ const extract = (currentNode, depth = 0) => {
17
+ let itemIndex = 0;
18
+ currentNode.forEach(child => {
19
+ if (child.type === itemType) {
20
+ itemIndex++;
21
+ const indent = config.indent.repeat(depth);
22
+ const prefix = config.getPrefix(depth, itemIndex, child);
23
+ const listPrefix = schema.text(`${indent}${prefix}`);
24
+
25
+ // Collect inline content and nested lists separately
26
+ const inlineContent = [];
27
+ const nestedLists = [];
28
+ child.forEach(grandChild => {
29
+ if (grandChild.type === listType) {
30
+ nestedLists.push(grandChild);
31
+ } else if (config.unwrapParagraphContent && grandChild.type === paragraphType) {
32
+ // Extract content from paragraph nodes
33
+ grandChild.forEach(content => {
34
+ inlineContent.push(content);
35
+ });
36
+ } else {
37
+ inlineContent.push(grandChild);
38
+ }
39
+ });
40
+
41
+ // Create paragraph with prefix + inline content
42
+ if (inlineContent.length > 0) {
43
+ const newContent = Fragment.from(listPrefix).append(Fragment.fromArray(inlineContent));
44
+ const newParagraph = paragraphType.create({}, newContent);
45
+ paragraphs.push(newParagraph);
46
+ }
47
+
48
+ // Recursively process nested lists with increased depth
49
+ nestedLists.forEach(nestedList => {
50
+ extract(nestedList, depth + 1);
51
+ });
52
+ } else if (child.type === listType) {
53
+ // Handle list that appears directly as a sibling
54
+ extract(child, depth + 1);
55
+ }
56
+ });
57
+ };
58
+ extract(node, 0);
59
+ return paragraphs;
60
+ };
61
+
62
+ /**
63
+ * Creates a TransformStep that converts a list to paragraphs with text prefixes.
64
+ *
65
+ * Given an array of nodes, processes each list by converting its items
66
+ * to paragraphs with configurable prefixes.
67
+ *
68
+ * Handles nested lists recursively with configurable indentation per level.
69
+ *
70
+ * @param config - Configuration for the list-to-text transformation
71
+ * @returns A TransformStep function
72
+ */
73
+ export const createListToTextStep = config => {
74
+ return (nodes, context) => {
75
+ const {
76
+ schema
77
+ } = context;
78
+ const listType = schema.nodes[config.listTypeName];
79
+ return nodes.flatMap(node => {
80
+ if (node.type === listType) {
81
+ return extractListItemsAsParagraphs(node, schema, config);
82
+ }
83
+ return node;
84
+ });
85
+ };
86
+ };
@@ -1,6 +1,9 @@
1
1
  import { getTargetNodeTypeNameInContext } from '../transform-node-utils/utils';
2
2
  import { flattenListStep } from './flattenListStep';
3
3
  import { flattenStep } from './flattenStep';
4
+ import { convertBulletListToTextStep } from './steps/convertBulletListToTextStep';
5
+ import { convertOrderedListToTextStep } from './steps/convertOrderedListToTextStep';
6
+ import { convertTaskListToTextStep } from './steps/convertTaskListToTextStep';
4
7
  import { unwrapLayoutStep } from './steps/unwrapLayoutStep';
5
8
  import { stubStep } from './stubStep';
6
9
  import { NODE_CATEGORY_BY_TYPE, toNodeTypeValue } from './types';
@@ -23,7 +26,7 @@ const wrapIntoPanelStep = (nodes, context) => {
23
26
  const TRANSFORM_STEPS = {
24
27
  atomic: {
25
28
  atomic: undefined,
26
- container: [stubStep],
29
+ container: [wrapStep],
27
30
  list: undefined,
28
31
  text: undefined
29
32
  },
@@ -35,7 +38,7 @@ const TRANSFORM_STEPS = {
35
38
  },
36
39
  list: {
37
40
  atomic: undefined,
38
- container: [stubStep],
41
+ container: [wrapStep],
39
42
  list: [stubStep],
40
43
  text: [flattenListStep, unwrapListStep]
41
44
  },
@@ -89,6 +92,28 @@ const TRANSFORM_STEPS_OVERRIDE = {
89
92
  nestedExpand: [wrapStep],
90
93
  layoutSection: [wrapIntoLayoutStep],
91
94
  panel: [wrapStep]
95
+ },
96
+ bulletList: {
97
+ // Warning: Actuall transformation logic not complete (Likelly prosemirror-markdown to be used)
98
+ codeBlock: [convertBulletListToTextStep, flattenStep, wrapStep],
99
+ layoutSection: [wrapIntoLayoutStep]
100
+ },
101
+ orderedList: {
102
+ // Warning: Actuall transformation logic not complete (Likelly prosemirror-markdown to be used)
103
+ codeBlock: [convertOrderedListToTextStep, flattenStep, wrapStep],
104
+ // Warning: Actuall transformation logic not complete (Likelly prosemirror-markdown to be used)
105
+ layoutSection: [wrapIntoLayoutStep]
106
+ },
107
+ taskList: {
108
+ // Warning: Actuall transformation logic not complete (Skeptical that prosemirror-markdown can be used)
109
+ blockquote: [convertTaskListToTextStep, wrapStep],
110
+ // Warning: Actuall transformation logic not complete (Likelly prosemirror-markdown to be used)
111
+ codeBlock: [convertTaskListToTextStep, flattenStep, wrapStep],
112
+ layoutSection: [wrapIntoLayoutStep]
113
+ },
114
+ table: {
115
+ expand: [wrapStep],
116
+ layoutSection: [wrapIntoLayoutStep]
92
117
  }
93
118
  };
94
119
  const getTransformStepsForNodeTypes = (selectedNodeTypeName, targetNodeTypeName) => {
@@ -1,7 +1,8 @@
1
1
  import { expandToBlockRange } from '@atlaskit/editor-common/selection';
2
2
  import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
3
- import { findParentNodeOfType, hasParentNode } from '@atlaskit/editor-prosemirror/utils';
3
+ import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
4
4
  import { CellSelection } from '@atlaskit/editor-tables';
5
+ import { findTable, isTableSelected } from '@atlaskit/editor-tables/utils';
5
6
  export const getSelectedNode = selection => {
6
7
  if (selection instanceof NodeSelection) {
7
8
  return {
@@ -53,28 +54,36 @@ export const getTargetNodeTypeNameInContext = (nodeTypeName, isNested) => {
53
54
  };
54
55
 
55
56
  /**
56
- * Use common expandToBlockRange function, but account for edge cases with lists.
57
- *
57
+ * Use common expandToBlockRange function to get the correct range for the selection
58
+ * For example, if selection starts in a listItem, go find the bullet list or ordered list, their $from
58
59
  * @param selection
59
60
  * @param schema
60
61
  * @returns
61
62
  */
62
63
  export const expandSelectionToBlockRange = (selection, schema) => {
63
- const isListInSelection = hasParentNode(node => node.type === schema.nodes.bulletList || node.type === schema.nodes.orderedList)(selection);
64
64
  const {
65
- $from,
66
- $to
67
- } = expandToBlockRange(selection.$from, selection.$to, node => {
68
- if (!isListInSelection) {
69
- return true;
65
+ nodes
66
+ } = schema;
67
+ const nodesNeedToExpandRange = [nodes.listItem, nodes.taskItem];
68
+
69
+ // when adding nodes.tableRow, tableHeader, tableCell in nodesNeedToExpandRang,
70
+ // expandToBlockRange does not return expected table start position, sometimes even freeze editor
71
+ // so handle table in the below logic
72
+ if (isTableSelected(selection)) {
73
+ const table = findTable(selection);
74
+ if (table) {
75
+ const $from = selection.$from.doc.resolve(table.pos);
76
+ const $to = selection.$from.doc.resolve(table.pos + table.node.nodeSize - 1);
77
+ return {
78
+ $from,
79
+ $to
80
+ };
70
81
  }
71
- if (node.type === schema.nodes.bulletList || node.type === schema.nodes.orderedList) {
72
- return true;
82
+ }
83
+ return expandToBlockRange(selection.$from, selection.$to, node => {
84
+ if (nodesNeedToExpandRange.includes(node.type)) {
85
+ return false;
73
86
  }
74
- return false;
87
+ return true;
75
88
  });
76
- return {
77
- $from,
78
- $to
79
- };
80
89
  };
@@ -0,0 +1,29 @@
1
+ import { createListToTextStep } from './createListToTextStep';
2
+
3
+ /**
4
+ * Given an array of nodes, processes each bullet list by converting its items
5
+ * to paragraphs with "- " prefix.
6
+ *
7
+ * Handles nested bullet lists recursively with 3-space indentation per level.
8
+ *
9
+ * @example
10
+ * Input:
11
+ * - bulletList()(
12
+ * listItem()(p()('Item 1')),
13
+ * bulletList()(listItem()(p()('Sub item 1')))
14
+ * )
15
+ *
16
+ * Output:
17
+ * - p()('- Item 1')
18
+ * - p()(' - Sub item 1')
19
+ */
20
+ export var convertBulletListToTextStep = createListToTextStep({
21
+ listTypeName: 'bulletList',
22
+ itemTypeName: 'listItem',
23
+ indent: ' ',
24
+ // 3 spaces per nesting level
25
+ getPrefix: function getPrefix() {
26
+ return '- ';
27
+ },
28
+ unwrapParagraphContent: true
29
+ });
@@ -0,0 +1,57 @@
1
+ import { createListToTextStep } from './createListToTextStep';
2
+
3
+ /**
4
+ * Converts a number to a letter (1=a, 2=b, etc.)
5
+ * For numbers > 26, continues with aa, ab, etc.
6
+ */
7
+ var numberToLetter = function numberToLetter(num) {
8
+ var result = '';
9
+ var n = num;
10
+ while (n > 0) {
11
+ n--;
12
+ result = String.fromCharCode(97 + n % 26) + result;
13
+ n = Math.floor(n / 26);
14
+ }
15
+ return result;
16
+ };
17
+
18
+ /**
19
+ * Gets the appropriate prefix for an ordered list item based on depth and index.
20
+ * - Level 0: "1. ", "2. ", "3. ", etc.
21
+ * - Level 1+: "a. ", "b. ", "c. ", etc.
22
+ */
23
+ var getOrderedListPrefix = function getOrderedListPrefix(depth, index) {
24
+ if (depth === 0) {
25
+ return "".concat(index, ". ");
26
+ }
27
+ return "".concat(numberToLetter(index), ". ");
28
+ };
29
+
30
+ /**
31
+ * Given an array of nodes, processes each ordered list by converting its items
32
+ * to paragraphs with numbered prefixes (1., 2., 3.) at the top level and
33
+ * lettered prefixes (a., b., c.) for nested levels.
34
+ *
35
+ * Handles nested ordered lists recursively with 3-space indentation per level.
36
+ *
37
+ * @example
38
+ * Input:
39
+ * - orderedList({ order: 1 })(
40
+ * listItem()(p()('Item 1')),
41
+ * orderedList({ order: 1 })(listItem()(p()('Sub item 1')))
42
+ * )
43
+ *
44
+ * Output:
45
+ * - p()('1. Item 1')
46
+ * - p()(' a. Sub item 1')
47
+ */
48
+ export var convertOrderedListToTextStep = createListToTextStep({
49
+ listTypeName: 'orderedList',
50
+ itemTypeName: 'listItem',
51
+ indent: ' ',
52
+ // 3 spaces per nesting level
53
+ getPrefix: function getPrefix(depth, index) {
54
+ return getOrderedListPrefix(depth, index);
55
+ },
56
+ unwrapParagraphContent: true
57
+ });
@@ -0,0 +1,34 @@
1
+ import { createListToTextStep } from './createListToTextStep';
2
+
3
+ /**
4
+ * Given an array of nodes, processes each task list by converting its items
5
+ * to paragraphs with a checkbox prefix. Uses "[] " for unchecked (TODO) tasks
6
+ * and "[x] " for checked (DONE) tasks.
7
+ *
8
+ * Handles nested task lists recursively with 4-space indentation per level.
9
+ *
10
+ * This is used when converting a task list to a container that doesn't support
11
+ * task items (like blockquote).
12
+ *
13
+ * @example
14
+ * Input:
15
+ * - taskList()(
16
+ * taskItem({ state: 'TODO' })('Task list item'),
17
+ * taskList()(taskItem({ state: 'DONE' })('Nested done task'))
18
+ * )
19
+ *
20
+ * Output:
21
+ * - p()('[] Task list item')
22
+ * - p()(' [x] Nested done task')
23
+ */
24
+ export var convertTaskListToTextStep = createListToTextStep({
25
+ listTypeName: 'taskList',
26
+ itemTypeName: 'taskItem',
27
+ indent: ' ',
28
+ // 4 spaces per nesting level
29
+ getPrefix: function getPrefix(_, __, itemNode) {
30
+ var _itemNode$attrs;
31
+ return ((_itemNode$attrs = itemNode.attrs) === null || _itemNode$attrs === void 0 ? void 0 : _itemNode$attrs.state) === 'DONE' ? '[x] ' : '[] ';
32
+ },
33
+ unwrapParagraphContent: false
34
+ });
@@ -0,0 +1,85 @@
1
+ import { Fragment } from '@atlaskit/editor-prosemirror/model';
2
+
3
+ /**
4
+ * Configuration for creating a list-to-text transformation step.
5
+ */
6
+
7
+ /**
8
+ * Recursively extracts list items from a list (including nested lists)
9
+ * and converts them to paragraphs with configurable prefixes and indentation.
10
+ */
11
+ var extractListItemsAsParagraphs = function extractListItemsAsParagraphs(node, schema, config) {
12
+ var paragraphs = [];
13
+ var paragraphType = schema.nodes.paragraph;
14
+ var listType = schema.nodes[config.listTypeName];
15
+ var itemType = schema.nodes[config.itemTypeName];
16
+ var _extract = function extract(currentNode) {
17
+ var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
18
+ var itemIndex = 0;
19
+ currentNode.forEach(function (child) {
20
+ if (child.type === itemType) {
21
+ itemIndex++;
22
+ var indent = config.indent.repeat(depth);
23
+ var prefix = config.getPrefix(depth, itemIndex, child);
24
+ var listPrefix = schema.text("".concat(indent).concat(prefix));
25
+
26
+ // Collect inline content and nested lists separately
27
+ var inlineContent = [];
28
+ var nestedLists = [];
29
+ child.forEach(function (grandChild) {
30
+ if (grandChild.type === listType) {
31
+ nestedLists.push(grandChild);
32
+ } else if (config.unwrapParagraphContent && grandChild.type === paragraphType) {
33
+ // Extract content from paragraph nodes
34
+ grandChild.forEach(function (content) {
35
+ inlineContent.push(content);
36
+ });
37
+ } else {
38
+ inlineContent.push(grandChild);
39
+ }
40
+ });
41
+
42
+ // Create paragraph with prefix + inline content
43
+ if (inlineContent.length > 0) {
44
+ var newContent = Fragment.from(listPrefix).append(Fragment.fromArray(inlineContent));
45
+ var newParagraph = paragraphType.create({}, newContent);
46
+ paragraphs.push(newParagraph);
47
+ }
48
+
49
+ // Recursively process nested lists with increased depth
50
+ nestedLists.forEach(function (nestedList) {
51
+ _extract(nestedList, depth + 1);
52
+ });
53
+ } else if (child.type === listType) {
54
+ // Handle list that appears directly as a sibling
55
+ _extract(child, depth + 1);
56
+ }
57
+ });
58
+ };
59
+ _extract(node, 0);
60
+ return paragraphs;
61
+ };
62
+
63
+ /**
64
+ * Creates a TransformStep that converts a list to paragraphs with text prefixes.
65
+ *
66
+ * Given an array of nodes, processes each list by converting its items
67
+ * to paragraphs with configurable prefixes.
68
+ *
69
+ * Handles nested lists recursively with configurable indentation per level.
70
+ *
71
+ * @param config - Configuration for the list-to-text transformation
72
+ * @returns A TransformStep function
73
+ */
74
+ export var createListToTextStep = function createListToTextStep(config) {
75
+ return function (nodes, context) {
76
+ var schema = context.schema;
77
+ var listType = schema.nodes[config.listTypeName];
78
+ return nodes.flatMap(function (node) {
79
+ if (node.type === listType) {
80
+ return extractListItemsAsParagraphs(node, schema, config);
81
+ }
82
+ return node;
83
+ });
84
+ };
85
+ };
@@ -1,6 +1,9 @@
1
1
  import { getTargetNodeTypeNameInContext } from '../transform-node-utils/utils';
2
2
  import { flattenListStep } from './flattenListStep';
3
3
  import { flattenStep } from './flattenStep';
4
+ import { convertBulletListToTextStep } from './steps/convertBulletListToTextStep';
5
+ import { convertOrderedListToTextStep } from './steps/convertOrderedListToTextStep';
6
+ import { convertTaskListToTextStep } from './steps/convertTaskListToTextStep';
4
7
  import { unwrapLayoutStep } from './steps/unwrapLayoutStep';
5
8
  import { stubStep } from './stubStep';
6
9
  import { NODE_CATEGORY_BY_TYPE, toNodeTypeValue } from './types';
@@ -23,7 +26,7 @@ var wrapIntoPanelStep = function wrapIntoPanelStep(nodes, context) {
23
26
  var TRANSFORM_STEPS = {
24
27
  atomic: {
25
28
  atomic: undefined,
26
- container: [stubStep],
29
+ container: [wrapStep],
27
30
  list: undefined,
28
31
  text: undefined
29
32
  },
@@ -35,7 +38,7 @@ var TRANSFORM_STEPS = {
35
38
  },
36
39
  list: {
37
40
  atomic: undefined,
38
- container: [stubStep],
41
+ container: [wrapStep],
39
42
  list: [stubStep],
40
43
  text: [flattenListStep, unwrapListStep]
41
44
  },
@@ -89,6 +92,28 @@ var TRANSFORM_STEPS_OVERRIDE = {
89
92
  nestedExpand: [wrapStep],
90
93
  layoutSection: [wrapIntoLayoutStep],
91
94
  panel: [wrapStep]
95
+ },
96
+ bulletList: {
97
+ // Warning: Actuall transformation logic not complete (Likelly prosemirror-markdown to be used)
98
+ codeBlock: [convertBulletListToTextStep, flattenStep, wrapStep],
99
+ layoutSection: [wrapIntoLayoutStep]
100
+ },
101
+ orderedList: {
102
+ // Warning: Actuall transformation logic not complete (Likelly prosemirror-markdown to be used)
103
+ codeBlock: [convertOrderedListToTextStep, flattenStep, wrapStep],
104
+ // Warning: Actuall transformation logic not complete (Likelly prosemirror-markdown to be used)
105
+ layoutSection: [wrapIntoLayoutStep]
106
+ },
107
+ taskList: {
108
+ // Warning: Actuall transformation logic not complete (Skeptical that prosemirror-markdown can be used)
109
+ blockquote: [convertTaskListToTextStep, wrapStep],
110
+ // Warning: Actuall transformation logic not complete (Likelly prosemirror-markdown to be used)
111
+ codeBlock: [convertTaskListToTextStep, flattenStep, wrapStep],
112
+ layoutSection: [wrapIntoLayoutStep]
113
+ },
114
+ table: {
115
+ expand: [wrapStep],
116
+ layoutSection: [wrapIntoLayoutStep]
92
117
  }
93
118
  };
94
119
  var getTransformStepsForNodeTypes = function getTransformStepsForNodeTypes(selectedNodeTypeName, targetNodeTypeName) {
@@ -1,7 +1,8 @@
1
1
  import { expandToBlockRange } from '@atlaskit/editor-common/selection';
2
2
  import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
3
- import { findParentNodeOfType, hasParentNode } from '@atlaskit/editor-prosemirror/utils';
3
+ import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
4
4
  import { CellSelection } from '@atlaskit/editor-tables';
5
+ import { findTable, isTableSelected } from '@atlaskit/editor-tables/utils';
5
6
  export var getSelectedNode = function getSelectedNode(selection) {
6
7
  if (selection instanceof NodeSelection) {
7
8
  return {
@@ -52,29 +53,34 @@ export var getTargetNodeTypeNameInContext = function getTargetNodeTypeNameInCont
52
53
  };
53
54
 
54
55
  /**
55
- * Use common expandToBlockRange function, but account for edge cases with lists.
56
- *
56
+ * Use common expandToBlockRange function to get the correct range for the selection
57
+ * For example, if selection starts in a listItem, go find the bullet list or ordered list, their $from
57
58
  * @param selection
58
59
  * @param schema
59
60
  * @returns
60
61
  */
61
62
  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
- }
63
+ var nodes = schema.nodes;
64
+ var nodesNeedToExpandRange = [nodes.listItem, nodes.taskItem];
65
+
66
+ // when adding nodes.tableRow, tableHeader, tableCell in nodesNeedToExpandRang,
67
+ // expandToBlockRange does not return expected table start position, sometimes even freeze editor
68
+ // so handle table in the below logic
69
+ if (isTableSelected(selection)) {
70
+ var table = findTable(selection);
71
+ if (table) {
72
+ var $from = selection.$from.doc.resolve(table.pos);
73
+ var $to = selection.$from.doc.resolve(table.pos + table.node.nodeSize - 1);
74
+ return {
75
+ $from: $from,
76
+ $to: $to
77
+ };
78
+ }
79
+ }
80
+ return expandToBlockRange(selection.$from, selection.$to, function (node) {
81
+ if (nodesNeedToExpandRange.includes(node.type)) {
72
82
  return false;
73
- }),
74
- $from = _expandToBlockRange.$from,
75
- $to = _expandToBlockRange.$to;
76
- return {
77
- $from: $from,
78
- $to: $to
79
- };
83
+ }
84
+ return true;
85
+ });
80
86
  };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Given an array of nodes, processes each bullet list by converting its items
3
+ * to paragraphs with "- " prefix.
4
+ *
5
+ * Handles nested bullet lists recursively with 3-space indentation per level.
6
+ *
7
+ * @example
8
+ * Input:
9
+ * - bulletList()(
10
+ * listItem()(p()('Item 1')),
11
+ * bulletList()(listItem()(p()('Sub item 1')))
12
+ * )
13
+ *
14
+ * Output:
15
+ * - p()('- Item 1')
16
+ * - p()(' - Sub item 1')
17
+ */
18
+ export declare const convertBulletListToTextStep: import("../types").TransformStep;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Given an array of nodes, processes each ordered list by converting its items
3
+ * to paragraphs with numbered prefixes (1., 2., 3.) at the top level and
4
+ * lettered prefixes (a., b., c.) for nested levels.
5
+ *
6
+ * Handles nested ordered lists recursively with 3-space indentation per level.
7
+ *
8
+ * @example
9
+ * Input:
10
+ * - orderedList({ order: 1 })(
11
+ * listItem()(p()('Item 1')),
12
+ * orderedList({ order: 1 })(listItem()(p()('Sub item 1')))
13
+ * )
14
+ *
15
+ * Output:
16
+ * - p()('1. Item 1')
17
+ * - p()(' a. Sub item 1')
18
+ */
19
+ export declare const convertOrderedListToTextStep: import("../types").TransformStep;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Given an array of nodes, processes each task list by converting its items
3
+ * to paragraphs with a checkbox prefix. Uses "[] " for unchecked (TODO) tasks
4
+ * and "[x] " for checked (DONE) tasks.
5
+ *
6
+ * Handles nested task lists recursively with 4-space indentation per level.
7
+ *
8
+ * This is used when converting a task list to a container that doesn't support
9
+ * task items (like blockquote).
10
+ *
11
+ * @example
12
+ * Input:
13
+ * - taskList()(
14
+ * taskItem({ state: 'TODO' })('Task list item'),
15
+ * taskList()(taskItem({ state: 'DONE' })('Nested done task'))
16
+ * )
17
+ *
18
+ * Output:
19
+ * - p()('[] Task list item')
20
+ * - p()(' [x] Nested done task')
21
+ */
22
+ export declare const convertTaskListToTextStep: import("../types").TransformStep;
@@ -0,0 +1,38 @@
1
+ import { type Node as PMNode } from '@atlaskit/editor-prosemirror/model';
2
+ import type { TransformStep } from '../types';
3
+ /**
4
+ * Configuration for creating a list-to-text transformation step.
5
+ */
6
+ export interface ListToTextConfig {
7
+ /**
8
+ * Generate prefix text for a list item.
9
+ * @param depth - Nesting depth (0 = top level)
10
+ * @param index - 1-based index within current list
11
+ * @param itemNode - The item node (for reading attrs like task state)
12
+ */
13
+ getPrefix: (depth: number, index: number, itemNode: PMNode) => string;
14
+ /** Indentation string per nesting level (e.g., ' ' for 3 spaces) */
15
+ indent: string;
16
+ /** Name of the item node type (e.g., 'listItem', 'taskItem') */
17
+ itemTypeName: string;
18
+ /** Name of the list node type (e.g., 'bulletList', 'orderedList', 'taskList') */
19
+ listTypeName: string;
20
+ /**
21
+ * Whether to unwrap content from paragraph children.
22
+ * - bullet/ordered lists = true (content is wrapped in paragraphs)
23
+ * - task lists = false (inline content is a direct child)
24
+ */
25
+ unwrapParagraphContent: boolean;
26
+ }
27
+ /**
28
+ * Creates a TransformStep that converts a list to paragraphs with text prefixes.
29
+ *
30
+ * Given an array of nodes, processes each list by converting its items
31
+ * to paragraphs with configurable prefixes.
32
+ *
33
+ * Handles nested lists recursively with configurable indentation per level.
34
+ *
35
+ * @param config - Configuration for the list-to-text transformation
36
+ * @returns A TransformStep function
37
+ */
38
+ export declare const createListToTextStep: (config: ListToTextConfig) => TransformStep;
@@ -5,8 +5,8 @@ import type { NodeTypeName } from './types';
5
5
  export declare const getSelectedNode: (selection: Selection) => ContentNodeWithPos | undefined;
6
6
  export declare const getTargetNodeTypeNameInContext: (nodeTypeName: NodeTypeName | null, isNested?: boolean) => NodeTypeName | null;
7
7
  /**
8
- * Use common expandToBlockRange function, but account for edge cases with lists.
9
- *
8
+ * Use common expandToBlockRange function to get the correct range for the selection
9
+ * For example, if selection starts in a listItem, go find the bullet list or ordered list, their $from
10
10
  * @param selection
11
11
  * @param schema
12
12
  * @returns
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Given an array of nodes, processes each bullet list by converting its items
3
+ * to paragraphs with "- " prefix.
4
+ *
5
+ * Handles nested bullet lists recursively with 3-space indentation per level.
6
+ *
7
+ * @example
8
+ * Input:
9
+ * - bulletList()(
10
+ * listItem()(p()('Item 1')),
11
+ * bulletList()(listItem()(p()('Sub item 1')))
12
+ * )
13
+ *
14
+ * Output:
15
+ * - p()('- Item 1')
16
+ * - p()(' - Sub item 1')
17
+ */
18
+ export declare const convertBulletListToTextStep: import("../types").TransformStep;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Given an array of nodes, processes each ordered list by converting its items
3
+ * to paragraphs with numbered prefixes (1., 2., 3.) at the top level and
4
+ * lettered prefixes (a., b., c.) for nested levels.
5
+ *
6
+ * Handles nested ordered lists recursively with 3-space indentation per level.
7
+ *
8
+ * @example
9
+ * Input:
10
+ * - orderedList({ order: 1 })(
11
+ * listItem()(p()('Item 1')),
12
+ * orderedList({ order: 1 })(listItem()(p()('Sub item 1')))
13
+ * )
14
+ *
15
+ * Output:
16
+ * - p()('1. Item 1')
17
+ * - p()(' a. Sub item 1')
18
+ */
19
+ export declare const convertOrderedListToTextStep: import("../types").TransformStep;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Given an array of nodes, processes each task list by converting its items
3
+ * to paragraphs with a checkbox prefix. Uses "[] " for unchecked (TODO) tasks
4
+ * and "[x] " for checked (DONE) tasks.
5
+ *
6
+ * Handles nested task lists recursively with 4-space indentation per level.
7
+ *
8
+ * This is used when converting a task list to a container that doesn't support
9
+ * task items (like blockquote).
10
+ *
11
+ * @example
12
+ * Input:
13
+ * - taskList()(
14
+ * taskItem({ state: 'TODO' })('Task list item'),
15
+ * taskList()(taskItem({ state: 'DONE' })('Nested done task'))
16
+ * )
17
+ *
18
+ * Output:
19
+ * - p()('[] Task list item')
20
+ * - p()(' [x] Nested done task')
21
+ */
22
+ export declare const convertTaskListToTextStep: import("../types").TransformStep;
@@ -0,0 +1,38 @@
1
+ import { type Node as PMNode } from '@atlaskit/editor-prosemirror/model';
2
+ import type { TransformStep } from '../types';
3
+ /**
4
+ * Configuration for creating a list-to-text transformation step.
5
+ */
6
+ export interface ListToTextConfig {
7
+ /**
8
+ * Generate prefix text for a list item.
9
+ * @param depth - Nesting depth (0 = top level)
10
+ * @param index - 1-based index within current list
11
+ * @param itemNode - The item node (for reading attrs like task state)
12
+ */
13
+ getPrefix: (depth: number, index: number, itemNode: PMNode) => string;
14
+ /** Indentation string per nesting level (e.g., ' ' for 3 spaces) */
15
+ indent: string;
16
+ /** Name of the item node type (e.g., 'listItem', 'taskItem') */
17
+ itemTypeName: string;
18
+ /** Name of the list node type (e.g., 'bulletList', 'orderedList', 'taskList') */
19
+ listTypeName: string;
20
+ /**
21
+ * Whether to unwrap content from paragraph children.
22
+ * - bullet/ordered lists = true (content is wrapped in paragraphs)
23
+ * - task lists = false (inline content is a direct child)
24
+ */
25
+ unwrapParagraphContent: boolean;
26
+ }
27
+ /**
28
+ * Creates a TransformStep that converts a list to paragraphs with text prefixes.
29
+ *
30
+ * Given an array of nodes, processes each list by converting its items
31
+ * to paragraphs with configurable prefixes.
32
+ *
33
+ * Handles nested lists recursively with configurable indentation per level.
34
+ *
35
+ * @param config - Configuration for the list-to-text transformation
36
+ * @returns A TransformStep function
37
+ */
38
+ export declare const createListToTextStep: (config: ListToTextConfig) => TransformStep;
@@ -5,8 +5,8 @@ import type { NodeTypeName } from './types';
5
5
  export declare const getSelectedNode: (selection: Selection) => ContentNodeWithPos | undefined;
6
6
  export declare const getTargetNodeTypeNameInContext: (nodeTypeName: NodeTypeName | null, isNested?: boolean) => NodeTypeName | null;
7
7
  /**
8
- * Use common expandToBlockRange function, but account for edge cases with lists.
9
- *
8
+ * Use common expandToBlockRange function to get the correct range for the selection
9
+ * For example, if selection starts in a listItem, go find the bullet list or ordered list, their $from
10
10
  * @param selection
11
11
  * @param schema
12
12
  * @returns
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-menu",
3
- "version": "5.1.11",
3
+ "version": "5.2.1",
4
4
  "description": "BlockMenu plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -44,7 +44,7 @@
44
44
  "@atlaskit/platform-feature-flags": "^1.1.0",
45
45
  "@atlaskit/platform-feature-flags-react": "^0.4.0",
46
46
  "@atlaskit/primitives": "^16.4.0",
47
- "@atlaskit/tmp-editor-statsig": "^15.6.0",
47
+ "@atlaskit/tmp-editor-statsig": "^15.7.0",
48
48
  "@atlaskit/tokens": "^8.4.0",
49
49
  "@babel/runtime": "^7.0.0"
50
50
  },