@atlaskit/editor-plugin-block-menu 6.0.4 → 6.0.5

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 (27) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/editor-commands/transform-node-utils/steps/convertEachNodeStep.js +46 -0
  3. package/dist/cjs/editor-commands/transform-node-utils/steps/mergeNeighbourListsStep.js +91 -0
  4. package/dist/cjs/editor-commands/transform-node-utils/transform.js +28 -10
  5. package/dist/cjs/editor-commands/transformNode.js +65 -65
  6. package/dist/es2019/editor-commands/transform-node-utils/steps/convertEachNodeStep.js +28 -0
  7. package/dist/es2019/editor-commands/transform-node-utils/steps/mergeNeighbourListsStep.js +75 -0
  8. package/dist/es2019/editor-commands/transform-node-utils/transform.js +27 -9
  9. package/dist/es2019/editor-commands/transformNode.js +64 -67
  10. package/dist/esm/editor-commands/transform-node-utils/steps/convertEachNodeStep.js +39 -0
  11. package/dist/esm/editor-commands/transform-node-utils/steps/mergeNeighbourListsStep.js +85 -0
  12. package/dist/esm/editor-commands/transform-node-utils/transform.js +27 -9
  13. package/dist/esm/editor-commands/transformNode.js +64 -65
  14. package/dist/types/editor-commands/transform-node-utils/steps/convertEachNodeStep.d.ts +2 -0
  15. package/dist/types/editor-commands/transform-node-utils/steps/mergeNeighbourListsStep.d.ts +32 -0
  16. package/dist/types/editor-commands/transform-node-utils/transform.d.ts +16 -1
  17. package/dist/types/editor-commands/transformNode.d.ts +1 -1
  18. package/dist/types-ts4.5/editor-commands/transform-node-utils/steps/convertEachNodeStep.d.ts +2 -0
  19. package/dist/types-ts4.5/editor-commands/transform-node-utils/steps/mergeNeighbourListsStep.d.ts +32 -0
  20. package/dist/types-ts4.5/editor-commands/transform-node-utils/transform.d.ts +16 -1
  21. package/dist/types-ts4.5/editor-commands/transformNode.d.ts +1 -1
  22. package/package.json +3 -3
  23. package/dist/cjs/editor-commands/transform-node-utils/tranformContent.js +0 -19
  24. package/dist/es2019/editor-commands/transform-node-utils/tranformContent.js +0 -13
  25. package/dist/esm/editor-commands/transform-node-utils/tranformContent.js +0 -13
  26. package/dist/types/editor-commands/transform-node-utils/tranformContent.d.ts +0 -3
  27. package/dist/types-ts4.5/editor-commands/transform-node-utils/tranformContent.d.ts +0 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/editor-plugin-block-menu
2
2
 
3
+ ## 6.0.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [`1c4801e3e64b4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1c4801e3e64b4) -
8
+ [ux] Add ability for multi selected block transformations to lists
9
+ - Updated dependencies
10
+
3
11
  ## 6.0.4
4
12
 
