UNPKG

@atlaskit/editor-plugin-extension

Version:

editor-plugin-extension plugin for @atlaskit/editor-core

289 lines (285 loc) 13.6 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.onCopyFailed = exports.getSelectedExtension = exports.getSelectedDomElement = exports.getNodeTypesReferenced = exports.getDataConsumerMark = exports.findNodePosWithLocalId = exports.findExtensionWithLocalId = exports.copyUnsupportedContentToClipboard = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _analytics = require("@atlaskit/editor-common/analytics"); var _clipboard = require("@atlaskit/editor-common/clipboard"); var _utils = require("@atlaskit/editor-common/utils"); var _editorJsonTransformer = require("@atlaskit/editor-json-transformer"); var _utils2 = require("@atlaskit/editor-prosemirror/utils"); var _resource = require("@atlaskit/mention/resource"); function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } var getSelectedExtension = exports.getSelectedExtension = function getSelectedExtension(state) { var searchParent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var _state$schema$nodes = state.schema.nodes, inlineExtension = _state$schema$nodes.inlineExtension, extension = _state$schema$nodes.extension, bodiedExtension = _state$schema$nodes.bodiedExtension, multiBodiedExtension = _state$schema$nodes.multiBodiedExtension; var nodeTypes = [extension, bodiedExtension, inlineExtension, multiBodiedExtension]; return (0, _utils2.findSelectedNodeOfType)(nodeTypes)(state.selection) || searchParent && (0, _utils2.findParentNodeOfType)(nodeTypes)(state.selection) || undefined; }; var findExtensionWithLocalId = exports.findExtensionWithLocalId = function findExtensionWithLocalId(state, localId) { var selectedExtension = getSelectedExtension(state, true); if (!localId) { return selectedExtension; } if (selectedExtension && selectedExtension.node.attrs.localId === localId) { return selectedExtension; } var _state$schema$nodes2 = state.schema.nodes, inlineExtension = _state$schema$nodes2.inlineExtension, extension = _state$schema$nodes2.extension, bodiedExtension = _state$schema$nodes2.bodiedExtension, multiBodiedExtension = _state$schema$nodes2.multiBodiedExtension; var nodeTypes = [extension, bodiedExtension, inlineExtension, multiBodiedExtension]; var matched; state.doc.descendants(function (node, pos) { if (nodeTypes.includes(node.type) && node.attrs.localId === localId) { matched = { node: node, pos: pos }; } }); return matched; }; var getSelectedDomElement = exports.getSelectedDomElement = function getSelectedDomElement(schema, domAtPos, selectedExtensionNode) { // Ignored via go/ees005 // eslint-disable-next-line @atlaskit/editor/no-as-casting var selectedExtensionDomNode = (0, _utils2.findDomRefAtPos)(selectedExtensionNode.pos, domAtPos); var isContentExtension = selectedExtensionNode.node.type !== schema.nodes.bodiedExtension; return ( // Content extension can be nested in bodied-extension, the following check is necessary for that case (isContentExtension // Search down ? selectedExtensionDomNode.querySelector('.extension-container') // Try searching up and then down : (0, _utils.closestElement)(selectedExtensionDomNode, '.extension-container') || selectedExtensionDomNode.querySelector('.extension-container')) || selectedExtensionDomNode ); }; var getDataConsumerMark = exports.getDataConsumerMark = function getDataConsumerMark(newNode) { var _newNode$marks; return (_newNode$marks = newNode.marks) === null || _newNode$marks === void 0 ? void 0 : _newNode$marks.find(function (mark) { return mark.type.name === 'dataConsumer'; }); }; var getNodeTypesReferenced = exports.getNodeTypesReferenced = function getNodeTypesReferenced(ids, state) { return (0, _utils.findNodePosByLocalIds)(state, ids, { includeDocNode: true }).map(function (_ref) { var node = _ref.node; return node.type.name; }); }; var findNodePosWithLocalId = exports.findNodePosWithLocalId = function findNodePosWithLocalId(state, localId) { var nodes = (0, _utils.findNodePosByLocalIds)(state, [localId]); return nodes.length >= 1 ? nodes[0] : undefined; }; /** * Converts a ProseMirror node to its text representation. * Handles text nodes with marks (links) and inline nodes (status, mention, emoji). * Returns the content for this node, with a trailing separator for text blocks. */ var convertNodeToText = function convertNodeToText(node, mentionSet, parent, locale) { if (node.isInline) { var schema = node.type.schema; var finalText = ''; if (node.isText) { finalText = node.text || ''; if (node.marks.length > 0) { var _iterator = _createForOfIteratorHelper(node.marks), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var mark = _step.value; // if it's link, include the href in the text if (mark.type === schema.marks.link) { var href = mark.attrs.href; var text = node.text || ''; // If the text differs from the href, include both if (text && text !== href) { finalText = "".concat(text, " ").concat(href); } else { finalText = href; } } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } } else { switch (node.type) { case schema.nodes.status: finalText = node.attrs.text || ''; break; case schema.nodes.mention: mentionSet.add(node.attrs.id); finalText = "@".concat(node.attrs.id); break; case schema.nodes.emoji: finalText = node.attrs.shortName || ''; break; case schema.nodes.date: var timestamp = new Date(Number(node.attrs.timestamp)); finalText = !isNaN(timestamp.getTime()) ? timestamp.toLocaleDateString(locale !== null && locale !== void 0 ? locale : 'en-US') : String(node.attrs.timestamp); break; default: finalText = node.textContent; break; } } if (parent && parent.isTextblock && node === parent.lastChild && parent.childCount > 0) { finalText += '\n\n'; } return finalText; } return ''; }; /** * Resolves mention IDs to their display names and replaces them in the text. * Returns the text with resolved mentions, or the original text if the provider is unavailable. */ var resolveMentionsInText = /*#__PURE__*/function () { var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(text, mentionSet, api) { var _api$mention; var mentionProvider, resolvedText, _iterator2, _step2, id, mention; return _regenerator.default.wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: mentionProvider = api === null || api === void 0 || (_api$mention = api.mention) === null || _api$mention === void 0 || (_api$mention = _api$mention.sharedState) === null || _api$mention === void 0 || (_api$mention = _api$mention.currentState()) === null || _api$mention === void 0 ? void 0 : _api$mention.mentionProvider; if (!(!mentionProvider || !(0, _resource.isResolvingMentionProvider)(mentionProvider))) { _context.next = 3; break; } return _context.abrupt("return", text); case 3: resolvedText = text; _iterator2 = _createForOfIteratorHelper(mentionSet); _context.prev = 5; _iterator2.s(); case 7: if ((_step2 = _iterator2.n()).done) { _context.next = 15; break; } id = _step2.value; _context.next = 11; return mentionProvider.resolveMentionName(id); case 11: mention = _context.sent; // eslint-disable-next-line @atlassian/perf-linting/no-expensive-split-replace -- Ignored via go/ees017 (to be fixed) resolvedText = resolvedText.replace("@".concat(id), "@".concat(mention.name) || '@…'); case 13: _context.next = 7; break; case 15: _context.next = 20; break; case 17: _context.prev = 17; _context.t0 = _context["catch"](5); _iterator2.e(_context.t0); case 20: _context.prev = 20; _iterator2.f(); return _context.finish(20); case 23: return _context.abrupt("return", resolvedText); case 24: case "end": return _context.stop(); } }, _callee, null, [[5, 17, 20, 23]]); })); return function resolveMentionsInText(_x, _x2, _x3) { return _ref2.apply(this, arguments); }; }(); /** * copying ADF from the unsupported content extension as text to clipboard */ var copyUnsupportedContentToClipboard = exports.copyUnsupportedContentToClipboard = /*#__PURE__*/function () { var _ref4 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(_ref3) { var locale, schema, unsupportedContent, api, transformer, pmNode, text, mentionSet; return _regenerator.default.wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: locale = _ref3.locale, schema = _ref3.schema, unsupportedContent = _ref3.unsupportedContent, api = _ref3.api; _context2.prev = 1; if (unsupportedContent) { _context2.next = 4; break; } throw new Error('No nested content found'); case 4: if (unsupportedContent.type !== 'doc') { unsupportedContent = { version: 1, type: 'doc', content: [unsupportedContent] }; } transformer = new _editorJsonTransformer.JSONTransformer(schema); pmNode = transformer.parse(unsupportedContent); text = ''; mentionSet = new Set(); pmNode.nodesBetween(0, pmNode.content.size, function (node, _pos, parent) { text += convertNodeToText(node, mentionSet, parent, locale); }); // Trim leading/trailing whitespace from the collected text text = text.trim(); _context2.next = 13; return resolveMentionsInText(text, mentionSet, api); case 13: text = _context2.sent; (0, _clipboard.copyToClipboard)(text); _context2.next = 20; break; case 17: _context2.prev = 17; _context2.t0 = _context2["catch"](1); throw _context2.t0 instanceof Error ? _context2.t0 : new Error('Failed to copy content'); case 20: case "end": return _context2.stop(); } }, _callee2, null, [[1, 17]]); })); return function copyUnsupportedContentToClipboard(_x4) { return _ref4.apply(this, arguments); }; }(); var onCopyFailed = exports.onCopyFailed = function onCopyFailed(_ref5) { var _extensionApi$analyti; var error = _ref5.error, extensionApi = _ref5.extensionApi, state = _ref5.state; var nodeWithPos = getSelectedExtension(state, true); if (!nodeWithPos) { return; } var node = nodeWithPos.node; var _node$attrs = node.attrs, extensionType = _node$attrs.extensionType, extensionKey = _node$attrs.extensionKey; extensionApi === null || extensionApi === void 0 || (_extensionApi$analyti = extensionApi.analytics) === null || _extensionApi$analyti === void 0 || _extensionApi$analyti.actions.fireAnalyticsEvent({ eventType: _analytics.EVENT_TYPE.OPERATIONAL, action: _analytics.ACTION.COPY_FAILED, actionSubject: _analytics.ACTION_SUBJECT.EXTENSION, actionSubjectId: node.type.name, attributes: { extensionKey: extensionKey, extensionType: extensionType, errorMessage: error.message, errorStack: error.stack } }); };