@atlaskit/editor-plugin-list
Version:
List plugin for @atlaskit/editor-core
276 lines (274 loc) • 11.9 kB
JavaScript
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);
};