5
13
  ### Patch Changes
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.convertEachNodeStep = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ var _transform = require("../transform");
10
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
11
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
12
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
13
+ var convertEachNodeStep = exports.convertEachNodeStep = function convertEachNodeStep(nodes, context) {
14
+ var schema = context.schema,
15
+ targetNodeTypeName = context.targetNodeTypeName,
16
+ targetAttrs = context.targetAttrs;
17
+ var targetNodeType = schema.nodes[targetNodeTypeName];
18
+ if (!targetNodeType) {
19
+ return nodes;
20
+ }
21
+ var resultNodes = [];
22
+ var _iterator = _createForOfIteratorHelper(nodes),
23
+ _step;
24
+ try {
25
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
26
+ var node = _step.value;
27
+ var transformedNodes = (0, _transform.convertNodesToTargetType)({
28
+ sourceNodes: [node],
29
+ targetNodeType: targetNodeType,
30
+ schema: schema,
31
+ isNested: false,
32
+ targetAttrs: targetAttrs
33
+ });
34
+ if (transformedNodes.length > 0) {
35
+ resultNodes.push.apply(resultNodes, (0, _toConsumableArray2.default)(transformedNodes));
36
+ } else {
37
+ resultNodes.push(node);
38
+ }
39
+ }
40
+ } catch (err) {
41
+ _iterator.e(err);
42
+ } finally {
43
+ _iterator.f();
44
+ }
45
+ return resultNodes;
46
+ };
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.mergeNeighbourListsStep = void 0;
7
+ var _nodeChecks = require("../nodeChecks");
8
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
9
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
10
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
11
+ /**
12
+ * Merges consecutive lists of the same type into a single list.
13
+ * This step is useful after multiToListStep which may create multiple separate lists
14
+ * that should be combined.
15
+ *
16
+ * Handles both nestable lists (bulletList, orderedList, taskList) and
17
+ * non-nestable lists (decisionList).
18
+ *
19
+ * @example
20
+ * Input:
21
+ * - bulletList
22
+ * - listItem "1"
23
+ * - bulletList
24
+ * - listItem "2"
25
+ * - panel (non-list node)
26
+ * - bulletList
27
+ * - listItem "3"
28
+ *
29
+ * Output:
30
+ * - bulletList
31
+ * - listItem "1"
32
+ * - listItem "2"
33
+ * - panel (non-list node)
34
+ * - bulletList
35
+ * - listItem "3"
36
+ *
37
+ * @param nodes - The nodes to process
38
+ * @param context - The transformation context
39
+ * @returns The merged nodes
40
+ */
41
+ var mergeNeighbourListsStep = exports.mergeNeighbourListsStep = function mergeNeighbourListsStep(nodes, context) {
42
+ if (nodes.length === 0) {
43
+ return nodes;
44
+ }
45
+ var schema = context.schema;
46
+ var resultNodes = [];
47
+ var currentList = null;
48
+
49
+ // Check if a node is any type of list (including decisionList)
50
+ var isList = function isList(node) {
51
+ return (0, _nodeChecks.isListWithIndentation)(node.type.name, schema) || node.type.name === 'decisionList';
52
+ };
53
+ var _iterator = _createForOfIteratorHelper(nodes),
54
+ _step;
55
+ try {
56
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
57
+ var node = _step.value;
58
+ // Check if this node is any type of list
59
+ if (isList(node)) {
60
+ if (currentList && currentList.type === node.type) {
61
+ // Merge with the current list by combining their children
62
+ var mergedContent = currentList.content.append(node.content);
63
+ currentList = currentList.type.create(currentList.attrs, mergedContent);
64
+ } else {
65
+ // Start a new list or switch to a different list type
66
+ if (currentList) {
67
+ resultNodes.push(currentList);
68
+ }
69
+ currentList = node;
70
+ }
71
+ } else {
72
+ // Non-list node - push any accumulated list and then this node
73
+ if (currentList) {
74
+ resultNodes.push(currentList);
75
+ currentList = null;
76
+ }
77
+ resultNodes.push(node);
78
+ }
79
+ }
80
+
81
+ // Don't forget the last list if we ended with one
82
+ } catch (err) {
83
+ _iterator.e(err);
84
+ } finally {
85
+ _iterator.f();
86
+ }
87
+ if (currentList) {
88
+ resultNodes.push(currentList);
89
+ }
90
+ return resultNodes;
91
+ };
@@ -3,14 +3,16 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.isTransformDisabledBasedOnStepsConfig = exports.getOutputNodes = void 0;
6
+ exports.isTransformDisabledBasedOnStepsConfig = exports.convertNodesToTargetType = void 0;
7
7
  var _utils = require("../transform-node-utils/utils");
8
8
  var _flattenStep = require("./flattenStep");
9
9
  var _applyTargetTextTypeStep = require("./steps/applyTargetTextTypeStep");
10
+ var _convertEachNodeStep = require("./steps/convertEachNodeStep");
10
11
  var _decisionListToListStep = require("./steps/decisionListToListStep");
11
12
  var _flattenListStep = require("./steps/flattenListStep");
12
13
  var _listToDecisionListStep = require("./steps/listToDecisionListStep");
