1 | 'use strict';
|
2 |
|
3 | var isPlainObject = require('is-plain-object');
|
4 | var slate = require('slate');
|
5 |
|
6 |
|
7 | var History = {
|
8 | |
9 |
|
10 |
|
11 | isHistory: function isHistory(value) {
|
12 | return isPlainObject.isPlainObject(value) && Array.isArray(value.redos) && Array.isArray(value.undos) && (value.redos.length === 0 || slate.Operation.isOperationList(value.redos[0].operations)) && (value.undos.length === 0 || slate.Operation.isOperationList(value.undos[0].operations));
|
13 | }
|
14 | };
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | var HISTORY = new WeakMap();
|
20 | var SAVING = new WeakMap();
|
21 | var MERGING = new WeakMap();
|
22 |
|
23 | var HistoryEditor = {
|
24 | |
25 |
|
26 |
|
27 | isHistoryEditor: function isHistoryEditor(value) {
|
28 | return History.isHistory(value.history) && slate.Editor.isEditor(value);
|
29 | },
|
30 | |
31 |
|
32 |
|
33 | isMerging: function isMerging(editor) {
|
34 | return MERGING.get(editor);
|
35 | },
|
36 | |
37 |
|
38 |
|
39 | isSaving: function isSaving(editor) {
|
40 | return SAVING.get(editor);
|
41 | },
|
42 | |
43 |
|
44 |
|
45 | redo: function redo(editor) {
|
46 | editor.redo();
|
47 | },
|
48 | |
49 |
|
50 |
|
51 | undo: function undo(editor) {
|
52 | editor.undo();
|
53 | },
|
54 | |
55 |
|
56 |
|
57 |
|
58 | withoutMerging: function withoutMerging(editor, fn) {
|
59 | var prev = HistoryEditor.isMerging(editor);
|
60 | MERGING.set(editor, false);
|
61 | fn();
|
62 | MERGING.set(editor, prev);
|
63 | },
|
64 | |
65 |
|
66 |
|
67 |
|
68 | withoutSaving: function withoutSaving(editor, fn) {
|
69 | var prev = HistoryEditor.isSaving(editor);
|
70 | SAVING.set(editor, false);
|
71 | fn();
|
72 | SAVING.set(editor, prev);
|
73 | }
|
74 | };
|
75 |
|
76 | function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
|
77 | function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
78 | function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | var withHistory = function withHistory(editor) {
|
89 | var e = editor;
|
90 | var apply = e.apply;
|
91 | e.history = {
|
92 | undos: [],
|
93 | redos: []
|
94 | };
|
95 | e.redo = function () {
|
96 | var history = e.history;
|
97 | var redos = history.redos;
|
98 | if (redos.length > 0) {
|
99 | var batch = redos[redos.length - 1];
|
100 | if (batch.selectionBefore) {
|
101 | slate.Transforms.setSelection(e, batch.selectionBefore);
|
102 | }
|
103 | HistoryEditor.withoutSaving(e, function () {
|
104 | slate.Editor.withoutNormalizing(e, function () {
|
105 | var _iterator = _createForOfIteratorHelper(batch.operations),
|
106 | _step;
|
107 | try {
|
108 | for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
109 | var op = _step.value;
|
110 | e.apply(op);
|
111 | }
|
112 | } catch (err) {
|
113 | _iterator.e(err);
|
114 | } finally {
|
115 | _iterator.f();
|
116 | }
|
117 | });
|
118 | });
|
119 | history.redos.pop();
|
120 | e.writeHistory('undos', batch);
|
121 | }
|
122 | };
|
123 | e.undo = function () {
|
124 | var history = e.history;
|
125 | var undos = history.undos;
|
126 | if (undos.length > 0) {
|
127 | var batch = undos[undos.length - 1];
|
128 | HistoryEditor.withoutSaving(e, function () {
|
129 | slate.Editor.withoutNormalizing(e, function () {
|
130 | var inverseOps = batch.operations.map(slate.Operation.inverse).reverse();
|
131 | var _iterator2 = _createForOfIteratorHelper(inverseOps),
|
132 | _step2;
|
133 | try {
|
134 | for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
135 | var op = _step2.value;
|
136 | e.apply(op);
|
137 | }
|
138 | } catch (err) {
|
139 | _iterator2.e(err);
|
140 | } finally {
|
141 | _iterator2.f();
|
142 | }
|
143 | if (batch.selectionBefore) {
|
144 | slate.Transforms.setSelection(e, batch.selectionBefore);
|
145 | }
|
146 | });
|
147 | });
|
148 | e.writeHistory('redos', batch);
|
149 | history.undos.pop();
|
150 | }
|
151 | };
|
152 | e.apply = function (op) {
|
153 | var operations = e.operations,
|
154 | history = e.history;
|
155 | var undos = history.undos;
|
156 | var lastBatch = undos[undos.length - 1];
|
157 | var lastOp = lastBatch && lastBatch.operations[lastBatch.operations.length - 1];
|
158 | var save = HistoryEditor.isSaving(e);
|
159 | var merge = HistoryEditor.isMerging(e);
|
160 | if (save == null) {
|
161 | save = shouldSave(op);
|
162 | }
|
163 | if (save) {
|
164 | if (merge == null) {
|
165 | if (lastBatch == null) {
|
166 | merge = false;
|
167 | } else if (operations.length !== 0) {
|
168 | merge = true;
|
169 | } else {
|
170 | merge = shouldMerge(op, lastOp);
|
171 | }
|
172 | }
|
173 | if (lastBatch && merge) {
|
174 | lastBatch.operations.push(op);
|
175 | } else {
|
176 | var batch = {
|
177 | operations: [op],
|
178 | selectionBefore: e.selection
|
179 | };
|
180 | e.writeHistory('undos', batch);
|
181 | }
|
182 | while (undos.length > 100) {
|
183 | undos.shift();
|
184 | }
|
185 | history.redos = [];
|
186 | }
|
187 | apply(op);
|
188 | };
|
189 | e.writeHistory = function (stack, batch) {
|
190 | e.history[stack].push(batch);
|
191 | };
|
192 | return e;
|
193 | };
|
194 |
|
195 |
|
196 |
|
197 | var shouldMerge = function shouldMerge(op, prev) {
|
198 | if (prev && op.type === 'insert_text' && prev.type === 'insert_text' && op.offset === prev.offset + prev.text.length && slate.Path.equals(op.path, prev.path)) {
|
199 | return true;
|
200 | }
|
201 | if (prev && op.type === 'remove_text' && prev.type === 'remove_text' && op.offset + op.text.length === prev.offset && slate.Path.equals(op.path, prev.path)) {
|
202 | return true;
|
203 | }
|
204 | return false;
|
205 | };
|
206 |
|
207 |
|
208 |
|
209 | var shouldSave = function shouldSave(op, prev) {
|
210 | if (op.type === 'set_selection') {
|
211 | return false;
|
212 | }
|
213 | return true;
|
214 | };
|
215 |
|
216 | exports.HISTORY = HISTORY;
|
217 | exports.History = History;
|
218 | exports.HistoryEditor = HistoryEditor;
|
219 | exports.MERGING = MERGING;
|
220 | exports.SAVING = SAVING;
|
221 | exports.withHistory = withHistory;
|
222 |
|