@atlaskit/editor-plugin-tasks-and-decisions 21.0.11 → 22.0.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.
@@ -2,14 +2,11 @@ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol
2
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
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
4
  import { uuid } from '@atlaskit/adf-schema/uuid';
5
- import { flattenList as flattenListBase } from '@atlaskit/editor-common/lists';
6
- import { fg } from '@atlaskit/platform-feature-flags/fg';
7
-
8
5
  /**
9
- * Flattens a taskList into one item per task item, recording which items the
10
- * selection touches.
6
+ * Flattens a taskList tree into an array of task items with computed depths.
7
+ * Only selected items have their depth adjusted by indentDelta.
11
8
  */
12
- function flattenTaskListImpl(options) {
9
+ export function flattenTaskList(options) {
13
10
  var doc = options.doc,
14
11
  rootListStart = options.rootListStart,
15
12
  rootListEnd = options.rootListEnd,
@@ -66,35 +63,6 @@ function flattenTaskListImpl(options) {
66
63
  };
67
64
  }
68
65
 
69
- /**
70
- * Flattens a taskList tree into an array of task items with computed depths.
71
- * Only selected items have their depth adjusted by indentDelta.
72
- */
73
- export function flattenTaskList(options) {
74
- if (fg('platform_editor_flexible_list_normalization_fix')) {
75
- return flattenTaskListImpl(options);
76
- }
77
- var _options$doc$type$sch = options.doc.type.schema.nodes,
78
- taskList = _options$doc$type$sch.taskList,
79
- taskItem = _options$doc$type$sch.taskItem,
80
- blockTaskItem = _options$doc$type$sch.blockTaskItem;
81
- return flattenListBase(options, {
82
- isContentNode: function isContentNode(node, parent) {
83
- var isTaskItemType = node.type === taskItem || blockTaskItem != null && node.type === blockTaskItem;
84
- return isTaskItemType && parent != null && parent.type === taskList;
85
- },
86
- getSelectionBounds: function getSelectionBounds(node, pos) {
87
- return {
88
- start: pos,
89
- end: pos + node.nodeSize
90
- };
91
- },
92
- getDepth: function getDepth(resolvedDepth, rootDepth) {
93
- return resolvedDepth - rootDepth - 1;
94
- }
95
- });
96
- }
97
-
98
66
  // Each stack entry collects children for a taskList at a given depth.
99
67
  // The root entry (depth -1) is special: its children become the content
100
68
  // of the outermost taskList directly (not wrapped in another taskList).
@@ -21,9 +21,7 @@ import { IconAction, IconDecision } from '@atlaskit/editor-common/quick-insert';
21
21
  import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
22
22
  import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
23
23
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
24
- import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
25
- import { editorExperiment } from '@atlaskit/tmp-editor-statsig/editor-experiment';
26
- import { closeRequestEditPopupAt, getCurrentIndentLevel, getTaskItemIndex, isInsideTask } from './pm-plugins/helpers';
24
+ import { closeRequestEditPopupAt, getCurrentIndentLevel, isInsideTask } from './pm-plugins/helpers';
27
25
  // Ignored via go/ees005
28
26
  // eslint-disable-next-line import/no-named-as-default
29
27
  import inputRulePlugin from './pm-plugins/input-rules';
@@ -87,7 +85,7 @@ function ContentComponent(_ref2) {
87
85
  });
88
86
  }
89
87
  export var tasksAndDecisionsPlugin = function tasksAndDecisionsPlugin(_ref3) {
90
- var _api$analytics2, _api$analytics3, _api$analytics4;
88
+ var _api$blockMenu, _api$analytics2, _api$analytics3, _api$analytics4;
91
89
  var _ref3$config = _ref3.config,
92
90
  _ref3$config2 = _ref3$config === void 0 ? {} : _ref3$config,
93
91
  allowNestedTasks = _ref3$config2.allowNestedTasks,
@@ -130,50 +128,47 @@ export var tasksAndDecisionsPlugin = function tasksAndDecisionsPlugin(_ref3) {
130
128
  });
