@atlaskit/editor-plugin-paste 0.1.22 → 0.2.0

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 (78) hide show
  1. package/.eslintrc.js +18 -0
  2. package/CHANGELOG.md +6 -0
  3. package/dist/cjs/actions.js +12 -0
  4. package/dist/cjs/commands.js +255 -0
  5. package/dist/cjs/edge-cases/index.js +88 -0
  6. package/dist/cjs/edge-cases/lists.js +107 -0
  7. package/dist/cjs/handlers.js +939 -0
  8. package/dist/cjs/index.js +8 -1
  9. package/dist/cjs/plugin.js +43 -0
  10. package/dist/cjs/plugins/media.js +207 -0
  11. package/dist/cjs/pm-plugins/analytics.js +376 -0
  12. package/dist/cjs/pm-plugins/clipboard-text-serializer.js +43 -0
  13. package/dist/cjs/pm-plugins/main.js +484 -0
  14. package/dist/cjs/pm-plugins/plugin-factory.js +42 -0
  15. package/dist/cjs/reducer.js +41 -0
  16. package/dist/cjs/util/index.js +214 -0
  17. package/dist/cjs/util/tinyMCE.js +183 -0
  18. package/dist/es2019/actions.js +6 -0
  19. package/dist/es2019/commands.js +236 -0
  20. package/dist/es2019/edge-cases/index.js +87 -0
  21. package/dist/es2019/edge-cases/lists.js +113 -0
  22. package/dist/es2019/handlers.js +919 -0
  23. package/dist/es2019/index.js +1 -1
  24. package/dist/es2019/plugin.js +38 -0
  25. package/dist/es2019/plugins/media.js +204 -0
  26. package/dist/es2019/pm-plugins/analytics.js +332 -0
  27. package/dist/es2019/pm-plugins/clipboard-text-serializer.js +37 -0
  28. package/dist/es2019/pm-plugins/main.js +453 -0
  29. package/dist/es2019/pm-plugins/plugin-factory.js +30 -0
  30. package/dist/es2019/reducer.js +32 -0
  31. package/dist/es2019/util/index.js +209 -0
  32. package/dist/es2019/util/tinyMCE.js +168 -0
  33. package/dist/esm/actions.js +6 -0
  34. package/dist/esm/commands.js +249 -0
  35. package/dist/esm/edge-cases/index.js +81 -0
  36. package/dist/esm/edge-cases/lists.js +98 -0
  37. package/dist/esm/handlers.js +918 -0
  38. package/dist/esm/index.js +1 -1
  39. package/dist/esm/plugin.js +37 -0
  40. package/dist/esm/plugins/media.js +199 -0
  41. package/dist/esm/pm-plugins/analytics.js +364 -0
  42. package/dist/esm/pm-plugins/clipboard-text-serializer.js +37 -0
  43. package/dist/esm/pm-plugins/main.js +471 -0
  44. package/dist/esm/pm-plugins/plugin-factory.js +36 -0
  45. package/dist/esm/reducer.js +34 -0
  46. package/dist/esm/util/index.js +194 -0
  47. package/dist/esm/util/tinyMCE.js +176 -0
  48. package/dist/types/actions.d.ts +21 -0
  49. package/dist/types/commands.d.ts +29 -0
  50. package/dist/types/edge-cases/index.d.ts +11 -0
  51. package/dist/types/edge-cases/lists.d.ts +18 -0
  52. package/dist/types/handlers.d.ts +55 -0
  53. package/dist/types/index.d.ts +1 -0
  54. package/dist/types/plugin.d.ts +2 -0
  55. package/dist/types/plugins/media.d.ts +23 -0
  56. package/dist/types/pm-plugins/analytics.d.ts +44 -0
  57. package/dist/types/pm-plugins/clipboard-text-serializer.d.ts +13 -0
  58. package/dist/types/pm-plugins/main.d.ts +12 -0
  59. package/dist/types/pm-plugins/plugin-factory.d.ts +3 -0
  60. package/dist/types/reducer.d.ts +3 -0
  61. package/dist/types/util/index.d.ts +21 -0
  62. package/dist/types/util/tinyMCE.d.ts +32 -0
  63. package/dist/types-ts4.5/actions.d.ts +21 -0
  64. package/dist/types-ts4.5/commands.d.ts +29 -0
  65. package/dist/types-ts4.5/edge-cases/index.d.ts +11 -0
  66. package/dist/types-ts4.5/edge-cases/lists.d.ts +18 -0
  67. package/dist/types-ts4.5/handlers.d.ts +55 -0
  68. package/dist/types-ts4.5/index.d.ts +1 -0
  69. package/dist/types-ts4.5/plugin.d.ts +2 -0
  70. package/dist/types-ts4.5/plugins/media.d.ts +23 -0
  71. package/dist/types-ts4.5/pm-plugins/analytics.d.ts +44 -0
  72. package/dist/types-ts4.5/pm-plugins/clipboard-text-serializer.d.ts +13 -0
  73. package/dist/types-ts4.5/pm-plugins/main.d.ts +12 -0
  74. package/dist/types-ts4.5/pm-plugins/plugin-factory.d.ts +3 -0
  75. package/dist/types-ts4.5/reducer.d.ts +3 -0
  76. package/dist/types-ts4.5/util/index.d.ts +21 -0
  77. package/dist/types-ts4.5/util/tinyMCE.d.ts +32 -0
  78. package/package.json +17 -5
