@atlaskit/editor-core 188.0.12 → 188.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/plugins/annotation/toolbar.js +5 -23
  3. package/dist/cjs/plugins/code-block/index.js +3 -3
  4. package/dist/cjs/plugins/code-block/pm-plugins/codeBlockCopySelectionPlugin.js +2 -2
  5. package/dist/cjs/plugins/help-dialog/index.js +3 -3
  6. package/dist/cjs/plugins/help-dialog/ui/index.js +21 -26
  7. package/dist/cjs/plugins/insert-block/ui/ToolbarInsertBlock/create-items.js +4 -4
  8. package/dist/cjs/plugins/media/index.js +12 -6
  9. package/dist/cjs/plugins/media/utils/media-common.js +7 -109
  10. package/dist/cjs/plugins/media/utils/media-single.js +7 -68
  11. package/dist/cjs/plugins/panel/index.js +13 -13
  12. package/dist/cjs/plugins/paste/handlers.js +4 -4
  13. package/dist/cjs/plugins/paste/plugins/media.js +181 -0
  14. package/dist/cjs/plugins/paste/pm-plugins/analytics.js +2 -2
  15. package/dist/cjs/plugins/paste/pm-plugins/main.js +6 -7
  16. package/dist/cjs/plugins/undo-redo/ui/ToolbarUndoRedo/index.js +3 -3
  17. package/dist/cjs/ui/Alignment/index.js +1 -1
  18. package/dist/cjs/version-wrapper.js +1 -1
  19. package/dist/es2019/plugins/annotation/toolbar.js +2 -18
  20. package/dist/es2019/plugins/code-block/index.js +3 -3
  21. package/dist/es2019/plugins/code-block/pm-plugins/codeBlockCopySelectionPlugin.js +1 -1
  22. package/dist/es2019/plugins/help-dialog/index.js +1 -1
  23. package/dist/es2019/plugins/help-dialog/ui/index.js +8 -13
  24. package/dist/es2019/plugins/insert-block/ui/ToolbarInsertBlock/create-items.js +1 -1
  25. package/dist/es2019/plugins/media/index.js +13 -6
  26. package/dist/es2019/plugins/media/utils/media-common.js +2 -107
  27. package/dist/es2019/plugins/media/utils/media-single.js +6 -72
  28. package/dist/es2019/plugins/panel/index.js +13 -13
  29. package/dist/es2019/plugins/paste/handlers.js +4 -4
  30. package/dist/es2019/plugins/paste/plugins/media.js +176 -0
  31. package/dist/es2019/plugins/paste/pm-plugins/analytics.js +2 -2
  32. package/dist/es2019/plugins/paste/pm-plugins/main.js +3 -4
  33. package/dist/es2019/plugins/undo-redo/ui/ToolbarUndoRedo/index.js +3 -3
  34. package/dist/es2019/ui/Alignment/index.js +1 -1
  35. package/dist/es2019/version-wrapper.js +1 -1
  36. package/dist/esm/plugins/annotation/toolbar.js +2 -18
  37. package/dist/esm/plugins/code-block/index.js +3 -3
  38. package/dist/esm/plugins/code-block/pm-plugins/codeBlockCopySelectionPlugin.js +1 -1
  39. package/dist/esm/plugins/help-dialog/index.js +1 -1
  40. package/dist/esm/plugins/help-dialog/ui/index.js +8 -13
  41. package/dist/esm/plugins/insert-block/ui/ToolbarInsertBlock/create-items.js +1 -1
  42. package/dist/esm/plugins/media/index.js +13 -6
  43. package/dist/esm/plugins/media/utils/media-common.js +2 -106
  44. package/dist/esm/plugins/media/utils/media-single.js +6 -66
  45. package/dist/esm/plugins/panel/index.js +13 -13
  46. package/dist/esm/plugins/paste/handlers.js +4 -4
  47. package/dist/esm/plugins/paste/plugins/media.js +172 -0
  48. package/dist/esm/plugins/paste/pm-plugins/analytics.js +2 -2
  49. package/dist/esm/plugins/paste/pm-plugins/main.js +3 -4
  50. package/dist/esm/plugins/undo-redo/ui/ToolbarUndoRedo/index.js +3 -3
  51. package/dist/esm/ui/Alignment/index.js +1 -1
  52. package/dist/esm/version-wrapper.js +1 -1
  53. package/dist/types/labs/next/presets/default.d.ts +6 -0
  54. package/dist/types/plugins/annotation/toolbar.d.ts +0 -17
  55. package/dist/types/plugins/help-dialog/index.d.ts +2 -15
  56. package/dist/types/plugins/media/next-plugin-type.d.ts +4 -0
  57. package/dist/types/plugins/media/utils/media-common.d.ts +2 -10
  58. package/dist/types/plugins/media/utils/media-single.d.ts +2 -4
  59. package/dist/types/plugins/paste/handlers.d.ts +2 -2
  60. package/dist/types/plugins/paste/index.d.ts +5 -2
  61. package/dist/types/plugins/paste/plugins/media.d.ts +12 -0
  62. package/dist/types/plugins/paste/pm-plugins/analytics.d.ts +2 -2
  63. package/dist/types/plugins/paste/pm-plugins/main.d.ts +2 -2
  64. package/dist/types/ui/Alignment/index.d.ts +2 -2
  65. package/dist/types/ui/Appearance/FullPage/StyledComponents.d.ts +1 -1
  66. package/dist/types/ui/ContentStyles/index.d.ts +2 -2
  67. package/dist/types-ts4.5/labs/next/presets/default.d.ts +6 -0
  68. package/dist/types-ts4.5/plugins/annotation/toolbar.d.ts +0 -17
  69. package/dist/types-ts4.5/plugins/help-dialog/index.d.ts +2 -15
  70. package/dist/types-ts4.5/plugins/media/next-plugin-type.d.ts +4 -0
  71. package/dist/types-ts4.5/plugins/media/utils/media-common.d.ts +2 -10
  72. package/dist/types-ts4.5/plugins/media/utils/media-single.d.ts +2 -4
  73. package/dist/types-ts4.5/plugins/paste/handlers.d.ts +2 -2
  74. package/dist/types-ts4.5/plugins/paste/index.d.ts +5 -2
  75. package/dist/types-ts4.5/plugins/paste/plugins/media.d.ts +12 -0
  76. package/dist/types-ts4.5/plugins/paste/pm-plugins/analytics.d.ts +2 -2
  77. package/dist/types-ts4.5/plugins/paste/pm-plugins/main.d.ts +2 -2
  78. package/dist/types-ts4.5/ui/Alignment/index.d.ts +2 -2
  79. package/dist/types-ts4.5/ui/Appearance/FullPage/StyledComponents.d.ts +1 -1
  80. package/dist/types-ts4.5/ui/ContentStyles/index.d.ts +2 -2
  81. package/package.json +6 -5
  82. package/dist/cjs/plugins/undo-redo/messages.js +0 -19
  83. package/dist/cjs/ui/Alignment/messages.js +0 -24
  84. package/dist/es2019/plugins/undo-redo/messages.js +0 -13
  85. package/dist/es2019/ui/Alignment/messages.js +0 -18
  86. package/dist/esm/plugins/undo-redo/messages.js +0 -13
  87. package/dist/esm/ui/Alignment/messages.js +0 -18
  88. package/dist/types/plugins/undo-redo/messages.d.ts +0 -12
  89. package/dist/types/ui/Alignment/messages.d.ts +0 -17
  90. package/dist/types-ts4.5/plugins/undo-redo/messages.d.ts +0 -12
  91. package/dist/types-ts4.5/ui/Alignment/messages.d.ts +0 -17
