codemirror-rails 3.13 → 3.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/codemirror/rails/version.rb +2 -2
- data/vendor/assets/javascripts/codemirror.js +328 -250
- data/vendor/assets/javascripts/codemirror/addons/comment/comment.js +7 -6
- data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +33 -7
- data/vendor/assets/javascripts/codemirror/addons/edit/matchbrackets.js +14 -10
- data/vendor/assets/javascripts/codemirror/addons/edit/trailingspace.js +15 -0
- data/vendor/assets/javascripts/codemirror/addons/fold/brace-fold.js +70 -17
- data/vendor/assets/javascripts/codemirror/addons/fold/foldcode.js +56 -20
- data/vendor/assets/javascripts/codemirror/addons/fold/xml-fold.js +135 -39
- data/vendor/assets/javascripts/codemirror/addons/hint/html-hint.js +324 -571
- data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +199 -109
- data/vendor/assets/javascripts/codemirror/addons/hint/xml-hint.js +60 -113
- data/vendor/assets/javascripts/codemirror/addons/lint/coffeescript-lint.js +24 -0
- data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +431 -0
- data/vendor/assets/javascripts/codemirror/addons/mode/multiplex.js +7 -1
- data/vendor/assets/javascripts/codemirror/addons/search/match-highlighter.js +46 -20
- data/vendor/assets/javascripts/codemirror/addons/search/search.js +1 -1
- data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +370 -13
- data/vendor/assets/javascripts/codemirror/keymaps/extra.js +43 -0
- data/vendor/assets/javascripts/codemirror/keymaps/vim.js +535 -214
- data/vendor/assets/javascripts/codemirror/modes/clike.js +56 -0
- data/vendor/assets/javascripts/codemirror/modes/javascript.js +19 -14
- data/vendor/assets/javascripts/codemirror/modes/markdown.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/ruby.js +67 -16
- data/vendor/assets/javascripts/codemirror/modes/smarty.js +167 -110
- data/vendor/assets/javascripts/codemirror/modes/sql.js +97 -15
- data/vendor/assets/javascripts/codemirror/modes/xml.js +14 -18
- data/vendor/assets/stylesheets/codemirror.css +0 -1
- data/vendor/assets/stylesheets/codemirror/addons/merge/merge.css +82 -0
- metadata +7 -2
@@ -0,0 +1,24 @@
|
|
1
|
+
// Depends on coffeelint.js from http://www.coffeelint.org/js/coffeelint.js
|
2
|
+
|
3
|
+
CodeMirror.coffeeValidator = function(text) {
|
4
|
+
var found = [];
|
5
|
+
var parseError = function(err) {
|
6
|
+
var loc = err.lineNumber;
|
7
|
+
found.push({from: CodeMirror.Pos(loc-1, 0),
|
8
|
+
to: CodeMirror.Pos(loc, 0),
|
9
|
+
severity: err.level,
|
10
|
+
message: err.message});
|
11
|
+
};
|
12
|
+
try {
|
13
|
+
var res = coffeelint.lint(text);
|
14
|
+
for(var i = 0; i < res.length; i++) {
|
15
|
+
parseError(res[i]);
|
16
|
+
}
|
17
|
+
} catch(e) {
|
18
|
+
found.push({from: CodeMirror.Pos(e.location.first_line, 0),
|
19
|
+
to: CodeMirror.Pos(e.location.last_line, e.location.last_column),
|
20
|
+
severity: 'error',
|
21
|
+
message: e.message});
|
22
|
+
}
|
23
|
+
return found;
|
24
|
+
};
|
@@ -0,0 +1,431 @@
|
|
1
|
+
(function() {
|
2
|
+
"use strict";
|
3
|
+
|
4
|
+
var Pos = CodeMirror.Pos;
|
5
|
+
var svgNS = "http://www.w3.org/2000/svg";
|
6
|
+
|
7
|
+
function DiffView(mv, type) {
|
8
|
+
this.mv = mv;
|
9
|
+
this.type = type;
|
10
|
+
this.classes = type == "left"
|
11
|
+
? {chunk: "CodeMirror-diff-l-chunk",
|
12
|
+
start: "CodeMirror-diff-l-chunk-start",
|
13
|
+
end: "CodeMirror-diff-l-chunk-end",
|
14
|
+
insert: "CodeMirror-diff-l-inserted",
|
15
|
+
del: "CodeMirror-diff-l-deleted",
|
16
|
+
connect: "CodeMirror-diff-l-connect"}
|
17
|
+
: {chunk: "CodeMirror-diff-r-chunk",
|
18
|
+
start: "CodeMirror-diff-r-chunk-start",
|
19
|
+
end: "CodeMirror-diff-r-chunk-end",
|
20
|
+
insert: "CodeMirror-diff-r-inserted",
|
21
|
+
del: "CodeMirror-diff-r-deleted",
|
22
|
+
connect: "CodeMirror-diff-r-connect"};
|
23
|
+
}
|
24
|
+
|
25
|
+
DiffView.prototype = {
|
26
|
+
constructor: DiffView,
|
27
|
+
init: function(pane, orig, options) {
|
28
|
+
this.edit = this.mv.edit;
|
29
|
+
this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: true}, copyObj(options)));
|
30
|
+
|
31
|
+
this.diff = getDiff(orig, options.value);
|
32
|
+
this.diffOutOfDate = false;
|
33
|
+
|
34
|
+
this.forceUpdate = registerUpdate(this);
|
35
|
+
setScrollLock(this, true, false);
|
36
|
+
registerScroll(this);
|
37
|
+
}
|
38
|
+
};
|
39
|
+
|
40
|
+
function registerUpdate(dv) {
|
41
|
+
var edit = {from: 0, to: 0, marked: []};
|
42
|
+
var orig = {from: 0, to: 0, marked: []};
|
43
|
+
var debounceChange;
|
44
|
+
function update() {
|
45
|
+
if (dv.diffOutOfDate) {
|
46
|
+
dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());
|
47
|
+
dv.diffOutOfDate = false;
|
48
|
+
}
|
49
|
+
updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);
|
50
|
+
updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
|
51
|
+
drawConnectors(dv);
|
52
|
+
}
|
53
|
+
function set(slow) {
|
54
|
+
clearTimeout(debounceChange);
|
55
|
+
debounceChange = setTimeout(update, slow == true ? 250 : 100);
|
56
|
+
}
|
57
|
+
dv.edit.on("change", function() {
|
58
|
+
if (!dv.diffOutOfDate) {
|
59
|
+
dv.diffOutOfDate = true;
|
60
|
+
edit.from = edit.to = orig.from = orig.to = 0;
|
61
|
+
}
|
62
|
+
set(true);
|
63
|
+
});
|
64
|
+
dv.edit.on("viewportChange", set);
|
65
|
+
dv.orig.on("viewportChange", set);
|
66
|
+
update();
|
67
|
+
return update;
|
68
|
+
}
|
69
|
+
|
70
|
+
function registerScroll(dv) {
|
71
|
+
dv.edit.on("scroll", function() {
|
72
|
+
syncScroll(dv, DIFF_INSERT) && drawConnectors(dv);
|
73
|
+
});
|
74
|
+
dv.orig.on("scroll", function() {
|
75
|
+
syncScroll(dv, DIFF_DELETE) && drawConnectors(dv);
|
76
|
+
});
|
77
|
+
}
|
78
|
+
|
79
|
+
function syncScroll(dv, type) {
|
80
|
+
// Change handler will do a refresh after a timeout when diff is out of date
|
81
|
+
if (dv.diffOutOfDate) return false;
|
82
|
+
if (!dv.lockScroll) return true;
|
83
|
+
var editor, other, now = +new Date;
|
84
|
+
if (type == DIFF_INSERT) { editor = dv.edit; other = dv.orig; }
|
85
|
+
else { editor = dv.orig; other = dv.edit; }
|
86
|
+
// Don't take action if the position of this editor was recently set
|
87
|
+
// (to prevent feedback loops)
|
88
|
+
if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 50 > now) return false;
|
89
|
+
|
90
|
+
var sInfo = editor.getScrollInfo(), halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;
|
91
|
+
var mid = editor.lineAtHeight(midY, "local");
|
92
|
+
var around = chunkBoundariesAround(dv.diff, mid, type == DIFF_INSERT);
|
93
|
+
var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);
|
94
|
+
var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);
|
95
|
+
var ratio = (midY - off.top) / (off.bot - off.top);
|
96
|
+
other.scrollTo(null, (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top));
|
97
|
+
other.state.scrollSetAt = now;
|
98
|
+
other.state.scrollSetBy = dv;
|
99
|
+
return true;
|
100
|
+
}
|
101
|
+
|
102
|
+
function getOffsets(editor, around) {
|
103
|
+
var bot = around.after;
|
104
|
+
if (bot == null) bot = editor.lastLine() + 1;
|
105
|
+
return {top: editor.heightAtLine(around.before || 0, "local"),
|
106
|
+
bot: editor.heightAtLine(bot, "local")};
|
107
|
+
}
|
108
|
+
|
109
|
+
function setScrollLock(dv, val, action) {
|
110
|
+
dv.lockScroll = val;
|
111
|
+
if (val && action != false) syncScroll(dv, DIFF_INSERT) && drawConnectors(dv);
|
112
|
+
dv.lockButton.innerHTML = val ? "\u21db\u21da" : "\u21db \u21da";
|
113
|
+
}
|
114
|
+
|
115
|
+
// Updating the marks for editor content
|
116
|
+
|
117
|
+
function clearMarks(editor, arr, classes) {
|
118
|
+
for (var i = 0; i < arr.length; ++i) {
|
119
|
+
var mark = arr[i];
|
120
|
+
if (mark instanceof CodeMirror.TextMarker) {
|
121
|
+
mark.clear();
|
122
|
+
} else {
|
123
|
+
editor.removeLineClass(mark, "background", classes.chunk);
|
124
|
+
editor.removeLineClass(mark, "background", classes.start);
|
125
|
+
editor.removeLineClass(mark, "background", classes.end);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
arr.length = 0;
|
129
|
+
}
|
130
|
+
|
131
|
+
// FIXME maybe add a margin around viewport to prevent too many updates
|
132
|
+
function updateMarks(editor, diff, state, type, classes) {
|
133
|
+
var vp = editor.getViewport();
|
134
|
+
editor.operation(function() {
|
135
|
+
if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
|
136
|
+
clearMarks(editor, state.marked, classes);
|
137
|
+
markChanges(editor, diff, type, state.marked, vp.from, vp.to, classes);
|
138
|
+
state.from = vp.from; state.to = vp.to;
|
139
|
+
} else {
|
140
|
+
if (vp.from < state.from) {
|
141
|
+
markChanges(editor, diff, type, state.marked, vp.from, state.from, classes);
|
142
|
+
state.from = vp.from;
|
143
|
+
}
|
144
|
+
if (vp.to > state.to) {
|
145
|
+
markChanges(editor, diff, type, state.marked, state.to, vp.to, classes);
|
146
|
+
state.to = vp.to;
|
147
|
+
}
|
148
|
+
}
|
149
|
+
});
|
150
|
+
}
|
151
|
+
|
152
|
+
function markChanges(editor, diff, type, marks, from, to, classes) {
|
153
|
+
var pos = Pos(0, 0);
|
154
|
+
var top = Pos(from, 0), bot = editor.clipPos(Pos(to - 1));
|
155
|
+
var cls = type == DIFF_DELETE ? classes.del : classes.insert;
|
156
|
+
function markChunk(start, end) {
|
157
|
+
var bfrom = Math.max(from, start), bto = Math.min(to, end);
|
158
|
+
for (var i = bfrom; i < bto; ++i) {
|
159
|
+
var line = editor.addLineClass(i, "background", classes.chunk);
|
160
|
+
if (i == start) editor.addLineClass(line, "background", classes.start);
|
161
|
+
if (i == end - 1) editor.addLineClass(line, "background", classes.end);
|
162
|
+
marks.push(line);
|
163
|
+
}
|
164
|
+
// When the chunk is empty, make sure a horizontal line shows up
|
165
|
+
if (start == end && bfrom == end && bto == end) {
|
166
|
+
if (bfrom)
|
167
|
+
marks.push(editor.addLineClass(bfrom - 1, "background", classes.end));
|
168
|
+
else
|
169
|
+
marks.push(editor.addLineClass(bfrom, "background", classes.start));
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
var chunkStart = 0;
|
174
|
+
for (var i = 0; i < diff.length; ++i) {
|
175
|
+
var part = diff[i], tp = part[0], str = part[1];
|
176
|
+
if (tp == DIFF_EQUAL) {
|
177
|
+
var cleanFrom = pos.line + (startOfLineClean(diff, i) ? 0 : 1);
|
178
|
+
moveOver(pos, str);
|
179
|
+
var cleanTo = pos.line + (endOfLineClean(diff, i) ? 1 : 0);
|
180
|
+
if (cleanTo > cleanFrom) {
|
181
|
+
if (i) markChunk(chunkStart, cleanFrom);
|
182
|
+
chunkStart = cleanTo;
|
183
|
+
}
|
184
|
+
} else {
|
185
|
+
if (tp == type) {
|
186
|
+
var end = moveOver(pos, str, true);
|
187
|
+
var a = posMax(top, pos), b = posMin(bot, end);
|
188
|
+
if (!posEq(a, b))
|
189
|
+
marks.push(editor.markText(a, b, {className: cls}));
|
190
|
+
pos = end;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
}
|
194
|
+
if (chunkStart <= pos.line) markChunk(chunkStart, pos.line + 1);
|
195
|
+
}
|
196
|
+
|
197
|
+
// Updating the gap between editor and original
|
198
|
+
|
199
|
+
function drawConnectors(dv) {
|
200
|
+
if (dv.svg) {
|
201
|
+
clear(dv.svg);
|
202
|
+
var w = dv.gap.offsetWidth;
|
203
|
+
attrs(dv.svg, "width", w, "height", dv.gap.offsetHeight);
|
204
|
+
}
|
205
|
+
clear(dv.copyButtons);
|
206
|
+
|
207
|
+
var flip = dv.type == "left";
|
208
|
+
var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();
|
209
|
+
var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top;
|
210
|
+
iterateChunks(dv.diff, function(topOrig, botOrig, topEdit, botEdit) {
|
211
|
+
if (topEdit >= vpEdit.to || botEdit < vpEdit.from ||
|
212
|
+
topOrig >= vpOrig.to || botOrig < vpOrig.from)
|
213
|
+
return;
|
214
|
+
var topLpx = dv.orig.heightAtLine(topOrig, "local") - sTopOrig, top = topLpx;
|
215
|
+
if (dv.svg) {
|
216
|
+
var topRpx = dv.edit.heightAtLine(topEdit, "local") - sTopEdit;
|
217
|
+
if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
|
218
|
+
var botLpx = dv.orig.heightAtLine(botOrig, "local") - sTopOrig;
|
219
|
+
var botRpx = dv.edit.heightAtLine(botEdit, "local") - sTopEdit;
|
220
|
+
if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
|
221
|
+
var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
|
222
|
+
var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
|
223
|
+
attrs(dv.svg.appendChild(document.createElementNS(svgNS, "path")),
|
224
|
+
"d", "M -1 " + topRpx + curveTop + " L " + (w + 2) + " " + botLpx + curveBot + " z",
|
225
|
+
"class", dv.classes.connect);
|
226
|
+
}
|
227
|
+
var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\u21dd" : "\u21dc",
|
228
|
+
"CodeMirror-diff-copy"));
|
229
|
+
copy.title = "Revert chunk";
|
230
|
+
copy.chunk = {topEdit: topEdit, botEdit: botEdit, topOrig: topOrig, botOrig: botOrig};
|
231
|
+
copy.style.top = top + "px";
|
232
|
+
});
|
233
|
+
}
|
234
|
+
|
235
|
+
function copyChunk(dv, chunk) {
|
236
|
+
if (dv.diffOutOfDate) return;
|
237
|
+
dv.edit.replaceRange(dv.orig.getRange(Pos(chunk.topOrig, 0), Pos(chunk.botOrig, 0)),
|
238
|
+
Pos(chunk.topEdit, 0), Pos(chunk.botEdit, 0));
|
239
|
+
}
|
240
|
+
|
241
|
+
// Merge view, containing 0, 1, or 2 diff views.
|
242
|
+
|
243
|
+
var MergeView = CodeMirror.MergeView = function(node, options) {
|
244
|
+
if (!(this instanceof MergeView)) return new MergeView(node, options);
|
245
|
+
|
246
|
+
var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight;
|
247
|
+
var hasLeft = origLeft != null, hasRight = origRight != null;
|
248
|
+
var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0);
|
249
|
+
var wrap = [], left = this.left = null, right = this.right = null;
|
250
|
+
|
251
|
+
if (hasLeft) {
|
252
|
+
left = this.left = new DiffView(this, "left");
|
253
|
+
var leftPane = elt("div", null, "CodeMirror-diff-pane");
|
254
|
+
wrap.push(leftPane);
|
255
|
+
wrap.push(buildGap(left));
|
256
|
+
}
|
257
|
+
|
258
|
+
var editPane = elt("div", null, "CodeMirror-diff-pane");
|
259
|
+
wrap.push(editPane);
|
260
|
+
|
261
|
+
if (hasRight) {
|
262
|
+
right = this.right = new DiffView(this, "right");
|
263
|
+
wrap.push(buildGap(right));
|
264
|
+
var rightPane = elt("div", null, "CodeMirror-diff-pane");
|
265
|
+
wrap.push(rightPane);
|
266
|
+
}
|
267
|
+
|
268
|
+
wrap.push(elt("div", null, null, "height: 0; clear: both;"));
|
269
|
+
var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-diff CodeMirror-diff-" + panes + "pane"));
|
270
|
+
this.edit = CodeMirror(editPane, copyObj(options));
|
271
|
+
|
272
|
+
if (left) left.init(leftPane, origLeft, options);
|
273
|
+
if (right) right.init(rightPane, origRight, options);
|
274
|
+
|
275
|
+
var onResize = function() {
|
276
|
+
if (left) drawConnectors(left);
|
277
|
+
if (right) drawConnectors(right);
|
278
|
+
};
|
279
|
+
CodeMirror.on(window, "resize", onResize);
|
280
|
+
var resizeInterval = setInterval(function() {
|
281
|
+
for (var p = wrapElt.parentNode; p && p != document.body; p = p.parentNode) {}
|
282
|
+
if (!p) { clearInterval(resizeInterval); CodeMirror.off(window, "resize", onResize); }
|
283
|
+
}, 5000);
|
284
|
+
};
|
285
|
+
|
286
|
+
function buildGap(dv) {
|
287
|
+
var lock = dv.lockButton = elt("div", null, "CodeMirror-diff-scrolllock");
|
288
|
+
lock.title = "Toggle locked scrolling";
|
289
|
+
var lockWrap = elt("div", [lock], "CodeMirror-diff-scrolllock-wrap");
|
290
|
+
CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); });
|
291
|
+
dv.copyButtons = elt("div", null, "CodeMirror-diff-copybuttons-" + dv.type);
|
292
|
+
CodeMirror.on(dv.copyButtons, "click", function(e) {
|
293
|
+
var node = e.target || e.srcElement;
|
294
|
+
if (node.chunk) copyChunk(dv, node.chunk);
|
295
|
+
});
|
296
|
+
var gapElts = [dv.copyButtons, lockWrap];
|
297
|
+
var svg = document.createElementNS && document.createElementNS(svgNS, "svg");
|
298
|
+
if (svg && !svg.createSVGRect) svg = null;
|
299
|
+
dv.svg = svg;
|
300
|
+
if (svg) gapElts.push(svg);
|
301
|
+
|
302
|
+
return dv.gap = elt("div", gapElts, "CodeMirror-diff-gap");
|
303
|
+
}
|
304
|
+
|
305
|
+
MergeView.prototype = {
|
306
|
+
constuctor: MergeView,
|
307
|
+
editor: function() { return this.edit; },
|
308
|
+
rightOriginal: function() { return this.right && this.right.orig; },
|
309
|
+
leftOriginal: function() { return this.left && this.left.orig; }
|
310
|
+
};
|
311
|
+
|
312
|
+
// Operations on diffs
|
313
|
+
|
314
|
+
var dmp = new diff_match_patch();
|
315
|
+
function getDiff(a, b) {
|
316
|
+
var diff = dmp.diff_main(a, b);
|
317
|
+
dmp.diff_cleanupSemantic(diff);
|
318
|
+
// The library sometimes leaves in empty parts, which confuse the algorithm
|
319
|
+
for (var i = 0; i < diff.length; ++i) {
|
320
|
+
var part = diff[i];
|
321
|
+
if (!part[1]) {
|
322
|
+
diff.splice(i--, 1);
|
323
|
+
} else if (i && diff[i - 1][0] == part[0]) {
|
324
|
+
diff.splice(i--, 1);
|
325
|
+
diff[i][1] += part[1];
|
326
|
+
}
|
327
|
+
}
|
328
|
+
return diff;
|
329
|
+
}
|
330
|
+
|
331
|
+
function iterateChunks(diff, f) {
|
332
|
+
var startEdit = 0, startOrig = 0;
|
333
|
+
var edit = Pos(0, 0), orig = Pos(0, 0);
|
334
|
+
for (var i = 0; i < diff.length; ++i) {
|
335
|
+
var part = diff[i], tp = part[0];
|
336
|
+
if (tp == DIFF_EQUAL) {
|
337
|
+
var startOff = startOfLineClean(diff, i) ? 0 : 1;
|
338
|
+
var cleanFromEdit = edit.line + startOff, cleanFromOrig = orig.line + startOff;
|
339
|
+
moveOver(edit, part[1], null, orig);
|
340
|
+
var endOff = endOfLineClean(diff, i) ? 1 : 0;
|
341
|
+
var cleanToEdit = edit.line + endOff, cleanToOrig = orig.line + endOff;
|
342
|
+
if (cleanToEdit > cleanFromEdit) {
|
343
|
+
if (i) f(startOrig, cleanFromOrig, startEdit, cleanFromEdit);
|
344
|
+
startEdit = cleanToEdit; startOrig = cleanToOrig;
|
345
|
+
}
|
346
|
+
} else {
|
347
|
+
moveOver(tp == DIFF_INSERT ? edit : orig, part[1]);
|
348
|
+
}
|
349
|
+
}
|
350
|
+
if (startEdit <= edit.line || startOrig <= orig.line)
|
351
|
+
f(startOrig, orig.line + 1, startEdit, edit.line + 1);
|
352
|
+
}
|
353
|
+
|
354
|
+
function endOfLineClean(diff, i) {
|
355
|
+
if (i == diff.length - 1) return true;
|
356
|
+
var next = diff[i + 1][1];
|
357
|
+
if (next.length == 1 || next.charCodeAt(0) != 10) return false;
|
358
|
+
if (i == diff.length - 2) return true;
|
359
|
+
next = diff[i + 2][1];
|
360
|
+
return next.length > 1 && next.charCodeAt(0) == 10;
|
361
|
+
}
|
362
|
+
|
363
|
+
function startOfLineClean(diff, i) {
|
364
|
+
if (i == 0) return true;
|
365
|
+
var last = diff[i - 1][1];
|
366
|
+
if (last.charCodeAt(last.length - 1) != 10) return false;
|
367
|
+
if (i == 1) return true;
|
368
|
+
last = diff[i - 2][1];
|
369
|
+
return last.charCodeAt(last.length - 1) == 10;
|
370
|
+
}
|
371
|
+
|
372
|
+
function chunkBoundariesAround(diff, n, nInEdit) {
|
373
|
+
var beforeE, afterE, beforeO, afterO;
|
374
|
+
iterateChunks(diff, function(fromOrig, toOrig, fromEdit, toEdit) {
|
375
|
+
var fromLocal = nInEdit ? fromEdit : fromOrig;
|
376
|
+
var toLocal = nInEdit ? toEdit : toOrig;
|
377
|
+
if (afterE == null) {
|
378
|
+
if (fromLocal > n) { afterE = fromEdit; afterO = fromOrig; }
|
379
|
+
else if (toLocal > n) { afterE = toEdit; afterO = toOrig; }
|
380
|
+
}
|
381
|
+
if (toLocal <= n) { beforeE = toEdit; beforeO = toOrig; }
|
382
|
+
else if (fromLocal <= n) { beforeE = fromEdit; beforeO = fromOrig; }
|
383
|
+
});
|
384
|
+
return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};
|
385
|
+
}
|
386
|
+
|
387
|
+
// General utilities
|
388
|
+
|
389
|
+
function elt(tag, content, className, style) {
|
390
|
+
var e = document.createElement(tag);
|
391
|
+
if (className) e.className = className;
|
392
|
+
if (style) e.style.cssText = style;
|
393
|
+
if (typeof content == "string") e.appendChild(document.createTextNode(content));
|
394
|
+
else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
|
395
|
+
return e;
|
396
|
+
}
|
397
|
+
|
398
|
+
function clear(node) {
|
399
|
+
for (var count = node.childNodes.length; count > 0; --count)
|
400
|
+
node.removeChild(node.firstChild);
|
401
|
+
}
|
402
|
+
|
403
|
+
function attrs(elt) {
|
404
|
+
for (var i = 1; i < arguments.length; i += 2)
|
405
|
+
elt.setAttribute(arguments[i], arguments[i+1]);
|
406
|
+
}
|
407
|
+
|
408
|
+
function copyObj(obj, target) {
|
409
|
+
if (!target) target = {};
|
410
|
+
for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
|
411
|
+
return target;
|
412
|
+
}
|
413
|
+
|
414
|
+
function moveOver(pos, str, copy, other) {
|
415
|
+
var out = copy ? Pos(pos.line, pos.ch) : pos, at = 0;
|
416
|
+
for (;;) {
|
417
|
+
var nl = str.indexOf("\n", at);
|
418
|
+
if (nl == -1) break;
|
419
|
+
++out.line;
|
420
|
+
if (other) ++other.line;
|
421
|
+
at = nl + 1;
|
422
|
+
}
|
423
|
+
out.ch = (at ? 0 : out.ch) + (str.length - at);
|
424
|
+
if (other) other.ch = (at ? 0 : other.ch) + (str.length - at);
|
425
|
+
return out;
|
426
|
+
}
|
427
|
+
|
428
|
+
function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }
|
429
|
+
function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }
|
430
|
+
function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
|
431
|
+
})();
|