@atlaskit/editor-plugin-paste
Version:
Paste plugin for @atlaskit/editor-core
148 lines (144 loc) • 6.55 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.insertSliceForLists = insertSliceForLists;
exports.insertSliceForTaskInsideList = insertSliceForTaskInsideList;
exports.insertSliceInsideBlockquote = insertSliceInsideBlockquote;
exports.updateSelectionAfterReplace = updateSelectionAfterReplace;
var _commands = require("@atlaskit/editor-common/commands");
var _utils = require("@atlaskit/editor-common/utils");
var _model = require("@atlaskit/editor-prosemirror/model");
var _state = require("@atlaskit/editor-prosemirror/state");
var _transform = require("@atlaskit/editor-prosemirror/transform");
var _utils2 = require("@atlaskit/editor-prosemirror/utils");
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
var _index = require("../index");
var _lists = require("./lists");
function insertSliceForLists(_ref) {
var _slice$content$firstC;
var tr = _ref.tr,
slice = _ref.slice,
schema = _ref.schema;
var selection = tr.selection,
_tr$selection = tr.selection,
$to = _tr$selection.$to,
$from = _tr$selection.$from;
var _ref2 = selection,
$cursor = _ref2.$cursor;
var panelNode = (0, _index.isSelectionInsidePanel)(selection);
var selectionIsInsideList = $from.blockRange($to, _utils.isListNode);
if (!$cursor && selectionIsInsideList) {
return (0, _lists.insertSliceIntoRangeSelectionInsideList)({
tr: tr,
slice: slice
});
}
// if inside an empty panel, try and insert content inside it rather than replace it
if (panelNode && (0, _index.isEmptyNode)(panelNode) && $from.node() === $to.node()) {
return (0, _lists.insertSliceInsideOfPanelNodeSelected)(panelNode)({
tr: tr,
slice: slice,
schema: schema
});
}
if (!$cursor || selectionIsInsideList) {
return tr.replaceSelection(slice);
}
if ((0, _index.isEmptyNode)(tr.doc.resolve($cursor.pos).node())) {
return (0, _lists.insertSliceIntoEmptyNode)({
tr: tr,
slice: slice
});
}
// When pasting a single list item into an action or decision, we skip the special "insert at node edge"
// logic so that prosemirror pastes the list's content into the action/decision, rather than
// pasting a whole list node directly after the action/decision item. (But we still preserve the
// existing "insert at" node edge" behaviour if dealing with a list with more than one item, so that
// it still inserts whole list node after the action/decision item).
var pastingIntoActionOrDecision = Boolean((0, _utils2.findParentNodeOfType)([schema.nodes.taskList, schema.nodes.decisionList])(selection));
var oneListItem = slice.content.childCount === 1 && (0, _utils.isListNode)(slice.content.firstChild) && ((_slice$content$firstC = slice.content.firstChild) === null || _slice$content$firstC === void 0 ? void 0 : _slice$content$firstC.childCount) === 1;
if (!(pastingIntoActionOrDecision && oneListItem) && (0, _index.isCursorSelectionAtTextStartOrEnd)(selection)) {
return (0, _lists.insertSliceAtNodeEdge)({
tr: tr,
slice: slice
});
}
tr.replaceSelection(slice);
}
var stripFontSizeInsideBlockquoteLists = function stripFontSizeInsideBlockquoteLists(tr, blockquotePos) {
var _tr$doc$type$schema = tr.doc.type.schema,
fontSize = _tr$doc$type$schema.marks.fontSize,
_tr$doc$type$schema$n = _tr$doc$type$schema.nodes,
paragraph = _tr$doc$type$schema$n.paragraph,
listItem = _tr$doc$type$schema$n.listItem,
taskItem = _tr$doc$type$schema$n.taskItem,
blockTaskItem = _tr$doc$type$schema$n.blockTaskItem;
var listItemParentNodeTypes = [listItem, taskItem, blockTaskItem];
if (!fontSize || !(0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true)) {
return;
}
var containingBlockquote = tr.doc.nodeAt(blockquotePos);
if (!containingBlockquote) {
return;
}
var from = blockquotePos + 1;
var to = blockquotePos + containingBlockquote.nodeSize - 1;
(0, _commands.createToggleBlockMarkOnRangeNext)(fontSize, function () {
return false;
}, function (_schema, node, parent) {
return node.type === paragraph && !!parent && listItemParentNodeTypes.some(function (nodeType) {
return nodeType === parent.type;
});
})(from, to, tr);
};
function insertSliceInsideBlockquote(_ref3) {
var tr = _ref3.tr,
slice = _ref3.slice;
//insert blockquote explicitly and set the selection in blockquote since replaceSelection will only insert the list
var schema = tr.doc.type.schema;
tr.replaceSelection(new _model.Slice(_model.Fragment.from(schema.nodes.blockquote.createAndFill()), 0, 0));
updateSelectionAfterReplace({
tr: tr
});
tr.replaceSelection(slice);
if ((0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true)) {
var insertedBlockquotePos = (0, _utils2.findParentNodeOfType)(schema.nodes.blockquote)(tr.selection);
if (!insertedBlockquotePos) {
return;
}
stripFontSizeInsideBlockquoteLists(tr, insertedBlockquotePos.pos);
}
}
function updateSelectionAfterReplace(_ref4) {
var tr = _ref4.tr;
// ProseMirror doesn't give a proper way to tell us where something was inserted.
// However, we can know "how" it inserted something.
//
// So, instead of weird depth calculations, we can use the step produced by the transform.
// For instance:
// The `replaceStep.to and replaceStep.from`, tell us the real position
// where the content will be insert.
// Then, we can use the `tr.mapping.map` to the updated position after the replace operation
var replaceStep = tr.steps[0];
if (!(replaceStep instanceof _transform.ReplaceStep)) {
return tr;
}
var nextPosition = tr.mapping.map(replaceStep.to);
// The findFrom will make search for both: TextSelection and NodeSelections.
var nextSelection = _state.Selection.findFrom(tr.doc.resolve(Math.min(nextPosition, tr.doc.content.size)), -1);
if (nextSelection) {
tr.setSelection(nextSelection);
}
}
function insertSliceForTaskInsideList(_ref5) {
var tr = _ref5.tr,
slice = _ref5.slice;
var schema = tr.doc.type.schema;
//To avoid the list being replaced with the tasklist, enclose the slice within a taskItem.
var selectionBeforeReplace = tr.selection.from;
tr.replaceSelection(new _model.Slice(_model.Fragment.from(schema.nodes.taskItem.createAndFill()), 0, 0));
var nextSelection = _state.Selection.near(tr.doc.resolve(selectionBeforeReplace + 1));
tr.setSelection(nextSelection);
tr.replaceSelection(slice);
}