@atlaskit/editor-plugin-paste 2.3.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/cjs/pm-plugins/move-analytics/commands.js +3 -1
- package/dist/cjs/pm-plugins/move-analytics/plugin.js +54 -23
- package/dist/cjs/pm-plugins/move-analytics/types.js +3 -1
- package/dist/cjs/pm-plugins/move-analytics/utils.js +26 -1
- package/dist/es2019/pm-plugins/move-analytics/commands.js +3 -1
- package/dist/es2019/pm-plugins/move-analytics/plugin.js +54 -26
- package/dist/es2019/pm-plugins/move-analytics/types.js +3 -1
- package/dist/es2019/pm-plugins/move-analytics/utils.js +23 -0
- package/dist/esm/pm-plugins/move-analytics/commands.js +3 -1
- package/dist/esm/pm-plugins/move-analytics/plugin.js +54 -24
- package/dist/esm/pm-plugins/move-analytics/types.js +3 -1
- package/dist/esm/pm-plugins/move-analytics/utils.js +24 -0
- package/dist/types/pm-plugins/move-analytics/types.d.ts +2 -0
- package/dist/types/pm-plugins/move-analytics/utils.d.ts +6 -0
- package/dist/types-ts4.5/pm-plugins/move-analytics/types.d.ts +2 -0
- package/dist/types-ts4.5/pm-plugins/move-analytics/utils.d.ts +6 -0
- package/package.json +7 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-paste
|
|
2
2
|
|
|
3
|
+
## 2.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#114384](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/114384)
|
|
8
|
+
[`72325f32502fb`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/72325f32502fb) -
|
|
9
|
+
[ED-26291] Update document moved event to reflect multiple selection information
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
|
|
3
12
|
## 2.3.0
|
|
4
13
|
|
|
5
14
|
### Minor Changes
|
|
@@ -17,7 +17,9 @@ var updateContentMoved = exports.updateContentMoved = function updateContentMove
|
|
|
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
19
|
nodeName: nextState === null || nextState === void 0 ? void 0 : nextState.nodeName,
|
|
20
|
-
nodeDepth: nextState === null || nextState === void 0 ? void 0 : nextState.nodeDepth
|
|
20
|
+
nodeDepth: nextState === null || nextState === void 0 ? void 0 : nextState.nodeDepth,
|
|
21
|
+
nodeTypes: nextState === null || nextState === void 0 ? void 0 : nextState.nodeTypes,
|
|
22
|
+
hasSelectedMultipleNodes: nextState === null || nextState === void 0 ? void 0 : nextState.hasSelectedMultipleNodes
|
|
21
23
|
};
|
|
22
24
|
return {
|
|
23
25
|
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
|
|
@@ -51,11 +56,12 @@ var createPlugin = exports.createPlugin = function createPlugin(dispatch, editor
|
|
|
51
56
|
actionSubjectId: _analytics.ACTION_SUBJECT_ID.NODE,
|
|
52
57
|
eventType: _analytics.EVENT_TYPE.TRACK,
|
|
53
58
|
attributes: {
|
|
59
|
+
// keep nodeName from copied slice
|
|
54
60
|
nodeType: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeName,
|
|
55
61
|
nodeDepth: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeDepth,
|
|
56
|
-
destinationNodeDepth: (0, _utils.getParentNodeDepth)(state.selection)
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
destinationNodeDepth: (0, _utils.getParentNodeDepth)(state.selection),
|
|
63
|
+
nodeTypes: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeTypes,
|
|
64
|
+
hasSelectedMultipleNodes: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.hasSelectedMultipleNodes
|
|
59
65
|
}
|
|
60
66
|
})(tr);
|
|
61
67
|
|
|
@@ -74,6 +80,9 @@ var createPlugin = exports.createPlugin = function createPlugin(dispatch, editor
|
|
|
74
80
|
var resetState = false;
|
|
75
81
|
var content = slice.content,
|
|
76
82
|
size = slice.size;
|
|
83
|
+
var selection = state.selection;
|
|
84
|
+
// Note: the following is not the case once `platform_editor_element_drag_and_drop_multiselect` is enabled
|
|
85
|
+
// we now want to track cut events for multiple nodes
|
|
77
86
|
// Content should be just one node, so we added a check for slice.content.childCount === 1;
|
|
78
87
|
// 1. It is possible to select a table by dragging the mouse over the table's rows.
|
|
79
88
|
// As a result, slice will contain rows without tableNode itself and the childCount will be the number of rows.
|
|
@@ -82,35 +91,57 @@ var createPlugin = exports.createPlugin = function createPlugin(dispatch, editor
|
|
|
82
91
|
// the paragraph below the node. Visually only the node in between is selected, in reality, three nodes are
|
|
83
92
|
// in the slice.
|
|
84
93
|
// These cases are ignored and moveContent event won't be counted.
|
|
85
|
-
|
|
86
|
-
resetState = true;
|
|
87
|
-
}
|
|
94
|
+
var isMultiSelectEnabled = (0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true);
|
|
88
95
|
var nodeName = ((_content$firstChild2 = content.firstChild) === null || _content$firstChild2 === void 0 ? void 0 : _content$firstChild2.type.name) || '';
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (
|
|
96
|
+
var nodeTypes,
|
|
97
|
+
hasSelectedMultipleNodes = false;
|
|
98
|
+
if (content.childCount > 1) {
|
|
99
|
+
if (isMultiSelectEnabled) {
|
|
100
|
+
if ((0, _utils.containsExcludedNode)(content)) {
|
|
101
|
+
resetState = true;
|
|
102
|
+
} else {
|
|
103
|
+
var attributes = (0, _utils.getMultipleSelectionAttributes)(content);
|
|
104
|
+
nodeTypes = attributes.nodeTypes;
|
|
105
|
+
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
resetState = true;
|
|
109
|
+
}
|
|
110
|
+
} else if (content.childCount === 1) {
|
|
111
|
+
// Some nodes are not relevant as they are parts of nodes, not whole nodes (like tableCell, tableHeader instead of table node)
|
|
112
|
+
// Some nodes like lists, taskList(item), decisionList(item) requires tricky checks that we want to avoid doing.
|
|
113
|
+
// These nodes were added to excludedNodes array.
|
|
114
|
+
if (!resetState && (0, _utils.isExcludedNode)(nodeName)) {
|
|
115
|
+
resetState = true;
|
|
116
|
+
}
|
|
117
|
+
if (!resetState && !(0, _utils.isEntireNestedParagraphOrHeadingSelected)(selection)) {
|
|
118
|
+
resetState = true;
|
|
119
|
+
}
|
|
120
|
+
if (!resetState && (0, _utils.isInlineNode)(nodeName) && (0, _utils.isNestedInlineNode)(selection)) {
|
|
121
|
+
resetState = true;
|
|
122
|
+
}
|
|
123
|
+
if (!resetState && (0, _utils.isNestedInTable)(state)) {
|
|
124
|
+
resetState = true;
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
104
127
|
resetState = true;
|
|
105
128
|
}
|
|
106
129
|
if (resetState) {
|
|
107
130
|
(0, _commands.resetContentMoved)()(state, dispatch);
|
|
108
131
|
} else {
|
|
109
|
-
|
|
132
|
+
var newState = {
|
|
110
133
|
size: size,
|
|
111
134
|
nodeName: nodeName,
|
|
112
135
|
nodeDepth: (0, _utils.getParentNodeDepth)(selection)
|
|
113
|
-
}
|
|
136
|
+
};
|
|
137
|
+
if (isMultiSelectEnabled) {
|
|
138
|
+
var _nodeTypes;
|
|
139
|
+
newState = _objectSpread(_objectSpread({}, newState), {}, {
|
|
140
|
+
nodeTypes: (_nodeTypes = nodeTypes) !== null && _nodeTypes !== void 0 ? _nodeTypes : nodeName,
|
|
141
|
+
hasSelectedMultipleNodes: hasSelectedMultipleNodes
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
(0, _commands.updateContentMoved)(newState, 'contentCut')(state, dispatch);
|
|
114
145
|
}
|
|
115
146
|
isCutEvent = false;
|
|
116
147
|
return slice;
|
|
@@ -1,11 +1,14 @@
|
|
|
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.isNestedInlineNode = exports.isNestedInTable = exports.isInlineNode = exports.isExcludedNode = exports.isEntireNestedParagraphOrHeadingSelected = exports.isCursorSelectionAtTopLevel = exports.getParentNodeDepth = void 0;
|
|
7
|
+
exports.isNestedInlineNode = exports.isNestedInTable = exports.isInlineNode = exports.isExcludedNode = exports.isEntireNestedParagraphOrHeadingSelected = exports.isCursorSelectionAtTopLevel = exports.getParentNodeDepth = exports.getMultipleSelectionAttributes = exports.containsExcludedNode = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
7
9
|
var _utils = require("@atlaskit/editor-prosemirror/utils");
|
|
8
10
|
var _cellSelection = require("@atlaskit/editor-tables/cell-selection");
|
|
11
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
9
12
|
var excludedNodes = ['caption', 'layoutColumn', 'listItem', 'tableHeader', 'tableCell', 'tableRow', 'text', 'placeholder', 'unsupportedBlock', 'unsupportedInline', 'hardBreak', 'confluenceUnsupportedBlock', 'confluenceUnsupportedInline', 'taskItem', 'decisionItem'];
|
|
10
13
|
var isExcludedNode = exports.isExcludedNode = function isExcludedNode(nodeName) {
|
|
11
14
|
return excludedNodes.includes(nodeName);
|
|
@@ -69,4 +72,26 @@ var isEntireNestedParagraphOrHeadingSelected = exports.isEntireNestedParagraphOr
|
|
|
69
72
|
var $from = selection.$from,
|
|
70
73
|
$to = selection.$to;
|
|
71
74
|
return $from.textOffset === 0 && $to.textOffset === 0;
|
|
75
|
+
};
|
|
76
|
+
var containsExcludedNode = exports.containsExcludedNode = function containsExcludedNode(content) {
|
|
77
|
+
for (var i = 0; i < content.childCount; i++) {
|
|
78
|
+
var _content$maybeChild;
|
|
79
|
+
var nodeName = ((_content$maybeChild = content.maybeChild(i)) === null || _content$maybeChild === void 0 ? void 0 : _content$maybeChild.type.name) || '';
|
|
80
|
+
if (isExcludedNode(nodeName)) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
};
|
|
86
|
+
var getMultipleSelectionAttributes = exports.getMultipleSelectionAttributes = function getMultipleSelectionAttributes(content) {
|
|
87
|
+
var nodeTypes = [];
|
|
88
|
+
if (content.size) {
|
|
89
|
+
content.forEach(function (node) {
|
|
90
|
+
nodeTypes.push(node.type.name);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
nodeTypes: (0, _platformFeatureFlags.fg)('platform_editor_track_node_types') ? (0, _toConsumableArray2.default)(new Set(nodeTypes)).sort().join(',') : undefined,
|
|
95
|
+
hasSelectedMultipleNodes: nodeTypes.length > 1
|
|
96
|
+
};
|
|
72
97
|
};
|
|
@@ -9,7 +9,9 @@ export const updateContentMoved = (nextState, nextAction) => createCommand(state
|
|
|
9
9
|
currentActions: [...contentMoved.currentActions, nextAction],
|
|
10
10
|
size: (nextState === null || nextState === void 0 ? void 0 : nextState.size) || contentMoved.size,
|
|
11
11
|
nodeName: nextState === null || nextState === void 0 ? void 0 : nextState.nodeName,
|
|
12
|
-
nodeDepth: nextState === null || nextState === void 0 ? void 0 : nextState.nodeDepth
|
|
12
|
+
nodeDepth: nextState === null || nextState === void 0 ? void 0 : nextState.nodeDepth,
|
|
13
|
+
nodeTypes: nextState === null || nextState === void 0 ? void 0 : nextState.nodeTypes,
|
|
14
|
+
hasSelectedMultipleNodes: nextState === null || nextState === void 0 ? void 0 : nextState.hasSelectedMultipleNodes
|
|
13
15
|
};
|
|
14
16
|
return {
|
|
15
17
|
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 { getParentNodeDepth, isCursorSelectionAtTopLevel, isEntireNestedParagraphOrHeadingSelected, isExcludedNode, isInlineNode, isNestedInlineNode, isNestedInTable } from './utils';
|
|
8
|
+
import { containsExcludedNode, getMultipleSelectionAttributes, getParentNodeDepth, isCursorSelectionAtTopLevel, isEntireNestedParagraphOrHeadingSelected, isExcludedNode, isInlineNode, isNestedInlineNode, isNestedInTable } 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
|
|
@@ -52,11 +53,12 @@ export const createPlugin = (dispatch, editorAnalyticsAPI) => {
|
|
|
52
53
|
actionSubjectId: ACTION_SUBJECT_ID.NODE,
|
|
53
54
|
eventType: EVENT_TYPE.TRACK,
|
|
54
55
|
attributes: {
|
|
56
|
+
// keep nodeName from copied slice
|
|
55
57
|
nodeType: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeName,
|
|
56
58
|
nodeDepth: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeDepth,
|
|
57
|
-
destinationNodeDepth: getParentNodeDepth(state.selection)
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
destinationNodeDepth: getParentNodeDepth(state.selection),
|
|
60
|
+
nodeTypes: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeTypes,
|
|
61
|
+
hasSelectedMultipleNodes: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.hasSelectedMultipleNodes
|
|
60
62
|
}
|
|
61
63
|
})(tr);
|
|
62
64
|
|
|
@@ -78,6 +80,11 @@ export const createPlugin = (dispatch, editorAnalyticsAPI) => {
|
|
|
78
80
|
content,
|
|
79
81
|
size
|
|
80
82
|
} = slice;
|
|
83
|
+
const {
|
|
84
|
+
selection
|
|
85
|
+
} = state;
|
|
86
|
+
// Note: the following is not the case once `platform_editor_element_drag_and_drop_multiselect` is enabled
|
|
87
|
+
// we now want to track cut events for multiple nodes
|
|
81
88
|
// Content should be just one node, so we added a check for slice.content.childCount === 1;
|
|
82
89
|
// 1. It is possible to select a table by dragging the mouse over the table's rows.
|
|
83
90
|
// As a result, slice will contain rows without tableNode itself and the childCount will be the number of rows.
|
|
@@ -86,37 +93,58 @@ export const createPlugin = (dispatch, editorAnalyticsAPI) => {
|
|
|
86
93
|
// the paragraph below the node. Visually only the node in between is selected, in reality, three nodes are
|
|
87
94
|
// in the slice.
|
|
88
95
|
// These cases are ignored and moveContent event won't be counted.
|
|
89
|
-
|
|
90
|
-
resetState = true;
|
|
91
|
-
}
|
|
96
|
+
const isMultiSelectEnabled = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
|
|
92
97
|
const nodeName = ((_content$firstChild2 = content.firstChild) === null || _content$firstChild2 === void 0 ? void 0 : _content$firstChild2.type.name) || '';
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
98
|
+
let nodeTypes,
|
|
99
|
+
hasSelectedMultipleNodes = false;
|
|
100
|
+
if (content.childCount > 1) {
|
|
101
|
+
if (isMultiSelectEnabled) {
|
|
102
|
+
if (containsExcludedNode(content)) {
|
|
103
|
+
resetState = true;
|
|
104
|
+
} else {
|
|
105
|
+
const attributes = getMultipleSelectionAttributes(content);
|
|
106
|
+
nodeTypes = attributes.nodeTypes;
|
|
107
|
+
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
resetState = true;
|
|
111
|
+
}
|
|
112
|
+
} else if (content.childCount === 1) {
|
|
113
|
+
// Some nodes are not relevant as they are parts of nodes, not whole nodes (like tableCell, tableHeader instead of table node)
|
|
114
|
+
// Some nodes like lists, taskList(item), decisionList(item) requires tricky checks that we want to avoid doing.
|
|
115
|
+
// These nodes were added to excludedNodes array.
|
|
116
|
+
if (!resetState && isExcludedNode(nodeName)) {
|
|
117
|
+
resetState = true;
|
|
118
|
+
}
|
|
119
|
+
if (!resetState && !isEntireNestedParagraphOrHeadingSelected(selection)) {
|
|
120
|
+
resetState = true;
|
|
121
|
+
}
|
|
122
|
+
if (!resetState && isInlineNode(nodeName) && isNestedInlineNode(selection)) {
|
|
123
|
+
resetState = true;
|
|
124
|
+
}
|
|
125
|
+
if (!resetState && isNestedInTable(state)) {
|
|
126
|
+
resetState = true;
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
110
129
|
resetState = true;
|
|
111
130
|
}
|
|
112
131
|
if (resetState) {
|
|
113
132
|
resetContentMoved()(state, dispatch);
|
|
114
133
|
} else {
|
|
115
|
-
|
|
134
|
+
let newState = {
|
|
116
135
|
size: size,
|
|
117
136
|
nodeName: nodeName,
|
|
118
137
|
nodeDepth: getParentNodeDepth(selection)
|
|
119
|
-
}
|
|
138
|
+
};
|
|
139
|
+
if (isMultiSelectEnabled) {
|
|
140
|
+
var _nodeTypes;
|
|
141
|
+
newState = {
|
|
142
|
+
...newState,
|
|
143
|
+
nodeTypes: (_nodeTypes = nodeTypes) !== null && _nodeTypes !== void 0 ? _nodeTypes : nodeName,
|
|
144
|
+
hasSelectedMultipleNodes
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
updateContentMoved(newState, 'contentCut')(state, dispatch);
|
|
120
148
|
}
|
|
121
149
|
isCutEvent = false;
|
|
122
150
|
return slice;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { findParentNodeClosestToPos, findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
|
|
2
2
|
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
3
4
|
const excludedNodes = ['caption', 'layoutColumn', 'listItem', 'tableHeader', 'tableCell', 'tableRow', 'text', 'placeholder', 'unsupportedBlock', 'unsupportedInline', 'hardBreak', 'confluenceUnsupportedBlock', 'confluenceUnsupportedInline', 'taskItem', 'decisionItem'];
|
|
4
5
|
export const isExcludedNode = nodeName => excludedNodes.includes(nodeName);
|
|
5
6
|
export const isCursorSelectionAtTopLevel = selection => {
|
|
@@ -67,4 +68,26 @@ export const isEntireNestedParagraphOrHeadingSelected = selection => {
|
|
|
67
68
|
$to
|
|
68
69
|
} = selection;
|
|
69
70
|
return $from.textOffset === 0 && $to.textOffset === 0;
|
|
71
|
+
};
|
|
72
|
+
export const containsExcludedNode = content => {
|
|
73
|
+
for (let i = 0; i < content.childCount; i++) {
|
|
74
|
+
var _content$maybeChild;
|
|
75
|
+
const nodeName = ((_content$maybeChild = content.maybeChild(i)) === null || _content$maybeChild === void 0 ? void 0 : _content$maybeChild.type.name) || '';
|
|
76
|
+
if (isExcludedNode(nodeName)) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
};
|
|
82
|
+
export const getMultipleSelectionAttributes = content => {
|
|
83
|
+
const nodeTypes = [];
|
|
84
|
+
if (content.size) {
|
|
85
|
+
content.forEach(node => {
|
|
86
|
+
nodeTypes.push(node.type.name);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
nodeTypes: fg('platform_editor_track_node_types') ? [...new Set(nodeTypes)].sort().join(',') : undefined,
|
|
91
|
+
hasSelectedMultipleNodes: nodeTypes.length > 1
|
|
92
|
+
};
|
|
70
93
|
};
|
|
@@ -10,7 +10,9 @@ export var updateContentMoved = function updateContentMoved(nextState, nextActio
|
|
|
10
10
|
currentActions: [].concat(_toConsumableArray(contentMoved.currentActions), [nextAction]),
|
|
11
11
|
size: (nextState === null || nextState === void 0 ? void 0 : nextState.size) || contentMoved.size,
|
|
12
12
|
nodeName: nextState === null || nextState === void 0 ? void 0 : nextState.nodeName,
|
|
13
|
-
nodeDepth: nextState === null || nextState === void 0 ? void 0 : nextState.nodeDepth
|
|
13
|
+
nodeDepth: nextState === null || nextState === void 0 ? void 0 : nextState.nodeDepth,
|
|
14
|
+
nodeTypes: nextState === null || nextState === void 0 ? void 0 : nextState.nodeTypes,
|
|
15
|
+
hasSelectedMultipleNodes: nextState === null || nextState === void 0 ? void 0 : nextState.hasSelectedMultipleNodes
|
|
14
16
|
};
|
|
15
17
|
return {
|
|
16
18
|
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 { getParentNodeDepth, isCursorSelectionAtTopLevel, isEntireNestedParagraphOrHeadingSelected, isExcludedNode, isInlineNode, isNestedInlineNode, isNestedInTable } from './utils';
|
|
11
|
+
import { containsExcludedNode, getMultipleSelectionAttributes, getParentNodeDepth, isCursorSelectionAtTopLevel, isEntireNestedParagraphOrHeadingSelected, isExcludedNode, isInlineNode, isNestedInlineNode, isNestedInTable } 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
|
|
@@ -46,11 +50,12 @@ export var createPlugin = function createPlugin(dispatch, editorAnalyticsAPI) {
|
|
|
46
50
|
actionSubjectId: ACTION_SUBJECT_ID.NODE,
|
|
47
51
|
eventType: EVENT_TYPE.TRACK,
|
|
48
52
|
attributes: {
|
|
53
|
+
// keep nodeName from copied slice
|
|
49
54
|
nodeType: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeName,
|
|
50
55
|
nodeDepth: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeDepth,
|
|
51
|
-
destinationNodeDepth: getParentNodeDepth(state.selection)
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
destinationNodeDepth: getParentNodeDepth(state.selection),
|
|
57
|
+
nodeTypes: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.nodeTypes,
|
|
58
|
+
hasSelectedMultipleNodes: contentMoved === null || contentMoved === void 0 ? void 0 : contentMoved.hasSelectedMultipleNodes
|
|
54
59
|
}
|
|
55
60
|
})(tr);
|
|
56
61
|
|
|
@@ -69,6 +74,9 @@ export var createPlugin = function createPlugin(dispatch, editorAnalyticsAPI) {
|
|
|
69
74
|
var resetState = false;
|
|
70
75
|
var content = slice.content,
|
|
71
76
|
size = slice.size;
|
|
77
|
+
var selection = state.selection;
|
|
78
|
+
// Note: the following is not the case once `platform_editor_element_drag_and_drop_multiselect` is enabled
|
|
79
|
+
// we now want to track cut events for multiple nodes
|
|
72
80
|
// Content should be just one node, so we added a check for slice.content.childCount === 1;
|
|
73
81
|
// 1. It is possible to select a table by dragging the mouse over the table's rows.
|
|
74
82
|
// As a result, slice will contain rows without tableNode itself and the childCount will be the number of rows.
|
|
@@ -77,35 +85,57 @@ export var createPlugin = function createPlugin(dispatch, editorAnalyticsAPI) {
|
|
|
77
85
|
// the paragraph below the node. Visually only the node in between is selected, in reality, three nodes are
|
|
78
86
|
// in the slice.
|
|
79
87
|
// These cases are ignored and moveContent event won't be counted.
|
|
80
|
-
|
|
81
|
-
resetState = true;
|
|
82
|
-
}
|
|
88
|
+
var isMultiSelectEnabled = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
|
|
83
89
|
var nodeName = ((_content$firstChild2 = content.firstChild) === null || _content$firstChild2 === void 0 ? void 0 : _content$firstChild2.type.name) || '';
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (
|
|
90
|
+
var nodeTypes,
|
|
91
|
+
hasSelectedMultipleNodes = false;
|
|
92
|
+
if (content.childCount > 1) {
|
|
93
|
+
if (isMultiSelectEnabled) {
|
|
94
|
+
if (containsExcludedNode(content)) {
|
|
95
|
+
resetState = true;
|
|
96
|
+
} else {
|
|
97
|
+
var attributes = getMultipleSelectionAttributes(content);
|
|
98
|
+
nodeTypes = attributes.nodeTypes;
|
|
99
|
+
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
resetState = true;
|
|
103
|
+
}
|
|
104
|
+
} else if (content.childCount === 1) {
|
|
105
|
+
// Some nodes are not relevant as they are parts of nodes, not whole nodes (like tableCell, tableHeader instead of table node)
|
|
106
|
+
// Some nodes like lists, taskList(item), decisionList(item) requires tricky checks that we want to avoid doing.
|
|
107
|
+
// These nodes were added to excludedNodes array.
|
|
108
|
+
if (!resetState && isExcludedNode(nodeName)) {
|
|
109
|
+
resetState = true;
|
|
110
|
+
}
|
|
111
|
+
if (!resetState && !isEntireNestedParagraphOrHeadingSelected(selection)) {
|
|
112
|
+
resetState = true;
|
|
113
|
+
}
|
|
114
|
+
if (!resetState && isInlineNode(nodeName) && isNestedInlineNode(selection)) {
|
|
115
|
+
resetState = true;
|
|
116
|
+
}
|
|
117
|
+
if (!resetState && isNestedInTable(state)) {
|
|
118
|
+
resetState = true;
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
99
121
|
resetState = true;
|
|
100
122
|
}
|
|
101
123
|
if (resetState) {
|
|
102
124
|
resetContentMoved()(state, dispatch);
|
|
103
125
|
} else {
|
|
104
|
-
|
|
126
|
+
var newState = {
|
|
105
127
|
size: size,
|
|
106
128
|
nodeName: nodeName,
|
|
107
129
|
nodeDepth: getParentNodeDepth(selection)
|
|
108
|
-
}
|
|
130
|
+
};
|
|
131
|
+
if (isMultiSelectEnabled) {
|
|
132
|
+
var _nodeTypes;
|
|
133
|
+
newState = _objectSpread(_objectSpread({}, newState), {}, {
|
|
134
|
+
nodeTypes: (_nodeTypes = nodeTypes) !== null && _nodeTypes !== void 0 ? _nodeTypes : nodeName,
|
|
135
|
+
hasSelectedMultipleNodes: hasSelectedMultipleNodes
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
updateContentMoved(newState, 'contentCut')(state, dispatch);
|
|
109
139
|
}
|
|
110
140
|
isCutEvent = false;
|
|
111
141
|
return slice;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
1
2
|
import { findParentNodeClosestToPos, findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
|
|
2
3
|
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
4
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
3
5
|
var excludedNodes = ['caption', 'layoutColumn', 'listItem', 'tableHeader', 'tableCell', 'tableRow', 'text', 'placeholder', 'unsupportedBlock', 'unsupportedInline', 'hardBreak', 'confluenceUnsupportedBlock', 'confluenceUnsupportedInline', 'taskItem', 'decisionItem'];
|
|
4
6
|
export var isExcludedNode = function isExcludedNode(nodeName) {
|
|
5
7
|
return excludedNodes.includes(nodeName);
|
|
@@ -63,4 +65,26 @@ export var isEntireNestedParagraphOrHeadingSelected = function isEntireNestedPar
|
|
|
63
65
|
var $from = selection.$from,
|
|
64
66
|
$to = selection.$to;
|
|
65
67
|
return $from.textOffset === 0 && $to.textOffset === 0;
|
|
68
|
+
};
|
|
69
|
+
export var containsExcludedNode = function containsExcludedNode(content) {
|
|
70
|
+
for (var i = 0; i < content.childCount; i++) {
|
|
71
|
+
var _content$maybeChild;
|
|
72
|
+
var nodeName = ((_content$maybeChild = content.maybeChild(i)) === null || _content$maybeChild === void 0 ? void 0 : _content$maybeChild.type.name) || '';
|
|
73
|
+
if (isExcludedNode(nodeName)) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
};
|
|
79
|
+
export var getMultipleSelectionAttributes = function getMultipleSelectionAttributes(content) {
|
|
80
|
+
var nodeTypes = [];
|
|
81
|
+
if (content.size) {
|
|
82
|
+
content.forEach(function (node) {
|
|
83
|
+
nodeTypes.push(node.type.name);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
nodeTypes: fg('platform_editor_track_node_types') ? _toConsumableArray(new Set(nodeTypes)).sort().join(',') : undefined,
|
|
88
|
+
hasSelectedMultipleNodes: nodeTypes.length > 1
|
|
89
|
+
};
|
|
66
90
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
1
2
|
import type { EditorState, Selection } from '@atlaskit/editor-prosemirror/state';
|
|
2
3
|
export declare const isExcludedNode: (nodeName: string) => boolean;
|
|
3
4
|
export declare const isCursorSelectionAtTopLevel: (selection: Selection) => boolean;
|
|
@@ -6,3 +7,8 @@ export declare const isNestedInlineNode: (selection: Selection) => boolean;
|
|
|
6
7
|
export declare const isNestedInTable: (state: EditorState) => boolean;
|
|
7
8
|
export declare const getParentNodeDepth: (selection: Selection) => number;
|
|
8
9
|
export declare const isEntireNestedParagraphOrHeadingSelected: (selection: Selection) => boolean;
|
|
10
|
+
export declare const containsExcludedNode: (content: Fragment) => boolean;
|
|
11
|
+
export declare const getMultipleSelectionAttributes: (content: Fragment) => {
|
|
12
|
+
nodeTypes: string | undefined;
|
|
13
|
+
hasSelectedMultipleNodes: boolean;
|
|
14
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
1
2
|
import type { EditorState, Selection } from '@atlaskit/editor-prosemirror/state';
|
|
2
3
|
export declare const isExcludedNode: (nodeName: string) => boolean;
|
|
3
4
|
export declare const isCursorSelectionAtTopLevel: (selection: Selection) => boolean;
|
|
@@ -6,3 +7,8 @@ export declare const isNestedInlineNode: (selection: Selection) => boolean;
|
|
|
6
7
|
export declare const isNestedInTable: (state: EditorState) => boolean;
|
|
7
8
|
export declare const getParentNodeDepth: (selection: Selection) => number;
|
|
8
9
|
export declare const isEntireNestedParagraphOrHeadingSelected: (selection: Selection) => boolean;
|
|
10
|
+
export declare const containsExcludedNode: (content: Fragment) => boolean;
|
|
11
|
+
export declare const getMultipleSelectionAttributes: (content: Fragment) => {
|
|
12
|
+
nodeTypes: string | undefined;
|
|
13
|
+
hasSelectedMultipleNodes: boolean;
|
|
14
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-paste",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"description": "Paste plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@atlaskit/adf-schema": "^47.2.1",
|
|
35
35
|
"@atlaskit/code": "^15.6.9",
|
|
36
|
-
"@atlaskit/editor-common": "^99.
|
|
36
|
+
"@atlaskit/editor-common": "^99.17.0",
|
|
37
37
|
"@atlaskit/editor-markdown-transformer": "^5.15.0",
|
|
38
38
|
"@atlaskit/editor-plugin-analytics": "^1.12.0",
|
|
39
39
|
"@atlaskit/editor-plugin-annotation": "^1.28.0",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@atlaskit/editor-tables": "^2.9.0",
|
|
48
48
|
"@atlaskit/media-client": "^31.1.0",
|
|
49
49
|
"@atlaskit/media-common": "^11.8.0",
|
|
50
|
-
"@atlaskit/platform-feature-flags": "^1.
|
|
50
|
+
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
51
51
|
"@atlaskit/tmp-editor-statsig": "^2.46.0",
|
|
52
52
|
"@babel/runtime": "^7.0.0",
|
|
53
53
|
"lodash": "^4.17.21",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@af/visual-regression": "*",
|
|
62
62
|
"@atlaskit/editor-plugin-block-type": "^4.3.0",
|
|
63
|
-
"@atlaskit/editor-plugin-history": "^1.
|
|
63
|
+
"@atlaskit/editor-plugin-history": "^1.5.0",
|
|
64
64
|
"@atlaskit/editor-plugin-type-ahead": "^1.13.0",
|
|
65
65
|
"@atlaskit/ssr": "*",
|
|
66
66
|
"@atlaskit/visual-regression": "*",
|
|
@@ -137,6 +137,9 @@
|
|
|
137
137
|
},
|
|
138
138
|
"platform_editor_legacy_content_macro_insert": {
|
|
139
139
|
"type": "boolean"
|
|
140
|
+
},
|
|
141
|
+
"platform_editor_track_node_types": {
|
|
142
|
+
"type": "boolean"
|
|
140
143
|
}
|
|
141
144
|
}
|
|
142
145
|
}
|