@atlaskit/editor-plugin-block-menu 6.0.3 → 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 (35) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cjs/editor-actions/isTransformToTargetDisabled.js +1 -1
  3. package/dist/cjs/editor-commands/transform-node-utils/steps/convertEachNodeStep.js +46 -0
  4. package/dist/cjs/editor-commands/transform-node-utils/steps/mergeNeighbourListsStep.js +91 -0
  5. package/dist/cjs/editor-commands/transform-node-utils/transform.js +31 -12
  6. package/dist/cjs/editor-commands/transform-node-utils/utils.js +4 -1
  7. package/dist/cjs/editor-commands/transformNode.js +65 -66
  8. package/dist/es2019/editor-actions/isTransformToTargetDisabled.js +1 -1
  9. package/dist/es2019/editor-commands/transform-node-utils/steps/convertEachNodeStep.js +28 -0
  10. package/dist/es2019/editor-commands/transform-node-utils/steps/mergeNeighbourListsStep.js +75 -0
  11. package/dist/es2019/editor-commands/transform-node-utils/transform.js +30 -11
  12. package/dist/es2019/editor-commands/transform-node-utils/utils.js +4 -1
  13. package/dist/es2019/editor-commands/transformNode.js +64 -68
  14. package/dist/esm/editor-actions/isTransformToTargetDisabled.js +1 -1
  15. package/dist/esm/editor-commands/transform-node-utils/steps/convertEachNodeStep.js +39 -0
  16. package/dist/esm/editor-commands/transform-node-utils/steps/mergeNeighbourListsStep.js +85 -0
  17. package/dist/esm/editor-commands/transform-node-utils/transform.js +30 -11
  18. package/dist/esm/editor-commands/transform-node-utils/utils.js +4 -1
  19. package/dist/esm/editor-commands/transformNode.js +64 -66
  20. package/dist/types/editor-commands/transform-node-utils/steps/convertEachNodeStep.d.ts +2 -0
  21. package/dist/types/editor-commands/transform-node-utils/steps/mergeNeighbourListsStep.d.ts +32 -0
  22. package/dist/types/editor-commands/transform-node-utils/transform.d.ts +17 -1
  23. package/dist/types/editor-commands/transform-node-utils/utils.d.ts +1 -1
  24. package/dist/types/editor-commands/transformNode.d.ts +1 -1
  25. package/dist/types-ts4.5/editor-commands/transform-node-utils/steps/convertEachNodeStep.d.ts +2 -0
  26. package/dist/types-ts4.5/editor-commands/transform-node-utils/steps/mergeNeighbourListsStep.d.ts +32 -0
  27. package/dist/types-ts4.5/editor-commands/transform-node-utils/transform.d.ts +17 -1
  28. package/dist/types-ts4.5/editor-commands/transform-node-utils/utils.d.ts +1 -1
  29. package/dist/types-ts4.5/editor-commands/transformNode.d.ts +1 -1
  30. package/package.json +3 -3
  31. package/dist/cjs/editor-commands/transform-node-utils/tranformContent.js +0 -18
  32. package/dist/es2019/editor-commands/transform-node-utils/tranformContent.js +0 -12
  33. package/dist/esm/editor-commands/transform-node-utils/tranformContent.js +0 -12
  34. package/dist/types/editor-commands/transform-node-utils/tranformContent.d.ts +0 -3
  35. package/dist/types-ts4.5/editor-commands/transform-node-utils/tranformContent.d.ts +0 -3
@@ -3,74 +3,70 @@ import { startMeasure, stopMeasure } from '@atlaskit/editor-common/performance-m
3
3
  import { expandSelectionToBlockRange } from '@atlaskit/editor-common/selection';
4
4
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
5
5
  import { isNestedNode } from '../ui/utils/isNestedNode';
6
- import { tranformContent } from './transform-node-utils/tranformContent';
6
+ import { convertNodesToTargetType } from './transform-node-utils/transform';
7
7
  import { isListNode } from './transforms/utils';
