UNPKG

@atlaskit/editor-plugin-media

Version:

Media plugin for @atlaskit/editor-core

173 lines (171 loc) 8.55 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import memoizeOne from 'memoize-one'; import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics'; import { safeInsert, shouldSplitSelectedNodeOnNodeInsertion } from '@atlaskit/editor-common/insert'; import { getMaxWidthForNestedNodeNext, getMediaSingleInitialWidth, MEDIA_SINGLE_DEFAULT_MIN_PIXEL_WIDTH, MEDIA_SINGLE_VIDEO_MIN_PIXEL_WIDTH } from '@atlaskit/editor-common/media-single'; import { atTheBeginningOfBlock } from '@atlaskit/editor-common/selection'; import { checkNodeDown, isEmptyParagraph } from '@atlaskit/editor-common/utils'; import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model'; import { safeInsert as pmSafeInsert } from '@atlaskit/editor-prosemirror/utils'; import { getBooleanFF } from '@atlaskit/platform-feature-flags'; import { copyOptionalAttrsFromMediaState } from '../utils/media-common'; import { isImage } from './is-type'; var getInsertMediaAnalytics = function getInsertMediaAnalytics(inputMethod, fileExtension) { return { action: ACTION.INSERTED, actionSubject: ACTION_SUBJECT.DOCUMENT, actionSubjectId: ACTION_SUBJECT_ID.MEDIA, attributes: { inputMethod: inputMethod, fileExtension: fileExtension, type: ACTION_SUBJECT_ID.MEDIA_SINGLE }, eventType: EVENT_TYPE.TRACK }; }; function shouldAddParagraph(state) { return atTheBeginningOfBlock(state) && !checkNodeDown(state.selection, state.doc, isEmptyParagraph); } function insertNodesWithOptionalParagraph(nodes) { var analyticsAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var editorAnalyticsAPI = arguments.length > 2 ? arguments[2] : undefined; return function (state, dispatch) { var tr = state.tr, schema = state.schema; var paragraph = schema.nodes.paragraph; var inputMethod = analyticsAttributes.inputMethod, fileExtension = analyticsAttributes.fileExtension; var openEnd = 0; if (shouldAddParagraph(state)) { nodes.push(paragraph.create()); openEnd = 1; } tr.replaceSelection(new Slice(Fragment.from(nodes), 0, openEnd)); if (inputMethod) { editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent(getInsertMediaAnalytics(inputMethod, fileExtension))(tr); } if (dispatch) { dispatch(tr); } return true; }; } export var isMediaSingle = function isMediaSingle(schema, fileMimeType) { return !!schema.nodes.mediaSingle && isImage(fileMimeType); }; export var insertMediaAsMediaSingle = function insertMediaAsMediaSingle(view, node, inputMethod, editorAnalyticsAPI) { var state = view.state, dispatch = view.dispatch; var _state$schema$nodes = state.schema.nodes, mediaSingle = _state$schema$nodes.mediaSingle, media = _state$schema$nodes.media; if (!mediaSingle) { return false; } // if not an image type media node if (node.type !== media || !isImage(node.attrs.__fileMimeType) && node.attrs.type !== 'external') { return false; } var mediaSingleNode = mediaSingle.create({}, node); var nodes = [mediaSingleNode]; var analyticsAttributes = { inputMethod: inputMethod, fileExtension: node.attrs.__fileMimeType }; return insertNodesWithOptionalParagraph(nodes, analyticsAttributes, editorAnalyticsAPI)(state, dispatch); }; export var insertMediaSingleNode = function insertMediaSingleNode(view, mediaState, inputMethod, collection, alignLeftOnInsert, newInsertionBehaviour, widthPluginState, editorAnalyticsAPI) { var _state$selection$$fro; if (collection === undefined) { return false; } var state = view.state, dispatch = view.dispatch; var grandParentNodeType = (_state$selection$$fro = state.selection.$from.node(-1)) === null || _state$selection$$fro === void 0 ? void 0 : _state$selection$$fro.type; var parentNodeType = state.selection.$from.parent.type; // add undefined as fallback as we don't want media single width to have upper limit as 0 // if widthPluginState.width is 0, default 760 will be used var contentWidth = getMaxWidthForNestedNodeNext(view, state.selection.$from.pos, true) || (widthPluginState === null || widthPluginState === void 0 ? void 0 : widthPluginState.lineLength) || (widthPluginState === null || widthPluginState === void 0 ? void 0 : widthPluginState.width) || undefined; var node = createMediaSingleNode(state.schema, collection, contentWidth, mediaState.status !== 'error' && isVideo(mediaState.fileMimeType) ? MEDIA_SINGLE_VIDEO_MIN_PIXEL_WIDTH : MEDIA_SINGLE_DEFAULT_MIN_PIXEL_WIDTH, alignLeftOnInsert)(mediaState); var fileExtension; if (mediaState.fileName) { var extensionIdx = mediaState.fileName.lastIndexOf('.'); fileExtension = extensionIdx >= 0 ? mediaState.fileName.substring(extensionIdx + 1) : undefined; } // should split if media is valid content for the grandparent of the selected node // and the parent node is a paragraph if (shouldSplitSelectedNodeOnNodeInsertion({ parentNodeType: parentNodeType, grandParentNodeType: grandParentNodeType, content: node })) { insertNodesWithOptionalParagraph([node], { fileExtension: fileExtension, inputMethod: inputMethod }, editorAnalyticsAPI)(state, dispatch); } else { var tr = null; if (newInsertionBehaviour) { tr = safeInsert(node, state.selection.from)(state.tr); } if (!tr) { var content = shouldAddParagraph(view.state) ? Fragment.fromArray([node, state.schema.nodes.paragraph.create()]) : node; tr = pmSafeInsert(content, undefined, true)(state.tr); } if (inputMethod) { editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent(getInsertMediaAnalytics(inputMethod, fileExtension))(tr); } dispatch(tr); } return true; }; export var createMediaSingleNode = function createMediaSingleNode(schema, collection, maxWidth, minWidth, alignLeftOnInsert) { return function (mediaState) { var id = mediaState.id, dimensions = mediaState.dimensions, contextId = mediaState.contextId, _mediaState$scaleFact = mediaState.scaleFactor, scaleFactor = _mediaState$scaleFact === void 0 ? 1 : _mediaState$scaleFact; var _ref = dimensions || { height: undefined, width: undefined }, width = _ref.width, height = _ref.height; var _schema$nodes = schema.nodes, media = _schema$nodes.media, mediaSingle = _schema$nodes.mediaSingle; var scaledWidth = width && Math.round(width / scaleFactor); var mediaNode = media.create({ id: id, type: 'file', collection: collection, contextId: contextId, width: scaledWidth, height: height && Math.round(height / scaleFactor) }); var mediaSingleAttrs = alignLeftOnInsert ? { layout: 'align-start' } : {}; var extendedMediaSingleAttrs = getBooleanFF('platform.editor.media.extended-resize-experience') ? _objectSpread(_objectSpread({}, mediaSingleAttrs), {}, { width: getMediaSingleInitialWidth(scaledWidth, maxWidth, minWidth), // TODO: change to use enum widthType: 'pixel' }) : mediaSingleAttrs; copyOptionalAttrsFromMediaState(mediaState, mediaNode); return mediaSingle.createChecked(extendedMediaSingleAttrs, mediaNode); }; }; export function isCaptionNode(editorView) { var $from = editorView.state.selection.$from; var immediateWrapperParentNode = editorView.state.doc.nodeAt($from.before(Math.max($from.depth, 1))); if (immediateWrapperParentNode && immediateWrapperParentNode.type.name === 'caption') { return true; } return false; } export var isVideo = memoizeOne(function (fileType) { return !!fileType && fileType.includes('video'); });