UNPKG

@atlaskit/editor-plugin-image-upload

Version:

Image upload plugin for @atlaskit/editor-core

196 lines (190 loc) 8.57 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.createPlugin = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _paste = require("@atlaskit/editor-common/paste"); var _safePlugin = require("@atlaskit/editor-common/safe-plugin"); var _clipboard = require("../ui/hooks/clipboard"); var _dragDrop = require("../ui/hooks/drag-drop"); var _utils = require("../ui/hooks/utils"); var _commands = require("./commands"); var _pluginKey = require("./plugin-key"); 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) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /** * Microsoft Office includes a screenshot image when copying text content. * * This function determines whether or not we can ignore the image if it * came from MS Office. We do this by checking for * * - plain text * - HTML text which includes the MS Office namespace * - the number of files and the file name/type * * It is easy to manually verify this using by using Office on Mac * (or Excel if on Windows) and pasting into * https://evercoder.github.io/clipboard-inspector/ * * Note: image content in Word is stored in the `text/html` portion * of the clipboard, not under `files` attachment like the screenshot. * * @returns boolean True if the paste event contains a screenshot from MS Office */ var hasScreenshotImageFromMSOffice = function hasScreenshotImageFromMSOffice(ev) { var _ref = ev, clipboardData = _ref.clipboardData; if (!clipboardData || clipboardData.files.length !== 1) { return false; } var textPlain = !!clipboardData.getData('text/plain'); var textHtml = clipboardData.getData('text/html'); var isOfficeXMLNamespace = textHtml.includes('urn:schemas-microsoft-com:office:office'); var file = clipboardData.files[0]; var isImagePNG = file.type === 'image/png' && file.name === 'image.png'; return isImagePNG && textPlain && isOfficeXMLNamespace; }; var createReferenceEventFromEvent = function createReferenceEventFromEvent(event) { var _event$dataTransfer, _event$clipboardData; if (!(0, _dragDrop.isDragEvent)(event) && !(0, _clipboard.isClipboardEvent)(event)) { return null; } // Get files list and early exit if files is undefined var files = (0, _dragDrop.isDragEvent)(event) ? (_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.files : (_event$clipboardData = event.clipboardData) === null || _event$clipboardData === void 0 ? void 0 : _event$clipboardData.files; if (!files) { return null; } // Convert filelist into an array var filesArray = Array.from(files); // Creating a new DataTransfer object should remove any mutation that could be possible from the original event var dataTransfer = filesArray.reduce(function (acc, value) { acc.items.add(value); return acc; }, new DataTransfer()); return _objectSpread(_objectSpread({ type: (0, _dragDrop.isDragEvent)(event) ? 'drop' : 'paste' }, (0, _dragDrop.isDragEvent)(event) && { dataTransfer: dataTransfer }), (0, _clipboard.isClipboardEvent)(event) && { clipboardData: dataTransfer }); }; var createDOMHandler = function createDOMHandler(pred, _eventName, uploadHandlerReference) { return function (view, event) { if (!pred(event)) { return false; } var shouldUpload = !hasScreenshotImageFromMSOffice(event); var referenceEvent = createReferenceEventFromEvent(event); if (shouldUpload && referenceEvent) { event.preventDefault(); event.stopPropagation(); // Insert external image into document if (uploadHandlerReference.current) { uploadHandlerReference.current(referenceEvent, function (options) { (0, _commands.insertExternalImage)(options)(view.state, view.dispatch); }); } // Start image upload (0, _commands.startImageUpload)(referenceEvent)(view.state, view.dispatch); } return shouldUpload; }; }; var getNewActiveUpload = function getNewActiveUpload(tr, pluginState) { var meta = tr.getMeta(_pluginKey.stateKey); if (meta && meta.name === 'START_UPLOAD') { return { event: meta.event }; } return pluginState.activeUpload; }; var createPlugin = exports.createPlugin = function createPlugin(uploadHandlerReference) { return function (_ref2) { var dispatch = _ref2.dispatch, providerFactory = _ref2.providerFactory; return new _safePlugin.SafePlugin({ state: { init: function init(_config, state) { return { active: false, enabled: (0, _utils.canInsertMedia)(state), hidden: !state.schema.nodes.media || !state.schema.nodes.mediaSingle }; }, apply: function apply(tr, pluginState, _oldState, newState) { var newActive = (0, _utils.isMediaSelected)(newState); var newEnabled = (0, _utils.canInsertMedia)(newState); var newActiveUpload = getNewActiveUpload(tr, pluginState); if (newActive !== pluginState.active || newEnabled !== pluginState.enabled || newActiveUpload !== pluginState.activeUpload) { var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, { active: newActive, enabled: newEnabled, activeUpload: newActiveUpload }); dispatch(_pluginKey.stateKey, newPluginState); return newPluginState; } return pluginState; } }, key: _pluginKey.stateKey, view: function view() { var handleProvider = /*#__PURE__*/function () { var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(name, provider) { var imageUploadProvider; return _regenerator.default.wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: if (!(name !== 'imageUploadProvider' || !provider)) { _context.next = 2; break; } return _context.abrupt("return"); case 2: _context.prev = 2; _context.next = 5; return provider; case 5: imageUploadProvider = _context.sent; uploadHandlerReference.current = imageUploadProvider; _context.next = 12; break; case 9: _context.prev = 9; _context.t0 = _context["catch"](2); uploadHandlerReference.current = null; case 12: case "end": return _context.stop(); } }, _callee, null, [[2, 9]]); })); return function handleProvider(_x, _x2) { return _ref3.apply(this, arguments); }; }(); providerFactory.subscribe('imageUploadProvider', handleProvider); return { destroy: function destroy() { uploadHandlerReference.current = null; providerFactory.unsubscribe('imageUploadProvider', handleProvider); } }; }, props: { handleDOMEvents: { drop: createDOMHandler(_dragDrop.isDroppedFile, 'atlassian.editor.image.drop', uploadHandlerReference), paste: createDOMHandler(function (event) { return (0, _paste.isPastedFile)(event); }, 'atlassian.editor.image.paste', uploadHandlerReference) } } }); }; };