UNPKG

@atlaskit/editor-plugin-list

Version:

List plugin for @atlaskit/editor-core

276 lines (274 loc) 11.9 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 { OUTDENT_SCENARIOS } from '@atlaskit/editor-common/analytics'; import { JoinDirection, joinSiblingLists, normalizeListItemsSelection // processNestedTaskListsInSameLevel, } from '@atlaskit/editor-common/lists'; import { GapCursorSelection } from '@atlaskit/editor-common/selection'; import { getOrderFromOrderedListNode, isListItemNode, isListNode } from '@atlaskit/editor-common/utils'; import { Fragment, NodeRange, Slice } from '@atlaskit/editor-prosemirror/model'; import { NodeSelection, Selection, TextSelection } from '@atlaskit/editor-prosemirror/state'; import { liftTarget, ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform'; import { getRestartListsAttributes, storeRestartListsAttributes } from '../utils/analytics'; import { findFirstParentListItemNode, findRootParentListNode } from '../utils/find'; import { createListNodeRange } from '../utils/selection'; export var outdentListItemsSelected = function outdentListItemsSelected(tr) { var originalSelection = tr.selection; var normalizedSelection = normalizeListItemsSelection({ selection: tr.selection, doc: tr.doc }); var rootList = findRootParentListNode(normalizedSelection.$from); if (!rootList) { return; } var commonList = normalizedSelection.$from.blockRange(rootList, isListNode); if (!commonList) { return; } var hasNormalizedToPositionLiftedOut = false; var hasNormalizedFromPositionLiftedOut = false; var oldFrom = normalizedSelection.from, oldTo = normalizedSelection.to; var nodeRanges = splitRangeSelection(normalizedSelection); nodeRanges.forEach(function (range) { var $from = tr.doc.resolve(tr.mapping.map(range.from)); var $to = tr.doc.resolve(tr.mapping.map(range.to)); var mappedRange = $from.blockRange($to, isListNode); if (!mappedRange) { return; } if (isListItemNode($from.node(mappedRange.depth - 1))) { outdentRangeToParentList({ tr: tr, range: mappedRange }); } else { extractListItemsRangeFromList({ tr: tr, range: mappedRange }); hasNormalizedToPositionLiftedOut = hasNormalizedToPositionLiftedOut || oldTo >= range.from && oldTo < range.to; hasNormalizedFromPositionLiftedOut = hasNormalizedFromPositionLiftedOut || oldFrom >= range.from && oldFrom < range.to; } }); var hasCommonListMoved = commonList.start !== tr.mapping.map(commonList.start); var nextSelection = calculateNewSelection({ originalSelection: originalSelection, normalizedSelection: normalizedSelection, tr: tr, hasCommonListMoved: hasCommonListMoved, hasNormalizedToPositionLiftedOut: hasNormalizedToPositionLiftedOut, hasNormalizedFromPositionLiftedOut: hasNormalizedFromPositionLiftedOut }); tr.setSelection(nextSelection); // processNestedTaskListsInSameLevel(tr); joinSiblingLists({ tr: tr, direction: JoinDirection.RIGHT }); }; var calculateNewSelection = function calculateNewSelection(_ref) { var tr = _ref.tr, originalSelection = _ref.originalSelection, normalizedSelection = _ref.normalizedSelection, hasCommonListMoved = _ref.hasCommonListMoved, hasNormalizedToPositionLiftedOut = _ref.hasNormalizedToPositionLiftedOut, hasNormalizedFromPositionLiftedOut = _ref.hasNormalizedFromPositionLiftedOut; var $from = normalizedSelection.$from, $to = normalizedSelection.$to; var isCursorSelection = normalizedSelection.empty; var from = tr.mapping.map($from.pos); var to = tr.mapping.map($to.pos); var LIST_STRUCTURE_CHANGED_OFFSET = 2; var isToFromSameListItem = $from.sameParent($to); if (hasNormalizedFromPositionLiftedOut) { var fromMapped = isToFromSameListItem ? $from.pos : from; from = hasNormalizedFromPositionLiftedOut ? $from.pos : fromMapped; from = hasCommonListMoved ? from - LIST_STRUCTURE_CHANGED_OFFSET : from; from = Math.max(from, 0); } if (hasNormalizedToPositionLiftedOut) { var toMapped = isToFromSameListItem ? $to.pos : to; to = hasNormalizedToPositionLiftedOut ? $to.pos : toMapped; to = hasCommonListMoved ? to - LIST_STRUCTURE_CHANGED_OFFSET : to; to = Math.min(to, tr.doc.nodeSize - 2); } if (normalizedSelection instanceof GapCursorSelection) { var nextSelectionFrom = tr.doc.resolve(from); return new GapCursorSelection(nextSelectionFrom, normalizedSelection.side); } if (originalSelection instanceof NodeSelection) { return NodeSelection.create(tr.doc, from); } if (isCursorSelection) { return TextSelection.between(tr.doc.resolve(to), tr.doc.resolve(to), -1); } return TextSelection.between(tr.doc.resolve(from), tr.doc.resolve(to), -1); }; var splitRangeSelection = function splitRangeSelection(selection) { var commonListRange = createListNodeRange({ selection: selection }); if (!commonListRange) { return []; } var $from = selection.$from, $to = selection.$to; if ($from.pos === $to.pos && $from.sameParent($to)) { return [{ from: commonListRange.start, to: commonListRange.end, depth: commonListRange.depth }]; } var lastListItem = findPreviousListItemSibling($from); if (!lastListItem) { return []; } var nodeRanges = []; var doc = $from.doc; var previousListItem = findPreviousListItemSibling($to); while (previousListItem && previousListItem.pos >= lastListItem.pos && previousListItem.pos >= commonListRange.start) { var node = doc.nodeAt(previousListItem.pos); if (!node || !isListItemNode(node)) { return []; } var offset = 0; if (node && node.lastChild && isListNode(node.lastChild)) { offset = node.lastChild.nodeSize; } var start = previousListItem.pos + 1; nodeRanges.push({ from: start, to: doc.resolve(start).end() - offset, depth: previousListItem.depth }); previousListItem = findPreviousListItemSibling(previousListItem); } return nodeRanges; }; var outdentRangeToParentList = function outdentRangeToParentList(_ref2) { var tr = _ref2.tr, range = _ref2.range; var end = range.end; var endOfList = range.$to.end(range.depth); var listItem = tr.doc.type.schema.nodes.listItem; if (end < endOfList) { var slice = new Slice(Fragment.from(listItem.create(null, range.parent.copy())), 1, 0); var step = new ReplaceAroundStep(end - 1, endOfList, end, endOfList, slice, 1, true); tr.step(step); range = new NodeRange(tr.doc.resolve(range.$from.pos), tr.doc.resolve(endOfList), range.depth); } var target = liftTarget(range); if (target) { tr.lift(range, target); } }; var extractListItemsRangeFromList = function extractListItemsRangeFromList(_ref3) { var tr = _ref3.tr, range = _ref3.range; var list = range.parent; var $start = tr.doc.resolve(range.start); var listStart = $start.start(range.depth); var listEnd = $start.end(range.depth); var isAtTop = listStart === range.start; var isAtBottom = listEnd === range.end; var isTheEntireList = isAtTop && isAtBottom; var listItemContent = isAtTop ? Fragment.empty : Fragment.from(list.copy(Fragment.empty)); for (var i = range.startIndex; i < range.endIndex; i++) { listItemContent = listItemContent.append(list.child(i).content); } if (isAtTop) { for (var _i = 0; _i < listItemContent.childCount; _i++) { var child = listItemContent.child(_i); if (child && isListNode(child) && child.type !== list.type) { var newNestedList = list.type.create(null, child.content); listItemContent = listItemContent.replaceChild(_i, newNestedList); } } } var nextList = list.copy(Fragment.empty); var nextListStartNumber; // if splitting a numbered list, keep the splitted item // counter as the start of the next (second half) list (instead // of reverting back to 1 as a starting number) var order = getOrderFromOrderedListNode(list); if (list.type.name === 'orderedList') { nextListStartNumber = range.endIndex - 1 + order; // @ts-ignore - [unblock prosemirror bump] assigning to readonly attrs nextList.attrs = _objectSpread(_objectSpread({}, nextList.attrs), {}, { order: nextListStartNumber }); var _getRestartListsAttri = getRestartListsAttributes(tr), splitListStartNumber = _getRestartListsAttri.splitListStartNumber; if (typeof splitListStartNumber !== 'number') { storeRestartListsAttributes(tr, { splitListStartNumber: nextListStartNumber }); } } var nextListFragment = listItemContent.append(Fragment.from(nextList)); // if the split list with nextListStartNumber is below another list // with order (e.g due to multi-level indent items being lifted), track the // list above's order instead, as it will be the split list's order after sibling joins nextListFragment.forEach(function (node, _offset, index) { var _node$attrs; if (node.type.name === 'orderedList' && ((_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.order) === nextListStartNumber) { var _prev$attrs; var prev = nextListFragment.child(index - 1); if ((prev === null || prev === void 0 || (_prev$attrs = prev.attrs) === null || _prev$attrs === void 0 ? void 0 : _prev$attrs.order) >= 0) { var _prev$attrs2; storeRestartListsAttributes(tr, { splitListStartNumber: prev === null || prev === void 0 || (_prev$attrs2 = prev.attrs) === null || _prev$attrs2 === void 0 ? void 0 : _prev$attrs2.order }); } } }); if (isTheEntireList) { var slice = new Slice(listItemContent, 0, 0); var step = new ReplaceStep($start.pos - 1, range.end + 1, slice, false); storeRestartListsAttributes(tr, { outdentScenario: undefined }); tr.step(step); } else if (isAtTop) { var _slice = new Slice(nextListFragment, 0, 1); var _step = new ReplaceStep($start.pos - 1, range.end, _slice, false); tr.step(_step); } else if (isAtBottom) { var _slice2 = new Slice(listItemContent, 1, 0); var _step2 = new ReplaceStep($start.pos, listEnd + 1, _slice2, false); tr.step(_step2); } else { storeRestartListsAttributes(tr, { outdentScenario: OUTDENT_SCENARIOS.SPLIT_LIST }); var _slice3 = new Slice(nextListFragment, 1, 1); var _step3 = new ReplaceAroundStep($start.pos, listEnd, range.end, listEnd, _slice3, _slice3.size, false); tr.step(_step3); } }; var findPreviousListItemSibling = function findPreviousListItemSibling($pos) { var doc = $pos.doc; var isPositionListItem = isListNode($pos.node()); var listItemPosition = $pos; if (!isPositionListItem) { var listItem = findFirstParentListItemNode($pos); if (!listItem) { return null; } return doc.resolve(listItem.pos); } var resolved = doc.resolve(listItemPosition.pos); var foundPosition = Selection.findFrom(resolved, -1); if (!foundPosition) { return null; } var parentListItemNode = findFirstParentListItemNode(foundPosition.$from); if (!parentListItemNode) { return null; } return doc.resolve(parentListItemNode.pos); };