@atlaskit/editor-plugin-media 1.31.7 → 1.31.8

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,15 @@
1
1
  # @atlaskit/editor-plugin-media
2
2
 
3
+ ## 1.31.8
4
+
5
+ ### Patch Changes
6
+
7
+ - [#141594](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/141594)
8
+ [`3f6b2eb7bd493`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/3f6b2eb7bd493) -
9
+ [ux] [ED-24867] This change moves nesting codeblocks and media in blockquotes via insertion
10
+ methods behind an experiment gate.
11
+ - Updated dependencies
12
+
3
13
  ## 1.31.7
4
14
 
5
15
  ### Patch Changes
@@ -32,6 +32,7 @@ var _utils2 = require("@atlaskit/editor-prosemirror/utils");
32
32
  var _view2 = require("@atlaskit/editor-prosemirror/view");
33
33
  var _cellSelection = require("@atlaskit/editor-tables/cell-selection");
34
34
  var _mediaCommon = require("@atlaskit/media-common");
35
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
35
36
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
36
37
  var _helpers = _interopRequireWildcard(require("../commands/helpers"));
37
38
  var helpers = _helpers;
@@ -126,9 +127,10 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
126
127
  * called when we insert a new file via the picker (connected via pickerfacade)
127
128
  */
128
129
  (0, _defineProperty2.default)(this, "insertFile", function (mediaState, onMediaStateChanged, pickerType) {
129
- var _this$pluginInjection, _mediaState$collectio, _this$pluginInjection2;
130
+ var _this$pluginInjection, _this$pluginInjection2, _mediaState$collectio, _this$pluginInjection3;
130
131
  var state = _this.view.state;
131
132
  var editorAnalyticsAPI = (_this$pluginInjection = _this.pluginInjectionApi) === null || _this$pluginInjection === void 0 || (_this$pluginInjection = _this$pluginInjection.analytics) === null || _this$pluginInjection === void 0 ? void 0 : _this$pluginInjection.actions;
133
+ var isNestingInQuoteSupported = ((_this$pluginInjection2 = _this.pluginInjectionApi) === null || _this$pluginInjection2 === void 0 || (_this$pluginInjection2 = _this$pluginInjection2.featureFlags) === null || _this$pluginInjection2 === void 0 || (_this$pluginInjection2 = _this$pluginInjection2.sharedState.currentState()) === null || _this$pluginInjection2 === void 0 ? void 0 : _this$pluginInjection2.nestMediaAndCodeblockInQuote) || (0, _platformFeatureFlags.fg)('editor_nest_media_and_codeblock_in_quotes_jira');
132
134
  var mediaStateWithContext = _objectSpread(_objectSpread({}, mediaState), {}, {
133
135
  contextId: _this.contextIdentifierProvider ? _this.contextIdentifierProvider.objectId : undefined
134
136
  });
@@ -155,11 +157,11 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
155
157
  break;
156
158
  case 'block':
157
159
  // read width state right before inserting to get up-to-date and define values
158
- var widthPluginState = (_this$pluginInjection2 = _this.pluginInjectionApi) === null || _this$pluginInjection2 === void 0 || (_this$pluginInjection2 = _this$pluginInjection2.width) === null || _this$pluginInjection2 === void 0 ? void 0 : _this$pluginInjection2.sharedState.currentState();
159
- (0, _mediaSingle2.insertMediaSingleNode)(_this.view, mediaStateWithContext, _this.getInputMethod(pickerType), collection, _this.mediaOptions && _this.mediaOptions.alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, _this.onNodeInserted);
160
+ var widthPluginState = (_this$pluginInjection3 = _this.pluginInjectionApi) === null || _this$pluginInjection3 === void 0 || (_this$pluginInjection3 = _this$pluginInjection3.width) === null || _this$pluginInjection3 === void 0 ? void 0 : _this$pluginInjection3.sharedState.currentState();
161
+ (0, _mediaSingle2.insertMediaSingleNode)(_this.view, mediaStateWithContext, _this.getInputMethod(pickerType), collection, _this.mediaOptions && _this.mediaOptions.alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, _this.onNodeInserted, isNestingInQuoteSupported);
160
162
  break;
161
163
  case 'group':
162
- (0, _mediaFiles.insertMediaGroupNode)(editorAnalyticsAPI)(_this.view, [mediaStateWithContext], collection, _this.getInputMethod(pickerType));
164
+ (0, _mediaFiles.insertMediaGroupNode)(editorAnalyticsAPI)(_this.view, [mediaStateWithContext], collection, _this.getInputMethod(pickerType), isNestingInQuoteSupported);
163
165
  break;
164
166
  }
165
167
 
@@ -598,8 +600,8 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
598
600
  }, {
599
601
  key: "contextIdentifierProvider",
600
602
  get: function get() {
601
- var _this$pluginInjection3;
602
- return (_this$pluginInjection3 = this.pluginInjectionApi) === null || _this$pluginInjection3 === void 0 || (_this$pluginInjection3 = _this$pluginInjection3.contextIdentifier) === null || _this$pluginInjection3 === void 0 || (_this$pluginInjection3 = _this$pluginInjection3.sharedState.currentState()) === null || _this$pluginInjection3 === void 0 ? void 0 : _this$pluginInjection3.contextIdentifierProvider;
603
+ var _this$pluginInjection4;
604
+ return (_this$pluginInjection4 = this.pluginInjectionApi) === null || _this$pluginInjection4 === void 0 || (_this$pluginInjection4 = _this$pluginInjection4.contextIdentifier) === null || _this$pluginInjection4 === void 0 || (_this$pluginInjection4 = _this$pluginInjection4.sharedState.currentState()) === null || _this$pluginInjection4 === void 0 ? void 0 : _this$pluginInjection4.contextIdentifierProvider;
603
605
  }
604
606
  }, {
605
607
  key: "selectLastAddedMediaNode",
@@ -146,7 +146,7 @@ var insertMediaInlineNode = exports.insertMediaInlineNode = function insertMedia
146
146
  * @param collection Collection for the media to be added
147
147
  */
148
148
  var insertMediaGroupNode = exports.insertMediaGroupNode = function insertMediaGroupNode(editorAnalyticsAPI) {
149
- return function (view, mediaStates, collection, inputMethod) {
149
+ return function (view, mediaStates, collection, inputMethod, isNestingInQuoteSupported) {
150
150
  var state = view.state,
151
151
  dispatch = view.dispatch;
152
152
  var tr = state.tr,
@@ -168,6 +168,17 @@ var insertMediaGroupNode = exports.insertMediaGroupNode = function insertMediaGr
168
168
  var withParagraph = shouldAppendParagraph(state, nodeAtInsertionPoint);
169
169
  var content = parent.type === schema.nodes.mediaGroup ? mediaNodes // If parent is a mediaGroup do not wrap items again.
170
170
  : [schema.nodes.mediaGroup.createChecked({}, mediaNodes)];
171
+
172
+ /** we only allow the insertion of media groups inside a blockquote if nesting in quotes is supported */
173
+ var grandParentNode = state.selection.$from.node(-1);
174
+ var grandParentNodeType = grandParentNode === null || grandParentNode === void 0 ? void 0 : grandParentNode.type.name;
175
+ if (grandParentNodeType === 'blockquote' && !isNestingInQuoteSupported) {
176
+ var grandparentEndPos = state.selection.$from.start(-1) + grandParentNode.nodeSize - 1;
177
+ (0, _utils2.safeInsert)(content[0], grandparentEndPos)(tr).scrollIntoView();
178
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent(getInsertMediaGroupAnalytics(mediaStates, inputMethod))(tr);
179
+ dispatch(tr);
180
+ return;
181
+ }
171
182
  if (shouldSplit) {
172
183
  content = withParagraph ? content.concat(paragraph.create()) : content;
173
184
  // delete the selection or empty paragraph
@@ -41,6 +41,7 @@ function shouldAddParagraph(state) {
41
41
  function insertNodesWithOptionalParagraph(nodes) {
42
42
  var analyticsAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
43
43
  var editorAnalyticsAPI = arguments.length > 2 ? arguments[2] : undefined;
44
+ var isNestingInQuoteSupported = arguments.length > 3 ? arguments[3] : undefined;
44
45
  return function (state, dispatch) {
45
46
  var tr = state.tr,
46
47
  schema = state.schema;
@@ -54,7 +55,14 @@ function insertNodesWithOptionalParagraph(nodes) {
54
55
  nodes.push(paragraph.create());
55
56
  openEnd = 1;
56
57
  }
57
- if (state.selection.empty) {
58
+
59
+ /** we only allow the insertion of media singles inside a blockquote if nesting in quotes is supported */
60
+ var grandParentNode = state.selection.$from.node(-1);
61
+ var grandParentNodeType = grandParentNode === null || grandParentNode === void 0 ? void 0 : grandParentNode.type.name;
62
+ if (grandParentNodeType === 'blockquote' && !isNestingInQuoteSupported) {
63
+ var grandparentEndPos = state.selection.$from.start(-1) + grandParentNode.nodeSize - 1;
64
+ (0, _utils2.safeInsert)(nodes[0], grandparentEndPos)(tr).scrollIntoView();
65
+ } else if (state.selection.empty) {
58
66
  tr.insert(state.selection.from, nodes);
59
67
  // Set the cursor position at the end of the insertion
60
68
  var endPos = state.selection.from + nodes.reduce(function (totalSize, currNode) {
@@ -79,7 +87,7 @@ function insertNodesWithOptionalParagraph(nodes) {
79
87
  var isMediaSingle = exports.isMediaSingle = function isMediaSingle(schema, fileMimeType) {
80
88
  return !!schema.nodes.mediaSingle && (0, _isType.isImage)(fileMimeType);
81
89
  };
82
- var insertMediaAsMediaSingle = exports.insertMediaAsMediaSingle = function insertMediaAsMediaSingle(view, node, inputMethod, editorAnalyticsAPI) {
90
+ var insertMediaAsMediaSingle = exports.insertMediaAsMediaSingle = function insertMediaAsMediaSingle(view, node, inputMethod, editorAnalyticsAPI, isNestingInQuoteSupported) {
83
91
  var _node$attrs$width;
84
92
  var state = view.state,
85
93
  dispatch = view.dispatch;
@@ -107,7 +115,7 @@ var insertMediaAsMediaSingle = exports.insertMediaAsMediaSingle = function inser
107
115
  inputMethod: inputMethod,
108
116
  fileExtension: node.attrs.__fileMimeType
109
117
  };
110
- return insertNodesWithOptionalParagraph(nodes, analyticsAttributes, editorAnalyticsAPI)(state, dispatch);
118
+ return insertNodesWithOptionalParagraph(nodes, analyticsAttributes, editorAnalyticsAPI, isNestingInQuoteSupported)(state, dispatch);
111
119
  };
112
120
  var getFileExtension = function getFileExtension(fileName) {
113
121
  if (fileName) {
@@ -116,7 +124,7 @@ var getFileExtension = function getFileExtension(fileName) {
116
124
  }
117
125
  return undefined;
118
126
  };
119
- var insertMediaSingleNode = exports.insertMediaSingleNode = function insertMediaSingleNode(view, mediaState, inputMethod, collection, alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, onNodeInserted) {
127
+ var insertMediaSingleNode = exports.insertMediaSingleNode = function insertMediaSingleNode(view, mediaState, inputMethod, collection, alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, onNodeInserted, isNestingInQuoteSupported) {
120
128
  var _state$selection$$fro;
121
129
  if (collection === undefined) {
122
130
  return false;
@@ -145,7 +153,7 @@ var insertMediaSingleNode = exports.insertMediaSingleNode = function insertMedia
145
153
  insertNodesWithOptionalParagraph([node], {
146
154
  fileExtension: fileExtension,
147
155
  inputMethod: inputMethod
148
- }, editorAnalyticsAPI)(state, dispatch);
156
+ }, editorAnalyticsAPI, isNestingInQuoteSupported)(state, dispatch);
149
157
  } else {
150
158
  var tr = null;
151
159
  tr = (0, _insert.safeInsert)(node, state.selection.from)(state.tr);
@@ -14,6 +14,7 @@ import { findDomRefAtPos, findParentNodeOfType, findSelectedNodeOfType, isNodeSe
14
14
  import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
15
15
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
16
16
  import { getMediaFeatureFlag } from '@atlaskit/media-common';
17
+ import { fg } from '@atlaskit/platform-feature-flags';
17
18
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
18
19
  import * as helpers from '../commands/helpers';
19
20
  import { updateMediaNodeAttrs } from '../commands/helpers';
@@ -99,11 +100,12 @@ export class MediaPluginStateImplementation {
99
100
  * called when we insert a new file via the picker (connected via pickerfacade)
100
101
  */
101
102
  _defineProperty(this, "insertFile", (mediaState, onMediaStateChanged, pickerType) => {
102
- var _this$pluginInjection, _this$pluginInjection2, _mediaState$collectio, _this$pluginInjection3, _this$pluginInjection4;
103
+ var _this$pluginInjection, _this$pluginInjection2, _this$pluginInjection3, _this$pluginInjection4, _this$pluginInjection5, _mediaState$collectio, _this$pluginInjection6, _this$pluginInjection7;
103
104
  const {
104
105
  state
105
106
  } = this.view;
106
107
  const editorAnalyticsAPI = (_this$pluginInjection = this.pluginInjectionApi) === null || _this$pluginInjection === void 0 ? void 0 : (_this$pluginInjection2 = _this$pluginInjection.analytics) === null || _this$pluginInjection2 === void 0 ? void 0 : _this$pluginInjection2.actions;
108
+ const isNestingInQuoteSupported = ((_this$pluginInjection3 = this.pluginInjectionApi) === null || _this$pluginInjection3 === void 0 ? void 0 : (_this$pluginInjection4 = _this$pluginInjection3.featureFlags) === null || _this$pluginInjection4 === void 0 ? void 0 : (_this$pluginInjection5 = _this$pluginInjection4.sharedState.currentState()) === null || _this$pluginInjection5 === void 0 ? void 0 : _this$pluginInjection5.nestMediaAndCodeblockInQuote) || fg('editor_nest_media_and_codeblock_in_quotes_jira');
107
109
  const mediaStateWithContext = {
108
110
  ...mediaState,
109
111
  contextId: this.contextIdentifierProvider ? this.contextIdentifierProvider.objectId : undefined
@@ -129,11 +131,11 @@ export class MediaPluginStateImplementation {
129
131
  break;
130
132
  case 'block':
131
133
  // read width state right before inserting to get up-to-date and define values
132
- const widthPluginState = (_this$pluginInjection3 = this.pluginInjectionApi) === null || _this$pluginInjection3 === void 0 ? void 0 : (_this$pluginInjection4 = _this$pluginInjection3.width) === null || _this$pluginInjection4 === void 0 ? void 0 : _this$pluginInjection4.sharedState.currentState();
133
- insertMediaSingleNode(this.view, mediaStateWithContext, this.getInputMethod(pickerType), collection, this.mediaOptions && this.mediaOptions.alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, this.onNodeInserted);
134
+ const widthPluginState = (_this$pluginInjection6 = this.pluginInjectionApi) === null || _this$pluginInjection6 === void 0 ? void 0 : (_this$pluginInjection7 = _this$pluginInjection6.width) === null || _this$pluginInjection7 === void 0 ? void 0 : _this$pluginInjection7.sharedState.currentState();
135
+ insertMediaSingleNode(this.view, mediaStateWithContext, this.getInputMethod(pickerType), collection, this.mediaOptions && this.mediaOptions.alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, this.onNodeInserted, isNestingInQuoteSupported);
134
136
  break;
135
137
  case 'group':
136
- insertMediaGroupNode(editorAnalyticsAPI)(this.view, [mediaStateWithContext], collection, this.getInputMethod(pickerType));
138
+ insertMediaGroupNode(editorAnalyticsAPI)(this.view, [mediaStateWithContext], collection, this.getInputMethod(pickerType), isNestingInQuoteSupported);
137
139
  break;
138
140
  }
139
141
 
@@ -522,8 +524,8 @@ export class MediaPluginStateImplementation {
522
524
  return;
523
525
  }
524
526
  get contextIdentifierProvider() {
525
- var _this$pluginInjection5, _this$pluginInjection6, _this$pluginInjection7;
526
- return (_this$pluginInjection5 = this.pluginInjectionApi) === null || _this$pluginInjection5 === void 0 ? void 0 : (_this$pluginInjection6 = _this$pluginInjection5.contextIdentifier) === null || _this$pluginInjection6 === void 0 ? void 0 : (_this$pluginInjection7 = _this$pluginInjection6.sharedState.currentState()) === null || _this$pluginInjection7 === void 0 ? void 0 : _this$pluginInjection7.contextIdentifierProvider;
527
+ var _this$pluginInjection8, _this$pluginInjection9, _this$pluginInjection10;
528
+ return (_this$pluginInjection8 = this.pluginInjectionApi) === null || _this$pluginInjection8 === void 0 ? void 0 : (_this$pluginInjection9 = _this$pluginInjection8.contextIdentifier) === null || _this$pluginInjection9 === void 0 ? void 0 : (_this$pluginInjection10 = _this$pluginInjection9.sharedState.currentState()) === null || _this$pluginInjection10 === void 0 ? void 0 : _this$pluginInjection10.contextIdentifierProvider;
527
529
  }
528
530
  selectLastAddedMediaNode() {
529
531
  // if lastAddedMediaSingleFileIds is empty exit because there are no added media single nodes to be selected
@@ -153,7 +153,7 @@ export const insertMediaInlineNode = editorAnalyticsAPI => (view, mediaState, co
153
153
  * @param mediaStates Media files to be added to the editor
154
154
  * @param collection Collection for the media to be added
155
155
  */
156
- export const insertMediaGroupNode = editorAnalyticsAPI => (view, mediaStates, collection, inputMethod) => {
156
+ export const insertMediaGroupNode = editorAnalyticsAPI => (view, mediaStates, collection, inputMethod, isNestingInQuoteSupported) => {
157
157
  const {
158
158
  state,
159
159
  dispatch
@@ -180,6 +180,17 @@ export const insertMediaGroupNode = editorAnalyticsAPI => (view, mediaStates, co
180
180
  const withParagraph = shouldAppendParagraph(state, nodeAtInsertionPoint);
181
181
  let content = parent.type === schema.nodes.mediaGroup ? mediaNodes // If parent is a mediaGroup do not wrap items again.
182
182
  : [schema.nodes.mediaGroup.createChecked({}, mediaNodes)];
183
+
184
+ /** we only allow the insertion of media groups inside a blockquote if nesting in quotes is supported */
185
+ const grandParentNode = state.selection.$from.node(-1);
186
+ const grandParentNodeType = grandParentNode === null || grandParentNode === void 0 ? void 0 : grandParentNode.type.name;
187
+ if (grandParentNodeType === 'blockquote' && !isNestingInQuoteSupported) {
188
+ const grandparentEndPos = state.selection.$from.start(-1) + grandParentNode.nodeSize - 1;
189
+ safeInsert(content[0], grandparentEndPos)(tr).scrollIntoView();
190
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent(getInsertMediaGroupAnalytics(mediaStates, inputMethod))(tr);
191
+ dispatch(tr);
192
+ return;
193
+ }
183
194
  if (shouldSplit) {
184
195
  content = withParagraph ? content.concat(paragraph.create()) : content;
185
196
  // delete the selection or empty paragraph
@@ -26,7 +26,7 @@ const getInsertMediaAnalytics = (inputMethod, fileExtension) => ({
26
26
  function shouldAddParagraph(state) {
27
27
  return atTheBeginningOfBlock(state) && !checkNodeDown(state.selection, state.doc, isEmptyParagraph);
28
28
  }
29
- function insertNodesWithOptionalParagraph(nodes, analyticsAttributes = {}, editorAnalyticsAPI) {
29
+ function insertNodesWithOptionalParagraph(nodes, analyticsAttributes = {}, editorAnalyticsAPI, isNestingInQuoteSupported) {
30
30
  return function (state, dispatch) {
31
31
  const {
32
32
  tr,
@@ -46,7 +46,14 @@ function insertNodesWithOptionalParagraph(nodes, analyticsAttributes = {}, edito
46
46
  nodes.push(paragraph.create());
47
47
  openEnd = 1;
48
48
  }
49
- if (state.selection.empty) {
49
+
50
+ /** we only allow the insertion of media singles inside a blockquote if nesting in quotes is supported */
51
+ const grandParentNode = state.selection.$from.node(-1);
52
+ const grandParentNodeType = grandParentNode === null || grandParentNode === void 0 ? void 0 : grandParentNode.type.name;
53
+ if (grandParentNodeType === 'blockquote' && !isNestingInQuoteSupported) {
54
+ const grandparentEndPos = state.selection.$from.start(-1) + grandParentNode.nodeSize - 1;
55
+ pmSafeInsert(nodes[0], grandparentEndPos)(tr).scrollIntoView();
56
+ } else if (state.selection.empty) {
50
57
  tr.insert(state.selection.from, nodes);
51
58
  // Set the cursor position at the end of the insertion
52
59
  const endPos = state.selection.from + nodes.reduce((totalSize, currNode) => totalSize + currNode.nodeSize, 0);
@@ -67,7 +74,7 @@ function insertNodesWithOptionalParagraph(nodes, analyticsAttributes = {}, edito
67
74
  };
68
75
  }
69
76
  export const isMediaSingle = (schema, fileMimeType) => !!schema.nodes.mediaSingle && isImage(fileMimeType);
70
- export const insertMediaAsMediaSingle = (view, node, inputMethod, editorAnalyticsAPI) => {
77
+ export const insertMediaAsMediaSingle = (view, node, inputMethod, editorAnalyticsAPI, isNestingInQuoteSupported) => {
71
78
  var _node$attrs$width;
72
79
  const {
73
80
  state,
@@ -98,7 +105,7 @@ export const insertMediaAsMediaSingle = (view, node, inputMethod, editorAnalytic
98
105
  inputMethod,
99
106
  fileExtension: node.attrs.__fileMimeType
100
107
  };
101
- return insertNodesWithOptionalParagraph(nodes, analyticsAttributes, editorAnalyticsAPI)(state, dispatch);
108
+ return insertNodesWithOptionalParagraph(nodes, analyticsAttributes, editorAnalyticsAPI, isNestingInQuoteSupported)(state, dispatch);
102
109
  };
103
110
  const getFileExtension = fileName => {
104
111
  if (fileName) {
@@ -107,7 +114,7 @@ const getFileExtension = fileName => {
107
114
  }
108
115
  return undefined;
109
116
  };
110
- export const insertMediaSingleNode = (view, mediaState, inputMethod, collection, alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, onNodeInserted) => {
117
+ export const insertMediaSingleNode = (view, mediaState, inputMethod, collection, alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, onNodeInserted, isNestingInQuoteSupported) => {
111
118
  var _state$selection$$fro;
112
119
  if (collection === undefined) {
113
120
  return false;
@@ -138,7 +145,7 @@ export const insertMediaSingleNode = (view, mediaState, inputMethod, collection,
138
145
  insertNodesWithOptionalParagraph([node], {
139
146
  fileExtension,
140
147
  inputMethod
141
- }, editorAnalyticsAPI)(state, dispatch);
148
+ }, editorAnalyticsAPI, isNestingInQuoteSupported)(state, dispatch);
142
149
  } else {
143
150
  let tr = null;
144
151
  tr = safeInsert(node, state.selection.from)(state.tr);
@@ -23,6 +23,7 @@ import { findDomRefAtPos, findParentNodeOfType, findSelectedNodeOfType, isNodeSe
23
23
  import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
24
24
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
25
25
  import { getMediaFeatureFlag } from '@atlaskit/media-common';
26
+ import { fg } from '@atlaskit/platform-feature-flags';
26
27
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
27
28
  import * as helpers from '../commands/helpers';
28
29
  import { updateMediaNodeAttrs } from '../commands/helpers';
@@ -111,9 +112,10 @@ export var MediaPluginStateImplementation = /*#__PURE__*/function () {
111
112
  * called when we insert a new file via the picker (connected via pickerfacade)
112
113
  */
113
114
  _defineProperty(this, "insertFile", function (mediaState, onMediaStateChanged, pickerType) {
114
- var _this$pluginInjection, _mediaState$collectio, _this$pluginInjection2;
115
+ var _this$pluginInjection, _this$pluginInjection2, _mediaState$collectio, _this$pluginInjection3;
115
116
  var state = _this.view.state;
116
117
  var editorAnalyticsAPI = (_this$pluginInjection = _this.pluginInjectionApi) === null || _this$pluginInjection === void 0 || (_this$pluginInjection = _this$pluginInjection.analytics) === null || _this$pluginInjection === void 0 ? void 0 : _this$pluginInjection.actions;
118
+ var isNestingInQuoteSupported = ((_this$pluginInjection2 = _this.pluginInjectionApi) === null || _this$pluginInjection2 === void 0 || (_this$pluginInjection2 = _this$pluginInjection2.featureFlags) === null || _this$pluginInjection2 === void 0 || (_this$pluginInjection2 = _this$pluginInjection2.sharedState.currentState()) === null || _this$pluginInjection2 === void 0 ? void 0 : _this$pluginInjection2.nestMediaAndCodeblockInQuote) || fg('editor_nest_media_and_codeblock_in_quotes_jira');
117
119
  var mediaStateWithContext = _objectSpread(_objectSpread({}, mediaState), {}, {
118
120
  contextId: _this.contextIdentifierProvider ? _this.contextIdentifierProvider.objectId : undefined
119
121
  });
@@ -140,11 +142,11 @@ export var MediaPluginStateImplementation = /*#__PURE__*/function () {
140
142
  break;
141
143
  case 'block':
142
144
  // read width state right before inserting to get up-to-date and define values
143
- var widthPluginState = (_this$pluginInjection2 = _this.pluginInjectionApi) === null || _this$pluginInjection2 === void 0 || (_this$pluginInjection2 = _this$pluginInjection2.width) === null || _this$pluginInjection2 === void 0 ? void 0 : _this$pluginInjection2.sharedState.currentState();
144
- insertMediaSingleNode(_this.view, mediaStateWithContext, _this.getInputMethod(pickerType), collection, _this.mediaOptions && _this.mediaOptions.alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, _this.onNodeInserted);
145
+ var widthPluginState = (_this$pluginInjection3 = _this.pluginInjectionApi) === null || _this$pluginInjection3 === void 0 || (_this$pluginInjection3 = _this$pluginInjection3.width) === null || _this$pluginInjection3 === void 0 ? void 0 : _this$pluginInjection3.sharedState.currentState();
146
+ insertMediaSingleNode(_this.view, mediaStateWithContext, _this.getInputMethod(pickerType), collection, _this.mediaOptions && _this.mediaOptions.alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, _this.onNodeInserted, isNestingInQuoteSupported);
145
147
  break;
146
148
  case 'group':
147
- insertMediaGroupNode(editorAnalyticsAPI)(_this.view, [mediaStateWithContext], collection, _this.getInputMethod(pickerType));
149
+ insertMediaGroupNode(editorAnalyticsAPI)(_this.view, [mediaStateWithContext], collection, _this.getInputMethod(pickerType), isNestingInQuoteSupported);
148
150
  break;
149
151
  }
150
152
 
@@ -583,8 +585,8 @@ export var MediaPluginStateImplementation = /*#__PURE__*/function () {
583
585
  }, {
584
586
  key: "contextIdentifierProvider",
585
587
  get: function get() {
586
- var _this$pluginInjection3;
587
- return (_this$pluginInjection3 = this.pluginInjectionApi) === null || _this$pluginInjection3 === void 0 || (_this$pluginInjection3 = _this$pluginInjection3.contextIdentifier) === null || _this$pluginInjection3 === void 0 || (_this$pluginInjection3 = _this$pluginInjection3.sharedState.currentState()) === null || _this$pluginInjection3 === void 0 ? void 0 : _this$pluginInjection3.contextIdentifierProvider;
588
+ var _this$pluginInjection4;
589
+ return (_this$pluginInjection4 = this.pluginInjectionApi) === null || _this$pluginInjection4 === void 0 || (_this$pluginInjection4 = _this$pluginInjection4.contextIdentifier) === null || _this$pluginInjection4 === void 0 || (_this$pluginInjection4 = _this$pluginInjection4.sharedState.currentState()) === null || _this$pluginInjection4 === void 0 ? void 0 : _this$pluginInjection4.contextIdentifierProvider;
588
590
  }
589
591
  }, {
590
592
  key: "selectLastAddedMediaNode",
@@ -140,7 +140,7 @@ export var insertMediaInlineNode = function insertMediaInlineNode(editorAnalytic
140
140
  * @param collection Collection for the media to be added
141
141
  */
142
142
  export var insertMediaGroupNode = function insertMediaGroupNode(editorAnalyticsAPI) {
143
- return function (view, mediaStates, collection, inputMethod) {
143
+ return function (view, mediaStates, collection, inputMethod, isNestingInQuoteSupported) {
144
144
  var state = view.state,
145
145
  dispatch = view.dispatch;
146
146
  var tr = state.tr,
@@ -162,6 +162,17 @@ export var insertMediaGroupNode = function insertMediaGroupNode(editorAnalyticsA
162
162
  var withParagraph = shouldAppendParagraph(state, nodeAtInsertionPoint);
163
163
  var content = parent.type === schema.nodes.mediaGroup ? mediaNodes // If parent is a mediaGroup do not wrap items again.
164
164
  : [schema.nodes.mediaGroup.createChecked({}, mediaNodes)];
165
+
166
+ /** we only allow the insertion of media groups inside a blockquote if nesting in quotes is supported */
167
+ var grandParentNode = state.selection.$from.node(-1);
168
+ var grandParentNodeType = grandParentNode === null || grandParentNode === void 0 ? void 0 : grandParentNode.type.name;
169
+ if (grandParentNodeType === 'blockquote' && !isNestingInQuoteSupported) {
170
+ var grandparentEndPos = state.selection.$from.start(-1) + grandParentNode.nodeSize - 1;
171
+ safeInsert(content[0], grandparentEndPos)(tr).scrollIntoView();
172
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent(getInsertMediaGroupAnalytics(mediaStates, inputMethod))(tr);
173
+ dispatch(tr);
174
+ return;
175
+ }
165
176
  if (shouldSplit) {
166
177
  content = withParagraph ? content.concat(paragraph.create()) : content;
167
178
  // delete the selection or empty paragraph
@@ -34,6 +34,7 @@ function shouldAddParagraph(state) {
34
34
  function insertNodesWithOptionalParagraph(nodes) {
35
35
  var analyticsAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
36
36
  var editorAnalyticsAPI = arguments.length > 2 ? arguments[2] : undefined;
37
+ var isNestingInQuoteSupported = arguments.length > 3 ? arguments[3] : undefined;
37
38
  return function (state, dispatch) {
38
39
  var tr = state.tr,
39
40
  schema = state.schema;
@@ -47,7 +48,14 @@ function insertNodesWithOptionalParagraph(nodes) {
47
48
  nodes.push(paragraph.create());
48
49
  openEnd = 1;
49
50
  }
50
- if (state.selection.empty) {
51
+
52
+ /** we only allow the insertion of media singles inside a blockquote if nesting in quotes is supported */
53
+ var grandParentNode = state.selection.$from.node(-1);
54
+ var grandParentNodeType = grandParentNode === null || grandParentNode === void 0 ? void 0 : grandParentNode.type.name;
55
+ if (grandParentNodeType === 'blockquote' && !isNestingInQuoteSupported) {
56
+ var grandparentEndPos = state.selection.$from.start(-1) + grandParentNode.nodeSize - 1;
57
+ pmSafeInsert(nodes[0], grandparentEndPos)(tr).scrollIntoView();
58
+ } else if (state.selection.empty) {
51
59
  tr.insert(state.selection.from, nodes);
52
60
  // Set the cursor position at the end of the insertion
53
61
  var endPos = state.selection.from + nodes.reduce(function (totalSize, currNode) {
@@ -72,7 +80,7 @@ function insertNodesWithOptionalParagraph(nodes) {
72
80
  export var isMediaSingle = function isMediaSingle(schema, fileMimeType) {
73
81
  return !!schema.nodes.mediaSingle && isImage(fileMimeType);
74
82
  };
75
- export var insertMediaAsMediaSingle = function insertMediaAsMediaSingle(view, node, inputMethod, editorAnalyticsAPI) {
83
+ export var insertMediaAsMediaSingle = function insertMediaAsMediaSingle(view, node, inputMethod, editorAnalyticsAPI, isNestingInQuoteSupported) {
76
84
  var _node$attrs$width;
77
85
  var state = view.state,
78
86
  dispatch = view.dispatch;
@@ -100,7 +108,7 @@ export var insertMediaAsMediaSingle = function insertMediaAsMediaSingle(view, no
100
108
  inputMethod: inputMethod,
101
109
  fileExtension: node.attrs.__fileMimeType
102
110
  };
103
- return insertNodesWithOptionalParagraph(nodes, analyticsAttributes, editorAnalyticsAPI)(state, dispatch);
111
+ return insertNodesWithOptionalParagraph(nodes, analyticsAttributes, editorAnalyticsAPI, isNestingInQuoteSupported)(state, dispatch);
104
112
  };
105
113
  var getFileExtension = function getFileExtension(fileName) {
106
114
  if (fileName) {
@@ -109,7 +117,7 @@ var getFileExtension = function getFileExtension(fileName) {
109
117
  }
110
118
  return undefined;
111
119
  };
112
- export var insertMediaSingleNode = function insertMediaSingleNode(view, mediaState, inputMethod, collection, alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, onNodeInserted) {
120
+ export var insertMediaSingleNode = function insertMediaSingleNode(view, mediaState, inputMethod, collection, alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, onNodeInserted, isNestingInQuoteSupported) {
113
121
  var _state$selection$$fro;
114
122
  if (collection === undefined) {
115
123
  return false;
@@ -138,7 +146,7 @@ export var insertMediaSingleNode = function insertMediaSingleNode(view, mediaSta
138
146
  insertNodesWithOptionalParagraph([node], {
139
147
  fileExtension: fileExtension,
140
148
  inputMethod: inputMethod
141
- }, editorAnalyticsAPI)(state, dispatch);
149
+ }, editorAnalyticsAPI, isNestingInQuoteSupported)(state, dispatch);
142
150
  } else {
143
151
  var tr = null;
144
152
  tr = safeInsert(node, state.selection.from)(state.tr);
@@ -6,6 +6,7 @@ import type { ContextIdentifierPlugin } from '@atlaskit/editor-plugin-context-id
6
6
  import type { DecorationsPlugin } from '@atlaskit/editor-plugin-decorations';
7
7
  import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
8
8
  import type { EditorViewModePlugin } from '@atlaskit/editor-plugin-editor-viewmode';
9
+ import type { FeatureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
9
10
  import type { FloatingToolbarPlugin } from '@atlaskit/editor-plugin-floating-toolbar';
10
11
  import type { FocusPlugin } from '@atlaskit/editor-plugin-focus';
11
12
  import type { GridPlugin } from '@atlaskit/editor-plugin-grid';
@@ -29,7 +30,8 @@ export type MediaNextEditorPluginType = NextEditorPlugin<'media', {
29
30
  EditorDisabledPlugin,
30
31
  FocusPlugin,
31
32
  SelectionPlugin,
32
- OptionalPlugin<AnnotationPlugin>
33
+ OptionalPlugin<AnnotationPlugin>,
34
+ OptionalPlugin<FeatureFlagsPlugin>
33
35
  ];
34
36
  sharedState: MediaPluginState | null;
35
37
  actions: {
@@ -18,7 +18,7 @@ export declare const insertMediaInlineNode: (editorAnalyticsAPI: EditorAnalytics
18
18
  * @param mediaStates Media files to be added to the editor
19
19
  * @param collection Collection for the media to be added
20
20
  */
21
- export declare const insertMediaGroupNode: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (view: EditorView, mediaStates: MediaState[], collection: string, inputMethod?: InputMethodInsertMedia) => void;
21
+ export declare const insertMediaGroupNode: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (view: EditorView, mediaStates: MediaState[], collection: string, inputMethod?: InputMethodInsertMedia, isNestingInQuoteSupported?: boolean) => void;
22
22
  /**
23
23
  * Return position of media to be inserted, if it is inside a list
24
24
  * @param content Content to be inserted
@@ -4,8 +4,8 @@ import type { Node as PMNode, Schema } from '@atlaskit/editor-prosemirror/model'
4
4
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
5
5
  import type { MediaState } from '../types';
6
6
  export declare const isMediaSingle: (schema: Schema, fileMimeType?: string) => boolean;
7
- export type InsertMediaAsMediaSingle = (view: EditorView, node: PMNode, inputMethod: InputMethodInsertMedia) => boolean;
8
- export declare const insertMediaAsMediaSingle: (view: EditorView, node: PMNode, inputMethod: InputMethodInsertMedia, editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => boolean;
9
- export declare const insertMediaSingleNode: (view: EditorView, mediaState: MediaState, inputMethod?: InputMethodInsertMedia, collection?: string, alignLeftOnInsert?: boolean, widthPluginState?: WidthPluginState | undefined, editorAnalyticsAPI?: EditorAnalyticsAPI | undefined, onNodeInserted?: ((id: string, selectionPosition: number) => void) | undefined) => boolean;
7
+ export type InsertMediaAsMediaSingle = (view: EditorView, node: PMNode, inputMethod: InputMethodInsertMedia, isNestingInQuoteSupported?: boolean) => boolean;
8
+ export declare const insertMediaAsMediaSingle: (view: EditorView, node: PMNode, inputMethod: InputMethodInsertMedia, editorAnalyticsAPI: EditorAnalyticsAPI | undefined, isNestingInQuoteSupported?: boolean) => boolean;
9
+ export declare const insertMediaSingleNode: (view: EditorView, mediaState: MediaState, inputMethod?: InputMethodInsertMedia, collection?: string, alignLeftOnInsert?: boolean, widthPluginState?: WidthPluginState | undefined, editorAnalyticsAPI?: EditorAnalyticsAPI | undefined, onNodeInserted?: ((id: string, selectionPosition: number) => void) | undefined, isNestingInQuoteSupported?: boolean) => boolean;
10
10
  export declare const changeFromMediaInlineToMediaSingleNode: (view: EditorView, fromNode: PMNode, widthPluginState?: WidthPluginState | undefined, editorAnalyticsAPI?: EditorAnalyticsAPI | undefined) => boolean;
11
11
  export declare const isVideo: import("memoize-one").MemoizedFn<(fileType?: string) => boolean>;
@@ -6,6 +6,7 @@ import type { ContextIdentifierPlugin } from '@atlaskit/editor-plugin-context-id
6
6
  import type { DecorationsPlugin } from '@atlaskit/editor-plugin-decorations';
7
7
  import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
8
8
  import type { EditorViewModePlugin } from '@atlaskit/editor-plugin-editor-viewmode';
9
+ import type { FeatureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
9
10
  import type { FloatingToolbarPlugin } from '@atlaskit/editor-plugin-floating-toolbar';
10
11
  import type { FocusPlugin } from '@atlaskit/editor-plugin-focus';
11
12
  import type { GridPlugin } from '@atlaskit/editor-plugin-grid';
@@ -29,7 +30,8 @@ export type MediaNextEditorPluginType = NextEditorPlugin<'media', {
29
30
  EditorDisabledPlugin,
30
31
  FocusPlugin,
31
32
  SelectionPlugin,
32
- OptionalPlugin<AnnotationPlugin>
33
+ OptionalPlugin<AnnotationPlugin>,
34
+ OptionalPlugin<FeatureFlagsPlugin>
33
35
  ];
34
36
  sharedState: MediaPluginState | null;
35
37
  actions: {
@@ -18,7 +18,7 @@ export declare const insertMediaInlineNode: (editorAnalyticsAPI: EditorAnalytics
18
18
  * @param mediaStates Media files to be added to the editor
19
19
  * @param collection Collection for the media to be added
20
20
  */
21
- export declare const insertMediaGroupNode: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (view: EditorView, mediaStates: MediaState[], collection: string, inputMethod?: InputMethodInsertMedia) => void;
21
+ export declare const insertMediaGroupNode: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (view: EditorView, mediaStates: MediaState[], collection: string, inputMethod?: InputMethodInsertMedia, isNestingInQuoteSupported?: boolean) => void;
22
22
  /**
23
23
  * Return position of media to be inserted, if it is inside a list
24
24
  * @param content Content to be inserted
@@ -4,8 +4,8 @@ import type { Node as PMNode, Schema } from '@atlaskit/editor-prosemirror/model'
4
4
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
5
5
  import type { MediaState } from '../types';
6
6
  export declare const isMediaSingle: (schema: Schema, fileMimeType?: string) => boolean;
7
- export type InsertMediaAsMediaSingle = (view: EditorView, node: PMNode, inputMethod: InputMethodInsertMedia) => boolean;
8
- export declare const insertMediaAsMediaSingle: (view: EditorView, node: PMNode, inputMethod: InputMethodInsertMedia, editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => boolean;
9
- export declare const insertMediaSingleNode: (view: EditorView, mediaState: MediaState, inputMethod?: InputMethodInsertMedia, collection?: string, alignLeftOnInsert?: boolean, widthPluginState?: WidthPluginState | undefined, editorAnalyticsAPI?: EditorAnalyticsAPI | undefined, onNodeInserted?: ((id: string, selectionPosition: number) => void) | undefined) => boolean;
7
+ export type InsertMediaAsMediaSingle = (view: EditorView, node: PMNode, inputMethod: InputMethodInsertMedia, isNestingInQuoteSupported?: boolean) => boolean;
8
+ export declare const insertMediaAsMediaSingle: (view: EditorView, node: PMNode, inputMethod: InputMethodInsertMedia, editorAnalyticsAPI: EditorAnalyticsAPI | undefined, isNestingInQuoteSupported?: boolean) => boolean;
9
+ export declare const insertMediaSingleNode: (view: EditorView, mediaState: MediaState, inputMethod?: InputMethodInsertMedia, collection?: string, alignLeftOnInsert?: boolean, widthPluginState?: WidthPluginState | undefined, editorAnalyticsAPI?: EditorAnalyticsAPI | undefined, onNodeInserted?: ((id: string, selectionPosition: number) => void) | undefined, isNestingInQuoteSupported?: boolean) => boolean;
10
10
  export declare const changeFromMediaInlineToMediaSingleNode: (view: EditorView, fromNode: PMNode, widthPluginState?: WidthPluginState | undefined, editorAnalyticsAPI?: EditorAnalyticsAPI | undefined) => boolean;
11
11
  export declare const isVideo: import("memoize-one").MemoizedFn<(fileType?: string) => boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-media",
3
- "version": "1.31.7",
3
+ "version": "1.31.8",
4
4
  "description": "Media plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -44,7 +44,7 @@
44
44
  "@atlaskit/editor-plugin-editor-disabled": "^1.3.0",
45
45
  "@atlaskit/editor-plugin-editor-viewmode": "^2.1.0",
46
46
  "@atlaskit/editor-plugin-floating-toolbar": "^1.13.0",
47
- "@atlaskit/editor-plugin-focus": "^1.3.0",
47
+ "@atlaskit/editor-plugin-focus": "^1.4.0",
48
48
  "@atlaskit/editor-plugin-grid": "^1.2.0",
49
49
  "@atlaskit/editor-plugin-guideline": "^1.2.0",
50
50
  "@atlaskit/editor-plugin-selection": "^1.4.0",
@@ -54,14 +54,14 @@
54
54
  "@atlaskit/editor-tables": "^2.8.0",
55
55
  "@atlaskit/form": "^10.5.0",
56
56
  "@atlaskit/icon": "^22.18.0",
57
- "@atlaskit/media-card": "^78.3.0",
57
+ "@atlaskit/media-card": "^78.4.0",
58
58
  "@atlaskit/media-client": "^28.0.0",
59
59
  "@atlaskit/media-client-react": "^2.2.0",
60
60
  "@atlaskit/media-common": "^11.4.0",
61
61
  "@atlaskit/media-filmstrip": "^47.2.0",
62
- "@atlaskit/media-picker": "^66.5.0",
63
- "@atlaskit/media-ui": "^25.11.0",
64
- "@atlaskit/media-viewer": "^48.8.0",
62
+ "@atlaskit/media-picker": "^66.6.0",
63
+ "@atlaskit/media-ui": "^25.12.0",
64
+ "@atlaskit/media-viewer": "^48.9.0",
65
65
  "@atlaskit/platform-feature-flags": "^0.3.0",
66
66
  "@atlaskit/primitives": "^12.1.0",
67
67
  "@atlaskit/textfield": "^6.5.0",
@@ -146,6 +146,9 @@
146
146
  },
147
147
  "platform_editor_media_batch_updates": {
148
148
  "type": "boolean"
149
+ },
150
+ "editor_nest_media_and_codeblock_in_quotes_jira": {
151
+ "type": "boolean"
149
152
  }
150
153
  },
151
154
  "stricter": {