@atlaskit/editor-plugin-paste 13.2.3 → 13.3.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @atlaskit/editor-plugin-paste
2
2
 
3
+ ## 13.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`73743eb8b36e6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/73743eb8b36e6) -
8
+ CLeanup prefer static regex violations
9
+ - Updated dependencies
10
+
11
+ ## 13.3.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [`3f5a55729ccfa`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/3f5a55729ccfa) -
16
+ Fix over-nesting (auto-indent) when pasting a task/action into a bullet list item under the
17
+ flexible list schema (EDITOR-6738), behind kill switch platform_editor_flexible_list_kill_switch_1
18
+
19
+ ### Patch Changes
20
+
21
+ - Updated dependencies
22
+
3
23
  ## 13.2.3
4
24
 
5
25
  ### Patch Changes
@@ -13,6 +13,7 @@ var _model = require("@atlaskit/editor-prosemirror/model");
13
13
  var _state = require("@atlaskit/editor-prosemirror/state");
14
14
  var _transform = require("@atlaskit/editor-prosemirror/transform");
15
15
  var _utils2 = require("@atlaskit/editor-prosemirror/utils");
16
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
16
17
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
17
18
  var _index = require("../index");
18
19
  var _lists = require("./lists");
@@ -139,10 +140,35 @@ function insertSliceForTaskInsideList(_ref5) {
139
140
  var tr = _ref5.tr,
140
141
  slice = _ref5.slice;
141
142
  var schema = tr.doc.type.schema;
142
- //To avoid the list being replaced with the tasklist, enclose the slice within a taskItem.
143
- var selectionBeforeReplace = tr.selection.from;
144
- tr.replaceSelection(new _model.Slice(_model.Fragment.from(schema.nodes.taskItem.createAndFill()), 0, 0));
145
- var nextSelection = _state.Selection.near(tr.doc.resolve(selectionBeforeReplace + 1));
146
- tr.setSelection(nextSelection);
147
- tr.replaceSelection(slice);
143
+
144
+ // The corrected insertion path only applies for the flexible list indentation dogfooding audience
145
+ // (`platform_editor_flexible_list_indentation`), and the kill switch protects that audience from
146
+ // regressions. Fall back to the legacy path when the experiment is OFF or the kill switch is ON.
147
+ if (!(0, _expValEquals.expValEquals)('platform_editor_flexible_list_indentation', 'isEnabled', true) || (0, _platformFeatureFlags.fg)('platform_editor_flexible_list_kill_switch_1')) {
148
+ //To avoid the list being replaced with the tasklist, enclose the slice within a taskItem.
149
+ var selectionBeforeReplace = tr.selection.from;
150
+ tr.replaceSelection(new _model.Slice(_model.Fragment.from(schema.nodes.taskItem.createAndFill()), 0, 0));
151
+ var nextSelection = _state.Selection.near(tr.doc.resolve(selectionBeforeReplace + 1));
152
+ tr.setSelection(nextSelection);
153
+ tr.replaceSelection(slice);
154
+ return tr;
155
+ }
156
+
157
+ // Collapse redundant nested taskList wrappers from the slice context, always keeping a single
158
+ // outermost taskList so the content can be safely inserted as a sibling of the list item's
159
+ // paragraph (a listItem cannot directly contain bare taskItems).
160
+ var taskList = schema.nodes.taskList;
161
+ var content = slice.content;
162
+ while (content.childCount === 1 && ((_content$firstChild = content.firstChild) === null || _content$firstChild === void 0 ? void 0 : _content$firstChild.type) === taskList && ((_content$firstChild$f = content.firstChild.firstChild) === null || _content$firstChild$f === void 0 ? void 0 : _content$firstChild$f.type) === taskList) {
163
+ var _content$firstChild, _content$firstChild$f;
164
+ content = content.firstChild.content;
165
+ }
166
+
167
+ // safeInsert keeps the task structure intact at the closest schema-valid position, instead of
168
+ // replacing into an empty taskItem which would add an extra taskList level.
169
+ tr = (0, _utils2.safeInsert)(content, tr.selection.$to.pos)(tr);
170
+ updateSelectionAfterReplace({
171
+ tr: tr
172
+ });
173
+ return tr;
148
174
  }
@@ -107,7 +107,7 @@ function handleMention(slice, schema) {
107
107
  }
