) → this
+// Insert the given content at the given position.
+Transform.prototype.insert = function(pos, content) {
+ return this.replaceWith(pos, pos, content)
+};
+
+
+
+function fitLeftInner($from, depth, placed, placedBelow) {
+ var content = prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Fragment"].empty, openEnd = 0, placedHere = placed[depth];
+ if ($from.depth > depth) {
+ var inner = fitLeftInner($from, depth + 1, placed, placedBelow || placedHere);
+ openEnd = inner.openEnd + 1;
+ content = prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Fragment"].from($from.node(depth + 1).copy(inner.content));
+ }
+
+ if (placedHere) {
+ content = content.append(placedHere.content);
+ openEnd = placedHere.openEnd;
+ }
+ if (placedBelow) {
+ content = content.append($from.node(depth).contentMatchAt($from.indexAfter(depth)).fillBefore(prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Fragment"].empty, true));
+ openEnd = 0;
+ }
+
+ return {content: content, openEnd: openEnd}
+}
+
+function fitLeft($from, placed) {
+ var ref = fitLeftInner($from, 0, placed, false);
+ var content = ref.content;
+ var openEnd = ref.openEnd;
+ return new prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Slice"](content, $from.depth, openEnd || 0)
+}
+
+function fitRightJoin(content, parent, $from, $to, depth, openStart, openEnd) {
+ var match, count = content.childCount, matchCount = count - (openEnd > 0 ? 1 : 0);
+ var parentNode = openStart < 0 ? parent : $from.node(depth);
+ if (openStart < 0)
+ { match = parentNode.contentMatchAt(matchCount); }
+ else if (count == 1 && openEnd > 0)
+ { match = parentNode.contentMatchAt(openStart ? $from.index(depth) : $from.indexAfter(depth)); }
+ else
+ { match = parentNode.contentMatchAt($from.indexAfter(depth))
+ .matchFragment(content, count > 0 && openStart ? 1 : 0, matchCount); }
+
+ var toNode = $to.node(depth);
+ if (openEnd > 0 && depth < $to.depth) {
+ var after = toNode.content.cutByIndex($to.indexAfter(depth)).addToStart(content.lastChild);
+ var joinable$1 = match.fillBefore(after, true);
+ // Can't insert content if there's a single node stretched across this gap
+ if (joinable$1 && joinable$1.size && openStart > 0 && count == 1) { joinable$1 = null; }
+
+ if (joinable$1) {
+ var inner = fitRightJoin(content.lastChild.content, content.lastChild, $from, $to,
+ depth + 1, count == 1 ? openStart - 1 : -1, openEnd - 1);
+ if (inner) {
+ var last = content.lastChild.copy(inner);
+ if (joinable$1.size)
+ { return content.cutByIndex(0, count - 1).append(joinable$1).addToEnd(last) }
+ else
+ { return content.replaceChild(count - 1, last) }
+ }
+ }
+ }
+ if (openEnd > 0)
+ { match = match.matchType((count == 1 && openStart > 0 ? $from.node(depth + 1) : content.lastChild).type); }
+
+ // If we're here, the next level can't be joined, so we see what
+ // happens if we leave it open.
+ var toIndex = $to.index(depth);
+ if (toIndex == toNode.childCount && !toNode.type.compatibleContent(parent.type)) { return null }
+ var joinable = match.fillBefore(toNode.content, true, toIndex);
+ for (var i = toIndex; joinable && i < toNode.content.childCount; i++)
+ { if (!parentNode.type.allowsMarks(toNode.content.child(i).marks)) { joinable = null; } }
+ if (!joinable) { return null }
+
+ if (openEnd > 0) {
+ var closed = fitRightClosed(content.lastChild, openEnd - 1, $from, depth + 1,
+ count == 1 ? openStart - 1 : -1);
+ content = content.replaceChild(count - 1, closed);
+ }
+ content = content.append(joinable);
+ if ($to.depth > depth)
+ { content = content.addToEnd(fitRightSeparate($to, depth + 1)); }
+ return content
+}
+
+function fitRightClosed(node, openEnd, $from, depth, openStart) {
+ var match, content = node.content, count = content.childCount;
+ if (openStart >= 0)
+ { match = $from.node(depth).contentMatchAt($from.indexAfter(depth))
+ .matchFragment(content, openStart > 0 ? 1 : 0, count); }
+ else
+ { match = node.contentMatchAt(count); }
+
+ if (openEnd > 0) {
+ var closed = fitRightClosed(content.lastChild, openEnd - 1, $from, depth + 1,
+ count == 1 ? openStart - 1 : -1);
+ content = content.replaceChild(count - 1, closed);
+ }
+
+ return node.copy(content.append(match.fillBefore(prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Fragment"].empty, true)))
+}
+
+function fitRightSeparate($to, depth) {
+ var node = $to.node(depth);
+ var fill = node.contentMatchAt(0).fillBefore(node.content, true, $to.index(depth));
+ if ($to.depth > depth) { fill = fill.addToEnd(fitRightSeparate($to, depth + 1)); }
+ return node.copy(fill)
+}
+
+function normalizeSlice(content, openStart, openEnd) {
+ while (openStart > 0 && openEnd > 0 && content.childCount == 1) {
+ content = content.firstChild.content;
+ openStart--;
+ openEnd--;
+ }
+ return new prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Slice"](content, openStart, openEnd)
+}
+
+// : (ResolvedPos, ResolvedPos, number, Slice) → Slice
+function fitRight($from, $to, slice) {
+ var fitted = fitRightJoin(slice.content, $from.node(0), $from, $to, 0, slice.openStart, slice.openEnd);
+ if (!fitted) { return null }
+ return normalizeSlice(fitted, slice.openStart, $to.depth)
+}
+
+function fitsTrivially($from, $to, slice) {
+ return !slice.openStart && !slice.openEnd && $from.start() == $to.start() &&
+ $from.parent.canReplace($from.index(), $to.index(), slice.content)
+}
+
+function canMoveText($from, $to, slice) {
+ if (!$to.parent.isTextblock) { return false }
+
+ var parent = slice.openEnd ? nodeRight(slice.content, slice.openEnd)
+ : $from.node($from.depth - (slice.openStart - slice.openEnd));
+ if (!parent.isTextblock) { return false }
+ for (var i = $to.index(); i < $to.parent.childCount; i++)
+ { if (!parent.type.allowsMarks($to.parent.child(i).marks)) { return false } }
+ var match;
+ if (slice.openEnd) {
+ match = parent.contentMatchAt(parent.childCount);
+ } else {
+ match = parent.contentMatchAt(parent.childCount);
+ if (slice.size) { match = match.matchFragment(slice.content, slice.openStart ? 1 : 0); }
+ }
+ match = match.matchFragment($to.parent.content, $to.index());
+ return match && match.validEnd
+}
+
+function nodeRight(content, depth) {
+ for (var i = 1; i < depth; i++) { content = content.lastChild.content; }
+ return content.lastChild
+}
+
+// Algorithm for 'placing' the elements of a slice into a gap:
+//
+// We consider the content of each node that is open to the left to be
+// independently placeable. I.e. in , when the
+// paragraph on the left is open, "foo" can be placed (somewhere on
+// the left side of the replacement gap) independently from p("bar").
+//
+// So placeSlice splits up a slice into a number of sub-slices,
+// along with information on where they can be placed on the given
+// left-side edge. It works by walking the open side of the slice,
+// from the inside out, and trying to find a landing spot for each
+// element, by simultaneously scanning over the gap side. When no
+// place is found for an open node's content, it is left in that node.
+
+// : (ResolvedPos, Slice) → [{content: Fragment, openEnd: number, depth: number}]
+function placeSlice($from, slice) {
+ var frontier = new Frontier($from);
+ for (var pass = 1; slice.size && pass <= 3; pass++) {
+ var value = frontier.placeSlice(slice.content, slice.openStart, slice.openEnd, pass);
+ if (pass == 3 && value != slice && value.size) { pass = 0; } // Restart if the 3rd pass made progress but left content
+ slice = value;
+ }
+ while (frontier.open.length) { frontier.closeNode(); }
+ return frontier.placed
+}
+
+// Helper class that models the open side of the insert position,
+// keeping track of the content match and already inserted content
+// at each depth.
+var Frontier = function Frontier($pos) {
+ // : [{parent: Node, match: ContentMatch, content: Fragment, wrapper: bool, openEnd: number, depth: number}]
+ this.open = [];
+ for (var d = 0; d <= $pos.depth; d++) {
+ var parent = $pos.node(d), match = parent.contentMatchAt($pos.indexAfter(d));
+ this.open.push({parent: parent, match: match, content: prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Fragment"].empty, wrapper: false, openEnd: 0, depth: d});
+ }
+ this.placed = [];
+};
+
+// : (Fragment, number, number, number, ?Node) → Slice
+// Tries to place the content of the given slice, and returns a
+// slice containing unplaced content.
+//
+// pass 1: try to fit directly
+// pass 2: allow wrapper nodes to be introduced
+// pass 3: allow unwrapping of nodes that aren't open
+Frontier.prototype.placeSlice = function placeSlice (fragment, openStart, openEnd, pass, parent) {
+ if (openStart > 0) {
+ var first = fragment.firstChild;
+ var inner = this.placeSlice(first.content, Math.max(0, openStart - 1),
+ openEnd && fragment.childCount == 1 ? openEnd - 1 : 0,
+ pass, first);
+ if (inner.content != first.content) {
+ if (inner.content.size) {
+ fragment = fragment.replaceChild(0, first.copy(inner.content));
+ openStart = inner.openStart + 1;
+ } else {
+ if (fragment.childCount == 1) { openEnd = 0; }
+ fragment = fragment.cutByIndex(1);
+ openStart = 0;
+ }
+ }
+ }
+ var result = this.placeContent(fragment, openStart, openEnd, pass, parent);
+ if (pass > 2 && result.size && openStart == 0) {
+ var child = result.content.firstChild, single = result.content.childCount == 1;
+ this.placeContent(child.content, 0, openEnd && single ? openEnd - 1 : 0, pass, child);
+ result = single ? prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Fragment"].empty : new prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Slice"](result.content.cutByIndex(1), 0, openEnd);
+ }
+ return result
+};
+
+Frontier.prototype.placeContent = function placeContent (fragment, openStart, openEnd, pass, parent) {
+ var i = 0;
+ // Go over the fragment's children
+ for (; i < fragment.childCount; i++) {
+ var child = fragment.child(i), placed = false, last = i == fragment.childCount - 1;
+ // Try each open node in turn, starting from the innermost
+ for (var d = this.open.length - 1; d >= 0; d--) {
+ var open = this.open[d], wrap = (void 0);
+
+ // If pass > 1, it is allowed to wrap the node to help find a
+ // fit, so if findWrapping returns something, we add open
+ // nodes to the frontier for that wrapping.
+ if (pass > 1 && (wrap = open.match.findWrapping(child.type)) &&
+ !(parent && wrap.length && wrap[wrap.length - 1] == parent.type)) {
+ while (this.open.length - 1 > d) { this.closeNode(); }
+ for (var w = 0; w < wrap.length; w++) {
+ open.match = open.match.matchType(wrap[w]);
+ d++;
+ open = {parent: wrap[w].create(),
+ match: wrap[w].contentMatch,
+ content: prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Fragment"].empty, wrapper: true, openEnd: 0, depth: d + w};
+ this.open.push(open);
+ }
+ }
+
+ // See if the child fits here
+ var match = open.match.matchType(child.type);
+ if (!match) {
+ var fill = open.match.fillBefore(prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Fragment"].from(child));
+ if (fill) {
+ for (var j = 0; j < fill.childCount; j++) {
+ var ch = fill.child(j);
+ this.addNode(open, ch, 0);
+ match = open.match.matchFragment(ch);
+ }
+ } else if (parent && open.match.matchType(parent.type)) {
+ // Don't continue looking further up if the parent node
+ // would fit here.
+ break
+ } else {
+ continue
+ }
+ }
+
+ // Close open nodes above this one, since we're starting to
+ // add to this.
+ while (this.open.length - 1 > d) { this.closeNode(); }
+ // Strip marks from the child or close its start when necessary
+ child = child.mark(open.parent.type.allowedMarks(child.marks));
+ if (openStart) {
+ child = closeNodeStart(child, openStart, last ? openEnd : 0);
+ openStart = 0;
+ }
+ // Add the child to this open node and adjust its metadata
+ this.addNode(open, child, last ? openEnd : 0);
+ open.match = match;
+ if (last) { openEnd = 0; }
+ placed = true;
+ break
+ }
+ // As soon as we've failed to place a node we stop looking at
+ // later nodes
+ if (!placed) { break }
+ }
+ // Close the current open node if it's not the the root and we
+ // either placed up to the end of the node or the the current
+ // slice depth's node type matches the open node's type
+ if (this.open.length > 1 &&
+ (i > 0 && i == fragment.childCount ||
+ parent && this.open[this.open.length - 1].parent.type == parent.type))
+ { this.closeNode(); }
+
+ return new prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Slice"](fragment.cutByIndex(i), openStart, openEnd)
+};
+
+Frontier.prototype.addNode = function addNode (open, node, openEnd) {
+ open.content = closeFragmentEnd(open.content, open.openEnd).addToEnd(node);
+ open.openEnd = openEnd;
+};
+
+Frontier.prototype.closeNode = function closeNode () {
+ var open = this.open.pop();
+ if (open.content.size == 0) ; else if (open.wrapper) {
+ this.addNode(this.open[this.open.length - 1], open.parent.copy(open.content), open.openEnd + 1);
+ } else {
+ this.placed[open.depth] = {depth: open.depth, content: open.content, openEnd: open.openEnd};
+ }
+};
+
+function closeNodeStart(node, openStart, openEnd) {
+ var content = node.content;
+ if (openStart > 1) {
+ var first = closeNodeStart(node.firstChild, openStart - 1, node.childCount == 1 ? openEnd - 1 : 0);
+ content = node.content.replaceChild(0, first);
+ }
+ var fill = node.type.contentMatch.fillBefore(content, openEnd == 0);
+ return node.copy(fill.append(content))
+}
+
+function closeNodeEnd(node, depth) {
+ var content = node.content;
+ if (depth > 1) {
+ var last = closeNodeEnd(node.lastChild, depth - 1);
+ content = node.content.replaceChild(node.childCount - 1, last);
+ }
+ var fill = node.contentMatchAt(node.childCount).fillBefore(prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Fragment"].empty, true);
+ return node.copy(content.append(fill))
+}
+
+function closeFragmentEnd(fragment, depth) {
+ return depth ? fragment.replaceChild(fragment.childCount - 1, closeNodeEnd(fragment.lastChild, depth)) : fragment
+}
+
+// :: (number, number, Slice) → this
+// Replace a range of the document with a given slice, using `from`,
+// `to`, and the slice's [`openStart`](#model.Slice.openStart) property
+// as hints, rather than fixed start and end points. This method may
+// grow the replaced area or close open nodes in the slice in order to
+// get a fit that is more in line with WYSIWYG expectations, by
+// dropping fully covered parent nodes of the replaced region when
+// they are marked [non-defining](#model.NodeSpec.defining), or
+// including an open parent node from the slice that _is_ marked as
+// [defining](#model.NodeSpec.defining).
+//
+// This is the method, for example, to handle paste. The similar
+// [`replace`](#transform.Transform.replace) method is a more
+// primitive tool which will _not_ move the start and end of its given
+// range, and is useful in situations where you need more precise
+// control over what happens.
+Transform.prototype.replaceRange = function(from, to, slice) {
+ if (!slice.size) { return this.deleteRange(from, to) }
+
+ var $from = this.doc.resolve(from), $to = this.doc.resolve(to);
+ if (fitsTrivially($from, $to, slice))
+ { return this.step(new ReplaceStep(from, to, slice)) }
+
+ var targetDepths = coveredDepths($from, this.doc.resolve(to));
+ // Can't replace the whole document, so remove 0 if it's present
+ if (targetDepths[targetDepths.length - 1] == 0) { targetDepths.pop(); }
+ // Negative numbers represent not expansion over the whole node at
+ // that depth, but replacing from $from.before(-D) to $to.pos.
+ var preferredTarget = -($from.depth + 1);
+ targetDepths.unshift(preferredTarget);
+ // This loop picks a preferred target depth, if one of the covering
+ // depths is not outside of a defining node, and adds negative
+ // depths for any depth that has $from at its start and does not
+ // cross a defining node.
+ for (var d = $from.depth, pos = $from.pos - 1; d > 0; d--, pos--) {
+ var spec = $from.node(d).type.spec;
+ if (spec.defining || spec.isolating) { break }
+ if (targetDepths.indexOf(d) > -1) { preferredTarget = d; }
+ else if ($from.before(d) == pos) { targetDepths.splice(1, 0, -d); }
+ }
+ // Try to fit each possible depth of the slice into each possible
+ // target depth, starting with the preferred depths.
+ var preferredTargetIndex = targetDepths.indexOf(preferredTarget);
+
+ var leftNodes = [], preferredDepth = slice.openStart;
+ for (var content = slice.content, i = 0;; i++) {
+ var node = content.firstChild;
+ leftNodes.push(node);
+ if (i == slice.openStart) { break }
+ content = node.content;
+ }
+ // Back up if the node directly above openStart, or the node above
+ // that separated only by a non-defining textblock node, is defining.
+ if (preferredDepth > 0 && leftNodes[preferredDepth - 1].type.spec.defining &&
+ $from.node(preferredTargetIndex).type != leftNodes[preferredDepth - 1].type)
+ { preferredDepth -= 1; }
+ else if (preferredDepth >= 2 && leftNodes[preferredDepth - 1].isTextblock && leftNodes[preferredDepth - 2].type.spec.defining &&
+ $from.node(preferredTargetIndex).type != leftNodes[preferredDepth - 2].type)
+ { preferredDepth -= 2; }
+
+ for (var j = slice.openStart; j >= 0; j--) {
+ var openDepth = (j + preferredDepth + 1) % (slice.openStart + 1);
+ var insert = leftNodes[openDepth];
+ if (!insert) { continue }
+ for (var i$1 = 0; i$1 < targetDepths.length; i$1++) {
+ // Loop over possible expansion levels, starting with the
+ // preferred one
+ var targetDepth = targetDepths[(i$1 + preferredTargetIndex) % targetDepths.length], expand = true;
+ if (targetDepth < 0) { expand = false; targetDepth = -targetDepth; }
+ var parent = $from.node(targetDepth - 1), index = $from.index(targetDepth - 1);
+ if (parent.canReplaceWith(index, index, insert.type, insert.marks))
+ { return this.replace($from.before(targetDepth), expand ? $to.after(targetDepth) : to,
+ new prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Slice"](closeFragment(slice.content, 0, slice.openStart, openDepth),
+ openDepth, slice.openEnd)) }
+ }
+ }
+
+ var startSteps = this.steps.length;
+ for (var i$2 = targetDepths.length - 1; i$2 >= 0; i$2--) {
+ this.replace(from, to, slice);
+ if (this.steps.length > startSteps) { break }
+ var depth = targetDepths[i$2];
+ if (i$2 < 0) { continue }
+ from = $from.before(depth); to = $to.after(depth);
+ }
+ return this
+};
+
+function closeFragment(fragment, depth, oldOpen, newOpen, parent) {
+ if (depth < oldOpen) {
+ var first = fragment.firstChild;
+ fragment = fragment.replaceChild(0, first.copy(closeFragment(first.content, depth + 1, oldOpen, newOpen, first)));
+ }
+ if (depth > newOpen) {
+ var match = parent.contentMatchAt(0);
+ var start = match.fillBefore(fragment).append(fragment);
+ fragment = start.append(match.matchFragment(start).fillBefore(prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Fragment"].empty, true));
+ }
+ return fragment
+}
+
+// :: (number, number, Node) → this
+// Replace the given range with a node, but use `from` and `to` as
+// hints, rather than precise positions. When from and to are the same
+// and are at the start or end of a parent node in which the given
+// node doesn't fit, this method may _move_ them out towards a parent
+// that does allow the given node to be placed. When the given range
+// completely covers a parent node, this method may completely replace
+// that parent node.
+Transform.prototype.replaceRangeWith = function(from, to, node) {
+ if (!node.isInline && from == to && this.doc.resolve(from).parent.content.size) {
+ var point = insertPoint(this.doc, from, node.type);
+ if (point != null) { from = to = point; }
+ }
+ return this.replaceRange(from, to, new prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Slice"](prosemirror_model__WEBPACK_IMPORTED_MODULE_0__["Fragment"].from(node), 0, 0))
+};
+
+// :: (number, number) → this
+// Delete the given range, expanding it to cover fully covered
+// parent nodes until a valid replace is found.
+Transform.prototype.deleteRange = function(from, to) {
+ var $from = this.doc.resolve(from), $to = this.doc.resolve(to);
+ var covered = coveredDepths($from, $to);
+ for (var i = 0; i < covered.length; i++) {
+ var depth = covered[i], last = i == covered.length - 1;
+ if ((last && depth == 0) || $from.node(depth).type.contentMatch.validEnd)
+ { return this.delete($from.start(depth), $to.end(depth)) }
+ if (depth > 0 && (last || $from.node(depth - 1).canReplace($from.index(depth - 1), $to.indexAfter(depth - 1))))
+ { return this.delete($from.before(depth), $to.after(depth)) }
+ }
+ for (var d = 1; d <= $from.depth && d <= $to.depth; d++) {
+ if (from - $from.start(d) == $from.depth - d && to > $from.end(d) && $to.end(d) - to != $to.depth - d)
+ { return this.delete($from.before(d), to) }
+ }
+ return this.delete(from, to)
+};
+
+// : (ResolvedPos, ResolvedPos) → [number]
+// Returns an array of all depths for which $from - $to spans the
+// whole content of the nodes at that depth.
+function coveredDepths($from, $to) {
+ var result = [], minDepth = Math.min($from.depth, $to.depth);
+ for (var d = minDepth; d >= 0; d--) {
+ var start = $from.start(d);
+ if (start < $from.pos - ($from.depth - d) ||
+ $to.end(d) > $to.pos + ($to.depth - d) ||
+ $from.node(d).type.spec.isolating ||
+ $to.node(d).type.spec.isolating) { break }
+ if (start == $to.start(d)) { result.push(d); }
+ }
+ return result
+}
+
+
+//# sourceMappingURL=index.es.js.map
+
+
+/***/ }),
+
+/***/ "./node_modules/prosemirror-utils/dist/index.js":
+/*!******************************************************!*\
+ !*** ./node_modules/prosemirror-utils/dist/index.js ***!
+ \******************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, '__esModule', { value: true });
+
+var prosemirrorState = __webpack_require__(/*! prosemirror-state */ "./node_modules/prosemirror-state/dist/index.es.js");
+var prosemirrorModel = __webpack_require__(/*! prosemirror-model */ "./node_modules/prosemirror-model/dist/index.es.js");
+var prosemirrorTables = __webpack_require__(/*! prosemirror-tables */ "./node_modules/prosemirror-tables/dist/index.es.js");
+
+// :: (nodeType: union) → (tr: Transaction) → Transaction
+// Returns a new transaction that removes a node of a given `nodeType`. It will return an original transaction if parent node hasn't been found.
+//
+// ```javascript
+// dispatch(
+// removeParentNodeOfType(schema.nodes.table)(tr)
+// );
+// ```
+var removeParentNodeOfType = function removeParentNodeOfType(nodeType) {
+ return function (tr) {
+ var parent = findParentNodeOfType(nodeType)(tr.selection);
+ if (parent) {
+ return removeNodeAtPos(parent.pos)(tr);
+ }
+ return tr;
+ };
+};
+
+// :: (nodeType: union, content: union) → (tr: Transaction) → Transaction
+// Returns a new transaction that replaces parent node of a given `nodeType` with the given `content`. It will return an original transaction if either parent node hasn't been found or replacing is not possible.
+//
+// ```javascript
+// const node = schema.nodes.paragraph.createChecked({}, schema.text('new'));
+//
+// dispatch(
+// replaceParentNodeOfType(schema.nodes.table, node)(tr)
+// );
+// ```
+var replaceParentNodeOfType = function replaceParentNodeOfType(nodeType, content) {
+ return function (tr) {
+ if (!Array.isArray(nodeType)) {
+ nodeType = [nodeType];
+ }
+ for (var i = 0, count = nodeType.length; i < count; i++) {
+ var parent = findParentNodeOfType(nodeType[i])(tr.selection);
+ if (parent) {
+ var newTr = replaceNodeAtPos(parent.pos, content)(tr);
+ if (newTr !== tr) {
+ return newTr;
+ }
+ }
+ }
+ return tr;
+ };
+};
+
+// :: (tr: Transaction) → Transaction
+// Returns a new transaction that removes selected node. It will return an original transaction if current selection is not a `NodeSelection`.
+//
+// ```javascript
+// dispatch(
+// removeSelectedNode(tr)
+// );
+// ```
+var removeSelectedNode = function removeSelectedNode(tr) {
+ if (isNodeSelection(tr.selection)) {
+ var from = tr.selection.$from.pos;
+ var to = tr.selection.$to.pos;
+ return cloneTr(tr.delete(from, to));
+ }
+ return tr;
+};
+
+// :: (content: union) → (tr: Transaction) → Transaction
+// Returns a new transaction that replaces selected node with a given `node`, keeping NodeSelection on the new `node`.
+// It will return the original transaction if either current selection is not a NodeSelection or replacing is not possible.
+//
+// ```javascript
+// const node = schema.nodes.paragraph.createChecked({}, schema.text('new'));
+// dispatch(
+// replaceSelectedNode(node)(tr)
+// );
+// ```
+var replaceSelectedNode = function replaceSelectedNode(content) {
+ return function (tr) {
+ if (isNodeSelection(tr.selection)) {
+ var _tr$selection = tr.selection,
+ $from = _tr$selection.$from,
+ $to = _tr$selection.$to;
+
+ if (content instanceof prosemirrorModel.Fragment && $from.parent.canReplace($from.index(), $from.indexAfter(), content) || $from.parent.canReplaceWith($from.index(), $from.indexAfter(), content.type)) {
+ return cloneTr(tr.replaceWith($from.pos, $to.pos, content)
+ // restore node selection
+ .setSelection(new prosemirrorState.NodeSelection(tr.doc.resolve($from.pos))));
+ }
+ }
+ return tr;
+ };
+};
+
+// :: (position: number, dir: ?number) → (tr: Transaction) → Transaction
+// Returns a new transaction that tries to find a valid cursor selection starting at the given `position`
+// and searching back if `dir` is negative, and forward if positive.
+// If a valid cursor position hasn't been found, it will return the original transaction.
+//
+// ```javascript
+// dispatch(
+// setTextSelection(5)(tr)
+// );
+// ```
+var setTextSelection = function setTextSelection(position) {
+ var dir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
+ return function (tr) {
+ var nextSelection = prosemirrorState.Selection.findFrom(tr.doc.resolve(position), dir, true);
+ if (nextSelection) {
+ return tr.setSelection(nextSelection);
+ }
+ return tr;
+ };
+};
+
+var isSelectableNode = function isSelectableNode(node) {
+ return node.type && node.type.spec.selectable;
+};
+var shouldSelectNode = function shouldSelectNode(node) {
+ return isSelectableNode(node) && node.type.isLeaf;
+};
+
+var setSelection = function setSelection(node, pos, tr) {
+ if (shouldSelectNode(node)) {
+ return tr.setSelection(new prosemirrorState.NodeSelection(tr.doc.resolve(pos)));
+ }
+ return setTextSelection(pos)(tr);
+};
+
+// :: (content: union, position: ?number, tryToReplace?: boolean) → (tr: Transaction) → Transaction
+// Returns a new transaction that inserts a given `content` at the current cursor position, or at a given `position`, if it is allowed by schema. If schema restricts such nesting, it will try to find an appropriate place for a given node in the document, looping through parent nodes up until the root document node.
+// If `tryToReplace` is true and current selection is a NodeSelection, it will replace selected node with inserted content if its allowed by schema.
+// If cursor is inside of an empty paragraph, it will try to replace that paragraph with the given content. If insertion is successful and inserted node has content, it will set cursor inside of that content.
+// It will return an original transaction if the place for insertion hasn't been found.
+//
+// ```javascript
+// const node = schema.nodes.extension.createChecked({});
+// dispatch(
+// safeInsert(node)(tr)
+// );
+// ```
+var safeInsert = function safeInsert(content, position, tryToReplace) {
+ return function (tr) {
+ var hasPosition = typeof position === 'number';
+ var $from = tr.selection.$from;
+
+ var $insertPos = hasPosition ? tr.doc.resolve(position) : isNodeSelection(tr.selection) ? tr.doc.resolve($from.pos + 1) : $from;
+ var parent = $insertPos.parent;
+
+ // try to replace selected node
+
+ if (isNodeSelection(tr.selection) && tryToReplace) {
+ var oldTr = tr;
+ tr = replaceSelectedNode(content)(tr);
+ if (oldTr !== tr) {
+ return tr;
+ }
+ }
+
+ // try to replace an empty paragraph
+ if (isEmptyParagraph(parent)) {
+ var _oldTr = tr;
+ tr = replaceParentNodeOfType(parent.type, content)(tr);
+ if (_oldTr !== tr) {
+ var pos = isSelectableNode(content) ? // for selectable node, selection position would be the position of the replaced parent
+ $insertPos.before($insertPos.depth) : $insertPos.pos;
+ return setSelection(content, pos, tr);
+ }
+ }
+
+ // given node is allowed at the current cursor position
+ if (canInsert($insertPos, content)) {
+ tr.insert($insertPos.pos, content);
+ var _pos = hasPosition ? $insertPos.pos : isSelectableNode(content) ? // for atom nodes selection position after insertion is the previous pos
+ tr.selection.$anchor.pos - 1 : tr.selection.$anchor.pos;
+ return cloneTr(setSelection(content, _pos, tr));
+ }
+
+ // looking for a place in the doc where the node is allowed
+ for (var i = $insertPos.depth; i > 0; i--) {
+ var _pos2 = $insertPos.after(i);
+ var $pos = tr.doc.resolve(_pos2);
+ if (canInsert($pos, content)) {
+ tr.insert(_pos2, content);
+ return cloneTr(setSelection(content, _pos2, tr));
+ }
+ }
+ return tr;
+ };
+};
+
+// :: (nodeType: union, type: ?union, attrs: ?union