annotate .cms/lib/codemirror/src/model/history.js @ 0:78edf6b517a0 draft

24.10
author Coffee CMS <info@coffee-cms.ru>
date Fri, 11 Oct 2024 22:40:23 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
1 import { cmp, copyPos } from "../line/pos.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
2 import { stretchSpansOverChange } from "../line/spans.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
3 import { getBetween } from "../line/utils_line.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
4 import { signal } from "../util/event.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
5 import { indexOf, lst } from "../util/misc.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
6
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
7 import { changeEnd } from "./change_measurement.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
8 import { linkedDocs } from "./document_data.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
9 import { Selection } from "./selection.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
10
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
11 export function History(prev) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
12 // Arrays of change events and selections. Doing something adds an
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
13 // event to done and clears undo. Undoing moves events from done
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
14 // to undone, redoing moves them in the other direction.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
15 this.done = []; this.undone = []
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
16 this.undoDepth = prev ? prev.undoDepth : Infinity
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
17 // Used to track when changes can be merged into a single undo
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
18 // event
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
19 this.lastModTime = this.lastSelTime = 0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
20 this.lastOp = this.lastSelOp = null
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
21 this.lastOrigin = this.lastSelOrigin = null
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
22 // Used by the isClean() method
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
23 this.generation = this.maxGeneration = prev ? prev.maxGeneration : 1
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
24 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
25
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
26 // Create a history change event from an updateDoc-style change
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
27 // object.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
28 export function historyChangeFromChange(doc, change) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
29 let histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
30 attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
31 linkedDocs(doc, doc => attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1), true)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
32 return histChange
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
33 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
34
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
35 // Pop all selection events off the end of a history array. Stop at
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
36 // a change event.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
37 function clearSelectionEvents(array) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
38 while (array.length) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
39 let last = lst(array)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
40 if (last.ranges) array.pop()
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
41 else break
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
42 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
43 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
44
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
45 // Find the top change event in the history. Pop off selection
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
46 // events that are in the way.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
47 function lastChangeEvent(hist, force) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
48 if (force) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
49 clearSelectionEvents(hist.done)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
50 return lst(hist.done)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
51 } else if (hist.done.length && !lst(hist.done).ranges) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
52 return lst(hist.done)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
53 } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
54 hist.done.pop()
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
55 return lst(hist.done)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
56 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
57 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
58
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
59 // Register a change in the history. Merges changes that are within
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
60 // a single operation, or are close together with an origin that
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
61 // allows merging (starting with "+") into a single event.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
62 export function addChangeToHistory(doc, change, selAfter, opId) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
63 let hist = doc.history
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
64 hist.undone.length = 0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
65 let time = +new Date, cur
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
66 let last
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
67
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
68 if ((hist.lastOp == opId ||
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
69 hist.lastOrigin == change.origin && change.origin &&
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
70 ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) ||
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
71 change.origin.charAt(0) == "*")) &&
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
72 (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
73 // Merge this change into the last event
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
74 last = lst(cur.changes)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
75 if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
76 // Optimized case for simple insertion -- don't want to add
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
77 // new changesets for every character typed
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
78 last.to = changeEnd(change)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
79 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
80 // Add new sub-event
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
81 cur.changes.push(historyChangeFromChange(doc, change))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
82 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
83 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
84 // Can not be merged, start a new event.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
85 let before = lst(hist.done)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
86 if (!before || !before.ranges)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
87 pushSelectionToHistory(doc.sel, hist.done)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
88 cur = {changes: [historyChangeFromChange(doc, change)],
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
89 generation: hist.generation}
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
90 hist.done.push(cur)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
91 while (hist.done.length > hist.undoDepth) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
92 hist.done.shift()
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
93 if (!hist.done[0].ranges) hist.done.shift()
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
94 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
95 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
96 hist.done.push(selAfter)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
97 hist.generation = ++hist.maxGeneration
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
98 hist.lastModTime = hist.lastSelTime = time
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
99 hist.lastOp = hist.lastSelOp = opId
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
100 hist.lastOrigin = hist.lastSelOrigin = change.origin
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
101
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
102 if (!last) signal(doc, "historyAdded")
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
103 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
104
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
105 function selectionEventCanBeMerged(doc, origin, prev, sel) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
106 let ch = origin.charAt(0)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
107 return ch == "*" ||
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
108 ch == "+" &&
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
109 prev.ranges.length == sel.ranges.length &&
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
110 prev.somethingSelected() == sel.somethingSelected() &&
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
111 new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
112 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
113
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
114 // Called whenever the selection changes, sets the new selection as
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
115 // the pending selection in the history, and pushes the old pending
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
116 // selection into the 'done' array when it was significantly
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
117 // different (in number of selected ranges, emptiness, or time).
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
118 export function addSelectionToHistory(doc, sel, opId, options) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
119 let hist = doc.history, origin = options && options.origin
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
120
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
121 // A new event is started when the previous origin does not match
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
122 // the current, or the origins don't allow matching. Origins
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
123 // starting with * are always merged, those starting with + are
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
124 // merged when similar and close together in time.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
125 if (opId == hist.lastSelOp ||
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
126 (origin && hist.lastSelOrigin == origin &&
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
127 (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
128 selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
129 hist.done[hist.done.length - 1] = sel
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
130 else
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
131 pushSelectionToHistory(sel, hist.done)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
132
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
133 hist.lastSelTime = +new Date
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
134 hist.lastSelOrigin = origin
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
135 hist.lastSelOp = opId
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
136 if (options && options.clearRedo !== false)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
137 clearSelectionEvents(hist.undone)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
138 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
139
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
140 export function pushSelectionToHistory(sel, dest) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
141 let top = lst(dest)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
142 if (!(top && top.ranges && top.equals(sel)))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
143 dest.push(sel)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
144 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
145
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
146 // Used to store marked span information in the history.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
147 function attachLocalSpans(doc, change, from, to) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
148 let existing = change["spans_" + doc.id], n = 0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
149 doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), line => {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
150 if (line.markedSpans)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
151 (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
152 ++n
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
153 })
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
154 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
155
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
156 // When un/re-doing restores text containing marked spans, those
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
157 // that have been explicitly cleared should not be restored.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
158 function removeClearedSpans(spans) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
159 if (!spans) return null
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
160 let out
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
161 for (let i = 0; i < spans.length; ++i) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
162 if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i) }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
163 else if (out) out.push(spans[i])
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
164 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
165 return !out ? spans : out.length ? out : null
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
166 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
167
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
168 // Retrieve and filter the old marked spans stored in a change event.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
169 function getOldSpans(doc, change) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
170 let found = change["spans_" + doc.id]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
171 if (!found) return null
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
172 let nw = []
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
173 for (let i = 0; i < change.text.length; ++i)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
174 nw.push(removeClearedSpans(found[i]))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
175 return nw
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
176 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
177
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
178 // Used for un/re-doing changes from the history. Combines the
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
179 // result of computing the existing spans with the set of spans that
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
180 // existed in the history (so that deleting around a span and then
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
181 // undoing brings back the span).
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
182 export function mergeOldSpans(doc, change) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
183 let old = getOldSpans(doc, change)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
184 let stretched = stretchSpansOverChange(doc, change)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
185 if (!old) return stretched
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
186 if (!stretched) return old
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
187
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
188 for (let i = 0; i < old.length; ++i) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
189 let oldCur = old[i], stretchCur = stretched[i]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
190 if (oldCur && stretchCur) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
191 spans: for (let j = 0; j < stretchCur.length; ++j) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
192 let span = stretchCur[j]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
193 for (let k = 0; k < oldCur.length; ++k)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
194 if (oldCur[k].marker == span.marker) continue spans
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
195 oldCur.push(span)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
196 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
197 } else if (stretchCur) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
198 old[i] = stretchCur
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
199 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
200 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
201 return old
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
202 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
203
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
204 // Used both to provide a JSON-safe object in .getHistory, and, when
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
205 // detaching a document, to split the history in two
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
206 export function copyHistoryArray(events, newGroup, instantiateSel) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
207 let copy = []
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
208 for (let i = 0; i < events.length; ++i) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
209 let event = events[i]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
210 if (event.ranges) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
211 copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
212 continue
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
213 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
214 let changes = event.changes, newChanges = []
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
215 copy.push({changes: newChanges})
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
216 for (let j = 0; j < changes.length; ++j) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
217 let change = changes[j], m
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
218 newChanges.push({from: change.from, to: change.to, text: change.text})
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
219 if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
220 if (indexOf(newGroup, Number(m[1])) > -1) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
221 lst(newChanges)[prop] = change[prop]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
222 delete change[prop]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
223 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
224 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
225 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
226 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
227 return copy
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
228 }