13
14
  var _listToListStep = require("./steps/listToListStep");
15
+ var _mergeNeighbourListsStep = require("./steps/mergeNeighbourListsStep");
14
16
  var _unwrapLayoutStep = require("./steps/unwrapLayoutStep");
15
17
  var _unwrapListStep = require("./steps/unwrapListStep");
16
18
  var _wrapBlockquoteToDecisionListStep = require("./steps/wrapBlockquoteToDecisionListStep");
@@ -55,10 +57,8 @@ var TRANSFORM_STEPS = {
55
57
  multi: {
56
58
  atomic: undefined,
57
59
  container: [_wrapMixedContentStep.wrapMixedContentStep],
58
- // TODO: EDITOR-4137 - Implement multi list transform
59
- list: undefined,
60
- // TODO: EDITOR-4140 - Implement multi text transform
61
- text: undefined,
60
+ list: [_convertEachNodeStep.convertEachNodeStep, _mergeNeighbourListsStep.mergeNeighbourListsStep],
61
+ text: [_convertEachNodeStep.convertEachNodeStep],
62
62
  multi: undefined
63
63
  }
64
64
  };
@@ -222,6 +222,10 @@ var TRANSFORM_STEPS_OVERRIDE = {
222
222
  decisionList: null
223
223
  },
224
224
  multi: {
225
+ // TODO: EDITOR-4140 - Implement multiple paragraphs/headings/codeblocks to heading transform
226
+ heading: null,
227
+ // TODO: EDITOR-4141 - Implement multiple codeblocks/headings to paragraph transform
228
+ paragraph: null,
225
229
  // TODO: EDITOR-4138 - Implement multi content to layout transform
226
230
  layoutSection: undefined
227
231
  }
@@ -237,7 +241,22 @@ var getTransformStepsForNodeTypes = function getTransformStepsForNodeTypes(selec
237
241
  var steps = overrideSteps !== null && overrideSteps !== void 0 ? overrideSteps : TRANSFORM_STEPS[fromCategory][toCategory];
238
242
  return steps;
239
243
  };