@@ -9,13 +9,8 @@ import AkModalDialog, { ModalTransition, useModal } from '@atlaskit/modal-dialog
9
9
  import { header, footer, contentWrapper, line, content, row, codeSm, codeMd, codeLg, title, column, dialogHeader } from './styles';
10
10
  import { navToFloatingToolbar, navToEditorToolbar, toggleBold, toggleItalic, toggleUnderline, toggleStrikethrough, toggleSubscript, toggleSuperscript, toggleHeading1, toggleHeading2, toggleHeading3, toggleHeading4, toggleHeading5, toggleHeading6, toggleOrderedList, insertRule, addLink, setNormalText, alignLeft, clearFormatting, undo, redo, pastePlainText, addInlineComment, toggleTaskItemCheckbox, toggleCode, openHelp, toggleBulletList, toggleBlockQuote } from '@atlaskit/editor-common/keymaps';
11
11
  import ToolbarButton from '../../../ui/ToolbarButton';
12
- import { toolbarMessages, listMessages } from '@atlaskit/editor-common/messages';
13
- import { messages as insertBlockMessages } from '../../insert-block/ui/ToolbarInsertBlock/messages';
14
- import { messages as blockTypeMessages } from '@atlaskit/editor-plugin-block-type/messages';
15
- import { messages as undoRedoMessages } from '../../undo-redo/messages';
16
- import { alignmentMessages } from '../../../ui/Alignment/messages';
12
+ import { alignmentMessages, annotationMessages, listMessages, toolbarInsertBlockMessages, toolbarMessages, undoRedoMessages, blockTypeMessages } from '@atlaskit/editor-common/messages';
17
13
  import { closeHelpCommand } from '../commands';
18
- import { annotationMessages } from '../../annotation/toolbar';
19
14
  import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
20
15
  const messages = defineMessages({
21
16
  editorHelp: {
@@ -203,19 +198,19 @@ export const formatting = ({
203
198
  css: codeLg
204
199
  }, "```"))
205
200
  }, {
206
- name: formatMessage(insertBlockMessages.horizontalRule),
201
+ name: formatMessage(toolbarInsertBlockMessages.horizontalRule),
207
202
  type: 'rule',
208
203
  keymap: () => insertRule,
209
204
  autoFormatting: () => jsx("span", null, jsx("span", {
210
205
  css: codeLg
211
206
  }, "---"))
212
207
  }, {
213
- name: formatMessage(insertBlockMessages.link),
208
+ name: formatMessage(toolbarInsertBlockMessages.link),
214
209
  type: 'link',
215
210
  keymap: () => addLink,
216
211
  autoFormatting: () => jsx("span", null, jsx("span", {
217
212
  css: codeLg
218
- }, "[", jsx(FormattedMessage, insertBlockMessages.link), "](http://a.com)"))
213
+ }, "[", jsx(FormattedMessage, toolbarInsertBlockMessages.link), "](http://a.com)"))
219
214
  }, {
220
215
  name: formatMessage(toolbarMessages.code),
221
216
  type: 'code',
@@ -224,7 +219,7 @@ export const formatting = ({
224
219
  css: codeLg
225
220
  }, "`", jsx(FormattedMessage, toolbarMessages.code), "`"))
