@atlaskit/editor-plugin-block-menu 6.0.44 → 6.0.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/editor-plugin-block-menu
2
2
 
3
+ ## 6.0.45
4
+
5
+ ### Patch Changes
6
+
7
+ - [`bc0a0c36fcc31`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/bc0a0c36fcc31) -
8
+ Add transform error tracking for block menu
9
+ - Updated dependencies
10
+
3
11
  ## 6.0.44
4
12
 
5
13
  ### Patch Changes
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.transformNode = void 0;
7
7
  var _analytics = require("@atlaskit/editor-common/analytics");
8
8
  var _expand = require("@atlaskit/editor-common/expand");
9
+ var _monitoring = require("@atlaskit/editor-common/monitoring");
9
10
  var _performanceMeasures = require("@atlaskit/editor-common/performance-measures");
10
11
  var _selection = require("@atlaskit/editor-common/selection");
11
12
  var _state = require("@atlaskit/editor-prosemirror/state");
@@ -43,99 +44,122 @@ var transformNode = exports.transformNode = function transformNode(api) {
43
44
 
44
45
  // Check if source node is empty paragraph or heading
45
46
  var isEmptyLine = sourceNodes.length === 1 && (sourceNodes[0].type === nodes.paragraph || sourceNodes[0].type === nodes.heading) && (sourceNodes[0].content.size === 0 || sourceNodes[0].textContent.trim() === '');
46
- var resultNodes = (0, _transform2.convertNodesToTargetType)({
47
- sourceNodes: sourceNodes,
48
- targetNodeType: targetType,
49
- schema: tr.doc.type.schema,
50
- isNested: isNested,
51
- targetAttrs: metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs,
52
- parentNode: selectedParent
53
- });
54
- var content = resultNodes.length > 0 ? resultNodes : sourceNodes;
55
- var sliceStart = isList ? $from.pos - 1 : $from.pos;
56
-
57
- // [FEATURE FLAG: platform_editor_block_menu_expand_localid_fix]
58
- // Pre-populates the expandedState WeakMap so ExpandNodeView initializes newly created
59
- // expand/nestedExpand nodes as expanded rather than collapsed. Works in conjunction with
60
- // the localId pre-assignment in the transform steps — without a pre-assigned localId the
61
- // localId plugin's appendTransaction replaces the node object (via setNodeAttribute),
62
- // invalidating this WeakMap entry. The else branch preserves the previous behaviour.
63
- // To clean up: remove the if-else block and keep only the flag-on body.
64
- if ((0, _platformFeatureFlags.fg)('platform_editor_block_menu_expand_localid_fix')) {
65
- var expand = nodes.expand,
66
- nestedExpand = nodes.nestedExpand;
67
- content.forEach(function (node) {
68
- if (node.type === expand || node.type === nestedExpand) {
69
- _expand.expandedState.set(node, true);
70
- }
71
- });
72
- }
73
- if (preservedSelection instanceof _state.NodeSelection && preservedSelection.node.type === nodes.mediaSingle) {
74
- var _api$blockControls2;
75
- // when node is media single, use tr.replaceWith freeze editor, if modify position, tr.replaceWith creates duplicats
76
- var deleteFrom = $from.pos;
77
- var deleteTo = $to.pos;
78
- tr.delete(deleteFrom, deleteTo);
79
- // After deletion, recalculate the insertion position to ensure it's valid
80
- // especially when mediaSingle with caption is at the bottom of the document
81
- var insertPos = Math.min(deleteFrom, tr.doc.content.size);
82
- tr.insert(insertPos, content);
83
-
84
- // when we replace and insert content, we need to manually map the preserved selection
85
- // through the transaction, otherwise it will treat the selection as having been deleted
86
- // and stop preserving it
87
- var oldSize = sourceNodes.reduce(function (sum, node) {
88
- return sum + node.nodeSize;
89
- }, 0);
90
- var newSize = content.reduce(function (sum, node) {
91
- return sum + node.nodeSize;
92
- }, 0);
93
- api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.mapPreservedSelection(new _transform.Mapping([new _transform.StepMap([0, oldSize, newSize])]))({
94
- tr: tr
47
+ try {
48
+ var resultNodes = (0, _transform2.convertNodesToTargetType)({
49
+ sourceNodes: sourceNodes,
50
+ targetNodeType: targetType,
51
+ schema: tr.doc.type.schema,
52
+ isNested: isNested,
53
+ targetAttrs: metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs,
54
+ parentNode: selectedParent
95
55
  });
96
- } else {
97
- tr.replaceWith(sliceStart, $to.pos, content);
98
- }
56
+ var content = resultNodes.length > 0 ? resultNodes : sourceNodes;
57
+ var sliceStart = isList ? $from.pos - 1 : $from.pos;
99
58
 
100
- // [FEATURE FLAG: platform_editor_table_transform_selection_fix]
101
- // Fixes table cell selection not being preserved after transform to expand/layout.
102
- // When a table with CellSelection is transformed, we need to re-select the wrapper node.
103
- // To clean up: remove the if-else block and keep only the flag-on behavior.
104
- if (preservedSelection instanceof _editorTables.CellSelection && (0, _platformFeatureFlags.fg)('platform_editor_table_transform_selection_fix')) {
105
- var insertedNode = tr.doc.nodeAt($from.pos);
106
- var isSelectable = insertedNode && _state.NodeSelection.isSelectable(insertedNode);
107
- if (isSelectable) {
108
- var _api$blockControls3;
109
- var nodeSelection = _state.NodeSelection.create(tr.doc, $from.pos);
110
- tr.setSelection(nodeSelection);
59
+ // [FEATURE FLAG: platform_editor_block_menu_expand_localid_fix]
60
+ // Pre-populates the expandedState WeakMap so ExpandNodeView initializes newly created
61
+ // expand/nestedExpand nodes as expanded rather than collapsed. Works in conjunction with
62
+ // the localId pre-assignment in the transform steps without a pre-assigned localId the
63
+ // localId plugin's appendTransaction replaces the node object (via setNodeAttribute),
64
+ // invalidating this WeakMap entry. The else branch preserves the previous behaviour.
65
+ // To clean up: remove the if-else block and keep only the flag-on body.
66
+ if ((0, _platformFeatureFlags.fg)('platform_editor_block_menu_expand_localid_fix')) {
67
+ var expand = nodes.expand,
68
+ nestedExpand = nodes.nestedExpand;
69
+ content.forEach(function (node) {
70
+ if (node.type === expand || node.type === nestedExpand) {
71
+ _expand.expandedState.set(node, true);
72
+ }
73
+ });
74
+ }
75
+ if (preservedSelection instanceof _state.NodeSelection && preservedSelection.node.type === nodes.mediaSingle) {
76
+ var _api$blockControls2;
77
+ // when node is media single, use tr.replaceWith freeze editor, if modify position, tr.replaceWith creates duplicats
78
+ var deleteFrom = $from.pos;
79
+ var deleteTo = $to.pos;
80
+ tr.delete(deleteFrom, deleteTo);
81
+ // After deletion, recalculate the insertion position to ensure it's valid
82
+ // especially when mediaSingle with caption is at the bottom of the document
83
+ var insertPos = Math.min(deleteFrom, tr.doc.content.size);
84
+ tr.insert(insertPos, content);
111
85
 
112
- // Update preserved selection to match the new NodeSelection
113
- // This prevents appendTransaction from restoring the old table selection positions
114
- api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.startPreservingSelection()({
86
+ // when we replace and insert content, we need to manually map the preserved selection
87
+ // through the transaction, otherwise it will treat the selection as having been deleted
88
+ // and stop preserving it
89
+ var oldSize = sourceNodes.reduce(function (sum, node) {
90
+ return sum + node.nodeSize;
91
+ }, 0);
92
+ var newSize = content.reduce(function (sum, node) {
93
+ return sum + node.nodeSize;
94
+ }, 0);
95
+ api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.mapPreservedSelection(new _transform.Mapping([new _transform.StepMap([0, oldSize, newSize])]))({
115
96
  tr: tr
116
97
  });
98
+ } else {
99
+ tr.replaceWith(sliceStart, $to.pos, content);
117
100
  }
118
- }
119
- (0, _performanceMeasures.stopMeasure)(measureId, function (duration, startTime) {
120
- var _api$analytics;
121
- api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.attachAnalyticsEvent({
122
- action: _analytics.ACTION.TRANSFORMED,
101
+
102
+ // [FEATURE FLAG: platform_editor_table_transform_selection_fix]
103
+ // Fixes table cell selection not being preserved after transform to expand/layout.
104
+ // When a table with CellSelection is transformed, we need to re-select the wrapper node.
105
+ // To clean up: remove the if-else block and keep only the flag-on behavior.
106
+ if (preservedSelection instanceof _editorTables.CellSelection && (0, _platformFeatureFlags.fg)('platform_editor_table_transform_selection_fix')) {
107
+ var insertedNode = tr.doc.nodeAt($from.pos);
108
+ var isSelectable = insertedNode && _state.NodeSelection.isSelectable(insertedNode);
109
+ if (isSelectable) {
110
+ var _api$blockControls3;
111
+ var nodeSelection = _state.NodeSelection.create(tr.doc, $from.pos);
112
+ tr.setSelection(nodeSelection);
113
+
114
+ // Update preserved selection to match the new NodeSelection
115
+ // This prevents appendTransaction from restoring the old table selection positions
116
+ api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.startPreservingSelection()({
117
+ tr: tr
118
+ });
119
+ }
120
+ }
121
+ (0, _performanceMeasures.stopMeasure)(measureId, function (duration, startTime) {
122
+ var _api$analytics;
123
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.attachAnalyticsEvent({
124
+ action: _analytics.ACTION.TRANSFORMED,
125
+ actionSubject: _analytics.ACTION_SUBJECT.ELEMENT,
126
+ attributes: {
127
+ duration: duration,
128
+ isEmptyLine: isEmptyLine,
129
+ isNested: isNested,
130
+ sourceNodesCount: sourceNodes.length,
131
+ sourceNodesCountByType: sourceNodeTypes,
132
+ sourceNodeType: sourceNodes.length === 1 ? sourceNodes[0].type.name : 'multiple',
133
+ startTime: startTime,
134
+ targetNodeType: targetType.name,
135
+ outputNodesCount: content.length,
136
+ inputMethod: _analytics.INPUT_METHOD.BLOCK_MENU
137
+ },
138
+ eventType: _analytics.EVENT_TYPE.TRACK
139
+ })(tr);
140
+ });
141
+ } catch (error) {
142
+ var _api$analytics2;
143
+ (0, _performanceMeasures.stopMeasure)(measureId);
144
+ (0, _monitoring.logException)(error, {
145
+ location: 'editor-plugin-block-menu'
146
+ });
147
+ api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || (_api$analytics2 = _api$analytics2.actions) === null || _api$analytics2 === void 0 || _api$analytics2.attachAnalyticsEvent({
148
+ action: _analytics.ACTION.ERRORED,
123
149
  actionSubject: _analytics.ACTION_SUBJECT.ELEMENT,
150
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.TRANSFORM,
151
+ eventType: _analytics.EVENT_TYPE.OPERATIONAL,
124
152
  attributes: {
125
- duration: duration,
126
- isEmptyLine: isEmptyLine,
127
- isNested: isNested,
128
- sourceNodesCount: sourceNodes.length,
129
- sourceNodesCountByType: sourceNodeTypes,
130
- sourceNodeType: sourceNodes.length === 1 ? sourceNodes[0].type.name : 'multiple',
131
- startTime: startTime,
132
- targetNodeType: targetType.name,
133
- outputNodesCount: content.length,
134
- inputMethod: _analytics.INPUT_METHOD.BLOCK_MENU
135
- },
136
- eventType: _analytics.EVENT_TYPE.TRACK
153
+ docSize: tr.doc.nodeSize,
154
+ error: error.message,
155
+ errorStack: error.stack,
156
+ from: sourceNodes.length === 1 ? sourceNodes[0].type.name : 'multiple',
157
+ inputMethod: _analytics.INPUT_METHOD.BLOCK_MENU,
158
+ selection: preservedSelection.toJSON(),
159
+ to: targetType.name
160
+ }
137
161
  })(tr);
138
- });
162
+ }
139
163
  return tr;
140
164
  };
141
165
  };
@@ -1,5 +1,6 @@
1
- import { ACTION, ACTION_SUBJECT, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
1
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
2
  import { expandedState } from '@atlaskit/editor-common/expand';
3
+ import { logException } from '@atlaskit/editor-common/monitoring';
3
4
  import { startMeasure, stopMeasure } from '@atlaskit/editor-common/performance-measures';
4
5
  import { expandSelectionToBlockRange, getSourceNodesFromSelectionRange } from '@atlaskit/editor-common/selection';
5
6
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
@@ -39,96 +40,119 @@ export const transformNode = api => (targetType, metadata) => ({
39
40
 
40
41
  // Check if source node is empty paragraph or heading
41
42
  const isEmptyLine = sourceNodes.length === 1 && (sourceNodes[0].type === nodes.paragraph || sourceNodes[0].type === nodes.heading) && (sourceNodes[0].content.size === 0 || sourceNodes[0].textContent.trim() === '');
42
- const resultNodes = convertNodesToTargetType({
43
- sourceNodes,
44
- targetNodeType: targetType,
45
- schema: tr.doc.type.schema,
46
- isNested,
47
- targetAttrs: metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs,
48
- parentNode: selectedParent
49
- });
50
- const content = resultNodes.length > 0 ? resultNodes : sourceNodes;
51
- const sliceStart = isList ? $from.pos - 1 : $from.pos;
52
-
53
- // [FEATURE FLAG: platform_editor_block_menu_expand_localid_fix]
54
- // Pre-populates the expandedState WeakMap so ExpandNodeView initializes newly created
55
- // expand/nestedExpand nodes as expanded rather than collapsed. Works in conjunction with
56
- // the localId pre-assignment in the transform steps — without a pre-assigned localId the
57
- // localId plugin's appendTransaction replaces the node object (via setNodeAttribute),
58
- // invalidating this WeakMap entry. The else branch preserves the previous behaviour.
59
- // To clean up: remove the if-else block and keep only the flag-on body.
60
- if (fg('platform_editor_block_menu_expand_localid_fix')) {
61
- const {
62
- expand,
63
- nestedExpand
64
- } = nodes;
65
- content.forEach(node => {
66
- if (node.type === expand || node.type === nestedExpand) {
67
- expandedState.set(node, true);
68
- }
69
- });
70
- }
71
- if (preservedSelection instanceof NodeSelection && preservedSelection.node.type === nodes.mediaSingle) {
72
- var _api$blockControls2;
73
- // when node is media single, use tr.replaceWith freeze editor, if modify position, tr.replaceWith creates duplicats
74
- const deleteFrom = $from.pos;
75
- const deleteTo = $to.pos;
76
- tr.delete(deleteFrom, deleteTo);
77
- // After deletion, recalculate the insertion position to ensure it's valid
78
- // especially when mediaSingle with caption is at the bottom of the document
79
- const insertPos = Math.min(deleteFrom, tr.doc.content.size);
80
- tr.insert(insertPos, content);
81
-
82
- // when we replace and insert content, we need to manually map the preserved selection
83
- // through the transaction, otherwise it will treat the selection as having been deleted
84
- // and stop preserving it
85
- const oldSize = sourceNodes.reduce((sum, node) => sum + node.nodeSize, 0);
86
- const newSize = content.reduce((sum, node) => sum + node.nodeSize, 0);
87
- api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.commands.mapPreservedSelection(new Mapping([new StepMap([0, oldSize, newSize])]))({
88
- tr
43
+ try {
44
+ const resultNodes = convertNodesToTargetType({
45
+ sourceNodes,
46
+ targetNodeType: targetType,
47
+ schema: tr.doc.type.schema,
48
+ isNested,
49
+ targetAttrs: metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs,
50
+ parentNode: selectedParent
89
51
  });
90
- } else {
91
- tr.replaceWith(sliceStart, $to.pos, content);
92
- }
52
+ const content = resultNodes.length > 0 ? resultNodes : sourceNodes;
53
+ const sliceStart = isList ? $from.pos - 1 : $from.pos;
93
54
 
94
- // [FEATURE FLAG: platform_editor_table_transform_selection_fix]
95
- // Fixes table cell selection not being preserved after transform to expand/layout.
96
- // When a table with CellSelection is transformed, we need to re-select the wrapper node.
97
- // To clean up: remove the if-else block and keep only the flag-on behavior.
98
- if (preservedSelection instanceof CellSelection && fg('platform_editor_table_transform_selection_fix')) {
99
- const insertedNode = tr.doc.nodeAt($from.pos);
100
- const isSelectable = insertedNode && NodeSelection.isSelectable(insertedNode);
101
- if (isSelectable) {
102
- var _api$blockControls3;
103
- const nodeSelection = NodeSelection.create(tr.doc, $from.pos);
104
- tr.setSelection(nodeSelection);
55
+ // [FEATURE FLAG: platform_editor_block_menu_expand_localid_fix]
56
+ // Pre-populates the expandedState WeakMap so ExpandNodeView initializes newly created
57
+ // expand/nestedExpand nodes as expanded rather than collapsed. Works in conjunction with
58
+ // the localId pre-assignment in the transform steps without a pre-assigned localId the
59
+ // localId plugin's appendTransaction replaces the node object (via setNodeAttribute),
60
+ // invalidating this WeakMap entry. The else branch preserves the previous behaviour.
61
+ // To clean up: remove the if-else block and keep only the flag-on body.
62
+ if (fg('platform_editor_block_menu_expand_localid_fix')) {
63
+ const {
64
+ expand,
65
+ nestedExpand
66
+ } = nodes;
67
+ content.forEach(node => {
68
+ if (node.type === expand || node.type === nestedExpand) {
69
+ expandedState.set(node, true);
70
+ }
71
+ });
72
+ }
73
+ if (preservedSelection instanceof NodeSelection && preservedSelection.node.type === nodes.mediaSingle) {
74
+ var _api$blockControls2;
75
+ // when node is media single, use tr.replaceWith freeze editor, if modify position, tr.replaceWith creates duplicats
76
+ const deleteFrom = $from.pos;
77
+ const deleteTo = $to.pos;
78
+ tr.delete(deleteFrom, deleteTo);
79
+ // After deletion, recalculate the insertion position to ensure it's valid
80
+ // especially when mediaSingle with caption is at the bottom of the document
81
+ const insertPos = Math.min(deleteFrom, tr.doc.content.size);
82
+ tr.insert(insertPos, content);
105
83
 
106
- // Update preserved selection to match the new NodeSelection
107
- // This prevents appendTransaction from restoring the old table selection positions
108
- api === null || api === void 0 ? void 0 : (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands.startPreservingSelection()({
84
+ // when we replace and insert content, we need to manually map the preserved selection
85
+ // through the transaction, otherwise it will treat the selection as having been deleted
86
+ // and stop preserving it
87
+ const oldSize = sourceNodes.reduce((sum, node) => sum + node.nodeSize, 0);
88
+ const newSize = content.reduce((sum, node) => sum + node.nodeSize, 0);
89
+ api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.commands.mapPreservedSelection(new Mapping([new StepMap([0, oldSize, newSize])]))({
109
90
  tr
110
91
  });
92
+ } else {
93
+ tr.replaceWith(sliceStart, $to.pos, content);
111
94
  }
112
- }
113
- stopMeasure(measureId, (duration, startTime) => {
114
- var _api$analytics, _api$analytics$action;
115
- api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : (_api$analytics$action = _api$analytics.actions) === null || _api$analytics$action === void 0 ? void 0 : _api$analytics$action.attachAnalyticsEvent({
116
- action: ACTION.TRANSFORMED,
95
+
96
+ // [FEATURE FLAG: platform_editor_table_transform_selection_fix]
97
+ // Fixes table cell selection not being preserved after transform to expand/layout.
98
+ // When a table with CellSelection is transformed, we need to re-select the wrapper node.
99
+ // To clean up: remove the if-else block and keep only the flag-on behavior.
100
+ if (preservedSelection instanceof CellSelection && fg('platform_editor_table_transform_selection_fix')) {
101
+ const insertedNode = tr.doc.nodeAt($from.pos);
102
+ const isSelectable = insertedNode && NodeSelection.isSelectable(insertedNode);
103
+ if (isSelectable) {
104
+ var _api$blockControls3;
105
+ const nodeSelection = NodeSelection.create(tr.doc, $from.pos);
106
+ tr.setSelection(nodeSelection);
107
+
108
+ // Update preserved selection to match the new NodeSelection
109
+ // This prevents appendTransaction from restoring the old table selection positions
110
+ api === null || api === void 0 ? void 0 : (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands.startPreservingSelection()({
111
+ tr
112
+ });
113
+ }
114
+ }
115
+ stopMeasure(measureId, (duration, startTime) => {
116
+ var _api$analytics, _api$analytics$action;
117
+ api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : (_api$analytics$action = _api$analytics.actions) === null || _api$analytics$action === void 0 ? void 0 : _api$analytics$action.attachAnalyticsEvent({
118
+ action: ACTION.TRANSFORMED,
119
+ actionSubject: ACTION_SUBJECT.ELEMENT,
120
+ attributes: {
121
+ duration,
122
+ isEmptyLine,
123
+ isNested,
124
+ sourceNodesCount: sourceNodes.length,
125
+ sourceNodesCountByType: sourceNodeTypes,
126
+ sourceNodeType: sourceNodes.length === 1 ? sourceNodes[0].type.name : 'multiple',
127
+ startTime,
128
+ targetNodeType: targetType.name,
129
+ outputNodesCount: content.length,
130
+ inputMethod: INPUT_METHOD.BLOCK_MENU
131
+ },
132
+ eventType: EVENT_TYPE.TRACK
133
+ })(tr);
134
+ });
135
+ } catch (error) {
136
+ var _api$analytics2, _api$analytics2$actio;
137
+ stopMeasure(measureId);
138
+ logException(error, {
139
+ location: 'editor-plugin-block-menu'
140
+ });
141
+ api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : (_api$analytics2$actio = _api$analytics2.actions) === null || _api$analytics2$actio === void 0 ? void 0 : _api$analytics2$actio.attachAnalyticsEvent({
142
+ action: ACTION.ERRORED,
117
143
  actionSubject: ACTION_SUBJECT.ELEMENT,
144
+ actionSubjectId: ACTION_SUBJECT_ID.TRANSFORM,
145
+ eventType: EVENT_TYPE.OPERATIONAL,
118
146
  attributes: {
119
- duration,
120
- isEmptyLine,
121
- isNested,
122
- sourceNodesCount: sourceNodes.length,
123
- sourceNodesCountByType: sourceNodeTypes,
124
- sourceNodeType: sourceNodes.length === 1 ? sourceNodes[0].type.name : 'multiple',
125
- startTime,
126
- targetNodeType: targetType.name,
127
- outputNodesCount: content.length,
128
- inputMethod: INPUT_METHOD.BLOCK_MENU
129
- },
130
- eventType: EVENT_TYPE.TRACK
147
+ docSize: tr.doc.nodeSize,
148
+ error: error.message,
149
+ errorStack: error.stack,
150
+ from: sourceNodes.length === 1 ? sourceNodes[0].type.name : 'multiple',
151
+ inputMethod: INPUT_METHOD.BLOCK_MENU,
152
+ selection: preservedSelection.toJSON(),
153
+ to: targetType.name
154
+ }
131
155
  })(tr);
132
- });
156
+ }
133
157
  return tr;
134
158
  };
@@ -1,5 +1,6 @@
1
- import { ACTION, ACTION_SUBJECT, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
1
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
2
  import { expandedState } from '@atlaskit/editor-common/expand';
3
+ import { logException } from '@atlaskit/editor-common/monitoring';
3
4
  import { startMeasure, stopMeasure } from '@atlaskit/editor-common/performance-measures';
4
5
  import { expandSelectionToBlockRange, getSourceNodesFromSelectionRange } from '@atlaskit/editor-common/selection';
5
6
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
@@ -37,99 +38,122 @@ export var transformNode = function transformNode(api) {
37
38
 
38
39
  // Check if source node is empty paragraph or heading
39
40
  var isEmptyLine = sourceNodes.length === 1 && (sourceNodes[0].type === nodes.paragraph || sourceNodes[0].type === nodes.heading) && (sourceNodes[0].content.size === 0 || sourceNodes[0].textContent.trim() === '');
40
- var resultNodes = convertNodesToTargetType({
41
- sourceNodes: sourceNodes,
42
- targetNodeType: targetType,
43
- schema: tr.doc.type.schema,
44
- isNested: isNested,
45
- targetAttrs: metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs,
46
- parentNode: selectedParent
47
- });
48
- var content = resultNodes.length > 0 ? resultNodes : sourceNodes;
49
- var sliceStart = isList ? $from.pos - 1 : $from.pos;
50
-
51
- // [FEATURE FLAG: platform_editor_block_menu_expand_localid_fix]
52
- // Pre-populates the expandedState WeakMap so ExpandNodeView initializes newly created
53
- // expand/nestedExpand nodes as expanded rather than collapsed. Works in conjunction with
54
- // the localId pre-assignment in the transform steps — without a pre-assigned localId the
55
- // localId plugin's appendTransaction replaces the node object (via setNodeAttribute),
56
- // invalidating this WeakMap entry. The else branch preserves the previous behaviour.
57
- // To clean up: remove the if-else block and keep only the flag-on body.
58
- if (fg('platform_editor_block_menu_expand_localid_fix')) {
59
- var expand = nodes.expand,
60
- nestedExpand = nodes.nestedExpand;
61
- content.forEach(function (node) {
62
- if (node.type === expand || node.type === nestedExpand) {
63
- expandedState.set(node, true);
64
- }
65
- });
66
- }
67
- if (preservedSelection instanceof NodeSelection && preservedSelection.node.type === nodes.mediaSingle) {
68
- var _api$blockControls2;
69
- // when node is media single, use tr.replaceWith freeze editor, if modify position, tr.replaceWith creates duplicats
70
- var deleteFrom = $from.pos;
71
- var deleteTo = $to.pos;
72
- tr.delete(deleteFrom, deleteTo);
73
- // After deletion, recalculate the insertion position to ensure it's valid
74
- // especially when mediaSingle with caption is at the bottom of the document
75
- var insertPos = Math.min(deleteFrom, tr.doc.content.size);
76
- tr.insert(insertPos, content);
77
-
78
- // when we replace and insert content, we need to manually map the preserved selection
79
- // through the transaction, otherwise it will treat the selection as having been deleted
80
- // and stop preserving it
81
- var oldSize = sourceNodes.reduce(function (sum, node) {
82
- return sum + node.nodeSize;
83
- }, 0);
84
- var newSize = content.reduce(function (sum, node) {
85
- return sum + node.nodeSize;
86
- }, 0);
87
- api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.mapPreservedSelection(new Mapping([new StepMap([0, oldSize, newSize])]))({
88
- tr: tr
41
+ try {
42
+ var resultNodes = convertNodesToTargetType({
43
+ sourceNodes: sourceNodes,
44
+ targetNodeType: targetType,
45
+ schema: tr.doc.type.schema,
46
+ isNested: isNested,
47
+ targetAttrs: metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs,
48
+ parentNode: selectedParent
89
49
  });
90
- } else {
91
- tr.replaceWith(sliceStart, $to.pos, content);
92
- }
50
+ var content = resultNodes.length > 0 ? resultNodes : sourceNodes;
51
+ var sliceStart = isList ? $from.pos - 1 : $from.pos;
93
52
 
94
- // [FEATURE FLAG: platform_editor_table_transform_selection_fix]
95
- // Fixes table cell selection not being preserved after transform to expand/layout.
96
- // When a table with CellSelection is transformed, we need to re-select the wrapper node.
97
- // To clean up: remove the if-else block and keep only the flag-on behavior.
98
- if (preservedSelection instanceof CellSelection && fg('platform_editor_table_transform_selection_fix')) {
99
- var insertedNode = tr.doc.nodeAt($from.pos);
100
- var isSelectable = insertedNode && NodeSelection.isSelectable(insertedNode);
101
- if (isSelectable) {
102
- var _api$blockControls3;
103
- var nodeSelection = NodeSelection.create(tr.doc, $from.pos);
104
- tr.setSelection(nodeSelection);
53
+ // [FEATURE FLAG: platform_editor_block_menu_expand_localid_fix]
54
+ // Pre-populates the expandedState WeakMap so ExpandNodeView initializes newly created
55
+ // expand/nestedExpand nodes as expanded rather than collapsed. Works in conjunction with
56
+ // the localId pre-assignment in the transform steps without a pre-assigned localId the
57
+ // localId plugin's appendTransaction replaces the node object (via setNodeAttribute),
58
+ // invalidating this WeakMap entry. The else branch preserves the previous behaviour.
59
+ // To clean up: remove the if-else block and keep only the flag-on body.
60
+ if (fg('platform_editor_block_menu_expand_localid_fix')) {
61
+ var expand = nodes.expand,
62
+ nestedExpand = nodes.nestedExpand;
63
+ content.forEach(function (node) {
64
+ if (node.type === expand || node.type === nestedExpand) {
65
+ expandedState.set(node, true);
66
+ }
67
+ });
68
+ }
69
+ if (preservedSelection instanceof NodeSelection && preservedSelection.node.type === nodes.mediaSingle) {
70
+ var _api$blockControls2;
71
+ // when node is media single, use tr.replaceWith freeze editor, if modify position, tr.replaceWith creates duplicats
72
+ var deleteFrom = $from.pos;
73
+ var deleteTo = $to.pos;
74
+ tr.delete(deleteFrom, deleteTo);
75
+ // After deletion, recalculate the insertion position to ensure it's valid
76
+ // especially when mediaSingle with caption is at the bottom of the document
77
+ var insertPos = Math.min(deleteFrom, tr.doc.content.size);
78
+ tr.insert(insertPos, content);
105
79
 
106
- // Update preserved selection to match the new NodeSelection
107
- // This prevents appendTransaction from restoring the old table selection positions
108
- api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.startPreservingSelection()({
80
+ // when we replace and insert content, we need to manually map the preserved selection
81
+ // through the transaction, otherwise it will treat the selection as having been deleted
82
+ // and stop preserving it
83
+ var oldSize = sourceNodes.reduce(function (sum, node) {
84
+ return sum + node.nodeSize;
85
+ }, 0);
86
+ var newSize = content.reduce(function (sum, node) {
87
+ return sum + node.nodeSize;
88
+ }, 0);
89
+ api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.mapPreservedSelection(new Mapping([new StepMap([0, oldSize, newSize])]))({
109
90
  tr: tr
110
91
  });
92
+ } else {
93
+ tr.replaceWith(sliceStart, $to.pos, content);
111
94
  }
112
- }
113
- stopMeasure(measureId, function (duration, startTime) {
114
- var _api$analytics;
115
- api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.attachAnalyticsEvent({
116
- action: ACTION.TRANSFORMED,
95
+
96
+ // [FEATURE FLAG: platform_editor_table_transform_selection_fix]
97
+ // Fixes table cell selection not being preserved after transform to expand/layout.
98
+ // When a table with CellSelection is transformed, we need to re-select the wrapper node.
99
+ // To clean up: remove the if-else block and keep only the flag-on behavior.
100
+ if (preservedSelection instanceof CellSelection && fg('platform_editor_table_transform_selection_fix')) {
101
+ var insertedNode = tr.doc.nodeAt($from.pos);
102
+ var isSelectable = insertedNode && NodeSelection.isSelectable(insertedNode);
103
+ if (isSelectable) {
104
+ var _api$blockControls3;
105
+ var nodeSelection = NodeSelection.create(tr.doc, $from.pos);
106
+ tr.setSelection(nodeSelection);
107
+
108
+ // Update preserved selection to match the new NodeSelection
109
+ // This prevents appendTransaction from restoring the old table selection positions
110
+ api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.startPreservingSelection()({
111
+ tr: tr
112
+ });
113
+ }
114
+ }
115
+ stopMeasure(measureId, function (duration, startTime) {
116
+ var _api$analytics;
117
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.attachAnalyticsEvent({
118
+ action: ACTION.TRANSFORMED,
119
+ actionSubject: ACTION_SUBJECT.ELEMENT,
120
+ attributes: {
121
+ duration: duration,
122
+ isEmptyLine: isEmptyLine,
123
+ isNested: isNested,
124
+ sourceNodesCount: sourceNodes.length,
125
+ sourceNodesCountByType: sourceNodeTypes,
126
+ sourceNodeType: sourceNodes.length === 1 ? sourceNodes[0].type.name : 'multiple',
127
+ startTime: startTime,
128
+ targetNodeType: targetType.name,
129
+ outputNodesCount: content.length,
130
+ inputMethod: INPUT_METHOD.BLOCK_MENU
131
+ },
132
+ eventType: EVENT_TYPE.TRACK
133
+ })(tr);
134
+ });
135
+ } catch (error) {
136
+ var _api$analytics2;
137
+ stopMeasure(measureId);
138
+ logException(error, {
139
+ location: 'editor-plugin-block-menu'
140
+ });
141
+ api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || (_api$analytics2 = _api$analytics2.actions) === null || _api$analytics2 === void 0 || _api$analytics2.attachAnalyticsEvent({
142
+ action: ACTION.ERRORED,
117
143
  actionSubject: ACTION_SUBJECT.ELEMENT,
144
+ actionSubjectId: ACTION_SUBJECT_ID.TRANSFORM,
145
+ eventType: EVENT_TYPE.OPERATIONAL,
118
146
  attributes: {
119
- duration: duration,
120
- isEmptyLine: isEmptyLine,
121
- isNested: isNested,
122
- sourceNodesCount: sourceNodes.length,
123
- sourceNodesCountByType: sourceNodeTypes,
124
- sourceNodeType: sourceNodes.length === 1 ? sourceNodes[0].type.name : 'multiple',
125
- startTime: startTime,
126
- targetNodeType: targetType.name,
127
- outputNodesCount: content.length,
128
- inputMethod: INPUT_METHOD.BLOCK_MENU
129
- },
130
- eventType: EVENT_TYPE.TRACK
147
+ docSize: tr.doc.nodeSize,
148
+ error: error.message,
149
+ errorStack: error.stack,
150
+ from: sourceNodes.length === 1 ? sourceNodes[0].type.name : 'multiple',
151
+ inputMethod: INPUT_METHOD.BLOCK_MENU,
152
+ selection: preservedSelection.toJSON(),
153
+ to: targetType.name
154
+ }
131
155
  })(tr);
132
- });
156
+ }
133
157
  return tr;
134
158
  };
135
159
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-menu",
3
- "version": "6.0.44",
3
+ "version": "6.0.45",
4
4
  "description": "BlockMenu plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -46,7 +46,7 @@
46
46
  "@atlaskit/platform-feature-flags-react": "^0.4.0",
47
47
  "@atlaskit/primitives": "^18.0.0",
48
48
  "@atlaskit/prosemirror-history": "^0.2.0",
49
- "@atlaskit/tmp-editor-statsig": "^26.0.0",
49
+ "@atlaskit/tmp-editor-statsig": "^27.1.0",
50
50
  "@atlaskit/tokens": "^11.0.0",
51
51
  "@babel/runtime": "^7.0.0",
52
52
  "bind-event-listener": "^3.0.0"