mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-26 13:00:24 +10:00
Streamlined the libraries.
This commit is contained in:
@@ -1,32 +0,0 @@
|
||||
.CodeMirror-dialog {
|
||||
position: absolute;
|
||||
left: 0; right: 0;
|
||||
background: white;
|
||||
z-index: 15;
|
||||
padding: .1em .8em;
|
||||
overflow: hidden;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.CodeMirror-dialog-top {
|
||||
border-bottom: 1px solid #eee;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-dialog-bottom {
|
||||
border-top: 1px solid #eee;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-dialog input {
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
width: 20em;
|
||||
color: inherit;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.CodeMirror-dialog button {
|
||||
font-size: 70%;
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
// Open simple dialogs on top of an editor. Relies on dialog.css.
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
function dialogDiv(cm, template, bottom) {
|
||||
var wrap = cm.getWrapperElement();
|
||||
var dialog;
|
||||
dialog = wrap.appendChild(document.createElement("div"));
|
||||
if (bottom)
|
||||
dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
|
||||
else
|
||||
dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
|
||||
|
||||
if (typeof template == "string") {
|
||||
dialog.innerHTML = template;
|
||||
} else { // Assuming it's a detached DOM element.
|
||||
dialog.appendChild(template);
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
|
||||
function closeNotification(cm, newVal) {
|
||||
if (cm.state.currentNotificationClose)
|
||||
cm.state.currentNotificationClose();
|
||||
cm.state.currentNotificationClose = newVal;
|
||||
}
|
||||
|
||||
CodeMirror.defineExtension("openDialog", function(template, callback, options) {
|
||||
if (!options) options = {};
|
||||
|
||||
closeNotification(this, null);
|
||||
|
||||
var dialog = dialogDiv(this, template, options.bottom);
|
||||
var closed = false, me = this;
|
||||
function close(newVal) {
|
||||
if (typeof newVal == 'string') {
|
||||
inp.value = newVal;
|
||||
} else {
|
||||
if (closed) return;
|
||||
closed = true;
|
||||
dialog.parentNode.removeChild(dialog);
|
||||
me.focus();
|
||||
|
||||
if (options.onClose) options.onClose(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
var inp = dialog.getElementsByTagName("input")[0], button;
|
||||
if (inp) {
|
||||
if (options.value) {
|
||||
inp.value = options.value;
|
||||
inp.select();
|
||||
}
|
||||
|
||||
if (options.onInput)
|
||||
CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});
|
||||
if (options.onKeyUp)
|
||||
CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
|
||||
|
||||
CodeMirror.on(inp, "keydown", function(e) {
|
||||
if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
|
||||
if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {
|
||||
inp.blur();
|
||||
CodeMirror.e_stop(e);
|
||||
close();
|
||||
}
|
||||
if (e.keyCode == 13) callback(inp.value, e);
|
||||
});
|
||||
|
||||
if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
|
||||
|
||||
inp.focus();
|
||||
} else if (button = dialog.getElementsByTagName("button")[0]) {
|
||||
CodeMirror.on(button, "click", function() {
|
||||
close();
|
||||
me.focus();
|
||||
});
|
||||
|
||||
if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);
|
||||
|
||||
button.focus();
|
||||
}
|
||||
return close;
|
||||
});
|
||||
|
||||
CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) {
|
||||
closeNotification(this, null);
|
||||
var dialog = dialogDiv(this, template, options && options.bottom);
|
||||
var buttons = dialog.getElementsByTagName("button");
|
||||
var closed = false, me = this, blurring = 1;
|
||||
function close() {
|
||||
if (closed) return;
|
||||
closed = true;
|
||||
dialog.parentNode.removeChild(dialog);
|
||||
me.focus();
|
||||
}
|
||||
buttons[0].focus();
|
||||
for (var i = 0; i < buttons.length; ++i) {
|
||||
var b = buttons[i];
|
||||
(function(callback) {
|
||||
CodeMirror.on(b, "click", function(e) {
|
||||
CodeMirror.e_preventDefault(e);
|
||||
close();
|
||||
if (callback) callback(me);
|
||||
});
|
||||
})(callbacks[i]);
|
||||
CodeMirror.on(b, "blur", function() {
|
||||
--blurring;
|
||||
setTimeout(function() { if (blurring <= 0) close(); }, 200);
|
||||
});
|
||||
CodeMirror.on(b, "focus", function() { ++blurring; });
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* openNotification
|
||||
* Opens a notification, that can be closed with an optional timer
|
||||
* (default 5000ms timer) and always closes on click.
|
||||
*
|
||||
* If a notification is opened while another is opened, it will close the
|
||||
* currently opened one and open the new one immediately.
|
||||
*/
|
||||
CodeMirror.defineExtension("openNotification", function(template, options) {
|
||||
closeNotification(this, close);
|
||||
var dialog = dialogDiv(this, template, options && options.bottom);
|
||||
var closed = false, doneTimer;
|
||||
var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;
|
||||
|
||||
function close() {
|
||||
if (closed) return;
|
||||
closed = true;
|
||||
clearTimeout(doneTimer);
|
||||
dialog.parentNode.removeChild(dialog);
|
||||
}
|
||||
|
||||
CodeMirror.on(dialog, 'click', function(e) {
|
||||
CodeMirror.e_preventDefault(e);
|
||||
close();
|
||||
});
|
||||
|
||||
if (duration)
|
||||
doneTimer = setTimeout(close, duration);
|
||||
|
||||
return close;
|
||||
});
|
||||
});
|
||||
@@ -1,112 +0,0 @@
|
||||
.CodeMirror-merge {
|
||||
position: relative;
|
||||
border: 1px solid #ddd;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.CodeMirror-merge, .CodeMirror-merge .CodeMirror {
|
||||
height: 350px;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 47%; }
|
||||
.CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 6%; }
|
||||
.CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }
|
||||
.CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }
|
||||
|
||||
.CodeMirror-merge-pane {
|
||||
display: inline-block;
|
||||
white-space: normal;
|
||||
vertical-align: top;
|
||||
}
|
||||
.CodeMirror-merge-pane-rightmost {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-gap {
|
||||
z-index: 2;
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
border-left: 1px solid #ddd;
|
||||
border-right: 1px solid #ddd;
|
||||
position: relative;
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-scrolllock-wrap {
|
||||
position: absolute;
|
||||
bottom: 0; left: 50%;
|
||||
}
|
||||
.CodeMirror-merge-scrolllock {
|
||||
position: relative;
|
||||
left: -50%;
|
||||
cursor: pointer;
|
||||
color: #555;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
|
||||
position: absolute;
|
||||
left: 0; top: 0;
|
||||
right: 0; bottom: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-copy {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
color: #44c;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-copy-reverse {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
color: #44c;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
|
||||
.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
|
||||
|
||||
.CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
|
||||
background-position: bottom left;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
|
||||
background-position: bottom left;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-r-chunk { background: #ffffe0; }
|
||||
.CodeMirror-merge-r-chunk-start { border-top: 1px solid #ee8; }
|
||||
.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #ee8; }
|
||||
.CodeMirror-merge-r-connect { fill: #ffffe0; stroke: #ee8; stroke-width: 1px; }
|
||||
|
||||
.CodeMirror-merge-l-chunk { background: #eef; }
|
||||
.CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }
|
||||
.CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }
|
||||
.CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
|
||||
|
||||
.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
|
||||
.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
|
||||
.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
|
||||
|
||||
.CodeMirror-merge-collapsed-widget:before {
|
||||
content: "(...)";
|
||||
}
|
||||
.CodeMirror-merge-collapsed-widget {
|
||||
cursor: pointer;
|
||||
color: #88b;
|
||||
background: #eef;
|
||||
border: 1px solid #ddf;
|
||||
font-size: 90%;
|
||||
padding: 0 3px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }
|
||||
@@ -1,735 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
// declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"), require("diff_match_patch"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror", "diff_match_patch"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror, diff_match_patch);
|
||||
})(function(CodeMirror, diff_match_patch) {
|
||||
"use strict";
|
||||
var Pos = CodeMirror.Pos;
|
||||
var svgNS = "http://www.w3.org/2000/svg";
|
||||
|
||||
function DiffView(mv, type) {
|
||||
this.mv = mv;
|
||||
this.type = type;
|
||||
this.classes = type == "left"
|
||||
? {chunk: "CodeMirror-merge-l-chunk",
|
||||
start: "CodeMirror-merge-l-chunk-start",
|
||||
end: "CodeMirror-merge-l-chunk-end",
|
||||
insert: "CodeMirror-merge-l-inserted",
|
||||
del: "CodeMirror-merge-l-deleted",
|
||||
connect: "CodeMirror-merge-l-connect"}
|
||||
: {chunk: "CodeMirror-merge-r-chunk",
|
||||
start: "CodeMirror-merge-r-chunk-start",
|
||||
end: "CodeMirror-merge-r-chunk-end",
|
||||
insert: "CodeMirror-merge-r-inserted",
|
||||
del: "CodeMirror-merge-r-deleted",
|
||||
connect: "CodeMirror-merge-r-connect"};
|
||||
}
|
||||
|
||||
DiffView.prototype = {
|
||||
constructor: DiffView,
|
||||
init: function(pane, orig, options) {
|
||||
this.edit = this.mv.edit;
|
||||
this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
|
||||
|
||||
this.diff = getDiff(asString(orig), asString(options.value));
|
||||
this.chunks = getChunks(this.diff);
|
||||
this.diffOutOfDate = this.dealigned = false;
|
||||
|
||||
this.showDifferences = options.showDifferences !== false;
|
||||
this.forceUpdate = registerUpdate(this);
|
||||
setScrollLock(this, true, false);
|
||||
registerScroll(this);
|
||||
},
|
||||
setShowDifferences: function(val) {
|
||||
val = val !== false;
|
||||
if (val != this.showDifferences) {
|
||||
this.showDifferences = val;
|
||||
this.forceUpdate("full");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function ensureDiff(dv) {
|
||||
if (dv.diffOutOfDate) {
|
||||
dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());
|
||||
dv.chunks = getChunks(dv.diff);
|
||||
dv.diffOutOfDate = false;
|
||||
CodeMirror.signal(dv.edit, "updateDiff", dv.diff);
|
||||
}
|
||||
}
|
||||
|
||||
var updating = false;
|
||||
function registerUpdate(dv) {
|
||||
var edit = {from: 0, to: 0, marked: []};
|
||||
var orig = {from: 0, to: 0, marked: []};
|
||||
var debounceChange, updatingFast = false;
|
||||
function update(mode) {
|
||||
updating = true;
|
||||
updatingFast = false;
|
||||
if (mode == "full") {
|
||||
if (dv.svg) clear(dv.svg);
|
||||
if (dv.copyButtons) clear(dv.copyButtons);
|
||||
clearMarks(dv.edit, edit.marked, dv.classes);
|
||||
clearMarks(dv.orig, orig.marked, dv.classes);
|
||||
edit.from = edit.to = orig.from = orig.to = 0;
|
||||
}
|
||||
ensureDiff(dv);
|
||||
if (dv.showDifferences) {
|
||||
updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);
|
||||
updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
|
||||
}
|
||||
makeConnections(dv);
|
||||
|
||||
if (dv.mv.options.connect == "align")
|
||||
alignChunks(dv);
|
||||
updating = false;
|
||||
}
|
||||
function setDealign(fast) {
|
||||
if (updating) return;
|
||||
dv.dealigned = true;
|
||||
set(fast);
|
||||
}
|
||||
function set(fast) {
|
||||
if (updating || updatingFast) return;
|
||||
clearTimeout(debounceChange);
|
||||
if (fast === true) updatingFast = true;
|
||||
debounceChange = setTimeout(update, fast === true ? 20 : 250);
|
||||
}
|
||||
function change(_cm, change) {
|
||||
if (!dv.diffOutOfDate) {
|
||||
dv.diffOutOfDate = true;
|
||||
edit.from = edit.to = orig.from = orig.to = 0;
|
||||
}
|
||||
// Update faster when a line was added/removed
|
||||
setDealign(change.text.length - 1 != change.to.line - change.from.line);
|
||||
}
|
||||
dv.edit.on("change", change);
|
||||
dv.orig.on("change", change);
|
||||
dv.edit.on("markerAdded", setDealign);
|
||||
dv.edit.on("markerCleared", setDealign);
|
||||
dv.orig.on("markerAdded", setDealign);
|
||||
dv.orig.on("markerCleared", setDealign);
|
||||
dv.edit.on("viewportChange", function() { set(false); });
|
||||
dv.orig.on("viewportChange", function() { set(false); });
|
||||
update();
|
||||
return update;
|
||||
}
|
||||
|
||||
function registerScroll(dv) {
|
||||
dv.edit.on("scroll", function() {
|
||||
syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
|
||||
});
|
||||
dv.orig.on("scroll", function() {
|
||||
syncScroll(dv, DIFF_DELETE) && makeConnections(dv);
|
||||
});
|
||||
}
|
||||
|
||||
function syncScroll(dv, type) {
|
||||
// Change handler will do a refresh after a timeout when diff is out of date
|
||||
if (dv.diffOutOfDate) return false;
|
||||
if (!dv.lockScroll) return true;
|
||||
var editor, other, now = +new Date;
|
||||
if (type == DIFF_INSERT) { editor = dv.edit; other = dv.orig; }
|
||||
else { editor = dv.orig; other = dv.edit; }
|
||||
// Don't take action if the position of this editor was recently set
|
||||
// (to prevent feedback loops)
|
||||
if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 50 > now) return false;
|
||||
|
||||
var sInfo = editor.getScrollInfo();
|
||||
if (dv.mv.options.connect == "align") {
|
||||
targetPos = sInfo.top;
|
||||
} else {
|
||||
var halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;
|
||||
var mid = editor.lineAtHeight(midY, "local");
|
||||
var around = chunkBoundariesAround(dv.chunks, mid, type == DIFF_INSERT);
|
||||
var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);
|
||||
var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);
|
||||
var ratio = (midY - off.top) / (off.bot - off.top);
|
||||
var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top);
|
||||
|
||||
var botDist, mix;
|
||||
// Some careful tweaking to make sure no space is left out of view
|
||||
// when scrolling to top or bottom.
|
||||
if (targetPos > sInfo.top && (mix = sInfo.top / halfScreen) < 1) {
|
||||
targetPos = targetPos * mix + sInfo.top * (1 - mix);
|
||||
} else if ((botDist = sInfo.height - sInfo.clientHeight - sInfo.top) < halfScreen) {
|
||||
var otherInfo = other.getScrollInfo();
|
||||
var botDistOther = otherInfo.height - otherInfo.clientHeight - targetPos;
|
||||
if (botDistOther > botDist && (mix = botDist / halfScreen) < 1)
|
||||
targetPos = targetPos * mix + (otherInfo.height - otherInfo.clientHeight - botDist) * (1 - mix);
|
||||
}
|
||||
}
|
||||
|
||||
other.scrollTo(sInfo.left, targetPos);
|
||||
other.state.scrollSetAt = now;
|
||||
other.state.scrollSetBy = dv;
|
||||
return true;
|
||||
}
|
||||
|
||||
function getOffsets(editor, around) {
|
||||
var bot = around.after;
|
||||
if (bot == null) bot = editor.lastLine() + 1;
|
||||
return {top: editor.heightAtLine(around.before || 0, "local"),
|
||||
bot: editor.heightAtLine(bot, "local")};
|
||||
}
|
||||
|
||||
function setScrollLock(dv, val, action) {
|
||||
dv.lockScroll = val;
|
||||
if (val && action != false) syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
|
||||
dv.lockButton.innerHTML = val ? "\u21db\u21da" : "\u21db \u21da";
|
||||
}
|
||||
|
||||
// Updating the marks for editor content
|
||||
|
||||
function clearMarks(editor, arr, classes) {
|
||||
for (var i = 0; i < arr.length; ++i) {
|
||||
var mark = arr[i];
|
||||
if (mark instanceof CodeMirror.TextMarker) {
|
||||
mark.clear();
|
||||
} else if (mark.parent) {
|
||||
editor.removeLineClass(mark, "background", classes.chunk);
|
||||
editor.removeLineClass(mark, "background", classes.start);
|
||||
editor.removeLineClass(mark, "background", classes.end);
|
||||
}
|
||||
}
|
||||
arr.length = 0;
|
||||
}
|
||||
|
||||
// FIXME maybe add a margin around viewport to prevent too many updates
|
||||
function updateMarks(editor, diff, state, type, classes) {
|
||||
var vp = editor.getViewport();
|
||||
editor.operation(function() {
|
||||
if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
|
||||
clearMarks(editor, state.marked, classes);
|
||||
markChanges(editor, diff, type, state.marked, vp.from, vp.to, classes);
|
||||
state.from = vp.from; state.to = vp.to;
|
||||
} else {
|
||||
if (vp.from < state.from) {
|
||||
markChanges(editor, diff, type, state.marked, vp.from, state.from, classes);
|
||||
state.from = vp.from;
|
||||
}
|
||||
if (vp.to > state.to) {
|
||||
markChanges(editor, diff, type, state.marked, state.to, vp.to, classes);
|
||||
state.to = vp.to;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function markChanges(editor, diff, type, marks, from, to, classes) {
|
||||
var pos = Pos(0, 0);
|
||||
var top = Pos(from, 0), bot = editor.clipPos(Pos(to - 1));
|
||||
var cls = type == DIFF_DELETE ? classes.del : classes.insert;
|
||||
function markChunk(start, end) {
|
||||
var bfrom = Math.max(from, start), bto = Math.min(to, end);
|
||||
for (var i = bfrom; i < bto; ++i) {
|
||||
var line = editor.addLineClass(i, "background", classes.chunk);
|
||||
if (i == start) editor.addLineClass(line, "background", classes.start);
|
||||
if (i == end - 1) editor.addLineClass(line, "background", classes.end);
|
||||
marks.push(line);
|
||||
}
|
||||
// When the chunk is empty, make sure a horizontal line shows up
|
||||
if (start == end && bfrom == end && bto == end) {
|
||||
if (bfrom)
|
||||
marks.push(editor.addLineClass(bfrom - 1, "background", classes.end));
|
||||
else
|
||||
marks.push(editor.addLineClass(bfrom, "background", classes.start));
|
||||
}
|
||||
}
|
||||
|
||||
var chunkStart = 0;
|
||||
for (var i = 0; i < diff.length; ++i) {
|
||||
var part = diff[i], tp = part[0], str = part[1];
|
||||
if (tp == DIFF_EQUAL) {
|
||||
var cleanFrom = pos.line + (startOfLineClean(diff, i) ? 0 : 1);
|
||||
moveOver(pos, str);
|
||||
var cleanTo = pos.line + (endOfLineClean(diff, i) ? 1 : 0);
|
||||
if (cleanTo > cleanFrom) {
|
||||
if (i) markChunk(chunkStart, cleanFrom);
|
||||
chunkStart = cleanTo;
|
||||
}
|
||||
} else {
|
||||
if (tp == type) {
|
||||
var end = moveOver(pos, str, true);
|
||||
var a = posMax(top, pos), b = posMin(bot, end);
|
||||
if (!posEq(a, b))
|
||||
marks.push(editor.markText(a, b, {className: cls}));
|
||||
pos = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chunkStart <= pos.line) markChunk(chunkStart, pos.line + 1);
|
||||
}
|
||||
|
||||
// Updating the gap between editor and original
|
||||
|
||||
function makeConnections(dv) {
|
||||
if (!dv.showDifferences) return;
|
||||
|
||||
if (dv.svg) {
|
||||
clear(dv.svg);
|
||||
var w = dv.gap.offsetWidth;
|
||||
attrs(dv.svg, "width", w, "height", dv.gap.offsetHeight);
|
||||
}
|
||||
if (dv.copyButtons) clear(dv.copyButtons);
|
||||
|
||||
var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();
|
||||
var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top;
|
||||
for (var i = 0; i < dv.chunks.length; i++) {
|
||||
var ch = dv.chunks[i];
|
||||
if (ch.editFrom <= vpEdit.to && ch.editTo >= vpEdit.from &&
|
||||
ch.origFrom <= vpOrig.to && ch.origTo >= vpOrig.from)
|
||||
drawConnectorsForChunk(dv, ch, sTopOrig, sTopEdit, w);
|
||||
}
|
||||
}
|
||||
|
||||
function getMatchingOrigLine(editLine, chunks) {
|
||||
var editStart = 0, origStart = 0;
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
var chunk = chunks[i];
|
||||
if (chunk.editTo > editLine && chunk.editFrom <= editLine) return null;
|
||||
if (chunk.editFrom > editLine) break;
|
||||
editStart = chunk.editTo;
|
||||
origStart = chunk.origTo;
|
||||
}
|
||||
return origStart + (editLine - editStart);
|
||||
}
|
||||
|
||||
function findAlignedLines(dv, other) {
|
||||
var linesToAlign = [];
|
||||
for (var i = 0; i < dv.chunks.length; i++) {
|
||||
var chunk = dv.chunks[i];
|
||||
linesToAlign.push([chunk.origTo, chunk.editTo, other ? getMatchingOrigLine(chunk.editTo, other.chunks) : null]);
|
||||
}
|
||||
if (other) {
|
||||
for (var i = 0; i < other.chunks.length; i++) {
|
||||
var chunk = other.chunks[i];
|
||||
for (var j = 0; j < linesToAlign.length; j++) {
|
||||
var align = linesToAlign[j];
|
||||
if (align[1] == chunk.editTo) {
|
||||
j = -1;
|
||||
break;
|
||||
} else if (align[1] > chunk.editTo) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j > -1)
|
||||
linesToAlign.splice(j - 1, 0, [getMatchingOrigLine(chunk.editTo, dv.chunks), chunk.editTo, chunk.origTo]);
|
||||
}
|
||||
}
|
||||
return linesToAlign;
|
||||
}
|
||||
|
||||
function alignChunks(dv, force) {
|
||||
if (!dv.dealigned && !force) return;
|
||||
if (!dv.orig.curOp) return dv.orig.operation(function() {
|
||||
alignChunks(dv, force);
|
||||
});
|
||||
|
||||
dv.dealigned = false;
|
||||
var other = dv.mv.left == dv ? dv.mv.right : dv.mv.left;
|
||||
if (other) {
|
||||
ensureDiff(other);
|
||||
other.dealigned = false;
|
||||
}
|
||||
var linesToAlign = findAlignedLines(dv, other);
|
||||
|
||||
// Clear old aligners
|
||||
var aligners = dv.mv.aligners;
|
||||
for (var i = 0; i < aligners.length; i++)
|
||||
aligners[i].clear();
|
||||
aligners.length = 0;
|
||||
|
||||
var cm = [dv.orig, dv.edit], scroll = [];
|
||||
if (other) cm.push(other.orig);
|
||||
for (var i = 0; i < cm.length; i++)
|
||||
scroll.push(cm[i].getScrollInfo().top);
|
||||
|
||||
for (var ln = 0; ln < linesToAlign.length; ln++)
|
||||
alignLines(cm, linesToAlign[ln], aligners);
|
||||
|
||||
for (var i = 0; i < cm.length; i++)
|
||||
cm[i].scrollTo(null, scroll[i]);
|
||||
}
|
||||
|
||||
function alignLines(cm, lines, aligners) {
|
||||
var maxOffset = 0, offset = [];
|
||||
for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
|
||||
var off = cm[i].heightAtLine(lines[i], "local");
|
||||
offset[i] = off;
|
||||
maxOffset = Math.max(maxOffset, off);
|
||||
}
|
||||
for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
|
||||
var diff = maxOffset - offset[i];
|
||||
if (diff > 1)
|
||||
aligners.push(padAbove(cm[i], lines[i], diff));
|
||||
}
|
||||
}
|
||||
|
||||
function padAbove(cm, line, size) {
|
||||
var above = true;
|
||||
if (line > cm.lastLine()) {
|
||||
line--;
|
||||
above = false;
|
||||
}
|
||||
var elt = document.createElement("div");
|
||||
elt.className = "CodeMirror-merge-spacer";
|
||||
elt.style.height = size + "px"; elt.style.minWidth = "1px";
|
||||
return cm.addLineWidget(line, elt, {height: size, above: above});
|
||||
}
|
||||
|
||||
function drawConnectorsForChunk(dv, chunk, sTopOrig, sTopEdit, w) {
|
||||
var flip = dv.type == "left";
|
||||
var top = dv.orig.heightAtLine(chunk.origFrom, "local") - sTopOrig;
|
||||
if (dv.svg) {
|
||||
var topLpx = top;
|
||||
var topRpx = dv.edit.heightAtLine(chunk.editFrom, "local") - sTopEdit;
|
||||
if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
|
||||
var botLpx = dv.orig.heightAtLine(chunk.origTo, "local") - sTopOrig;
|
||||
var botRpx = dv.edit.heightAtLine(chunk.editTo, "local") - sTopEdit;
|
||||
if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
|
||||
var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
|
||||
var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
|
||||
attrs(dv.svg.appendChild(document.createElementNS(svgNS, "path")),
|
||||
"d", "M -1 " + topRpx + curveTop + " L " + (w + 2) + " " + botLpx + curveBot + " z",
|
||||
"class", dv.classes.connect);
|
||||
}
|
||||
if (dv.copyButtons) {
|
||||
var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\u21dd" : "\u21dc",
|
||||
"CodeMirror-merge-copy"));
|
||||
var editOriginals = dv.mv.options.allowEditingOriginals;
|
||||
copy.title = editOriginals ? "Push to left" : "Revert chunk";
|
||||
copy.chunk = chunk;
|
||||
copy.style.top = top + "px";
|
||||
|
||||
if (editOriginals) {
|
||||
var topReverse = dv.orig.heightAtLine(chunk.editFrom, "local") - sTopEdit;
|
||||
var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc",
|
||||
"CodeMirror-merge-copy-reverse"));
|
||||
copyReverse.title = "Push to right";
|
||||
copyReverse.chunk = {editFrom: chunk.origFrom, editTo: chunk.origTo,
|
||||
origFrom: chunk.editFrom, origTo: chunk.editTo};
|
||||
copyReverse.style.top = topReverse + "px";
|
||||
dv.type == "right" ? copyReverse.style.left = "2px" : copyReverse.style.right = "2px";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function copyChunk(dv, to, from, chunk) {
|
||||
if (dv.diffOutOfDate) return;
|
||||
to.replaceRange(from.getRange(Pos(chunk.origFrom, 0), Pos(chunk.origTo, 0)),
|
||||
Pos(chunk.editFrom, 0), Pos(chunk.editTo, 0));
|
||||
}
|
||||
|
||||
// Merge view, containing 0, 1, or 2 diff views.
|
||||
|
||||
var MergeView = CodeMirror.MergeView = function(node, options) {
|
||||
if (!(this instanceof MergeView)) return new MergeView(node, options);
|
||||
|
||||
this.options = options;
|
||||
var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight;
|
||||
|
||||
var hasLeft = origLeft != null, hasRight = origRight != null;
|
||||
var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0);
|
||||
var wrap = [], left = this.left = null, right = this.right = null;
|
||||
var self = this;
|
||||
|
||||
if (hasLeft) {
|
||||
left = this.left = new DiffView(this, "left");
|
||||
var leftPane = elt("div", null, "CodeMirror-merge-pane");
|
||||
wrap.push(leftPane);
|
||||
wrap.push(buildGap(left));
|
||||
}
|
||||
|
||||
var editPane = elt("div", null, "CodeMirror-merge-pane");
|
||||
wrap.push(editPane);
|
||||
|
||||
if (hasRight) {
|
||||
right = this.right = new DiffView(this, "right");
|
||||
wrap.push(buildGap(right));
|
||||
var rightPane = elt("div", null, "CodeMirror-merge-pane");
|
||||
wrap.push(rightPane);
|
||||
}
|
||||
|
||||
(hasRight ? rightPane : editPane).className += " CodeMirror-merge-pane-rightmost";
|
||||
|
||||
wrap.push(elt("div", null, null, "height: 0; clear: both;"));
|
||||
|
||||
var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-merge CodeMirror-merge-" + panes + "pane"));
|
||||
this.edit = CodeMirror(editPane, copyObj(options));
|
||||
|
||||
if (left) left.init(leftPane, origLeft, options);
|
||||
if (right) right.init(rightPane, origRight, options);
|
||||
|
||||
if (options.collapseIdentical) {
|
||||
updating = true;
|
||||
this.editor().operation(function() {
|
||||
collapseIdenticalStretches(self, options.collapseIdentical);
|
||||
});
|
||||
updating = false;
|
||||
}
|
||||
if (options.connect == "align") {
|
||||
this.aligners = [];
|
||||
alignChunks(this.left || this.right, true);
|
||||
}
|
||||
|
||||
var onResize = function() {
|
||||
if (left) makeConnections(left);
|
||||
if (right) makeConnections(right);
|
||||
};
|
||||
CodeMirror.on(window, "resize", onResize);
|
||||
var resizeInterval = setInterval(function() {
|
||||
for (var p = wrapElt.parentNode; p && p != document.body; p = p.parentNode) {}
|
||||
if (!p) { clearInterval(resizeInterval); CodeMirror.off(window, "resize", onResize); }
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
function buildGap(dv) {
|
||||
var lock = dv.lockButton = elt("div", null, "CodeMirror-merge-scrolllock");
|
||||
lock.title = "Toggle locked scrolling";
|
||||
var lockWrap = elt("div", [lock], "CodeMirror-merge-scrolllock-wrap");
|
||||
CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); });
|
||||
var gapElts = [lockWrap];
|
||||
if (dv.mv.options.revertButtons !== false) {
|
||||
dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type);
|
||||
CodeMirror.on(dv.copyButtons, "click", function(e) {
|
||||
var node = e.target || e.srcElement;
|
||||
if (!node.chunk) return;
|
||||
if (node.className == "CodeMirror-merge-copy-reverse") {
|
||||
copyChunk(dv, dv.orig, dv.edit, node.chunk);
|
||||
return;
|
||||
}
|
||||
copyChunk(dv, dv.edit, dv.orig, node.chunk);
|
||||
});
|
||||
gapElts.unshift(dv.copyButtons);
|
||||
}
|
||||
if (dv.mv.options.connect != "align") {
|
||||
var svg = document.createElementNS && document.createElementNS(svgNS, "svg");
|
||||
if (svg && !svg.createSVGRect) svg = null;
|
||||
dv.svg = svg;
|
||||
if (svg) gapElts.push(svg);
|
||||
}
|
||||
|
||||
return dv.gap = elt("div", gapElts, "CodeMirror-merge-gap");
|
||||
}
|
||||
|
||||
MergeView.prototype = {
|
||||
constuctor: MergeView,
|
||||
editor: function() { return this.edit; },
|
||||
rightOriginal: function() { return this.right && this.right.orig; },
|
||||
leftOriginal: function() { return this.left && this.left.orig; },
|
||||
setShowDifferences: function(val) {
|
||||
if (this.right) this.right.setShowDifferences(val);
|
||||
if (this.left) this.left.setShowDifferences(val);
|
||||
},
|
||||
rightChunks: function() {
|
||||
if (this.right) { ensureDiff(this.right); return this.right.chunks; }
|
||||
},
|
||||
leftChunks: function() {
|
||||
if (this.left) { ensureDiff(this.left); return this.left.chunks; }
|
||||
}
|
||||
};
|
||||
|
||||
function asString(obj) {
|
||||
if (typeof obj == "string") return obj;
|
||||
else return obj.getValue();
|
||||
}
|
||||
|
||||
// Operations on diffs
|
||||
|
||||
var dmp = new diff_match_patch();
|
||||
function getDiff(a, b) {
|
||||
var diff = dmp.diff_main(a, b);
|
||||
dmp.diff_cleanupSemantic(diff);
|
||||
// The library sometimes leaves in empty parts, which confuse the algorithm
|
||||
for (var i = 0; i < diff.length; ++i) {
|
||||
var part = diff[i];
|
||||
if (!part[1]) {
|
||||
diff.splice(i--, 1);
|
||||
} else if (i && diff[i - 1][0] == part[0]) {
|
||||
diff.splice(i--, 1);
|
||||
diff[i][1] += part[1];
|
||||
}
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
function getChunks(diff) {
|
||||
var chunks = [];
|
||||
var startEdit = 0, startOrig = 0;
|
||||
var edit = Pos(0, 0), orig = Pos(0, 0);
|
||||
for (var i = 0; i < diff.length; ++i) {
|
||||
var part = diff[i], tp = part[0];
|
||||
if (tp == DIFF_EQUAL) {
|
||||
var startOff = startOfLineClean(diff, i) ? 0 : 1;
|
||||
var cleanFromEdit = edit.line + startOff, cleanFromOrig = orig.line + startOff;
|
||||
moveOver(edit, part[1], null, orig);
|
||||
var endOff = endOfLineClean(diff, i) ? 1 : 0;
|
||||
var cleanToEdit = edit.line + endOff, cleanToOrig = orig.line + endOff;
|
||||
if (cleanToEdit > cleanFromEdit) {
|
||||
if (i) chunks.push({origFrom: startOrig, origTo: cleanFromOrig,
|
||||
editFrom: startEdit, editTo: cleanFromEdit});
|
||||
startEdit = cleanToEdit; startOrig = cleanToOrig;
|
||||
}
|
||||
} else {
|
||||
moveOver(tp == DIFF_INSERT ? edit : orig, part[1]);
|
||||
}
|
||||
}
|
||||
if (startEdit <= edit.line || startOrig <= orig.line)
|
||||
chunks.push({origFrom: startOrig, origTo: orig.line + 1,
|
||||
editFrom: startEdit, editTo: edit.line + 1});
|
||||
return chunks;
|
||||
}
|
||||
|
||||
function endOfLineClean(diff, i) {
|
||||
if (i == diff.length - 1) return true;
|
||||
var next = diff[i + 1][1];
|
||||
if (next.length == 1 || next.charCodeAt(0) != 10) return false;
|
||||
if (i == diff.length - 2) return true;
|
||||
next = diff[i + 2][1];
|
||||
return next.length > 1 && next.charCodeAt(0) == 10;
|
||||
}
|
||||
|
||||
function startOfLineClean(diff, i) {
|
||||
if (i == 0) return true;
|
||||
var last = diff[i - 1][1];
|
||||
if (last.charCodeAt(last.length - 1) != 10) return false;
|
||||
if (i == 1) return true;
|
||||
last = diff[i - 2][1];
|
||||
return last.charCodeAt(last.length - 1) == 10;
|
||||
}
|
||||
|
||||
function chunkBoundariesAround(chunks, n, nInEdit) {
|
||||
var beforeE, afterE, beforeO, afterO;
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
var chunk = chunks[i];
|
||||
var fromLocal = nInEdit ? chunk.editFrom : chunk.origFrom;
|
||||
var toLocal = nInEdit ? chunk.editTo : chunk.origTo;
|
||||
if (afterE == null) {
|
||||
if (fromLocal > n) { afterE = chunk.editFrom; afterO = chunk.origFrom; }
|
||||
else if (toLocal > n) { afterE = chunk.editTo; afterO = chunk.origTo; }
|
||||
}
|
||||
if (toLocal <= n) { beforeE = chunk.editTo; beforeO = chunk.origTo; }
|
||||
else if (fromLocal <= n) { beforeE = chunk.editFrom; beforeO = chunk.origFrom; }
|
||||
}
|
||||
return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};
|
||||
}
|
||||
|
||||
function collapseSingle(cm, from, to) {
|
||||
cm.addLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
|
||||
var widget = document.createElement("span");
|
||||
widget.className = "CodeMirror-merge-collapsed-widget";
|
||||
widget.title = "Identical text collapsed. Click to expand.";
|
||||
var mark = cm.markText(Pos(from, 0), Pos(to - 1), {
|
||||
inclusiveLeft: true,
|
||||
inclusiveRight: true,
|
||||
replacedWith: widget,
|
||||
clearOnEnter: true
|
||||
});
|
||||
function clear() {
|
||||
mark.clear();
|
||||
cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
|
||||
}
|
||||
widget.addEventListener("click", clear);
|
||||
return {mark: mark, clear: clear};
|
||||
}
|
||||
|
||||
function collapseStretch(size, editors) {
|
||||
var marks = [];
|
||||
function clear() {
|
||||
for (var i = 0; i < marks.length; i++) marks[i].clear();
|
||||
}
|
||||
for (var i = 0; i < editors.length; i++) {
|
||||
var editor = editors[i];
|
||||
var mark = collapseSingle(editor.cm, editor.line, editor.line + size);
|
||||
marks.push(mark);
|
||||
mark.mark.on("clear", clear);
|
||||
}
|
||||
return marks[0].mark;
|
||||
}
|
||||
|
||||
function unclearNearChunks(dv, margin, off, clear) {
|
||||
for (var i = 0; i < dv.chunks.length; i++) {
|
||||
var chunk = dv.chunks[i];
|
||||
for (var l = chunk.editFrom - margin; l < chunk.editTo + margin; l++) {
|
||||
var pos = l + off;
|
||||
if (pos >= 0 && pos < clear.length) clear[pos] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function collapseIdenticalStretches(mv, margin) {
|
||||
if (typeof margin != "number") margin = 2;
|
||||
var clear = [], edit = mv.editor(), off = edit.firstLine();
|
||||
for (var l = off, e = edit.lastLine(); l <= e; l++) clear.push(true);
|
||||
if (mv.left) unclearNearChunks(mv.left, margin, off, clear);
|
||||
if (mv.right) unclearNearChunks(mv.right, margin, off, clear);
|
||||
|
||||
for (var i = 0; i < clear.length; i++) {
|
||||
if (clear[i]) {
|
||||
var line = i + off;
|
||||
for (var size = 1; i < clear.length - 1 && clear[i + 1]; i++, size++) {}
|
||||
if (size > margin) {
|
||||
var editors = [{line: line, cm: edit}];
|
||||
if (mv.left) editors.push({line: getMatchingOrigLine(line, mv.left.chunks), cm: mv.left.orig});
|
||||
if (mv.right) editors.push({line: getMatchingOrigLine(line, mv.right.chunks), cm: mv.right.orig});
|
||||
var mark = collapseStretch(size, editors);
|
||||
if (mv.options.onCollapse) mv.options.onCollapse(mv, line, size, mark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// General utilities
|
||||
|
||||
function elt(tag, content, className, style) {
|
||||
var e = document.createElement(tag);
|
||||
if (className) e.className = className;
|
||||
if (style) e.style.cssText = style;
|
||||
if (typeof content == "string") e.appendChild(document.createTextNode(content));
|
||||
else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
|
||||
return e;
|
||||
}
|
||||
|
||||
function clear(node) {
|
||||
for (var count = node.childNodes.length; count > 0; --count)
|
||||
node.removeChild(node.firstChild);
|
||||
}
|
||||
|
||||
function attrs(elt) {
|
||||
for (var i = 1; i < arguments.length; i += 2)
|
||||
elt.setAttribute(arguments[i], arguments[i+1]);
|
||||
}
|
||||
|
||||
function copyObj(obj, target) {
|
||||
if (!target) target = {};
|
||||
for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
|
||||
return target;
|
||||
}
|
||||
|
||||
function moveOver(pos, str, copy, other) {
|
||||
var out = copy ? Pos(pos.line, pos.ch) : pos, at = 0;
|
||||
for (;;) {
|
||||
var nl = str.indexOf("\n", at);
|
||||
if (nl == -1) break;
|
||||
++out.line;
|
||||
if (other) ++other.line;
|
||||
at = nl + 1;
|
||||
}
|
||||
out.ch = (at ? 0 : out.ch) + (str.length - at);
|
||||
if (other) other.ch = (at ? 0 : other.ch) + (str.length - at);
|
||||
return out;
|
||||
}
|
||||
|
||||
function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }
|
||||
function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }
|
||||
function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
|
||||
});
|
||||
@@ -1,64 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"), "cjs");
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], function(CM) { mod(CM, "amd"); });
|
||||
else // Plain browser env
|
||||
mod(CodeMirror, "plain");
|
||||
})(function(CodeMirror, env) {
|
||||
if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
|
||||
|
||||
var loading = {};
|
||||
function splitCallback(cont, n) {
|
||||
var countDown = n;
|
||||
return function() { if (--countDown == 0) cont(); };
|
||||
}
|
||||
function ensureDeps(mode, cont) {
|
||||
var deps = CodeMirror.modes[mode].dependencies;
|
||||
if (!deps) return cont();
|
||||
var missing = [];
|
||||
for (var i = 0; i < deps.length; ++i) {
|
||||
if (!CodeMirror.modes.hasOwnProperty(deps[i]))
|
||||
missing.push(deps[i]);
|
||||
}
|
||||
if (!missing.length) return cont();
|
||||
var split = splitCallback(cont, missing.length);
|
||||
for (var i = 0; i < missing.length; ++i)
|
||||
CodeMirror.requireMode(missing[i], split);
|
||||
}
|
||||
|
||||
CodeMirror.requireMode = function(mode, cont) {
|
||||
if (typeof mode != "string") mode = mode.name;
|
||||
if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
|
||||
if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
|
||||
|
||||
var file = CodeMirror.modeURL.replace(/%N/g, mode);
|
||||
if (env == "plain") {
|
||||
var script = document.createElement("script");
|
||||
script.src = file;
|
||||
var others = document.getElementsByTagName("script")[0];
|
||||
var list = loading[mode] = [cont];
|
||||
CodeMirror.on(script, "load", function() {
|
||||
ensureDeps(mode, function() {
|
||||
for (var i = 0; i < list.length; ++i) list[i]();
|
||||
});
|
||||
});
|
||||
others.parentNode.insertBefore(script, others);
|
||||
} else if (env == "cjs") {
|
||||
require(file);
|
||||
cont();
|
||||
} else if (env == "amd") {
|
||||
requirejs([file], cont);
|
||||
}
|
||||
};
|
||||
|
||||
CodeMirror.autoLoadMode = function(instance, mode) {
|
||||
if (!CodeMirror.modes.hasOwnProperty(mode))
|
||||
CodeMirror.requireMode(mode, function() {
|
||||
instance.setOption("mode", instance.getOption("mode"));
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -1,118 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.multiplexingMode = function(outer /*, others */) {
|
||||
// Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
|
||||
var others = Array.prototype.slice.call(arguments, 1);
|
||||
var n_others = others.length;
|
||||
|
||||
function indexOf(string, pattern, from) {
|
||||
if (typeof pattern == "string") return string.indexOf(pattern, from);
|
||||
var m = pattern.exec(from ? string.slice(from) : string);
|
||||
return m ? m.index + from : -1;
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
outer: CodeMirror.startState(outer),
|
||||
innerActive: null,
|
||||
inner: null
|
||||
};
|
||||
},
|
||||
|
||||
copyState: function(state) {
|
||||
return {
|
||||
outer: CodeMirror.copyState(outer, state.outer),
|
||||
innerActive: state.innerActive,
|
||||
inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner)
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (!state.innerActive) {
|
||||
var cutOff = Infinity, oldContent = stream.string;
|
||||
for (var i = 0; i < n_others; ++i) {
|
||||
var other = others[i];
|
||||
var found = indexOf(oldContent, other.open, stream.pos);
|
||||
if (found == stream.pos) {
|
||||
stream.match(other.open);
|
||||
state.innerActive = other;
|
||||
state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
|
||||
return other.delimStyle;
|
||||
} else if (found != -1 && found < cutOff) {
|
||||
cutOff = found;
|
||||
}
|
||||
}
|
||||
if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
|
||||
var outerToken = outer.token(stream, state.outer);
|
||||
if (cutOff != Infinity) stream.string = oldContent;
|
||||
return outerToken;
|
||||
} else {
|
||||
var curInner = state.innerActive, oldContent = stream.string;
|
||||
if (!curInner.close && stream.sol()) {
|
||||
state.innerActive = state.inner = null;
|
||||
return this.token(stream, state);
|
||||
}
|
||||
var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos) : -1;
|
||||
if (found == stream.pos) {
|
||||
stream.match(curInner.close);
|
||||
state.innerActive = state.inner = null;
|
||||
return curInner.delimStyle;
|
||||
}
|
||||
if (found > -1) stream.string = oldContent.slice(0, found);
|
||||
var innerToken = curInner.mode.token(stream, state.inner);
|
||||
if (found > -1) stream.string = oldContent;
|
||||
|
||||
if (curInner.innerStyle) {
|
||||
if (innerToken) innerToken = innerToken + ' ' + curInner.innerStyle;
|
||||
else innerToken = curInner.innerStyle;
|
||||
}
|
||||
|
||||
return innerToken;
|
||||
}
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
var mode = state.innerActive ? state.innerActive.mode : outer;
|
||||
if (!mode.indent) return CodeMirror.Pass;
|
||||
return mode.indent(state.innerActive ? state.inner : state.outer, textAfter);
|
||||
},
|
||||
|
||||
blankLine: function(state) {
|
||||
var mode = state.innerActive ? state.innerActive.mode : outer;
|
||||
if (mode.blankLine) {
|
||||
mode.blankLine(state.innerActive ? state.inner : state.outer);
|
||||
}
|
||||
if (!state.innerActive) {
|
||||
for (var i = 0; i < n_others; ++i) {
|
||||
var other = others[i];
|
||||
if (other.open === "\n") {
|
||||
state.innerActive = other;
|
||||
state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "") : 0);
|
||||
}
|
||||
}
|
||||
} else if (state.innerActive.close === "\n") {
|
||||
state.innerActive = state.inner = null;
|
||||
}
|
||||
},
|
||||
|
||||
electricChars: outer.electricChars,
|
||||
|
||||
innerMode: function(state) {
|
||||
return state.inner ? {state: state.inner, mode: state.innerActive.mode} : {state: state.outer, mode: outer};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
});
|
||||
@@ -1,33 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
CodeMirror.defineMode("markdown_with_stex", function(){
|
||||
var inner = CodeMirror.getMode({}, "stex");
|
||||
var outer = CodeMirror.getMode({}, "markdown");
|
||||
|
||||
var innerOptions = {
|
||||
open: '$',
|
||||
close: '$',
|
||||
mode: inner,
|
||||
delimStyle: 'delim',
|
||||
innerStyle: 'inner'
|
||||
};
|
||||
|
||||
return CodeMirror.multiplexingMode(outer, innerOptions);
|
||||
});
|
||||
|
||||
var mode = CodeMirror.getMode({}, "markdown_with_stex");
|
||||
|
||||
function MT(name) {
|
||||
test.mode(
|
||||
name,
|
||||
mode,
|
||||
Array.prototype.slice.call(arguments, 1),
|
||||
'multiplexing');
|
||||
}
|
||||
|
||||
MT(
|
||||
"stexInsideMarkdown",
|
||||
"[strong **Equation:**] [delim $][inner&tag \\pi][delim $]");
|
||||
})();
|
||||
@@ -1,85 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
// Utility function that allows modes to be combined. The mode given
|
||||
// as the base argument takes care of most of the normal mode
|
||||
// functionality, but a second (typically simple) mode is used, which
|
||||
// can override the style of text. Both modes get to parse all of the
|
||||
// text, but when both assign a non-null style to a piece of code, the
|
||||
// overlay wins, unless the combine argument was true and not overridden,
|
||||
// or state.overlay.combineTokens was true, in which case the styles are
|
||||
// combined.
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.overlayMode = function(base, overlay, combine) {
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
base: CodeMirror.startState(base),
|
||||
overlay: CodeMirror.startState(overlay),
|
||||
basePos: 0, baseCur: null,
|
||||
overlayPos: 0, overlayCur: null,
|
||||
streamSeen: null
|
||||
};
|
||||
},
|
||||
copyState: function(state) {
|
||||
return {
|
||||
base: CodeMirror.copyState(base, state.base),
|
||||
overlay: CodeMirror.copyState(overlay, state.overlay),
|
||||
basePos: state.basePos, baseCur: null,
|
||||
overlayPos: state.overlayPos, overlayCur: null
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (stream != state.streamSeen ||
|
||||
Math.min(state.basePos, state.overlayPos) < stream.start) {
|
||||
state.streamSeen = stream;
|
||||
state.basePos = state.overlayPos = stream.start;
|
||||
}
|
||||
|
||||
if (stream.start == state.basePos) {
|
||||
state.baseCur = base.token(stream, state.base);
|
||||
state.basePos = stream.pos;
|
||||
}
|
||||
if (stream.start == state.overlayPos) {
|
||||
stream.pos = stream.start;
|
||||
state.overlayCur = overlay.token(stream, state.overlay);
|
||||
state.overlayPos = stream.pos;
|
||||
}
|
||||
stream.pos = Math.min(state.basePos, state.overlayPos);
|
||||
|
||||
// state.overlay.combineTokens always takes precedence over combine,
|
||||
// unless set to null
|
||||
if (state.overlayCur == null) return state.baseCur;
|
||||
else if (state.baseCur != null &&
|
||||
state.overlay.combineTokens ||
|
||||
combine && state.overlay.combineTokens == null)
|
||||
return state.baseCur + " " + state.overlayCur;
|
||||
else return state.overlayCur;
|
||||
},
|
||||
|
||||
indent: base.indent && function(state, textAfter) {
|
||||
return base.indent(state.base, textAfter);
|
||||
},
|
||||
electricChars: base.electricChars,
|
||||
|
||||
innerMode: function(state) { return {state: state.base, mode: base}; },
|
||||
|
||||
blankLine: function(state) {
|
||||
if (base.blankLine) base.blankLine(state.base);
|
||||
if (overlay.blankLine) overlay.blankLine(state.overlay);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
});
|
||||
@@ -1,213 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineSimpleMode = function(name, states) {
|
||||
CodeMirror.defineMode(name, function(config) {
|
||||
return CodeMirror.simpleMode(config, states);
|
||||
});
|
||||
};
|
||||
|
||||
CodeMirror.simpleMode = function(config, states) {
|
||||
ensureState(states, "start");
|
||||
var states_ = {}, meta = states.meta || {}, hasIndentation = false;
|
||||
for (var state in states) if (state != meta && states.hasOwnProperty(state)) {
|
||||
var list = states_[state] = [], orig = states[state];
|
||||
for (var i = 0; i < orig.length; i++) {
|
||||
var data = orig[i];
|
||||
list.push(new Rule(data, states));
|
||||
if (data.indent || data.dedent) hasIndentation = true;
|
||||
}
|
||||
}
|
||||
var mode = {
|
||||
startState: function() {
|
||||
return {state: "start", pending: null,
|
||||
local: null, localState: null,
|
||||
indent: hasIndentation ? [] : null};
|
||||
},
|
||||
copyState: function(state) {
|
||||
var s = {state: state.state, pending: state.pending,
|
||||
local: state.local, localState: null,
|
||||
indent: state.indent && state.indent.slice(0)};
|
||||
if (state.localState)
|
||||
s.localState = CodeMirror.copyState(state.local.mode, state.localState);
|
||||
if (state.stack)
|
||||
s.stack = state.stack.slice(0);
|
||||
for (var pers = state.persistentStates; pers; pers = pers.next)
|
||||
s.persistentStates = {mode: pers.mode,
|
||||
spec: pers.spec,
|
||||
state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state),
|
||||
next: s.persistentStates};
|
||||
return s;
|
||||
},
|
||||
token: tokenFunction(states_, config),
|
||||
innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; },
|
||||
indent: indentFunction(states_, meta)
|
||||
};
|
||||
if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop))
|
||||
mode[prop] = meta[prop];
|
||||
return mode;
|
||||
};
|
||||
|
||||
function ensureState(states, name) {
|
||||
if (!states.hasOwnProperty(name))
|
||||
throw new Error("Undefined state " + name + "in simple mode");
|
||||
}
|
||||
|
||||
function toRegex(val, caret) {
|
||||
if (!val) return /(?:)/;
|
||||
var flags = "";
|
||||
if (val instanceof RegExp) {
|
||||
if (val.ignoreCase) flags = "i";
|
||||
val = val.source;
|
||||
} else {
|
||||
val = String(val);
|
||||
}
|
||||
return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags);
|
||||
}
|
||||
|
||||
function asToken(val) {
|
||||
if (!val) return null;
|
||||
if (typeof val == "string") return val.replace(/\./g, " ");
|
||||
var result = [];
|
||||
for (var i = 0; i < val.length; i++)
|
||||
result.push(val[i] && val[i].replace(/\./g, " "));
|
||||
return result;
|
||||
}
|
||||
|
||||
function Rule(data, states) {
|
||||
if (data.next || data.push) ensureState(states, data.next || data.push);
|
||||
this.regex = toRegex(data.regex);
|
||||
this.token = asToken(data.token);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
function tokenFunction(states, config) {
|
||||
return function(stream, state) {
|
||||
if (state.pending) {
|
||||
var pend = state.pending.shift();
|
||||
if (state.pending.length == 0) state.pending = null;
|
||||
stream.pos += pend.text.length;
|
||||
return pend.token;
|
||||
}
|
||||
|
||||
if (state.local) {
|
||||
if (state.local.end && stream.match(state.local.end)) {
|
||||
var tok = state.local.endToken || null;
|
||||
state.local = state.localState = null;
|
||||
return tok;
|
||||
} else {
|
||||
var tok = state.local.mode.token(stream, state.localState), m;
|
||||
if (state.local.endScan && (m = state.local.endScan.exec(stream.current())))
|
||||
stream.pos = stream.start + m.index;
|
||||
return tok;
|
||||
}
|
||||
}
|
||||
|
||||
var curState = states[state.state];
|
||||
for (var i = 0; i < curState.length; i++) {
|
||||
var rule = curState[i];
|
||||
var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex);
|
||||
if (matches) {
|
||||
if (rule.data.next) {
|
||||
state.state = rule.data.next;
|
||||
} else if (rule.data.push) {
|
||||
(state.stack || (state.stack = [])).push(state.state);
|
||||
state.state = rule.data.push;
|
||||
} else if (rule.data.pop && state.stack && state.stack.length) {
|
||||
state.state = state.stack.pop();
|
||||
}
|
||||
|
||||
if (rule.data.mode)
|
||||
enterLocalMode(config, state, rule.data.mode, rule.token);
|
||||
if (rule.data.indent)
|
||||
state.indent.push(stream.indentation() + config.indentUnit);
|
||||
if (rule.data.dedent)
|
||||
state.indent.pop();
|
||||
if (matches.length > 2) {
|
||||
state.pending = [];
|
||||
for (var j = 2; j < matches.length; j++)
|
||||
if (matches[j])
|
||||
state.pending.push({text: matches[j], token: rule.token[j - 1]});
|
||||
stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));
|
||||
return rule.token[0];
|
||||
} else if (rule.token && rule.token.join) {
|
||||
return rule.token[0];
|
||||
} else {
|
||||
return rule.token;
|
||||
}
|
||||
}
|
||||
}
|
||||
stream.next();
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
function cmp(a, b) {
|
||||
if (a === b) return true;
|
||||
if (!a || typeof a != "object" || !b || typeof b != "object") return false;
|
||||
var props = 0;
|
||||
for (var prop in a) if (a.hasOwnProperty(prop)) {
|
||||
if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false;
|
||||
props++;
|
||||
}
|
||||
for (var prop in b) if (b.hasOwnProperty(prop)) props--;
|
||||
return props == 0;
|
||||
}
|
||||
|
||||
function enterLocalMode(config, state, spec, token) {
|
||||
var pers;
|
||||
if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next)
|
||||
if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p;
|
||||
var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec);
|
||||
var lState = pers ? pers.state : CodeMirror.startState(mode);
|
||||
if (spec.persistent && !pers)
|
||||
state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates};
|
||||
|
||||
state.localState = lState;
|
||||
state.local = {mode: mode,
|
||||
end: spec.end && toRegex(spec.end),
|
||||
endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false),
|
||||
endToken: token && token.join ? token[token.length - 1] : token};
|
||||
}
|
||||
|
||||
function indexOf(val, arr) {
|
||||
for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true;
|
||||
}
|
||||
|
||||
function indentFunction(states, meta) {
|
||||
return function(state, textAfter, line) {
|
||||
if (state.local && state.local.mode.indent)
|
||||
return state.local.mode.indent(state.localState, textAfter, line);
|
||||
if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1)
|
||||
return CodeMirror.Pass;
|
||||
|
||||
var pos = state.indent.length - 1, rules = states[state.state];
|
||||
scan: for (;;) {
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
var rule = rules[i];
|
||||
if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {
|
||||
var m = rule.regex.exec(textAfter);
|
||||
if (m && m[0]) {
|
||||
pos--;
|
||||
if (rule.next || rule.push) rules = states[rule.next || rule.push];
|
||||
textAfter = textAfter.slice(m[0].length);
|
||||
continue scan;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return pos < 0 ? 0 : state.indent[pos];
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -1,40 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"), require("./runmode"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror", "./runmode"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
var isBlock = /^(p|li|div|h\\d|pre|blockquote|td)$/;
|
||||
|
||||
function textContent(node, out) {
|
||||
if (node.nodeType == 3) return out.push(node.nodeValue);
|
||||
for (var ch = node.firstChild; ch; ch = ch.nextSibling) {
|
||||
textContent(ch, out);
|
||||
if (isBlock.test(node.nodeType)) out.push("\n");
|
||||
}
|
||||
}
|
||||
|
||||
CodeMirror.colorize = function(collection, defaultMode) {
|
||||
if (!collection) collection = document.body.getElementsByTagName("pre");
|
||||
|
||||
for (var i = 0; i < collection.length; ++i) {
|
||||
var node = collection[i];
|
||||
var mode = node.getAttribute("data-lang") || defaultMode;
|
||||
if (!mode) continue;
|
||||
|
||||
var text = [];
|
||||
textContent(node, text);
|
||||
node.innerHTML = "";
|
||||
CodeMirror.runMode(text.join(""), mode, node);
|
||||
|
||||
node.className += " cm-s-default";
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,157 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
window.CodeMirror = {};
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
function splitLines(string){ return string.split(/\r?\n|\r/); };
|
||||
|
||||
function StringStream(string) {
|
||||
this.pos = this.start = 0;
|
||||
this.string = string;
|
||||
this.lineStart = 0;
|
||||
}
|
||||
StringStream.prototype = {
|
||||
eol: function() {return this.pos >= this.string.length;},
|
||||
sol: function() {return this.pos == 0;},
|
||||
peek: function() {return this.string.charAt(this.pos) || null;},
|
||||
next: function() {
|
||||
if (this.pos < this.string.length)
|
||||
return this.string.charAt(this.pos++);
|
||||
},
|
||||
eat: function(match) {
|
||||
var ch = this.string.charAt(this.pos);
|
||||
if (typeof match == "string") var ok = ch == match;
|
||||
else var ok = ch && (match.test ? match.test(ch) : match(ch));
|
||||
if (ok) {++this.pos; return ch;}
|
||||
},
|
||||
eatWhile: function(match) {
|
||||
var start = this.pos;
|
||||
while (this.eat(match)){}
|
||||
return this.pos > start;
|
||||
},
|
||||
eatSpace: function() {
|
||||
var start = this.pos;
|
||||
while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
|
||||
return this.pos > start;
|
||||
},
|
||||
skipToEnd: function() {this.pos = this.string.length;},
|
||||
skipTo: function(ch) {
|
||||
var found = this.string.indexOf(ch, this.pos);
|
||||
if (found > -1) {this.pos = found; return true;}
|
||||
},
|
||||
backUp: function(n) {this.pos -= n;},
|
||||
column: function() {return this.start - this.lineStart;},
|
||||
indentation: function() {return 0;},
|
||||
match: function(pattern, consume, caseInsensitive) {
|
||||
if (typeof pattern == "string") {
|
||||
var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
|
||||
var substr = this.string.substr(this.pos, pattern.length);
|
||||
if (cased(substr) == cased(pattern)) {
|
||||
if (consume !== false) this.pos += pattern.length;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
var match = this.string.slice(this.pos).match(pattern);
|
||||
if (match && match.index > 0) return null;
|
||||
if (match && consume !== false) this.pos += match[0].length;
|
||||
return match;
|
||||
}
|
||||
},
|
||||
current: function(){return this.string.slice(this.start, this.pos);},
|
||||
hideFirstChars: function(n, inner) {
|
||||
this.lineStart += n;
|
||||
try { return inner(); }
|
||||
finally { this.lineStart -= n; }
|
||||
}
|
||||
};
|
||||
CodeMirror.StringStream = StringStream;
|
||||
|
||||
CodeMirror.startState = function (mode, a1, a2) {
|
||||
return mode.startState ? mode.startState(a1, a2) : true;
|
||||
};
|
||||
|
||||
var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
|
||||
CodeMirror.defineMode = function (name, mode) {
|
||||
if (arguments.length > 2)
|
||||
mode.dependencies = Array.prototype.slice.call(arguments, 2);
|
||||
modes[name] = mode;
|
||||
};
|
||||
CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; };
|
||||
CodeMirror.resolveMode = function(spec) {
|
||||
if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
|
||||
spec = mimeModes[spec];
|
||||
} else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
|
||||
spec = mimeModes[spec.name];
|
||||
}
|
||||
if (typeof spec == "string") return {name: spec};
|
||||
else return spec || {name: "null"};
|
||||
};
|
||||
CodeMirror.getMode = function (options, spec) {
|
||||
spec = CodeMirror.resolveMode(spec);
|
||||
var mfactory = modes[spec.name];
|
||||
if (!mfactory) throw new Error("Unknown mode: " + spec);
|
||||
return mfactory(options, spec);
|
||||
};
|
||||
CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min;
|
||||
CodeMirror.defineMode("null", function() {
|
||||
return {token: function(stream) {stream.skipToEnd();}};
|
||||
});
|
||||
CodeMirror.defineMIME("text/plain", "null");
|
||||
|
||||
CodeMirror.runMode = function (string, modespec, callback, options) {
|
||||
var mode = CodeMirror.getMode({ indentUnit: 2 }, modespec);
|
||||
|
||||
if (callback.nodeType == 1) {
|
||||
var tabSize = (options && options.tabSize) || 4;
|
||||
var node = callback, col = 0;
|
||||
node.innerHTML = "";
|
||||
callback = function (text, style) {
|
||||
if (text == "\n") {
|
||||
node.appendChild(document.createElement("br"));
|
||||
col = 0;
|
||||
return;
|
||||
}
|
||||
var content = "";
|
||||
// replace tabs
|
||||
for (var pos = 0; ;) {
|
||||
var idx = text.indexOf("\t", pos);
|
||||
if (idx == -1) {
|
||||
content += text.slice(pos);
|
||||
col += text.length - pos;
|
||||
break;
|
||||
} else {
|
||||
col += idx - pos;
|
||||
content += text.slice(pos, idx);
|
||||
var size = tabSize - col % tabSize;
|
||||
col += size;
|
||||
for (var i = 0; i < size; ++i) content += " ";
|
||||
pos = idx + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (style) {
|
||||
var sp = node.appendChild(document.createElement("span"));
|
||||
sp.className = "cm-" + style.replace(/ +/g, " cm-");
|
||||
sp.appendChild(document.createTextNode(content));
|
||||
} else {
|
||||
node.appendChild(document.createTextNode(content));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var lines = splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
|
||||
for (var i = 0, e = lines.length; i < e; ++i) {
|
||||
if (i) callback("\n");
|
||||
var stream = new CodeMirror.StringStream(lines[i]);
|
||||
if (!stream.string && mode.blankLine) mode.blankLine(state);
|
||||
while (!stream.eol()) {
|
||||
var style = mode.token(stream, state);
|
||||
callback(stream.current(), style, i, stream.start, state);
|
||||
stream.start = stream.pos;
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
@@ -1,72 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.runMode = function(string, modespec, callback, options) {
|
||||
var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
|
||||
var ie = /MSIE \d/.test(navigator.userAgent);
|
||||
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
|
||||
|
||||
if (callback.nodeType == 1) {
|
||||
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
|
||||
var node = callback, col = 0;
|
||||
node.innerHTML = "";
|
||||
callback = function(text, style) {
|
||||
if (text == "\n") {
|
||||
// Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
|
||||
// Emitting a carriage return makes everything ok.
|
||||
node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
|
||||
col = 0;
|
||||
return;
|
||||
}
|
||||
var content = "";
|
||||
// replace tabs
|
||||
for (var pos = 0;;) {
|
||||
var idx = text.indexOf("\t", pos);
|
||||
if (idx == -1) {
|
||||
content += text.slice(pos);
|
||||
col += text.length - pos;
|
||||
break;
|
||||
} else {
|
||||
col += idx - pos;
|
||||
content += text.slice(pos, idx);
|
||||
var size = tabSize - col % tabSize;
|
||||
col += size;
|
||||
for (var i = 0; i < size; ++i) content += " ";
|
||||
pos = idx + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (style) {
|
||||
var sp = node.appendChild(document.createElement("span"));
|
||||
sp.className = "cm-" + style.replace(/ +/g, " cm-");
|
||||
sp.appendChild(document.createTextNode(content));
|
||||
} else {
|
||||
node.appendChild(document.createTextNode(content));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
|
||||
for (var i = 0, e = lines.length; i < e; ++i) {
|
||||
if (i) callback("\n");
|
||||
var stream = new CodeMirror.StringStream(lines[i]);
|
||||
if (!stream.string && mode.blankLine) mode.blankLine(state);
|
||||
while (!stream.eol()) {
|
||||
var style = mode.token(stream, state);
|
||||
callback(stream.current(), style, i, stream.start, state);
|
||||
stream.start = stream.pos;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
@@ -1,120 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
/* Just enough of CodeMirror to run runMode under node.js */
|
||||
|
||||
// declare global: StringStream
|
||||
|
||||
function splitLines(string){ return string.split(/\r?\n|\r/); };
|
||||
|
||||
function StringStream(string) {
|
||||
this.pos = this.start = 0;
|
||||
this.string = string;
|
||||
this.lineStart = 0;
|
||||
}
|
||||
StringStream.prototype = {
|
||||
eol: function() {return this.pos >= this.string.length;},
|
||||
sol: function() {return this.pos == 0;},
|
||||
peek: function() {return this.string.charAt(this.pos) || null;},
|
||||
next: function() {
|
||||
if (this.pos < this.string.length)
|
||||
return this.string.charAt(this.pos++);
|
||||
},
|
||||
eat: function(match) {
|
||||
var ch = this.string.charAt(this.pos);
|
||||
if (typeof match == "string") var ok = ch == match;
|
||||
else var ok = ch && (match.test ? match.test(ch) : match(ch));
|
||||
if (ok) {++this.pos; return ch;}
|
||||
},
|
||||
eatWhile: function(match) {
|
||||
var start = this.pos;
|
||||
while (this.eat(match)){}
|
||||
return this.pos > start;
|
||||
},
|
||||
eatSpace: function() {
|
||||
var start = this.pos;
|
||||
while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
|
||||
return this.pos > start;
|
||||
},
|
||||
skipToEnd: function() {this.pos = this.string.length;},
|
||||
skipTo: function(ch) {
|
||||
var found = this.string.indexOf(ch, this.pos);
|
||||
if (found > -1) {this.pos = found; return true;}
|
||||
},
|
||||
backUp: function(n) {this.pos -= n;},
|
||||
column: function() {return this.start - this.lineStart;},
|
||||
indentation: function() {return 0;},
|
||||
match: function(pattern, consume, caseInsensitive) {
|
||||
if (typeof pattern == "string") {
|
||||
var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
|
||||
var substr = this.string.substr(this.pos, pattern.length);
|
||||
if (cased(substr) == cased(pattern)) {
|
||||
if (consume !== false) this.pos += pattern.length;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
var match = this.string.slice(this.pos).match(pattern);
|
||||
if (match && match.index > 0) return null;
|
||||
if (match && consume !== false) this.pos += match[0].length;
|
||||
return match;
|
||||
}
|
||||
},
|
||||
current: function(){return this.string.slice(this.start, this.pos);},
|
||||
hideFirstChars: function(n, inner) {
|
||||
this.lineStart += n;
|
||||
try { return inner(); }
|
||||
finally { this.lineStart -= n; }
|
||||
}
|
||||
};
|
||||
exports.StringStream = StringStream;
|
||||
|
||||
exports.startState = function(mode, a1, a2) {
|
||||
return mode.startState ? mode.startState(a1, a2) : true;
|
||||
};
|
||||
|
||||
var modes = exports.modes = {}, mimeModes = exports.mimeModes = {};
|
||||
exports.defineMode = function(name, mode) {
|
||||
if (arguments.length > 2)
|
||||
mode.dependencies = Array.prototype.slice.call(arguments, 2);
|
||||
modes[name] = mode;
|
||||
};
|
||||
exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; };
|
||||
|
||||
exports.defineMode("null", function() {
|
||||
return {token: function(stream) {stream.skipToEnd();}};
|
||||
});
|
||||
exports.defineMIME("text/plain", "null");
|
||||
|
||||
exports.resolveMode = function(spec) {
|
||||
if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
|
||||
spec = mimeModes[spec];
|
||||
} else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
|
||||
spec = mimeModes[spec.name];
|
||||
}
|
||||
if (typeof spec == "string") return {name: spec};
|
||||
else return spec || {name: "null"};
|
||||
};
|
||||
exports.getMode = function(options, spec) {
|
||||
spec = exports.resolveMode(spec);
|
||||
var mfactory = modes[spec.name];
|
||||
if (!mfactory) throw new Error("Unknown mode: " + spec);
|
||||
return mfactory(options, spec);
|
||||
};
|
||||
exports.registerHelper = exports.registerGlobalHelper = Math.min;
|
||||
|
||||
exports.runMode = function(string, modespec, callback, options) {
|
||||
var mode = exports.getMode({indentUnit: 2}, modespec);
|
||||
var lines = splitLines(string), state = (options && options.state) || exports.startState(mode);
|
||||
for (var i = 0, e = lines.length; i < e; ++i) {
|
||||
if (i) callback("\n");
|
||||
var stream = new exports.StringStream(lines[i]);
|
||||
if (!stream.string && mode.blankLine) mode.blankLine(state);
|
||||
while (!stream.eol()) {
|
||||
var style = mode.token(stream, state);
|
||||
callback(stream.current(), style, i, stream.start, state);
|
||||
stream.start = stream.pos;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")];
|
||||
@@ -1,100 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineExtension("annotateScrollbar", function(options) {
|
||||
if (typeof options == "string") options = {className: options};
|
||||
return new Annotation(this, options);
|
||||
});
|
||||
|
||||
CodeMirror.defineOption("scrollButtonHeight", 0);
|
||||
|
||||
function Annotation(cm, options) {
|
||||
this.cm = cm;
|
||||
this.options = options;
|
||||
this.buttonHeight = options.scrollButtonHeight || cm.getOption("scrollButtonHeight");
|
||||
this.annotations = [];
|
||||
this.doRedraw = this.doUpdate = null;
|
||||
this.div = cm.getWrapperElement().appendChild(document.createElement("div"));
|
||||
this.div.style.cssText = "position: absolute; right: 0; top: 0; z-index: 7; pointer-events: none";
|
||||
this.computeScale();
|
||||
|
||||
function scheduleRedraw(delay) {
|
||||
clearTimeout(self.doRedraw);
|
||||
self.doRedraw = setTimeout(function() { self.redraw(); }, delay);
|
||||
}
|
||||
|
||||
var self = this;
|
||||
cm.on("refresh", this.resizeHandler = function() {
|
||||
clearTimeout(self.doUpdate);
|
||||
self.doUpdate = setTimeout(function() {
|
||||
if (self.computeScale()) scheduleRedraw(20);
|
||||
}, 100);
|
||||
});
|
||||
cm.on("markerAdded", this.resizeHandler);
|
||||
cm.on("markerCleared", this.resizeHandler);
|
||||
if (options.listenForChanges !== false)
|
||||
cm.on("change", this.changeHandler = function() {
|
||||
scheduleRedraw(250);
|
||||
});
|
||||
}
|
||||
|
||||
Annotation.prototype.computeScale = function() {
|
||||
var cm = this.cm;
|
||||
var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight - this.buttonHeight * 2) /
|
||||
cm.heightAtLine(cm.lastLine() + 1, "local");
|
||||
if (hScale != this.hScale) {
|
||||
this.hScale = hScale;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Annotation.prototype.update = function(annotations) {
|
||||
this.annotations = annotations;
|
||||
this.redraw();
|
||||
};
|
||||
|
||||
Annotation.prototype.redraw = function(compute) {
|
||||
if (compute !== false) this.computeScale();
|
||||
var cm = this.cm, hScale = this.hScale;
|
||||
|
||||
var frag = document.createDocumentFragment(), anns = this.annotations;
|
||||
if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) {
|
||||
var ann = anns[i];
|
||||
var top = nextTop || cm.charCoords(ann.from, "local").top * hScale;
|
||||
var bottom = cm.charCoords(ann.to, "local").bottom * hScale;
|
||||
while (i < anns.length - 1) {
|
||||
nextTop = cm.charCoords(anns[i + 1].from, "local").top * hScale;
|
||||
if (nextTop > bottom + .9) break;
|
||||
ann = anns[++i];
|
||||
bottom = cm.charCoords(ann.to, "local").bottom * hScale;
|
||||
}
|
||||
if (bottom == top) continue;
|
||||
var height = Math.max(bottom - top, 3);
|
||||
|
||||
var elt = frag.appendChild(document.createElement("div"));
|
||||
elt.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: "
|
||||
+ (top + this.buttonHeight) + "px; height: " + height + "px";
|
||||
elt.className = this.options.className;
|
||||
}
|
||||
this.div.textContent = "";
|
||||
this.div.appendChild(frag);
|
||||
};
|
||||
|
||||
Annotation.prototype.clear = function() {
|
||||
this.cm.off("refresh", this.resizeHandler);
|
||||
this.cm.off("markerAdded", this.resizeHandler);
|
||||
this.cm.off("markerCleared", this.resizeHandler);
|
||||
if (this.changeHandler) this.cm.off("change", this.changeHandler);
|
||||
this.div.parentNode.removeChild(this.div);
|
||||
};
|
||||
});
|
||||
@@ -1,46 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineOption("scrollPastEnd", false, function(cm, val, old) {
|
||||
if (old && old != CodeMirror.Init) {
|
||||
cm.off("change", onChange);
|
||||
cm.off("refresh", updateBottomMargin);
|
||||
cm.display.lineSpace.parentNode.style.paddingBottom = "";
|
||||
cm.state.scrollPastEndPadding = null;
|
||||
}
|
||||
if (val) {
|
||||
cm.on("change", onChange);
|
||||
cm.on("refresh", updateBottomMargin);
|
||||
updateBottomMargin(cm);
|
||||
}
|
||||
});
|
||||
|
||||
function onChange(cm, change) {
|
||||
if (CodeMirror.changeEnd(change).line == cm.lastLine())
|
||||
updateBottomMargin(cm);
|
||||
}
|
||||
|
||||
function updateBottomMargin(cm) {
|
||||
var padding = "";
|
||||
if (cm.lineCount() > 1) {
|
||||
var totalH = cm.display.scroller.clientHeight - 30,
|
||||
lastLineH = cm.getLineHandle(cm.lastLine()).height;
|
||||
padding = (totalH - lastLineH) + "px";
|
||||
}
|
||||
if (cm.state.scrollPastEndPadding != padding) {
|
||||
cm.state.scrollPastEndPadding = padding;
|
||||
cm.display.lineSpace.parentNode.style.paddingBottom = padding;
|
||||
cm.setSize();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,66 +0,0 @@
|
||||
.CodeMirror-simplescroll-horizontal div, .CodeMirror-simplescroll-vertical div {
|
||||
position: absolute;
|
||||
background: #ccc;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #bbb;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.CodeMirror-simplescroll-horizontal, .CodeMirror-simplescroll-vertical {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.CodeMirror-simplescroll-horizontal {
|
||||
bottom: 0; left: 0;
|
||||
height: 8px;
|
||||
}
|
||||
.CodeMirror-simplescroll-horizontal div {
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.CodeMirror-simplescroll-vertical {
|
||||
right: 0; top: 0;
|
||||
width: 8px;
|
||||
}
|
||||
.CodeMirror-simplescroll-vertical div {
|
||||
right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.CodeMirror-overlayscroll .CodeMirror-scrollbar-filler, .CodeMirror-overlayscroll .CodeMirror-gutter-filler {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.CodeMirror-overlayscroll-horizontal div, .CodeMirror-overlayscroll-vertical div {
|
||||
position: absolute;
|
||||
background: #bcd;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.CodeMirror-overlayscroll-horizontal, .CodeMirror-overlayscroll-vertical {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
.CodeMirror-overlayscroll-horizontal {
|
||||
bottom: 0; left: 0;
|
||||
height: 6px;
|
||||
}
|
||||
.CodeMirror-overlayscroll-horizontal div {
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.CodeMirror-overlayscroll-vertical {
|
||||
right: 0; top: 0;
|
||||
width: 6px;
|
||||
}
|
||||
.CodeMirror-overlayscroll-vertical div {
|
||||
right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
function Bar(cls, orientation, scroll) {
|
||||
this.orientation = orientation;
|
||||
this.scroll = scroll;
|
||||
this.screen = this.total = this.size = 1;
|
||||
this.pos = 0;
|
||||
|
||||
this.node = document.createElement("div");
|
||||
this.node.className = cls + "-" + orientation;
|
||||
this.inner = this.node.appendChild(document.createElement("div"));
|
||||
|
||||
var self = this;
|
||||
CodeMirror.on(this.inner, "mousedown", function(e) {
|
||||
if (e.which != 1) return;
|
||||
CodeMirror.e_preventDefault(e);
|
||||
var axis = self.orientation == "horizontal" ? "pageX" : "pageY";
|
||||
var start = e[axis], startpos = self.pos;
|
||||
function done() {
|
||||
CodeMirror.off(document, "mousemove", move);
|
||||
CodeMirror.off(document, "mouseup", done);
|
||||
}
|
||||
function move(e) {
|
||||
if (e.which != 1) return done();
|
||||
self.moveTo(startpos + (e[axis] - start) * (self.total / self.size));
|
||||
}
|
||||
CodeMirror.on(document, "mousemove", move);
|
||||
CodeMirror.on(document, "mouseup", done);
|
||||
});
|
||||
|
||||
CodeMirror.on(this.node, "click", function(e) {
|
||||
CodeMirror.e_preventDefault(e);
|
||||
var innerBox = self.inner.getBoundingClientRect(), where;
|
||||
if (self.orientation == "horizontal")
|
||||
where = e.clientX < innerBox.left ? -1 : e.clientX > innerBox.right ? 1 : 0;
|
||||
else
|
||||
where = e.clientY < innerBox.top ? -1 : e.clientY > innerBox.bottom ? 1 : 0;
|
||||
self.moveTo(self.pos + where * self.screen);
|
||||
});
|
||||
|
||||
function onWheel(e) {
|
||||
var moved = CodeMirror.wheelEventPixels(e)[self.orientation == "horizontal" ? "x" : "y"];
|
||||
var oldPos = self.pos;
|
||||
self.moveTo(self.pos + moved);
|
||||
if (self.pos != oldPos) CodeMirror.e_preventDefault(e);
|
||||
}
|
||||
CodeMirror.on(this.node, "mousewheel", onWheel);
|
||||
CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
|
||||
}
|
||||
|
||||
Bar.prototype.moveTo = function(pos, update) {
|
||||
if (pos < 0) pos = 0;
|
||||
if (pos > this.total - this.screen) pos = this.total - this.screen;
|
||||
if (pos == this.pos) return;
|
||||
this.pos = pos;
|
||||
this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
|
||||
(pos * (this.size / this.total)) + "px";
|
||||
if (update !== false) this.scroll(pos, this.orientation);
|
||||
};
|
||||
|
||||
Bar.prototype.update = function(scrollSize, clientSize, barSize) {
|
||||
this.screen = clientSize;
|
||||
this.total = scrollSize;
|
||||
this.size = barSize;
|
||||
|
||||
// FIXME clip to min size?
|
||||
this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
|
||||
this.screen * (this.size / this.total) + "px";
|
||||
this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
|
||||
this.pos * (this.size / this.total) + "px";
|
||||
};
|
||||
|
||||
function SimpleScrollbars(cls, place, scroll) {
|
||||
this.addClass = cls;
|
||||
this.horiz = new Bar(cls, "horizontal", scroll);
|
||||
place(this.horiz.node);
|
||||
this.vert = new Bar(cls, "vertical", scroll);
|
||||
place(this.vert.node);
|
||||
this.width = null;
|
||||
}
|
||||
|
||||
SimpleScrollbars.prototype.update = function(measure) {
|
||||
if (this.width == null) {
|
||||
var style = window.getComputedStyle ? window.getComputedStyle(this.horiz.node) : this.horiz.node.currentStyle;
|
||||
if (style) this.width = parseInt(style.height);
|
||||
}
|
||||
var width = this.width || 0;
|
||||
|
||||
var needsH = measure.scrollWidth > measure.clientWidth + 1;
|
||||
var needsV = measure.scrollHeight > measure.clientHeight + 1;
|
||||
this.vert.node.style.display = needsV ? "block" : "none";
|
||||
this.horiz.node.style.display = needsH ? "block" : "none";
|
||||
|
||||
if (needsV) {
|
||||
this.vert.update(measure.scrollHeight, measure.clientHeight,
|
||||
measure.viewHeight - (needsH ? width : 0));
|
||||
this.vert.node.style.display = "block";
|
||||
this.vert.node.style.bottom = needsH ? width + "px" : "0";
|
||||
}
|
||||
if (needsH) {
|
||||
this.horiz.update(measure.scrollWidth, measure.clientWidth,
|
||||
measure.viewWidth - (needsV ? width : 0) - measure.barLeft);
|
||||
this.horiz.node.style.right = needsV ? width + "px" : "0";
|
||||
this.horiz.node.style.left = measure.barLeft + "px";
|
||||
}
|
||||
|
||||
return {right: needsV ? width : 0, bottom: needsH ? width : 0};
|
||||
};
|
||||
|
||||
SimpleScrollbars.prototype.setScrollTop = function(pos) {
|
||||
this.vert.moveTo(pos, false);
|
||||
};
|
||||
|
||||
SimpleScrollbars.prototype.setScrollLeft = function(pos) {
|
||||
this.horiz.moveTo(pos, false);
|
||||
};
|
||||
|
||||
SimpleScrollbars.prototype.clear = function() {
|
||||
var parent = this.horiz.node.parentNode;
|
||||
parent.removeChild(this.horiz.node);
|
||||
parent.removeChild(this.vert.node);
|
||||
};
|
||||
|
||||
CodeMirror.scrollbarModel.simple = function(place, scroll) {
|
||||
return new SimpleScrollbars("CodeMirror-simplescroll", place, scroll);
|
||||
};
|
||||
CodeMirror.scrollbarModel.overlay = function(place, scroll) {
|
||||
return new SimpleScrollbars("CodeMirror-overlayscroll", place, scroll);
|
||||
};
|
||||
});
|
||||
@@ -1,71 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
// Because sometimes you need to style the cursor's line.
|
||||
//
|
||||
// Adds an option 'styleActiveLine' which, when enabled, gives the
|
||||
// active line's wrapping <div> the CSS class "CodeMirror-activeline",
|
||||
// and gives its background <div> the class "CodeMirror-activeline-background".
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
var WRAP_CLASS = "CodeMirror-activeline";
|
||||
var BACK_CLASS = "CodeMirror-activeline-background";
|
||||
|
||||
CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
|
||||
var prev = old && old != CodeMirror.Init;
|
||||
if (val && !prev) {
|
||||
cm.state.activeLines = [];
|
||||
updateActiveLines(cm, cm.listSelections());
|
||||
cm.on("beforeSelectionChange", selectionChange);
|
||||
} else if (!val && prev) {
|
||||
cm.off("beforeSelectionChange", selectionChange);
|
||||
clearActiveLines(cm);
|
||||
delete cm.state.activeLines;
|
||||
}
|
||||
});
|
||||
|
||||
function clearActiveLines(cm) {
|
||||
for (var i = 0; i < cm.state.activeLines.length; i++) {
|
||||
cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
|
||||
cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
|
||||
}
|
||||
}
|
||||
|
||||
function sameArray(a, b) {
|
||||
if (a.length != b.length) return false;
|
||||
for (var i = 0; i < a.length; i++)
|
||||
if (a[i] != b[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function updateActiveLines(cm, ranges) {
|
||||
var active = [];
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
var range = ranges[i];
|
||||
if (!range.empty()) continue;
|
||||
var line = cm.getLineHandleVisualStart(range.head.line);
|
||||
if (active[active.length - 1] != line) active.push(line);
|
||||
}
|
||||
if (sameArray(cm.state.activeLines, active)) return;
|
||||
cm.operation(function() {
|
||||
clearActiveLines(cm);
|
||||
for (var i = 0; i < active.length; i++) {
|
||||
cm.addLineClass(active[i], "wrap", WRAP_CLASS);
|
||||
cm.addLineClass(active[i], "background", BACK_CLASS);
|
||||
}
|
||||
cm.state.activeLines = active;
|
||||
});
|
||||
}
|
||||
|
||||
function selectionChange(cm, sel) {
|
||||
updateActiveLines(cm, sel.ranges);
|
||||
}
|
||||
});
|
||||
@@ -1,118 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
// Because sometimes you need to mark the selected *text*.
|
||||
//
|
||||
// Adds an option 'styleSelectedText' which, when enabled, gives
|
||||
// selected text the CSS class given as option value, or
|
||||
// "CodeMirror-selectedtext" when the value is not a string.
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) {
|
||||
var prev = old && old != CodeMirror.Init;
|
||||
if (val && !prev) {
|
||||
cm.state.markedSelection = [];
|
||||
cm.state.markedSelectionStyle = typeof val == "string" ? val : "CodeMirror-selectedtext";
|
||||
reset(cm);
|
||||
cm.on("cursorActivity", onCursorActivity);
|
||||
cm.on("change", onChange);
|
||||
} else if (!val && prev) {
|
||||
cm.off("cursorActivity", onCursorActivity);
|
||||
cm.off("change", onChange);
|
||||
clear(cm);
|
||||
cm.state.markedSelection = cm.state.markedSelectionStyle = null;
|
||||
}
|
||||
});
|
||||
|
||||
function onCursorActivity(cm) {
|
||||
cm.operation(function() { update(cm); });
|
||||
}
|
||||
|
||||
function onChange(cm) {
|
||||
if (cm.state.markedSelection.length)
|
||||
cm.operation(function() { clear(cm); });
|
||||
}
|
||||
|
||||
var CHUNK_SIZE = 8;
|
||||
var Pos = CodeMirror.Pos;
|
||||
var cmp = CodeMirror.cmpPos;
|
||||
|
||||
function coverRange(cm, from, to, addAt) {
|
||||
if (cmp(from, to) == 0) return;
|
||||
var array = cm.state.markedSelection;
|
||||
var cls = cm.state.markedSelectionStyle;
|
||||
for (var line = from.line;;) {
|
||||
var start = line == from.line ? from : Pos(line, 0);
|
||||
var endLine = line + CHUNK_SIZE, atEnd = endLine >= to.line;
|
||||
var end = atEnd ? to : Pos(endLine, 0);
|
||||
var mark = cm.markText(start, end, {className: cls});
|
||||
if (addAt == null) array.push(mark);
|
||||
else array.splice(addAt++, 0, mark);
|
||||
if (atEnd) break;
|
||||
line = endLine;
|
||||
}
|
||||
}
|
||||
|
||||
function clear(cm) {
|
||||
var array = cm.state.markedSelection;
|
||||
for (var i = 0; i < array.length; ++i) array[i].clear();
|
||||
array.length = 0;
|
||||
}
|
||||
|
||||
function reset(cm) {
|
||||
clear(cm);
|
||||
var ranges = cm.listSelections();
|
||||
for (var i = 0; i < ranges.length; i++)
|
||||
coverRange(cm, ranges[i].from(), ranges[i].to());
|
||||
}
|
||||
|
||||
function update(cm) {
|
||||
if (!cm.somethingSelected()) return clear(cm);
|
||||
if (cm.listSelections().length > 1) return reset(cm);
|
||||
|
||||
var from = cm.getCursor("start"), to = cm.getCursor("end");
|
||||
|
||||
var array = cm.state.markedSelection;
|
||||
if (!array.length) return coverRange(cm, from, to);
|
||||
|
||||
var coverStart = array[0].find(), coverEnd = array[array.length - 1].find();
|
||||
if (!coverStart || !coverEnd || to.line - from.line < CHUNK_SIZE ||
|
||||
cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0)
|
||||
return reset(cm);
|
||||
|
||||
while (cmp(from, coverStart.from) > 0) {
|
||||
array.shift().clear();
|
||||
coverStart = array[0].find();
|
||||
}
|
||||
if (cmp(from, coverStart.from) < 0) {
|
||||
if (coverStart.to.line - from.line < CHUNK_SIZE) {
|
||||
array.shift().clear();
|
||||
coverRange(cm, from, coverStart.to, 0);
|
||||
} else {
|
||||
coverRange(cm, from, coverStart.from, 0);
|
||||
}
|
||||
}
|
||||
|
||||
while (cmp(to, coverEnd.to) < 0) {
|
||||
array.pop().clear();
|
||||
coverEnd = array[array.length - 1].find();
|
||||
}
|
||||
if (cmp(to, coverEnd.to) > 0) {
|
||||
if (to.line - coverEnd.from.line < CHUNK_SIZE) {
|
||||
array.pop().clear();
|
||||
coverRange(cm, coverEnd.from, to);
|
||||
} else {
|
||||
coverRange(cm, coverEnd.to, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,98 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineOption("selectionPointer", false, function(cm, val) {
|
||||
var data = cm.state.selectionPointer;
|
||||
if (data) {
|
||||
CodeMirror.off(cm.getWrapperElement(), "mousemove", data.mousemove);
|
||||
CodeMirror.off(cm.getWrapperElement(), "mouseout", data.mouseout);
|
||||
CodeMirror.off(window, "scroll", data.windowScroll);
|
||||
cm.off("cursorActivity", reset);
|
||||
cm.off("scroll", reset);
|
||||
cm.state.selectionPointer = null;
|
||||
cm.display.lineDiv.style.cursor = "";
|
||||
}
|
||||
if (val) {
|
||||
data = cm.state.selectionPointer = {
|
||||
value: typeof val == "string" ? val : "default",
|
||||
mousemove: function(event) { mousemove(cm, event); },
|
||||
mouseout: function(event) { mouseout(cm, event); },
|
||||
windowScroll: function() { reset(cm); },
|
||||
rects: null,
|
||||
mouseX: null, mouseY: null,
|
||||
willUpdate: false
|
||||
};
|
||||
CodeMirror.on(cm.getWrapperElement(), "mousemove", data.mousemove);
|
||||
CodeMirror.on(cm.getWrapperElement(), "mouseout", data.mouseout);
|
||||
CodeMirror.on(window, "scroll", data.windowScroll);
|
||||
cm.on("cursorActivity", reset);
|
||||
cm.on("scroll", reset);
|
||||
}
|
||||
});
|
||||
|
||||
function mousemove(cm, event) {
|
||||
var data = cm.state.selectionPointer;
|
||||
if (event.buttons == null ? event.which : event.buttons) {
|
||||
data.mouseX = data.mouseY = null;
|
||||
} else {
|
||||
data.mouseX = event.clientX;
|
||||
data.mouseY = event.clientY;
|
||||
}
|
||||
scheduleUpdate(cm);
|
||||
}
|
||||
|
||||
function mouseout(cm, event) {
|
||||
if (!cm.getWrapperElement().contains(event.relatedTarget)) {
|
||||
var data = cm.state.selectionPointer;
|
||||
data.mouseX = data.mouseY = null;
|
||||
scheduleUpdate(cm);
|
||||
}
|
||||
}
|
||||
|
||||
function reset(cm) {
|
||||
cm.state.selectionPointer.rects = null;
|
||||
scheduleUpdate(cm);
|
||||
}
|
||||
|
||||
function scheduleUpdate(cm) {
|
||||
if (!cm.state.selectionPointer.willUpdate) {
|
||||
cm.state.selectionPointer.willUpdate = true;
|
||||
setTimeout(function() {
|
||||
update(cm);
|
||||
cm.state.selectionPointer.willUpdate = false;
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
|
||||
function update(cm) {
|
||||
var data = cm.state.selectionPointer;
|
||||
if (!data) return;
|
||||
if (data.rects == null && data.mouseX != null) {
|
||||
data.rects = [];
|
||||
if (cm.somethingSelected()) {
|
||||
for (var sel = cm.display.selectionDiv.firstChild; sel; sel = sel.nextSibling)
|
||||
data.rects.push(sel.getBoundingClientRect());
|
||||
}
|
||||
}
|
||||
var inside = false;
|
||||
if (data.mouseX != null) for (var i = 0; i < data.rects.length; i++) {
|
||||
var rect = data.rects[i];
|
||||
if (rect.left <= data.mouseX && rect.right >= data.mouseX &&
|
||||
rect.top <= data.mouseY && rect.bottom >= data.mouseY)
|
||||
inside = true;
|
||||
}
|
||||
var cursor = inside ? data.value : "";
|
||||
if (cm.display.lineDiv.style.cursor != cursor)
|
||||
cm.display.lineDiv.style.cursor = cursor;
|
||||
}
|
||||
});
|
||||
@@ -1,86 +0,0 @@
|
||||
.CodeMirror-Tern-completion {
|
||||
padding-left: 22px;
|
||||
position: relative;
|
||||
}
|
||||
.CodeMirror-Tern-completion:before {
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
bottom: 2px;
|
||||
border-radius: 50%;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.CodeMirror-Tern-completion-unknown:before {
|
||||
content: "?";
|
||||
background: #4bb;
|
||||
}
|
||||
.CodeMirror-Tern-completion-object:before {
|
||||
content: "O";
|
||||
background: #77c;
|
||||
}
|
||||
.CodeMirror-Tern-completion-fn:before {
|
||||
content: "F";
|
||||
background: #7c7;
|
||||
}
|
||||
.CodeMirror-Tern-completion-array:before {
|
||||
content: "A";
|
||||
background: #c66;
|
||||
}
|
||||
.CodeMirror-Tern-completion-number:before {
|
||||
content: "1";
|
||||
background: #999;
|
||||
}
|
||||
.CodeMirror-Tern-completion-string:before {
|
||||
content: "S";
|
||||
background: #999;
|
||||
}
|
||||
.CodeMirror-Tern-completion-bool:before {
|
||||
content: "B";
|
||||
background: #999;
|
||||
}
|
||||
|
||||
.CodeMirror-Tern-completion-guess {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.CodeMirror-Tern-tooltip {
|
||||
border: 1px solid silver;
|
||||
border-radius: 3px;
|
||||
color: #444;
|
||||
padding: 2px 5px;
|
||||
font-size: 90%;
|
||||
font-family: monospace;
|
||||
background-color: white;
|
||||
white-space: pre-wrap;
|
||||
|
||||
max-width: 40em;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
|
||||
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
|
||||
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
|
||||
|
||||
transition: opacity 1s;
|
||||
-moz-transition: opacity 1s;
|
||||
-webkit-transition: opacity 1s;
|
||||
-o-transition: opacity 1s;
|
||||
-ms-transition: opacity 1s;
|
||||
}
|
||||
|
||||
.CodeMirror-Tern-hint-doc {
|
||||
max-width: 25em;
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
||||
.CodeMirror-Tern-fname { color: black; }
|
||||
.CodeMirror-Tern-farg { color: #70a; }
|
||||
.CodeMirror-Tern-farg-current { text-decoration: underline; }
|
||||
.CodeMirror-Tern-type { color: #07c; }
|
||||
.CodeMirror-Tern-fhint-guess { opacity: .7; }
|
||||
@@ -1,697 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
// Glue code between CodeMirror and Tern.
|
||||
//
|
||||
// Create a CodeMirror.TernServer to wrap an actual Tern server,
|
||||
// register open documents (CodeMirror.Doc instances) with it, and
|
||||
// call its methods to activate the assisting functions that Tern
|
||||
// provides.
|
||||
//
|
||||
// Options supported (all optional):
|
||||
// * defs: An array of JSON definition data structures.
|
||||
// * plugins: An object mapping plugin names to configuration
|
||||
// options.
|
||||
// * getFile: A function(name, c) that can be used to access files in
|
||||
// the project that haven't been loaded yet. Simply do c(null) to
|
||||
// indicate that a file is not available.
|
||||
// * fileFilter: A function(value, docName, doc) that will be applied
|
||||
// to documents before passing them on to Tern.
|
||||
// * switchToDoc: A function(name, doc) that should, when providing a
|
||||
// multi-file view, switch the view or focus to the named file.
|
||||
// * showError: A function(editor, message) that can be used to
|
||||
// override the way errors are displayed.
|
||||
// * completionTip: Customize the content in tooltips for completions.
|
||||
// Is passed a single argument—the completion's data as returned by
|
||||
// Tern—and may return a string, DOM node, or null to indicate that
|
||||
// no tip should be shown. By default the docstring is shown.
|
||||
// * typeTip: Like completionTip, but for the tooltips shown for type
|
||||
// queries.
|
||||
// * responseFilter: A function(doc, query, request, error, data) that
|
||||
// will be applied to the Tern responses before treating them
|
||||
//
|
||||
//
|
||||
// It is possible to run the Tern server in a web worker by specifying
|
||||
// these additional options:
|
||||
// * useWorker: Set to true to enable web worker mode. You'll probably
|
||||
// want to feature detect the actual value you use here, for example
|
||||
// !!window.Worker.
|
||||
// * workerScript: The main script of the worker. Point this to
|
||||
// wherever you are hosting worker.js from this directory.
|
||||
// * workerDeps: An array of paths pointing (relative to workerScript)
|
||||
// to the Acorn and Tern libraries and any Tern plugins you want to
|
||||
// load. Or, if you minified those into a single script and included
|
||||
// them in the workerScript, simply leave this undefined.
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
// declare global: tern
|
||||
|
||||
CodeMirror.TernServer = function(options) {
|
||||
var self = this;
|
||||
this.options = options || {};
|
||||
var plugins = this.options.plugins || (this.options.plugins = {});
|
||||
if (!plugins.doc_comment) plugins.doc_comment = true;
|
||||
if (this.options.useWorker) {
|
||||
this.server = new WorkerServer(this);
|
||||
} else {
|
||||
this.server = new tern.Server({
|
||||
getFile: function(name, c) { return getFile(self, name, c); },
|
||||
async: true,
|
||||
defs: this.options.defs || [],
|
||||
plugins: plugins
|
||||
});
|
||||
}
|
||||
this.docs = Object.create(null);
|
||||
this.trackChange = function(doc, change) { trackChange(self, doc, change); };
|
||||
|
||||
this.cachedArgHints = null;
|
||||
this.activeArgHints = null;
|
||||
this.jumpStack = [];
|
||||
|
||||
this.getHint = function(cm, c) { return hint(self, cm, c); };
|
||||
this.getHint.async = true;
|
||||
};
|
||||
|
||||
CodeMirror.TernServer.prototype = {
|
||||
addDoc: function(name, doc) {
|
||||
var data = {doc: doc, name: name, changed: null};
|
||||
this.server.addFile(name, docValue(this, data));
|
||||
CodeMirror.on(doc, "change", this.trackChange);
|
||||
return this.docs[name] = data;
|
||||
},
|
||||
|
||||
delDoc: function(id) {
|
||||
var found = resolveDoc(this, id);
|
||||
if (!found) return;
|
||||
CodeMirror.off(found.doc, "change", this.trackChange);
|
||||
delete this.docs[found.name];
|
||||
this.server.delFile(found.name);
|
||||
},
|
||||
|
||||
hideDoc: function(id) {
|
||||
closeArgHints(this);
|
||||
var found = resolveDoc(this, id);
|
||||
if (found && found.changed) sendDoc(this, found);
|
||||
},
|
||||
|
||||
complete: function(cm) {
|
||||
cm.showHint({hint: this.getHint});
|
||||
},
|
||||
|
||||
showType: function(cm, pos, c) { showContextInfo(this, cm, pos, "type", c); },
|
||||
|
||||
showDocs: function(cm, pos, c) { showContextInfo(this, cm, pos, "documentation", c); },
|
||||
|
||||
updateArgHints: function(cm) { updateArgHints(this, cm); },
|
||||
|
||||
jumpToDef: function(cm) { jumpToDef(this, cm); },
|
||||
|
||||
jumpBack: function(cm) { jumpBack(this, cm); },
|
||||
|
||||
rename: function(cm) { rename(this, cm); },
|
||||
|
||||
selectName: function(cm) { selectName(this, cm); },
|
||||
|
||||
request: function (cm, query, c, pos) {
|
||||
var self = this;
|
||||
var doc = findDoc(this, cm.getDoc());
|
||||
var request = buildRequest(this, doc, query, pos);
|
||||
|
||||
this.server.request(request, function (error, data) {
|
||||
if (!error && self.options.responseFilter)
|
||||
data = self.options.responseFilter(doc, query, request, error, data);
|
||||
c(error, data);
|
||||
});
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
if (this.worker) {
|
||||
this.worker.terminate();
|
||||
this.worker = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var Pos = CodeMirror.Pos;
|
||||
var cls = "CodeMirror-Tern-";
|
||||
var bigDoc = 250;
|
||||
|
||||
function getFile(ts, name, c) {
|
||||
var buf = ts.docs[name];
|
||||
if (buf)
|
||||
c(docValue(ts, buf));
|
||||
else if (ts.options.getFile)
|
||||
ts.options.getFile(name, c);
|
||||
else
|
||||
c(null);
|
||||
}
|
||||
|
||||
function findDoc(ts, doc, name) {
|
||||
for (var n in ts.docs) {
|
||||
var cur = ts.docs[n];
|
||||
if (cur.doc == doc) return cur;
|
||||
}
|
||||
if (!name) for (var i = 0;; ++i) {
|
||||
n = "[doc" + (i || "") + "]";
|
||||
if (!ts.docs[n]) { name = n; break; }
|
||||
}
|
||||
return ts.addDoc(name, doc);
|
||||
}
|
||||
|
||||
function resolveDoc(ts, id) {
|
||||
if (typeof id == "string") return ts.docs[id];
|
||||
if (id instanceof CodeMirror) id = id.getDoc();
|
||||
if (id instanceof CodeMirror.Doc) return findDoc(ts, id);
|
||||
}
|
||||
|
||||
function trackChange(ts, doc, change) {
|
||||
var data = findDoc(ts, doc);
|
||||
|
||||
var argHints = ts.cachedArgHints;
|
||||
if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) <= 0)
|
||||
ts.cachedArgHints = null;
|
||||
|
||||
var changed = data.changed;
|
||||
if (changed == null)
|
||||
data.changed = changed = {from: change.from.line, to: change.from.line};
|
||||
var end = change.from.line + (change.text.length - 1);
|
||||
if (change.from.line < changed.to) changed.to = changed.to - (change.to.line - end);
|
||||
if (end >= changed.to) changed.to = end + 1;
|
||||
if (changed.from > change.from.line) changed.from = change.from.line;
|
||||
|
||||
if (doc.lineCount() > bigDoc && change.to - changed.from > 100) setTimeout(function() {
|
||||
if (data.changed && data.changed.to - data.changed.from > 100) sendDoc(ts, data);
|
||||
}, 200);
|
||||
}
|
||||
|
||||
function sendDoc(ts, doc) {
|
||||
ts.server.request({files: [{type: "full", name: doc.name, text: docValue(ts, doc)}]}, function(error) {
|
||||
if (error) window.console.error(error);
|
||||
else doc.changed = null;
|
||||
});
|
||||
}
|
||||
|
||||
// Completion
|
||||
|
||||
function hint(ts, cm, c) {
|
||||
ts.request(cm, {type: "completions", types: true, docs: true, urls: true}, function(error, data) {
|
||||
if (error) return showError(ts, cm, error);
|
||||
var completions = [], after = "";
|
||||
var from = data.start, to = data.end;
|
||||
if (cm.getRange(Pos(from.line, from.ch - 2), from) == "[\"" &&
|
||||
cm.getRange(to, Pos(to.line, to.ch + 2)) != "\"]")
|
||||
after = "\"]";
|
||||
|
||||
for (var i = 0; i < data.completions.length; ++i) {
|
||||
var completion = data.completions[i], className = typeToIcon(completion.type);
|
||||
if (data.guess) className += " " + cls + "guess";
|
||||
completions.push({text: completion.name + after,
|
||||
displayText: completion.name,
|
||||
className: className,
|
||||
data: completion});
|
||||
}
|
||||
|
||||
var obj = {from: from, to: to, list: completions};
|
||||
var tooltip = null;
|
||||
CodeMirror.on(obj, "close", function() { remove(tooltip); });
|
||||
CodeMirror.on(obj, "update", function() { remove(tooltip); });
|
||||
CodeMirror.on(obj, "select", function(cur, node) {
|
||||
remove(tooltip);
|
||||
var content = ts.options.completionTip ? ts.options.completionTip(cur.data) : cur.data.doc;
|
||||
if (content) {
|
||||
tooltip = makeTooltip(node.parentNode.getBoundingClientRect().right + window.pageXOffset,
|
||||
node.getBoundingClientRect().top + window.pageYOffset, content);
|
||||
tooltip.className += " " + cls + "hint-doc";
|
||||
}
|
||||
});
|
||||
c(obj);
|
||||
});
|
||||
}
|
||||
|
||||
function typeToIcon(type) {
|
||||
var suffix;
|
||||
if (type == "?") suffix = "unknown";
|
||||
else if (type == "number" || type == "string" || type == "bool") suffix = type;
|
||||
else if (/^fn\(/.test(type)) suffix = "fn";
|
||||
else if (/^\[/.test(type)) suffix = "array";
|
||||
else suffix = "object";
|
||||
return cls + "completion " + cls + "completion-" + suffix;
|
||||
}
|
||||
|
||||
// Type queries
|
||||
|
||||
function showContextInfo(ts, cm, pos, queryName, c) {
|
||||
ts.request(cm, queryName, function(error, data) {
|
||||
if (error) return showError(ts, cm, error);
|
||||
if (ts.options.typeTip) {
|
||||
var tip = ts.options.typeTip(data);
|
||||
} else {
|
||||
var tip = elt("span", null, elt("strong", null, data.type || "not found"));
|
||||
if (data.doc)
|
||||
tip.appendChild(document.createTextNode(" — " + data.doc));
|
||||
if (data.url) {
|
||||
tip.appendChild(document.createTextNode(" "));
|
||||
var child = tip.appendChild(elt("a", null, "[docs]"));
|
||||
child.href = data.url;
|
||||
child.target = "_blank";
|
||||
}
|
||||
}
|
||||
tempTooltip(cm, tip);
|
||||
if (c) c();
|
||||
}, pos);
|
||||
}
|
||||
|
||||
// Maintaining argument hints
|
||||
|
||||
function updateArgHints(ts, cm) {
|
||||
closeArgHints(ts);
|
||||
|
||||
if (cm.somethingSelected()) return;
|
||||
var state = cm.getTokenAt(cm.getCursor()).state;
|
||||
var inner = CodeMirror.innerMode(cm.getMode(), state);
|
||||
if (inner.mode.name != "javascript") return;
|
||||
var lex = inner.state.lexical;
|
||||
if (lex.info != "call") return;
|
||||
|
||||
var ch, argPos = lex.pos || 0, tabSize = cm.getOption("tabSize");
|
||||
for (var line = cm.getCursor().line, e = Math.max(0, line - 9), found = false; line >= e; --line) {
|
||||
var str = cm.getLine(line), extra = 0;
|
||||
for (var pos = 0;;) {
|
||||
var tab = str.indexOf("\t", pos);
|
||||
if (tab == -1) break;
|
||||
extra += tabSize - (tab + extra) % tabSize - 1;
|
||||
pos = tab + 1;
|
||||
}
|
||||
ch = lex.column - extra;
|
||||
if (str.charAt(ch) == "(") {found = true; break;}
|
||||
}
|
||||
if (!found) return;
|
||||
|
||||
var start = Pos(line, ch);
|
||||
var cache = ts.cachedArgHints;
|
||||
if (cache && cache.doc == cm.getDoc() && cmpPos(start, cache.start) == 0)
|
||||
return showArgHints(ts, cm, argPos);
|
||||
|
||||
ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) {
|
||||
if (error || !data.type || !(/^fn\(/).test(data.type)) return;
|
||||
ts.cachedArgHints = {
|
||||
start: pos,
|
||||
type: parseFnType(data.type),
|
||||
name: data.exprName || data.name || "fn",
|
||||
guess: data.guess,
|
||||
doc: cm.getDoc()
|
||||
};
|
||||
showArgHints(ts, cm, argPos);
|
||||
});
|
||||
}
|
||||
|
||||
function showArgHints(ts, cm, pos) {
|
||||
closeArgHints(ts);
|
||||
|
||||
var cache = ts.cachedArgHints, tp = cache.type;
|
||||
var tip = elt("span", cache.guess ? cls + "fhint-guess" : null,
|
||||
elt("span", cls + "fname", cache.name), "(");
|
||||
for (var i = 0; i < tp.args.length; ++i) {
|
||||
if (i) tip.appendChild(document.createTextNode(", "));
|
||||
var arg = tp.args[i];
|
||||
tip.appendChild(elt("span", cls + "farg" + (i == pos ? " " + cls + "farg-current" : ""), arg.name || "?"));
|
||||
if (arg.type != "?") {
|
||||
tip.appendChild(document.createTextNode(":\u00a0"));
|
||||
tip.appendChild(elt("span", cls + "type", arg.type));
|
||||
}
|
||||
}
|
||||
tip.appendChild(document.createTextNode(tp.rettype ? ") ->\u00a0" : ")"));
|
||||
if (tp.rettype) tip.appendChild(elt("span", cls + "type", tp.rettype));
|
||||
var place = cm.cursorCoords(null, "page");
|
||||
ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip);
|
||||
}
|
||||
|
||||
function parseFnType(text) {
|
||||
var args = [], pos = 3;
|
||||
|
||||
function skipMatching(upto) {
|
||||
var depth = 0, start = pos;
|
||||
for (;;) {
|
||||
var next = text.charAt(pos);
|
||||
if (upto.test(next) && !depth) return text.slice(start, pos);
|
||||
if (/[{\[\(]/.test(next)) ++depth;
|
||||
else if (/[}\]\)]/.test(next)) --depth;
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse arguments
|
||||
if (text.charAt(pos) != ")") for (;;) {
|
||||
var name = text.slice(pos).match(/^([^, \(\[\{]+): /);
|
||||
if (name) {
|
||||
pos += name[0].length;
|
||||
name = name[1];
|
||||
}
|
||||
args.push({name: name, type: skipMatching(/[\),]/)});
|
||||
if (text.charAt(pos) == ")") break;
|
||||
pos += 2;
|
||||
}
|
||||
|
||||
var rettype = text.slice(pos).match(/^\) -> (.*)$/);
|
||||
|
||||
return {args: args, rettype: rettype && rettype[1]};
|
||||
}
|
||||
|
||||
// Moving to the definition of something
|
||||
|
||||
function jumpToDef(ts, cm) {
|
||||
function inner(varName) {
|
||||
var req = {type: "definition", variable: varName || null};
|
||||
var doc = findDoc(ts, cm.getDoc());
|
||||
ts.server.request(buildRequest(ts, doc, req), function(error, data) {
|
||||
if (error) return showError(ts, cm, error);
|
||||
if (!data.file && data.url) { window.open(data.url); return; }
|
||||
|
||||
if (data.file) {
|
||||
var localDoc = ts.docs[data.file], found;
|
||||
if (localDoc && (found = findContext(localDoc.doc, data))) {
|
||||
ts.jumpStack.push({file: doc.name,
|
||||
start: cm.getCursor("from"),
|
||||
end: cm.getCursor("to")});
|
||||
moveTo(ts, doc, localDoc, found.start, found.end);
|
||||
return;
|
||||
}
|
||||
}
|
||||
showError(ts, cm, "Could not find a definition.");
|
||||
});
|
||||
}
|
||||
|
||||
if (!atInterestingExpression(cm))
|
||||
dialog(cm, "Jump to variable", function(name) { if (name) inner(name); });
|
||||
else
|
||||
inner();
|
||||
}
|
||||
|
||||
function jumpBack(ts, cm) {
|
||||
var pos = ts.jumpStack.pop(), doc = pos && ts.docs[pos.file];
|
||||
if (!doc) return;
|
||||
moveTo(ts, findDoc(ts, cm.getDoc()), doc, pos.start, pos.end);
|
||||
}
|
||||
|
||||
function moveTo(ts, curDoc, doc, start, end) {
|
||||
doc.doc.setSelection(start, end);
|
||||
if (curDoc != doc && ts.options.switchToDoc) {
|
||||
closeArgHints(ts);
|
||||
ts.options.switchToDoc(doc.name, doc.doc);
|
||||
}
|
||||
}
|
||||
|
||||
// The {line,ch} representation of positions makes this rather awkward.
|
||||
function findContext(doc, data) {
|
||||
var before = data.context.slice(0, data.contextOffset).split("\n");
|
||||
var startLine = data.start.line - (before.length - 1);
|
||||
var start = Pos(startLine, (before.length == 1 ? data.start.ch : doc.getLine(startLine).length) - before[0].length);
|
||||
|
||||
var text = doc.getLine(startLine).slice(start.ch);
|
||||
for (var cur = startLine + 1; cur < doc.lineCount() && text.length < data.context.length; ++cur)
|
||||
text += "\n" + doc.getLine(cur);
|
||||
if (text.slice(0, data.context.length) == data.context) return data;
|
||||
|
||||
var cursor = doc.getSearchCursor(data.context, 0, false);
|
||||
var nearest, nearestDist = Infinity;
|
||||
while (cursor.findNext()) {
|
||||
var from = cursor.from(), dist = Math.abs(from.line - start.line) * 10000;
|
||||
if (!dist) dist = Math.abs(from.ch - start.ch);
|
||||
if (dist < nearestDist) { nearest = from; nearestDist = dist; }
|
||||
}
|
||||
if (!nearest) return null;
|
||||
|
||||
if (before.length == 1)
|
||||
nearest.ch += before[0].length;
|
||||
else
|
||||
nearest = Pos(nearest.line + (before.length - 1), before[before.length - 1].length);
|
||||
if (data.start.line == data.end.line)
|
||||
var end = Pos(nearest.line, nearest.ch + (data.end.ch - data.start.ch));
|
||||
else
|
||||
var end = Pos(nearest.line + (data.end.line - data.start.line), data.end.ch);
|
||||
return {start: nearest, end: end};
|
||||
}
|
||||
|
||||
function atInterestingExpression(cm) {
|
||||
var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos);
|
||||
if (tok.start < pos.ch && (tok.type == "comment" || tok.type == "string")) return false;
|
||||
return /\w/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
|
||||
}
|
||||
|
||||
// Variable renaming
|
||||
|
||||
function rename(ts, cm) {
|
||||
var token = cm.getTokenAt(cm.getCursor());
|
||||
if (!/\w/.test(token.string)) return showError(ts, cm, "Not at a variable");
|
||||
dialog(cm, "New name for " + token.string, function(newName) {
|
||||
ts.request(cm, {type: "rename", newName: newName, fullDocs: true}, function(error, data) {
|
||||
if (error) return showError(ts, cm, error);
|
||||
applyChanges(ts, data.changes);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function selectName(ts, cm) {
|
||||
var name = findDoc(ts, cm.doc).name;
|
||||
ts.request(cm, {type: "refs"}, function(error, data) {
|
||||
if (error) return showError(ts, cm, error);
|
||||
var ranges = [], cur = 0;
|
||||
for (var i = 0; i < data.refs.length; i++) {
|
||||
var ref = data.refs[i];
|
||||
if (ref.file == name) {
|
||||
ranges.push({anchor: ref.start, head: ref.end});
|
||||
if (cmpPos(cur, ref.start) >= 0 && cmpPos(cur, ref.end) <= 0)
|
||||
cur = ranges.length - 1;
|
||||
}
|
||||
}
|
||||
cm.setSelections(ranges, cur);
|
||||
});
|
||||
}
|
||||
|
||||
var nextChangeOrig = 0;
|
||||
function applyChanges(ts, changes) {
|
||||
var perFile = Object.create(null);
|
||||
for (var i = 0; i < changes.length; ++i) {
|
||||
var ch = changes[i];
|
||||
(perFile[ch.file] || (perFile[ch.file] = [])).push(ch);
|
||||
}
|
||||
for (var file in perFile) {
|
||||
var known = ts.docs[file], chs = perFile[file];;
|
||||
if (!known) continue;
|
||||
chs.sort(function(a, b) { return cmpPos(b.start, a.start); });
|
||||
var origin = "*rename" + (++nextChangeOrig);
|
||||
for (var i = 0; i < chs.length; ++i) {
|
||||
var ch = chs[i];
|
||||
known.doc.replaceRange(ch.text, ch.start, ch.end, origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generic request-building helper
|
||||
|
||||
function buildRequest(ts, doc, query, pos) {
|
||||
var files = [], offsetLines = 0, allowFragments = !query.fullDocs;
|
||||
if (!allowFragments) delete query.fullDocs;
|
||||
if (typeof query == "string") query = {type: query};
|
||||
query.lineCharPositions = true;
|
||||
if (query.end == null) {
|
||||
query.end = pos || doc.doc.getCursor("end");
|
||||
if (doc.doc.somethingSelected())
|
||||
query.start = doc.doc.getCursor("start");
|
||||
}
|
||||
var startPos = query.start || query.end;
|
||||
|
||||
if (doc.changed) {
|
||||
if (doc.doc.lineCount() > bigDoc && allowFragments !== false &&
|
||||
doc.changed.to - doc.changed.from < 100 &&
|
||||
doc.changed.from <= startPos.line && doc.changed.to > query.end.line) {
|
||||
files.push(getFragmentAround(doc, startPos, query.end));
|
||||
query.file = "#0";
|
||||
var offsetLines = files[0].offsetLines;
|
||||
if (query.start != null) query.start = Pos(query.start.line - -offsetLines, query.start.ch);
|
||||
query.end = Pos(query.end.line - offsetLines, query.end.ch);
|
||||
} else {
|
||||
files.push({type: "full",
|
||||
name: doc.name,
|
||||
text: docValue(ts, doc)});
|
||||
query.file = doc.name;
|
||||
doc.changed = null;
|
||||
}
|
||||
} else {
|
||||
query.file = doc.name;
|
||||
}
|
||||
for (var name in ts.docs) {
|
||||
var cur = ts.docs[name];
|
||||
if (cur.changed && cur != doc) {
|
||||
files.push({type: "full", name: cur.name, text: docValue(ts, cur)});
|
||||
cur.changed = null;
|
||||
}
|
||||
}
|
||||
|
||||
return {query: query, files: files};
|
||||
}
|
||||
|
||||
function getFragmentAround(data, start, end) {
|
||||
var doc = data.doc;
|
||||
var minIndent = null, minLine = null, endLine, tabSize = 4;
|
||||
for (var p = start.line - 1, min = Math.max(0, p - 50); p >= min; --p) {
|
||||
var line = doc.getLine(p), fn = line.search(/\bfunction\b/);
|
||||
if (fn < 0) continue;
|
||||
var indent = CodeMirror.countColumn(line, null, tabSize);
|
||||
if (minIndent != null && minIndent <= indent) continue;
|
||||
minIndent = indent;
|
||||
minLine = p;
|
||||
}
|
||||
if (minLine == null) minLine = min;
|
||||
var max = Math.min(doc.lastLine(), end.line + 20);
|
||||
if (minIndent == null || minIndent == CodeMirror.countColumn(doc.getLine(start.line), null, tabSize))
|
||||
endLine = max;
|
||||
else for (endLine = end.line + 1; endLine < max; ++endLine) {
|
||||
var indent = CodeMirror.countColumn(doc.getLine(endLine), null, tabSize);
|
||||
if (indent <= minIndent) break;
|
||||
}
|
||||
var from = Pos(minLine, 0);
|
||||
|
||||
return {type: "part",
|
||||
name: data.name,
|
||||
offsetLines: from.line,
|
||||
text: doc.getRange(from, Pos(endLine, 0))};
|
||||
}
|
||||
|
||||
// Generic utilities
|
||||
|
||||
var cmpPos = CodeMirror.cmpPos;
|
||||
|
||||
function elt(tagname, cls /*, ... elts*/) {
|
||||
var e = document.createElement(tagname);
|
||||
if (cls) e.className = cls;
|
||||
for (var i = 2; i < arguments.length; ++i) {
|
||||
var elt = arguments[i];
|
||||
if (typeof elt == "string") elt = document.createTextNode(elt);
|
||||
e.appendChild(elt);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
function dialog(cm, text, f) {
|
||||
if (cm.openDialog)
|
||||
cm.openDialog(text + ": <input type=text>", f);
|
||||
else
|
||||
f(prompt(text, ""));
|
||||
}
|
||||
|
||||
// Tooltips
|
||||
|
||||
function tempTooltip(cm, content) {
|
||||
if (cm.state.ternTooltip) remove(cm.state.ternTooltip);
|
||||
var where = cm.cursorCoords();
|
||||
var tip = cm.state.ternTooltip = makeTooltip(where.right + 1, where.bottom, content);
|
||||
function maybeClear() {
|
||||
old = true;
|
||||
if (!mouseOnTip) clear();
|
||||
}
|
||||
function clear() {
|
||||
cm.state.ternTooltip = null;
|
||||
if (!tip.parentNode) return;
|
||||
cm.off("cursorActivity", clear);
|
||||
cm.off('blur', clear);
|
||||
cm.off('scroll', clear);
|
||||
fadeOut(tip);
|
||||
}
|
||||
var mouseOnTip = false, old = false;
|
||||
CodeMirror.on(tip, "mousemove", function() { mouseOnTip = true; });
|
||||
CodeMirror.on(tip, "mouseout", function(e) {
|
||||
if (!CodeMirror.contains(tip, e.relatedTarget || e.toElement)) {
|
||||
if (old) clear();
|
||||
else mouseOnTip = false;
|
||||
}
|
||||
});
|
||||
setTimeout(maybeClear, 1700);
|
||||
cm.on("cursorActivity", clear);
|
||||
cm.on('blur', clear);
|
||||
cm.on('scroll', clear);
|
||||
}
|
||||
|
||||
function makeTooltip(x, y, content) {
|
||||
var node = elt("div", cls + "tooltip", content);
|
||||
node.style.left = x + "px";
|
||||
node.style.top = y + "px";
|
||||
document.body.appendChild(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
function remove(node) {
|
||||
var p = node && node.parentNode;
|
||||
if (p) p.removeChild(node);
|
||||
}
|
||||
|
||||
function fadeOut(tooltip) {
|
||||
tooltip.style.opacity = "0";
|
||||
setTimeout(function() { remove(tooltip); }, 1100);
|
||||
}
|
||||
|
||||
function showError(ts, cm, msg) {
|
||||
if (ts.options.showError)
|
||||
ts.options.showError(cm, msg);
|
||||
else
|
||||
tempTooltip(cm, String(msg));
|
||||
}
|
||||
|
||||
function closeArgHints(ts) {
|
||||
if (ts.activeArgHints) { remove(ts.activeArgHints); ts.activeArgHints = null; }
|
||||
}
|
||||
|
||||
function docValue(ts, doc) {
|
||||
var val = doc.doc.getValue();
|
||||
if (ts.options.fileFilter) val = ts.options.fileFilter(val, doc.name, doc.doc);
|
||||
return val;
|
||||
}
|
||||
|
||||
// Worker wrapper
|
||||
|
||||
function WorkerServer(ts) {
|
||||
var worker = ts.worker = new Worker(ts.options.workerScript);
|
||||
worker.postMessage({type: "init",
|
||||
defs: ts.options.defs,
|
||||
plugins: ts.options.plugins,
|
||||
scripts: ts.options.workerDeps});
|
||||
var msgId = 0, pending = {};
|
||||
|
||||
function send(data, c) {
|
||||
if (c) {
|
||||
data.id = ++msgId;
|
||||
pending[msgId] = c;
|
||||
}
|
||||
worker.postMessage(data);
|
||||
}
|
||||
worker.onmessage = function(e) {
|
||||
var data = e.data;
|
||||
if (data.type == "getFile") {
|
||||
getFile(ts, data.name, function(err, text) {
|
||||
send({type: "getFile", err: String(err), text: text, id: data.id});
|
||||
});
|
||||
} else if (data.type == "debug") {
|
||||
window.console.log(data.message);
|
||||
} else if (data.id && pending[data.id]) {
|
||||
pending[data.id](data.err, data.body);
|
||||
delete pending[data.id];
|
||||
}
|
||||
};
|
||||
worker.onerror = function(e) {
|
||||
for (var id in pending) pending[id](e);
|
||||
pending = {};
|
||||
};
|
||||
|
||||
this.addFile = function(name, text) { send({type: "add", name: name, text: text}); };
|
||||
this.delFile = function(name) { send({type: "del", name: name}); };
|
||||
this.request = function(body, c) { send({type: "req", body: body}, c); };
|
||||
}
|
||||
});
|
||||
@@ -1,44 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
// declare global: tern, server
|
||||
|
||||
var server;
|
||||
|
||||
this.onmessage = function(e) {
|
||||
var data = e.data;
|
||||
switch (data.type) {
|
||||
case "init": return startServer(data.defs, data.plugins, data.scripts);
|
||||
case "add": return server.addFile(data.name, data.text);
|
||||
case "del": return server.delFile(data.name);
|
||||
case "req": return server.request(data.body, function(err, reqData) {
|
||||
postMessage({id: data.id, body: reqData, err: err && String(err)});
|
||||
});
|
||||
case "getFile":
|
||||
var c = pending[data.id];
|
||||
delete pending[data.id];
|
||||
return c(data.err, data.text);
|
||||
default: throw new Error("Unknown message type: " + data.type);
|
||||
}
|
||||
};
|
||||
|
||||
var nextId = 0, pending = {};
|
||||
function getFile(file, c) {
|
||||
postMessage({type: "getFile", name: file, id: ++nextId});
|
||||
pending[nextId] = c;
|
||||
}
|
||||
|
||||
function startServer(defs, plugins, scripts) {
|
||||
if (scripts) importScripts.apply(null, scripts);
|
||||
|
||||
server = new tern.Server({
|
||||
getFile: getFile,
|
||||
async: true,
|
||||
defs: defs,
|
||||
plugins: plugins
|
||||
});
|
||||
}
|
||||
|
||||
var console = {
|
||||
log: function(v) { postMessage({type: "debug", message: v}); }
|
||||
};
|
||||
@@ -1,139 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
var Pos = CodeMirror.Pos;
|
||||
|
||||
function findParagraph(cm, pos, options) {
|
||||
var startRE = options.paragraphStart || cm.getHelper(pos, "paragraphStart");
|
||||
for (var start = pos.line, first = cm.firstLine(); start > first; --start) {
|
||||
var line = cm.getLine(start);
|
||||
if (startRE && startRE.test(line)) break;
|
||||
if (!/\S/.test(line)) { ++start; break; }
|
||||
}
|
||||
var endRE = options.paragraphEnd || cm.getHelper(pos, "paragraphEnd");
|
||||
for (var end = pos.line + 1, last = cm.lastLine(); end <= last; ++end) {
|
||||
var line = cm.getLine(end);
|
||||
if (endRE && endRE.test(line)) { ++end; break; }
|
||||
if (!/\S/.test(line)) break;
|
||||
}
|
||||
return {from: start, to: end};
|
||||
}
|
||||
|
||||
function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
|
||||
for (var at = column; at > 0; --at)
|
||||
if (wrapOn.test(text.slice(at - 1, at + 1))) break;
|
||||
if (at == 0) at = column;
|
||||
var endOfText = at;
|
||||
if (killTrailingSpace)
|
||||
while (text.charAt(endOfText - 1) == " ") --endOfText;
|
||||
return {from: endOfText, to: at};
|
||||
}
|
||||
|
||||
function wrapRange(cm, from, to, options) {
|
||||
from = cm.clipPos(from); to = cm.clipPos(to);
|
||||
var column = options.column || 80;
|
||||
var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/;
|
||||
var killTrailing = options.killTrailingSpace !== false;
|
||||
var changes = [], curLine = "", curNo = from.line;
|
||||
var lines = cm.getRange(from, to, false);
|
||||
if (!lines.length) return null;
|
||||
var leadingSpace = lines[0].match(/^[ \t]*/)[0];
|
||||
|
||||
for (var i = 0; i < lines.length; ++i) {
|
||||
var text = lines[i], oldLen = curLine.length, spaceInserted = 0;
|
||||
if (curLine && text && !wrapOn.test(curLine.charAt(curLine.length - 1) + text.charAt(0))) {
|
||||
curLine += " ";
|
||||
spaceInserted = 1;
|
||||
}
|
||||
var spaceTrimmed = "";
|
||||
if (i) {
|
||||
spaceTrimmed = text.match(/^\s*/)[0];
|
||||
text = text.slice(spaceTrimmed.length);
|
||||
}
|
||||
curLine += text;
|
||||
if (i) {
|
||||
var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed &&
|
||||
findBreakPoint(curLine, column, wrapOn, killTrailing);
|
||||
// If this isn't broken, or is broken at a different point, remove old break
|
||||
if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) {
|
||||
changes.push({text: [spaceInserted ? " " : ""],
|
||||
from: Pos(curNo, oldLen),
|
||||
to: Pos(curNo + 1, spaceTrimmed.length)});
|
||||
} else {
|
||||
curLine = leadingSpace + text;
|
||||
++curNo;
|
||||
}
|
||||
}
|
||||
while (curLine.length > column) {
|
||||
var bp = findBreakPoint(curLine, column, wrapOn, killTrailing);
|
||||
changes.push({text: ["", leadingSpace],
|
||||
from: Pos(curNo, bp.from),
|
||||
to: Pos(curNo, bp.to)});
|
||||
curLine = leadingSpace + curLine.slice(bp.to);
|
||||
++curNo;
|
||||
}
|
||||
}
|
||||
if (changes.length) cm.operation(function() {
|
||||
for (var i = 0; i < changes.length; ++i) {
|
||||
var change = changes[i];
|
||||
cm.replaceRange(change.text, change.from, change.to);
|
||||
}
|
||||
});
|
||||
return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null;
|
||||
}
|
||||
|
||||
CodeMirror.defineExtension("wrapParagraph", function(pos, options) {
|
||||
options = options || {};
|
||||
if (!pos) pos = this.getCursor();
|
||||
var para = findParagraph(this, pos, options);
|
||||
return wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options);
|
||||
});
|
||||
|
||||
CodeMirror.commands.wrapLines = function(cm) {
|
||||
cm.operation(function() {
|
||||
var ranges = cm.listSelections(), at = cm.lastLine() + 1;
|
||||
for (var i = ranges.length - 1; i >= 0; i--) {
|
||||
var range = ranges[i], span;
|
||||
if (range.empty()) {
|
||||
var para = findParagraph(cm, range.head, {});
|
||||
span = {from: Pos(para.from, 0), to: Pos(para.to - 1)};
|
||||
} else {
|
||||
span = {from: range.from(), to: range.to()};
|
||||
}
|
||||
if (span.to.line >= at) continue;
|
||||
at = span.from.line;
|
||||
wrapRange(cm, span.from, span.to, {});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
CodeMirror.defineExtension("wrapRange", function(from, to, options) {
|
||||
return wrapRange(this, from, to, options || {});
|
||||
});
|
||||
|
||||
CodeMirror.defineExtension("wrapParagraphsInRange", function(from, to, options) {
|
||||
options = options || {};
|
||||
var cm = this, paras = [];
|
||||
for (var line = from.line; line <= to.line;) {
|
||||
var para = findParagraph(cm, Pos(line, 0), options);
|
||||
paras.push(para);
|
||||
line = para.to;
|
||||
}
|
||||
var madeChange = false;
|
||||
if (paras.length) cm.operation(function() {
|
||||
for (var i = paras.length - 1; i >= 0; --i)
|
||||
madeChange = madeChange || wrapRange(cm, Pos(paras[i].from, 0), Pos(paras[i].to - 1), options);
|
||||
});
|
||||
return madeChange;
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user