8
- export const transformNode = api =>
9
- // eslint-disable-next-line no-unused-vars
10
- (targetType, metadata) => {
11
- return ({
12
- tr
13
- }) => {
14
- var _api$blockControls, _api$blockControls$sh;
15
- const preservedSelection = api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : (_api$blockControls$sh = _api$blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.preservedSelection;
16
- if (!preservedSelection) {
17
- return tr;
18
- }
19
-
20
- // Start performance measurement
21
- const measureId = `transformNode_${targetType.name}_${Date.now()}`;
22
- startMeasure(measureId);
23
- const schema = tr.doc.type.schema;
24
- const {
25
- nodes
26
- } = schema;
27
- const {
28
- $from,
29
- $to
30
- } = expandSelectionToBlockRange(preservedSelection);
31
- const selectedParent = $from.parent;
32
- const isParentLayout = selectedParent.type === nodes.layoutColumn;
33
- const isNestedExceptLayout = isNestedNode(preservedSelection, '') && !isParentLayout;
34
- const isList = isListNode(selectedParent);
35
- const slice = tr.doc.slice(isList ? $from.pos - 1 : $from.pos, isList ? $to.pos + 1 : $to.pos);
36
-
37
- // Collect source node information for analytics before transformation
38
- let nodeCount = 0;
39
- const sourceNodeTypes = {};
40
- slice.content.forEach(node => {
41
- nodeCount++;
42
- const nodeTypeName = node.type.name;
43
- sourceNodeTypes[nodeTypeName] = (sourceNodeTypes[nodeTypeName] || 0) + 1;
44
- });
45
- const transformedNodes = tranformContent(slice.content, targetType, schema, isNestedExceptLayout, metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs);
46
- const nodesToDeleteAndInsert = [nodes.mediaSingle];
47
- if (preservedSelection instanceof NodeSelection && nodesToDeleteAndInsert.includes(preservedSelection.node.type)) {
48
- // when node is media single, use tr.replaceWith freeze editor, if modify position, tr.replaceWith creates duplicats
49
- tr.deleteRange($from.pos, $to.pos);
50
- tr.insert($from.pos, transformedNodes);
51
- } else {
52
- tr.replaceWith(isList ? $from.pos - 1 : $from.pos, $to.pos, transformedNodes);
53
- }
54
-
55
- // Stop performance measurement and fire analytics
56
- stopMeasure(measureId, (duration, startTime) => {
57
- var _api$analytics, _api$analytics$action;
58
- api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : (_api$analytics$action = _api$analytics.actions) === null || _api$analytics$action === void 0 ? void 0 : _api$analytics$action.fireAnalyticsEvent({
59
- action: ACTION.TRANSFORMED,
60
- actionSubject: ACTION_SUBJECT.ELEMENT,
61
- actionSubjectId: ACTION_SUBJECT_ID.TRANSFORM,
62
- attributes: {
63
- duration,
64
- isList,
65
- isNested: isNestedExceptLayout,
66
- nodeCount,
67
- sourceNodeTypes,
68
- startTime,
69
- targetNodeType: targetType.name
70
- },
71
- eventType: EVENT_TYPE.OPERATIONAL
72
- });
73
- });
8
+ export const transformNode = api => (targetType, metadata) => ({
9
+ tr
10
+ }) => {
11
+ var _api$blockControls, _api$blockControls$sh;
12
+ const preservedSelection = api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : (_api$blockControls$sh = _api$blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.preservedSelection;
13
+ if (!preservedSelection) {
74
14
  return tr;
75
- };
15
+ }
16
+ const measureId = `transformNode_${targetType.name}_${Date.now()}`;
17
+ startMeasure(measureId);
18
+ const {
19
+ nodes
20
+ } = tr.doc.type.schema;
21
+ const {
22
+ $from,
23
+ $to
24
+ } = expandSelectionToBlockRange(preservedSelection);
25
+ const selectedParent = $from.parent;
26
+ const isParentLayout = selectedParent.type === nodes.layoutColumn;
27
+ const isNested = isNestedNode(preservedSelection, '') && !isParentLayout;
28
+ const isList = isListNode(selectedParent);
29
+ const sliceStart = isList ? $from.pos - 1 : $from.pos;
30
+ const sliceEnd = isList ? $to.pos + 1 : $to.pos;
31
+ const slice = tr.doc.slice(sliceStart, sliceEnd);
32
+ const sourceNodes = [...slice.content.content];
33
+ const sourceNodeTypes = {};
34
+ sourceNodes.forEach(node => {
35
+ const typeName = node.type.name;
36
+ sourceNodeTypes[typeName] = (sourceNodeTypes[typeName] || 0) + 1;
37
+ });
38
+ const resultNodes = convertNodesToTargetType({
39
+ sourceNodes,
40
+ targetNodeType: targetType,
41
+ schema: tr.doc.type.schema,
42
+ isNested,
43
+ targetAttrs: metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs,
44
+ parentNode: selectedParent
45
+ });
46
+ const content = resultNodes.length > 0 ? resultNodes : slice.content;
47
+ if (preservedSelection instanceof NodeSelection && preservedSelection.node.type === nodes.mediaSingle) {
48
+ tr.deleteRange($from.pos, $to.pos);
49
+ tr.insert($from.pos, content);
50
+ } else {
51
+ tr.replaceWith(sliceStart, $to.pos, content);
52
+ }
53
+ stopMeasure(measureId, (duration, startTime) => {
54
+ var _api$analytics, _api$analytics$action;
55
+ api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : (_api$analytics$action = _api$analytics.actions) === null || _api$analytics$action === void 0 ? void 0 : _api$analytics$action.fireAnalyticsEvent({
56
+ action: ACTION.TRANSFORMED,
57
+ actionSubject: ACTION_SUBJECT.ELEMENT,
58
+ actionSubjectId: ACTION_SUBJECT_ID.TRANSFORM,
59
+ attributes: {
60
+ duration,
61
+ isList,
62
+ isNested,
63
+ nodeCount: sourceNodes.length,
64
+ sourceNodeTypes,
65
+ startTime,
66
+ targetNodeType: targetType.name
67
+ },
68
+ eventType: EVENT_TYPE.OPERATIONAL
69
+ });
70
+ });
71
+ return tr;
76
72
  };
@@ -4,7 +4,7 @@ import { isTransformDisabledBasedOnStepsConfig } from '../editor-commands/transf
4
4
  import { toNodeTypeValue } from '../editor-commands/transform-node-utils/types';
5
5
  import { getBlockNodesInRange, getTargetNodeTypeNameInContext } from '../editor-commands/transform-node-utils/utils';
6
6
  export var canParentContainNodeType = function canParentContainNodeType(schema, selectedNodeTypeName, parentNode, nodeTypeName, nodeTypeAttrs) {
7
- var adjustedNodeTypeName = parentNode.type.name === 'layoutColumn' || parentNode.type.name === 'bodiedSyncBlock' ? nodeTypeName : getTargetNodeTypeNameInContext(nodeTypeName, true);
7
+ var adjustedNodeTypeName = getTargetNodeTypeNameInContext(nodeTypeName, true, parentNode);
8
8
  if (!adjustedNodeTypeName) {
9
9
  return false;
10
10
  }
@@ -0,0 +1,39 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ 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; } } }; }
3
+ 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; } }
4
+ 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; }
5
+ import { convertNodesToTargetType } from '../transform';
6
+ export var convertEachNodeStep = function convertEachNodeStep(nodes, context) {
7
+ var schema = context.schema,
8
+ targetNodeTypeName = context.targetNodeTypeName,
9
+ targetAttrs = context.targetAttrs;
10
+ var targetNodeType = schema.nodes[targetNodeTypeName];
11
+ if (!targetNodeType) {
12
+ return nodes;
13
+ }
14
+ var resultNodes = [];
15
+ var _iterator = _createForOfIteratorHelper(nodes),
16
+ _step;
17
+ try {
18
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
19
+ var node = _step.value;
20
+ var transformedNodes = convertNodesToTargetType({
21
+ sourceNodes: [node],
22
+ targetNodeType: targetNodeType,
23
+ schema: schema,
24
+ isNested: false,
25
+ targetAttrs: targetAttrs
26
+ });
27
+ if (transformedNodes.length > 0) {
28
+ resultNodes.push.apply(resultNodes, _toConsumableArray(transformedNodes));
29
+ } else {
30
+ resultNodes.push(node);
31
+ }
32
+ }
33
+ } catch (err) {
34
+ _iterator.e(err);
35
+ } finally {
36
+ _iterator.f();
37
+ }
38
+ return resultNodes;
39
+ };
@@ -0,0 +1,85 @@
1
+ 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; } } }; }
2
+ 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; } }
3
+ 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; }
4
+ import { isListWithIndentation } from '../nodeChecks';
5
+ /**
6
+ * Merges consecutive lists of the same type into a single list.
7
+ * This step is useful after multiToListStep which may create multiple separate lists
8
+ * that should be combined.
9
+ *
10
+ * Handles both nestable lists (bulletList, orderedList, taskList) and
11
+ * non-nestable lists (decisionList).
12
+ *
13
+ * @example
14
+ * Input:
15
+ * - bulletList
16
+ * - listItem "1"
17
+ * - bulletList
18
+ * - listItem "2"
19
+ * - panel (non-list node)
20
+ * - bulletList
21
+ * - listItem "3"
22
+ *
23
+ * Output:
24
+ * - bulletList
25
+ * - listItem "1"
26
+ * - listItem "2"
27
+ * - panel (non-list node)
28
+ * - bulletList
29
+ * - listItem "3"
30
+ *
31
+ * @param nodes - The nodes to process
32
+ * @param context - The transformation context
33
+ * @returns The merged nodes
34
+ */
35
+ export var mergeNeighbourListsStep = function mergeNeighbourListsStep(nodes, context) {
36
+ if (nodes.length === 0) {
37
+ return nodes;
38
+ }
39
+ var schema = context.schema;
40
+ var resultNodes = [];
41
+ var currentList = null;
42
+
43
+ // Check if a node is any type of list (including decisionList)
44
+ var isList = function isList(node) {
45
+ return isListWithIndentation(node.type.name, schema) || node.type.name === 'decisionList';
46
+ };
47
+ var _iterator = _createForOfIteratorHelper(nodes),
48
+ _step;
49
+ try {
50
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
51
+ var node = _step.value;
52
+ // Check if this node is any type of list
53
+ if (isList(node)) {
54
+ if (currentList && currentList.type === node.type) {
55
+ // Merge with the current list by combining their children
56
+ var mergedContent = currentList.content.append(node.content);
57
+ currentList = currentList.type.create(currentList.attrs, mergedContent);
58
+ } else {
59
+ // Start a new list or switch to a different list type
60
+ if (currentList) {
61
+ resultNodes.push(currentList);
62
+ }
63
+ currentList = node;
64
+ }
65
+ } else {
66
+ // Non-list node - push any accumulated list and then this node
67
+ if (currentList) {
68
+ resultNodes.push(currentList);
69
+ currentList = null;
70
+ }
71
+ resultNodes.push(node);
72
+ }
73
+ }
74
+
75
+ // Don't forget the last list if we ended with one
76
+ } catch (err) {
77
+ _iterator.e(err);
78
+ } finally {
79
+ _iterator.f();
80
+ }
81
+ if (currentList) {
82
+ resultNodes.push(currentList);
83
+ }
84
+ return resultNodes;
85
+ };
@@ -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 @@ var 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 @@ var 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,22 +236,37 @@ var getTransformStepsForNodeTypes = function getTransformStepsForNodeTypes(selec
232
236
  var steps = overrideSteps !== null && overrideSteps !== void 0 ? overrideSteps : TRANSFORM_STEPS[fromCategory][toCategory];
233
237
  return steps;
234
238
  };
