You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
452 lines
15 KiB
452 lines
15 KiB
'use strict';
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
|
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
|
|
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
|
|
Object.defineProperty(exports, '__esModule', {
|
|
value: true
|
|
});
|
|
|
|
var RopeSequence = require('rope-sequence');
|
|
|
|
var prosemirrorTransform = require('prosemirror-transform');
|
|
|
|
var prosemirrorState = require('prosemirror-state');
|
|
|
|
function _interopDefaultLegacy(e) {
|
|
return e && _typeof(e) === 'object' && 'default' in e ? e : {
|
|
'default': e
|
|
};
|
|
}
|
|
|
|
var RopeSequence__default = _interopDefaultLegacy(RopeSequence);
|
|
|
|
var max_empty_items = 500;
|
|
|
|
var Branch = function () {
|
|
function Branch(items, eventCount) {
|
|
_classCallCheck(this, Branch);
|
|
|
|
this.items = items;
|
|
this.eventCount = eventCount;
|
|
}
|
|
|
|
_createClass(Branch, [{
|
|
key: "popEvent",
|
|
value: function popEvent(state, preserveItems) {
|
|
var _this = this;
|
|
|
|
if (this.eventCount == 0) return null;
|
|
var end = this.items.length;
|
|
|
|
for (;; end--) {
|
|
var next = this.items.get(end - 1);
|
|
|
|
if (next.selection) {
|
|
--end;
|
|
break;
|
|
}
|
|
}
|
|
|
|
var remap, mapFrom;
|
|
|
|
if (preserveItems) {
|
|
remap = this.remapping(end, this.items.length);
|
|
mapFrom = remap.maps.length;
|
|
}
|
|
|
|
var transform = state.tr;
|
|
var selection, remaining;
|
|
var addAfter = [],
|
|
addBefore = [];
|
|
this.items.forEach(function (item, i) {
|
|
if (!item.step) {
|
|
if (!remap) {
|
|
remap = _this.remapping(end, i + 1);
|
|
mapFrom = remap.maps.length;
|
|
}
|
|
|
|
mapFrom--;
|
|
addBefore.push(item);
|
|
return;
|
|
}
|
|
|
|
if (remap) {
|
|
addBefore.push(new Item(item.map));
|
|
var step = item.step.map(remap.slice(mapFrom)),
|
|
map;
|
|
|
|
if (step && transform.maybeStep(step).doc) {
|
|
map = transform.mapping.maps[transform.mapping.maps.length - 1];
|
|
addAfter.push(new Item(map, undefined, undefined, addAfter.length + addBefore.length));
|
|
}
|
|
|
|
mapFrom--;
|
|
if (map) remap.appendMap(map, mapFrom);
|
|
} else {
|
|
transform.maybeStep(item.step);
|
|
}
|
|
|
|
if (item.selection) {
|
|
selection = remap ? item.selection.map(remap.slice(mapFrom)) : item.selection;
|
|
remaining = new Branch(_this.items.slice(0, end).append(addBefore.reverse().concat(addAfter)), _this.eventCount - 1);
|
|
return false;
|
|
}
|
|
}, this.items.length, 0);
|
|
return {
|
|
remaining: remaining,
|
|
transform: transform,
|
|
selection: selection
|
|
};
|
|
}
|
|
}, {
|
|
key: "addTransform",
|
|
value: function addTransform(transform, selection, histOptions, preserveItems) {
|
|
var newItems = [],
|
|
eventCount = this.eventCount;
|
|
var oldItems = this.items,
|
|
lastItem = !preserveItems && oldItems.length ? oldItems.get(oldItems.length - 1) : null;
|
|
|
|
for (var i = 0; i < transform.steps.length; i++) {
|
|
var step = transform.steps[i].invert(transform.docs[i]);
|
|
var item = new Item(transform.mapping.maps[i], step, selection),
|
|
merged = void 0;
|
|
|
|
if (merged = lastItem && lastItem.merge(item)) {
|
|
item = merged;
|
|
if (i) newItems.pop();else oldItems = oldItems.slice(0, oldItems.length - 1);
|
|
}
|
|
|
|
newItems.push(item);
|
|
|
|
if (selection) {
|
|
eventCount++;
|
|
selection = undefined;
|
|
}
|
|
|
|
if (!preserveItems) lastItem = item;
|
|
}
|
|
|
|
var overflow = eventCount - histOptions.depth;
|
|
|
|
if (overflow > DEPTH_OVERFLOW) {
|
|
oldItems = cutOffEvents(oldItems, overflow);
|
|
eventCount -= overflow;
|
|
}
|
|
|
|
return new Branch(oldItems.append(newItems), eventCount);
|
|
}
|
|
}, {
|
|
key: "remapping",
|
|
value: function remapping(from, to) {
|
|
var maps = new prosemirrorTransform.Mapping();
|
|
this.items.forEach(function (item, i) {
|
|
var mirrorPos = item.mirrorOffset != null && i - item.mirrorOffset >= from ? maps.maps.length - item.mirrorOffset : undefined;
|
|
maps.appendMap(item.map, mirrorPos);
|
|
}, from, to);
|
|
return maps;
|
|
}
|
|
}, {
|
|
key: "addMaps",
|
|
value: function addMaps(array) {
|
|
if (this.eventCount == 0) return this;
|
|
return new Branch(this.items.append(array.map(function (map) {
|
|
return new Item(map);
|
|
})), this.eventCount);
|
|
}
|
|
}, {
|
|
key: "rebased",
|
|
value: function rebased(rebasedTransform, rebasedCount) {
|
|
if (!this.eventCount) return this;
|
|
var rebasedItems = [],
|
|
start = Math.max(0, this.items.length - rebasedCount);
|
|
var mapping = rebasedTransform.mapping;
|
|
var newUntil = rebasedTransform.steps.length;
|
|
var eventCount = this.eventCount;
|
|
this.items.forEach(function (item) {
|
|
if (item.selection) eventCount--;
|
|
}, start);
|
|
var iRebased = rebasedCount;
|
|
this.items.forEach(function (item) {
|
|
var pos = mapping.getMirror(--iRebased);
|
|
if (pos == null) return;
|
|
newUntil = Math.min(newUntil, pos);
|
|
var map = mapping.maps[pos];
|
|
|
|
if (item.step) {
|
|
var step = rebasedTransform.steps[pos].invert(rebasedTransform.docs[pos]);
|
|
var selection = item.selection && item.selection.map(mapping.slice(iRebased + 1, pos));
|
|
if (selection) eventCount++;
|
|
rebasedItems.push(new Item(map, step, selection));
|
|
} else {
|
|
rebasedItems.push(new Item(map));
|
|
}
|
|
}, start);
|
|
var newMaps = [];
|
|
|
|
for (var i = rebasedCount; i < newUntil; i++) {
|
|
newMaps.push(new Item(mapping.maps[i]));
|
|
}
|
|
|
|
var items = this.items.slice(0, start).append(newMaps).append(rebasedItems);
|
|
var branch = new Branch(items, eventCount);
|
|
if (branch.emptyItemCount() > max_empty_items) branch = branch.compress(this.items.length - rebasedItems.length);
|
|
return branch;
|
|
}
|
|
}, {
|
|
key: "emptyItemCount",
|
|
value: function emptyItemCount() {
|
|
var count = 0;
|
|
this.items.forEach(function (item) {
|
|
if (!item.step) count++;
|
|
});
|
|
return count;
|
|
}
|
|
}, {
|
|
key: "compress",
|
|
value: function compress() {
|
|
var upto = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.items.length;
|
|
var remap = this.remapping(0, upto),
|
|
mapFrom = remap.maps.length;
|
|
var items = [],
|
|
events = 0;
|
|
this.items.forEach(function (item, i) {
|
|
if (i >= upto) {
|
|
items.push(item);
|
|
if (item.selection) events++;
|
|
} else if (item.step) {
|
|
var step = item.step.map(remap.slice(mapFrom)),
|
|
map = step && step.getMap();
|
|
mapFrom--;
|
|
if (map) remap.appendMap(map, mapFrom);
|
|
|
|
if (step) {
|
|
var selection = item.selection && item.selection.map(remap.slice(mapFrom));
|
|
if (selection) events++;
|
|
var newItem = new Item(map.invert(), step, selection),
|
|
merged,
|
|
last = items.length - 1;
|
|
if (merged = items.length && items[last].merge(newItem)) items[last] = merged;else items.push(newItem);
|
|
}
|
|
} else if (item.map) {
|
|
mapFrom--;
|
|
}
|
|
}, this.items.length, 0);
|
|
return new Branch(RopeSequence__default["default"].from(items.reverse()), events);
|
|
}
|
|
}]);
|
|
|
|
return Branch;
|
|
}();
|
|
|
|
Branch.empty = new Branch(RopeSequence__default["default"].empty, 0);
|
|
|
|
function cutOffEvents(items, n) {
|
|
var cutPoint;
|
|
items.forEach(function (item, i) {
|
|
if (item.selection && n-- == 0) {
|
|
cutPoint = i;
|
|
return false;
|
|
}
|
|
});
|
|
return items.slice(cutPoint);
|
|
}
|
|
|
|
var Item = function () {
|
|
function Item(map, step, selection, mirrorOffset) {
|
|
_classCallCheck(this, Item);
|
|
|
|
this.map = map;
|
|
this.step = step;
|
|
this.selection = selection;
|
|
this.mirrorOffset = mirrorOffset;
|
|
}
|
|
|
|
_createClass(Item, [{
|
|
key: "merge",
|
|
value: function merge(other) {
|
|
if (this.step && other.step && !other.selection) {
|
|
var step = other.step.merge(this.step);
|
|
if (step) return new Item(step.getMap().invert(), step, this.selection);
|
|
}
|
|
}
|
|
}]);
|
|
|
|
return Item;
|
|
}();
|
|
|
|
var HistoryState = _createClass(function HistoryState(done, undone, prevRanges, prevTime) {
|
|
_classCallCheck(this, HistoryState);
|
|
|
|
this.done = done;
|
|
this.undone = undone;
|
|
this.prevRanges = prevRanges;
|
|
this.prevTime = prevTime;
|
|
});
|
|
|
|
var DEPTH_OVERFLOW = 20;
|
|
|
|
function applyTransaction(history, state, tr, options) {
|
|
var historyTr = tr.getMeta(historyKey),
|
|
rebased;
|
|
if (historyTr) return historyTr.historyState;
|
|
if (tr.getMeta(closeHistoryKey)) history = new HistoryState(history.done, history.undone, null, 0);
|
|
var appended = tr.getMeta("appendedTransaction");
|
|
|
|
if (tr.steps.length == 0) {
|
|
return history;
|
|
} else if (appended && appended.getMeta(historyKey)) {
|
|
if (appended.getMeta(historyKey).redo) return new HistoryState(history.done.addTransform(tr, undefined, options, mustPreserveItems(state)), history.undone, rangesFor(tr.mapping.maps[tr.steps.length - 1]), history.prevTime);else return new HistoryState(history.done, history.undone.addTransform(tr, undefined, options, mustPreserveItems(state)), null, history.prevTime);
|
|
} else if (tr.getMeta("addToHistory") !== false && !(appended && appended.getMeta("addToHistory") === false)) {
|
|
var newGroup = history.prevTime == 0 || !appended && (history.prevTime < (tr.time || 0) - options.newGroupDelay || !isAdjacentTo(tr, history.prevRanges));
|
|
var prevRanges = appended ? mapRanges(history.prevRanges, tr.mapping) : rangesFor(tr.mapping.maps[tr.steps.length - 1]);
|
|
return new HistoryState(history.done.addTransform(tr, newGroup ? state.selection.getBookmark() : undefined, options, mustPreserveItems(state)), Branch.empty, prevRanges, tr.time);
|
|
} else if (rebased = tr.getMeta("rebased")) {
|
|
return new HistoryState(history.done.rebased(tr, rebased), history.undone.rebased(tr, rebased), mapRanges(history.prevRanges, tr.mapping), history.prevTime);
|
|
} else {
|
|
return new HistoryState(history.done.addMaps(tr.mapping.maps), history.undone.addMaps(tr.mapping.maps), mapRanges(history.prevRanges, tr.mapping), history.prevTime);
|
|
}
|
|
}
|
|
|
|
function isAdjacentTo(transform, prevRanges) {
|
|
if (!prevRanges) return false;
|
|
if (!transform.docChanged) return true;
|
|
var adjacent = false;
|
|
transform.mapping.maps[0].forEach(function (start, end) {
|
|
for (var i = 0; i < prevRanges.length; i += 2) {
|
|
if (start <= prevRanges[i + 1] && end >= prevRanges[i]) adjacent = true;
|
|
}
|
|
});
|
|
return adjacent;
|
|
}
|
|
|
|
function rangesFor(map) {
|
|
var result = [];
|
|
map.forEach(function (_from, _to, from, to) {
|
|
return result.push(from, to);
|
|
});
|
|
return result;
|
|
}
|
|
|
|
function mapRanges(ranges, mapping) {
|
|
if (!ranges) return null;
|
|
var result = [];
|
|
|
|
for (var i = 0; i < ranges.length; i += 2) {
|
|
var from = mapping.map(ranges[i], 1),
|
|
to = mapping.map(ranges[i + 1], -1);
|
|
if (from <= to) result.push(from, to);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
function histTransaction(history, state, dispatch, redo) {
|
|
var preserveItems = mustPreserveItems(state);
|
|
var histOptions = historyKey.get(state).spec.config;
|
|
var pop = (redo ? history.undone : history.done).popEvent(state, preserveItems);
|
|
if (!pop) return;
|
|
var selection = pop.selection.resolve(pop.transform.doc);
|
|
var added = (redo ? history.done : history.undone).addTransform(pop.transform, state.selection.getBookmark(), histOptions, preserveItems);
|
|
var newHist = new HistoryState(redo ? added : pop.remaining, redo ? pop.remaining : added, null, 0);
|
|
dispatch(pop.transform.setSelection(selection).setMeta(historyKey, {
|
|
redo: redo,
|
|
historyState: newHist
|
|
}).scrollIntoView());
|
|
}
|
|
|
|
var cachedPreserveItems = false,
|
|
cachedPreserveItemsPlugins = null;
|
|
|
|
function mustPreserveItems(state) {
|
|
var plugins = state.plugins;
|
|
|
|
if (cachedPreserveItemsPlugins != plugins) {
|
|
cachedPreserveItems = false;
|
|
cachedPreserveItemsPlugins = plugins;
|
|
|
|
for (var i = 0; i < plugins.length; i++) {
|
|
if (plugins[i].spec.historyPreserveItems) {
|
|
cachedPreserveItems = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return cachedPreserveItems;
|
|
}
|
|
|
|
function closeHistory(tr) {
|
|
return tr.setMeta(closeHistoryKey, true);
|
|
}
|
|
|
|
var historyKey = new prosemirrorState.PluginKey("history");
|
|
var closeHistoryKey = new prosemirrorState.PluginKey("closeHistory");
|
|
|
|
function history() {
|
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
config = {
|
|
depth: config.depth || 100,
|
|
newGroupDelay: config.newGroupDelay || 500
|
|
};
|
|
return new prosemirrorState.Plugin({
|
|
key: historyKey,
|
|
state: {
|
|
init: function init() {
|
|
return new HistoryState(Branch.empty, Branch.empty, null, 0);
|
|
},
|
|
apply: function apply(tr, hist, state) {
|
|
return applyTransaction(hist, state, tr, config);
|
|
}
|
|
},
|
|
config: config,
|
|
props: {
|
|
handleDOMEvents: {
|
|
beforeinput: function beforeinput(view, e) {
|
|
var inputType = e.inputType;
|
|
var command = inputType == "historyUndo" ? undo : inputType == "historyRedo" ? redo : null;
|
|
if (!command) return false;
|
|
e.preventDefault();
|
|
return command(view.state, view.dispatch);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
var undo = function undo(state, dispatch) {
|
|
var hist = historyKey.getState(state);
|
|
if (!hist || hist.done.eventCount == 0) return false;
|
|
if (dispatch) histTransaction(hist, state, dispatch, false);
|
|
return true;
|
|
};
|
|
|
|
var redo = function redo(state, dispatch) {
|
|
var hist = historyKey.getState(state);
|
|
if (!hist || hist.undone.eventCount == 0) return false;
|
|
if (dispatch) histTransaction(hist, state, dispatch, true);
|
|
return true;
|
|
};
|
|
|
|
function undoDepth(state) {
|
|
var hist = historyKey.getState(state);
|
|
return hist ? hist.done.eventCount : 0;
|
|
}
|
|
|
|
function redoDepth(state) {
|
|
var hist = historyKey.getState(state);
|
|
return hist ? hist.undone.eventCount : 0;
|
|
}
|
|
|
|
exports.closeHistory = closeHistory;
|
|
exports.history = history;
|
|
exports.redo = redo;
|
|
exports.redoDepth = redoDepth;
|
|
exports.undo = undo;
|
|
exports.undoDepth = undoDepth;
|