@@ -0,0 +1,939 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.doesSelectionWhichStartsOrEndsInListContainEntireList = void 0;
8
+ exports.flattenNestedListInSlice = flattenNestedListInSlice;
9
+ exports.handleCodeBlock = handleCodeBlock;
10
+ exports.handleExpandPasteInTable = handleExpandPasteInTable;
11
+ exports.handleMacroAutoConvert = handleMacroAutoConvert;
12
+ exports.handleMarkdown = handleMarkdown;
13
+ exports.handleMediaSingle = handleMediaSingle;
14
+ exports.handleMention = handleMention;
15
+ exports.handleParagraphBlockMarks = handleParagraphBlockMarks;
16
+ exports.handlePasteAsPlainText = handlePasteAsPlainText;
17
+ exports.handlePasteIntoCaption = handlePasteIntoCaption;
18
+ exports.handlePasteIntoTaskOrDecisionOrPanel = handlePasteIntoTaskOrDecisionOrPanel;
19
+ exports.handlePasteLinkOnSelectedText = handlePasteLinkOnSelectedText;
20
+ exports.handlePasteNonNestableBlockNodesIntoList = handlePasteNonNestableBlockNodesIntoList;
21
+ exports.handlePastePanelOrDecisionContentIntoList = handlePastePanelOrDecisionContentIntoList;
22
+ exports.handlePastePreservingMarks = handlePastePreservingMarks;
23
+ exports.handleRichText = handleRichText;
24
+ exports.handleSelectedTable = void 0;
25
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
26
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
27
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
28
+ var _v = _interopRequireDefault(require("uuid/v4"));
29
+ var _analytics = require("@atlaskit/editor-common/analytics");
30
+ var _coreUtils = require("@atlaskit/editor-common/core-utils");
31
+ var _mark = require("@atlaskit/editor-common/mark");
32
+ var _selection = require("@atlaskit/editor-common/selection");
33
+ var _utils = require("@atlaskit/editor-common/utils");
34
+ var _history = require("@atlaskit/editor-prosemirror/history");
35
+ var _model = require("@atlaskit/editor-prosemirror/model");
36
+ var _state = require("@atlaskit/editor-prosemirror/state");
37
+ var _utils2 = require("@atlaskit/editor-prosemirror/utils");
38
+ var _utils3 = require("@atlaskit/editor-tables/utils");
39
+ var _commands = require("./commands");
40
+ var _edgeCases = require("./edge-cases");
41
+ var _pluginFactory = require("./pm-plugins/plugin-factory");
42
+ var _util = require("./util");
43
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, 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 normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
44
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
45
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
46
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
47
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // TODO: ED-20519 Needs Macro extraction
48
+ /** Helper type for single arg function */
49
+
50
+ /* eslint-disable @typescript-eslint/no-explicit-any */
51
+ /**
52
+ * Compose 1 to n functions.
53
+ * @param func first function
54
+ * @param funcs additional functions
55
+ */
56
+ function compose(func) {
57
+ for (var _len = arguments.length, funcs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
58
+ funcs[_key - 1] = arguments[_key];
59
+ }
60
+ var allFuncs = [func].concat(funcs);
61
+ return function composed(raw) {
62
+ return allFuncs.reduceRight(function (memo, func) {
63
+ return func(memo);
64
+ }, raw);
65
+ };
66
+ }
67
+ /* eslint-enable @typescript-eslint/no-explicit-any */
68
+
69
+ // remove text attribute from mention for copy/paste (GDPR)
70
+ function handleMention(slice, schema) {
71
+ return (0, _utils.mapSlice)(slice, function (node) {
72
+ if (node.type.name === schema.nodes.mention.name) {
73
+ var mention = node.attrs;
74
+ var newMention = _objectSpread(_objectSpread({}, mention), {}, {
75
+ text: ''
76
+ });
77
+ return schema.nodes.mention.create(newMention, node.content, node.marks);
78
+ }
79
+ return node;
80
+ });
81
+ }
82
+ function handlePasteIntoTaskOrDecisionOrPanel(slice, queueCardsFromChangedTr) {
83
+ return function (state, dispatch) {
84
+ var _slice$content$firstC, _transformedSlice$con;
85
+ var schema = state.schema,
86
+ selection = state.tr.selection;
87
+ var codeMark = schema.marks.code,
88
+ _schema$nodes = schema.nodes,
89
+ decisionItem = _schema$nodes.decisionItem,
90
+ emoji = _schema$nodes.emoji,
91
+ hardBreak = _schema$nodes.hardBreak,
92
+ mention = _schema$nodes.mention,
93
+ paragraph = _schema$nodes.paragraph,
94
+ taskItem = _schema$nodes.taskItem,
95
+ text = _schema$nodes.text,
96
+ panel = _schema$nodes.panel,
97
+ bulletList = _schema$nodes.bulletList,
98
+ orderedList = _schema$nodes.orderedList,
99
+ taskList = _schema$nodes.taskList,
100
+ listItem = _schema$nodes.listItem,
101
+ expand = _schema$nodes.expand,
102
+ heading = _schema$nodes.heading;
103
+ var selectionIsValidNode = state.selection instanceof _state.NodeSelection && ['decisionList', 'decisionItem', 'taskList', 'taskItem'].includes(state.selection.node.type.name);
104
+ var selectionHasValidParentNode = (0, _utils2.hasParentNodeOfType)([decisionItem, taskItem, panel])(state.selection);
105
+ var selectionIsPanel = (0, _utils2.hasParentNodeOfType)([panel])(state.selection);
106
+
107
+ // Some types of content should be handled by the default handler, not this function.
108
+ // Check through slice content to see if it contains an invalid node.
109
+ var sliceIsInvalid = false;
110
+ slice.content.nodesBetween(0, slice.content.size, function (node) {
111
+ if (node.type === bulletList || node.type === orderedList || node.type === expand || node.type === heading || node.type === listItem) {
112
+ sliceIsInvalid = true;
113
+ }
114
+ if (selectionIsPanel && node.type === taskList) {
115
+ sliceIsInvalid = true;
116
+ }
117
+ });
118
+
119
+ // If the selection is a panel,
120
+ // and the slice's first node is a paragraph
121
+ // and it is not from a depth that would indicate it being from inside from another node (e.g. text from a decision)
122
+ // then we can rely on the default behaviour.
123
+ var sliceIsAPanelReceivingLowDepthText = selectionIsPanel && ((_slice$content$firstC = slice.content.firstChild) === null || _slice$content$firstC === void 0 ? void 0 : _slice$content$firstC.type) === paragraph && slice.openEnd < 2;
124
+ if (sliceIsInvalid || sliceIsAPanelReceivingLowDepthText || !selectionIsValidNode && !selectionHasValidParentNode) {
125
+ return false;
126
+ }
127
+ var filters = [(0, _utils.linkifyContent)(schema)];
128
+ var selectionMarks = selection.$head.marks();
129
+ if (selection instanceof _state.TextSelection && Array.isArray(selectionMarks) && selectionMarks.length > 0 && (0, _util.hasOnlyNodesOfType)(paragraph, text, emoji, mention, hardBreak)(slice) && (!codeMark.isInSet(selectionMarks) || (0, _mark.anyMarkActive)(state, codeMark)) // check if there is a code mark anywhere in the selection
130
+ ) {
131
+ filters.push((0, _util.applyTextMarksToSlice)(schema, selection.$head.marks()));
132
+ }
133
+ var transformedSlice = compose.apply(null, filters)(slice);
134
+ var tr = (0, _history.closeHistory)(state.tr);
135
+ var transformedSliceIsValidNode = transformedSlice.content.firstChild.type.inlineContent || ['decisionList', 'decisionItem', 'taskList', 'taskItem', 'panel'].includes(transformedSlice.content.firstChild.type.name) && !(0, _utils.isInListItem)(state);
136
+ // If the slice or the selection are valid nodes to handle,
137
+ // and the slice is not a whole node (i.e. openStart is 1 and openEnd is 0)
138
+ // or the slice's first node is a paragraph,
139
+ // then we can replace the selection with our slice.
140
+ if ((transformedSliceIsValidNode || selectionIsValidNode) && !(transformedSlice.openStart === 1 && transformedSlice.openEnd === 0 ||
141
+ // Whole codeblock node has reverse slice depths.
142
+ transformedSlice.openStart === 0 && transformedSlice.openEnd === 1) || ((_transformedSlice$con = transformedSlice.content.firstChild) === null || _transformedSlice$con === void 0 ? void 0 : _transformedSlice$con.type) === paragraph) {
143
+ tr.replaceSelection(transformedSlice).scrollIntoView();
144
+ } else {
145
+ // This maintains both the selection (destination) and the slice (paste content).
146
+ (0, _utils2.safeInsert)(transformedSlice.content)(tr).scrollIntoView();
147
+ }
148
+ queueCardsFromChangedTr === null || queueCardsFromChangedTr === void 0 || queueCardsFromChangedTr(state, tr, _analytics.INPUT_METHOD.CLIPBOARD);
149
+ if (dispatch) {
150
+ dispatch(tr);
151
+ }
152
+ return true;
153
+ };
154
+ }
155
+ function handlePasteNonNestableBlockNodesIntoList(slice) {
156
+ return function (state, dispatch) {
157
+ var _tr$doc$nodeAt, _sliceContent$firstCh, _findParentNodeOfType;
158
+ var tr = state.tr;
159
+ var selection = tr.selection;
160
+ var $from = selection.$from,
161
+ $to = selection.$to,
162
+ from = selection.from,
163
+ to = selection.to;
164
+ var _state$schema$nodes = state.schema.nodes,
165
+ orderedList = _state$schema$nodes.orderedList,
166
+ bulletList = _state$schema$nodes.bulletList,
167
+ listItem = _state$schema$nodes.listItem;
168
+
169
+ // Selected nodes
170
+ var selectionParentListItemNode = (0, _utils2.findParentNodeOfType)(listItem)(selection);
171
+ var selectionParentListNodeWithPos = (0, _utils2.findParentNodeOfType)([bulletList, orderedList])(selection);
172
+ var selectionParentListNode = selectionParentListNodeWithPos === null || selectionParentListNodeWithPos === void 0 ? void 0 : selectionParentListNodeWithPos.node;
173
+
174
+ // Slice info
175
+ var sliceContent = slice.content;
176
+ var sliceIsListItems = (0, _utils.isListNode)(sliceContent.firstChild) && (0, _utils.isListNode)(sliceContent.lastChild);
177
+
178
+ // Find case of slices that can be inserted into a list item
179
+ // (eg. paragraphs, list items, code blocks, media single)
180
+ // These scenarios already get handled elsewhere and don't need to split the list
181
+ var sliceContainsBlockNodesOtherThanThoseAllowedInListItem = false;
182
+ slice.content.forEach(function (child) {
183
+ var _listItem$spec$conten;
184
+ if (!listItem || child.isBlock && !((_listItem$spec$conten = listItem.spec.content) !== null && _listItem$spec$conten !== void 0 && _listItem$spec$conten.includes(child.type.name))) {
185
+ sliceContainsBlockNodesOtherThanThoseAllowedInListItem = true;
186
+ }
187
+ });
188
+ if (!selectionParentListItemNode || !sliceContent || (0, _utils2.canInsert)($from, sliceContent) ||
189
+ // eg. inline nodes that can be inserted in a list item
190
+ !sliceContainsBlockNodesOtherThanThoseAllowedInListItem || sliceIsListItems || !selectionParentListNodeWithPos) {
191
+ return false;
192
+ }
193
+
194
+ // Offsets
195
+ var listWrappingOffset = $to.depth - selectionParentListNodeWithPos.depth + 1; // difference in depth between to position and list node
196
+ var listItemWrappingOffset = $to.depth - selectionParentListNodeWithPos.depth; // difference in depth between to position and list item node
197
+
198
+ // Anything to do with nested lists should safeInsert and not be handled here
199
+ var grandParentListNode = (0, _utils2.findParentNodeOfTypeClosestToPos)(tr.doc.resolve(selectionParentListNodeWithPos.pos), [bulletList, orderedList]);
200
+ var selectionIsInNestedList = !!grandParentListNode;
201
+ var selectedListItemHasNestedList = false;
202
+ selectionParentListItemNode.node.content.forEach(function (child) {
203
+ if ((0, _utils.isListNode)(child)) {
204
+ selectedListItemHasNestedList = true;
205
+ }
206
+ });
207
+ if (selectedListItemHasNestedList || selectionIsInNestedList) {
208
+ return false;
209
+ }
210
+
211
+ // Node after the insert position
212
+ var nodeAfterInsertPositionIsListItem = ((_tr$doc$nodeAt = tr.doc.nodeAt(to + listItemWrappingOffset)) === null || _tr$doc$nodeAt === void 0 ? void 0 : _tr$doc$nodeAt.type.name) === 'listItem';
213
+
214
+ // Get the next list items position (used later to find the split out ordered list)
215
+ var indexOfNextListItem = $to.indexAfter($to.depth - listItemWrappingOffset);
216
+ var positionOfNextListItem = tr.doc.resolve(selectionParentListNodeWithPos.pos + 1).posAtIndex(indexOfNextListItem);
217
+
218
+ // These nodes paste as plain text by default so need to be handled differently
219
+ var sliceContainsNodeThatPastesAsPlainText = sliceContent.firstChild && ['taskItem', 'taskList', 'heading', 'blockquote'].includes(sliceContent.firstChild.type.name);
220
+
221
+ // Work out position to replace up to
222
+ var replaceTo;
223
+ if (sliceContainsNodeThatPastesAsPlainText && nodeAfterInsertPositionIsListItem) {
224
+ replaceTo = to + listItemWrappingOffset;
225
+ } else if (sliceContainsNodeThatPastesAsPlainText || !nodeAfterInsertPositionIsListItem) {
226
+ replaceTo = to;
227
+ } else {
228
+ replaceTo = to + listWrappingOffset;
229
+ }
230
+
231
+ // handle the insertion of the slice
232
+ if (sliceContainsNodeThatPastesAsPlainText || nodeAfterInsertPositionIsListItem || sliceContent.childCount > 1 && ((_sliceContent$firstCh = sliceContent.firstChild) === null || _sliceContent$firstCh === void 0 ? void 0 : _sliceContent$firstCh.type.name) !== 'paragraph') {
233
+ tr.replaceWith(from, replaceTo, sliceContent).scrollIntoView();
234
+ } else {
235
+ // When the selection is not at the end of a list item
236
+ // eg. middle of list item, start of list item
237
+ tr.replaceSelection(slice).scrollIntoView();
238
+ }
239
+
240
+ // Find the ordered list node after the pasted content so we can set it's order
241
+ var mappedPositionOfNextListItem = tr.mapping.map(positionOfNextListItem);
242
+ if (mappedPositionOfNextListItem > tr.doc.nodeSize) {
243
+ return false;
244
+ }
245
+ var nodeAfterPastedContentResolvedPos = (0, _utils2.findParentNodeOfTypeClosestToPos)(tr.doc.resolve(mappedPositionOfNextListItem), [orderedList]);
246
+
247
+ // Work out the new split out lists 'order' (the number it starts from)
248
+ var originalParentOrderedListNodeOrder = selectionParentListNode === null || selectionParentListNode === void 0 ? void 0 : selectionParentListNode.attrs.order;
249
+ var numOfListItemsInOriginalList = (_findParentNodeOfType = (0, _utils2.findParentNodeOfTypeClosestToPos)(tr.doc.resolve(from - 1), [orderedList])) === null || _findParentNodeOfType === void 0 ? void 0 : _findParentNodeOfType.node.childCount;
250
+
251
+ // Set the new split out lists order attribute
252
+ if (typeof originalParentOrderedListNodeOrder === 'number' && numOfListItemsInOriginalList && nodeAfterPastedContentResolvedPos) {
253
+ tr.setNodeMarkup(nodeAfterPastedContentResolvedPos.pos, orderedList, _objectSpread(_objectSpread({}, nodeAfterPastedContentResolvedPos.node.attrs), {}, {
254
+ order: originalParentOrderedListNodeOrder + numOfListItemsInOriginalList
255
+ }));
256
+ }
257
+
258
+ // dispatch transaction
259
+ if (tr.docChanged) {
260
+ if (dispatch) {
261
+ dispatch(tr);
262
+ }
263
+ return true;
264
+ }
265
+ return false;
266
+ };
267
+ }
268
+ var doesSelectionWhichStartsOrEndsInListContainEntireList = exports.doesSelectionWhichStartsOrEndsInListContainEntireList = function doesSelectionWhichStartsOrEndsInListContainEntireList(selection, findRootParentListNode) {
269
+ var $from = selection.$from,
270
+ $to = selection.$to,
271
+ from = selection.from,
272
+ to = selection.to;
273
+ var selectionParentListItemNodeResolvedPos = findRootParentListNode ? findRootParentListNode($from) || findRootParentListNode($to) : null;
274
+ var selectionParentListNode = selectionParentListItemNodeResolvedPos === null || selectionParentListItemNodeResolvedPos === void 0 ? void 0 : selectionParentListItemNodeResolvedPos.parent;
275
+ if (!selectionParentListItemNodeResolvedPos || !selectionParentListNode) {
276
+ return false;
277
+ }
278
+ var startOfEntireList = $from.pos < $to.pos ? selectionParentListItemNodeResolvedPos.pos + $from.depth - 1 : selectionParentListItemNodeResolvedPos.pos + $to.depth - 1;
279
+ var endOfEntireList = $from.pos < $to.pos ? selectionParentListItemNodeResolvedPos.pos + selectionParentListNode.nodeSize - $to.depth - 1 : selectionParentListItemNodeResolvedPos.pos + selectionParentListNode.nodeSize - $from.depth - 1;
280
+ if (!startOfEntireList || !endOfEntireList) {
281
+ return false;
282
+ }
283
+ if (from < to) {
284
+ return startOfEntireList >= $from.pos && endOfEntireList <= $to.pos;
285
+ } else if (from > to) {
286
+ return startOfEntireList >= $to.pos && endOfEntireList <= $from.pos;
287
+ } else {
288
+ return false;
289
+ }
290
+ };
291
+ function handlePastePanelOrDecisionContentIntoList(slice, findRootParentListNode) {
292
+ return function (state, dispatch) {
293
+ var schema = state.schema,
294
+ tr = state.tr;
295
+ var selection = tr.selection;
296
+ // Check this pasting action is related to copy content from panel node into a selected the list node
297
+ var blockNode = slice.content.firstChild;
298
+ var isSliceWholeNode = slice.openStart === 0 && slice.openEnd === 0;
299
+ var selectionParentListItemNode = selection.$to.node(selection.$to.depth - 1);
300
+ var sliceIsWholeNodeButShouldNotReplaceSelection = isSliceWholeNode && !doesSelectionWhichStartsOrEndsInListContainEntireList(selection, findRootParentListNode);
301
+ if (!selectionParentListItemNode || (selectionParentListItemNode === null || selectionParentListItemNode === void 0 ? void 0 : selectionParentListItemNode.type) !== schema.nodes.listItem || !blockNode || !['panel', 'decisionList'].includes(blockNode === null || blockNode === void 0 ? void 0 : blockNode.type.name) || slice.content.childCount > 1 || (blockNode === null || blockNode === void 0 ? void 0 : blockNode.content.firstChild) === undefined || sliceIsWholeNodeButShouldNotReplaceSelection) {
302
+ return false;
303
+ }
304
+
305
+ // Paste the panel node contents extracted instead of pasting the entire panel node
306
+ tr.replaceSelection(slice).scrollIntoView();
307
+ if (dispatch) {
308
+ dispatch(tr);
309
+ }
310
+ return true;
311
+ };
312
+ }
313
+
314
+ // If we paste a link onto some selected text, apply the link as a mark
315
+ function handlePasteLinkOnSelectedText(slice) {
316
+ return function (state, dispatch) {
317
+ var schema = state.schema,
318
+ selection = state.selection,
319
+ _state$selection = state.selection,
320
+ from = _state$selection.from,
321
+ to = _state$selection.to,
322
+ tr = state.tr;
323
+ var linkMark;
324
+
325
+ // check if we have a link on the clipboard
326
+ if (slice.content.childCount === 1 && (0, _utils.isParagraph)(slice.content.child(0), schema)) {
327
+ var paragraph = slice.content.child(0);
328
+ if (paragraph.content.childCount === 1 && (0, _utils.isText)(paragraph.content.child(0), schema)) {
329
+ var text = paragraph.content.child(0);
330
+
331
+ // If pasteType is plain text, then
332
+ // @atlaskit/editor-markdown-transformer in getMarkdownSlice decode
333
+ // url before setting text property of text node.
334
+ // However href of marks will be without decoding.
335
+ // So, if there is character (e.g space) in url eligible escaping then
336
+ // mark.attrs.href will not be equal to text.text.
337
+ // That's why decoding mark.attrs.href before comparing.
338
+ // However, if pasteType is richText, that means url in text.text
339
+ // and href in marks, both won't be decoded.
340
+ linkMark = text.marks.find(function (mark) {
341
+ return (0, _utils.isLinkMark)(mark, schema) && (mark.attrs.href === text.text || decodeURI(mark.attrs.href) === text.text);
342
+ });
343
+ }
344
+ }
345
+
346
+ // if we have a link, apply it to the selected text if we have any and it's allowed
347
+ if (linkMark && selection instanceof _state.TextSelection && !selection.empty && (0, _utils.canLinkBeCreatedInRange)(from, to)(state)) {
348
+ tr.addMark(from, to, linkMark);
349
+ if (dispatch) {
350
+ dispatch(tr);
351
+ }
352
+ return true;
353
+ }
354
+ return false;
355
+ };
356
+ }
357
+ function handlePasteAsPlainText(slice, _event, editorAnalyticsAPI) {
358
+ return function (state, dispatch, view) {
359
+ var _input;
360
+ if (!view) {
361
+ return false;
362
+ }
363
+
364
+ // prosemirror-bump-fix
365
+ // Yes, this is wrong by default. But, we need to keep the private PAI usage to unblock the prosemirror bump
366
+ // So, this code will make sure we are checking for both version (current and the newest prosemirror-view version
367
+ var isShiftKeyPressed =
368
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
369
+ view.shiftKey || ((_input = view.input) === null || _input === void 0 ? void 0 : _input.shiftKey);
370
+ // In case of SHIFT+CMD+V ("Paste and Match Style") we don't want to run the usual
371
+ // fuzzy matching of content. ProseMirror already handles this scenario and will
372
+ // provide us with slice containing paragraphs with plain text, which we decorate
373
+ // with "stored marks".
374
+ // @see prosemirror-view/src/clipboard.js:parseFromClipboard()).
375
+ // @see prosemirror-view/src/input.js:doPaste().
376
+ if (isShiftKeyPressed) {
377
+ var tr = (0, _history.closeHistory)(state.tr);
378
+ var _tr = tr,
379
+ selection = _tr.selection;
380
+
381
+ // <- using the same internal flag that prosemirror-view is using
382
+
383
+ // if user has selected table we need custom logic to replace the table
384
+ tr = (0, _utils3.replaceSelectedTable)(state, slice);
385
+
386
+ // add analytics after replacing selected table
387
+ tr = (0, _util.addReplaceSelectedTableAnalytics)(state, tr, editorAnalyticsAPI);
388
+
389
+ // otherwise just replace the selection
390
+ if (!tr.docChanged) {
391
+ tr.replaceSelection(slice);
392
+ }
393
+ (state.storedMarks || []).forEach(function (mark) {
394
+ tr.addMark(selection.from, selection.from + slice.size, mark);
395
+ });
396
+ tr.scrollIntoView();
397
+ if (dispatch) {
398
+ dispatch(tr);
399
+ }
400
+ return true;
401
+ }
402
+ return false;
403
+ };
404
+ }
405
+ function handlePastePreservingMarks(slice, queueCardsFromChangedTr) {
406
+ return function (state, dispatch) {
407
+ var schema = state.schema,
408
+ selection = state.tr.selection;
409
+ var _schema$marks = schema.marks,
410
+ codeMark = _schema$marks.code,
411
+ annotationMark = _schema$marks.annotation,
412
+ _schema$nodes2 = schema.nodes,
413
+ bulletList = _schema$nodes2.bulletList,
414
+ emoji = _schema$nodes2.emoji,
415
+ hardBreak = _schema$nodes2.hardBreak,
416
+ heading = _schema$nodes2.heading,
417
+ listItem = _schema$nodes2.listItem,
418
+ mention = _schema$nodes2.mention,
419
+ orderedList = _schema$nodes2.orderedList,
420
+ text = _schema$nodes2.text;
421
+ if (!(selection instanceof _state.TextSelection)) {
422
+ return false;
423
+ }
424
+ var selectionMarks = selection.$head.marks();
425
+ if (selectionMarks.length === 0) {
426
+ return false;
427
+ }
428
+
429
+ // special case for codeMark: will preserve mark only if codeMark is currently active
430
+ // won't preserve mark if cursor is on the edge on the mark (namely inactive)
431
+ var hasActiveCodeMark = codeMark && codeMark.isInSet(selectionMarks) && (0, _mark.anyMarkActive)(state, codeMark);
432
+ var hasAnnotationMark = annotationMark && annotationMark.isInSet(selectionMarks);
433
+ var selectionIsHeading = (0, _utils2.hasParentNodeOfType)([heading])(state.selection);
434
+
435
+ // if the pasted data is one of the node types below
436
+ // we apply current selection marks to the pasted slice
437
+ if ((0, _util.hasOnlyNodesOfType)(bulletList, hardBreak, heading, listItem, text, emoji, mention, orderedList)(slice) || selectionIsHeading || hasActiveCodeMark || hasAnnotationMark) {
438
+ var transformedSlice = (0, _util.applyTextMarksToSlice)(schema, selectionMarks)(slice);
439
+ var tr = (0, _history.closeHistory)(state.tr).replaceSelection(transformedSlice).setStoredMarks(selectionMarks).scrollIntoView();
440
+ queueCardsFromChangedTr === null || queueCardsFromChangedTr === void 0 || queueCardsFromChangedTr(state, tr, _analytics.INPUT_METHOD.CLIPBOARD);
441
+ if (dispatch) {
442
+ dispatch(tr);
443
+ }
444
+ return true;
445
+ }
446
+ return false;
447
+ };
448
+ }
449
+ function getSmartLinkAdf(_x, _x2, _x3) {
450
+ return _getSmartLinkAdf.apply(this, arguments);
451
+ }
452
+ function _getSmartLinkAdf() {
453
+ _getSmartLinkAdf = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(text, type, cardOptions) {
454
+ var provider;
455
+ return _regenerator.default.wrap(function _callee$(_context) {
456
+ while (1) switch (_context.prev = _context.next) {
457
+ case 0:
458
+ if (cardOptions.provider) {
459
+ _context.next = 2;
460
+ break;
461
+ }
462
+ throw Error('No card provider found');
463
+ case 2:
464
+ _context.next = 4;
465
+ return cardOptions.provider;
466
+ case 4:
467
+ provider = _context.sent;
468
+ _context.next = 7;
469
+ return provider.resolve(text, type);
470
+ case 7:
471
+ return _context.abrupt("return", _context.sent);
472
+ case 8:
473
+ case "end":
474
+ return _context.stop();
475
+ }
476
+ }, _callee);
477
+ }));
478
+ return _getSmartLinkAdf.apply(this, arguments);
479
+ }
480
+ function insertAutoMacro(slice, macro, view, from, to) {
481
+ if (view) {
482
+ // insert the text or linkified/md-converted clipboard data
483
+ var selection = view.state.tr.selection;
484
+ var tr;
485
+ var before;
486
+ if (typeof from === 'number' && typeof to === 'number') {
487
+ tr = view.state.tr.replaceRange(from, to, slice);
488
+ before = tr.mapping.map(from, -1);
489
+ } else {
490
+ tr = view.state.tr.replaceSelection(slice);
491
+ before = tr.mapping.map(selection.from, -1);
492
+ }
493
+ view.dispatch(tr);
494
+
495
+ // replace the text with the macro as a separate transaction
496
+ // so the autoconversion generates 2 undo steps
497
+ view.dispatch((0, _history.closeHistory)(view.state.tr).replaceRangeWith(before, before + slice.size, macro).scrollIntoView());
498
+ return true;
499
+ }
500
+ return false;
501
+ }
502
+ function handleMacroAutoConvert(text, slice, queueCardsFromChangedTr, runMacroAutoConvert, cardsOptions, extensionAutoConverter) {
503
+ return function (state, dispatch, view) {
504
+ var macro = null;
505
+
506
+ // try to use auto convert from extension provider first
507
+ if (extensionAutoConverter) {
508
+ var extension = extensionAutoConverter(text);
509
+ if (extension) {
510
+ macro = _model.Node.fromJSON(state.schema, extension);
511
+ }
512
+ }
513
+
514
+ // then try from macro provider (which will be removed some time in the future)
515
+ if (!macro) {
516
+ var _runMacroAutoConvert;
517
+ macro = (_runMacroAutoConvert = runMacroAutoConvert === null || runMacroAutoConvert === void 0 ? void 0 : runMacroAutoConvert(state, text)) !== null && _runMacroAutoConvert !== void 0 ? _runMacroAutoConvert : null;
518
+ }
519
+ if (macro) {
520
+ /**
521
+ * if FF enabled, run through smart links and check for result
522
+ */
523
+ if (cardsOptions && cardsOptions.resolveBeforeMacros && cardsOptions.resolveBeforeMacros.length) {
524
+ var _startTrackingPastedM;
525
+ if (cardsOptions.resolveBeforeMacros.indexOf(macro.attrs.extensionKey) < 0) {
526
+ return insertAutoMacro(slice, macro, view);
527
+ }
528
+ if (!view) {
529
+ throw new Error('View is missing');
530
+ }
531
+ var trackingId = (0, _v.default)();
532
+ var trackingFrom = "handleMacroAutoConvert-from-".concat(trackingId);
533
+ var trackingTo = "handleMacroAutoConvert-to-".concat(trackingId);
534
+ (0, _commands.startTrackingPastedMacroPositions)((_startTrackingPastedM = {}, (0, _defineProperty2.default)(_startTrackingPastedM, trackingFrom, state.selection.from), (0, _defineProperty2.default)(_startTrackingPastedM, trackingTo, state.selection.to), _startTrackingPastedM))(state, dispatch);
535
+ getSmartLinkAdf(text, 'inline', cardsOptions).then(function () {
536
+ // we use view.state rather than state because state becomes a stale
537
+ // state reference after getSmartLinkAdf's async work
538
+ var _getPastePluginState = (0, _pluginFactory.getPluginState)(view.state),
539
+ pastedMacroPositions = _getPastePluginState.pastedMacroPositions;
540
+ if (dispatch) {
541
+ handleMarkdown(slice, queueCardsFromChangedTr, pastedMacroPositions[trackingFrom], pastedMacroPositions[trackingTo])(view.state, dispatch);
542
+ }
543
+ }).catch(function () {
544
+ var _getPastePluginState2 = (0, _pluginFactory.getPluginState)(view.state),
545
+ pastedMacroPositions = _getPastePluginState2.pastedMacroPositions;
546
+ insertAutoMacro(slice, macro, view, pastedMacroPositions[trackingFrom], pastedMacroPositions[trackingTo]);
547
+ }).finally(function () {
548
+ (0, _commands.stopTrackingPastedMacroPositions)([trackingFrom, trackingTo])(view.state, dispatch);
549
+ });
550
+ return true;
551
+ }
552
+ return insertAutoMacro(slice, macro, view);
553
+ }
554
+ return !!macro;
555
+ };
556
+ }
557
+ function handleCodeBlock(text) {
558
+ return function (state, dispatch) {
559
+ var codeBlock = state.schema.nodes.codeBlock;
560
+ if (text && (0, _utils2.hasParentNodeOfType)(codeBlock)(state.selection)) {
561
+ var tr = (0, _history.closeHistory)(state.tr);
562
+ tr.scrollIntoView();
563
+ if (dispatch) {
564
+ dispatch(tr.insertText(text));
565
+ }
566
+ return true;
567
+ }
568
+ return false;
569
+ };
570
+ }
571
+ function isOnlyMedia(state, slice) {
572
+ var media = state.schema.nodes.media;
573
+ return slice.content.childCount === 1 && slice.content.firstChild.type === media;
574
+ }
575
+ function isOnlyMediaSingle(state, slice) {
576
+ var mediaSingle = state.schema.nodes.mediaSingle;
577
+ return mediaSingle && slice.content.childCount === 1 && slice.content.firstChild.type === mediaSingle;
578
+ }
579
+ function handleMediaSingle(inputMethod, insertMediaAsMediaSingle) {
580
+ return function (slice) {
581
+ return function (state, dispatch, view) {
582
+ if (view) {
583
+ if (isOnlyMedia(state, slice)) {
584
+ var _insertMediaAsMediaSi;
585
+ return (_insertMediaAsMediaSi = insertMediaAsMediaSingle === null || insertMediaAsMediaSingle === void 0 ? void 0 : insertMediaAsMediaSingle(view, slice.content.firstChild, inputMethod)) !== null && _insertMediaAsMediaSi !== void 0 ? _insertMediaAsMediaSi : false;
586
+ }
587
+ if ((0, _coreUtils.insideTable)(state) && isOnlyMediaSingle(state, slice)) {
588
+ var tr = state.tr.replaceSelection(slice);
589
+ var nextPos = tr.doc.resolve(tr.mapping.map(state.selection.$from.pos));
590
+ if (dispatch) {
591
+ dispatch(tr.setSelection(new _selection.GapCursorSelection(nextPos, _selection.Side.RIGHT)));
592
+ }
593
+ return true;
594
+ }
595
+ }
596
+ return false;
597
+ };
598
+ };
599
+ }
600
+ var checkExpand = function checkExpand(slice) {
601
+ var hasExpand = false;
602
+ slice.content.forEach(function (node) {
603
+ if (node.type.name === 'expand') {
604
+ hasExpand = true;
605
+ }
606
+ });
607
+ return hasExpand;
608
+ };
609
+ function handleExpandPasteInTable(slice) {
610
+ return function (state, dispatch) {
611
+ // Do not handle expand if it's not being pasted into a table
612
+ // OR if it's nested within another node when being pasted into a table
613
+ if (!(0, _coreUtils.insideTable)(state) || !checkExpand(slice)) {
614
+ return false;
615
+ }
616
+ var _state$schema$nodes2 = state.schema.nodes,
617
+ expand = _state$schema$nodes2.expand,
618
+ nestedExpand = _state$schema$nodes2.nestedExpand;
619
+ var tr = state.tr;
620
+ var hasExpand = false;
621
+ var newSlice = (0, _utils.mapSlice)(slice, function (maybeNode) {
622
+ if (maybeNode.type === expand) {
623
+ hasExpand = true;
624
+ try {
625
+ return nestedExpand.createChecked(maybeNode.attrs, maybeNode.content, maybeNode.marks);
626
+ } catch (e) {
627
+ tr = (0, _utils2.safeInsert)(maybeNode, tr.selection.$to.pos)(tr);
628
+ return _model.Fragment.empty;
629
+ }
630
+ }
631
+ return maybeNode;
632
+ });
633
+ if (hasExpand && dispatch) {
634
+ // If the slice is a subset, we can let PM replace the selection
635
+ // it will insert as text where it can't place the node.
636
+ // Otherwise we use safeInsert to insert below instead of
637
+ // replacing/splitting the current node.
638
+ if (slice.openStart > 1 && slice.openEnd > 1) {
639
+ dispatch(tr.replaceSelection(newSlice));
640
+ } else {
641
+ dispatch((0, _utils2.safeInsert)(newSlice.content)(tr));
642
+ }
643
+ return true;
644
+ }
645
+ return false;
646
+ };
647
+ }
648
+ function handleMarkdown(markdownSlice, queueCardsFromChangedTr, from, to) {
649
+ return function (state, dispatch) {
650
+ var tr = (0, _history.closeHistory)(state.tr);
651
+ var pastesFrom = typeof from === 'number' ? from : tr.selection.from;
652
+ if (typeof from === 'number' && typeof to === 'number') {
653
+ tr.replaceRange(from, to, markdownSlice);
654
+ } else {
655
+ tr.replaceSelection(markdownSlice);
656
+ }
657
+ var textPosition = tr.doc.resolve(Math.min(pastesFrom + markdownSlice.size, tr.doc.content.size));
658
+ tr.setSelection(_state.TextSelection.near(textPosition, -1));
659
+ queueCardsFromChangedTr === null || queueCardsFromChangedTr === void 0 || queueCardsFromChangedTr(state, tr, _analytics.INPUT_METHOD.CLIPBOARD);
660
+ if (dispatch) {
661
+ dispatch(tr.scrollIntoView());
662
+ }
663
+ return true;
664
+ };
665
+ }
666
+ function removePrecedingBackTick(tr) {
667
+ var _tr$selection = tr.selection,
668
+ nodeBefore = _tr$selection.$from.nodeBefore,
669
+ from = _tr$selection.from;
670
+ if (nodeBefore && nodeBefore.isText && nodeBefore.text.endsWith('`')) {
671
+ tr.delete(from - 1, from);
672
+ }
673
+ }
674
+ function hasInlineCode(state, slice) {
675
+ return slice.content.firstChild && slice.content.firstChild.marks.some(function (m) {
676
+ return m.type === state.schema.marks.code;
677
+ });
678
+ }
679
+ function rollupLeafListItems(list, leafListItems) {
680
+ list.content.forEach(function (child) {
681
+ if ((0, _utils.isListNode)(child) || (0, _utils.isListItemNode)(child) && (0, _utils.isListNode)(child.firstChild)) {
682
+ rollupLeafListItems(child, leafListItems);
683
+ } else {
684
+ leafListItems.push(child);
685
+ }
686
+ });
687
+ }
688
+ function shouldFlattenList(state, slice) {
689
+ var node = slice.content.firstChild;
690
+ return node && (0, _coreUtils.insideTable)(state) && (0, _utils.isListNode)(node) && slice.openStart > slice.openEnd;
691
+ }
692
+ function sliceHasTopLevelMarks(slice) {
693
+ var hasTopLevelMarks = false;
694
+ slice.content.descendants(function (node) {
695
+ if (node.marks.length > 0) {
696
+ hasTopLevelMarks = true;
697
+ }
698
+ return false;
699
+ });
700
+ return hasTopLevelMarks;
701
+ }
702
+ function getTopLevelMarkTypesInSlice(slice) {
703
+ var markTypes = new Set();
704
+ slice.content.descendants(function (node) {
705
+ node.marks.map(function (mark) {
706
+ return mark.type;
707
+ }).forEach(function (markType) {
708
+ return markTypes.add(markType);
709
+ });
710
+ return false;
711
+ });
712
+ return markTypes;
713
+ }
714
+ function handleParagraphBlockMarks(state, slice) {
715
+ if (slice.content.size === 0) {
716
+ return slice;
717
+ }
718
+ var schema = state.schema,
719
+ $from = state.selection.$from;
720
+
721
+ // If no paragraph in the slice contains marks, there's no need for special handling
722
+ // Note: this doesn't check for marks applied to lower level nodes such as text
723
+ if (!sliceHasTopLevelMarks(slice)) {
724
+ return slice;
725
+ }
726
+
727
+ // If pasting a single paragraph into pre-existing content, match destination formatting
728
+ var destinationHasContent = $from.parent.textContent.length > 0;
729
+ if (slice.content.childCount === 1 && destinationHasContent) {
730
+ return slice;
731
+ }
732
+
733
+ // Check the parent of (paragraph -> text) because block marks are assigned to a wrapper
734
+ // element around the paragraph node
735
+ var grandparent = $from.node(Math.max(0, $from.depth - 1));
736
+ var markTypesInSlice = getTopLevelMarkTypesInSlice(slice);
737
+ var forbiddenMarkTypes = [];
738
+ var _iterator = _createForOfIteratorHelper(markTypesInSlice),
739
+ _step;
740
+ try {
741
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
742
+ var markType = _step.value;
743
+ if (!grandparent.type.allowsMarkType(markType)) {
744
+ forbiddenMarkTypes.push(markType);
745
+ }
746
+ }
747
+ } catch (err) {
748
+ _iterator.e(err);
749
+ } finally {
750
+ _iterator.f();
751
+ }
752
+ if (forbiddenMarkTypes.length === 0) {
753
+ // In a slice containing one or more paragraphs at the document level (not wrapped in
754
+ // another node), the first paragraph will only have its text content captured and pasted
755
+ // since openStart is 1. We decrement the open depth of the slice so it retains any block
756
+ // marks applied to it. We only care about the depth at the start of the selection so
757
+ // there's no need to change openEnd - the rest of the slice gets pasted correctly.
758
+ var openStart = Math.max(0, slice.openStart - 1);
759
+ return new _model.Slice(slice.content, openStart, slice.openEnd);
760
+ }
761
+
762
+ // If the paragraph contains marks forbidden by the parent node (e.g. alignment/indentation),
763
+ // drop those marks from the slice
764
+ return (0, _utils.mapSlice)(slice, function (node) {
765
+ if (node.type === schema.nodes.paragraph) {
766
+ return schema.nodes.paragraph.createChecked(undefined, node.content, node.marks.filter(function (mark) {
767
+ return !forbiddenMarkTypes.includes(mark.type);
768
+ }));
769
+ }
770
+ return node;
771
+ });
772
+ }
773
+
774
+ /**
775
+ * ED-6300: When a nested list is pasted in a table cell and the slice has openStart > openEnd,
776
+ * it splits the table. As a workaround, we flatten the list to even openStart and openEnd.
777
+ *
778
+ * Note: this only happens if the first child is a list
779
+ *
780
+ * Example: copying "one" and "two"
781
+ * - zero
782
+ * - one
783
+ * - two
784
+ *
785
+ * Before:
786
+ * ul
787
+ * ┗━ li
788
+ * ┗━ ul
789
+ * ┗━ li
790
+ * ┗━ p -> "one"
791
+ * ┗━ li
792
+ * ┗━ p -> "two"
793
+ *
794
+ * After:
795
+ * ul
796
+ * ┗━ li
797
+ * ┗━ p -> "one"
798
+ * ┗━ li
799
+ * ┗━p -> "two"
800
+ */
801
+ function flattenNestedListInSlice(slice) {
802
+ if (!slice.content.firstChild) {
803
+ return slice;
804
+ }
805
+ var listToFlatten = slice.content.firstChild;
806
+ var leafListItems = [];
807
+ rollupLeafListItems(listToFlatten, leafListItems);
808
+ var contentWithFlattenedList = slice.content.replaceChild(0, listToFlatten.type.createChecked(listToFlatten.attrs, leafListItems));
809
+ return new _model.Slice(contentWithFlattenedList, slice.openEnd, slice.openEnd);
810
+ }
811
+ function handleRichText(slice, queueCardsFromChangedTr) {
812
+ return function (state, dispatch) {
813
+ var _slice$content, _slice$content2, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
814
+ var _state$schema$nodes3 = state.schema.nodes,
815
+ codeBlock = _state$schema$nodes3.codeBlock,
816
+ heading = _state$schema$nodes3.heading,
817
+ paragraph = _state$schema$nodes3.paragraph,
818
+ panel = _state$schema$nodes3.panel;
819
+ var selection = state.selection,
820
+ schema = state.schema;
821
+ var firstChildOfSlice = (_slice$content = slice.content) === null || _slice$content === void 0 ? void 0 : _slice$content.firstChild;
822
+ var lastChildOfSlice = (_slice$content2 = slice.content) === null || _slice$content2 === void 0 ? void 0 : _slice$content2.lastChild;
823
+
824
+ // In case user is pasting inline code,
825
+ // any backtick ` immediately preceding it should be removed.
826
+ var tr = state.tr;
827
+ if (hasInlineCode(state, slice)) {
828
+ removePrecedingBackTick(tr);
829
+ }
830
+ if (shouldFlattenList(state, slice)) {
831
+ slice = flattenNestedListInSlice(slice);
832
+ }
833
+ (0, _history.closeHistory)(tr);
834
+ var isFirstChildListNode = (0, _utils.isListNode)(firstChildOfSlice);
835
+ var isLastChildListNode = (0, _utils.isListNode)(lastChildOfSlice);
836
+ var isSliceContentListNodes = isFirstChildListNode || isLastChildListNode;
837
+ var isFirstChildTaskListNode = (firstChildOfSlice === null || firstChildOfSlice === void 0 || (_firstChildOfSlice$ty = firstChildOfSlice.type) === null || _firstChildOfSlice$ty === void 0 ? void 0 : _firstChildOfSlice$ty.name) === 'taskList';
838
+ var isLastChildTaskListNode = (lastChildOfSlice === null || lastChildOfSlice === void 0 || (_lastChildOfSlice$typ = lastChildOfSlice.type) === null || _lastChildOfSlice$typ === void 0 ? void 0 : _lastChildOfSlice$typ.name) === 'taskList';
839
+ var isSliceContentTaskListNodes = isFirstChildTaskListNode || isLastChildTaskListNode;
840
+
841
+ // We want to use safeInsert to insert invalid content, as it inserts at the closest non schema violating position
842
+ // rather than spliting the selection parent node in half (which is what replaceSelection does)
843
+ // Exception is paragraph and heading nodes, these should be split, provided their parent supports the pasted content
844
+ var textNodes = [heading, paragraph];
845
+ var selectionParent = selection.$to.node(selection.$to.depth - 1);
846
+ var noNeedForSafeInsert = selection.$to.node().type.validContent(slice.content) || textNodes.includes(selection.$to.node().type) && selectionParent.type.validContent(slice.content);
847
+ var panelParentOverCurrentSelection = (0, _utils2.findParentNodeOfType)(panel)(tr.selection);
848
+ var isTargetPanelEmpty = panelParentOverCurrentSelection && ((_panelParentOverCurre = panelParentOverCurrentSelection.node) === null || _panelParentOverCurre === void 0 ? void 0 : _panelParentOverCurre.content.size) === 2;
849
+ if (!isSliceContentTaskListNodes && (isSliceContentListNodes || isTargetPanelEmpty)) {
850
+ (0, _edgeCases.insertSliceForLists)({
851
+ tr: tr,
852
+ slice: slice,
853
+ schema: schema
854
+ });
855
+ } else if (noNeedForSafeInsert) {
856
+ var _firstChildOfSlice$ty2, _firstChildOfSlice$co, _firstChildOfSlice$co2;
857
+ if ((firstChildOfSlice === null || firstChildOfSlice === void 0 || (_firstChildOfSlice$ty2 = firstChildOfSlice.type) === null || _firstChildOfSlice$ty2 === void 0 ? void 0 : _firstChildOfSlice$ty2.name) === 'blockquote' && firstChildOfSlice !== null && firstChildOfSlice !== void 0 && (_firstChildOfSlice$co = firstChildOfSlice.content.firstChild) !== null && _firstChildOfSlice$co !== void 0 && _firstChildOfSlice$co.type.name && ['bulletList', 'orderedList'].includes(firstChildOfSlice === null || firstChildOfSlice === void 0 || (_firstChildOfSlice$co2 = firstChildOfSlice.content.firstChild) === null || _firstChildOfSlice$co2 === void 0 ? void 0 : _firstChildOfSlice$co2.type.name)) {
858
+ // checks if parent node is a blockquote and child node is either a bulletlist or orderedlist
859
+ (0, _edgeCases.insertSliceForListsInsideBlockquote)({
860
+ tr: tr,
861
+ slice: slice
862
+ });
863
+ } else {
864
+ var _slice$content$lastCh;
865
+ tr.replaceSelection(slice);
866
+ // when cursor is inside a table cell, and slice.content.lastChild is a panel, expand, or decisionList
867
+ // need to make sure the cursor position is is right after the panel, expand, or decisionList
868
+ // still in the same table cell, see issue: https://product-fabric.atlassian.net/browse/ED-17862
869
+ var shouldUpdateCursorPosAfterPaste = ['panel', 'nestedExpand', 'decisionList', 'codeBlock'].includes(((_slice$content$lastCh = slice.content.lastChild) === null || _slice$content$lastCh === void 0 || (_slice$content$lastCh = _slice$content$lastCh.type) === null || _slice$content$lastCh === void 0 ? void 0 : _slice$content$lastCh.name) || '');
870
+ if ((0, _utils.insideTableCell)(state) && shouldUpdateCursorPosAfterPaste) {
871
+ var nextPos = tr.doc.resolve(tr.mapping.map(selection.$from.pos));
872
+ tr.setSelection(new _selection.GapCursorSelection(nextPos, _selection.Side.RIGHT));
873
+ }
874
+ }
875
+ } else {
876
+ // need to scan the slice if there's a block node or list items inside it
877
+ var sliceHasList = false;
878
+ slice.content.nodesBetween(0, slice.content.size, function (node, start) {
879
+ if (node.type === state.schema.nodes.listItem) {
880
+ sliceHasList = true;
881
+ return false;
882
+ }
883
+ });
884
+ if ((0, _utils.insideTableCell)(state) && (0, _utils.isInListItem)(state) && (0, _utils2.canInsert)(selection.$from, slice.content) && (0, _utils2.canInsert)(selection.$to, slice.content) || sliceHasList) {
885
+ tr.replaceSelection(slice);
886
+ } else {
887
+ // need safeInsert rather than replaceSelection, so that nodes aren't split in half
888
+ // e.g. when pasting a layout into a table, replaceSelection splits the table in half and adds the layout in the middle
889
+ tr = (0, _utils2.safeInsert)(slice.content, tr.selection.$to.pos)(tr);
890
+ }
891
+ }
892
+ tr.setStoredMarks([]);
893
+ if (tr.selection.empty && tr.selection.$from.parent.type === codeBlock) {
894
+ tr.setSelection(_state.TextSelection.near(tr.selection.$from, 1));
895
+ }
896
+ tr.scrollIntoView();
897
+
898
+ // queue link cards, ignoring any errors
899
+ queueCardsFromChangedTr === null || queueCardsFromChangedTr === void 0 || queueCardsFromChangedTr(state, tr, _analytics.INPUT_METHOD.CLIPBOARD);
900
+ if (dispatch) {
901
+ dispatch(tr);
902
+ }
903
+ return true;
904
+ };
905
+ }
906
+ function handlePasteIntoCaption(slice) {
907
+ return function (state, dispatch) {
908
+ var caption = state.schema.nodes.caption;
909
+ var tr = state.tr;
910
+ if ((0, _utils2.hasParentNodeOfType)(caption)(state.selection)) {
911
+ // We let PM replace the selection and it will insert as text where it can't place the node
912
+ // This is totally fine as caption is just a simple block that only contains inline contents
913
+ // And it is more in line with WYSIWYG expectations
914
+ tr.replaceSelection(slice).scrollIntoView();
915
+ if (dispatch) {
916
+ dispatch(tr);
917
+ }
918
+ return true;
919
+ }
920
+ return false;
921
+ };
922
+ }
923
+ var handleSelectedTable = exports.handleSelectedTable = function handleSelectedTable(editorAnalyticsAPI) {
924
+ return function (slice) {
925
+ return function (state, dispatch) {
926
+ var tr = (0, _utils3.replaceSelectedTable)(state, slice);
927
+
928
+ // add analytics after replacing selected table
929
+ tr = (0, _util.addReplaceSelectedTableAnalytics)(state, tr, editorAnalyticsAPI);
930
+ if (tr.docChanged) {
931
+ if (dispatch) {
932
+ dispatch(tr);
933
+ }
934
+ return true;
935
+ }
936
+ return false;
937
+ };
938
+ };
939
+ };