235
- export var getOutputNodes = function getOutputNodes(_ref) {
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 var convertNodesToTargetType = function convertNodesToTargetType(_ref) {
236
255
  var sourceNodes = _ref.sourceNodes,
237
256
  targetNodeType = _ref.targetNodeType,
238
257
  schema = _ref.schema,
239
258
  isNested = _ref.isNested,
240
- targetAttrs = _ref.targetAttrs;
259
+ targetAttrs = _ref.targetAttrs,
260
+ parentNode = _ref.parentNode;
241
261
  var sourceNode = sourceNodes.at(0);
242
262
  if (!sourceNode) {
243
- return;
263
+ return sourceNodes;
244
264
  }
245
265
  var selectedNodeTypeName = toNodeTypeValue(getNodeName(sourceNodes));
246
266
  var initialTargetNodeTypeName = toNodeTypeValue(targetNodeType.name);
247
- var targetNodeTypeName = getTargetNodeTypeNameInContext(initialTargetNodeTypeName, isNested);
267
+ var targetNodeTypeName = getTargetNodeTypeNameInContext(initialTargetNodeTypeName, isNested, parentNode);
248
268
  if (!selectedNodeTypeName || !targetNodeTypeName) {
249
- // We may decide to return an empty array or undefined here
250
- return;
269
+ return sourceNodes;
251
270
  }
252
271
  var steps = getTransformStepsForNodeTypes(selectedNodeTypeName, targetNodeTypeName);
253
272
  var context = {
@@ -258,7 +277,7 @@ export var getOutputNodes = function getOutputNodes(_ref) {
258
277
  targetAttrs: targetAttrs
259
278
  };
260
279
  if (!steps || steps.length === 0) {
261
- return;
280
+ return sourceNodes;
262
281
  }
263
282
  return steps.reduce(function (nodes, step) {
264
283
  return step(nodes, context);
@@ -43,7 +43,10 @@ export var getSelectedNode = function getSelectedNode(selection) {
43
43
  }
44
44
  return undefined;
45
45
  };
46
- export var getTargetNodeTypeNameInContext = function getTargetNodeTypeNameInContext(nodeTypeName, isNested) {
46
+ export var getTargetNodeTypeNameInContext = function getTargetNodeTypeNameInContext(nodeTypeName, isNested, parentNode) {
47
+ if (parentNode && isNested && (parentNode.type.name === 'layoutColumn' || parentNode.type.name === 'bodiedSyncBlock')) {
48
+ return nodeTypeName;
49
+ }
47
50
  if (nodeTypeName === 'expand' && isNested) {
48
51
  return 'nestedExpand';
49
52
  }
@@ -1,75 +1,73 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
1
2
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
3
  import { startMeasure, stopMeasure } from '@atlaskit/editor-common/performance-measures';
3
4
  import { expandSelectionToBlockRange } from '@atlaskit/editor-common/selection';
4
5
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
5
6
  import { isNestedNode } from '../ui/utils/isNestedNode';
6
- import { tranformContent } from './transform-node-utils/tranformContent';
7
+ import { convertNodesToTargetType } from './transform-node-utils/transform';
7
8
  import { isListNode } from './transforms/utils';
8
9
  export var transformNode = function transformNode(api) {
9
- return (
10
- // eslint-disable-next-line no-unused-vars
11
- function (targetType, metadata) {
12
- return function (_ref) {
13
- var _api$blockControls;
14
- var tr = _ref.tr;
15
- 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;
16
- if (!preservedSelection) {
17
- return tr;
18
- }
19
-
20
- // Start performance measurement
21
- var measureId = "transformNode_".concat(targetType.name, "_").concat(Date.now());
22
- startMeasure(measureId);
23
- var schema = tr.doc.type.schema;
24
- var nodes = schema.nodes;
25
- var _expandSelectionToBlo = expandSelectionToBlockRange(preservedSelection),
26
- $from = _expandSelectionToBlo.$from,
27
- $to = _expandSelectionToBlo.$to;
28
- var selectedParent = $from.parent;
29
- var isParentLayout = selectedParent.type === nodes.layoutColumn;
30
- var isNestedExceptLayout = isNestedNode(preservedSelection, '') && !isParentLayout;
31
- var isList = isListNode(selectedParent);
32
- var slice = tr.doc.slice(isList ? $from.pos - 1 : $from.pos, isList ? $to.pos + 1 : $to.pos);
33
-
34
- // Collect source node information for analytics before transformation
35
- var nodeCount = 0;
36
- var sourceNodeTypes = {};
37
- slice.content.forEach(function (node) {
38
- nodeCount++;
39
- var nodeTypeName = node.type.name;
40
- sourceNodeTypes[nodeTypeName] = (sourceNodeTypes[nodeTypeName] || 0) + 1;
41
- });
42
- var transformedNodes = tranformContent(slice.content, targetType, schema, isNestedExceptLayout, metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs);
43
- var nodesToDeleteAndInsert = [nodes.mediaSingle];
44
- if (preservedSelection instanceof NodeSelection && nodesToDeleteAndInsert.includes(preservedSelection.node.type)) {
45
- // when node is media single, use tr.replaceWith freeze editor, if modify position, tr.replaceWith creates duplicats
46
- tr.deleteRange($from.pos, $to.pos);
47
- tr.insert($from.pos, transformedNodes);
48
- } else {
49
- tr.replaceWith(isList ? $from.pos - 1 : $from.pos, $to.pos, transformedNodes);
50
- }
51
-
52
- // Stop performance measurement and fire analytics
53
- stopMeasure(measureId, function (duration, startTime) {
54
- var _api$analytics;
55
- 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({
56
- action: ACTION.TRANSFORMED,
57
- actionSubject: ACTION_SUBJECT.ELEMENT,
58
- actionSubjectId: ACTION_SUBJECT_ID.TRANSFORM,
59
- attributes: {
60
- duration: duration,
61
- isList: isList,
62
- isNested: isNestedExceptLayout,
63
- nodeCount: nodeCount,
64
- sourceNodeTypes: sourceNodeTypes,
65
- startTime: startTime,
66
- targetNodeType: targetType.name
67
- },
68
- eventType: EVENT_TYPE.OPERATIONAL
69
- });
70
- });
10
+ return function (targetType, metadata) {
11
+ return function (_ref) {
12
+ var _api$blockControls;
13
+ var tr = _ref.tr;
14
+ 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;
15
+ if (!preservedSelection) {
71
16
  return tr;
72
- };
73
- }
74
- );
17
+ }
18
+ var measureId = "transformNode_".concat(targetType.name, "_").concat(Date.now());
19
+ startMeasure(measureId);
20
+ var nodes = tr.doc.type.schema.nodes;
21
+ var _expandSelectionToBlo = expandSelectionToBlockRange(preservedSelection),
22
+ $from = _expandSelectionToBlo.$from,
23
+ $to = _expandSelectionToBlo.$to;
24
+ var selectedParent = $from.parent;
25
+ var isParentLayout = selectedParent.type === nodes.layoutColumn;
26
+ var isNested = isNestedNode(preservedSelection, '') && !isParentLayout;
27
+ var isList = isListNode(selectedParent);
28
+ var sliceStart = isList ? $from.pos - 1 : $from.pos;
29
+ var sliceEnd = isList ? $to.pos + 1 : $to.pos;
30
+ var slice = tr.doc.slice(sliceStart, sliceEnd);
31
+ var sourceNodes = _toConsumableArray(slice.content.content);
32
+ var sourceNodeTypes = {};
33
+ sourceNodes.forEach(function (node) {
34
+ var typeName = node.type.name;
35
+ sourceNodeTypes[typeName] = (sourceNodeTypes[typeName] || 0) + 1;
36
+ });
37
+ var resultNodes = convertNodesToTargetType({
38
+ sourceNodes: sourceNodes,
39
+ targetNodeType: targetType,
40
+ schema: tr.doc.type.schema,
41
+ isNested: isNested,
42
+ targetAttrs: metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs,
43
+ parentNode: selectedParent
44
+ });
45
+ var content = resultNodes.length > 0 ? resultNodes : slice.content;
46
+ if (preservedSelection instanceof NodeSelection && preservedSelection.node.type === nodes.mediaSingle) {
47
+ tr.deleteRange($from.pos, $to.pos);
48
+ tr.insert($from.pos, content);
49
+ } else {
50
+ tr.replaceWith(sliceStart, $to.pos, content);
51
+ }
52
+ stopMeasure(measureId, function (duration, startTime) {
53
+ var _api$analytics;
54
+ 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({
55
+ action: ACTION.TRANSFORMED,
56
+ actionSubject: ACTION_SUBJECT.ELEMENT,
57
+ actionSubjectId: ACTION_SUBJECT_ID.TRANSFORM,
58
+ attributes: {
59
+ duration: duration,
60
+ isList: isList,
61
+ isNested: isNested,
62
+ nodeCount: sourceNodes.length,
63
+ sourceNodeTypes: sourceNodeTypes,
64
+ startTime: startTime,
65
+ targetNodeType: targetType.name
66
+ },
67
+ eventType: EVENT_TYPE.OPERATIONAL
68
+ });
69
+ });
70
+ return tr;
71
+ };
72
+ };
75
73
  };
@@ -0,0 +1,2 @@
1
+ import type { TransformStep } from '../types';
2
+ export declare const convertEachNodeStep: TransformStep;
@@ -0,0 +1,32 @@
1
+ import type { TransformStep } from '../types';
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 declare const mergeNeighbourListsStep: TransformStep;
@@ -2,11 +2,27 @@ import { type Node as PMNode, type NodeType, type Schema } from '@atlaskit/edito
2
2
  import type { NodeTypeName } from './types';
3
3
  interface GetOutputNodesArgs {
4
4
  isNested: boolean;
5
+ parentNode?: PMNode;
5
6
  schema: Schema;
6
7
  sourceNodes: PMNode[];
7
8
  targetAttrs?: Record<string, unknown>;
8
9
  targetNodeType: NodeType;
9
10
  }
10
- export declare const getOutputNodes: ({ sourceNodes, targetNodeType, schema, isNested, targetAttrs, }: GetOutputNodesArgs) => PMNode[] | undefined;
11
+ /**
12
+ * Convert a list of nodes to a target node type.
13
+ * If no steps are found, the source nodes are returned unchanged.
14
+ * If steps are found, they are applied to the source nodes in order.
15
+ * If a step returns an empty array, the source nodes are returned.
16
+ * If a step returns a non-empty array, that array is returned.
17
+ * @param args - The conversion arguments
18
+ * @param args.sourceNodes - The list of nodes to convert
19
+ * @param args.targetNodeType - The type of node to convert into
20
+ * @param args.schema - The schema to use for the conversion
21
+ * @param args.isNested - Whether the conversion is nested
22
+ * @param args.targetAttrs - The attributes to use for the conversion
23
+ * @param args.parentNode - The parent node of the selected node
24
+ * @returns The converted list of nodes
25
+ */
26
+ export declare const convertNodesToTargetType: ({ sourceNodes, targetNodeType, schema, isNested, targetAttrs, parentNode, }: GetOutputNodesArgs) => PMNode[];
11
27
  export declare const isTransformDisabledBasedOnStepsConfig: (selectedNodeType: NodeTypeName, targetNodeType: NodeTypeName) => boolean;
12
28
  export {};
@@ -3,7 +3,7 @@ import type { Selection } from '@atlaskit/editor-prosemirror/state';
3
3
  import { type ContentNodeWithPos } from '@atlaskit/editor-prosemirror/utils';
4
4
  import type { NodeTypeName } from './types';
5
5
  export declare const getSelectedNode: (selection: Selection) => ContentNodeWithPos | undefined;
6
- export declare const getTargetNodeTypeNameInContext: (nodeTypeName: NodeTypeName | null, isNested?: boolean) => NodeTypeName | null;
6
+ export declare const getTargetNodeTypeNameInContext: (nodeTypeName: NodeTypeName | null, isNested?: boolean, parentNode?: PMNode) => NodeTypeName | null;
7
7
  /**
8
8
  * Converts a nestedExpand to a regular expand node.
9
9
  * NestedExpands can only exist inside expands, so when breaking out or placing
@@ -1,5 +1,5 @@
1
1
  import type { EditorCommand, ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
- import { type NodeType } from '@atlaskit/editor-prosemirror/model';
2
+ import type { NodeType } from '@atlaskit/editor-prosemirror/model';
3
3
  import type { BlockMenuPlugin } from '../blockMenuPluginType';
4
4
  import type { TransformNodeMetadata } from './transforms/types';
5
5
  export declare const transformNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: NodeType, metadata?: TransformNodeMetadata) => EditorCommand;
@@ -0,0 +1,2 @@
1
+ import type { TransformStep } from '../types';
2
+ export declare const convertEachNodeStep: TransformStep;
@@ -0,0 +1,32 @@
1
+ import type { TransformStep } from '../types';
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 declare const mergeNeighbourListsStep: TransformStep;