UNPKG

@atlaskit/editor-common

Version:

A package that contains common classes and components for editor and renderer

277 lines (265 loc) • 12.7 kB
import _typeof from "@babel/runtime/helpers/typeof"; import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; 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; } export var isReferencedSource = function isReferencedSource(state, node) { var _node$attrs, _node$marks; if (!node) { return false; } var found = false; // Handle nodes having 2 uuids. They could have a localId or a fragment. Regardless this needs // to check if either id is used by a data consumer. var localIds = new Set([(_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.localId, (_node$marks = node.marks) === null || _node$marks === void 0 || (_node$marks = _node$marks.find(function (mark) { return mark.type === state.schema.marks.fragment; })) === null || _node$marks === void 0 || (_node$marks = _node$marks.attrs) === null || _node$marks === void 0 ? void 0 : _node$marks.localId].filter(Boolean)); // If there are no uuids on the node then it's not possible for it to be referenced anywhere. if (!localIds.size) { return false; } state.doc.descendants(function (node) { var _dataConsumer$attrs$s, _dataConsumer$attrs$s2; if (found) { return false; } var dataConsumer = node.marks.find(function (mark) { return mark.type === state.schema.marks.dataConsumer; }); if (!dataConsumer) { return true; } found = (_dataConsumer$attrs$s = (_dataConsumer$attrs$s2 = dataConsumer.attrs.sources) === null || _dataConsumer$attrs$s2 === void 0 ? void 0 : _dataConsumer$attrs$s2.some(function (src) { return localIds.has(src); })) !== null && _dataConsumer$attrs$s !== void 0 ? _dataConsumer$attrs$s : false; return !found; }); return found; }; export var getConnections = function getConnections(state) { var result = {}; var doc = state.doc, schema = state.schema; // Keeps a map of all raw ids -> to their preferred normalised varient. A node with both fragmentMark & localId will // have both ids mapped here to the same normalized version. var normalizedIds = new Map(); var dataConsumerSources = new Map(); // Perform a prelim scan creating the initial id to connection link mappings. // This will also save a list of data sources consumed per node. doc.descendants(function (node, pos) { var _node$attrs2, _fragmentMark$attrs$l, _fragmentMark, _node$attrs3, _fragmentMark2, _node$attrs4, _fragmentMark3; var dataConsumer; var fragmentMark; node.marks.some(function (mark) { if (mark.type === schema.marks.dataConsumer) { dataConsumer = mark; } else if (mark.type === schema.marks.fragment) { fragmentMark = mark; } // Stop searching marks if we've found both consumer and fragment. return !!dataConsumer && !!fragmentMark; }); // If node cannot be referenced by any means then abort. if (!fragmentMark && !((_node$attrs2 = node.attrs) !== null && _node$attrs2 !== void 0 && _node$attrs2.localId)) { return true; } var normalizedId = (_fragmentMark$attrs$l = (_fragmentMark = fragmentMark) === null || _fragmentMark === void 0 || (_fragmentMark = _fragmentMark.attrs) === null || _fragmentMark === void 0 ? void 0 : _fragmentMark.localId) !== null && _fragmentMark$attrs$l !== void 0 ? _fragmentMark$attrs$l : (_node$attrs3 = node.attrs) === null || _node$attrs3 === void 0 ? void 0 : _node$attrs3.localId; if (!normalizedId) { return true; } if (!!((_fragmentMark2 = fragmentMark) !== null && _fragmentMark2 !== void 0 && (_fragmentMark2 = _fragmentMark2.attrs) !== null && _fragmentMark2 !== void 0 && _fragmentMark2.localId)) { normalizedIds.set(fragmentMark.attrs.localId, normalizedId); } if (!!((_node$attrs4 = node.attrs) !== null && _node$attrs4 !== void 0 && _node$attrs4.localId)) { normalizedIds.set(node.attrs.localId, normalizedId); } if (!!result[normalizedId]) { // Duplicate ID has been found, we'll care about the first one for now. return true; } result[normalizedId] = { localId: normalizedId, name: (_fragmentMark3 = fragmentMark) === null || _fragmentMark3 === void 0 || (_fragmentMark3 = _fragmentMark3.attrs) === null || _fragmentMark3 === void 0 ? void 0 : _fragmentMark3.name, node: node, pos: pos, targets: [] }; if (!!dataConsumer && dataConsumer.attrs.sources.length) { dataConsumerSources.set(normalizedId, dataConsumer.attrs.sources); } // Do not descend into children of a node which has a dataConsumer attached. This assumes all children of the node cannot // be referenced by another node. return !dataConsumer; }); // This 2nd-pass only looks at the consumer sources and updates all connections with the correct id refs. var _iterator = _createForOfIteratorHelper(dataConsumerSources), _step; try { var _loop = function _loop() { var _step$value = _slicedToArray(_step.value, 2), localId = _step$value[0], sources = _step$value[1]; // This is a ref to the node (connection link) which contains the consumer. sources.forEach(function (src) { var _normalizedIds$get; var normalizedId = (_normalizedIds$get = normalizedIds.get(src)) !== null && _normalizedIds$get !== void 0 ? _normalizedIds$get : src; var srcLink = result[normalizedId]; if (srcLink && normalizedId !== localId) { srcLink.targets.push(localId); } }); }; for (_iterator.s(); !(_step = _iterator.n()).done;) { _loop(); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return result; }; export var removeConnectedNodes = function removeConnectedNodes(state, node) { if (!node) { return state.tr; } var selectedLocalIds = getSelectedLocalIds(state, node); var allNodes = getConnections(state); var idsToBeDeleted = getIdsToBeDeleted(selectedLocalIds, allNodes); if (!(idsToBeDeleted !== null && idsToBeDeleted !== void 0 && idsToBeDeleted.length)) { return state.tr; } var tr = state.tr; var newTr = tr; idsToBeDeleted.forEach(function (id) { if (!allNodes[id]) { return; } var _allNodes$id = allNodes[id], node = _allNodes$id.node, pos = _allNodes$id.pos; newTr = newTr.delete(newTr.mapping.map(pos), newTr.mapping.map(node.nodeSize + pos)); }); return newTr; }; // find all ids need to be remove connected to selected extension var getIdsToBeDeleted = function getIdsToBeDeleted(selectedIds, allNodes) { if (!selectedIds.size) { return []; } var searchSet = _toConsumableArray(selectedIds); var deletedIds = new Set(); while (searchSet.length) { // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var id = searchSet.pop(); if (allNodes[id]) { var _allNodes$id$targets$, _allNodes$id2; deletedIds.add(allNodes[id].localId); searchSet = searchSet.concat((_allNodes$id$targets$ = (_allNodes$id2 = allNodes[id]) === null || _allNodes$id2 === void 0 ? void 0 : _allNodes$id2.targets.filter(function (targetId) { var _allNodes$targetId; return !deletedIds.has((_allNodes$targetId = allNodes[targetId]) === null || _allNodes$targetId === void 0 ? void 0 : _allNodes$targetId.localId); })) !== null && _allNodes$id$targets$ !== void 0 ? _allNodes$id$targets$ : []); } } return Array.from(deletedIds); }; // for get children info for confirmation dialog export var getChildrenInfo = function getChildrenInfo(state, node) { var allChildrenHadName = true; if (!node) { return []; } var childrenIdSet = new Set(); var childrenInfoArray = []; var allNodes = getConnections(state); var selectedNodeIds = getSelectedLocalIds(state, node); selectedNodeIds.forEach(function (id) { if (allNodes[id]) { allNodes[id].targets.forEach(childrenIdSet.add, childrenIdSet); } }); var _iterator2 = _createForOfIteratorHelper(childrenIdSet), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var id = _step2.value; if (!getNodeNameById(id, allNodes)) { allChildrenHadName = false; break; } else { childrenInfoArray.push({ id: id, name: getNodeNameById(id, allNodes), amount: getChildrenNodeAmount(id, allNodes) }); } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } return allChildrenHadName ? childrenInfoArray : []; }; var getChildrenNodeAmount = function getChildrenNodeAmount(id, allNodes) { var searchTerms = new Set([id]); var traverseHistory = new Map(); var childrenIds = new Set(); traverseHistory.set(id, false); while (searchTerms.size > 0) { var _searchTerms = _slicedToArray(searchTerms, 1), currTerm = _searchTerms[0]; var targets = getNodeTargetsById(currTerm, allNodes); targets.forEach(function (target) { var isTargetCounted = traverseHistory.get(target); if (!isTargetCounted) { searchTerms.add(target); childrenIds.add(target); } target !== id && childrenIds.add(target); }); traverseHistory.set(currTerm, true); searchTerms.delete(currTerm); } return childrenIds.size; }; // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any var getNodeTargetsById = function getNodeTargetsById(id, allNodes) { if (!id || !allNodes[id]) { return []; } return allNodes[id].targets; }; var getNodeNameById = function getNodeNameById(id, allNodes) { if (_typeof(id) === 'object') { var name; id.forEach(function (localId) { var _name, _allNodes$localId; name = (_name = name) !== null && _name !== void 0 ? _name : (_allNodes$localId = allNodes[localId]) === null || _allNodes$localId === void 0 ? void 0 : _allNodes$localId.name; }); return name || null; } if (!id || !allNodes[id]) { return null; } return allNodes[id].name; }; var getSelectedLocalIds = function getSelectedLocalIds(state, node) { var _node$attrs5, _node$marks2; if (!node) { return new Set([]); } var localIds = new Set([(_node$attrs5 = node.attrs) === null || _node$attrs5 === void 0 ? void 0 : _node$attrs5.localId, (_node$marks2 = node.marks) === null || _node$marks2 === void 0 || (_node$marks2 = _node$marks2.find(function (mark) { return mark.type === state.schema.marks.fragment; })) === null || _node$marks2 === void 0 || (_node$marks2 = _node$marks2.attrs) === null || _node$marks2 === void 0 ? void 0 : _node$marks2.localId].filter(Boolean)); return localIds; }; export var getNodeName = function getNodeName(state, node) { var _node$marks$find$attr, _node$marks3; return (_node$marks$find$attr = node === null || node === void 0 || (_node$marks3 = node.marks) === null || _node$marks3 === void 0 || (_node$marks3 = _node$marks3.find(function (mark) { return mark.type === state.schema.marks.fragment; })) === null || _node$marks3 === void 0 || (_node$marks3 = _node$marks3.attrs) === null || _node$marks3 === void 0 ? void 0 : _node$marks3.name) !== null && _node$marks$find$attr !== void 0 ? _node$marks$find$attr : ''; };