131
129
  });
132
130
  }
133
- if (editorExperiment('platform_editor_block_menu', true)) {
134
- var _api$blockMenu;
135
- api === null || api === void 0 || (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 || _api$blockMenu.actions.registerBlockMenuComponents([{
136
- type: 'block-menu-item',
137
- key: TRANSFORM_STRUCTURE_TASK_LIST_MENU_ITEM.key,
138
- parent: {
139
- type: 'block-menu-section',
140
- key: TRANSFORM_STRUCTURE_MENU_SECTION.key,
141
- rank: TRANSFORM_STRUCTURE_MENU_SECTION_RANK[TRANSFORM_STRUCTURE_TASK_LIST_MENU_ITEM.key]
142
- },
143
- component: function component() {
144
- var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
145
- isSuggested = _ref5.isSuggested;
146
- return /*#__PURE__*/React.createElement(TaskListBlockMenuItem, {
147
- api: api,
148
- isSuggested: isSuggested
149
- });
150
- },
151
- isHidden: function isHidden() {
152
- var _api$blockMenu2;
153
- return Boolean(api === null || api === void 0 || (_api$blockMenu2 = api.blockMenu) === null || _api$blockMenu2 === void 0 ? void 0 : _api$blockMenu2.actions.isTransformOptionDisabled(TASK_LIST_NODE_NAME));
154
- }
155
- }, {
156
- type: 'block-menu-item',
157
- key: TRANSFORM_STRUCTURE_DECISION_MENU_ITEM.key,
158
- parent: {
159
- type: 'block-menu-section',
160
- key: TRANSFORM_STRUCTURE_MENU_SECTION.key,
161
- rank: TRANSFORM_STRUCTURE_MENU_SECTION_RANK[TRANSFORM_STRUCTURE_DECISION_MENU_ITEM.key]
162
- },
163
- component: function component() {
164
- var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
165
- isSuggested = _ref6.isSuggested;
166
- return /*#__PURE__*/React.createElement(DecisionListBlockMenuItem, {
167
- api: api,
168
- isSuggested: isSuggested
169
- });
170
- },
171
- isHidden: function isHidden() {
172
- var _api$blockMenu3;
173
- return Boolean(api === null || api === void 0 || (_api$blockMenu3 = api.blockMenu) === null || _api$blockMenu3 === void 0 ? void 0 : _api$blockMenu3.actions.isTransformOptionDisabled(DECISION_LIST_NODE_NAME));
174
- }
175
- }]);
176
- }
131
+ api === null || api === void 0 || (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 || _api$blockMenu.actions.registerBlockMenuComponents([{
132
+ type: 'block-menu-item',
133
+ key: TRANSFORM_STRUCTURE_TASK_LIST_MENU_ITEM.key,
134
+ parent: {
135
+ type: 'block-menu-section',
136
+ key: TRANSFORM_STRUCTURE_MENU_SECTION.key,
137
+ rank: TRANSFORM_STRUCTURE_MENU_SECTION_RANK[TRANSFORM_STRUCTURE_TASK_LIST_MENU_ITEM.key]
138
+ },
139
+ component: function component() {
140
+ var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
141
+ isSuggested = _ref5.isSuggested;
142
+ return /*#__PURE__*/React.createElement(TaskListBlockMenuItem, {
143
+ api: api,
144
+ isSuggested: isSuggested
145
+ });
146
+ },
147
+ isHidden: function isHidden() {
148
+ var _api$blockMenu2;
149
+ return Boolean(api === null || api === void 0 || (_api$blockMenu2 = api.blockMenu) === null || _api$blockMenu2 === void 0 ? void 0 : _api$blockMenu2.actions.isTransformOptionDisabled(TASK_LIST_NODE_NAME));
150
+ }
151
+ }, {
152
+ type: 'block-menu-item',
153
+ key: TRANSFORM_STRUCTURE_DECISION_MENU_ITEM.key,
154
+ parent: {
155
+ type: 'block-menu-section',
156
+ key: TRANSFORM_STRUCTURE_MENU_SECTION.key,
157
+ rank: TRANSFORM_STRUCTURE_MENU_SECTION_RANK[TRANSFORM_STRUCTURE_DECISION_MENU_ITEM.key]
158
+ },
159
+ component: function component() {
160
+ var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
161
+ isSuggested = _ref6.isSuggested;
162
+ return /*#__PURE__*/React.createElement(DecisionListBlockMenuItem, {
163
+ api: api,
164
+ isSuggested: isSuggested
165
+ });
166
+ },
167
+ isHidden: function isHidden() {
168
+ var _api$blockMenu3;
169
+ return Boolean(api === null || api === void 0 || (_api$blockMenu3 = api.blockMenu) === null || _api$blockMenu3 === void 0 ? void 0 : _api$blockMenu3.actions.isTransformOptionDisabled(DECISION_LIST_NODE_NAME));
170
+ }
171
+ }]);
177
172
  return {
178
173
  name: 'taskDecision',
179
174
  nodes: function nodes() {
@@ -200,13 +195,11 @@ export var tasksAndDecisionsPlugin = function tasksAndDecisionsPlugin(_ref3) {
200
195
  }
201
196
  var pluginState = taskPluginKey.getState(editorState);
202
197
  var indentLevel = getCurrentIndentLevel(editorState.selection) || 0;
203
- var itemIndex = getTaskItemIndex(editorState);
204
- var isFlexibleListIndentationEnabled = expValEqualsNoExposure('platform_editor_flexible_list_indentation', 'isEnabled', true);
205
198
  return {
206
199
  focusedTaskItemLocalId: (pluginState === null || pluginState === void 0 ? void 0 : pluginState.focusedTaskItemLocalId) || null,
207
200
  isInsideTask: isInsideTask(editorState),
208
- indentDisabled: !isFlexibleListIndentationEnabled && itemIndex === 0 || indentLevel >= MAX_INDENTATION_LEVEL,
209
- outdentDisabled: isFlexibleListIndentationEnabled ? indentLevel <= 0 : indentLevel <= 1,
201
+ indentDisabled: indentLevel >= MAX_INDENTATION_LEVEL,
202
+ outdentDisabled: indentLevel <= 0,
210
203
  // hasEditPermission is assumed to be true if pluginState.hasEditPermission is undefined
211
204
  // this allows the default plugin state to initialise as true if the extra configuration is not provided
212
205
  hasEditPermission: (pluginState === null || pluginState === void 0 ? void 0 : pluginState.hasEditPermission) !== undefined ? pluginState === null || pluginState === void 0 ? void 0 : pluginState.hasEditPermission : true,
@@ -1,24 +1,5 @@
1
1
  import type { Command } from '@atlaskit/editor-common/types';
2
2
  import type { ResolvedPos } from '@atlaskit/editor-prosemirror/model';
3
- export declare const liftSelection: Command;
4
- /**
5
- * Wraps the current selection in a task list, respecting a maximum indentation depth of 6 levels.
6
- *
7
- * - Normalizes the selection to ensure it covers complete task items.
8
- * - Determines the maximum depth of task list nesting within the selection.
9
- * - If the selection is already nested at or beyond the maximum depth, the command does nothing.
10
- * - Calculates the block range to wrap, handling both regular and block task items.
11
- * - Wraps the block in a task list to increase indentation or create a new task list if necessary.
12
- *
13
- * @param state - The current editor state.
14
- * @param dispatch - The dispatch function to apply the transaction.
15
- * @returns `true` if the command was handled (even if no changes were made), otherwise `false`.
16
- * @example
17
- * ```typescript
18
- * autoJoin(wrapSelectionInTaskList, ['taskList']))(state, dispatch);
19
- * ```
20
- */
21
- export declare const wrapSelectionInTaskList: Command;
22
3
  /**
23
4
  * Tries to move the paragraph content near the given position into the taskItem or decisionItem
24
5
  * before it.
@@ -1,5 +1,5 @@
1
1
  import { NodeRange } from '@atlaskit/editor-prosemirror/model';
2
- import type { Node, NodeType, ResolvedPos } from '@atlaskit/editor-prosemirror/model';
2
+ import type { Node, ResolvedPos } from '@atlaskit/editor-prosemirror/model';
3
3
  import type { EditorState, Selection, Transaction } from '@atlaskit/editor-prosemirror/state';
4
4
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
5
5
  import type { TaskItemData } from './types';
@@ -43,19 +43,6 @@ export declare const getTaskItemIndex: (state: EditorState) => number;
43
43
  * @param $startPos Position to start walking from.
44
44
  */
45
45
  export declare const walkOut: ($startPos: ResolvedPos) => ResolvedPos;
46
- /**
47
- * Finds the height of a tree-like structure, given any position inside it.
48
- *
49
- * Traverses from the top of the tree to all leaf nodes, and returns the length
50
- * of the longest path.
51
- *
52
- * This means you can use it with things like taskList, which
53
- * do not nest themselves inside taskItems but rather as adjacent children.
54
- *
55
- * @param $pos Any position inside the tree.
56
- * @param types The node types to consider traversable
57
- */
58
- export declare const subtreeHeight: ($from: ResolvedPos, $to: ResolvedPos, types: NodeType[]) => number;
59
46
  /**
60
47
  * Determines if the current selection is inside an empty taskItem, decisionItem, or blockTaskItem.
61
48
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-tasks-and-decisions",
3
- "version": "21.0.11",
3
+ "version": "22.0.1",
4
4
  "description": "Tasks and decisions plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -29,14 +29,14 @@
29
29
  "@atlaskit/adf-schema": "^57.5.0",
30
30
  "@atlaskit/analytics-namespaced-context": "^8.2.0",
31
31
  "@atlaskit/css": "^1.1.0",
32
- "@atlaskit/editor-plugin-analytics": "^18.0.0",
33
- "@atlaskit/editor-plugin-block-menu": "^17.0.0",
34
- "@atlaskit/editor-plugin-context-identifier": "^18.0.0",
35
- "@atlaskit/editor-plugin-editor-viewmode": "^20.0.0",
36
- "@atlaskit/editor-plugin-selection": "^18.0.0",
37
- "@atlaskit/editor-plugin-toolbar": "^15.0.0",
38
- "@atlaskit/editor-plugin-type-ahead": "^19.1.0",
39
- "@atlaskit/editor-prosemirror": "^8.0.0",
32
+ "@atlaskit/editor-plugin-analytics": "^19.0.0",
33
+ "@atlaskit/editor-plugin-block-menu": "^18.0.0",
34
+ "@atlaskit/editor-plugin-context-identifier": "^19.0.0",
35
+ "@atlaskit/editor-plugin-editor-viewmode": "^21.0.0",
36
+ "@atlaskit/editor-plugin-selection": "^19.0.0",
37
+ "@atlaskit/editor-plugin-toolbar": "^16.0.0",
38
+ "@atlaskit/editor-plugin-type-ahead": "^20.0.0",
39
+ "@atlaskit/editor-prosemirror": "^9.0.0",
40
40
  "@atlaskit/editor-shared-styles": "^4.3.0",
41
41
  "@atlaskit/editor-toolbar": "^2.6.0",
42
42
  "@atlaskit/editor-toolbar-model": "^1.2.0",
@@ -47,14 +47,14 @@
47
47
  "@atlaskit/primitives": "^22.5.0",
48
48
  "@atlaskit/prosemirror-input-rules": "^4.1.0",
49
49
  "@atlaskit/task-decision": "^21.10.0",
50
- "@atlaskit/tmp-editor-statsig": "^199.0.0",
51
- "@atlaskit/tokens": "^18.0.0",
50
+ "@atlaskit/tmp-editor-statsig": "^200.0.0",
51
+ "@atlaskit/tokens": "^18.2.0",
52
52
  "@babel/runtime": "^7.0.0",
53
53
  "@compiled/react": "^1.0.2",
54
54
  "bind-event-listener": "^3.0.0"
55
55
  },
56
56
  "peerDependencies": {
57
- "@atlaskit/editor-common": "^122.11.0",
57
+ "@atlaskit/editor-common": "^123.0.0",
58
58
  "react": "^18.2.0 || ^19.2.0",
59
59
  "react-dom": "^18.2.0 || ^19.2.0",
60
60
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
@@ -76,9 +76,6 @@
76
76
  "platform_editor_element_browser_analytic": {
77
77
  "type": "boolean"
78
78
  },
79
- "platform_editor_flexible_list_normalization_fix": {
80
- "type": "boolean"
81
- },
82
79
  "platform_editor_markdown_compatible_toolbar": {
83
80
  "type": "boolean"
84
81
  }
@@ -1,150 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.applyTaskListNormalisationFixes = applyTaskListNormalisationFixes;
8
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
- var _transform = require("@atlaskit/editor-prosemirror/transform");
11
- var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
12
- 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; } } }; }
13
- 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; } }
14
- 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; }
15
- function getAffectedTaskListsFromTransactions(transactions, doc, schema) {
16
- var taskList = schema.nodes.taskList;
17
- if (!taskList) {
18
- return new Map();
19
- }
20
- var result = new Map();
21
- var _iterator = _createForOfIteratorHelper(transactions),
22
- _step;
23
- try {
24
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
25
- var tr = _step.value;
26
- var _iterator2 = _createForOfIteratorHelper(tr.steps),
27
- _step2;
28
- try {
29
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
30
- var step = _step2.value;
31
- // ReplaceStep and ReplaceAroundStep both have from/to — other step types are skipped.
32
- if (!(step instanceof _transform.ReplaceStep) && !(step instanceof _transform.ReplaceAroundStep)) {
33
- continue;
34
- }
35
- // Check both the start and end of each changed range, mapped to post-transaction positions.
36
- for (var _i = 0, _arr = [step.from, step.to]; _i < _arr.length; _i++) {
37
- var rawPos = _arr[_i];
38
- var mappedPos = Math.min(tr.mapping.map(rawPos), doc.content.size - 1);
39
- var $pos = doc.resolve(mappedPos);
40
- // Walk ancestors from inner to outer, recording the outermost taskList node.
41
- // Once we find a taskList and then exit list structure (hit a non-taskList ancestor),
42
- // break early — prevents container nodes (e.g. panel) from causing us to
43
- // return an outer taskList in a different structural context.
44
- var rootTaskListPos = null;
45
- var rootTaskListNode = null;
46
- for (var depth = $pos.depth; depth >= 0; depth--) {
47
- var node = $pos.node(depth);
48
- if (node.type === taskList) {
49
- rootTaskListPos = $pos.before(depth);
50
- rootTaskListNode = node;
51
- } else if (rootTaskListNode !== null && node.type !== schema.nodes.taskItem) {
52
- // We've exited the taskList structure — stop walking.
53
- break;
54
- }
55
- }
56
- if (rootTaskListPos !== null && rootTaskListNode !== null) {
57
- result.set(rootTaskListPos, rootTaskListNode);
58
- }
59
- }
60
- }
61
- } catch (err) {
62
- _iterator2.e(err);
63
- } finally {
64
- _iterator2.f();
65
- }
66
- }
67
- } catch (err) {
68
- _iterator.e(err);
69
- } finally {
70
- _iterator.f();
71
- }
72
- return result;
73
- }
74
- function applyTaskListNormalisationFixes(_ref) {
75
- var doc = _ref.doc,
76
- schema = _ref.schema,
77
- tr = _ref.tr,
78
- transactions = _ref.transactions;
79
- var _schema$nodes = schema.nodes,
80
- taskList = _schema$nodes.taskList,
81
- taskItem = _schema$nodes.taskItem;
82
- if (!taskList || !taskItem) {
83
- return tr;
84
- }
85
- var affectedTaskLists = getAffectedTaskListsFromTransactions(transactions, doc, schema);
86
- if (affectedTaskLists.size === 0) {
87
- return tr;
88
- }
89
-
90
- // Sort by position descending so we process deeper/later positions first,
91
- // preventing earlier insertions from shifting later positions.
92
- var sortedEntries = (0, _toConsumableArray2.default)(affectedTaskLists.entries()).sort(function (_ref2, _ref3) {
93
- var _ref4 = (0, _slicedToArray2.default)(_ref2, 1),
94
- a = _ref4[0];
95
- var _ref5 = (0, _slicedToArray2.default)(_ref3, 1),
96
- b = _ref5[0];
97
- return b - a;
98
- });
99
- var _iterator3 = _createForOfIteratorHelper(sortedEntries),
100
- _step3;
101
- try {
102
- var _loop = function _loop() {
103
- var _step3$value = (0, _slicedToArray2.default)(_step3.value, 1),
104
- taskListPos = _step3$value[0];
105
- // Re-resolve the taskList node from the current transaction doc (post-operation state).
106
- var mappedTaskListPos = tr.mapping.map(taskListPos);
107
- var currentTaskListNode = tr.doc.nodeAt(mappedTaskListPos);
108
- if (!currentTaskListNode) {
109
- return 1; // continue
110
- }
111
- if (!(0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_flexible_list_indentation', 'isEnabled', true)) {
112
- // Collect positions of all taskList nodes (at any depth) whose direct children
113
- // include a taskList — this is the invalid structure. The taskList schema requires
114
- // taskItem as children, not nested taskLists directly.
115
- // Process in reverse order so higher-position insertions don't shift lower positions.
116
- var invalidTaskListPositions = [];
117
- currentTaskListNode.descendants(function (node, offsetPos) {
118
- if (node.type === taskList) {
119
- // A taskList as the FIRST child of another taskList is invalid — it means a
120
- // delete or paste removed the leading taskItem, leaving a bare nested list.
121
- // A taskList that follows a taskItem is valid (that's normal indentation).
122
- var firstChild = node.firstChild;
123
- if (firstChild && firstChild.type === taskList) {
124
- var pos = mappedTaskListPos + 1 + offsetPos + 1;
125
- invalidTaskListPositions.push(pos);
126
- }
127
- }
128
- return true;
129
- });
130
-
131
- // Process in reverse (highest positions first).
132
- for (var i = invalidTaskListPositions.length - 1; i >= 0; i--) {
133
- var remappedPos = tr.mapping.map(invalidTaskListPositions[i]);
134
- var emptyTaskItem = taskItem.createAndFill();
135
- if (emptyTaskItem) {
136
- tr.insert(remappedPos, emptyTaskItem);
137
- }
138
- }
139
- }
140
- };
141
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
142
- if (_loop()) continue;
143
- }
144
- } catch (err) {
145
- _iterator3.e(err);
146
- } finally {
147
- _iterator3.f();
148
- }
149
- return tr;
150
- }
@@ -1,104 +0,0 @@
1
- import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
2
- import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
3
- function getAffectedTaskListsFromTransactions(transactions, doc, schema) {
4
- const {
5
- taskList
6
- } = schema.nodes;
7
- if (!taskList) {
8
- return new Map();
9
- }
10
- const result = new Map();
11
- for (const tr of transactions) {
12
- for (const step of tr.steps) {
13
- // ReplaceStep and ReplaceAroundStep both have from/to — other step types are skipped.
14
- if (!(step instanceof ReplaceStep) && !(step instanceof ReplaceAroundStep)) {
15
- continue;
16
- }
17
- // Check both the start and end of each changed range, mapped to post-transaction positions.
18
- for (const rawPos of [step.from, step.to]) {
19
- const mappedPos = Math.min(tr.mapping.map(rawPos), doc.content.size - 1);
20
- const $pos = doc.resolve(mappedPos);
21
- // Walk ancestors from inner to outer, recording the outermost taskList node.
22
- // Once we find a taskList and then exit list structure (hit a non-taskList ancestor),
23
- // break early — prevents container nodes (e.g. panel) from causing us to
24
- // return an outer taskList in a different structural context.
25
- let rootTaskListPos = null;
26
- let rootTaskListNode = null;
27
- for (let depth = $pos.depth; depth >= 0; depth--) {
28
- const node = $pos.node(depth);
29
- if (node.type === taskList) {
30
- rootTaskListPos = $pos.before(depth);
31
- rootTaskListNode = node;
32
- } else if (rootTaskListNode !== null && node.type !== schema.nodes.taskItem) {
33
- // We've exited the taskList structure — stop walking.
34
- break;
35
- }
36
- }
37
- if (rootTaskListPos !== null && rootTaskListNode !== null) {
38
- result.set(rootTaskListPos, rootTaskListNode);
39
- }
40
- }
41
- }
42
- }
43
- return result;
44
- }
45
- export function applyTaskListNormalisationFixes({
46
- doc,
47
- schema,
48
- tr,
49
- transactions
50
- }) {
51
- const {
52
- taskList,
53
- taskItem
54
- } = schema.nodes;
55
- if (!taskList || !taskItem) {
56
- return tr;
57
- }
58
- const affectedTaskLists = getAffectedTaskListsFromTransactions(transactions, doc, schema);
59
- if (affectedTaskLists.size === 0) {
60
- return tr;
61
- }
62
-
63
- // Sort by position descending so we process deeper/later positions first,
64
- // preventing earlier insertions from shifting later positions.
65
- const sortedEntries = [...affectedTaskLists.entries()].sort(([a], [b]) => b - a);
66
- for (const [taskListPos] of sortedEntries) {
67
- // Re-resolve the taskList node from the current transaction doc (post-operation state).
68
- const mappedTaskListPos = tr.mapping.map(taskListPos);
69
- const currentTaskListNode = tr.doc.nodeAt(mappedTaskListPos);
70
- if (!currentTaskListNode) {
71
- continue;
72
- }
73
- if (!expValEqualsNoExposure('platform_editor_flexible_list_indentation', 'isEnabled', true)) {
74
- // Collect positions of all taskList nodes (at any depth) whose direct children
75
- // include a taskList — this is the invalid structure. The taskList schema requires
76
- // taskItem as children, not nested taskLists directly.
77
- // Process in reverse order so higher-position insertions don't shift lower positions.
78
- const invalidTaskListPositions = [];
79
- currentTaskListNode.descendants((node, offsetPos) => {
80
- if (node.type === taskList) {
81
- // A taskList as the FIRST child of another taskList is invalid — it means a
82
- // delete or paste removed the leading taskItem, leaving a bare nested list.
83
- // A taskList that follows a taskItem is valid (that's normal indentation).
84
- const firstChild = node.firstChild;
85
- if (firstChild && firstChild.type === taskList) {
86
- const pos = mappedTaskListPos + 1 + offsetPos + 1;
87
- invalidTaskListPositions.push(pos);
88
- }
89
- }
90
- return true;
91
- });
92
-
93
- // Process in reverse (highest positions first).
94
- for (let i = invalidTaskListPositions.length - 1; i >= 0; i--) {
95
- const remappedPos = tr.mapping.map(invalidTaskListPositions[i]);
96
- const emptyTaskItem = taskItem.createAndFill();
97
- if (emptyTaskItem) {
98
- tr.insert(remappedPos, emptyTaskItem);
99
- }
100
- }
101
- }
102
- }
103
- return tr;
104
- }