108
108
  function handlePasteIntoTaskOrDecisionOrPanel(slice, queueCardsFromChangedTr) {
109
109
  return function (state, dispatch) {
110
- var _slice$content$firstC, _slice$content$firstC2, _slice$content$firstC3, _transformedSlice$con;
110
+ var _slice$content$firstC, _slice$content$firstC2, _slice$content$firstC3, _transformedSlice$con, _transformedSlice$con2;
111
111
  var schema = state.schema,
112
112
  selection = state.tr.selection;
113
113
  var codeMark = schema.marks.code,
@@ -187,9 +187,21 @@ function handlePasteIntoTaskOrDecisionOrPanel(slice, queueCardsFromChangedTr) {
187
187
  // or the slice's first node is a paragraph,
188
188
  // then we can replace the selection with our slice.
189
189
  var pastingIntoExtendedPanel = selectionIsPanel && panel.validContent(transformedSlice.content);
190
- if ((transformedSliceIsValidNode || selectionIsValidNode) && !pastingIntoExtendedPanel && !(transformedSlice.openStart === 1 && transformedSlice.openEnd === 0 ||
190
+
191
+ // A task slice carrying its own open taskList wrapper would, on a plain replaceSelection,
192
+ // nest that wrapper inside the current item and add an extra taskList level. Unwrapping one
193
+ // level keeps the pasted task(s) at the same level. Guarded by a kill switch.
194
+ var isOpenTaskListSlice = ((_transformedSlice$con = transformedSlice.content.firstChild) === null || _transformedSlice$con === void 0 ? void 0 : _transformedSlice$con.type) === taskList && transformedSlice.openStart >= 2 && transformedSlice.openEnd >= 1;
195
+ // Restrict the unwrap to a taskItem destination: its task content is schema-invalid inside a
196
+ // decisionItem (decisionList only accepts decisionItem), so decisionItem must fall through to
197
+ // the normal replaceSelection path.
198
+ var pastingIntoTaskItem = (0, _utils2.hasParentNodeOfType)([taskItem])(selection);
199
+ if ((0, _expValEquals.expValEquals)('platform_editor_flexible_list_indentation', 'isEnabled', true) && !(0, _platformFeatureFlags.fg)('platform_editor_flexible_list_kill_switch_1') && isOpenTaskListSlice && pastingIntoTaskItem && !selectionIsPanel) {
200
+ var unwrappedSlice = new _model.Slice(transformedSlice.content.firstChild.content, transformedSlice.openStart - 1, transformedSlice.openEnd - 1);
201
+ tr.replaceSelection(unwrappedSlice).scrollIntoView();
202
+ } else if ((transformedSliceIsValidNode || selectionIsValidNode) && !pastingIntoExtendedPanel && !(transformedSlice.openStart === 1 && transformedSlice.openEnd === 0 ||
191
203
  // Whole codeblock node has reverse slice depths.
192
- transformedSlice.openStart === 0 && transformedSlice.openEnd === 1) || ((_transformedSlice$con = transformedSlice.content.firstChild) === null || _transformedSlice$con === void 0 ? void 0 : _transformedSlice$con.type) === paragraph) {
204
+ transformedSlice.openStart === 0 && transformedSlice.openEnd === 1) || ((_transformedSlice$con2 = transformedSlice.content.firstChild) === null || _transformedSlice$con2 === void 0 ? void 0 : _transformedSlice$con2.type) === paragraph) {
193
205
  tr.replaceSelection(transformedSlice).scrollIntoView();
194
206
  } else {
195
207
  var isWholeContentSelected = selection.$from.pos === selection.$from.start() && selection.$to.end() === selection.$to.pos;
@@ -208,14 +220,14 @@ function handlePasteIntoTaskOrDecisionOrPanel(slice, queueCardsFromChangedTr) {
208
220
  tr.replaceSelection(transformedSlice).scrollIntoView();
209
221
  }
210
222
  } else {
211
- var _transformedSlice$con2;
223
+ var _transformedSlice$con3;
212
224
  if (pastingIntoExtendedPanel && isWholeContentSelected) {
213
225
  // if the entire panel content is selected, doing a replaceSelection removes the panel as well. Hence we do delete followed by safeInsert
214
226
  tr.delete(selection.$from.pos, selection.$to.pos);
215
227
  }
216
228
  // This maintains both the selection (destination) and the slice (paste content).
217
229
  (0, _utils2.safeInsert)(transformedSlice.content)(tr).scrollIntoView();
218
- if (((_transformedSlice$con2 = transformedSlice.content.lastChild) === null || _transformedSlice$con2 === void 0 || (_transformedSlice$con2 = _transformedSlice$con2.type) === null || _transformedSlice$con2 === void 0 ? void 0 : _transformedSlice$con2.name) === 'rule') {
230
+ if (((_transformedSlice$con3 = transformedSlice.content.lastChild) === null || _transformedSlice$con3 === void 0 || (_transformedSlice$con3 = _transformedSlice$con3.type) === null || _transformedSlice$con3 === void 0 ? void 0 : _transformedSlice$con3.name) === 'rule') {
219
231
  tr.setSelection(_state.TextSelection.near(tr.doc.resolve(tr.selection.$from.pos + transformedSlice.content.size)));
220
232
  } else {
221
233
  // safeInsert doesn't set correct cursor position
@@ -1231,8 +1243,17 @@ function handleRichText(slice, queueCardsFromChangedTr) {
1231
1243
  });
1232
1244
  if ((0, _utils.insideTableCell)(state) && (0, _utils.isInListItem)(state) && (0, _utils2.canInsert)(selection.$from, slice.content) && (0, _utils2.canInsert)(selection.$to, slice.content) || sliceHasList) {
1233
1245
  tr.replaceSelection(slice);
1246
+ } else if ((0, _expValEquals.expValEquals)('platform_editor_flexible_list_indentation', 'isEnabled', true) && !(0, _platformFeatureFlags.fg)('platform_editor_flexible_list_kill_switch_1') && checkTaskListInList(state, slice) && !checkIfSelectionInNestedList(state)) {
1247
+ // Corrected task-into-list insertion is gated behind the flexible list indentation
1248
+ // experiment and protected by the kill switch.
1249
+ tr = (0, _edgeCases.insertSliceForTaskInsideList)({
1250
+ tr: tr,
1251
+ slice: slice
1252
+ });
1234
1253
  } else if (checkTaskListInList(state, slice) && !checkIfSelectionInNestedList(state)) {
1235
- (0, _edgeCases.insertSliceForTaskInsideList)({
1254
+ // Legacy path (experiment OFF or kill switch ON): preserve the previous over-nesting
1255
+ // behaviour via the function's internal fallback.
1256
+ tr = (0, _edgeCases.insertSliceForTaskInsideList)({
1236
1257
  tr: tr,
1237
1258
  slice: slice
1238
1259
  });
@@ -29,6 +29,23 @@ var _utils2 = require("@atlaskit/editor-prosemirror/utils");
29
29
  var _utils3 = require("@atlaskit/editor-tables/utils");
30
30
  var _mediaClient = require("@atlaskit/media-client");
31
31
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
32
+ // Ignored via go/ees005
33
+ // eslint-disable-next-line require-unicode-regexp
34
+ var HTML_CONTAINS_SINGLE_FILE_REGEX = /<img .*>/;
35
+ // Ignored via go/ees005
36
+ // eslint-disable-next-line require-unicode-regexp
37
+ var ESCAPE_LINKS_INNER_REGEX = /^(https?|ftp|jamfselfservice):\/\/[^\s>"]+$/;
38
+ // Allows up to 3 leading spaces before ``` and optional trailing characters
39
+ // Ignored via go/ees005
40
+ // eslint-disable-next-line require-unicode-regexp
41
+ var OPENING_CODE_FENCE_REGEX = /^( {0,3})```.*$/;
42
+ // Allows up to 3 leading spaces before ``` and optional trailing spaces or tabs
43
+ // Ignored via go/ees005
44
+ // eslint-disable-next-line require-unicode-regexp
45
+ var CLOSING_CODE_FENCE_REGEX = /^( {0,3})```[ ]*$/;
46
+ // Ignored via go/ees005
47
+ // eslint-disable-next-line require-unicode-regexp
48
+ var SPLIT_ON_ANCHOR_REGEX = /(?=<a)/;
32
49
  function isPastedFromWord(html) {
33
50
  return !!html && html.indexOf('urn:schemas-microsoft-com:office:word') >= 0;
34
51
  }
@@ -63,9 +80,7 @@ var isSingleLine = exports.isSingleLine = function isSingleLine(text) {
63
80
  return !!text && text.trim().split('\n').length === 1;
64
81
  };
65
82
  function htmlContainsSingleFile(html) {
66
- // Ignored via go/ees005
67
- // eslint-disable-next-line require-unicode-regexp
68
- return !!html.match(/<img .*>/) && !(0, _mediaClient.isMediaBlobUrl)(html);
83
+ return !!html.match(HTML_CONTAINS_SINGLE_FILE_REGEX) && !(0, _mediaClient.isMediaBlobUrl)(html);
69
84
  }
70
85
  function getPasteSource(event) {
71
86
  // Ignored via go/ees005
@@ -110,9 +125,7 @@ function escapeLinks(text) {
110
125
  // Ignored via go/ees005
111
126
  // eslint-disable-next-line require-unicode-regexp
112
127
  return text.replace(/(\[([^\]]+)\]\()?((https?|ftp|jamfselfservice):\/\/[^\s>"]+)/g, function (str) {
113
- // Ignored via go/ees005
114
- // eslint-disable-next-line require-unicode-regexp
115
- return str.match(/^(https?|ftp|jamfselfservice):\/\/[^\s>"]+$/) ? "<".concat(str, ">") : str;
128
+ return str.match(ESCAPE_LINKS_INNER_REGEX) ? "<".concat(str, ">") : str;
116
129
  });
117
130
  }
118
131
 
@@ -127,23 +140,15 @@ function escapeLinks(text) {
127
140
  */
128
141
  function escapeBackslashAndLinksExceptCodeBlock(textInput) {
129
142
  // ref: https://spec.commonmark.org/0.31.2/#fenced-code-blocks
130
- // Allows up to 3 leading spaces before ``` and optional trailing characters
131
- // Ignored via go/ees005
132
- // eslint-disable-next-line require-unicode-regexp
133
- var openingCodeFenceRegex = /^( {0,3})```.*$/;
134
- // Allows up to 3 leading spaces before ``` and optional trailing spaces or tabs
135
- // Ignored via go/ees005
136
- // eslint-disable-next-line require-unicode-regexp
137
- var closingCodeFenceRegex = /^( {0,3})```[ \t]*$/;
138
143
  var isInsideCodeBlock = false;
139
144
  var lines = textInput.split('\n');
140
145
  // In the splitted array, we traverse through every line and check if it will be parsed as a codeblock.
141
146
  return lines.map(function (line) {
142
- if (!isInsideCodeBlock && openingCodeFenceRegex.test(line)) {
147
+ if (!isInsideCodeBlock && OPENING_CODE_FENCE_REGEX.test(line)) {
143
148
  isInsideCodeBlock = true;
144
149
  return line;
145
150
  }
146
- if (isInsideCodeBlock && closingCodeFenceRegex.test(line)) {
151
+ if (isInsideCodeBlock && CLOSING_CODE_FENCE_REGEX.test(line)) {
147
152
  isInsideCodeBlock = false;
148
153
  return line;
149
154
  }
@@ -244,9 +249,7 @@ var htmlHasInvalidLinkTags = exports.htmlHasInvalidLinkTags = function htmlHasIn
244
249
  // <li><a href="http://www.atlassian.com\"<a> href="http://www.atlassian.com\"http://www.atlassian.com</a></a></li>">
245
250
  var removeDuplicateInvalidLinks = exports.removeDuplicateInvalidLinks = function removeDuplicateInvalidLinks(html) {
246
251
  if (htmlHasInvalidLinkTags(html)) {
247
- // Ignored via go/ees005
248
- // eslint-disable-next-line require-unicode-regexp
249
- var htmlArray = html.split(/(?=<a)/);
252
+ var htmlArray = html.split(SPLIT_ON_ANCHOR_REGEX);
250
253
  var htmlArrayWithoutInvalidLinks = htmlArray.filter(function (item) {
251
254
  return !(item.includes('<a') && item.includes('"></a>')) && !(item.includes('<a') && !item.includes('</a>'));
252
255
  });
@@ -3,7 +3,8 @@ import { isListNode } from '@atlaskit/editor-common/utils';
3
3
  import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
4
4
  import { Selection } from '@atlaskit/editor-prosemirror/state';
5
5
  import { ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
6
- import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
6
+ import { findParentNodeOfType, safeInsert } from '@atlaskit/editor-prosemirror/utils';
7
+ import { fg } from '@atlaskit/platform-feature-flags';
7
8
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
8
9
  import { isCursorSelectionAtTextStartOrEnd, isEmptyNode, isSelectionInsidePanel } from '../index';
9
10
  import { insertSliceAtNodeEdge, insertSliceInsideOfPanelNodeSelected, insertSliceIntoEmptyNode, insertSliceIntoRangeSelectionInsideList } from './lists';
@@ -140,10 +141,37 @@ export function insertSliceForTaskInsideList({
140
141
  const {
141
142
  schema
142
143
  } = tr.doc.type;
143
- //To avoid the list being replaced with the tasklist, enclose the slice within a taskItem.
144
- const selectionBeforeReplace = tr.selection.from;
145
- tr.replaceSelection(new Slice(Fragment.from(schema.nodes.taskItem.createAndFill()), 0, 0));
146
- const nextSelection = Selection.near(tr.doc.resolve(selectionBeforeReplace + 1));
147
- tr.setSelection(nextSelection);
148
- tr.replaceSelection(slice);
144
+
145
+ // The corrected insertion path only applies for the flexible list indentation dogfooding audience
146
+ // (`platform_editor_flexible_list_indentation`), and the kill switch protects that audience from
147
+ // regressions. Fall back to the legacy path when the experiment is OFF or the kill switch is ON.
148
+ if (!expValEquals('platform_editor_flexible_list_indentation', 'isEnabled', true) || fg('platform_editor_flexible_list_kill_switch_1')) {
149
+ //To avoid the list being replaced with the tasklist, enclose the slice within a taskItem.
150
+ const selectionBeforeReplace = tr.selection.from;
151
+ tr.replaceSelection(new Slice(Fragment.from(schema.nodes.taskItem.createAndFill()), 0, 0));
152
+ const nextSelection = Selection.near(tr.doc.resolve(selectionBeforeReplace + 1));
153
+ tr.setSelection(nextSelection);
154
+ tr.replaceSelection(slice);
155
+ return tr;
156
+ }
157
+
158
+ // Collapse redundant nested taskList wrappers from the slice context, always keeping a single
159
+ // outermost taskList so the content can be safely inserted as a sibling of the list item's
160
+ // paragraph (a listItem cannot directly contain bare taskItems).
161
+ const {
162
+ taskList
163
+ } = schema.nodes;
164
+ let content = slice.content;
165
+ while (content.childCount === 1 && ((_content$firstChild = content.firstChild) === null || _content$firstChild === void 0 ? void 0 : _content$firstChild.type) === taskList && ((_content$firstChild$f = content.firstChild.firstChild) === null || _content$firstChild$f === void 0 ? void 0 : _content$firstChild$f.type) === taskList) {
166
+ var _content$firstChild, _content$firstChild$f;
167
+ content = content.firstChild.content;
168
+ }
169
+
170
+ // safeInsert keeps the task structure intact at the closest schema-valid position, instead of
171
+ // replacing into an empty taskItem which would add an extra taskList level.
172
+ tr = safeInsert(content, tr.selection.$to.pos)(tr);
173
+ updateSelectionAfterReplace({
174
+ tr
175
+ });
176
+ return tr;
149
177
  }
@@ -67,7 +67,7 @@ export function handleMention(slice, schema) {
67
67
  }
68
68
  export function handlePasteIntoTaskOrDecisionOrPanel(slice, queueCardsFromChangedTr) {
69
69
  return (state, dispatch) => {
70
- var _slice$content$firstC, _slice$content$firstC2, _slice$content$firstC3, _transformedSlice$con;
70
+ var _slice$content$firstC, _slice$content$firstC2, _slice$content$firstC3, _transformedSlice$con, _transformedSlice$con2;
71
71
  const {
72
72
  schema,
73
73
  tr: {
@@ -154,9 +154,21 @@ export function handlePasteIntoTaskOrDecisionOrPanel(slice, queueCardsFromChange
154
154
  // or the slice's first node is a paragraph,
155
155
  // then we can replace the selection with our slice.
156
156
  const pastingIntoExtendedPanel = selectionIsPanel && panel.validContent(transformedSlice.content);
157
- if ((transformedSliceIsValidNode || selectionIsValidNode) && !pastingIntoExtendedPanel && !(transformedSlice.openStart === 1 && transformedSlice.openEnd === 0 ||
157
+
158
+ // A task slice carrying its own open taskList wrapper would, on a plain replaceSelection,
159
+ // nest that wrapper inside the current item and add an extra taskList level. Unwrapping one
160
+ // level keeps the pasted task(s) at the same level. Guarded by a kill switch.
161
+ const isOpenTaskListSlice = ((_transformedSlice$con = transformedSlice.content.firstChild) === null || _transformedSlice$con === void 0 ? void 0 : _transformedSlice$con.type) === taskList && transformedSlice.openStart >= 2 && transformedSlice.openEnd >= 1;
162
+ // Restrict the unwrap to a taskItem destination: its task content is schema-invalid inside a
163
+ // decisionItem (decisionList only accepts decisionItem), so decisionItem must fall through to
164
+ // the normal replaceSelection path.
165
+ const pastingIntoTaskItem = hasParentNodeOfType([taskItem])(selection);
166
+ if (expValEquals('platform_editor_flexible_list_indentation', 'isEnabled', true) && !fg('platform_editor_flexible_list_kill_switch_1') && isOpenTaskListSlice && pastingIntoTaskItem && !selectionIsPanel) {
167
+ const unwrappedSlice = new Slice(transformedSlice.content.firstChild.content, transformedSlice.openStart - 1, transformedSlice.openEnd - 1);
168
+ tr.replaceSelection(unwrappedSlice).scrollIntoView();
169
+ } else if ((transformedSliceIsValidNode || selectionIsValidNode) && !pastingIntoExtendedPanel && !(transformedSlice.openStart === 1 && transformedSlice.openEnd === 0 ||
158
170
  // Whole codeblock node has reverse slice depths.
159
- transformedSlice.openStart === 0 && transformedSlice.openEnd === 1) || ((_transformedSlice$con = transformedSlice.content.firstChild) === null || _transformedSlice$con === void 0 ? void 0 : _transformedSlice$con.type) === paragraph) {
171
+ transformedSlice.openStart === 0 && transformedSlice.openEnd === 1) || ((_transformedSlice$con2 = transformedSlice.content.firstChild) === null || _transformedSlice$con2 === void 0 ? void 0 : _transformedSlice$con2.type) === paragraph) {
160
172
  tr.replaceSelection(transformedSlice).scrollIntoView();
161
173
  } else {
162
174
  const isWholeContentSelected = selection.$from.pos === selection.$from.start() && selection.$to.end() === selection.$to.pos;
@@ -175,14 +187,14 @@ export function handlePasteIntoTaskOrDecisionOrPanel(slice, queueCardsFromChange
175
187
  tr.replaceSelection(transformedSlice).scrollIntoView();
176
188
  }
177
189
  } else {
178
- var _transformedSlice$con2, _transformedSlice$con3;
190
+ var _transformedSlice$con3, _transformedSlice$con4;
179
191
  if (pastingIntoExtendedPanel && isWholeContentSelected) {
180
192
  // if the entire panel content is selected, doing a replaceSelection removes the panel as well. Hence we do delete followed by safeInsert
181
193
  tr.delete(selection.$from.pos, selection.$to.pos);
182
194
  }
183
195
  // This maintains both the selection (destination) and the slice (paste content).
184
196
  safeInsert(transformedSlice.content)(tr).scrollIntoView();
185
- if (((_transformedSlice$con2 = transformedSlice.content.lastChild) === null || _transformedSlice$con2 === void 0 ? void 0 : (_transformedSlice$con3 = _transformedSlice$con2.type) === null || _transformedSlice$con3 === void 0 ? void 0 : _transformedSlice$con3.name) === 'rule') {
197
+ if (((_transformedSlice$con3 = transformedSlice.content.lastChild) === null || _transformedSlice$con3 === void 0 ? void 0 : (_transformedSlice$con4 = _transformedSlice$con3.type) === null || _transformedSlice$con4 === void 0 ? void 0 : _transformedSlice$con4.name) === 'rule') {
186
198
  tr.setSelection(TextSelection.near(tr.doc.resolve(tr.selection.$from.pos + transformedSlice.content.size)));
187
199
  } else {
188
200
  // safeInsert doesn't set correct cursor position
@@ -1206,8 +1218,17 @@ export function handleRichText(slice, queueCardsFromChangedTr) {
1206
1218
  });
1207
1219
  if (insideTableCell(state) && isInListItem(state) && canInsert(selection.$from, slice.content) && canInsert(selection.$to, slice.content) || sliceHasList) {
1208
1220
  tr.replaceSelection(slice);
1221
+ } else if (expValEquals('platform_editor_flexible_list_indentation', 'isEnabled', true) && !fg('platform_editor_flexible_list_kill_switch_1') && checkTaskListInList(state, slice) && !checkIfSelectionInNestedList(state)) {
1222
+ // Corrected task-into-list insertion is gated behind the flexible list indentation
1223
+ // experiment and protected by the kill switch.
1224
+ tr = insertSliceForTaskInsideList({
1225
+ tr,
1226
+ slice
1227
+ });
1209
1228
  } else if (checkTaskListInList(state, slice) && !checkIfSelectionInNestedList(state)) {
1210
- insertSliceForTaskInsideList({
1229
+ // Legacy path (experiment OFF or kill switch ON): preserve the previous over-nesting
1230
+ // behaviour via the function's internal fallback.
1231
+ tr = insertSliceForTaskInsideList({
1211
1232
  tr,
1212
1233
  slice
1213
1234
  });
@@ -7,6 +7,24 @@ import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
7
7
  import { getSelectedTableInfo, isTableSelected } from '@atlaskit/editor-tables/utils';
8
8
  import { isMediaBlobUrl } from '@atlaskit/media-client';
9
9
  import { fg } from '@atlaskit/platform-feature-flags';
10
+
11
+ // Ignored via go/ees005
12
+ // eslint-disable-next-line require-unicode-regexp
13
+ const HTML_CONTAINS_SINGLE_FILE_REGEX = /<img .*>/;
14
+ // Ignored via go/ees005
15
+ // eslint-disable-next-line require-unicode-regexp
16
+ const ESCAPE_LINKS_INNER_REGEX = /^(https?|ftp|jamfselfservice):\/\/[^\s>"]+$/;
17
+ // Allows up to 3 leading spaces before ``` and optional trailing characters
18
+ // Ignored via go/ees005
19
+ // eslint-disable-next-line require-unicode-regexp
20
+ const OPENING_CODE_FENCE_REGEX = /^( {0,3})```.*$/;
21
+ // Allows up to 3 leading spaces before ``` and optional trailing spaces or tabs
22
+ // Ignored via go/ees005
23
+ // eslint-disable-next-line require-unicode-regexp
24
+ const CLOSING_CODE_FENCE_REGEX = /^( {0,3})```[ ]*$/;
25
+ // Ignored via go/ees005
26
+ // eslint-disable-next-line require-unicode-regexp
27
+ const SPLIT_ON_ANCHOR_REGEX = /(?=<a)/;
10
28
  export function isPastedFromWord(html) {
11
29
  return !!html && html.indexOf('urn:schemas-microsoft-com:office:word') >= 0;
12
30
  }
@@ -41,9 +59,7 @@ export const isSingleLine = text => {
41
59
  return !!text && text.trim().split('\n').length === 1;
42
60
  };
43
61
  export function htmlContainsSingleFile(html) {
44
- // Ignored via go/ees005
45
- // eslint-disable-next-line require-unicode-regexp
46
- return !!html.match(/<img .*>/) && !isMediaBlobUrl(html);
62
+ return !!html.match(HTML_CONTAINS_SINGLE_FILE_REGEX) && !isMediaBlobUrl(html);
47
63
  }
48
64
  export function getPasteSource(event) {
49
65
  // Ignored via go/ees005
@@ -88,9 +104,7 @@ export function escapeLinks(text) {
88
104
  // Ignored via go/ees005
89
105
  // eslint-disable-next-line require-unicode-regexp
90
106
  return text.replace(/(\[([^\]]+)\]\()?((https?|ftp|jamfselfservice):\/\/[^\s>"]+)/g, str => {
91
- // Ignored via go/ees005
92
- // eslint-disable-next-line require-unicode-regexp
93
- return str.match(/^(https?|ftp|jamfselfservice):\/\/[^\s>"]+$/) ? `<${str}>` : str;
107
+ return str.match(ESCAPE_LINKS_INNER_REGEX) ? `<${str}>` : str;
94
108
  });
95
109
  }
96
110
 
@@ -105,23 +119,15 @@ export function escapeLinks(text) {
105
119
  */
106
120
  export function escapeBackslashAndLinksExceptCodeBlock(textInput) {
107
121
  // ref: https://spec.commonmark.org/0.31.2/#fenced-code-blocks
108
- // Allows up to 3 leading spaces before ``` and optional trailing characters
109
- // Ignored via go/ees005
110
- // eslint-disable-next-line require-unicode-regexp
111
- const openingCodeFenceRegex = /^( {0,3})```.*$/;
112
- // Allows up to 3 leading spaces before ``` and optional trailing spaces or tabs
113
- // Ignored via go/ees005
114
- // eslint-disable-next-line require-unicode-regexp
115
- const closingCodeFenceRegex = /^( {0,3})```[ \t]*$/;
116
122
  let isInsideCodeBlock = false;
117
123
  const lines = textInput.split('\n');
118
124
  // In the splitted array, we traverse through every line and check if it will be parsed as a codeblock.
119
125
  return lines.map(line => {
120
- if (!isInsideCodeBlock && openingCodeFenceRegex.test(line)) {
126
+ if (!isInsideCodeBlock && OPENING_CODE_FENCE_REGEX.test(line)) {
121
127
  isInsideCodeBlock = true;
122
128
  return line;
123
129
  }
124
- if (isInsideCodeBlock && closingCodeFenceRegex.test(line)) {
130
+ if (isInsideCodeBlock && CLOSING_CODE_FENCE_REGEX.test(line)) {
125
131
  isInsideCodeBlock = false;
126
132
  return line;
127
133
  }
@@ -234,9 +240,7 @@ export const htmlHasInvalidLinkTags = html => {
234
240
  // <li><a href="http://www.atlassian.com\"<a> href="http://www.atlassian.com\"http://www.atlassian.com</a></a></li>">
235
241
  export const removeDuplicateInvalidLinks = html => {
236
242
  if (htmlHasInvalidLinkTags(html)) {
237
- // Ignored via go/ees005
238
- // eslint-disable-next-line require-unicode-regexp
239
- const htmlArray = html.split(/(?=<a)/);
243
+ const htmlArray = html.split(SPLIT_ON_ANCHOR_REGEX);
240
244
  const htmlArrayWithoutInvalidLinks = htmlArray.filter(item => {
241
245
  return !(item.includes('<a') && item.includes('"></a>')) && !(item.includes('<a') && !item.includes('</a>'));
242
246
  });
@@ -3,7 +3,8 @@ import { isListNode } from '@atlaskit/editor-common/utils';
3
3
  import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
4
4
  import { Selection } from '@atlaskit/editor-prosemirror/state';
5
5
  import { ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
6
- import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
6
+ import { findParentNodeOfType, safeInsert } from '@atlaskit/editor-prosemirror/utils';
7
+ import { fg } from '@atlaskit/platform-feature-flags';
7
8
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
8
9
  import { isCursorSelectionAtTextStartOrEnd, isEmptyNode, isSelectionInsidePanel } from '../index';
9
10
  import { insertSliceAtNodeEdge, insertSliceInsideOfPanelNodeSelected, insertSliceIntoEmptyNode, insertSliceIntoRangeSelectionInsideList } from './lists';
@@ -130,10 +131,35 @@ export function insertSliceForTaskInsideList(_ref5) {
130
131
  var tr = _ref5.tr,
131
132
  slice = _ref5.slice;
132
133
  var schema = tr.doc.type.schema;
133
- //To avoid the list being replaced with the tasklist, enclose the slice within a taskItem.
134
- var selectionBeforeReplace = tr.selection.from;
135
- tr.replaceSelection(new Slice(Fragment.from(schema.nodes.taskItem.createAndFill()), 0, 0));
136
- var nextSelection = Selection.near(tr.doc.resolve(selectionBeforeReplace + 1));
137
- tr.setSelection(nextSelection);
138
- tr.replaceSelection(slice);
134
+
135
+ // The corrected insertion path only applies for the flexible list indentation dogfooding audience
136
+ // (`platform_editor_flexible_list_indentation`), and the kill switch protects that audience from
137
+ // regressions. Fall back to the legacy path when the experiment is OFF or the kill switch is ON.
138
+ if (!expValEquals('platform_editor_flexible_list_indentation', 'isEnabled', true) || fg('platform_editor_flexible_list_kill_switch_1')) {
139
+ //To avoid the list being replaced with the tasklist, enclose the slice within a taskItem.
140
+ var selectionBeforeReplace = tr.selection.from;
141
+ tr.replaceSelection(new Slice(Fragment.from(schema.nodes.taskItem.createAndFill()), 0, 0));
142
+ var nextSelection = Selection.near(tr.doc.resolve(selectionBeforeReplace + 1));
143
+ tr.setSelection(nextSelection);
144
+ tr.replaceSelection(slice);
145
+ return tr;
146
+ }
147
+
148
+ // Collapse redundant nested taskList wrappers from the slice context, always keeping a single
149
+ // outermost taskList so the content can be safely inserted as a sibling of the list item's
150
+ // paragraph (a listItem cannot directly contain bare taskItems).
151
+ var taskList = schema.nodes.taskList;
152
+ var content = slice.content;
153
+ while (content.childCount === 1 && ((_content$firstChild = content.firstChild) === null || _content$firstChild === void 0 ? void 0 : _content$firstChild.type) === taskList && ((_content$firstChild$f = content.firstChild.firstChild) === null || _content$firstChild$f === void 0 ? void 0 : _content$firstChild$f.type) === taskList) {
154
+ var _content$firstChild, _content$firstChild$f;
155
+ content = content.firstChild.content;
156
+ }
157
+
158
+ // safeInsert keeps the task structure intact at the closest schema-valid position, instead of
159
+ // replacing into an empty taskItem which would add an extra taskList level.
160
+ tr = safeInsert(content, tr.selection.$to.pos)(tr);
161
+ updateSelectionAfterReplace({
162
+ tr: tr
163
+ });
164
+ return tr;
139
165
  }
@@ -78,7 +78,7 @@ export function handleMention(slice, schema) {
78
78
  }
79
79
  export function handlePasteIntoTaskOrDecisionOrPanel(slice, queueCardsFromChangedTr) {
80
80
  return function (state, dispatch) {
81
- var _slice$content$firstC, _slice$content$firstC2, _slice$content$firstC3, _transformedSlice$con;
81
+ var _slice$content$firstC, _slice$content$firstC2, _slice$content$firstC3, _transformedSlice$con, _transformedSlice$con2;
82
82
  var schema = state.schema,
83
83
  selection = state.tr.selection;
84
84
  var codeMark = schema.marks.code,
@@ -158,9 +158,21 @@ export function handlePasteIntoTaskOrDecisionOrPanel(slice, queueCardsFromChange
158
158
  // or the slice's first node is a paragraph,
159
159
  // then we can replace the selection with our slice.
160
160
  var pastingIntoExtendedPanel = selectionIsPanel && panel.validContent(transformedSlice.content);
161
- if ((transformedSliceIsValidNode || selectionIsValidNode) && !pastingIntoExtendedPanel && !(transformedSlice.openStart === 1 && transformedSlice.openEnd === 0 ||
161
+
162
+ // A task slice carrying its own open taskList wrapper would, on a plain replaceSelection,
163
+ // nest that wrapper inside the current item and add an extra taskList level. Unwrapping one
164
+ // level keeps the pasted task(s) at the same level. Guarded by a kill switch.
165
+ var isOpenTaskListSlice = ((_transformedSlice$con = transformedSlice.content.firstChild) === null || _transformedSlice$con === void 0 ? void 0 : _transformedSlice$con.type) === taskList && transformedSlice.openStart >= 2 && transformedSlice.openEnd >= 1;
166
+ // Restrict the unwrap to a taskItem destination: its task content is schema-invalid inside a
167
+ // decisionItem (decisionList only accepts decisionItem), so decisionItem must fall through to
168
+ // the normal replaceSelection path.
169
+ var pastingIntoTaskItem = hasParentNodeOfType([taskItem])(selection);
170
+ if (expValEquals('platform_editor_flexible_list_indentation', 'isEnabled', true) && !fg('platform_editor_flexible_list_kill_switch_1') && isOpenTaskListSlice && pastingIntoTaskItem && !selectionIsPanel) {
171
+ var unwrappedSlice = new Slice(transformedSlice.content.firstChild.content, transformedSlice.openStart - 1, transformedSlice.openEnd - 1);
172
+ tr.replaceSelection(unwrappedSlice).scrollIntoView();
173
+ } else if ((transformedSliceIsValidNode || selectionIsValidNode) && !pastingIntoExtendedPanel && !(transformedSlice.openStart === 1 && transformedSlice.openEnd === 0 ||
162
174
  // Whole codeblock node has reverse slice depths.
163
- transformedSlice.openStart === 0 && transformedSlice.openEnd === 1) || ((_transformedSlice$con = transformedSlice.content.firstChild) === null || _transformedSlice$con === void 0 ? void 0 : _transformedSlice$con.type) === paragraph) {
175
+ transformedSlice.openStart === 0 && transformedSlice.openEnd === 1) || ((_transformedSlice$con2 = transformedSlice.content.firstChild) === null || _transformedSlice$con2 === void 0 ? void 0 : _transformedSlice$con2.type) === paragraph) {
164
176
  tr.replaceSelection(transformedSlice).scrollIntoView();
165
177
  } else {
166
178
  var isWholeContentSelected = selection.$from.pos === selection.$from.start() && selection.$to.end() === selection.$to.pos;
@@ -179,14 +191,14 @@ export function handlePasteIntoTaskOrDecisionOrPanel(slice, queueCardsFromChange
179
191
  tr.replaceSelection(transformedSlice).scrollIntoView();
180
192
  }
181
193
  } else {
182
- var _transformedSlice$con2;
194
+ var _transformedSlice$con3;
183
195
  if (pastingIntoExtendedPanel && isWholeContentSelected) {
184
196
  // if the entire panel content is selected, doing a replaceSelection removes the panel as well. Hence we do delete followed by safeInsert
185
197
  tr.delete(selection.$from.pos, selection.$to.pos);
186
198
  }
187
199
  // This maintains both the selection (destination) and the slice (paste content).
188
200
  safeInsert(transformedSlice.content)(tr).scrollIntoView();
189
- if (((_transformedSlice$con2 = transformedSlice.content.lastChild) === null || _transformedSlice$con2 === void 0 || (_transformedSlice$con2 = _transformedSlice$con2.type) === null || _transformedSlice$con2 === void 0 ? void 0 : _transformedSlice$con2.name) === 'rule') {
201
+ if (((_transformedSlice$con3 = transformedSlice.content.lastChild) === null || _transformedSlice$con3 === void 0 || (_transformedSlice$con3 = _transformedSlice$con3.type) === null || _transformedSlice$con3 === void 0 ? void 0 : _transformedSlice$con3.name) === 'rule') {
190
202
  tr.setSelection(TextSelection.near(tr.doc.resolve(tr.selection.$from.pos + transformedSlice.content.size)));
191
203
  } else {
192
204
  // safeInsert doesn't set correct cursor position
@@ -1202,8 +1214,17 @@ export function handleRichText(slice, queueCardsFromChangedTr) {
1202
1214
  });
1203
1215
  if (insideTableCell(state) && isInListItem(state) && canInsert(selection.$from, slice.content) && canInsert(selection.$to, slice.content) || sliceHasList) {
1204
1216
  tr.replaceSelection(slice);
1217
+ } else if (expValEquals('platform_editor_flexible_list_indentation', 'isEnabled', true) && !fg('platform_editor_flexible_list_kill_switch_1') && checkTaskListInList(state, slice) && !checkIfSelectionInNestedList(state)) {
1218
+ // Corrected task-into-list insertion is gated behind the flexible list indentation
1219
+ // experiment and protected by the kill switch.
1220
+ tr = insertSliceForTaskInsideList({
1221
+ tr: tr,
1222
+ slice: slice
1223
+ });
1205
1224
  } else if (checkTaskListInList(state, slice) && !checkIfSelectionInNestedList(state)) {
1206
- insertSliceForTaskInsideList({
1225
+ // Legacy path (experiment OFF or kill switch ON): preserve the previous over-nesting
1226
+ // behaviour via the function's internal fallback.
1227
+ tr = insertSliceForTaskInsideList({
1207
1228
  tr: tr,
1208
1229
  slice: slice
1209
1230
  });
@@ -8,6 +8,24 @@ import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
8
8
  import { getSelectedTableInfo, isTableSelected } from '@atlaskit/editor-tables/utils';
9
9
  import { isMediaBlobUrl } from '@atlaskit/media-client';
10
10
  import { fg } from '@atlaskit/platform-feature-flags';
11
+
12
+ // Ignored via go/ees005
13
+ // eslint-disable-next-line require-unicode-regexp
14
+ var HTML_CONTAINS_SINGLE_FILE_REGEX = /<img .*>/;
15
+ // Ignored via go/ees005
16
+ // eslint-disable-next-line require-unicode-regexp
17
+ var ESCAPE_LINKS_INNER_REGEX = /^(https?|ftp|jamfselfservice):\/\/[^\s>"]+$/;
18
+ // Allows up to 3 leading spaces before ``` and optional trailing characters
19
+ // Ignored via go/ees005
20
+ // eslint-disable-next-line require-unicode-regexp
21
+ var OPENING_CODE_FENCE_REGEX = /^( {0,3})```.*$/;
22
+ // Allows up to 3 leading spaces before ``` and optional trailing spaces or tabs
23
+ // Ignored via go/ees005
24
+ // eslint-disable-next-line require-unicode-regexp
25
+ var CLOSING_CODE_FENCE_REGEX = /^( {0,3})```[ ]*$/;
26
+ // Ignored via go/ees005
27
+ // eslint-disable-next-line require-unicode-regexp
28
+ var SPLIT_ON_ANCHOR_REGEX = /(?=<a)/;
11
29
  export function isPastedFromWord(html) {
12
30
  return !!html && html.indexOf('urn:schemas-microsoft-com:office:word') >= 0;
13
31
  }
@@ -42,9 +60,7 @@ export var isSingleLine = function isSingleLine(text) {
42
60
  return !!text && text.trim().split('\n').length === 1;
43
61
  };
44
62
  export function htmlContainsSingleFile(html) {
45
- // Ignored via go/ees005
46
- // eslint-disable-next-line require-unicode-regexp
47
- return !!html.match(/<img .*>/) && !isMediaBlobUrl(html);
63
+ return !!html.match(HTML_CONTAINS_SINGLE_FILE_REGEX) && !isMediaBlobUrl(html);
48
64
  }
49
65
  export function getPasteSource(event) {
50
66
  // Ignored via go/ees005
@@ -89,9 +105,7 @@ export function escapeLinks(text) {
89
105
  // Ignored via go/ees005
90
106
  // eslint-disable-next-line require-unicode-regexp
91
107
  return text.replace(/(\[([^\]]+)\]\()?((https?|ftp|jamfselfservice):\/\/[^\s>"]+)/g, function (str) {
92
- // Ignored via go/ees005
93
- // eslint-disable-next-line require-unicode-regexp
94
- return str.match(/^(https?|ftp|jamfselfservice):\/\/[^\s>"]+$/) ? "<".concat(str, ">") : str;
108
+ return str.match(ESCAPE_LINKS_INNER_REGEX) ? "<".concat(str, ">") : str;
95
109
  });
96
110
  }
97
111
 
@@ -106,23 +120,15 @@ export function escapeLinks(text) {
106
120
  */
107
121
  export function escapeBackslashAndLinksExceptCodeBlock(textInput) {
108
122
  // ref: https://spec.commonmark.org/0.31.2/#fenced-code-blocks
109
- // Allows up to 3 leading spaces before ``` and optional trailing characters
110
- // Ignored via go/ees005
111
- // eslint-disable-next-line require-unicode-regexp
112
- var openingCodeFenceRegex = /^( {0,3})```.*$/;
113
- // Allows up to 3 leading spaces before ``` and optional trailing spaces or tabs
114
- // Ignored via go/ees005
115
- // eslint-disable-next-line require-unicode-regexp
116
- var closingCodeFenceRegex = /^( {0,3})```[ \t]*$/;
117
123
  var isInsideCodeBlock = false;
118
124
  var lines = textInput.split('\n');
119
125
  // In the splitted array, we traverse through every line and check if it will be parsed as a codeblock.
120
126
  return lines.map(function (line) {
121
- if (!isInsideCodeBlock && openingCodeFenceRegex.test(line)) {
127
+ if (!isInsideCodeBlock && OPENING_CODE_FENCE_REGEX.test(line)) {
122
128
  isInsideCodeBlock = true;
123
129
  return line;
124
130
  }
125
- if (isInsideCodeBlock && closingCodeFenceRegex.test(line)) {
131
+ if (isInsideCodeBlock && CLOSING_CODE_FENCE_REGEX.test(line)) {
126
132
  isInsideCodeBlock = false;
127
133
  return line;
128
134
  }
@@ -223,9 +229,7 @@ export var htmlHasInvalidLinkTags = function htmlHasInvalidLinkTags(html) {
223
229
  // <li><a href="http://www.atlassian.com\"<a> href="http://www.atlassian.com\"http://www.atlassian.com</a></a></li>">
224
230
  export var removeDuplicateInvalidLinks = function removeDuplicateInvalidLinks(html) {
225
231
  if (htmlHasInvalidLinkTags(html)) {
226
- // Ignored via go/ees005
227
- // eslint-disable-next-line require-unicode-regexp
228
- var htmlArray = html.split(/(?=<a)/);
232
+ var htmlArray = html.split(SPLIT_ON_ANCHOR_REGEX);
229
233
  var htmlArrayWithoutInvalidLinks = htmlArray.filter(function (item) {
230
234
  return !(item.includes('<a') && item.includes('"></a>')) && !(item.includes('<a') && !item.includes('</a>'));
231
235
  });
@@ -15,4 +15,4 @@ export declare function updateSelectionAfterReplace({ tr }: {
15
15
  export declare function insertSliceForTaskInsideList({ tr, slice, }: {
16
16
  slice: PMSlice;
17
17
  tr: Transaction;
18
- }): void;
18
+ }): Transaction;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-paste",
3
- "version": "13.2.3",
3
+ "version": "13.3.1",
4
4
  "description": "Paste plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -21,7 +21,7 @@
21
21
  "dependencies": {
22
22
  "@atlaskit/adf-schema": "^56.0.0",
23
23
  "@atlaskit/adf-utils": "^20.0.0",
24
- "@atlaskit/code": "^18.0.0",
24
+ "@atlaskit/code": "^18.2.0",
25
25
  "@atlaskit/editor-markdown-transformer": "^6.0.0",
26
26
  "@atlaskit/editor-plugin-analytics": "^12.0.0",
27
27
  "@atlaskit/editor-plugin-annotation": "^12.0.0",
@@ -31,24 +31,24 @@
31
31
  "@atlaskit/editor-plugin-feature-flags": "^11.0.0",
32
32
  "@atlaskit/editor-plugin-list": "^14.1.0",
33
33
  "@atlaskit/editor-plugin-media": "^14.2.0",
34
- "@atlaskit/editor-plugin-mentions": "^14.4.0",
34
+ "@atlaskit/editor-plugin-mentions": "^14.5.0",
35
35
  "@atlaskit/editor-prosemirror": "^8.0.0",
36
36
  "@atlaskit/editor-tables": "^3.0.0",
37
- "@atlaskit/flag": "^18.0.0",
38
- "@atlaskit/icon": "^36.0.0",
37
+ "@atlaskit/flag": "^18.1.0",
38
+ "@atlaskit/icon": "^36.1.0",
39
39
  "@atlaskit/insm": "^1.0.0",
40
40
  "@atlaskit/media-client": "^37.1.0",
41
- "@atlaskit/media-common": "^14.1.0",
41
+ "@atlaskit/media-common": "^14.2.0",
42
42
  "@atlaskit/platform-feature-flags": "^2.0.0",
43
43
  "@atlaskit/prosemirror-history": "^1.0.0",
44
- "@atlaskit/tmp-editor-statsig": "^114.0.0",
45
- "@atlaskit/tokens": "^15.0.0",
44
+ "@atlaskit/tmp-editor-statsig": "^114.5.0",
45
+ "@atlaskit/tokens": "^15.2.0",
46
46
  "@babel/runtime": "^7.0.0",
47
47
  "lodash": "^4.17.21",
48
48
  "uuid": "^3.1.0"
49
49
  },
50
50
  "peerDependencies": {
51
- "@atlaskit/editor-common": "^116.13.0",
51
+ "@atlaskit/editor-common": "^116.17.0",
52
52
  "react": "^18.2.0",
53
53
  "react-dom": "^18.2.0",
54
54
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
@@ -127,6 +127,9 @@
127
127
  },
128
128
  "platform_editor_paste_renderer_analytics": {
129
129
  "type": "boolean"
130
+ },
131
+ "platform_editor_flexible_list_kill_switch_1": {
132
+ "type": "boolean"
130
133
  }
131
134
  }
132
135
  }