240
- var getOutputNodes = exports.getOutputNodes = function getOutputNodes(_ref) {
244
+ /**
245
+ * Convert a list of nodes to a target node type.
246
+ * If no steps are found, the source nodes are returned unchanged.
247
+ * If steps are found, they are applied to the source nodes in order.
248
+ * If a step returns an empty array, the source nodes are returned.
249
+ * If a step returns a non-empty array, that array is returned.
250
+ * @param args - The conversion arguments
251
+ * @param args.sourceNodes - The list of nodes to convert
252
+ * @param args.targetNodeType - The type of node to convert into
253
+ * @param args.schema - The schema to use for the conversion
254
+ * @param args.isNested - Whether the conversion is nested
255
+ * @param args.targetAttrs - The attributes to use for the conversion
256
+ * @param args.parentNode - The parent node of the selected node
257
+ * @returns The converted list of nodes
258
+ */
259
+ var convertNodesToTargetType = exports.convertNodesToTargetType = function convertNodesToTargetType(_ref) {
241
260
  var sourceNodes = _ref.sourceNodes,
242
261
  targetNodeType = _ref.targetNodeType,
243
262
  schema = _ref.schema,
@@ -246,14 +265,13 @@ var getOutputNodes = exports.getOutputNodes = function getOutputNodes(_ref) {
246
265
  parentNode = _ref.parentNode;
247
266
  var sourceNode = sourceNodes.at(0);
248
267
  if (!sourceNode) {
249
- return;
268
+ return sourceNodes;
250
269
  }
251
270
  var selectedNodeTypeName = (0, _types.toNodeTypeValue)((0, _types.getNodeName)(sourceNodes));
252
271
  var initialTargetNodeTypeName = (0, _types.toNodeTypeValue)(targetNodeType.name);
253
272
  var targetNodeTypeName = (0, _utils.getTargetNodeTypeNameInContext)(initialTargetNodeTypeName, isNested, parentNode);
254
273
  if (!selectedNodeTypeName || !targetNodeTypeName) {
255
- // We may decide to return an empty array or undefined here
256
- return;
274
+ return sourceNodes;
257
275
  }
258
276
  var steps = getTransformStepsForNodeTypes(selectedNodeTypeName, targetNodeTypeName);
259
277
  var context = {
@@ -264,7 +282,7 @@ var getOutputNodes = exports.getOutputNodes = function getOutputNodes(_ref) {
264
282
  targetAttrs: targetAttrs
265
283
  };
266
284
  if (!steps || steps.length === 0) {
267
- return;
285
+ return sourceNodes;
268
286
  }
269
287
  return steps.reduce(function (nodes, step) {
270
288
  return step(nodes, context);
@@ -1,80 +1,80 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
7
  exports.transformNode = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
7
9
  var _analytics = require("@atlaskit/editor-common/analytics");
8
10
  var _performanceMeasures = require("@atlaskit/editor-common/performance-measures");
9
11
  var _selection = require("@atlaskit/editor-common/selection");
10
12
  var _state = require("@atlaskit/editor-prosemirror/state");
11
13
  var _isNestedNode = require("../ui/utils/isNestedNode");
12
- var _tranformContent = require("./transform-node-utils/tranformContent");
14
+ var _transform = require("./transform-node-utils/transform");
13
15
  var _utils = require("./transforms/utils");
14
16
  var transformNode = exports.transformNode = function transformNode(api) {
15
- return (
16
- // eslint-disable-next-line no-unused-vars
17
- function (targetType, metadata) {
18
- return function (_ref) {
19
- var _api$blockControls;
20
- var tr = _ref.tr;
21
- var preservedSelection = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.sharedState.currentState()) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.preservedSelection;
22
- if (!preservedSelection) {
23
- return tr;
24
- }
25
-
26
- // Start performance measurement
27
- var measureId = "transformNode_".concat(targetType.name, "_").concat(Date.now());
28
- (0, _performanceMeasures.startMeasure)(measureId);
29
- var schema = tr.doc.type.schema;
30
- var nodes = schema.nodes;
31
- var _expandSelectionToBlo = (0, _selection.expandSelectionToBlockRange)(preservedSelection),
32
- $from = _expandSelectionToBlo.$from,
33
- $to = _expandSelectionToBlo.$to;
34
- var selectedParent = $from.parent;
35
- var isNested = (0, _isNestedNode.isNestedNode)(preservedSelection, '');
36
- var isList = (0, _utils.isListNode)(selectedParent);
37
- var slice = tr.doc.slice(isList ? $from.pos - 1 : $from.pos, isList ? $to.pos + 1 : $to.pos);
38
-
39
- // Collect source node information for analytics before transformation
40
- var nodeCount = 0;
41
- var sourceNodeTypes = {};
42
- slice.content.forEach(function (node) {
43
- nodeCount++;
44
- var nodeTypeName = node.type.name;
45
- sourceNodeTypes[nodeTypeName] = (sourceNodeTypes[nodeTypeName] || 0) + 1;
46
- });
47
- var transformedNodes = (0, _tranformContent.tranformContent)(slice.content, targetType, schema, isNested, metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs, selectedParent);
48
- var nodesToDeleteAndInsert = [nodes.mediaSingle];
49
- if (preservedSelection instanceof _state.NodeSelection && nodesToDeleteAndInsert.includes(preservedSelection.node.type)) {
50
- // when node is media single, use tr.replaceWith freeze editor, if modify position, tr.replaceWith creates duplicats
51
- tr.deleteRange($from.pos, $to.pos);
52
- tr.insert($from.pos, transformedNodes);
53
- } else {
54
- tr.replaceWith(isList ? $from.pos - 1 : $from.pos, $to.pos, transformedNodes);
55
- }
56
-
57
- // Stop performance measurement and fire analytics
58
- (0, _performanceMeasures.stopMeasure)(measureId, function (duration, startTime) {
59
- var _api$analytics;
60
- api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.fireAnalyticsEvent({
61
- action: _analytics.ACTION.TRANSFORMED,
62
- actionSubject: _analytics.ACTION_SUBJECT.ELEMENT,
63
- actionSubjectId: _analytics.ACTION_SUBJECT_ID.TRANSFORM,
64
- attributes: {
65
- duration: duration,
66
- isList: isList,
67
- isNested: isNested,
68
- nodeCount: nodeCount,
69
- sourceNodeTypes: sourceNodeTypes,
70
- startTime: startTime,
71
- targetNodeType: targetType.name
72
- },
73
- eventType: _analytics.EVENT_TYPE.OPERATIONAL
74
- });
75
- });
17
+ return function (targetType, metadata) {
18
+ return function (_ref) {
19
+ var _api$blockControls;
20
+ var tr = _ref.tr;
21
+ var preservedSelection = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.sharedState.currentState()) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.preservedSelection;
22
+ if (!preservedSelection) {
76
23
  return tr;
77
- };
78
- }
79
- );
24
+ }
25
+ var measureId = "transformNode_".concat(targetType.name, "_").concat(Date.now());
26
+ (0, _performanceMeasures.startMeasure)(measureId);
27
+ var nodes = tr.doc.type.schema.nodes;
28
+ var _expandSelectionToBlo = (0, _selection.expandSelectionToBlockRange)(preservedSelection),
29
+ $from = _expandSelectionToBlo.$from,
30
+ $to = _expandSelectionToBlo.$to;
31
+ var selectedParent = $from.parent;
32
+ var isParentLayout = selectedParent.type === nodes.layoutColumn;
33
+ var isNested = (0, _isNestedNode.isNestedNode)(preservedSelection, '') && !isParentLayout;
34
+ var isList = (0, _utils.isListNode)(selectedParent);
35
+ var sliceStart = isList ? $from.pos - 1 : $from.pos;
36
+ var sliceEnd = isList ? $to.pos + 1 : $to.pos;
37
+ var slice = tr.doc.slice(sliceStart, sliceEnd);
38
+ var sourceNodes = (0, _toConsumableArray2.default)(slice.content.content);
39
+ var sourceNodeTypes = {};
40
+ sourceNodes.forEach(function (node) {
41
+ var typeName = node.type.name;
42
+ sourceNodeTypes[typeName] = (sourceNodeTypes[typeName] || 0) + 1;
43
+ });
44
+ var resultNodes = (0, _transform.convertNodesToTargetType)({
45
+ sourceNodes: sourceNodes,
46
+ targetNodeType: targetType,
47
+ schema: tr.doc.type.schema,
48
+ isNested: isNested,
49
+ targetAttrs: metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs,
50
+ parentNode: selectedParent
51
+ });
52
+ var content = resultNodes.length > 0 ? resultNodes : slice.content;
53
+ if (preservedSelection instanceof _state.NodeSelection && preservedSelection.node.type === nodes.mediaSingle) {
54
+ tr.deleteRange($from.pos, $to.pos);
55
+ tr.insert($from.pos, content);
56
+ } else {
57
+ tr.replaceWith(sliceStart, $to.pos, content);
58
+ }
59
+ (0, _performanceMeasures.stopMeasure)(measureId, function (duration, startTime) {
60
+ var _api$analytics;
61
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.fireAnalyticsEvent({
62
+ action: _analytics.ACTION.TRANSFORMED,
63
+ actionSubject: _analytics.ACTION_SUBJECT.ELEMENT,
64
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.TRANSFORM,
65
+ attributes: {
66
+ duration: duration,
67
+ isList: isList,
68
+ isNested: isNested,
69
+ nodeCount: sourceNodes.length,
70
+ sourceNodeTypes: sourceNodeTypes,
71
+ startTime: startTime,
72
+ targetNodeType: targetType.name
73
+ },
74
+ eventType: _analytics.EVENT_TYPE.OPERATIONAL
75
+ });
76
+ });
77
+ return tr;
78
+ };
79
+ };
80
80
  };
@@ -0,0 +1,28 @@
1
+ import { convertNodesToTargetType } from '../transform';
2
+ export const convertEachNodeStep = (nodes, context) => {
3
+ const {
4
+ schema,
5
+ targetNodeTypeName,
6
+ targetAttrs
7
+ } = context;
8
+ const targetNodeType = schema.nodes[targetNodeTypeName];
9
+ if (!targetNodeType) {
10
+ return nodes;
11
+ }
12
+ const resultNodes = [];
13
+ for (const node of nodes) {
14
+ const transformedNodes = convertNodesToTargetType({
15
+ sourceNodes: [node],
16
+ targetNodeType,
17
+ schema,
18
+ isNested: false,
19
+ targetAttrs
20
+ });
21
+ if (transformedNodes.length > 0) {
22
+ resultNodes.push(...transformedNodes);
23
+ } else {
24
+ resultNodes.push(node);
25
+ }
26
+ }
27
+ return resultNodes;
28
+ };
@@ -0,0 +1,75 @@
1
+ import { isListWithIndentation } from '../nodeChecks';
2
+ /**
3
+ * Merges consecutive lists of the same type into a single list.
4
+ * This step is useful after multiToListStep which may create multiple separate lists
5
+ * that should be combined.
6
+ *
7
+ * Handles both nestable lists (bulletList, orderedList, taskList) and
8
+ * non-nestable lists (decisionList).
9
+ *
10
+ * @example
11
+ * Input:
12
+ * - bulletList
13
+ * - listItem "1"
14
+ * - bulletList
15
+ * - listItem "2"
16
+ * - panel (non-list node)
17
+ * - bulletList
18
+ * - listItem "3"
19
+ *
20
+ * Output:
21
+ * - bulletList
22
+ * - listItem "1"
23
+ * - listItem "2"
24
+ * - panel (non-list node)
25
+ * - bulletList
26
+ * - listItem "3"
27
+ *
28
+ * @param nodes - The nodes to process
29
+ * @param context - The transformation context
30
+ * @returns The merged nodes
31
+ */
32
+ export const mergeNeighbourListsStep = (nodes, context) => {
33
+ if (nodes.length === 0) {
34
+ return nodes;
35
+ }
36
+ const {
37
+ schema
38
+ } = context;
39
+ const resultNodes = [];
40
+ let currentList = null;
41
+
42
+ // Check if a node is any type of list (including decisionList)
43
+ const isList = node => {
44
+ return isListWithIndentation(node.type.name, schema) || node.type.name === 'decisionList';
45
+ };
46
+ for (const node of nodes) {
47
+ // Check if this node is any type of list
48
+ if (isList(node)) {
49
+ if (currentList && currentList.type === node.type) {
50
+ // Merge with the current list by combining their children
51
+ const mergedContent = currentList.content.append(node.content);
52
+ currentList = currentList.type.create(currentList.attrs, mergedContent);
53
+ } else {
54
+ // Start a new list or switch to a different list type
55
+ if (currentList) {
56
+ resultNodes.push(currentList);
57
+ }
58
+ currentList = node;
59
+ }
60
+ } else {
61
+ // Non-list node - push any accumulated list and then this node
62
+ if (currentList) {
63
+ resultNodes.push(currentList);
64
+ currentList = null;
65
+ }
66
+ resultNodes.push(node);
67
+ }
68
+ }
69
+
70
+ // Don't forget the last list if we ended with one
71
+ if (currentList) {
72
+ resultNodes.push(currentList);
73
+ }
74
+ return resultNodes;
75
+ };
@@ -1,10 +1,12 @@
1
1
  import { getTargetNodeTypeNameInContext } from '../transform-node-utils/utils';
2
2
  import { flattenStep } from './flattenStep';
3
3
  import { applyTargetTextTypeStep } from './steps/applyTargetTextTypeStep';
4
+ import { convertEachNodeStep } from './steps/convertEachNodeStep';
4
5
  import { decisionListToListStep } from './steps/decisionListToListStep';
5
6
  import { flattenListStep } from './steps/flattenListStep';
6
7
  import { listToDecisionListStep } from './steps/listToDecisionListStep';
7
8
  import { listToListStep } from './steps/listToListStep';
9
+ import { mergeNeighbourListsStep } from './steps/mergeNeighbourListsStep';
8
10
  import { unwrapLayoutStep } from './steps/unwrapLayoutStep';
9
11
  import { unwrapListStep } from './steps/unwrapListStep';
10
12
  import { wrapBlockquoteToDecisionListStep } from './steps/wrapBlockquoteToDecisionListStep';
@@ -50,10 +52,8 @@ const TRANSFORM_STEPS = {
50
52
  multi: {
51
53
  atomic: undefined,
52
54
  container: [wrapMixedContentStep],
53
- // TODO: EDITOR-4137 - Implement multi list transform
54
- list: undefined,
55
- // TODO: EDITOR-4140 - Implement multi text transform
56
- text: undefined,
55
+ list: [convertEachNodeStep, mergeNeighbourListsStep],
56
+ text: [convertEachNodeStep],
57
57
  multi: undefined
58
58
  }
59
59
  };
@@ -217,6 +217,10 @@ const TRANSFORM_STEPS_OVERRIDE = {
217
217
  decisionList: null
218
218
  },
219
219
  multi: {
220
+ // TODO: EDITOR-4140 - Implement multiple paragraphs/headings/codeblocks to heading transform
221
+ heading: null,
222
+ // TODO: EDITOR-4141 - Implement multiple codeblocks/headings to paragraph transform
223
+ paragraph: null,
220
224
  // TODO: EDITOR-4138 - Implement multi content to layout transform
221
225
  layoutSection: undefined
222
226
  }
@@ -232,7 +236,22 @@ const getTransformStepsForNodeTypes = (selectedNodeTypeName, targetNodeTypeName)
232
236
  const steps = overrideSteps !== null && overrideSteps !== void 0 ? overrideSteps : TRANSFORM_STEPS[fromCategory][toCategory];
233
237
  return steps;
234
238
  };
235
- export const getOutputNodes = ({
239
+ /**
240
+ * Convert a list of nodes to a target node type.
241
+ * If no steps are found, the source nodes are returned unchanged.
242
+ * If steps are found, they are applied to the source nodes in order.
243
+ * If a step returns an empty array, the source nodes are returned.
244
+ * If a step returns a non-empty array, that array is returned.
245
+ * @param args - The conversion arguments
246
+ * @param args.sourceNodes - The list of nodes to convert
247
+ * @param args.targetNodeType - The type of node to convert into
248
+ * @param args.schema - The schema to use for the conversion
249
+ * @param args.isNested - Whether the conversion is nested
250
+ * @param args.targetAttrs - The attributes to use for the conversion
251
+ * @param args.parentNode - The parent node of the selected node
252
+ * @returns The converted list of nodes
253
+ */
254
+ export const convertNodesToTargetType = ({
236
255
  sourceNodes,
237
256
  targetNodeType,
238
257
  schema,
@@ -242,14 +261,13 @@ export const getOutputNodes = ({
242
261
  }) => {
243
262
  const sourceNode = sourceNodes.at(0);
244
263
  if (!sourceNode) {
245
- return;
264
+ return sourceNodes;
246
265
  }
247
266
  const selectedNodeTypeName = toNodeTypeValue(getNodeName(sourceNodes));
248
267
  const initialTargetNodeTypeName = toNodeTypeValue(targetNodeType.name);
249
268
  const targetNodeTypeName = getTargetNodeTypeNameInContext(initialTargetNodeTypeName, isNested, parentNode);
250
269
  if (!selectedNodeTypeName || !targetNodeTypeName) {
251
- // We may decide to return an empty array or undefined here
252
- return;
270
+ return sourceNodes;
253
271
  }
254
272
  const steps = getTransformStepsForNodeTypes(selectedNodeTypeName, targetNodeTypeName);
255
273
  const context = {
@@ -260,7 +278,7 @@ export const getOutputNodes = ({
260
278
  targetAttrs
261
279
  };
262
280
  if (!steps || steps.length === 0) {
263
- return;
281
+ return sourceNodes;
264
282
  }
265
283
  return steps.reduce((nodes, step) => {
266
284
  return step(nodes, context);