226
221
  }, {
227
- name: formatMessage(insertBlockMessages.action),
222
+ name: formatMessage(toolbarInsertBlockMessages.action),
228
223
  type: 'taskItem',
229
224
  autoFormatting: () => jsx("span", null, jsx("span", {
230
225
  css: codeSm
@@ -232,7 +227,7 @@ export const formatting = ({
232
227
  css: codeLg
233
228
  }, "Space"))
234
229
  }, {
235
- name: formatMessage(insertBlockMessages.decision),
230
+ name: formatMessage(toolbarInsertBlockMessages.decision),
236
231
  type: 'decisionItem',
237
232
  autoFormatting: () => jsx("span", null, jsx("span", {
238
233
  css: codeSm
@@ -240,13 +235,13 @@ export const formatting = ({
240
235
  css: codeLg
241
236
  }, "Space"))
242
237
  }, {
243
- name: formatMessage(insertBlockMessages.emoji),
238
+ name: formatMessage(toolbarInsertBlockMessages.emoji),
244
239
  type: 'emoji',
245
240
  autoFormatting: () => jsx("span", null, jsx("span", {
246
241
  css: codeLg
247
242
  }, ":"))
248
243
  }, {
249
- name: formatMessage(insertBlockMessages.mention),
244
+ name: formatMessage(toolbarInsertBlockMessages.mention),
250
245
  type: 'mention',
251
246
  autoFormatting: () => jsx("span", null, jsx("span", {
252
247
  css: codeLg
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import memoize from 'lodash/memoize';
3
3
  import memoizeOne from 'memoize-one';
4
4
  import { messages } from './messages';
5
- import { messages as blockTypeMessages } from '@atlaskit/editor-plugin-block-type/messages';
5
+ import { blockTypeMessages } from '@atlaskit/editor-common/messages';
6
6
  import { ToolTipContent } from '../../../../keymaps';
7
7
  import { sortItems } from './sort-items';
8
8
  import { action, link, media, mention, emoji, table, layout, codeblock, panel, blockquote, decision, horizontalrule, expand, date, placeholder, status, more, imageUpload } from './item';
@@ -23,6 +23,7 @@ import { ReactMediaNode } from './nodeviews/mediaNodeView';
23
23
  import { ReactMediaInlineNode } from './nodeviews/mediaInline';
24
24
  import { getBooleanFF } from '@atlaskit/platform-feature-flags';
25
25
  import { stateKey } from './pm-plugins/plugin-key';
26
+ import { insertMediaAsMediaSingle } from './utils/media-single';
26
27
  export { insertMediaSingleNode } from './utils/media-single';
27
28
  const MediaPickerFunctionalComponent = ({
28
29
  api,
@@ -56,6 +57,12 @@ const mediaPlugin = ({
56
57
  }
57
58
  return stateKey.getState(editorState) || null;
58
59
  },
60
+ actions: {
61
+ insertMediaAsMediaSingle: (view, node, inputMethod) => {
62
+ var _api$analytics;
63
+ return insertMediaAsMediaSingle(view, node, inputMethod, api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions);
64
+ }
65
+ },
59
66
  nodes() {
60
67
  const {
61
68
  allowMediaGroup = true,
@@ -136,8 +143,8 @@ const mediaPlugin = ({
136
143
  }, {
137
144
  name: 'mediaKeymap',
138
145
  plugin: () => {
139
- var _api$analytics;
140
- return keymapPlugin(options, api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions);
146
+ var _api$analytics2;
147
+ return keymapPlugin(options, api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions);
141
148
  }
142
149
  }];
143
150
  if (options && options.allowMediaSingle) {
@@ -158,8 +165,8 @@ const mediaPlugin = ({
158
165
  plugin: ({
159
166
  schema
160
167
  }) => {
161
- var _api$analytics2;
162
- return keymapMediaAltTextPlugin(schema, api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions);
168
+ var _api$analytics3;
169
+ return keymapMediaAltTextPlugin(schema, api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions);
163
170
  }
164
171
  });
165
172
  }
@@ -245,11 +252,11 @@ const mediaPlugin = ({
245
252
  keywords: ['attachment', 'gif', 'media', 'picture', 'image', 'video'],
246
253
  icon: () => /*#__PURE__*/React.createElement(IconImages, null),
247
254
  action(insert, state) {
248
- var _api$analytics3;
255
+ var _api$analytics4;
249
256
  const pluginState = pluginKey.getState(state);
250
257
  pluginState === null || pluginState === void 0 ? void 0 : pluginState.showMediaPicker();
251
258
  const tr = insert('');
252
- api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.attachAnalyticsEvent({
259
+ api === null || api === void 0 ? void 0 : (_api$analytics4 = api.analytics) === null || _api$analytics4 === void 0 ? void 0 : _api$analytics4.actions.attachAnalyticsEvent({
253
260
  action: ACTION.OPENED,
254
261
  actionSubject: ACTION_SUBJECT.PICKER,
255
262
  actionSubjectId: ACTION_SUBJECT_ID.PICKER_CLOUD,
@@ -1,11 +1,8 @@
1
+ import { atTheBeginningOfBlock, atTheBeginningOfDoc, atTheEndOfBlock, endPositionOfParent, GapCursorSelection, startPositionOfParent } from '@atlaskit/editor-common/selection';
2
+ import { createNewParagraphBelow, createParagraphNear } from '@atlaskit/editor-common/utils';
1
3
  import { deleteSelection, splitBlock } from '@atlaskit/editor-prosemirror/commands';
2
4
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
3
5
  import { findPositionOfNodeBefore } from '@atlaskit/editor-prosemirror/utils';
4
- import { createParagraphNear, createNewParagraphBelow } from '@atlaskit/editor-common/utils';
5
- import { mapSlice } from '@atlaskit/editor-common/utils';
6
- import { walkUpTreeUntil, removeNestedEmptyEls, unwrap } from '@atlaskit/editor-common/utils';
7
- import { isImage } from './is-image';
8
- import { GapCursorSelection, atTheBeginningOfBlock, atTheBeginningOfDoc, atTheEndOfBlock, endPositionOfParent, startPositionOfParent } from '@atlaskit/editor-common/selection';
9
6
  import { isMediaBlobUrl } from '@atlaskit/media-client';
10
7
  const isTemporary = id => {
11
8
  return id.indexOf('temporary:') === 0;
@@ -178,108 +175,6 @@ export const copyOptionalAttrsFromMediaState = (mediaState, node) => {
178
175
  }
179
176
  });
180
177
  };
181
- export const transformSliceToCorrectMediaWrapper = (slice, schema) => {
182
- const {
183
- mediaGroup,
184
- mediaSingle,
185
- media
186
- } = schema.nodes;
187
- return mapSlice(slice, (node, parent) => {
188
- if (!parent && node.type === media) {
189
- if (mediaSingle && (isImage(node.attrs.__fileMimeType) || node.attrs.type === 'external')) {
190
- return mediaSingle.createChecked({}, node);
191
- } else {
192
- return mediaGroup.createChecked({}, [node]);
193
- }
194
- }
195
- return node;
196
- });
197
- };
198
-
199
- /**
200
- * Check base styles to see if an element will be invisible when rendered in a document.
201
- * @param element
202
- */
203
- const isElementInvisible = element => {
204
- return element.style.opacity === '0' || element.style.display === 'none' || element.style.visibility === 'hidden';
205
- };
206
- const VALID_TAGS_CONTAINER = ['DIV', 'TD'];
207
- function canContainImage(element) {
208
- if (!element) {
209
- return false;
210
- }
211
- return VALID_TAGS_CONTAINER.indexOf(element.tagName) !== -1;
212
- }
213
-
214
- /**
215
- * Given a html string, we attempt to hoist any nested `<img>` tags,
216
- * not directly wrapped by a `<div>` as ProseMirror no-op's
217
- * on those scenarios.
218
- * @param html
219
- */
220
- export const unwrapNestedMediaElements = html => {
221
- const parser = new DOMParser();
222
- let doc = parser.parseFromString(html, 'text/html');
223
- const wrapper = doc.body;
224
-
225
- // Remove Google Doc's wrapper <b> el
226
- const docsWrapper = wrapper.querySelector('b[id^="docs-internal-guid-"]');
227
- if (docsWrapper) {
228
- unwrap(wrapper, docsWrapper);
229
- }
230
- const imageTags = wrapper.querySelectorAll('img');
231
- if (!imageTags.length) {
232
- return html;
233
- }
234
- imageTags.forEach(imageTag => {
235
- // Capture the immediate parent, we may remove the media from here later.
236
- const mediaParent = imageTag.parentElement;
237
- if (!mediaParent) {
238
- return;
239
- }
240
-
241
- // If either the parent or the image itself contains styles that would make
242
- // them invisible on copy, dont paste them.
243
- if (isElementInvisible(mediaParent) || isElementInvisible(imageTag)) {
244
- mediaParent.removeChild(imageTag);
245
- return;
246
- }
247
-
248
- // If its wrapped by a valid container we assume its safe to bypass.
249
- // ProseMirror should handle these cases properly.
250
- if (canContainImage(mediaParent) || mediaParent instanceof HTMLSpanElement && mediaParent.closest('[class*="emoji-common"]')) {
251
- return;
252
- }
253
-
254
- // Find the top most element that the parent has a valid container for the image.
255
- // Stop just before found the wrapper
256
- const insertBeforeElement = walkUpTreeUntil(mediaParent, element => {
257
- // If is at the top just use this element as reference
258
- if (element.parentElement === wrapper) {
259
- return true;
260
- }
261
- return canContainImage(element.parentElement);
262
- });
263
-
264
- // Here we try to insert the media right after its top most valid parent element
265
- // Unless its the last element in our structure then we will insert above it.
266
- if (insertBeforeElement && insertBeforeElement.parentElement) {
267
- // Insert as close as possible to the most closest valid element index in the tree.
268
- insertBeforeElement.parentElement.insertBefore(imageTag, insertBeforeElement.nextElementSibling || insertBeforeElement);
269
-
270
- // Attempt to clean up lines left behind by the image
271
- mediaParent.innerText = mediaParent.innerText.trim();
272
- // Walk up and delete empty elements left over after removing the image tag
273
- removeNestedEmptyEls(mediaParent);
274
- }
275
- });
276
-
277
- // If last child is a hardbreak we don't want it
278
- if (wrapper.lastElementChild && wrapper.lastElementChild.tagName === 'BR') {
279
- wrapper.removeChild(wrapper.lastElementChild);
280
- }
281
- return wrapper.innerHTML;
282
- };
283
178
  export const getMediaNodeFromSelection = state => {
284
179
  if (!isSelectionMediaSingleNode(state)) {
285
180
  return null;
@@ -1,14 +1,13 @@
1
+ import { getMaxWidthForNestedNodeNext, getMediaSingleInitialWidth, MEDIA_SINGLE_DEFAULT_MIN_PIXEL_WIDTH, MEDIA_SINGLE_VIDEO_MIN_PIXEL_WIDTH } from '@atlaskit/editor-common/media-single';
2
+ import { checkNodeDown, isEmptyParagraph } from '@atlaskit/editor-common/utils';
1
3
  import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
2
- import { safeInsert as pmSafeInsert, hasParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
3
- import { checkNodeDown, isEmptyParagraph, mapSlice } from '@atlaskit/editor-common/utils';
4
- import { getMediaSingleInitialWidth, MEDIA_SINGLE_DEFAULT_MIN_PIXEL_WIDTH, MEDIA_SINGLE_VIDEO_MIN_PIXEL_WIDTH, getMaxWidthForNestedNodeNext } from '@atlaskit/editor-common/media-single';
5
- import { copyOptionalAttrsFromMediaState } from '../utils/media-common';
6
- import { ACTION, ACTION_SUBJECT, EVENT_TYPE, ACTION_SUBJECT_ID } from '@atlaskit/editor-common/analytics';
4
+ import { safeInsert as pmSafeInsert } from '@atlaskit/editor-prosemirror/utils';
5
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
7
6
  import { safeInsert, shouldSplitSelectedNodeOnNodeInsertion } from '@atlaskit/editor-common/insert';
8
- import { isImage } from './is-image';
7
+ import { copyOptionalAttrsFromMediaState } from '../utils/media-common';
9
8
  import { atTheBeginningOfBlock } from '@atlaskit/editor-common/selection';
10
- import { getRandomHex } from '@atlaskit/media-common';
11
9
  import { getBooleanFF } from '@atlaskit/platform-feature-flags';
10
+ import { isImage } from './is-image';
12
11
  const getInsertMediaAnalytics = (inputMethod, fileExtension) => ({
13
12
  action: ACTION.INSERTED,
14
13
  actionSubject: ACTION_SUBJECT.DOCUMENT,
@@ -164,71 +163,6 @@ export const createMediaSingleNode = (schema, collection, maxWidth, minWidth, al
164
163
  copyOptionalAttrsFromMediaState(mediaState, mediaNode);
165
164
  return mediaSingle.createChecked(extendedMediaSingleAttrs, mediaNode);
166
165
  };
167
- export function transformSliceForMedia(slice, schema) {
168
- const {
169
- mediaSingle,
170
- layoutSection,
171
- table,
172
- bulletList,
173
- orderedList,
174
- media,
175
- mediaInline,
176
- expand,
177
- nestedExpand
178
- } = schema.nodes;
179
- return selection => {
180
- let newSlice = slice;
181
- if (hasParentNodeOfType([layoutSection, table, bulletList, orderedList, expand, nestedExpand])(selection)) {
182
- newSlice = mapSlice(newSlice, node => {
183
- const extendedOrLegacyAttrs = getBooleanFF('platform.editor.media.extended-resize-experience') ? {
184
- layout: node.attrs.layout,
185
- widthType: node.attrs.widthType,
186
- width: node.attrs.width
187
- } : {
188
- layout: node.attrs.layout
189
- };
190
- let attrs = {};
191
- if (hasParentNodeOfType([layoutSection, table])(selection)) {
192
- // Supports layouts
193
- attrs = {
194
- ...extendedOrLegacyAttrs
195
- };
196
- } else if (hasParentNodeOfType([bulletList, orderedList, expand, nestedExpand])(selection)) {
197
- // does not support other layouts
198
- attrs = {
199
- ...extendedOrLegacyAttrs,
200
- layout: 'center'
201
- };
202
- }
203
- return node.type.name === 'mediaSingle' ? mediaSingle.createChecked(attrs, node.content, node.marks) : node;
204
- });
205
- }
206
- const __mediaTraceId = getRandomHex(8);
207
- newSlice = mapSlice(newSlice, node => {
208
- // This logic is duplicated in editor-plugin-ai where external images can be inserted
209
- // from external sources through the use of AI. The editor-plugin-ai package is avoiding
210
- // sharing dependencies with editor-core to support products using it with various versions
211
- // of editor packages.
212
- // The duplication is in the following file:
213
- // packages/editor/editor-plugin-ai/src/prebuilt/content-transformers/markdown-to-pm/markdown-transformer.ts
214
- if (node.type.name === 'media') {
215
- return media.createChecked({
216
- ...node.attrs,
217
- __external: node.attrs.type === 'external',
218
- __mediaTraceId: node.attrs.type === 'external' ? null : __mediaTraceId
219
- }, node.content, node.marks);
220
- }
221
- if (node.type.name === 'mediaInline') {
222
- return mediaInline.createChecked({
223
- ...node.attrs,
224
- __mediaTraceId
225
- }, node.content, node.marks);
226
- }
227
- return node;
228
- });
229
- return newSlice;
230
- };
231
- }
232
166
  export function isCaptionNode(editorView) {
233
167
  const {
234
168
  $from
@@ -6,7 +6,7 @@ import keymap from './pm-plugins/keymaps';
6
6
  import { addAnalytics, ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, INPUT_METHOD, EVENT_TYPE } from '../analytics';
7
7
  import { IconPanel, IconPanelNote, IconPanelSuccess, IconPanelWarning, IconPanelError } from '@atlaskit/editor-common/quick-insert';
8
8
  import { createWrapSelectionTransaction } from '@atlaskit/editor-common/utils';
9
- import { messages } from '@atlaskit/editor-plugin-block-type/messages';
9
+ import { blockTypeMessages } from '@atlaskit/editor-common/messages';
10
10
  import { IconCustomPanel } from '@atlaskit/editor-common/quick-insert';
11
11
  import { T50 } from '@atlaskit/theme/colors';
12
12
  import { insertPanelWithAnalytics } from './actions';
@@ -46,9 +46,9 @@ const panelPlugin = ({
46
46
  }) => {
47
47
  let quickInsertOptions = [{
48
48
  id: 'infopanel',
49
- title: formatMessage(messages.infoPanel),
49
+ title: formatMessage(blockTypeMessages.infoPanel),
50
50
  keywords: ['panel'],
51
- description: formatMessage(messages.infoPanelDescription),
51
+ description: formatMessage(blockTypeMessages.infoPanelDescription),
52
52
  priority: 800,
53
53
  icon: () => /*#__PURE__*/React.createElement(IconPanel, null),
54
54
  action(insert, state) {
@@ -61,8 +61,8 @@ const panelPlugin = ({
61
61
  }
62
62
  }, {
63
63
  id: 'notepanel',
64
- title: formatMessage(messages.notePanel),
65
- description: formatMessage(messages.notePanelDescription),
64
+ title: formatMessage(blockTypeMessages.notePanel),
65
+ description: formatMessage(blockTypeMessages.notePanelDescription),
66
66
  priority: 1000,
67
67
  icon: () => /*#__PURE__*/React.createElement(IconPanelNote, null),
68
68
  action(insert, state) {
@@ -75,8 +75,8 @@ const panelPlugin = ({
75
75
  }
76
76
  }, {
77
77
  id: 'successpanel',
78
- title: formatMessage(messages.successPanel),
79
- description: formatMessage(messages.successPanelDescription),
78
+ title: formatMessage(blockTypeMessages.successPanel),
79
+ description: formatMessage(blockTypeMessages.successPanelDescription),
80
80
  keywords: ['tip'],
81
81
  priority: 1000,
82
82
  icon: () => /*#__PURE__*/React.createElement(IconPanelSuccess, null),
@@ -90,8 +90,8 @@ const panelPlugin = ({
90
90
  }
91
91
  }, {
92
92
  id: 'warningpanel',
93
- title: formatMessage(messages.warningPanel),
94
- description: formatMessage(messages.warningPanelDescription),
93
+ title: formatMessage(blockTypeMessages.warningPanel),
94
+ description: formatMessage(blockTypeMessages.warningPanelDescription),
95
95
  priority: 1000,
96
96
  icon: () => /*#__PURE__*/React.createElement(IconPanelWarning, null),
97
97
  action(insert, state) {
@@ -104,8 +104,8 @@ const panelPlugin = ({
104
104
  }
105
105
  }, {
106
106
  id: 'errorpanel',
107
- title: formatMessage(messages.errorPanel),
108
- description: formatMessage(messages.errorPanelDescription),
107
+ title: formatMessage(blockTypeMessages.errorPanel),
108
+ description: formatMessage(blockTypeMessages.errorPanelDescription),
109
109
  priority: 1000,
110
110
  icon: () => /*#__PURE__*/React.createElement(IconPanelError, null),
111
111
  action(insert, state) {
@@ -120,8 +120,8 @@ const panelPlugin = ({
120
120
  if (options.allowCustomPanel && options.allowCustomPanelEdit) {
121
121
  quickInsertOptions.push({
122
122
  id: 'custompanel',
123
- title: formatMessage(messages.customPanel),
124
- description: formatMessage(messages.customPanelDescription),
123
+ title: formatMessage(blockTypeMessages.customPanel),
124
+ description: formatMessage(blockTypeMessages.customPanelDescription),
125
125
  priority: 1000,
126
126
  icon: () => /*#__PURE__*/React.createElement(IconCustomPanel, null),
127
127
  action(insert, state) {
@@ -6,10 +6,9 @@ import uuid from 'uuid/v4';
6
6
  import { replaceSelectedTable } from '@atlaskit/editor-tables/utils';
7
7
  import { compose, insideTable, isParagraph, isText, isLinkMark, insideTableCell, isInListItem } from '../../utils';
8
8
  import { mapSlice } from '../../utils/slice';
9
- import { INPUT_METHOD } from '../analytics';
9
+ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
10
10
  import { GapCursorSelection, Side } from '@atlaskit/editor-common/selection';
11
11
  import { runMacroAutoConvert } from '../macro';
12
- import { insertMediaAsMediaSingle } from '../media/utils/media-single';
13
12
  import { addReplaceSelectedTableAnalytics, applyTextMarksToSlice, hasOnlyNodesOfType } from './util';
14
13
  import { linkifyContent, isListItemNode, isListNode, canLinkBeCreatedInRange } from '@atlaskit/editor-common/utils';
15
14
  import { insertSliceForLists } from './edge-cases';
@@ -555,12 +554,13 @@ function isOnlyMediaSingle(state, slice) {
555
554
  } = state.schema.nodes;
556
555
  return mediaSingle && slice.content.childCount === 1 && slice.content.firstChild.type === mediaSingle;
557
556
  }
558
- export function handleMediaSingle(inputMethod, editorAnalyticsAPI) {
557
+ export function handleMediaSingle(inputMethod, insertMediaAsMediaSingle) {
559
558
  return function (slice) {
560
559
  return (state, dispatch, view) => {
561
560
  if (view) {
562
561
  if (isOnlyMedia(state, slice)) {
563
- return insertMediaAsMediaSingle(view, slice.content.firstChild, inputMethod, editorAnalyticsAPI);
562
+ var _insertMediaAsMediaSi;
563
+ return (_insertMediaAsMediaSi = insertMediaAsMediaSingle === null || insertMediaAsMediaSingle === void 0 ? void 0 : insertMediaAsMediaSingle(view, slice.content.firstChild, inputMethod)) !== null && _insertMediaAsMediaSi !== void 0 ? _insertMediaAsMediaSi : false;
564
564
  }
565
565
  if (insideTable(state) && isOnlyMediaSingle(state, slice)) {
566
566
  const tr = state.tr.replaceSelection(slice);
@@ -0,0 +1,176 @@
1
+ import { hasParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
2
+ import { mapSlice, unwrap, removeNestedEmptyEls, walkUpTreeUntil } from '@atlaskit/editor-common/utils';
3
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
4
+ import { getRandomHex } from '@atlaskit/media-common';
5
+ export function transformSliceForMedia(slice, schema) {
6
+ const {
7
+ mediaSingle,
8
+ layoutSection,
9
+ table,
10
+ bulletList,
11
+ orderedList,
12
+ media,
13
+ mediaInline,
14
+ expand,
15
+ nestedExpand
16
+ } = schema.nodes;
17
+ return selection => {
18
+ let newSlice = slice;
19
+ if (hasParentNodeOfType([layoutSection, table, bulletList, orderedList, expand, nestedExpand])(selection)) {
20
+ newSlice = mapSlice(newSlice, node => {
21
+ const extendedOrLegacyAttrs = getBooleanFF('platform.editor.media.extended-resize-experience') ? {
22
+ layout: node.attrs.layout,
23
+ widthType: node.attrs.widthType,
24
+ width: node.attrs.width
25
+ } : {
26
+ layout: node.attrs.layout
27
+ };
28
+ let attrs = {};
29
+ if (hasParentNodeOfType([layoutSection, table])(selection)) {
30
+ // Supports layouts
31
+ attrs = {
32
+ ...extendedOrLegacyAttrs
33
+ };
34
+ } else if (hasParentNodeOfType([bulletList, orderedList, expand, nestedExpand])(selection)) {
35
+ // does not support other layouts
36
+ attrs = {
37
+ ...extendedOrLegacyAttrs,
38
+ layout: 'center'
39
+ };
40
+ }
41
+ return node.type.name === 'mediaSingle' ? mediaSingle.createChecked(attrs, node.content, node.marks) : node;
42
+ });
43
+ }
44
+ const __mediaTraceId = getRandomHex(8);
45
+ newSlice = mapSlice(newSlice, node => {
46
+ // This logic is duplicated in editor-plugin-ai where external images can be inserted
47
+ // from external sources through the use of AI. The editor-plugin-ai package is avoiding
48
+ // sharing dependencies with editor-core to support products using it with various versions
49
+ // of editor packages.
50
+ // The duplication is in the following file:
51
+ // packages/editor/editor-plugin-ai/src/prebuilt/content-transformers/markdown-to-pm/markdown-transformer.ts
52
+ if (node.type.name === 'media') {
53
+ return media.createChecked({
54
+ ...node.attrs,
55
+ __external: node.attrs.type === 'external',
56
+ __mediaTraceId: node.attrs.type === 'external' ? null : __mediaTraceId
57
+ }, node.content, node.marks);
58
+ }
59
+ if (node.type.name === 'mediaInline') {
60
+ return mediaInline.createChecked({
61
+ ...node.attrs,
62
+ __mediaTraceId
63
+ }, node.content, node.marks);
64
+ }
65
+ return node;
66
+ });
67
+ return newSlice;
68
+ };
69
+ }
70
+
71
+ // TODO move this to editor-common
72
+ export const isImage = fileType => {
73
+ return !!fileType && (fileType.indexOf('image/') > -1 || fileType.indexOf('video/') > -1);
74
+ };
75
+ export const transformSliceToCorrectMediaWrapper = (slice, schema) => {
76
+ const {
77
+ mediaGroup,
78
+ mediaSingle,
79
+ media
80
+ } = schema.nodes;
81
+ return mapSlice(slice, (node, parent) => {
82
+ if (!parent && node.type === media) {
83
+ if (mediaSingle && (isImage(node.attrs.__fileMimeType) || node.attrs.type === 'external')) {
84
+ return mediaSingle.createChecked({}, node);
85
+ } else {
86
+ return mediaGroup.createChecked({}, [node]);
87
+ }
88
+ }
89
+ return node;
90
+ });
91
+ };
92
+
93
+ /**
94
+ * Check base styles to see if an element will be invisible when rendered in a document.
95
+ * @param element
96
+ */
97
+ const isElementInvisible = element => {
98
+ return element.style.opacity === '0' || element.style.display === 'none' || element.style.visibility === 'hidden';
99
+ };
100
+ const VALID_TAGS_CONTAINER = ['DIV', 'TD'];
101
+ function canContainImage(element) {
102
+ if (!element) {
103
+ return false;
104
+ }
105
+ return VALID_TAGS_CONTAINER.indexOf(element.tagName) !== -1;
106
+ }
107
+
108
+ /**
109
+ * Given a html string, we attempt to hoist any nested `<img>` tags,
110
+ * not directly wrapped by a `<div>` as ProseMirror no-op's
111
+ * on those scenarios.
112
+ * @param html
113
+ */
114
+ export const unwrapNestedMediaElements = html => {
115
+ const parser = new DOMParser();
116
+ let doc = parser.parseFromString(html, 'text/html');
117
+ const wrapper = doc.body;
118
+
119
+ // Remove Google Doc's wrapper <b> el
120
+ const docsWrapper = wrapper.querySelector('b[id^="docs-internal-guid-"]');
121
+ if (docsWrapper) {
122
+ unwrap(wrapper, docsWrapper);
123
+ }
124
+ const imageTags = wrapper.querySelectorAll('img');
125
+ if (!imageTags.length) {
126
+ return html;
127
+ }
128
+ imageTags.forEach(imageTag => {
129
+ // Capture the immediate parent, we may remove the media from here later.
130
+ const mediaParent = imageTag.parentElement;
131
+ if (!mediaParent) {
132
+ return;
133
+ }
134
+
135
+ // If either the parent or the image itself contains styles that would make
136
+ // them invisible on copy, dont paste them.
137
+ if (isElementInvisible(mediaParent) || isElementInvisible(imageTag)) {
138
+ mediaParent.removeChild(imageTag);
139
+ return;
140
+ }
141
+
142
+ // If its wrapped by a valid container we assume its safe to bypass.
143
+ // ProseMirror should handle these cases properly.
144
+ if (canContainImage(mediaParent) || mediaParent instanceof HTMLSpanElement && mediaParent.closest('[class*="emoji-common"]')) {
145
+ return;
146
+ }
147
+
148
+ // Find the top most element that the parent has a valid container for the image.
149
+ // Stop just before found the wrapper
150
+ const insertBeforeElement = walkUpTreeUntil(mediaParent, element => {
151
+ // If is at the top just use this element as reference
152
+ if (element.parentElement === wrapper) {
153
+ return true;
154
+ }
155
+ return canContainImage(element.parentElement);
156
+ });
157
+
158
+ // Here we try to insert the media right after its top most valid parent element
159
+ // Unless its the last element in our structure then we will insert above it.
160
+ if (insertBeforeElement && insertBeforeElement.parentElement) {
161
+ // Insert as close as possible to the most closest valid element index in the tree.
162
+ insertBeforeElement.parentElement.insertBefore(imageTag, insertBeforeElement.nextElementSibling || insertBeforeElement);
163
+
164
+ // Attempt to clean up lines left behind by the image
165
+ mediaParent.innerText = mediaParent.innerText.trim();
166
+ // Walk up and delete empty elements left over after removing the image tag
167
+ removeNestedEmptyEls(mediaParent);
168
+ }
169
+ });
170
+
171
+ // If last child is a hardbreak we don't want it
172
+ if (wrapper.lastElementChild && wrapper.lastElementChild.tagName === 'BR') {
173
+ wrapper.removeChild(wrapper.lastElementChild);
174
+ }
175
+ return wrapper.innerHTML;
176
+ };
@@ -238,9 +238,9 @@ export const handlePasteIntoCaptionWithAnalytics = (view, event, slice, type) =>
238
238
  export const handleCodeBlockWithAnalytics = (view, event, slice, text) => injectAnalyticsPayloadBeforeCommand(createPasteAnalyticsPayloadBySelection(event, slice, {
239
239
  type: PasteTypes.plain
240
240
  }))(handleCodeBlock(text));
241
- export const handleMediaSingleWithAnalytics = (view, event, slice, type, editorAnalyticsAPI) => injectAnalyticsPayloadBeforeCommand(createPasteAnalyticsPayloadBySelection(event, slice, {
241
+ export const handleMediaSingleWithAnalytics = (view, event, slice, type, insertMediaAsMediaSingle) => injectAnalyticsPayloadBeforeCommand(createPasteAnalyticsPayloadBySelection(event, slice, {
242
242
  type
243
- }))(handleMediaSingle(INPUT_METHOD.CLIPBOARD, editorAnalyticsAPI)(slice));
243
+ }))(handleMediaSingle(INPUT_METHOD.CLIPBOARD, insertMediaAsMediaSingle)(slice));
244
244
  export const handlePastePreservingMarksWithAnalytics = (view, event, slice, type, pluginInjectionApi) => {
245
245
  var _pluginInjectionApi$c3, _pluginInjectionApi$c4;
246
246
  return injectAnalyticsPayloadBeforeCommand(createPasteAnalyticsPayloadBySelection(event, slice, {