@atlaskit/editor-plugin-paste 1.12.3 → 1.12.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/cjs/handlers.js +16 -1
- package/dist/cjs/pm-plugins/analytics.js +2 -2
- package/dist/cjs/pm-plugins/main.js +7 -3
- package/dist/cjs/pm-plugins/move-analytics/commands.js +2 -1
- package/dist/cjs/pm-plugins/move-analytics/plugin.js +34 -13
- package/dist/cjs/pm-plugins/move-analytics/types.js +1 -0
- package/dist/cjs/pm-plugins/move-analytics/utils.js +42 -2
- package/dist/es2019/handlers.js +16 -1
- package/dist/es2019/pm-plugins/analytics.js +2 -2
- package/dist/es2019/pm-plugins/main.js +7 -3
- package/dist/es2019/pm-plugins/move-analytics/commands.js +2 -1
- package/dist/es2019/pm-plugins/move-analytics/plugin.js +31 -11
- package/dist/es2019/pm-plugins/move-analytics/types.js +1 -0
- package/dist/es2019/pm-plugins/move-analytics/utils.js +46 -2
- package/dist/esm/handlers.js +16 -1
- package/dist/esm/pm-plugins/analytics.js +2 -2
- package/dist/esm/pm-plugins/main.js +7 -3
- package/dist/esm/pm-plugins/move-analytics/commands.js +2 -1
- package/dist/esm/pm-plugins/move-analytics/plugin.js +34 -14
- package/dist/esm/pm-plugins/move-analytics/types.js +1 -0
- package/dist/esm/pm-plugins/move-analytics/utils.js +41 -2
- package/dist/types/handlers.d.ts +1 -1
- package/dist/types/pm-plugins/analytics.d.ts +1 -1
- package/dist/types/pm-plugins/move-analytics/types.d.ts +1 -0
- package/dist/types/pm-plugins/move-analytics/utils.d.ts +4 -0
- package/dist/types-ts4.5/handlers.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/analytics.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/move-analytics/types.d.ts +1 -0
- package/dist/types-ts4.5/pm-plugins/move-analytics/utils.d.ts +4 -0
- package/package.json +8 -4
- package/.eslintrc.js +0 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-paste
|
|
2
2
|
|
|
3
|
+
## 1.12.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#143700](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/143700)
|
|
8
|
+
[`9ef9b7e3bc1d7`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/9ef9b7e3bc1d7) -
|
|
9
|
+
[ux] [ED-24868] Paste gating for codeblock and media in quotes.
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
|
|
12
|
+
## 1.12.4
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- [#142433](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/142433)
|
|
17
|
+
[`896303d4b4390`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/896303d4b4390) -
|
|
18
|
+
ED-24552 Update document moved event to fire when nested nodes are cut/paste into nodes and add
|
|
19
|
+
nodeDepth attributes
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
|
|
3
22
|
## 1.12.3
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/dist/cjs/handlers.js
CHANGED
|
@@ -41,6 +41,7 @@ var _utils3 = require("@atlaskit/editor-tables/utils");
|
|
|
41
41
|
var _commands = require("./commands");
|
|
42
42
|
var _edgeCases = require("./edge-cases");
|
|
43
43
|
var _lists = require("./edge-cases/lists");
|
|
44
|
+
var _main = require("./pm-plugins/main");
|
|
44
45
|
var _pluginFactory = require("./pm-plugins/plugin-factory");
|
|
45
46
|
var _util = require("./util");
|
|
46
47
|
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
@@ -905,10 +906,11 @@ function flattenNestedListInSlice(slice) {
|
|
|
905
906
|
var contentWithFlattenedList = slice.content.replaceChild(0, listToFlatten.type.createChecked(listToFlatten.attrs, leafListItems));
|
|
906
907
|
return new _model.Slice(contentWithFlattenedList, slice.openEnd, slice.openEnd);
|
|
907
908
|
}
|
|
908
|
-
function handleRichText(slice, queueCardsFromChangedTr) {
|
|
909
|
+
function handleRichText(slice, queueCardsFromChangedTr, isNestingMediaOrCodeblockSupported) {
|
|
909
910
|
return function (state, dispatch) {
|
|
910
911
|
var _slice$content, _slice$content2, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
911
912
|
var _state$schema$nodes4 = state.schema.nodes,
|
|
913
|
+
blockquote = _state$schema$nodes4.blockquote,
|
|
912
914
|
codeBlock = _state$schema$nodes4.codeBlock,
|
|
913
915
|
heading = _state$schema$nodes4.heading,
|
|
914
916
|
paragraph = _state$schema$nodes4.paragraph,
|
|
@@ -943,12 +945,25 @@ function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
943
945
|
var noNeedForSafeInsert = selection.$to.node().type.validContent(slice.content) || textNodes.includes(selection.$to.node().type) && selectionParent.type.validContent(slice.content);
|
|
944
946
|
var panelParentOverCurrentSelection = (0, _utils2.findParentNodeOfType)(panel)(tr.selection);
|
|
945
947
|
var isTargetPanelEmpty = panelParentOverCurrentSelection && ((_panelParentOverCurre = panelParentOverCurrentSelection.node) === null || _panelParentOverCurre === void 0 ? void 0 : _panelParentOverCurre.content.size) === 2;
|
|
948
|
+
var sliceContainsCodeblockOrMedia = false;
|
|
949
|
+
var codeBlockAndMediaNodes = ['codeBlock', 'mediaSingle', 'mediaGroup'];
|
|
950
|
+
slice.content.forEach(function (child) {
|
|
951
|
+
if (codeBlockAndMediaNodes.includes(child.type.name)) {
|
|
952
|
+
sliceContainsCodeblockOrMedia = true;
|
|
953
|
+
}
|
|
954
|
+
});
|
|
955
|
+
var blockquoteNode = (0, _utils2.findParentNodeOfType)(blockquote)(tr.selection);
|
|
946
956
|
if (!isSliceContentTaskListNodes && (isSliceContentListNodes || isTargetPanelEmpty)) {
|
|
947
957
|
(0, _edgeCases.insertSliceForLists)({
|
|
948
958
|
tr: tr,
|
|
949
959
|
slice: slice,
|
|
950
960
|
schema: schema
|
|
951
961
|
});
|
|
962
|
+
} else if (
|
|
963
|
+
// If nesting media or codeblock in blockquote is not supported
|
|
964
|
+
// we want to insert slice after the blockquote.
|
|
965
|
+
(0, _main.isInsideBlockQuote)(state) && sliceContainsCodeblockOrMedia && !isNestingMediaOrCodeblockSupported && blockquoteNode) {
|
|
966
|
+
tr = (0, _utils2.safeInsert)(slice.content, blockquoteNode.start + blockquoteNode.node.nodeSize - 1)(tr);
|
|
952
967
|
} else if (noNeedForSafeInsert) {
|
|
953
968
|
var _firstChildOfSlice$ty2, _firstChildOfSlice$co, _firstChildOfSlice$co2;
|
|
954
969
|
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', 'mediaSingle'].includes(firstChildOfSlice === null || firstChildOfSlice === void 0 || (_firstChildOfSlice$co2 = firstChildOfSlice.content.firstChild) === null || _firstChildOfSlice$co2 === void 0 ? void 0 : _firstChildOfSlice$co2.type.name)) {
|
|
@@ -314,11 +314,11 @@ var handleMarkdownWithAnalytics = exports.handleMarkdownWithAnalytics = function
|
|
|
314
314
|
type: _analytics.PasteTypes.markdown
|
|
315
315
|
}))((0, _handlers.handleMarkdown)(slice, pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c3 = pluginInjectionApi.card) === null || _pluginInjectionApi$c3 === void 0 || (_pluginInjectionApi$c3 = _pluginInjectionApi$c3.actions) === null || _pluginInjectionApi$c3 === void 0 ? void 0 : _pluginInjectionApi$c3.queueCardsFromChangedTr));
|
|
316
316
|
};
|
|
317
|
-
var handleRichTextWithAnalytics = exports.handleRichTextWithAnalytics = function handleRichTextWithAnalytics(view, event, slice, pluginInjectionApi) {
|
|
317
|
+
var handleRichTextWithAnalytics = exports.handleRichTextWithAnalytics = function handleRichTextWithAnalytics(view, event, slice, pluginInjectionApi, isNestingMediaOrCodeblockSupported) {
|
|
318
318
|
var _pluginInjectionApi$a4, _pluginInjectionApi$c4;
|
|
319
319
|
return injectAnalyticsPayloadBeforeCommand(pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a4 = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a4 === void 0 ? void 0 : _pluginInjectionApi$a4.actions)(createPasteAnalyticsPayloadBySelection(event, slice, {
|
|
320
320
|
type: _analytics.PasteTypes.richText
|
|
321
|
-
}, pluginInjectionApi))((0, _handlers.handleRichText)(slice, pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c4 = pluginInjectionApi.card) === null || _pluginInjectionApi$c4 === void 0 || (_pluginInjectionApi$c4 = _pluginInjectionApi$c4.actions) === null || _pluginInjectionApi$c4 === void 0 ? void 0 : _pluginInjectionApi$c4.queueCardsFromChangedTr));
|
|
321
|
+
}, pluginInjectionApi))((0, _handlers.handleRichText)(slice, pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c4 = pluginInjectionApi.card) === null || _pluginInjectionApi$c4 === void 0 || (_pluginInjectionApi$c4 = _pluginInjectionApi$c4.actions) === null || _pluginInjectionApi$c4 === void 0 ? void 0 : _pluginInjectionApi$c4.queueCardsFromChangedTr, isNestingMediaOrCodeblockSupported));
|
|
322
322
|
};
|
|
323
323
|
var injectAnalyticsPayloadBeforeCommand = function injectAnalyticsPayloadBeforeCommand(editorAnalyticsAPI) {
|
|
324
324
|
return function (createPayloadByTransaction) {
|
|
@@ -173,8 +173,11 @@ function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, pl
|
|
|
173
173
|
/**
|
|
174
174
|
* We want to return false for external copied image to allow
|
|
175
175
|
* it to be uploaded by the client.
|
|
176
|
+
*
|
|
177
|
+
* Scenario where we are pasting an external image inside a block quote
|
|
178
|
+
* is skipped and handled in handleRichText
|
|
176
179
|
*/
|
|
177
|
-
if ((0, _util.htmlContainsSingleFile)(html)) {
|
|
180
|
+
if ((0, _util.htmlContainsSingleFile)(html) && !isInsideBlockQuote(view.state)) {
|
|
178
181
|
return true;
|
|
179
182
|
}
|
|
180
183
|
|
|
@@ -370,7 +373,7 @@ function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, pl
|
|
|
370
373
|
|
|
371
374
|
// finally, handle rich-text copy-paste
|
|
372
375
|
if (isRichText || isNestedMarkdownTable) {
|
|
373
|
-
var _pluginInjectionApi$c2, _pluginInjectionApi$e2, _pluginInjectionApi$f, _pluginInjectionApi$l;
|
|
376
|
+
var _pluginInjectionApi$c2, _pluginInjectionApi$e2, _pluginInjectionApi$f, _pluginInjectionApi$l, _pluginInjectionApi$f2;
|
|
374
377
|
// linkify the text where possible
|
|
375
378
|
slice = (0, _utils.linkifyContent)(state.schema)(slice);
|
|
376
379
|
if ((0, _analytics2.handlePasteLinkOnSelectedTextWithAnalytics)(editorAnalyticsAPI)(view, event, slice, _analytics.PasteTypes.richText)(state, dispatch)) {
|
|
@@ -447,7 +450,8 @@ function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, pl
|
|
|
447
450
|
if ((0, _analytics2.handlePasteNonNestableBlockNodesIntoListWithAnalytics)(editorAnalyticsAPI)(view, event, slice)(state, dispatch)) {
|
|
448
451
|
return true;
|
|
449
452
|
}
|
|
450
|
-
|
|
453
|
+
var isNestingMediaOrCodeblockSupported = (pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$f2 = pluginInjectionApi.featureFlags) === null || _pluginInjectionApi$f2 === void 0 || (_pluginInjectionApi$f2 = _pluginInjectionApi$f2.sharedState.currentState()) === null || _pluginInjectionApi$f2 === void 0 ? void 0 : _pluginInjectionApi$f2.nestMediaAndCodeblockInQuote) || (0, _platformFeatureFlags.fg)('editor_nest_media_and_codeblock_in_quotes_jira');
|
|
454
|
+
return (0, _analytics2.handleRichTextWithAnalytics)(view, event, slice, pluginInjectionApi, isNestingMediaOrCodeblockSupported)(state, dispatch);
|
|
451
455
|
}
|
|
452
456
|
return false;
|
|
453
457
|
},
|
|
@@ -16,7 +16,8 @@ var updateContentMoved = exports.updateContentMoved = function updateContentMove
|
|
|
16
16
|
var data = {
|
|
17
17
|
currentActions: [].concat((0, _toConsumableArray2.default)(contentMoved.currentActions), [nextAction]),
|
|
18
18
|
size: (nextState === null || nextState === void 0 ? void 0 : nextState.size) || contentMoved.size,
|
|
19
|
-
nodeName: nextState === null || nextState === void 0 ? void 0 : nextState.nodeName
|
|
19
|
+
nodeName: nextState === null || nextState === void 0 ? void 0 : nextState.nodeName,
|
|
20
|
+
nodeDepth: nextState === null || nextState === void 0 ? void 0 : nextState.nodeDepth
|
|
20
21
|
};
|
|
21
22
|
return {
|
|
22
23
|
type: _actions.MoveAnalyticPluginTypes.UpdateMovedAction,
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
3
4
|
Object.defineProperty(exports, "__esModule", {
|
|
4
5
|
value: true
|
|
5
6
|
});
|
|
6
7
|
exports.createPlugin = void 0;
|
|
8
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
7
9
|
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
8
10
|
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
11
|
+
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
9
12
|
var _commands = require("./commands");
|
|
10
13
|
var _pluginFactory = require("./plugin-factory");
|
|
11
14
|
var _pluginKey = require("./plugin-key");
|
|
12
15
|
var _types = require("./types");
|
|
13
16
|
var _utils = require("./utils");
|
|
17
|
+
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; }
|
|
18
|
+
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; }
|
|
14
19
|
// This plugin exists only in FullPage/FullWidth Editor and is used to register an event that tells us
|
|
15
20
|
// that a user cut and than pasted a node. This order of actions could be considered an alternative
|
|
16
21
|
// to new Drag and Drop functionality. The event (document moved) is not accurate, but should be enough to be
|
|
@@ -42,8 +47,12 @@ var createPlugin = exports.createPlugin = function createPlugin(dispatch, editor
|
|
|
42
47
|
var content = slice.content,
|
|
43
48
|
size = slice.size;
|
|
44
49
|
var nodeName = (_content$firstChild = content.firstChild) === null || _content$firstChild === void 0 ? void 0 : _content$firstChild.type.name;
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
|
|
51
|
+
// We should not account for pastes that go inside another node and create nested content as DnD can't do it when nested-dnd is disabled
|
|
52
|
+
if ((!nodeName || !(contentMoved !== null && contentMoved !== void 0 && contentMoved.nodeName) || !(0, _utils.isValidNodeName)(contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeName, nodeName) || size !== (contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.size) || !(0, _utils.isCursorSelectionAndInsideTopLevelNode)(state.selection)) && (0, _experiments.editorExperiment)('nested-dnd', false)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (!nodeName || !(contentMoved !== null && contentMoved !== void 0 && contentMoved.nodeName) || !(0, _utils.isCursorSelectionAtTopLevel)(state.selection) && (0, _experiments.editorExperiment)('nested-dnd', true)) {
|
|
47
56
|
return;
|
|
48
57
|
}
|
|
49
58
|
var tr = state.tr;
|
|
@@ -52,9 +61,12 @@ var createPlugin = exports.createPlugin = function createPlugin(dispatch, editor
|
|
|
52
61
|
actionSubject: _analytics.ACTION_SUBJECT.DOCUMENT,
|
|
53
62
|
actionSubjectId: _analytics.ACTION_SUBJECT_ID.NODE,
|
|
54
63
|
eventType: _analytics.EVENT_TYPE.TRACK,
|
|
55
|
-
attributes: {
|
|
56
|
-
nodeType: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeName
|
|
57
|
-
}
|
|
64
|
+
attributes: _objectSpread({
|
|
65
|
+
nodeType: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeName
|
|
66
|
+
}, (0, _experiments.editorExperiment)('nested-dnd', true) && {
|
|
67
|
+
nodeDepth: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeDepth,
|
|
68
|
+
destinationNodeDepth: (0, _utils.getParentNodeDepth)(state.selection)
|
|
69
|
+
})
|
|
58
70
|
})(tr);
|
|
59
71
|
|
|
60
72
|
// reset to default state
|
|
@@ -84,6 +96,7 @@ var createPlugin = exports.createPlugin = function createPlugin(dispatch, editor
|
|
|
84
96
|
resetState = true;
|
|
85
97
|
}
|
|
86
98
|
var nodeName = ((_content$firstChild2 = content.firstChild) === null || _content$firstChild2 === void 0 ? void 0 : _content$firstChild2.type.name) || '';
|
|
99
|
+
|
|
87
100
|
// Some nodes are not relevant as they are parts of nodes, not whole nodes (like tableCell, tableHeader instead of table node)
|
|
88
101
|
// Some nodes like lists, taskList(item), decisionList(item) requires tricky checks that we want to avoid doing.
|
|
89
102
|
// These nodes were added to excludedNodes array.
|
|
@@ -93,42 +106,50 @@ var createPlugin = exports.createPlugin = function createPlugin(dispatch, editor
|
|
|
93
106
|
var selection = state.selection;
|
|
94
107
|
// DnD can't drag part of text in a paragraph/heading. DnD will select the whole node with all the text inside.
|
|
95
108
|
// So we are only interested in cut slices that contain the entire node, not just a part of it.
|
|
96
|
-
if (!resetState && nodeName === 'paragraph' && !(0, _utils.isEntireTopLevelHeadingOrParagraphSelected)(selection, nodeName)) {
|
|
109
|
+
if (!resetState && nodeName === 'paragraph' && !(0, _utils.isEntireTopLevelHeadingOrParagraphSelected)(selection, nodeName) && (0, _experiments.editorExperiment)('nested-dnd', false)) {
|
|
97
110
|
resetState = true;
|
|
98
111
|
}
|
|
99
|
-
if (!resetState && nodeName === 'heading' && !(0, _utils.isEntireTopLevelHeadingOrParagraphSelected)(selection, nodeName)) {
|
|
112
|
+
if (!resetState && nodeName === 'heading' && !(0, _utils.isEntireTopLevelHeadingOrParagraphSelected)(selection, nodeName) && (0, _experiments.editorExperiment)('nested-dnd', false)) {
|
|
113
|
+
resetState = true;
|
|
114
|
+
}
|
|
115
|
+
if (!resetState && !(0, _utils.isEntireNestedParagraphOrHeadingSelected)(selection) && (0, _experiments.editorExperiment)('nested-dnd', true)) {
|
|
100
116
|
resetState = true;
|
|
101
117
|
}
|
|
102
118
|
|
|
103
119
|
// DnD can't drag just one paragraph (when blockquote contains multiple paragraphs) or just a part of a paragraph in the blockquote.
|
|
104
120
|
// DnD will select and drag the whole blockquote. So we need to register cut events that have the entire blockquote too.
|
|
105
|
-
if (!resetState && nodeName === 'blockquote' && !(0, _utils.isEntireTopLevelBlockquoteSelected)(state)) {
|
|
121
|
+
if (!resetState && nodeName === 'blockquote' && !(0, _utils.isEntireTopLevelBlockquoteSelected)(state) && (0, _experiments.editorExperiment)('nested-dnd', false)) {
|
|
106
122
|
resetState = true;
|
|
107
123
|
}
|
|
108
124
|
if (!resetState && (0, _utils.isInlineNode)(nodeName) && (0, _utils.isNestedInlineNode)(selection)) {
|
|
109
125
|
resetState = true;
|
|
110
126
|
}
|
|
111
|
-
if (!resetState && nodeName === 'table' && (0, _utils.isNestedTable)(selection)) {
|
|
127
|
+
if (!resetState && nodeName === 'table' && (0, _utils.isNestedTable)(selection) && (0, _experiments.editorExperiment)('nested-dnd', false)) {
|
|
128
|
+
resetState = true;
|
|
129
|
+
}
|
|
130
|
+
if (!resetState && (0, _utils.isNestedInTable)(state) && (0, _experiments.editorExperiment)('nested-dnd', true) && (0, _experiments.editorExperiment)('table-nested-dnd', false)) {
|
|
112
131
|
resetState = true;
|
|
113
132
|
}
|
|
114
133
|
var isBlockNode = (0, _utils.isBlockNodeWithoutTable)(nodeName);
|
|
115
|
-
if (!resetState && (0, _utils.isNodeSelection)(selection) && isBlockNode && selection.$anchor.node().type.name !== 'doc' // checks that the block node is not a topLevel node
|
|
134
|
+
if (!resetState && (0, _utils.isNodeSelection)(selection) && isBlockNode && selection.$anchor.node().type.name !== 'doc' && (0, _experiments.editorExperiment)('nested-dnd', false) // checks that the block node is not a topLevel node
|
|
116
135
|
) {
|
|
117
136
|
resetState = true;
|
|
118
137
|
}
|
|
119
138
|
|
|
120
139
|
// Some blockNodes can have text inside of them cut, in that case TextSelection occurs, we don't need to track
|
|
121
140
|
// these cut events.
|
|
122
|
-
if (!resetState && (0, _utils.isTextSelection)(selection) && isBlockNode) {
|
|
141
|
+
if (!resetState && (0, _utils.isTextSelection)(selection) && isBlockNode && (0, _experiments.editorExperiment)('nested-dnd', false)) {
|
|
123
142
|
resetState = true;
|
|
124
143
|
}
|
|
125
144
|
if (resetState) {
|
|
126
145
|
(0, _commands.resetContentMoved)()(state, dispatch);
|
|
127
146
|
} else {
|
|
128
|
-
(0, _commands.updateContentMoved)({
|
|
147
|
+
(0, _commands.updateContentMoved)(_objectSpread({
|
|
129
148
|
size: size,
|
|
130
149
|
nodeName: nodeName
|
|
131
|
-
}, '
|
|
150
|
+
}, (0, _experiments.editorExperiment)('nested-dnd', true) && {
|
|
151
|
+
nodeDepth: (0, _utils.getParentNodeDepth)(selection)
|
|
152
|
+
}), 'contentCut')(state, dispatch);
|
|
132
153
|
}
|
|
133
154
|
isCutEvent = false;
|
|
134
155
|
return slice;
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
3
4
|
Object.defineProperty(exports, "__esModule", {
|
|
4
5
|
value: true
|
|
5
6
|
});
|
|
6
|
-
exports.isValidNodeName = exports.isTextSelection = exports.isNodeSelection = exports.isNestedTable = exports.isNestedInlineNode = exports.isInlineNode = exports.isExcludedNode = exports.isEntireTopLevelHeadingOrParagraphSelected = exports.isEntireTopLevelBlockquoteSelected = exports.isCursorSelectionAndInsideTopLevelNode = exports.isBlockNodeWithoutTable = void 0;
|
|
7
|
+
exports.isValidNodeName = exports.isTextSelection = exports.isNodeSelection = exports.isNestedTable = exports.isNestedInlineNode = exports.isNestedInTable = exports.isInlineNode = exports.isExcludedNode = exports.isEntireTopLevelHeadingOrParagraphSelected = exports.isEntireTopLevelBlockquoteSelected = exports.isEntireNestedParagraphOrHeadingSelected = exports.isCursorSelectionAtTopLevel = exports.isCursorSelectionAndInsideTopLevelNode = exports.isBlockNodeWithoutTable = exports.getParentNodeDepth = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
7
9
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
8
10
|
var _utils = require("@atlaskit/editor-prosemirror/utils");
|
|
9
|
-
var
|
|
11
|
+
var _cellSelection = require("@atlaskit/editor-tables/cell-selection");
|
|
12
|
+
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
13
|
+
var excludedNodes = ['caption', 'layoutColumn', 'listItem', 'tableHeader', 'tableCell', 'tableRow', 'text', 'placeholder', 'unsupportedBlock', 'unsupportedInline', 'hardBreak', 'confluenceUnsupportedBlock', 'confluenceUnsupportedInline', 'taskItem', 'decisionItem'].concat((0, _toConsumableArray2.default)((0, _experiments.editorExperiment)('nested-dnd', false) ? ['bulletList', 'orderedList', 'taskList', 'decisionList', 'nestedExpand', 'media'] : []));
|
|
10
14
|
var isExcludedNode = exports.isExcludedNode = function isExcludedNode(nodeName) {
|
|
11
15
|
return excludedNodes.includes(nodeName);
|
|
12
16
|
};
|
|
@@ -19,6 +23,15 @@ var isCursorSelectionAndInsideTopLevelNode = exports.isCursorSelectionAndInsideT
|
|
|
19
23
|
}
|
|
20
24
|
return true;
|
|
21
25
|
};
|
|
26
|
+
var isCursorSelectionAtTopLevel = exports.isCursorSelectionAtTopLevel = function isCursorSelectionAtTopLevel(selection) {
|
|
27
|
+
var from = selection.from,
|
|
28
|
+
to = selection.to,
|
|
29
|
+
$from = selection.$from;
|
|
30
|
+
if (from !== to) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return $from.parentOffset === 0;
|
|
34
|
+
};
|
|
22
35
|
var inlineNodes = ['emoji', 'date', 'status', 'mention', 'mediaInline', 'inlineCard', 'inlineExtension'];
|
|
23
36
|
var isInlineNode = exports.isInlineNode = function isInlineNode(nodeName) {
|
|
24
37
|
return inlineNodes.includes(nodeName);
|
|
@@ -52,6 +65,28 @@ var isNestedTable = exports.isNestedTable = function isNestedTable(selection) {
|
|
|
52
65
|
var parentNode = selection.$anchor.node(1);
|
|
53
66
|
return parentNode && parentNodes.includes(parentNode.type.name);
|
|
54
67
|
};
|
|
68
|
+
var isNestedInTable = exports.isNestedInTable = function isNestedInTable(state) {
|
|
69
|
+
var schema = state.schema,
|
|
70
|
+
selection = state.selection;
|
|
71
|
+
if (selection instanceof _cellSelection.CellSelection) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
var table = schema.nodes.table;
|
|
75
|
+
var tableNode = (0, _utils.findParentNodeOfTypeClosestToPos)(selection.$from, table);
|
|
76
|
+
if (!tableNode) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
return true;
|
|
80
|
+
};
|
|
81
|
+
var getParentNodeDepth = exports.getParentNodeDepth = function getParentNodeDepth(selection) {
|
|
82
|
+
var parentNode = (0, _utils.findParentNodeClosestToPos)(selection.$from, function () {
|
|
83
|
+
return true;
|
|
84
|
+
});
|
|
85
|
+
if (!parentNode) {
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
return parentNode.node.type.name === 'heading' || parentNode.node.type.name === 'paragraph' ? parentNode.depth - 1 : parentNode.depth;
|
|
89
|
+
};
|
|
55
90
|
var getPastedNameOfInlineNode = function getPastedNameOfInlineNode(nodeName) {
|
|
56
91
|
if (inlineNodes.includes(nodeName)) {
|
|
57
92
|
return 'paragraph';
|
|
@@ -117,4 +152,9 @@ var isEntireTopLevelBlockquoteSelected = exports.isEntireTopLevelBlockquoteSelec
|
|
|
117
152
|
}
|
|
118
153
|
});
|
|
119
154
|
return selectedNodesCount === blockquoteNode.node.childCount;
|
|
155
|
+
};
|
|
156
|
+
var isEntireNestedParagraphOrHeadingSelected = exports.isEntireNestedParagraphOrHeadingSelected = function isEntireNestedParagraphOrHeadingSelected(selection) {
|
|
157
|
+
var $from = selection.$from,
|
|
158
|
+
$to = selection.$to;
|
|
159
|
+
return $from.textOffset === 0 && $to.textOffset === 0;
|
|
120
160
|
};
|
package/dist/es2019/handlers.js
CHANGED
|
@@ -14,6 +14,7 @@ import { replaceSelectedTable } from '@atlaskit/editor-tables/utils';
|
|
|
14
14
|
import { startTrackingPastedMacroPositions, stopTrackingPastedMacroPositions } from './commands';
|
|
15
15
|
import { insertSliceForLists, insertSliceForTaskInsideList, insertSliceInsideBlockquote } from './edge-cases';
|
|
16
16
|
import { insertSliceInsideOfPanelNodeSelected } from './edge-cases/lists';
|
|
17
|
+
import { isInsideBlockQuote } from './pm-plugins/main';
|
|
17
18
|
import { getPluginState as getPastePluginState } from './pm-plugins/plugin-factory';
|
|
18
19
|
import { addReplaceSelectedTableAnalytics, applyTextMarksToSlice, hasOnlyNodesOfType, isEmptyNode, isSelectionInsidePanel } from './util';
|
|
19
20
|
const insideExpand = state => {
|
|
@@ -880,10 +881,11 @@ export function flattenNestedListInSlice(slice) {
|
|
|
880
881
|
const contentWithFlattenedList = slice.content.replaceChild(0, listToFlatten.type.createChecked(listToFlatten.attrs, leafListItems));
|
|
881
882
|
return new Slice(contentWithFlattenedList, slice.openEnd, slice.openEnd);
|
|
882
883
|
}
|
|
883
|
-
export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
884
|
+
export function handleRichText(slice, queueCardsFromChangedTr, isNestingMediaOrCodeblockSupported) {
|
|
884
885
|
return (state, dispatch) => {
|
|
885
886
|
var _slice$content, _slice$content2, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
886
887
|
const {
|
|
888
|
+
blockquote,
|
|
887
889
|
codeBlock,
|
|
888
890
|
heading,
|
|
889
891
|
paragraph,
|
|
@@ -921,12 +923,25 @@ export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
921
923
|
const noNeedForSafeInsert = selection.$to.node().type.validContent(slice.content) || textNodes.includes(selection.$to.node().type) && selectionParent.type.validContent(slice.content);
|
|
922
924
|
let panelParentOverCurrentSelection = findParentNodeOfType(panel)(tr.selection);
|
|
923
925
|
const isTargetPanelEmpty = panelParentOverCurrentSelection && ((_panelParentOverCurre = panelParentOverCurrentSelection.node) === null || _panelParentOverCurre === void 0 ? void 0 : _panelParentOverCurre.content.size) === 2;
|
|
926
|
+
let sliceContainsCodeblockOrMedia = false;
|
|
927
|
+
const codeBlockAndMediaNodes = ['codeBlock', 'mediaSingle', 'mediaGroup'];
|
|
928
|
+
slice.content.forEach(child => {
|
|
929
|
+
if (codeBlockAndMediaNodes.includes(child.type.name)) {
|
|
930
|
+
sliceContainsCodeblockOrMedia = true;
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
const blockquoteNode = findParentNodeOfType(blockquote)(tr.selection);
|
|
924
934
|
if (!isSliceContentTaskListNodes && (isSliceContentListNodes || isTargetPanelEmpty)) {
|
|
925
935
|
insertSliceForLists({
|
|
926
936
|
tr,
|
|
927
937
|
slice,
|
|
928
938
|
schema
|
|
929
939
|
});
|
|
940
|
+
} else if (
|
|
941
|
+
// If nesting media or codeblock in blockquote is not supported
|
|
942
|
+
// we want to insert slice after the blockquote.
|
|
943
|
+
isInsideBlockQuote(state) && sliceContainsCodeblockOrMedia && !isNestingMediaOrCodeblockSupported && blockquoteNode) {
|
|
944
|
+
tr = safeInsert(slice.content, blockquoteNode.start + blockquoteNode.node.nodeSize - 1)(tr);
|
|
930
945
|
} else if (noNeedForSafeInsert) {
|
|
931
946
|
var _firstChildOfSlice$ty2, _firstChildOfSlice$co, _firstChildOfSlice$co2;
|
|
932
947
|
if ((firstChildOfSlice === null || firstChildOfSlice === void 0 ? 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', 'mediaSingle'].includes(firstChildOfSlice === null || firstChildOfSlice === void 0 ? void 0 : (_firstChildOfSlice$co2 = firstChildOfSlice.content.firstChild) === null || _firstChildOfSlice$co2 === void 0 ? void 0 : _firstChildOfSlice$co2.type.name)) {
|
|
@@ -291,11 +291,11 @@ export const handleMarkdownWithAnalytics = (view, event, slice, pluginInjectionA
|
|
|
291
291
|
type: PasteTypes.markdown
|
|
292
292
|
}))(handleMarkdown(slice, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c5 = pluginInjectionApi.card) === null || _pluginInjectionApi$c5 === void 0 ? void 0 : (_pluginInjectionApi$c6 = _pluginInjectionApi$c5.actions) === null || _pluginInjectionApi$c6 === void 0 ? void 0 : _pluginInjectionApi$c6.queueCardsFromChangedTr));
|
|
293
293
|
};
|
|
294
|
-
export const handleRichTextWithAnalytics = (view, event, slice, pluginInjectionApi) => {
|
|
294
|
+
export const handleRichTextWithAnalytics = (view, event, slice, pluginInjectionApi, isNestingMediaOrCodeblockSupported) => {
|
|
295
295
|
var _pluginInjectionApi$a4, _pluginInjectionApi$c7, _pluginInjectionApi$c8;
|
|
296
296
|
return injectAnalyticsPayloadBeforeCommand(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$a4 = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a4 === void 0 ? void 0 : _pluginInjectionApi$a4.actions)(createPasteAnalyticsPayloadBySelection(event, slice, {
|
|
297
297
|
type: PasteTypes.richText
|
|
298
|
-
}, pluginInjectionApi))(handleRichText(slice, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c7 = pluginInjectionApi.card) === null || _pluginInjectionApi$c7 === void 0 ? void 0 : (_pluginInjectionApi$c8 = _pluginInjectionApi$c7.actions) === null || _pluginInjectionApi$c8 === void 0 ? void 0 : _pluginInjectionApi$c8.queueCardsFromChangedTr));
|
|
298
|
+
}, pluginInjectionApi))(handleRichText(slice, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c7 = pluginInjectionApi.card) === null || _pluginInjectionApi$c7 === void 0 ? void 0 : (_pluginInjectionApi$c8 = _pluginInjectionApi$c7.actions) === null || _pluginInjectionApi$c8 === void 0 ? void 0 : _pluginInjectionApi$c8.queueCardsFromChangedTr, isNestingMediaOrCodeblockSupported));
|
|
299
299
|
};
|
|
300
300
|
const injectAnalyticsPayloadBeforeCommand = editorAnalyticsAPI => createPayloadByTransaction => {
|
|
301
301
|
return mainCommand => {
|
|
@@ -137,8 +137,11 @@ export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFl
|
|
|
137
137
|
/**
|
|
138
138
|
* We want to return false for external copied image to allow
|
|
139
139
|
* it to be uploaded by the client.
|
|
140
|
+
*
|
|
141
|
+
* Scenario where we are pasting an external image inside a block quote
|
|
142
|
+
* is skipped and handled in handleRichText
|
|
140
143
|
*/
|
|
141
|
-
if (htmlContainsSingleFile(html)) {
|
|
144
|
+
if (htmlContainsSingleFile(html) && !isInsideBlockQuote(view.state)) {
|
|
142
145
|
return true;
|
|
143
146
|
}
|
|
144
147
|
|
|
@@ -341,7 +344,7 @@ export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFl
|
|
|
341
344
|
|
|
342
345
|
// finally, handle rich-text copy-paste
|
|
343
346
|
if (isRichText || isNestedMarkdownTable) {
|
|
344
|
-
var _pluginInjectionApi$c3, _pluginInjectionApi$c4, _pluginInjectionApi$e3, _pluginInjectionApi$e4, _pluginInjectionApi$f, _pluginInjectionApi$f2, _pluginInjectionApi$l;
|
|
347
|
+
var _pluginInjectionApi$c3, _pluginInjectionApi$c4, _pluginInjectionApi$e3, _pluginInjectionApi$e4, _pluginInjectionApi$f, _pluginInjectionApi$f2, _pluginInjectionApi$l, _pluginInjectionApi$f3, _pluginInjectionApi$f4;
|
|
345
348
|
// linkify the text where possible
|
|
346
349
|
slice = linkifyContent(state.schema)(slice);
|
|
347
350
|
if (handlePasteLinkOnSelectedTextWithAnalytics(editorAnalyticsAPI)(view, event, slice, PasteTypes.richText)(state, dispatch)) {
|
|
@@ -416,7 +419,8 @@ export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFl
|
|
|
416
419
|
if (handlePasteNonNestableBlockNodesIntoListWithAnalytics(editorAnalyticsAPI)(view, event, slice)(state, dispatch)) {
|
|
417
420
|
return true;
|
|
418
421
|
}
|
|
419
|
-
|
|
422
|
+
const isNestingMediaOrCodeblockSupported = (pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$f3 = pluginInjectionApi.featureFlags) === null || _pluginInjectionApi$f3 === void 0 ? void 0 : (_pluginInjectionApi$f4 = _pluginInjectionApi$f3.sharedState.currentState()) === null || _pluginInjectionApi$f4 === void 0 ? void 0 : _pluginInjectionApi$f4.nestMediaAndCodeblockInQuote) || fg('editor_nest_media_and_codeblock_in_quotes_jira');
|
|
423
|
+
return handleRichTextWithAnalytics(view, event, slice, pluginInjectionApi, isNestingMediaOrCodeblockSupported)(state, dispatch);
|
|
420
424
|
}
|
|
421
425
|
return false;
|
|
422
426
|
},
|
|
@@ -8,7 +8,8 @@ export const updateContentMoved = (nextState, nextAction) => createCommand(state
|
|
|
8
8
|
const data = {
|
|
9
9
|
currentActions: [...contentMoved.currentActions, nextAction],
|
|
10
10
|
size: (nextState === null || nextState === void 0 ? void 0 : nextState.size) || contentMoved.size,
|
|
11
|
-
nodeName: nextState === null || nextState === void 0 ? void 0 : nextState.nodeName
|
|
11
|
+
nodeName: nextState === null || nextState === void 0 ? void 0 : nextState.nodeName,
|
|
12
|
+
nodeDepth: nextState === null || nextState === void 0 ? void 0 : nextState.nodeDepth
|
|
12
13
|
};
|
|
13
14
|
return {
|
|
14
15
|
type: MoveAnalyticPluginTypes.UpdateMovedAction,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
2
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
|
+
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
3
4
|
import { resetContentMoved, resetContentMovedTransform, updateContentMoved } from './commands';
|
|
4
5
|
import { createPluginState, getPluginState } from './plugin-factory';
|
|
5
6
|
import { pluginKey } from './plugin-key';
|
|
6
7
|
import { defaultState } from './types';
|
|
7
|
-
import { isBlockNodeWithoutTable, isCursorSelectionAndInsideTopLevelNode, isEntireTopLevelBlockquoteSelected, isEntireTopLevelHeadingOrParagraphSelected, isExcludedNode, isInlineNode, isNestedInlineNode, isNestedTable, isNodeSelection, isTextSelection, isValidNodeName } from './utils';
|
|
8
|
+
import { getParentNodeDepth, isBlockNodeWithoutTable, isCursorSelectionAndInsideTopLevelNode, isCursorSelectionAtTopLevel, isEntireNestedParagraphOrHeadingSelected, isEntireTopLevelBlockquoteSelected, isEntireTopLevelHeadingOrParagraphSelected, isExcludedNode, isInlineNode, isNestedInlineNode, isNestedInTable, isNestedTable, isNodeSelection, isTextSelection, isValidNodeName } from './utils';
|
|
8
9
|
|
|
9
10
|
// This plugin exists only in FullPage/FullWidth Editor and is used to register an event that tells us
|
|
10
11
|
// that a user cut and than pasted a node. This order of actions could be considered an alternative
|
|
@@ -41,8 +42,12 @@ export const createPlugin = (dispatch, editorAnalyticsAPI) => {
|
|
|
41
42
|
size
|
|
42
43
|
} = slice;
|
|
43
44
|
const nodeName = (_content$firstChild = content.firstChild) === null || _content$firstChild === void 0 ? void 0 : _content$firstChild.type.name;
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
|
|
46
|
+
// We should not account for pastes that go inside another node and create nested content as DnD can't do it when nested-dnd is disabled
|
|
47
|
+
if ((!nodeName || !(contentMoved !== null && contentMoved !== void 0 && contentMoved.nodeName) || !isValidNodeName(contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeName, nodeName) || size !== (contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.size) || !isCursorSelectionAndInsideTopLevelNode(state.selection)) && editorExperiment('nested-dnd', false)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (!nodeName || !(contentMoved !== null && contentMoved !== void 0 && contentMoved.nodeName) || !isCursorSelectionAtTopLevel(state.selection) && editorExperiment('nested-dnd', true)) {
|
|
46
51
|
return;
|
|
47
52
|
}
|
|
48
53
|
const {
|
|
@@ -54,7 +59,12 @@ export const createPlugin = (dispatch, editorAnalyticsAPI) => {
|
|
|
54
59
|
actionSubjectId: ACTION_SUBJECT_ID.NODE,
|
|
55
60
|
eventType: EVENT_TYPE.TRACK,
|
|
56
61
|
attributes: {
|
|
57
|
-
nodeType: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeName
|
|
62
|
+
nodeType: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeName,
|
|
63
|
+
...(editorExperiment('nested-dnd', true) && {
|
|
64
|
+
nodeDepth: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeDepth,
|
|
65
|
+
destinationNodeDepth: getParentNodeDepth(state.selection)
|
|
66
|
+
})
|
|
67
|
+
// keep nodeName from copied slice
|
|
58
68
|
}
|
|
59
69
|
})(tr);
|
|
60
70
|
|
|
@@ -88,6 +98,7 @@ export const createPlugin = (dispatch, editorAnalyticsAPI) => {
|
|
|
88
98
|
resetState = true;
|
|
89
99
|
}
|
|
90
100
|
const nodeName = ((_content$firstChild2 = content.firstChild) === null || _content$firstChild2 === void 0 ? void 0 : _content$firstChild2.type.name) || '';
|
|
101
|
+
|
|
91
102
|
// Some nodes are not relevant as they are parts of nodes, not whole nodes (like tableCell, tableHeader instead of table node)
|
|
92
103
|
// Some nodes like lists, taskList(item), decisionList(item) requires tricky checks that we want to avoid doing.
|
|
93
104
|
// These nodes were added to excludedNodes array.
|
|
@@ -99,33 +110,39 @@ export const createPlugin = (dispatch, editorAnalyticsAPI) => {
|
|
|
99
110
|
} = state;
|
|
100
111
|
// DnD can't drag part of text in a paragraph/heading. DnD will select the whole node with all the text inside.
|
|
101
112
|
// So we are only interested in cut slices that contain the entire node, not just a part of it.
|
|
102
|
-
if (!resetState && nodeName === 'paragraph' && !isEntireTopLevelHeadingOrParagraphSelected(selection, nodeName)) {
|
|
113
|
+
if (!resetState && nodeName === 'paragraph' && !isEntireTopLevelHeadingOrParagraphSelected(selection, nodeName) && editorExperiment('nested-dnd', false)) {
|
|
103
114
|
resetState = true;
|
|
104
115
|
}
|
|
105
|
-
if (!resetState && nodeName === 'heading' && !isEntireTopLevelHeadingOrParagraphSelected(selection, nodeName)) {
|
|
116
|
+
if (!resetState && nodeName === 'heading' && !isEntireTopLevelHeadingOrParagraphSelected(selection, nodeName) && editorExperiment('nested-dnd', false)) {
|
|
117
|
+
resetState = true;
|
|
118
|
+
}
|
|
119
|
+
if (!resetState && !isEntireNestedParagraphOrHeadingSelected(selection) && editorExperiment('nested-dnd', true)) {
|
|
106
120
|
resetState = true;
|
|
107
121
|
}
|
|
108
122
|
|
|
109
123
|
// DnD can't drag just one paragraph (when blockquote contains multiple paragraphs) or just a part of a paragraph in the blockquote.
|
|
110
124
|
// DnD will select and drag the whole blockquote. So we need to register cut events that have the entire blockquote too.
|
|
111
|
-
if (!resetState && nodeName === 'blockquote' && !isEntireTopLevelBlockquoteSelected(state)) {
|
|
125
|
+
if (!resetState && nodeName === 'blockquote' && !isEntireTopLevelBlockquoteSelected(state) && editorExperiment('nested-dnd', false)) {
|
|
112
126
|
resetState = true;
|
|
113
127
|
}
|
|
114
128
|
if (!resetState && isInlineNode(nodeName) && isNestedInlineNode(selection)) {
|
|
115
129
|
resetState = true;
|
|
116
130
|
}
|
|
117
|
-
if (!resetState && nodeName === 'table' && isNestedTable(selection)) {
|
|
131
|
+
if (!resetState && nodeName === 'table' && isNestedTable(selection) && editorExperiment('nested-dnd', false)) {
|
|
132
|
+
resetState = true;
|
|
133
|
+
}
|
|
134
|
+
if (!resetState && isNestedInTable(state) && editorExperiment('nested-dnd', true) && editorExperiment('table-nested-dnd', false)) {
|
|
118
135
|
resetState = true;
|
|
119
136
|
}
|
|
120
137
|
const isBlockNode = isBlockNodeWithoutTable(nodeName);
|
|
121
|
-
if (!resetState && isNodeSelection(selection) && isBlockNode && selection.$anchor.node().type.name !== 'doc' // checks that the block node is not a topLevel node
|
|
138
|
+
if (!resetState && isNodeSelection(selection) && isBlockNode && selection.$anchor.node().type.name !== 'doc' && editorExperiment('nested-dnd', false) // checks that the block node is not a topLevel node
|
|
122
139
|
) {
|
|
123
140
|
resetState = true;
|
|
124
141
|
}
|
|
125
142
|
|
|
126
143
|
// Some blockNodes can have text inside of them cut, in that case TextSelection occurs, we don't need to track
|
|
127
144
|
// these cut events.
|
|
128
|
-
if (!resetState && isTextSelection(selection) && isBlockNode) {
|
|
145
|
+
if (!resetState && isTextSelection(selection) && isBlockNode && editorExperiment('nested-dnd', false)) {
|
|
129
146
|
resetState = true;
|
|
130
147
|
}
|
|
131
148
|
if (resetState) {
|
|
@@ -133,7 +150,10 @@ export const createPlugin = (dispatch, editorAnalyticsAPI) => {
|
|
|
133
150
|
} else {
|
|
134
151
|
updateContentMoved({
|
|
135
152
|
size: size,
|
|
136
|
-
nodeName: nodeName
|
|
153
|
+
nodeName: nodeName,
|
|
154
|
+
...(editorExperiment('nested-dnd', true) && {
|
|
155
|
+
nodeDepth: getParentNodeDepth(selection)
|
|
156
|
+
})
|
|
137
157
|
}, 'contentCut')(state, dispatch);
|
|
138
158
|
}
|
|
139
159
|
isCutEvent = false;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
-
import { findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
|
|
3
|
-
|
|
2
|
+
import { findParentNodeClosestToPos, findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
|
|
3
|
+
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
4
|
+
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
5
|
+
const excludedNodes = ['caption', 'layoutColumn', 'listItem', 'tableHeader', 'tableCell', 'tableRow', 'text', 'placeholder', 'unsupportedBlock', 'unsupportedInline', 'hardBreak', 'confluenceUnsupportedBlock', 'confluenceUnsupportedInline', 'taskItem', 'decisionItem', ...(editorExperiment('nested-dnd', false) ? ['bulletList', 'orderedList', 'taskList', 'decisionList', 'nestedExpand', 'media'] : [])];
|
|
4
6
|
export const isExcludedNode = nodeName => excludedNodes.includes(nodeName);
|
|
5
7
|
export const isCursorSelectionAndInsideTopLevelNode = selection => {
|
|
6
8
|
const {
|
|
@@ -13,6 +15,17 @@ export const isCursorSelectionAndInsideTopLevelNode = selection => {
|
|
|
13
15
|
}
|
|
14
16
|
return true;
|
|
15
17
|
};
|
|
18
|
+
export const isCursorSelectionAtTopLevel = selection => {
|
|
19
|
+
const {
|
|
20
|
+
from,
|
|
21
|
+
to,
|
|
22
|
+
$from
|
|
23
|
+
} = selection;
|
|
24
|
+
if (from !== to) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return $from.parentOffset === 0;
|
|
28
|
+
};
|
|
16
29
|
const inlineNodes = ['emoji', 'date', 'status', 'mention', 'mediaInline', 'inlineCard', 'inlineExtension'];
|
|
17
30
|
export const isInlineNode = nodeName => {
|
|
18
31
|
return inlineNodes.includes(nodeName);
|
|
@@ -46,6 +59,30 @@ export const isNestedTable = selection => {
|
|
|
46
59
|
const parentNode = selection.$anchor.node(1);
|
|
47
60
|
return parentNode && parentNodes.includes(parentNode.type.name);
|
|
48
61
|
};
|
|
62
|
+
export const isNestedInTable = state => {
|
|
63
|
+
const {
|
|
64
|
+
schema,
|
|
65
|
+
selection
|
|
66
|
+
} = state;
|
|
67
|
+
if (selection instanceof CellSelection) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
const {
|
|
71
|
+
table
|
|
72
|
+
} = schema.nodes;
|
|
73
|
+
const tableNode = findParentNodeOfTypeClosestToPos(selection.$from, table);
|
|
74
|
+
if (!tableNode) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
};
|
|
79
|
+
export const getParentNodeDepth = selection => {
|
|
80
|
+
const parentNode = findParentNodeClosestToPos(selection.$from, () => true);
|
|
81
|
+
if (!parentNode) {
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
84
|
+
return parentNode.node.type.name === 'heading' || parentNode.node.type.name === 'paragraph' ? parentNode.depth - 1 : parentNode.depth;
|
|
85
|
+
};
|
|
49
86
|
const getPastedNameOfInlineNode = nodeName => {
|
|
50
87
|
if (inlineNodes.includes(nodeName)) {
|
|
51
88
|
return 'paragraph';
|
|
@@ -121,4 +158,11 @@ export const isEntireTopLevelBlockquoteSelected = state => {
|
|
|
121
158
|
}
|
|
122
159
|
});
|
|
123
160
|
return selectedNodesCount === blockquoteNode.node.childCount;
|
|
161
|
+
};
|
|
162
|
+
export const isEntireNestedParagraphOrHeadingSelected = selection => {
|
|
163
|
+
const {
|
|
164
|
+
$from,
|
|
165
|
+
$to
|
|
166
|
+
} = selection;
|
|
167
|
+
return $from.textOffset === 0 && $to.textOffset === 0;
|
|
124
168
|
};
|
package/dist/esm/handlers.js
CHANGED
|
@@ -22,6 +22,7 @@ import { replaceSelectedTable } from '@atlaskit/editor-tables/utils';
|
|
|
22
22
|
import { startTrackingPastedMacroPositions, stopTrackingPastedMacroPositions } from './commands';
|
|
23
23
|
import { insertSliceForLists, insertSliceForTaskInsideList, insertSliceInsideBlockquote } from './edge-cases';
|
|
24
24
|
import { insertSliceInsideOfPanelNodeSelected } from './edge-cases/lists';
|
|
25
|
+
import { isInsideBlockQuote } from './pm-plugins/main';
|
|
25
26
|
import { getPluginState as getPastePluginState } from './pm-plugins/plugin-factory';
|
|
26
27
|
import { addReplaceSelectedTableAnalytics, applyTextMarksToSlice, hasOnlyNodesOfType, isEmptyNode, isSelectionInsidePanel } from './util';
|
|
27
28
|
var insideExpand = function insideExpand(state) {
|
|
@@ -881,10 +882,11 @@ export function flattenNestedListInSlice(slice) {
|
|
|
881
882
|
var contentWithFlattenedList = slice.content.replaceChild(0, listToFlatten.type.createChecked(listToFlatten.attrs, leafListItems));
|
|
882
883
|
return new Slice(contentWithFlattenedList, slice.openEnd, slice.openEnd);
|
|
883
884
|
}
|
|
884
|
-
export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
885
|
+
export function handleRichText(slice, queueCardsFromChangedTr, isNestingMediaOrCodeblockSupported) {
|
|
885
886
|
return function (state, dispatch) {
|
|
886
887
|
var _slice$content, _slice$content2, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
887
888
|
var _state$schema$nodes4 = state.schema.nodes,
|
|
889
|
+
blockquote = _state$schema$nodes4.blockquote,
|
|
888
890
|
codeBlock = _state$schema$nodes4.codeBlock,
|
|
889
891
|
heading = _state$schema$nodes4.heading,
|
|
890
892
|
paragraph = _state$schema$nodes4.paragraph,
|
|
@@ -919,12 +921,25 @@ export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
919
921
|
var noNeedForSafeInsert = selection.$to.node().type.validContent(slice.content) || textNodes.includes(selection.$to.node().type) && selectionParent.type.validContent(slice.content);
|
|
920
922
|
var panelParentOverCurrentSelection = findParentNodeOfType(panel)(tr.selection);
|
|
921
923
|
var isTargetPanelEmpty = panelParentOverCurrentSelection && ((_panelParentOverCurre = panelParentOverCurrentSelection.node) === null || _panelParentOverCurre === void 0 ? void 0 : _panelParentOverCurre.content.size) === 2;
|
|
924
|
+
var sliceContainsCodeblockOrMedia = false;
|
|
925
|
+
var codeBlockAndMediaNodes = ['codeBlock', 'mediaSingle', 'mediaGroup'];
|
|
926
|
+
slice.content.forEach(function (child) {
|
|
927
|
+
if (codeBlockAndMediaNodes.includes(child.type.name)) {
|
|
928
|
+
sliceContainsCodeblockOrMedia = true;
|
|
929
|
+
}
|
|
930
|
+
});
|
|
931
|
+
var blockquoteNode = findParentNodeOfType(blockquote)(tr.selection);
|
|
922
932
|
if (!isSliceContentTaskListNodes && (isSliceContentListNodes || isTargetPanelEmpty)) {
|
|
923
933
|
insertSliceForLists({
|
|
924
934
|
tr: tr,
|
|
925
935
|
slice: slice,
|
|
926
936
|
schema: schema
|
|
927
937
|
});
|
|
938
|
+
} else if (
|
|
939
|
+
// If nesting media or codeblock in blockquote is not supported
|
|
940
|
+
// we want to insert slice after the blockquote.
|
|
941
|
+
isInsideBlockQuote(state) && sliceContainsCodeblockOrMedia && !isNestingMediaOrCodeblockSupported && blockquoteNode) {
|
|
942
|
+
tr = safeInsert(slice.content, blockquoteNode.start + blockquoteNode.node.nodeSize - 1)(tr);
|
|
928
943
|
} else if (noNeedForSafeInsert) {
|
|
929
944
|
var _firstChildOfSlice$ty2, _firstChildOfSlice$co, _firstChildOfSlice$co2;
|
|
930
945
|
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', 'mediaSingle'].includes(firstChildOfSlice === null || firstChildOfSlice === void 0 || (_firstChildOfSlice$co2 = firstChildOfSlice.content.firstChild) === null || _firstChildOfSlice$co2 === void 0 ? void 0 : _firstChildOfSlice$co2.type.name)) {
|
|
@@ -302,11 +302,11 @@ export var handleMarkdownWithAnalytics = function handleMarkdownWithAnalytics(vi
|
|
|
302
302
|
type: PasteTypes.markdown
|
|
303
303
|
}))(handleMarkdown(slice, pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c3 = pluginInjectionApi.card) === null || _pluginInjectionApi$c3 === void 0 || (_pluginInjectionApi$c3 = _pluginInjectionApi$c3.actions) === null || _pluginInjectionApi$c3 === void 0 ? void 0 : _pluginInjectionApi$c3.queueCardsFromChangedTr));
|
|
304
304
|
};
|
|
305
|
-
export var handleRichTextWithAnalytics = function handleRichTextWithAnalytics(view, event, slice, pluginInjectionApi) {
|
|
305
|
+
export var handleRichTextWithAnalytics = function handleRichTextWithAnalytics(view, event, slice, pluginInjectionApi, isNestingMediaOrCodeblockSupported) {
|
|
306
306
|
var _pluginInjectionApi$a4, _pluginInjectionApi$c4;
|
|
307
307
|
return injectAnalyticsPayloadBeforeCommand(pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a4 = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a4 === void 0 ? void 0 : _pluginInjectionApi$a4.actions)(createPasteAnalyticsPayloadBySelection(event, slice, {
|
|
308
308
|
type: PasteTypes.richText
|
|
309
|
-
}, pluginInjectionApi))(handleRichText(slice, pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c4 = pluginInjectionApi.card) === null || _pluginInjectionApi$c4 === void 0 || (_pluginInjectionApi$c4 = _pluginInjectionApi$c4.actions) === null || _pluginInjectionApi$c4 === void 0 ? void 0 : _pluginInjectionApi$c4.queueCardsFromChangedTr));
|
|
309
|
+
}, pluginInjectionApi))(handleRichText(slice, pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c4 = pluginInjectionApi.card) === null || _pluginInjectionApi$c4 === void 0 || (_pluginInjectionApi$c4 = _pluginInjectionApi$c4.actions) === null || _pluginInjectionApi$c4 === void 0 ? void 0 : _pluginInjectionApi$c4.queueCardsFromChangedTr, isNestingMediaOrCodeblockSupported));
|
|
310
310
|
};
|
|
311
311
|
var injectAnalyticsPayloadBeforeCommand = function injectAnalyticsPayloadBeforeCommand(editorAnalyticsAPI) {
|
|
312
312
|
return function (createPayloadByTransaction) {
|
|
@@ -160,8 +160,11 @@ export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFl
|
|
|
160
160
|
/**
|
|
161
161
|
* We want to return false for external copied image to allow
|
|
162
162
|
* it to be uploaded by the client.
|
|
163
|
+
*
|
|
164
|
+
* Scenario where we are pasting an external image inside a block quote
|
|
165
|
+
* is skipped and handled in handleRichText
|
|
163
166
|
*/
|
|
164
|
-
if (htmlContainsSingleFile(html)) {
|
|
167
|
+
if (htmlContainsSingleFile(html) && !isInsideBlockQuote(view.state)) {
|
|
165
168
|
return true;
|
|
166
169
|
}
|
|
167
170
|
|
|
@@ -357,7 +360,7 @@ export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFl
|
|
|
357
360
|
|
|
358
361
|
// finally, handle rich-text copy-paste
|
|
359
362
|
if (isRichText || isNestedMarkdownTable) {
|
|
360
|
-
var _pluginInjectionApi$c2, _pluginInjectionApi$e2, _pluginInjectionApi$f, _pluginInjectionApi$l;
|
|
363
|
+
var _pluginInjectionApi$c2, _pluginInjectionApi$e2, _pluginInjectionApi$f, _pluginInjectionApi$l, _pluginInjectionApi$f2;
|
|
361
364
|
// linkify the text where possible
|
|
362
365
|
slice = linkifyContent(state.schema)(slice);
|
|
363
366
|
if (handlePasteLinkOnSelectedTextWithAnalytics(editorAnalyticsAPI)(view, event, slice, PasteTypes.richText)(state, dispatch)) {
|
|
@@ -434,7 +437,8 @@ export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFl
|
|
|
434
437
|
if (handlePasteNonNestableBlockNodesIntoListWithAnalytics(editorAnalyticsAPI)(view, event, slice)(state, dispatch)) {
|
|
435
438
|
return true;
|
|
436
439
|
}
|
|
437
|
-
|
|
440
|
+
var isNestingMediaOrCodeblockSupported = (pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$f2 = pluginInjectionApi.featureFlags) === null || _pluginInjectionApi$f2 === void 0 || (_pluginInjectionApi$f2 = _pluginInjectionApi$f2.sharedState.currentState()) === null || _pluginInjectionApi$f2 === void 0 ? void 0 : _pluginInjectionApi$f2.nestMediaAndCodeblockInQuote) || fg('editor_nest_media_and_codeblock_in_quotes_jira');
|
|
441
|
+
return handleRichTextWithAnalytics(view, event, slice, pluginInjectionApi, isNestingMediaOrCodeblockSupported)(state, dispatch);
|
|
438
442
|
}
|
|
439
443
|
return false;
|
|
440
444
|
},
|
|
@@ -9,7 +9,8 @@ export var updateContentMoved = function updateContentMoved(nextState, nextActio
|
|
|
9
9
|
var data = {
|
|
10
10
|
currentActions: [].concat(_toConsumableArray(contentMoved.currentActions), [nextAction]),
|
|
11
11
|
size: (nextState === null || nextState === void 0 ? void 0 : nextState.size) || contentMoved.size,
|
|
12
|
-
nodeName: nextState === null || nextState === void 0 ? void 0 : nextState.nodeName
|
|
12
|
+
nodeName: nextState === null || nextState === void 0 ? void 0 : nextState.nodeName,
|
|
13
|
+
nodeDepth: nextState === null || nextState === void 0 ? void 0 : nextState.nodeDepth
|
|
13
14
|
};
|
|
14
15
|
return {
|
|
15
16
|
type: MoveAnalyticPluginTypes.UpdateMovedAction,
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
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; }
|
|
3
|
+
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) { _defineProperty(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; }
|
|
1
4
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
2
5
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
6
|
+
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
3
7
|
import { resetContentMoved, resetContentMovedTransform, updateContentMoved } from './commands';
|
|
4
8
|
import { createPluginState, getPluginState } from './plugin-factory';
|
|
5
9
|
import { pluginKey } from './plugin-key';
|
|
6
10
|
import { defaultState } from './types';
|
|
7
|
-
import { isBlockNodeWithoutTable, isCursorSelectionAndInsideTopLevelNode, isEntireTopLevelBlockquoteSelected, isEntireTopLevelHeadingOrParagraphSelected, isExcludedNode, isInlineNode, isNestedInlineNode, isNestedTable, isNodeSelection, isTextSelection, isValidNodeName } from './utils';
|
|
11
|
+
import { getParentNodeDepth, isBlockNodeWithoutTable, isCursorSelectionAndInsideTopLevelNode, isCursorSelectionAtTopLevel, isEntireNestedParagraphOrHeadingSelected, isEntireTopLevelBlockquoteSelected, isEntireTopLevelHeadingOrParagraphSelected, isExcludedNode, isInlineNode, isNestedInlineNode, isNestedInTable, isNestedTable, isNodeSelection, isTextSelection, isValidNodeName } from './utils';
|
|
8
12
|
|
|
9
13
|
// This plugin exists only in FullPage/FullWidth Editor and is used to register an event that tells us
|
|
10
14
|
// that a user cut and than pasted a node. This order of actions could be considered an alternative
|
|
@@ -37,8 +41,12 @@ export var createPlugin = function createPlugin(dispatch, editorAnalyticsAPI) {
|
|
|
37
41
|
var content = slice.content,
|
|
38
42
|
size = slice.size;
|
|
39
43
|
var nodeName = (_content$firstChild = content.firstChild) === null || _content$firstChild === void 0 ? void 0 : _content$firstChild.type.name;
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
|
|
45
|
+
// We should not account for pastes that go inside another node and create nested content as DnD can't do it when nested-dnd is disabled
|
|
46
|
+
if ((!nodeName || !(contentMoved !== null && contentMoved !== void 0 && contentMoved.nodeName) || !isValidNodeName(contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeName, nodeName) || size !== (contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.size) || !isCursorSelectionAndInsideTopLevelNode(state.selection)) && editorExperiment('nested-dnd', false)) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (!nodeName || !(contentMoved !== null && contentMoved !== void 0 && contentMoved.nodeName) || !isCursorSelectionAtTopLevel(state.selection) && editorExperiment('nested-dnd', true)) {
|
|
42
50
|
return;
|
|
43
51
|
}
|
|
44
52
|
var tr = state.tr;
|
|
@@ -47,9 +55,12 @@ export var createPlugin = function createPlugin(dispatch, editorAnalyticsAPI) {
|
|
|
47
55
|
actionSubject: ACTION_SUBJECT.DOCUMENT,
|
|
48
56
|
actionSubjectId: ACTION_SUBJECT_ID.NODE,
|
|
49
57
|
eventType: EVENT_TYPE.TRACK,
|
|
50
|
-
attributes: {
|
|
51
|
-
nodeType: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeName
|
|
52
|
-
}
|
|
58
|
+
attributes: _objectSpread({
|
|
59
|
+
nodeType: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeName
|
|
60
|
+
}, editorExperiment('nested-dnd', true) && {
|
|
61
|
+
nodeDepth: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeDepth,
|
|
62
|
+
destinationNodeDepth: getParentNodeDepth(state.selection)
|
|
63
|
+
})
|
|
53
64
|
})(tr);
|
|
54
65
|
|
|
55
66
|
// reset to default state
|
|
@@ -79,6 +90,7 @@ export var createPlugin = function createPlugin(dispatch, editorAnalyticsAPI) {
|
|
|
79
90
|
resetState = true;
|
|
80
91
|
}
|
|
81
92
|
var nodeName = ((_content$firstChild2 = content.firstChild) === null || _content$firstChild2 === void 0 ? void 0 : _content$firstChild2.type.name) || '';
|
|
93
|
+
|
|
82
94
|
// Some nodes are not relevant as they are parts of nodes, not whole nodes (like tableCell, tableHeader instead of table node)
|
|
83
95
|
// Some nodes like lists, taskList(item), decisionList(item) requires tricky checks that we want to avoid doing.
|
|
84
96
|
// These nodes were added to excludedNodes array.
|
|
@@ -88,42 +100,50 @@ export var createPlugin = function createPlugin(dispatch, editorAnalyticsAPI) {
|
|
|
88
100
|
var selection = state.selection;
|
|
89
101
|
// DnD can't drag part of text in a paragraph/heading. DnD will select the whole node with all the text inside.
|
|
90
102
|
// So we are only interested in cut slices that contain the entire node, not just a part of it.
|
|
91
|
-
if (!resetState && nodeName === 'paragraph' && !isEntireTopLevelHeadingOrParagraphSelected(selection, nodeName)) {
|
|
103
|
+
if (!resetState && nodeName === 'paragraph' && !isEntireTopLevelHeadingOrParagraphSelected(selection, nodeName) && editorExperiment('nested-dnd', false)) {
|
|
92
104
|
resetState = true;
|
|
93
105
|
}
|
|
94
|
-
if (!resetState && nodeName === 'heading' && !isEntireTopLevelHeadingOrParagraphSelected(selection, nodeName)) {
|
|
106
|
+
if (!resetState && nodeName === 'heading' && !isEntireTopLevelHeadingOrParagraphSelected(selection, nodeName) && editorExperiment('nested-dnd', false)) {
|
|
107
|
+
resetState = true;
|
|
108
|
+
}
|
|
109
|
+
if (!resetState && !isEntireNestedParagraphOrHeadingSelected(selection) && editorExperiment('nested-dnd', true)) {
|
|
95
110
|
resetState = true;
|
|
96
111
|
}
|
|
97
112
|
|
|
98
113
|
// DnD can't drag just one paragraph (when blockquote contains multiple paragraphs) or just a part of a paragraph in the blockquote.
|
|
99
114
|
// DnD will select and drag the whole blockquote. So we need to register cut events that have the entire blockquote too.
|
|
100
|
-
if (!resetState && nodeName === 'blockquote' && !isEntireTopLevelBlockquoteSelected(state)) {
|
|
115
|
+
if (!resetState && nodeName === 'blockquote' && !isEntireTopLevelBlockquoteSelected(state) && editorExperiment('nested-dnd', false)) {
|
|
101
116
|
resetState = true;
|
|
102
117
|
}
|
|
103
118
|
if (!resetState && isInlineNode(nodeName) && isNestedInlineNode(selection)) {
|
|
104
119
|
resetState = true;
|
|
105
120
|
}
|
|
106
|
-
if (!resetState && nodeName === 'table' && isNestedTable(selection)) {
|
|
121
|
+
if (!resetState && nodeName === 'table' && isNestedTable(selection) && editorExperiment('nested-dnd', false)) {
|
|
122
|
+
resetState = true;
|
|
123
|
+
}
|
|
124
|
+
if (!resetState && isNestedInTable(state) && editorExperiment('nested-dnd', true) && editorExperiment('table-nested-dnd', false)) {
|
|
107
125
|
resetState = true;
|
|
108
126
|
}
|
|
109
127
|
var isBlockNode = isBlockNodeWithoutTable(nodeName);
|
|
110
|
-
if (!resetState && isNodeSelection(selection) && isBlockNode && selection.$anchor.node().type.name !== 'doc' // checks that the block node is not a topLevel node
|
|
128
|
+
if (!resetState && isNodeSelection(selection) && isBlockNode && selection.$anchor.node().type.name !== 'doc' && editorExperiment('nested-dnd', false) // checks that the block node is not a topLevel node
|
|
111
129
|
) {
|
|
112
130
|
resetState = true;
|
|
113
131
|
}
|
|
114
132
|
|
|
115
133
|
// Some blockNodes can have text inside of them cut, in that case TextSelection occurs, we don't need to track
|
|
116
134
|
// these cut events.
|
|
117
|
-
if (!resetState && isTextSelection(selection) && isBlockNode) {
|
|
135
|
+
if (!resetState && isTextSelection(selection) && isBlockNode && editorExperiment('nested-dnd', false)) {
|
|
118
136
|
resetState = true;
|
|
119
137
|
}
|
|
120
138
|
if (resetState) {
|
|
121
139
|
resetContentMoved()(state, dispatch);
|
|
122
140
|
} else {
|
|
123
|
-
updateContentMoved({
|
|
141
|
+
updateContentMoved(_objectSpread({
|
|
124
142
|
size: size,
|
|
125
143
|
nodeName: nodeName
|
|
126
|
-
}, '
|
|
144
|
+
}, editorExperiment('nested-dnd', true) && {
|
|
145
|
+
nodeDepth: getParentNodeDepth(selection)
|
|
146
|
+
}), 'contentCut')(state, dispatch);
|
|
127
147
|
}
|
|
128
148
|
isCutEvent = false;
|
|
129
149
|
return slice;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
1
2
|
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
-
import { findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
|
|
3
|
-
|
|
3
|
+
import { findParentNodeClosestToPos, findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
|
|
4
|
+
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
5
|
+
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
6
|
+
var excludedNodes = ['caption', 'layoutColumn', 'listItem', 'tableHeader', 'tableCell', 'tableRow', 'text', 'placeholder', 'unsupportedBlock', 'unsupportedInline', 'hardBreak', 'confluenceUnsupportedBlock', 'confluenceUnsupportedInline', 'taskItem', 'decisionItem'].concat(_toConsumableArray(editorExperiment('nested-dnd', false) ? ['bulletList', 'orderedList', 'taskList', 'decisionList', 'nestedExpand', 'media'] : []));
|
|
4
7
|
export var isExcludedNode = function isExcludedNode(nodeName) {
|
|
5
8
|
return excludedNodes.includes(nodeName);
|
|
6
9
|
};
|
|
@@ -13,6 +16,15 @@ export var isCursorSelectionAndInsideTopLevelNode = function isCursorSelectionAn
|
|
|
13
16
|
}
|
|
14
17
|
return true;
|
|
15
18
|
};
|
|
19
|
+
export var isCursorSelectionAtTopLevel = function isCursorSelectionAtTopLevel(selection) {
|
|
20
|
+
var from = selection.from,
|
|
21
|
+
to = selection.to,
|
|
22
|
+
$from = selection.$from;
|
|
23
|
+
if (from !== to) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return $from.parentOffset === 0;
|
|
27
|
+
};
|
|
16
28
|
var inlineNodes = ['emoji', 'date', 'status', 'mention', 'mediaInline', 'inlineCard', 'inlineExtension'];
|
|
17
29
|
export var isInlineNode = function isInlineNode(nodeName) {
|
|
18
30
|
return inlineNodes.includes(nodeName);
|
|
@@ -46,6 +58,28 @@ export var isNestedTable = function isNestedTable(selection) {
|
|
|
46
58
|
var parentNode = selection.$anchor.node(1);
|
|
47
59
|
return parentNode && parentNodes.includes(parentNode.type.name);
|
|
48
60
|
};
|
|
61
|
+
export var isNestedInTable = function isNestedInTable(state) {
|
|
62
|
+
var schema = state.schema,
|
|
63
|
+
selection = state.selection;
|
|
64
|
+
if (selection instanceof CellSelection) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
var table = schema.nodes.table;
|
|
68
|
+
var tableNode = findParentNodeOfTypeClosestToPos(selection.$from, table);
|
|
69
|
+
if (!tableNode) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
};
|
|
74
|
+
export var getParentNodeDepth = function getParentNodeDepth(selection) {
|
|
75
|
+
var parentNode = findParentNodeClosestToPos(selection.$from, function () {
|
|
76
|
+
return true;
|
|
77
|
+
});
|
|
78
|
+
if (!parentNode) {
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
return parentNode.node.type.name === 'heading' || parentNode.node.type.name === 'paragraph' ? parentNode.depth - 1 : parentNode.depth;
|
|
82
|
+
};
|
|
49
83
|
var getPastedNameOfInlineNode = function getPastedNameOfInlineNode(nodeName) {
|
|
50
84
|
if (inlineNodes.includes(nodeName)) {
|
|
51
85
|
return 'paragraph';
|
|
@@ -111,4 +145,9 @@ export var isEntireTopLevelBlockquoteSelected = function isEntireTopLevelBlockqu
|
|
|
111
145
|
}
|
|
112
146
|
});
|
|
113
147
|
return selectedNodesCount === blockquoteNode.node.childCount;
|
|
148
|
+
};
|
|
149
|
+
export var isEntireNestedParagraphOrHeadingSelected = function isEntireNestedParagraphOrHeadingSelected(selection) {
|
|
150
|
+
var $from = selection.$from,
|
|
151
|
+
$to = selection.$to;
|
|
152
|
+
return $from.textOffset === 0 && $to.textOffset === 0;
|
|
114
153
|
};
|
package/dist/types/handlers.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export declare function handleParagraphBlockMarks(state: EditorState, slice: Sli
|
|
|
51
51
|
* ┗━p -> "two"
|
|
52
52
|
*/
|
|
53
53
|
export declare function flattenNestedListInSlice(slice: Slice): Slice;
|
|
54
|
-
export declare function handleRichText(slice: Slice, queueCardsFromChangedTr: QueueCardsFromTransactionAction | undefined): Command;
|
|
54
|
+
export declare function handleRichText(slice: Slice, queueCardsFromChangedTr: QueueCardsFromTransactionAction | undefined, isNestingMediaOrCodeblockSupported?: boolean): Command;
|
|
55
55
|
export declare function handlePasteIntoCaption(slice: Slice): Command;
|
|
56
56
|
export declare const handleSelectedTable: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (slice: Slice) => Command;
|
|
57
57
|
export declare function checkTaskListInList(state: EditorState, slice: Slice): boolean;
|
|
@@ -28,7 +28,7 @@ export declare const handleCodeBlockWithAnalytics: (editorAnalyticsAPI: EditorAn
|
|
|
28
28
|
export declare const handleMediaSingleWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (view: EditorView, event: ClipboardEvent, slice: Slice, type: PasteType, insertMediaAsMediaSingle: InsertMediaAsMediaSingle | undefined) => Command;
|
|
29
29
|
export declare const handlePastePreservingMarksWithAnalytics: (view: EditorView, event: ClipboardEvent, slice: Slice, type: PasteType, pluginInjectionApi: ExtractInjectionAPI<PastePlugin> | undefined) => Command;
|
|
30
30
|
export declare const handleMarkdownWithAnalytics: (view: EditorView, event: ClipboardEvent, slice: Slice, pluginInjectionApi: ExtractInjectionAPI<PastePlugin> | undefined) => Command;
|
|
31
|
-
export declare const handleRichTextWithAnalytics: (view: EditorView, event: ClipboardEvent, slice: Slice, pluginInjectionApi: ExtractInjectionAPI<PastePlugin> | undefined) => Command;
|
|
31
|
+
export declare const handleRichTextWithAnalytics: (view: EditorView, event: ClipboardEvent, slice: Slice, pluginInjectionApi: ExtractInjectionAPI<PastePlugin> | undefined, isNestingMediaOrCodeblockSupported: boolean) => Command;
|
|
32
32
|
export declare const handlePastePanelOrDecisionIntoListWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (view: EditorView, event: ClipboardEvent, slice: Slice, findRootParentListNode: FindRootParentListNode | undefined) => Command;
|
|
33
33
|
export declare const handlePasteNonNestableBlockNodesIntoListWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (view: EditorView, event: ClipboardEvent, slice: Slice) => Command;
|
|
34
34
|
export declare const handleExpandWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined, isNestingExpandsSupported: boolean) => (view: EditorView, event: ClipboardEvent, slice: Slice) => Command;
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { EditorState, Selection } from '@atlaskit/editor-prosemirror/state';
|
|
2
2
|
export declare const isExcludedNode: (nodeName: string) => boolean;
|
|
3
3
|
export declare const isCursorSelectionAndInsideTopLevelNode: (selection: Selection) => boolean;
|
|
4
|
+
export declare const isCursorSelectionAtTopLevel: (selection: Selection) => boolean;
|
|
4
5
|
export declare const isInlineNode: (nodeName: string) => boolean;
|
|
5
6
|
export declare const isNestedInlineNode: (selection: Selection) => boolean;
|
|
6
7
|
export declare const isBlockNodeWithoutTable: (nodeName: string) => boolean;
|
|
7
8
|
export declare const isNestedTable: (selection: Selection) => boolean;
|
|
9
|
+
export declare const isNestedInTable: (state: EditorState) => boolean;
|
|
10
|
+
export declare const getParentNodeDepth: (selection: Selection) => number;
|
|
8
11
|
export declare const isValidNodeName: (copiedNodeName: string, pastedNodeName: string) => boolean;
|
|
9
12
|
export declare const isTextSelection: (selection: Selection) => boolean;
|
|
10
13
|
export declare const isNodeSelection: (selection: Selection) => boolean;
|
|
11
14
|
export declare const isEntireTopLevelHeadingOrParagraphSelected: (selection: Selection, nodeName: 'paragraph' | 'heading') => boolean | undefined;
|
|
12
15
|
export declare const isEntireTopLevelBlockquoteSelected: (state: EditorState) => boolean;
|
|
16
|
+
export declare const isEntireNestedParagraphOrHeadingSelected: (selection: Selection) => boolean;
|
|
@@ -51,7 +51,7 @@ export declare function handleParagraphBlockMarks(state: EditorState, slice: Sli
|
|
|
51
51
|
* ┗━p -> "two"
|
|
52
52
|
*/
|
|
53
53
|
export declare function flattenNestedListInSlice(slice: Slice): Slice;
|
|
54
|
-
export declare function handleRichText(slice: Slice, queueCardsFromChangedTr: QueueCardsFromTransactionAction | undefined): Command;
|
|
54
|
+
export declare function handleRichText(slice: Slice, queueCardsFromChangedTr: QueueCardsFromTransactionAction | undefined, isNestingMediaOrCodeblockSupported?: boolean): Command;
|
|
55
55
|
export declare function handlePasteIntoCaption(slice: Slice): Command;
|
|
56
56
|
export declare const handleSelectedTable: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (slice: Slice) => Command;
|
|
57
57
|
export declare function checkTaskListInList(state: EditorState, slice: Slice): boolean;
|
|
@@ -28,7 +28,7 @@ export declare const handleCodeBlockWithAnalytics: (editorAnalyticsAPI: EditorAn
|
|
|
28
28
|
export declare const handleMediaSingleWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (view: EditorView, event: ClipboardEvent, slice: Slice, type: PasteType, insertMediaAsMediaSingle: InsertMediaAsMediaSingle | undefined) => Command;
|
|
29
29
|
export declare const handlePastePreservingMarksWithAnalytics: (view: EditorView, event: ClipboardEvent, slice: Slice, type: PasteType, pluginInjectionApi: ExtractInjectionAPI<PastePlugin> | undefined) => Command;
|
|
30
30
|
export declare const handleMarkdownWithAnalytics: (view: EditorView, event: ClipboardEvent, slice: Slice, pluginInjectionApi: ExtractInjectionAPI<PastePlugin> | undefined) => Command;
|
|
31
|
-
export declare const handleRichTextWithAnalytics: (view: EditorView, event: ClipboardEvent, slice: Slice, pluginInjectionApi: ExtractInjectionAPI<PastePlugin> | undefined) => Command;
|
|
31
|
+
export declare const handleRichTextWithAnalytics: (view: EditorView, event: ClipboardEvent, slice: Slice, pluginInjectionApi: ExtractInjectionAPI<PastePlugin> | undefined, isNestingMediaOrCodeblockSupported: boolean) => Command;
|
|
32
32
|
export declare const handlePastePanelOrDecisionIntoListWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (view: EditorView, event: ClipboardEvent, slice: Slice, findRootParentListNode: FindRootParentListNode | undefined) => Command;
|
|
33
33
|
export declare const handlePasteNonNestableBlockNodesIntoListWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (view: EditorView, event: ClipboardEvent, slice: Slice) => Command;
|
|
34
34
|
export declare const handleExpandWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined, isNestingExpandsSupported: boolean) => (view: EditorView, event: ClipboardEvent, slice: Slice) => Command;
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { EditorState, Selection } from '@atlaskit/editor-prosemirror/state';
|
|
2
2
|
export declare const isExcludedNode: (nodeName: string) => boolean;
|
|
3
3
|
export declare const isCursorSelectionAndInsideTopLevelNode: (selection: Selection) => boolean;
|
|
4
|
+
export declare const isCursorSelectionAtTopLevel: (selection: Selection) => boolean;
|
|
4
5
|
export declare const isInlineNode: (nodeName: string) => boolean;
|
|
5
6
|
export declare const isNestedInlineNode: (selection: Selection) => boolean;
|
|
6
7
|
export declare const isBlockNodeWithoutTable: (nodeName: string) => boolean;
|
|
7
8
|
export declare const isNestedTable: (selection: Selection) => boolean;
|
|
9
|
+
export declare const isNestedInTable: (state: EditorState) => boolean;
|
|
10
|
+
export declare const getParentNodeDepth: (selection: Selection) => number;
|
|
8
11
|
export declare const isValidNodeName: (copiedNodeName: string, pastedNodeName: string) => boolean;
|
|
9
12
|
export declare const isTextSelection: (selection: Selection) => boolean;
|
|
10
13
|
export declare const isNodeSelection: (selection: Selection) => boolean;
|
|
11
14
|
export declare const isEntireTopLevelHeadingOrParagraphSelected: (selection: Selection, nodeName: 'paragraph' | 'heading') => boolean | undefined;
|
|
12
15
|
export declare const isEntireTopLevelBlockquoteSelected: (state: EditorState) => boolean;
|
|
16
|
+
export declare const isEntireNestedParagraphOrHeadingSelected: (selection: Selection) => boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-paste",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.5",
|
|
4
4
|
"description": "Paste plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
".": "./src/index.ts"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@atlaskit/editor-common": "^
|
|
34
|
+
"@atlaskit/editor-common": "^91.0.0",
|
|
35
35
|
"@atlaskit/editor-markdown-transformer": "^5.12.0",
|
|
36
36
|
"@atlaskit/editor-plugin-analytics": "^1.8.0",
|
|
37
37
|
"@atlaskit/editor-plugin-annotation": "^1.19.0",
|
|
@@ -39,13 +39,14 @@
|
|
|
39
39
|
"@atlaskit/editor-plugin-card": "^3.0.0",
|
|
40
40
|
"@atlaskit/editor-plugin-feature-flags": "^1.2.0",
|
|
41
41
|
"@atlaskit/editor-plugin-list": "^3.8.0",
|
|
42
|
-
"@atlaskit/editor-plugin-media": "^1.
|
|
42
|
+
"@atlaskit/editor-plugin-media": "^1.32.0",
|
|
43
43
|
"@atlaskit/editor-plugin-mentions": "^2.6.0",
|
|
44
44
|
"@atlaskit/editor-prosemirror": "6.0.0",
|
|
45
45
|
"@atlaskit/editor-tables": "^2.8.0",
|
|
46
46
|
"@atlaskit/media-client": "^28.0.0",
|
|
47
47
|
"@atlaskit/media-common": "^11.4.0",
|
|
48
48
|
"@atlaskit/platform-feature-flags": "^0.3.0",
|
|
49
|
+
"@atlaskit/tmp-editor-statsig": "*",
|
|
49
50
|
"@babel/runtime": "^7.0.0",
|
|
50
51
|
"lodash": "^4.17.21",
|
|
51
52
|
"uuid": "^3.1.0"
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
"devDependencies": {
|
|
57
58
|
"@af/visual-regression": "*",
|
|
58
59
|
"@atlaskit/adf-schema": "^40.9.0",
|
|
59
|
-
"@atlaskit/editor-plugin-block-type": "^3.
|
|
60
|
+
"@atlaskit/editor-plugin-block-type": "^3.15.0",
|
|
60
61
|
"@atlaskit/editor-plugin-history": "^1.3.0",
|
|
61
62
|
"@atlaskit/editor-plugin-type-ahead": "^1.8.0",
|
|
62
63
|
"@atlaskit/ssr": "*",
|
|
@@ -119,6 +120,9 @@
|
|
|
119
120
|
},
|
|
120
121
|
"platform_editor_nest_nested_expand_in_expand_jira": {
|
|
121
122
|
"type": "boolean"
|
|
123
|
+
},
|
|
124
|
+
"editor_nest_media_and_codeblock_in_quotes_jira": {
|
|
125
|
+
"type": "boolean"
|
|
122
126
|
}
|
|
123
127
|
}
|
|
124
128
|
}
|
package/.eslintrc.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
rules: {
|
|
3
|
-
'@typescript-eslint/no-duplicate-imports': 'error',
|
|
4
|
-
'@typescript-eslint/no-explicit-any': 'error',
|
|
5
|
-
'@typescript-eslint/ban-types': [
|
|
6
|
-
'error',
|
|
7
|
-
{
|
|
8
|
-
types: {
|
|
9
|
-
'React.FC':
|
|
10
|
-
'Please use types directly on props instead, and explicitly define children if required',
|
|
11
|
-
'React.FunctionalComponent':
|
|
12
|
-
'Please use types directly on props instead, and explicitly define children if required',
|
|
13
|
-
},
|
|
14
|
-
extendDefaults: false,
|
|
15
|
-
},
|
|
16
|
-
],
|
|
17
|
-
},
|
|
18
|
-
};
|