mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge fx-team to m-c
This commit is contained in:
commit
86e4fa5ab2
@ -145,11 +145,10 @@
|
||||
<body><![CDATA[
|
||||
// we always set the src on click if it has not been set for this tab,
|
||||
// but we only want to open the panel if it was previously annotated.
|
||||
let openPanel = this.isMarked || aOpenPanel;
|
||||
let openPanel = this.isMarked || aOpenPanel || !this.provider.haveLoggedInUser();
|
||||
let src = this.getAttribute("src");
|
||||
if (!src || src == "about:blank") {
|
||||
this.loadPanel();
|
||||
this.isMarked = true;
|
||||
}
|
||||
if (openPanel)
|
||||
this.panel.openPopup(this, "bottomcenter topright", 0, 0, false, false);
|
||||
@ -170,7 +169,6 @@
|
||||
// previous url when it is closed.
|
||||
this.setAttribute("src", "about:blank");
|
||||
this.loadPanel({ url: aUrl });
|
||||
this.isMarked = true;
|
||||
this.panel.openPopup(this, "bottomcenter topright", 0, 0, false, false);
|
||||
this.panel.addEventListener("popuphidden", function _hidden() {
|
||||
this.panel.removeEventListener("popuphidden", _hidden);
|
||||
|
@ -199,6 +199,7 @@ var tests = {
|
||||
EventUtils.synthesizeMouseAtCenter(btn, {});
|
||||
// wait for the button to be marked, click to open panel
|
||||
waitForCondition(function() btn.isMarked, function() {
|
||||
is(btn.panel.state, "closed", "panel should not be visible yet");
|
||||
EventUtils.synthesizeMouseAtCenter(btn, {});
|
||||
}, "button is marked");
|
||||
break;
|
||||
@ -214,7 +215,69 @@ var tests = {
|
||||
// page should no longer be marked
|
||||
port.close();
|
||||
waitForCondition(function() !btn.isMarked, function() {
|
||||
// after closing the addons tab, verify provider is still installed
|
||||
// cleanup after the page has been unmarked
|
||||
gBrowser.tabContainer.addEventListener("TabClose", function onTabClose() {
|
||||
gBrowser.tabContainer.removeEventListener("TabClose", onTabClose);
|
||||
executeSoon(function () {
|
||||
ok(btn.disabled, "button is disabled");
|
||||
next();
|
||||
});
|
||||
});
|
||||
gBrowser.removeTab(tab);
|
||||
}, "button unmarked");
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
port.postMessage({topic: "test-init"});
|
||||
});
|
||||
},
|
||||
|
||||
testMarkPanelLoggedOut: function(next) {
|
||||
// click on panel to open and wait for visibility
|
||||
let provider = Social._getProviderFromOrigin(manifest2.origin);
|
||||
ok(provider.enabled, "provider is enabled");
|
||||
let id = "social-mark-button-" + provider.origin;
|
||||
let btn = document.getElementById(id)
|
||||
ok(btn, "got a mark button");
|
||||
let port = provider.getWorkerPort();
|
||||
ok(port, "got a port");
|
||||
|
||||
// verify markbutton is disabled when there is no browser url
|
||||
ok(btn.disabled, "button is disabled");
|
||||
let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html"
|
||||
addTab(activationURL, function(tab) {
|
||||
ok(!btn.disabled, "button is enabled");
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init-done":
|
||||
ok(true, "test-init-done received");
|
||||
ok(provider.profile.userName, "profile was set by test worker");
|
||||
port.postMessage({topic: "test-logout"});
|
||||
waitForCondition(function() !provider.profile.userName,
|
||||
function() {
|
||||
// when the provider has not indicated to us that a user is
|
||||
// logged in, the first click opens the page.
|
||||
EventUtils.synthesizeMouseAtCenter(btn, {});
|
||||
},
|
||||
"profile was unset by test worker");
|
||||
break;
|
||||
case "got-social-panel-visibility":
|
||||
ok(true, "got the panel message " + e.data.result);
|
||||
if (e.data.result == "shown") {
|
||||
// our test marks the page during the load event (see
|
||||
// social_mark.html) regardless of login state, unmark the page
|
||||
// via the button in the page
|
||||
let doc = btn.contentDocument;
|
||||
let unmarkBtn = doc.getElementById("unmark");
|
||||
ok(unmarkBtn, "got the panel unmark button");
|
||||
EventUtils.sendMouseEvent({type: "click"}, unmarkBtn, btn.contentWindow);
|
||||
} else {
|
||||
// page should no longer be marked
|
||||
port.close();
|
||||
waitForCondition(function() !btn.isMarked, function() {
|
||||
// cleanup after the page has been unmarked
|
||||
gBrowser.tabContainer.addEventListener("TabClose", function onTabClose() {
|
||||
gBrowser.tabContainer.removeEventListener("TabClose", onTabClose);
|
||||
executeSoon(function () {
|
||||
|
@ -59,6 +59,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
|
||||
"resource://gre/modules/DownloadUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "OS",
|
||||
"resource://gre/modules/osfile.jsm")
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
|
||||
@ -668,6 +670,27 @@ DownloadsDataCtor.prototype = {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// This state transition code should actually be located in a Downloads
|
||||
// API module (bug 941009). Moreover, the fact that state is stored as
|
||||
// annotations should be ideally hidden behind methods of
|
||||
// nsIDownloadHistory (bug 830415).
|
||||
if (!this._isPrivate && !aDataItem.inProgress) {
|
||||
try {
|
||||
let downloadMetaData = { state: aDataItem.state,
|
||||
endTime: aDataItem.endTime };
|
||||
if (aDataItem.done) {
|
||||
downloadMetaData.fileSize = aDataItem.maxBytes;
|
||||
}
|
||||
|
||||
PlacesUtils.annotations.setPageAnnotation(
|
||||
NetUtil.newURI(aDataItem.uri), "downloads/metaData",
|
||||
JSON.stringify(downloadMetaData), 0,
|
||||
PlacesUtils.annotations.EXPIRE_WITH_HISTORY);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!aDataItem.newDownloadNotified) {
|
||||
@ -858,10 +881,26 @@ DownloadsDataItem.prototype = {
|
||||
this.referrer = this._download.source.referrer;
|
||||
this.startTime = this._download.startTime;
|
||||
this.currBytes = this._download.currentBytes;
|
||||
this.maxBytes = this._download.totalBytes;
|
||||
this.resumable = this._download.hasPartialData;
|
||||
this.speed = this._download.speed;
|
||||
this.percentComplete = this._download.progress;
|
||||
|
||||
if (this._download.succeeded) {
|
||||
// If the download succeeded, show the final size if available, otherwise
|
||||
// use the last known number of bytes transferred. The final size on disk
|
||||
// will be available when bug 941063 is resolved.
|
||||
this.maxBytes = this._download.hasProgress ?
|
||||
this._download.totalBytes :
|
||||
this._download.currentBytes;
|
||||
this.percentComplete = 100;
|
||||
} else if (this._download.hasProgress) {
|
||||
// If the final size and progress are known, use them.
|
||||
this.maxBytes = this._download.totalBytes;
|
||||
this.percentComplete = this._download.progress;
|
||||
} else {
|
||||
// The download final size and progress percentage is unknown.
|
||||
this.maxBytes = -1;
|
||||
this.percentComplete = -1;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,7 @@ code, and optionally help with indentation.
|
||||
|
||||
# Upgrade
|
||||
|
||||
Currently used version is 3.15. To upgrade, download a new version of
|
||||
Currently used version is 3.20. To upgrade, download a new version of
|
||||
CodeMirror from the project's page [1] and replace all JavaScript and
|
||||
CSS files inside the codemirror directory [2].
|
||||
|
||||
|
@ -74,7 +74,6 @@
|
||||
.cm-s-default .cm-string {color: #a11;}
|
||||
.cm-s-default .cm-string-2 {color: #f50;}
|
||||
.cm-s-default .cm-meta {color: #555;}
|
||||
.cm-s-default .cm-error {color: #f00;}
|
||||
.cm-s-default .cm-qualifier {color: #555;}
|
||||
.cm-s-default .cm-builtin {color: #30a;}
|
||||
.cm-s-default .cm-bracket {color: #997;}
|
||||
@ -91,10 +90,12 @@
|
||||
.cm-em {font-style: italic;}
|
||||
.cm-link {text-decoration: underline;}
|
||||
|
||||
.cm-s-default .cm-error {color: #f00;}
|
||||
.cm-invalidchar {color: #f00;}
|
||||
|
||||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
.CodeMirror-activeline-background {background: #e8f2ff;}
|
||||
|
||||
/* STOP */
|
||||
|
||||
@ -117,6 +118,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
height: 100%;
|
||||
outline: none; /* Prevent dragging from highlighting the element */
|
||||
position: relative;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
.CodeMirror-sizer {
|
||||
position: relative;
|
||||
@ -155,6 +158,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
.CodeMirror-gutter {
|
||||
white-space: normal;
|
||||
height: 100%;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
padding-bottom: 30px;
|
||||
margin-bottom: -32px;
|
||||
display: inline-block;
|
||||
@ -214,8 +219,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.CodeMirror-widget {
|
||||
}
|
||||
.CodeMirror-widget {}
|
||||
|
||||
.CodeMirror-wrap .CodeMirror-scroll {
|
||||
overflow-x: hidden;
|
||||
@ -223,7 +227,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
|
||||
.CodeMirror-measure {
|
||||
position: absolute;
|
||||
width: 100%; height: 0px;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
// CodeMirror version 3.15
|
||||
|
||||
// CodeMirror version 3.20
|
||||
//
|
||||
// CodeMirror is the only global var we claim
|
||||
window.CodeMirror = (function() {
|
||||
"use strict";
|
||||
|
||||
@ -8,9 +9,13 @@ window.CodeMirror = (function() {
|
||||
// Crude, but necessary to handle a number of hard-to-feature-detect
|
||||
// bugs and behavior differences.
|
||||
var gecko = /gecko\/\d/i.test(navigator.userAgent);
|
||||
// IE11 currently doesn't count as 'ie', since it has almost none of
|
||||
// the same bugs as earlier versions. Use ie_gt10 to handle
|
||||
// incompatibilities in that version.
|
||||
var ie = /MSIE \d/.test(navigator.userAgent);
|
||||
var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8);
|
||||
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
|
||||
var ie_gt10 = /Trident\/([7-9]|\d{2,})\./.test(navigator.userAgent);
|
||||
var webkit = /WebKit\//.test(navigator.userAgent);
|
||||
var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
|
||||
var chrome = /Chrome\//.test(navigator.userAgent);
|
||||
@ -25,7 +30,7 @@ window.CodeMirror = (function() {
|
||||
// This is woefully incomplete. Suggestions for alternative methods welcome.
|
||||
var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
|
||||
var mac = ios || /Mac/.test(navigator.platform);
|
||||
var windows = /windows/i.test(navigator.platform);
|
||||
var windows = /win/i.test(navigator.platform);
|
||||
|
||||
var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
|
||||
if (opera_version) opera_version = Number(opera_version[1]);
|
||||
@ -305,15 +310,13 @@ window.CodeMirror = (function() {
|
||||
// Make sure the gutters options contains the element
|
||||
// "CodeMirror-linenumbers" when the lineNumbers option is true.
|
||||
function setGuttersForLineNumbers(options) {
|
||||
var found = false;
|
||||
for (var i = 0; i < options.gutters.length; ++i) {
|
||||
if (options.gutters[i] == "CodeMirror-linenumbers") {
|
||||
if (options.lineNumbers) found = true;
|
||||
else options.gutters.splice(i--, 1);
|
||||
}
|
||||
var found = indexOf(options.gutters, "CodeMirror-linenumbers");
|
||||
if (found == -1 && options.lineNumbers) {
|
||||
options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]);
|
||||
} else if (found > -1 && !options.lineNumbers) {
|
||||
options.gutters = options.gutters.slice(0);
|
||||
options.gutters.splice(found, 1);
|
||||
}
|
||||
if (!found && options.lineNumbers)
|
||||
options.gutters.push("CodeMirror-linenumbers");
|
||||
}
|
||||
|
||||
// SCROLLBARS
|
||||
@ -333,13 +336,19 @@ window.CodeMirror = (function() {
|
||||
d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
|
||||
d.scrollbarV.firstChild.style.height =
|
||||
(scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
|
||||
} else d.scrollbarV.style.display = "";
|
||||
} else {
|
||||
d.scrollbarV.style.display = "";
|
||||
d.scrollbarV.firstChild.style.height = "0";
|
||||
}
|
||||
if (needsH) {
|
||||
d.scrollbarH.style.display = "block";
|
||||
d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
|
||||
d.scrollbarH.firstChild.style.width =
|
||||
(d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
|
||||
} else d.scrollbarH.style.display = "";
|
||||
} else {
|
||||
d.scrollbarH.style.display = "";
|
||||
d.scrollbarH.firstChild.style.width = "0";
|
||||
}
|
||||
if (needsH && needsV) {
|
||||
d.scrollbarFiller.style.display = "block";
|
||||
d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
|
||||
@ -350,8 +359,10 @@ window.CodeMirror = (function() {
|
||||
d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
|
||||
} else d.gutterFiller.style.display = "";
|
||||
|
||||
if (mac_geLion && scrollbarWidth(d.measure) === 0)
|
||||
if (mac_geLion && scrollbarWidth(d.measure) === 0) {
|
||||
d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
|
||||
d.scrollbarV.style.pointerEvents = d.scrollbarH.style.pointerEvents = "none";
|
||||
}
|
||||
}
|
||||
|
||||
function visibleLines(display, doc, viewPort) {
|
||||
@ -406,12 +417,18 @@ window.CodeMirror = (function() {
|
||||
function updateDisplay(cm, changes, viewPort, forced) {
|
||||
var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
|
||||
var visible = visibleLines(cm.display, cm.doc, viewPort);
|
||||
for (;;) {
|
||||
for (var first = true;; first = false) {
|
||||
var oldWidth = cm.display.scroller.clientWidth;
|
||||
if (!updateDisplayInner(cm, changes, visible, forced)) break;
|
||||
forced = false;
|
||||
updated = true;
|
||||
changes = [];
|
||||
updateSelection(cm);
|
||||
updateScrollbars(cm);
|
||||
if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) {
|
||||
forced = true;
|
||||
continue;
|
||||
}
|
||||
forced = false;
|
||||
|
||||
// Clip forced viewport to actual scrollable area
|
||||
if (viewPort)
|
||||
@ -420,7 +437,6 @@ window.CodeMirror = (function() {
|
||||
visible = visibleLines(cm.display, cm.doc, viewPort);
|
||||
if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)
|
||||
break;
|
||||
changes = [];
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
@ -456,7 +472,7 @@ window.CodeMirror = (function() {
|
||||
var positionsChangedFrom = Infinity;
|
||||
if (cm.options.lineNumbers)
|
||||
for (var i = 0; i < changes.length; ++i)
|
||||
if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
|
||||
if (changes[i].diff && changes[i].from < positionsChangedFrom) { positionsChangedFrom = changes[i].from; }
|
||||
|
||||
var end = doc.first + doc.size;
|
||||
var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
|
||||
@ -613,7 +629,7 @@ window.CodeMirror = (function() {
|
||||
if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
|
||||
if (lineIsHidden(cm.doc, line)) {
|
||||
if (line.height != 0) updateLineHeight(line, 0);
|
||||
if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
|
||||
if (line.widgets && cur && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
|
||||
var w = line.widgets[i];
|
||||
if (w.showIfHidden) {
|
||||
var prev = cur.previousSibling;
|
||||
@ -658,10 +674,11 @@ window.CodeMirror = (function() {
|
||||
}
|
||||
|
||||
function buildLineElement(cm, line, lineNo, dims, reuse) {
|
||||
var lineElement = lineContent(cm, line);
|
||||
var built = buildLineContent(cm, line), lineElement = built.pre;
|
||||
var markers = line.gutterMarkers, display = cm.display, wrap;
|
||||
|
||||
if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets)
|
||||
var bgClass = built.bgClass ? built.bgClass + " " + (line.bgClass || "") : line.bgClass;
|
||||
if (!cm.options.lineNumbers && !markers && !bgClass && !line.wrapClass && !line.widgets)
|
||||
return lineElement;
|
||||
|
||||
// Lines with gutter elements, widgets or a background class need
|
||||
@ -699,8 +716,8 @@ window.CodeMirror = (function() {
|
||||
wrap.appendChild(lineElement);
|
||||
}
|
||||
// Kludge to make sure the styled element lies behind the selection (by z-index)
|
||||
if (line.bgClass)
|
||||
wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild);
|
||||
if (bgClass)
|
||||
wrap.insertBefore(elt("div", null, bgClass + " CodeMirror-linebackground"), wrap.firstChild);
|
||||
if (cm.options.lineNumbers || markers) {
|
||||
var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
|
||||
(cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
|
||||
@ -872,9 +889,10 @@ window.CodeMirror = (function() {
|
||||
clearInterval(display.blinker);
|
||||
var on = true;
|
||||
display.cursor.style.visibility = display.otherCursor.style.visibility = "";
|
||||
display.blinker = setInterval(function() {
|
||||
display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
|
||||
}, cm.options.cursorBlinkRate);
|
||||
if (cm.options.cursorBlinkRate > 0)
|
||||
display.blinker = setInterval(function() {
|
||||
display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
|
||||
}, cm.options.cursorBlinkRate);
|
||||
}
|
||||
|
||||
// HIGHLIGHT WORKER
|
||||
@ -894,7 +912,7 @@ window.CodeMirror = (function() {
|
||||
doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
|
||||
if (doc.frontier >= cm.display.showingFrom) { // Visible
|
||||
var oldStyles = line.styles;
|
||||
line.styles = highlightLine(cm, line, state);
|
||||
line.styles = highlightLine(cm, line, state, true);
|
||||
var ischange = !oldStyles || oldStyles.length != line.styles.length;
|
||||
for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
|
||||
if (ischange) {
|
||||
@ -903,7 +921,7 @@ window.CodeMirror = (function() {
|
||||
}
|
||||
line.stateAfter = copyState(doc.mode, state);
|
||||
} else {
|
||||
processLine(cm, line, state);
|
||||
processLine(cm, line.text, state);
|
||||
line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
|
||||
}
|
||||
++doc.frontier;
|
||||
@ -926,7 +944,8 @@ window.CodeMirror = (function() {
|
||||
// parse correctly.
|
||||
function findStartLine(cm, n, precise) {
|
||||
var minindent, minline, doc = cm.doc;
|
||||
for (var search = n, lim = n - 100; search > lim; --search) {
|
||||
var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
|
||||
for (var search = n; search > lim; --search) {
|
||||
if (search <= doc.first) return doc.first;
|
||||
var line = getLine(doc, search - 1);
|
||||
if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
|
||||
@ -941,16 +960,17 @@ window.CodeMirror = (function() {
|
||||
|
||||
function getStateBefore(cm, n, precise) {
|
||||
var doc = cm.doc, display = cm.display;
|
||||
if (!doc.mode.startState) return true;
|
||||
if (!doc.mode.startState) return true;
|
||||
var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
|
||||
if (!state) state = startState(doc.mode);
|
||||
else state = copyState(doc.mode, state);
|
||||
doc.iter(pos, n, function(line) {
|
||||
processLine(cm, line, state);
|
||||
processLine(cm, line.text, state);
|
||||
var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;
|
||||
line.stateAfter = save ? copyState(doc.mode, state) : null;
|
||||
++pos;
|
||||
});
|
||||
if (precise) doc.frontier = pos;
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -966,6 +986,10 @@ window.CodeMirror = (function() {
|
||||
function measureChar(cm, line, ch, data, bias) {
|
||||
var dir = -1;
|
||||
data = data || measureLine(cm, line);
|
||||
if (data.crude) {
|
||||
var left = data.left + ch * data.width;
|
||||
return {left: left, right: left + data.width, top: data.top, bottom: data.bottom};
|
||||
}
|
||||
|
||||
for (var pos = ch;; pos += dir) {
|
||||
var r = data[pos];
|
||||
@ -987,7 +1011,7 @@ window.CodeMirror = (function() {
|
||||
var memo = cache[i];
|
||||
if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
|
||||
cm.display.scroller.clientWidth == memo.width &&
|
||||
memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
|
||||
memo.classes == line.textClass + "|" + line.wrapClass)
|
||||
return memo;
|
||||
}
|
||||
}
|
||||
@ -1007,15 +1031,18 @@ window.CodeMirror = (function() {
|
||||
var cache = cm.display.measureLineCache;
|
||||
var memo = {text: line.text, width: cm.display.scroller.clientWidth,
|
||||
markedSpans: line.markedSpans, measure: measure,
|
||||
classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
|
||||
classes: line.textClass + "|" + line.wrapClass};
|
||||
if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
|
||||
else cache.push(memo);
|
||||
return measure;
|
||||
}
|
||||
|
||||
function measureLineInner(cm, line) {
|
||||
if (!cm.options.lineWrapping && line.text.length >= cm.options.crudeMeasuringFrom)
|
||||
return crudelyMeasureLine(cm, line);
|
||||
|
||||
var display = cm.display, measure = emptyArray(line.text.length);
|
||||
var pre = lineContent(cm, line, measure, true);
|
||||
var pre = buildLineContent(cm, line, measure, true).pre;
|
||||
|
||||
// IE does not cache element positions of inline elements between
|
||||
// calls to getBoundingClientRect. This makes the loop below,
|
||||
@ -1091,6 +1118,7 @@ window.CodeMirror = (function() {
|
||||
if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
|
||||
if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
|
||||
}
|
||||
removeChildren(cm.display.measure);
|
||||
for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
|
||||
finishRect(cur);
|
||||
if (cur.leftSide) finishRect(cur.leftSide);
|
||||
@ -1099,6 +1127,15 @@ window.CodeMirror = (function() {
|
||||
return data;
|
||||
}
|
||||
|
||||
function crudelyMeasureLine(cm, line) {
|
||||
var copy = new Line(line.text.slice(0, 100), null);
|
||||
if (line.textClass) copy.textClass = line.textClass;
|
||||
var measure = measureLineInner(cm, copy);
|
||||
var left = measureChar(cm, copy, 0, measure, "left");
|
||||
var right = measureChar(cm, copy, 99, measure, "right");
|
||||
return {crude: true, top: left.top, left: left.left, bottom: left.bottom, width: (right.right - left.left) / 100};
|
||||
}
|
||||
|
||||
function measureLineWidth(cm, line) {
|
||||
var hasBadSpan = false;
|
||||
if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {
|
||||
@ -1106,9 +1143,10 @@ window.CodeMirror = (function() {
|
||||
if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
|
||||
}
|
||||
var cached = !hasBadSpan && findCachedMeasurement(cm, line);
|
||||
if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;
|
||||
if (cached || line.text.length >= cm.options.crudeMeasuringFrom)
|
||||
return measureChar(cm, line, line.text.length, cached && cached.measure, "right").right;
|
||||
|
||||
var pre = lineContent(cm, line, null, true);
|
||||
var pre = buildLineContent(cm, line, null, true).pre;
|
||||
var end = pre.appendChild(zeroWidthElement(cm.display.measure));
|
||||
removeChildrenAndAdd(cm.display.measure, pre);
|
||||
return getRect(end).right - getRect(cm.display.lineDiv).left;
|
||||
@ -1351,11 +1389,14 @@ window.CodeMirror = (function() {
|
||||
}
|
||||
if (!updated && op.selectionChanged) updateSelection(cm);
|
||||
if (op.updateScrollPos) {
|
||||
display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
|
||||
display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
|
||||
var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, newScrollPos.scrollTop));
|
||||
var left = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, newScrollPos.scrollLeft));
|
||||
display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = top;
|
||||
display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = left;
|
||||
alignHorizontally(cm);
|
||||
if (op.scrollToPos)
|
||||
scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin);
|
||||
scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos.from),
|
||||
clipPos(cm.doc, op.scrollToPos.to), op.scrollToPos.margin);
|
||||
} else if (newScrollPos) {
|
||||
scrollCursorIntoView(cm);
|
||||
}
|
||||
@ -1443,6 +1484,10 @@ window.CodeMirror = (function() {
|
||||
function readInput(cm) {
|
||||
var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
|
||||
if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
|
||||
if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
|
||||
input.value = input.value.substring(0, input.value.length - 1);
|
||||
cm.state.fakedLastChar = false;
|
||||
}
|
||||
var text = input.value;
|
||||
if (text == prevInput && posEq(sel.from, sel.to)) return false;
|
||||
if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
|
||||
@ -1573,7 +1618,10 @@ window.CodeMirror = (function() {
|
||||
if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
|
||||
if (e.keyCode == 16) cm.doc.sel.shift = false;
|
||||
}));
|
||||
on(d.input, "input", bind(fastPoll, cm));
|
||||
on(d.input, "input", function() {
|
||||
if (ie && !ie_lt9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;
|
||||
fastPoll(cm);
|
||||
});
|
||||
on(d.input, "keydown", operation(cm, onKeyDown));
|
||||
on(d.input, "keypress", operation(cm, onKeyPress));
|
||||
on(d.input, "focus", bind(onFocus, cm));
|
||||
@ -1589,12 +1637,22 @@ window.CodeMirror = (function() {
|
||||
on(d.scroller, "dragover", drag_);
|
||||
on(d.scroller, "drop", operation(cm, onDrop));
|
||||
}
|
||||
on(d.scroller, "paste", function(e){
|
||||
on(d.scroller, "paste", function(e) {
|
||||
if (eventInWidget(d, e)) return;
|
||||
focusInput(cm);
|
||||
fastPoll(cm);
|
||||
});
|
||||
on(d.input, "paste", function() {
|
||||
// Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
|
||||
// Add a char to the end of textarea before paste occur so that
|
||||
// selection doesn't span to the end of textarea.
|
||||
if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {
|
||||
var start = d.input.selectionStart, end = d.input.selectionEnd;
|
||||
d.input.value += "$";
|
||||
d.input.selectionStart = start;
|
||||
d.input.selectionEnd = end;
|
||||
cm.state.fakedLastChar = true;
|
||||
}
|
||||
cm.state.pasteIncoming = true;
|
||||
fastPoll(cm);
|
||||
});
|
||||
@ -1658,6 +1716,7 @@ window.CodeMirror = (function() {
|
||||
if (captureMiddleClick) onContextMenu.call(cm, cm, e);
|
||||
return;
|
||||
case 2:
|
||||
if (webkit) cm.state.lastMiddleDown = +new Date;
|
||||
if (start) extendSelection(cm.doc, start);
|
||||
setTimeout(bind(focusInput, cm), 20);
|
||||
e_preventDefault(e);
|
||||
@ -1778,17 +1837,16 @@ window.CodeMirror = (function() {
|
||||
on(document, "mouseup", up);
|
||||
}
|
||||
|
||||
function clickInGutter(cm, e) {
|
||||
var display = cm.display;
|
||||
function gutterEvent(cm, e, type, prevent, signalfn) {
|
||||
try { var mX = e.clientX, mY = e.clientY; }
|
||||
catch(e) { return false; }
|
||||
if (mX >= Math.floor(getRect(cm.display.gutters).right)) return false;
|
||||
if (prevent) e_preventDefault(e);
|
||||
|
||||
if (mX >= Math.floor(getRect(display.gutters).right)) return false;
|
||||
e_preventDefault(e);
|
||||
if (!hasHandler(cm, "gutterClick")) return true;
|
||||
|
||||
var display = cm.display;
|
||||
var lineBox = getRect(display.lineDiv);
|
||||
if (mY > lineBox.bottom) return true;
|
||||
|
||||
if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);
|
||||
mY -= lineBox.top - display.viewOffset;
|
||||
|
||||
for (var i = 0; i < cm.options.gutters.length; ++i) {
|
||||
@ -1796,11 +1854,19 @@ window.CodeMirror = (function() {
|
||||
if (g && getRect(g).right >= mX) {
|
||||
var line = lineAtHeight(cm.doc, mY);
|
||||
var gutter = cm.options.gutters[i];
|
||||
signalLater(cm, "gutterClick", cm, line, gutter, e);
|
||||
break;
|
||||
signalfn(cm, type, cm, line, gutter, e);
|
||||
return e_defaultPrevented(e);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function contextMenuInGutter(cm, e) {
|
||||
if (!hasHandler(cm, "gutterContextMenu")) return false;
|
||||
return gutterEvent(cm, e, "gutterContextMenu", false, signal);
|
||||
}
|
||||
|
||||
function clickInGutter(cm, e) {
|
||||
return gutterEvent(cm, e, "gutterClick", true, signalLater);
|
||||
}
|
||||
|
||||
// Kludge to work around strange IE behavior where it'll sometimes
|
||||
@ -1845,7 +1911,6 @@ window.CodeMirror = (function() {
|
||||
if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste");
|
||||
cm.replaceSelection(text, null, "paste");
|
||||
focusInput(cm);
|
||||
onFocus(cm);
|
||||
}
|
||||
}
|
||||
catch(e){}
|
||||
@ -1863,6 +1928,7 @@ window.CodeMirror = (function() {
|
||||
// Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
|
||||
if (e.dataTransfer.setDragImage && !safari) {
|
||||
var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
|
||||
img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
|
||||
if (opera) {
|
||||
img.width = img.height = 1;
|
||||
cm.display.wrapper.appendChild(img);
|
||||
@ -2061,8 +2127,8 @@ window.CodeMirror = (function() {
|
||||
function onKeyDown(e) {
|
||||
var cm = this;
|
||||
if (!cm.state.focused) onFocus(cm);
|
||||
if (ie && e.keyCode == 27) { e.returnValue = false; }
|
||||
if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
|
||||
if (ie && e.keyCode == 27) e.returnValue = false;
|
||||
var code = e.keyCode;
|
||||
// IE does strange things with escape.
|
||||
cm.doc.sel.shift = code == 16 || e.shiftKey;
|
||||
@ -2099,7 +2165,10 @@ window.CodeMirror = (function() {
|
||||
cm.state.focused = true;
|
||||
if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
|
||||
cm.display.wrapper.className += " CodeMirror-focused";
|
||||
resetInput(cm, true);
|
||||
if (!cm.curOp) {
|
||||
resetInput(cm, true);
|
||||
if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730
|
||||
}
|
||||
}
|
||||
slowPoll(cm);
|
||||
restartBlink(cm);
|
||||
@ -2118,11 +2187,15 @@ window.CodeMirror = (function() {
|
||||
function onContextMenu(cm, e) {
|
||||
if (signalDOMEvent(cm, e, "contextmenu")) return;
|
||||
var display = cm.display, sel = cm.doc.sel;
|
||||
if (eventInWidget(display, e)) return;
|
||||
if (eventInWidget(display, e) || contextMenuInGutter(cm, e)) return;
|
||||
|
||||
var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
|
||||
if (!pos || opera) return; // Opera is difficult.
|
||||
if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
|
||||
|
||||
// Reset the current text selection only if the click is done outside of the selection
|
||||
// and 'resetSelectionOnContextMenu' option is true.
|
||||
var reset = cm.options.resetSelectionOnContextMenu;
|
||||
if (reset && (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)))
|
||||
operation(cm, setSelection)(cm.doc, pos, pos);
|
||||
|
||||
var oldCSS = display.input.style.cssText;
|
||||
@ -2137,8 +2210,8 @@ window.CodeMirror = (function() {
|
||||
|
||||
function prepareSelectAllHack() {
|
||||
if (display.input.selectionStart != null) {
|
||||
var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value);
|
||||
display.prevInput = " ";
|
||||
var extval = display.input.value = "\u200b" + (posEq(sel.from, sel.to) ? "" : display.input.value);
|
||||
display.prevInput = "\u200b";
|
||||
display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
|
||||
}
|
||||
}
|
||||
@ -2272,6 +2345,7 @@ window.CodeMirror = (function() {
|
||||
}
|
||||
|
||||
function makeChangeNoReadonly(doc, change, selUpdate) {
|
||||
if (change.text.length == 1 && change.text[0] == "" && posEq(change.from, change.to)) return;
|
||||
var selAfter = computeSelAfterChange(doc, change, selUpdate);
|
||||
addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
|
||||
|
||||
@ -2494,6 +2568,7 @@ window.CodeMirror = (function() {
|
||||
|
||||
var sel = doc.sel;
|
||||
sel.goalColumn = null;
|
||||
if (bias == null) bias = posLess(head, sel.head) ? -1 : 1;
|
||||
// Skip over atomic spans.
|
||||
if (checkAtomic || !posEq(anchor, sel.anchor))
|
||||
anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push");
|
||||
@ -2571,7 +2646,7 @@ window.CodeMirror = (function() {
|
||||
// SCROLLING
|
||||
|
||||
function scrollCursorIntoView(cm) {
|
||||
var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin);
|
||||
var coords = scrollPosIntoView(cm, cm.doc.sel.head, null, cm.options.cursorScrollMargin);
|
||||
if (!cm.state.focused) return;
|
||||
var display = cm.display, box = getRect(display.sizer), doScroll = null;
|
||||
if (coords.top + box.top < 0) doScroll = true;
|
||||
@ -2588,11 +2663,15 @@ window.CodeMirror = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
function scrollPosIntoView(cm, pos, margin) {
|
||||
function scrollPosIntoView(cm, pos, end, margin) {
|
||||
if (margin == null) margin = 0;
|
||||
for (;;) {
|
||||
var changed = false, coords = cursorCoords(cm, pos);
|
||||
var scrollPos = calculateScrollPos(cm, coords.left, coords.top - margin, coords.left, coords.bottom + margin);
|
||||
var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
|
||||
var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
|
||||
Math.min(coords.top, endCoords.top) - margin,
|
||||
Math.max(coords.left, endCoords.left),
|
||||
Math.max(coords.bottom, endCoords.bottom) + margin);
|
||||
var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
|
||||
if (scrollPos.scrollTop != null) {
|
||||
setScrollTop(cm, scrollPos.scrollTop);
|
||||
@ -2689,6 +2768,8 @@ window.CodeMirror = (function() {
|
||||
|
||||
if (indentString != curSpaceString)
|
||||
replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
|
||||
else if (doc.sel.head.line == n && doc.sel.head.ch < curSpaceString.length)
|
||||
setSelection(doc, Pos(n, curSpaceString.length), Pos(n, curSpaceString.length), 1);
|
||||
line.stateAfter = null;
|
||||
}
|
||||
|
||||
@ -2789,7 +2870,7 @@ window.CodeMirror = (function() {
|
||||
|
||||
CodeMirror.prototype = {
|
||||
constructor: CodeMirror,
|
||||
focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
|
||||
focus: function(){window.focus(); focusInput(this); fastPoll(this);},
|
||||
|
||||
setOption: function(option, value) {
|
||||
var options = this.options, old = options[option];
|
||||
@ -3110,17 +3191,23 @@ window.CodeMirror = (function() {
|
||||
clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
|
||||
},
|
||||
|
||||
scrollIntoView: operation(null, function(pos, margin) {
|
||||
if (typeof pos == "number") pos = Pos(pos, 0);
|
||||
scrollIntoView: operation(null, function(range, margin) {
|
||||
if (range == null) range = {from: this.doc.sel.head, to: null};
|
||||
else if (typeof range == "number") range = {from: Pos(range, 0), to: null};
|
||||
else if (range.from == null) range = {from: range, to: null};
|
||||
if (!range.to) range.to = range.from;
|
||||
if (!margin) margin = 0;
|
||||
var coords = pos;
|
||||
|
||||
if (!pos || pos.line != null) {
|
||||
this.curOp.scrollToPos = pos ? clipPos(this.doc, pos) : this.doc.sel.head;
|
||||
this.curOp.scrollToPosMargin = margin;
|
||||
coords = cursorCoords(this, this.curOp.scrollToPos);
|
||||
var coords = range;
|
||||
if (range.from.line != null) {
|
||||
this.curOp.scrollToPos = {from: range.from, to: range.to, margin: margin};
|
||||
coords = {from: cursorCoords(this, range.from),
|
||||
to: cursorCoords(this, range.to)};
|
||||
}
|
||||
var sPos = calculateScrollPos(this, coords.left, coords.top - margin, coords.right, coords.bottom + margin);
|
||||
var sPos = calculateScrollPos(this, Math.min(coords.from.left, coords.to.left),
|
||||
Math.min(coords.from.top, coords.to.top) - margin,
|
||||
Math.max(coords.from.right, coords.to.right),
|
||||
Math.max(coords.from.bottom, coords.to.bottom) + margin);
|
||||
updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
|
||||
}),
|
||||
|
||||
@ -3138,9 +3225,11 @@ window.CodeMirror = (function() {
|
||||
operation: function(f){return runInOp(this, f);},
|
||||
|
||||
refresh: operation(null, function() {
|
||||
var badHeight = this.display.cachedTextHeight == null;
|
||||
clearCaches(this);
|
||||
updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop);
|
||||
regChange(this);
|
||||
if (badHeight) estimateLineHeights(this);
|
||||
}),
|
||||
|
||||
swapDoc: operation(null, function(doc) {
|
||||
@ -3150,6 +3239,7 @@ window.CodeMirror = (function() {
|
||||
clearCaches(this);
|
||||
resetInput(this, true);
|
||||
updateScrollPos(this, doc.scrollLeft, doc.scrollTop);
|
||||
signalLater(this, "swapDoc", this, old);
|
||||
return old;
|
||||
}),
|
||||
|
||||
@ -3193,8 +3283,14 @@ window.CodeMirror = (function() {
|
||||
clearCaches(cm);
|
||||
regChange(cm);
|
||||
}, true);
|
||||
option("specialChars", /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/g, function(cm, val) {
|
||||
cm.options.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
|
||||
cm.refresh();
|
||||
}, true);
|
||||
option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
|
||||
option("electricChars", true);
|
||||
option("rtlMoveVisually", !windows);
|
||||
option("wholeLineUpdateBefore", true);
|
||||
|
||||
option("theme", "default", function(cm) {
|
||||
themeChanged(cm);
|
||||
@ -3224,9 +3320,17 @@ window.CodeMirror = (function() {
|
||||
option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
|
||||
option("showCursorWhenSelecting", false, updateSelection, true);
|
||||
|
||||
option("resetSelectionOnContextMenu", true);
|
||||
|
||||
option("readOnly", false, function(cm, val) {
|
||||
if (val == "nocursor") {onBlur(cm); cm.display.input.blur();}
|
||||
else if (!val) resetInput(cm, true);
|
||||
if (val == "nocursor") {
|
||||
onBlur(cm);
|
||||
cm.display.input.blur();
|
||||
cm.display.disabled = true;
|
||||
} else {
|
||||
cm.display.disabled = false;
|
||||
if (!val) resetInput(cm, true);
|
||||
}
|
||||
});
|
||||
option("dragDrop", true);
|
||||
|
||||
@ -3241,6 +3345,7 @@ window.CodeMirror = (function() {
|
||||
option("historyEventDelay", 500);
|
||||
option("viewportMargin", 10, function(cm){cm.refresh();}, true);
|
||||
option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true);
|
||||
option("crudeMeasuringFrom", 10000);
|
||||
option("moveInputWithCursor", true, function(cm, val) {
|
||||
if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
|
||||
});
|
||||
@ -3459,7 +3564,8 @@ window.CodeMirror = (function() {
|
||||
keyMap.basic = {
|
||||
"Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
|
||||
"End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
|
||||
"Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
|
||||
"Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
|
||||
"Tab": "defaultTab", "Shift-Tab": "indentAuto",
|
||||
"Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
|
||||
};
|
||||
// Note that the save and find-related commands aren't defined by
|
||||
@ -3730,9 +3836,10 @@ window.CodeMirror = (function() {
|
||||
TextMarker.prototype.changed = function() {
|
||||
var pos = this.find(), cm = this.doc.cm;
|
||||
if (!pos || !cm) return;
|
||||
var line = getLine(this.doc, pos.from.line);
|
||||
if (this.type != "bookmark") pos = pos.from;
|
||||
var line = getLine(this.doc, pos.line);
|
||||
clearCachedMeasurement(cm, line);
|
||||
if (pos.from.line >= cm.display.showingFrom && pos.from.line < cm.display.showingTo) {
|
||||
if (pos.line >= cm.display.showingFrom && pos.line < cm.display.showingTo) {
|
||||
for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
|
||||
if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
|
||||
break;
|
||||
@ -3764,7 +3871,9 @@ window.CodeMirror = (function() {
|
||||
if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
|
||||
|
||||
var marker = new TextMarker(doc, type);
|
||||
if (type == "range" && !posLess(from, to)) return marker;
|
||||
if (posLess(to, from) || posEq(from, to) && type == "range" &&
|
||||
!(options.inclusiveLeft && options.inclusiveRight))
|
||||
return marker;
|
||||
if (options) copyObj(options, marker);
|
||||
if (marker.replacedWith) {
|
||||
marker.collapsed = true;
|
||||
@ -3880,7 +3989,9 @@ window.CodeMirror = (function() {
|
||||
if (old) for (var i = 0, nw; i < old.length; ++i) {
|
||||
var span = old[i], marker = span.marker;
|
||||
var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
|
||||
if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
|
||||
if (startsBefore ||
|
||||
(marker.inclusiveLeft && marker.inclusiveRight || marker.type == "bookmark") &&
|
||||
span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
|
||||
var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
|
||||
(nw || (nw = [])).push({from: span.from,
|
||||
to: endsAfter ? null : span.to,
|
||||
@ -4153,6 +4264,7 @@ window.CodeMirror = (function() {
|
||||
this.height = estimateHeight ? estimateHeight(this) : 1;
|
||||
};
|
||||
eventMixin(Line);
|
||||
Line.prototype.lineNo = function() { return lineNo(this); };
|
||||
|
||||
function updateLine(line, text, markedSpans, estimateHeight) {
|
||||
line.text = text;
|
||||
@ -4173,7 +4285,7 @@ window.CodeMirror = (function() {
|
||||
// Run the given mode's parser over a line, update the styles
|
||||
// array, which contains alternating fragments of text and CSS
|
||||
// classes.
|
||||
function runMode(cm, text, mode, state, f) {
|
||||
function runMode(cm, text, mode, state, f, forceToEnd) {
|
||||
var flattenSpans = mode.flattenSpans;
|
||||
if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
|
||||
var curStart = 0, curStyle = null;
|
||||
@ -4182,8 +4294,8 @@ window.CodeMirror = (function() {
|
||||
while (!stream.eol()) {
|
||||
if (stream.pos > cm.options.maxHighlightLength) {
|
||||
flattenSpans = false;
|
||||
// Webkit seems to refuse to render text nodes longer than 57444 characters
|
||||
stream.pos = Math.min(text.length, stream.start + 50000);
|
||||
if (forceToEnd) processLine(cm, text, state, stream.pos);
|
||||
stream.pos = text.length;
|
||||
style = null;
|
||||
} else {
|
||||
style = mode.token(stream, state);
|
||||
@ -4194,15 +4306,22 @@ window.CodeMirror = (function() {
|
||||
}
|
||||
stream.start = stream.pos;
|
||||
}
|
||||
if (curStart < stream.pos) f(stream.pos, curStyle);
|
||||
while (curStart < stream.pos) {
|
||||
// Webkit seems to refuse to render text nodes longer than 57444 characters
|
||||
var pos = Math.min(stream.pos, curStart + 50000);
|
||||
f(pos, curStyle);
|
||||
curStart = pos;
|
||||
}
|
||||
}
|
||||
|
||||
function highlightLine(cm, line, state) {
|
||||
function highlightLine(cm, line, state, forceToEnd) {
|
||||
// A styles array always starts with a number identifying the
|
||||
// mode/overlays that it is based on (for easy invalidation).
|
||||
var st = [cm.state.modeGen];
|
||||
// Compute the base array of styles
|
||||
runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);});
|
||||
runMode(cm, line.text, cm.doc.mode, state, function(end, style) {
|
||||
st.push(end, style);
|
||||
}, forceToEnd);
|
||||
|
||||
// Run overlays, adjust style array.
|
||||
for (var o = 0; o < cm.state.overlays.length; ++o) {
|
||||
@ -4241,10 +4360,11 @@ window.CodeMirror = (function() {
|
||||
|
||||
// Lightweight form of highlight -- proceed over this line and
|
||||
// update state, but don't save a style array.
|
||||
function processLine(cm, line, state) {
|
||||
function processLine(cm, text, state, startAt) {
|
||||
var mode = cm.doc.mode;
|
||||
var stream = new StringStream(line.text, cm.options.tabSize);
|
||||
if (line.text == "" && mode.blankLine) mode.blankLine(state);
|
||||
var stream = new StringStream(text, cm.options.tabSize);
|
||||
stream.start = stream.pos = startAt || 0;
|
||||
if (text == "" && mode.blankLine) mode.blankLine(state);
|
||||
while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
|
||||
mode.token(stream, state);
|
||||
stream.start = stream.pos;
|
||||
@ -4252,13 +4372,23 @@ window.CodeMirror = (function() {
|
||||
}
|
||||
|
||||
var styleToClassCache = {};
|
||||
function styleToClass(style) {
|
||||
function interpretTokenStyle(style, builder) {
|
||||
if (!style) return null;
|
||||
for (;;) {
|
||||
var lineClass = style.match(/(?:^|\s)line-(background-)?(\S+)/);
|
||||
if (!lineClass) break;
|
||||
style = style.slice(0, lineClass.index) + style.slice(lineClass.index + lineClass[0].length);
|
||||
var prop = lineClass[1] ? "bgClass" : "textClass";
|
||||
if (builder[prop] == null)
|
||||
builder[prop] = lineClass[2];
|
||||
else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(builder[prop]))
|
||||
builder[prop] += " " + lineClass[2];
|
||||
}
|
||||
return styleToClassCache[style] ||
|
||||
(styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
|
||||
}
|
||||
|
||||
function lineContent(cm, realLine, measure, copyWidgets) {
|
||||
function buildLineContent(cm, realLine, measure, copyWidgets) {
|
||||
var merged, line = realLine, empty = true;
|
||||
while (merged = collapsedSpanAtStart(line))
|
||||
line = getLine(cm.doc, merged.find().from.line);
|
||||
@ -4266,7 +4396,6 @@ window.CodeMirror = (function() {
|
||||
var builder = {pre: elt("pre"), col: 0, pos: 0,
|
||||
measure: null, measuredSomething: false, cm: cm,
|
||||
copyWidgets: copyWidgets};
|
||||
if (line.textClass) builder.pre.className = line.textClass;
|
||||
|
||||
do {
|
||||
if (line.text) empty = false;
|
||||
@ -4292,7 +4421,7 @@ window.CodeMirror = (function() {
|
||||
// Work around problem with the reported dimensions of single-char
|
||||
// direction spans on IE (issue #1129). See also the comment in
|
||||
// cursorCoords.
|
||||
if (measure && ie && (order = getOrder(line))) {
|
||||
if (measure && (ie || ie_gt10) && (order = getOrder(line))) {
|
||||
var l = order.length - 1;
|
||||
if (order[l].from == order[l].to) --l;
|
||||
var last = order[l], prev = order[l - 1];
|
||||
@ -4303,21 +4432,30 @@ window.CodeMirror = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
var textClass = builder.textClass ? builder.textClass + " " + (realLine.textClass || "") : realLine.textClass;
|
||||
if (textClass) builder.pre.className = textClass;
|
||||
|
||||
signal(cm, "renderLine", cm, realLine, builder.pre);
|
||||
return builder.pre;
|
||||
return builder;
|
||||
}
|
||||
|
||||
function defaultSpecialCharPlaceholder(ch) {
|
||||
var token = elt("span", "\u2022", "cm-invalidchar");
|
||||
token.title = "\\u" + ch.charCodeAt(0).toString(16);
|
||||
return token;
|
||||
}
|
||||
|
||||
var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
|
||||
function buildToken(builder, text, style, startStyle, endStyle, title) {
|
||||
if (!text) return;
|
||||
if (!tokenSpecialChars.test(text)) {
|
||||
var special = builder.cm.options.specialChars;
|
||||
if (!special.test(text)) {
|
||||
builder.col += text.length;
|
||||
var content = document.createTextNode(text);
|
||||
} else {
|
||||
var content = document.createDocumentFragment(), pos = 0;
|
||||
while (true) {
|
||||
tokenSpecialChars.lastIndex = pos;
|
||||
var m = tokenSpecialChars.exec(text);
|
||||
special.lastIndex = pos;
|
||||
var m = special.exec(text);
|
||||
var skipped = m ? m.index - pos : text.length - pos;
|
||||
if (skipped) {
|
||||
content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
|
||||
@ -4330,8 +4468,7 @@ window.CodeMirror = (function() {
|
||||
content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
|
||||
builder.col += tabWidth;
|
||||
} else {
|
||||
var token = elt("span", "\u2022", "cm-invalidchar");
|
||||
token.title = "\\u" + m[0].charCodeAt(0).toString(16);
|
||||
var token = builder.cm.options.specialCharPlaceholder(m[0]);
|
||||
content.appendChild(token);
|
||||
builder.col += 1;
|
||||
}
|
||||
@ -4382,7 +4519,7 @@ window.CodeMirror = (function() {
|
||||
return out;
|
||||
}
|
||||
return function(builder, text, style, startStyle, endStyle, title) {
|
||||
return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle, title);
|
||||
return inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);
|
||||
};
|
||||
}
|
||||
|
||||
@ -4395,11 +4532,13 @@ window.CodeMirror = (function() {
|
||||
if (size) {
|
||||
builder.measure[builder.pos] = widget;
|
||||
} else {
|
||||
var elt = builder.measure[builder.pos] = zeroWidthElement(builder.cm.display.measure);
|
||||
if (marker.type != "bookmark" || marker.insertLeft)
|
||||
builder.pre.insertBefore(elt, widget);
|
||||
var elt = zeroWidthElement(builder.cm.display.measure);
|
||||
if (marker.type == "bookmark" && !marker.insertLeft)
|
||||
builder.measure[builder.pos] = builder.pre.appendChild(elt);
|
||||
else if (builder.measure[builder.pos])
|
||||
return;
|
||||
else
|
||||
builder.pre.appendChild(elt);
|
||||
builder.measure[builder.pos] = builder.pre.insertBefore(elt, widget);
|
||||
}
|
||||
builder.measuredSomething = true;
|
||||
}
|
||||
@ -4413,7 +4552,7 @@ window.CodeMirror = (function() {
|
||||
var spans = line.markedSpans, allText = line.text, at = 0;
|
||||
if (!spans) {
|
||||
for (var i = 1; i < styles.length; i+=2)
|
||||
builder.addToken(builder, allText.slice(at, at = styles[i]), styleToClass(styles[i+1]));
|
||||
builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4423,7 +4562,7 @@ window.CodeMirror = (function() {
|
||||
if (nextChange == pos) { // Update current marker set
|
||||
spanStyle = spanEndStyle = spanStartStyle = title = "";
|
||||
collapsed = null; nextChange = Infinity;
|
||||
var foundBookmark = null;
|
||||
var foundBookmarks = [];
|
||||
for (var j = 0; j < spans.length; ++j) {
|
||||
var sp = spans[j], m = sp.marker;
|
||||
if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
|
||||
@ -4437,14 +4576,15 @@ window.CodeMirror = (function() {
|
||||
} else if (sp.from > pos && nextChange > sp.from) {
|
||||
nextChange = sp.from;
|
||||
}
|
||||
if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmark = m;
|
||||
if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmarks.push(m);
|
||||
}
|
||||
if (collapsed && (collapsed.from || 0) == pos) {
|
||||
buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
|
||||
collapsed.marker, collapsed.from == null);
|
||||
if (collapsed.to == null) return collapsed.marker.find();
|
||||
}
|
||||
if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
|
||||
if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
|
||||
buildCollapsedSpan(builder, 0, foundBookmarks[j]);
|
||||
}
|
||||
if (pos >= len) break;
|
||||
|
||||
@ -4462,7 +4602,7 @@ window.CodeMirror = (function() {
|
||||
spanStartStyle = "";
|
||||
}
|
||||
text = allText.slice(at, at = styles[i++]);
|
||||
style = styleToClass(styles[i++]);
|
||||
style = interpretTokenStyle(styles[i++], builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4481,7 +4621,8 @@ window.CodeMirror = (function() {
|
||||
var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
|
||||
|
||||
// First adjust the line structure
|
||||
if (from.ch == 0 && to.ch == 0 && lastText == "") {
|
||||
if (from.ch == 0 && to.ch == 0 && lastText == "" &&
|
||||
(!doc.cm || doc.cm.options.wholeLineUpdateBefore)) {
|
||||
// This is a whole-line replace. Treated specially to make
|
||||
// sure line objects move the way they are supposed to.
|
||||
for (var i = 0, e = text.length - 1, added = []; i < e; ++i)
|
||||
@ -4740,11 +4881,11 @@ window.CodeMirror = (function() {
|
||||
if (extend) extendSelection(this, pos);
|
||||
else setSelection(this, pos, pos);
|
||||
}),
|
||||
setSelection: docOperation(function(anchor, head) {
|
||||
setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor));
|
||||
setSelection: docOperation(function(anchor, head, bias) {
|
||||
setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), bias);
|
||||
}),
|
||||
extendSelection: docOperation(function(from, to) {
|
||||
extendSelection(this, clipPos(this, from), to && clipPos(this, to));
|
||||
extendSelection: docOperation(function(from, to, bias) {
|
||||
extendSelection(this, clipPos(this, from), to && clipPos(this, to), bias);
|
||||
}),
|
||||
|
||||
getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
|
||||
@ -5368,7 +5509,7 @@ window.CodeMirror = (function() {
|
||||
return true;
|
||||
}
|
||||
|
||||
var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;
|
||||
var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\u1DC0–\u1DFF\u20D0–\u20FF\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff\uFE20–\uFE2F]/;
|
||||
|
||||
// DOM UTILITIES
|
||||
|
||||
@ -5430,13 +5571,18 @@ window.CodeMirror = (function() {
|
||||
spanAffectsWrapping = function(str, i) {
|
||||
return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1));
|
||||
};
|
||||
else if (webkit && !/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent))
|
||||
else if (webkit && /Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent))
|
||||
spanAffectsWrapping = function(str, i) {
|
||||
var code = str.charCodeAt(i - 1);
|
||||
return code >= 8208 && code <= 8212;
|
||||
};
|
||||
else if (webkit)
|
||||
spanAffectsWrapping = function(str, i) {
|
||||
if (i > 1 && str.charCodeAt(i - 1) == 45) {
|
||||
if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true;
|
||||
if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false;
|
||||
}
|
||||
return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
|
||||
return /[~!#%&*)=+}\]\\|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
|
||||
};
|
||||
|
||||
var knownScrollbarWidth;
|
||||
@ -5792,7 +5938,7 @@ window.CodeMirror = (function() {
|
||||
|
||||
// THE END
|
||||
|
||||
CodeMirror.version = "3.15.0";
|
||||
CodeMirror.version = "3.20.0";
|
||||
|
||||
return CodeMirror;
|
||||
})();
|
||||
|
@ -1,11 +1,9 @@
|
||||
CodeMirror.defineMode("css", function(config) {
|
||||
return CodeMirror.getMode(config, "text/css");
|
||||
});
|
||||
|
||||
CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
CodeMirror.defineMode("css", function(config, parserConfig) {
|
||||
"use strict";
|
||||
|
||||
var indentUnit = config.indentUnit,
|
||||
if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
|
||||
|
||||
var indentUnit = config.indentUnit || config.tabSize || 2,
|
||||
hooks = parserConfig.hooks || {},
|
||||
atMediaTypes = parserConfig.atMediaTypes || {},
|
||||
atMediaFeatures = parserConfig.atMediaFeatures || {},
|
||||
@ -39,7 +37,7 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
stream.match(/^\s*\w*/);
|
||||
return ret("keyword", "important");
|
||||
}
|
||||
else if (/\d/.test(ch)) {
|
||||
else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
|
||||
stream.eatWhile(/[\w.%]/);
|
||||
return ret("number", "unit");
|
||||
}
|
||||
@ -261,8 +259,13 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
}
|
||||
else if (type == "}") {
|
||||
if (context == "interpolation") style = "operator";
|
||||
state.stack.pop();
|
||||
if (context == "propertyValue") state.stack.pop();
|
||||
// Pop off end of array until { is reached
|
||||
while(state.stack.length){
|
||||
var removed = state.stack.pop();
|
||||
if(removed.indexOf("{") > -1 || removed == "block" || removed == "rule"){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == "interpolation") state.stack.push("interpolation");
|
||||
else if (type == "@media") state.stack.push("@media");
|
||||
@ -277,15 +280,15 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
state.stack[state.stack.length-1] = "@mediaType";
|
||||
state.stack.push("@mediaType(");
|
||||
}
|
||||
else state.stack.push("(");
|
||||
}
|
||||
else if (type == ")") {
|
||||
if (context == "propertyValue" && state.stack[state.stack.length-2] == "@mediaType(") {
|
||||
// In @mediaType( without closing ; after propertyValue
|
||||
state.stack.pop();
|
||||
state.stack.pop();
|
||||
}
|
||||
else if (context == "@mediaType(") {
|
||||
state.stack.pop();
|
||||
// Pop off end of array until ( is reached
|
||||
while(state.stack.length){
|
||||
var removed = state.stack.pop();
|
||||
if(removed.indexOf("(") > -1){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == ":" && state.lastToken == "property") state.stack.push("propertyValue");
|
||||
@ -366,8 +369,8 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
"drop-initial-before-align", "drop-initial-size", "drop-initial-value",
|
||||
"elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
|
||||
"flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
|
||||
"float", "float-offset", "font", "font-feature-settings", "font-family",
|
||||
"font-kerning", "font-language-override", "font-size", "font-size-adjust",
|
||||
"float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
|
||||
"font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
|
||||
"font-stretch", "font-style", "font-synthesis", "font-variant",
|
||||
"font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
|
||||
"font-variant-ligatures", "font-variant-numeric", "font-variant-position",
|
||||
@ -391,10 +394,12 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
"page", "page-break-after", "page-break-before", "page-break-inside",
|
||||
"page-policy", "pause", "pause-after", "pause-before", "perspective",
|
||||
"perspective-origin", "pitch", "pitch-range", "play-during", "position",
|
||||
"presentation-level", "punctuation-trim", "quotes", "rendering-intent",
|
||||
"resize", "rest", "rest-after", "rest-before", "richness", "right",
|
||||
"rotation", "rotation-point", "ruby-align", "ruby-overhang",
|
||||
"ruby-position", "ruby-span", "size", "speak", "speak-as", "speak-header",
|
||||
"presentation-level", "punctuation-trim", "quotes", "region-break-after",
|
||||
"region-break-before", "region-break-inside", "region-fragment",
|
||||
"rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
|
||||
"right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
|
||||
"ruby-position", "ruby-span", "shape-inside", "shape-outside", "size",
|
||||
"speak", "speak-as", "speak-header",
|
||||
"speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
|
||||
"tab-size", "table-layout", "target", "target-name", "target-new",
|
||||
"target-position", "text-align", "text-align-last", "text-decoration",
|
||||
@ -432,7 +437,7 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
|
||||
"deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
|
||||
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
|
||||
"gold", "goldenrod", "gray", "green", "greenyellow", "honeydew",
|
||||
"gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
|
||||
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
|
||||
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
|
||||
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
|
||||
@ -455,22 +460,22 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
"above", "absolute", "activeborder", "activecaption", "afar",
|
||||
"after-white-space", "ahead", "alias", "all", "all-scroll", "alternate",
|
||||
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
|
||||
"arabic-indic", "armenian", "asterisks", "auto", "avoid", "background",
|
||||
"backwards", "baseline", "below", "bidi-override", "binary", "bengali",
|
||||
"blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
|
||||
"both", "bottom", "break-all", "break-word", "button", "button-bevel",
|
||||
"arabic-indic", "armenian", "asterisks", "auto", "avoid", "avoid-column", "avoid-page",
|
||||
"avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
|
||||
"bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
|
||||
"both", "bottom", "break", "break-all", "break-word", "button", "button-bevel",
|
||||
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian",
|
||||
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
|
||||
"cell", "center", "checkbox", "circle", "cjk-earthly-branch",
|
||||
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
|
||||
"col-resize", "collapse", "compact", "condensed", "contain", "content",
|
||||
"col-resize", "collapse", "column", "compact", "condensed", "contain", "content",
|
||||
"content-box", "context-menu", "continuous", "copy", "cover", "crop",
|
||||
"cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal",
|
||||
"decimal-leading-zero", "default", "default-button", "destination-atop",
|
||||
"destination-in", "destination-out", "destination-over", "devanagari",
|
||||
"disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted",
|
||||
"double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
|
||||
"element", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
|
||||
"element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
|
||||
"ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
|
||||
"ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
|
||||
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
|
||||
@ -486,7 +491,7 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
|
||||
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
|
||||
"inline-block", "inline-table", "inset", "inside", "intrinsic", "invert",
|
||||
"italic", "justify", "kannada", "katakana", "katakana-iroha", "khmer",
|
||||
"italic", "justify", "kannada", "katakana", "katakana-iroha", "keep-all", "khmer",
|
||||
"landscape", "lao", "large", "larger", "left", "level", "lighter",
|
||||
"line-through", "linear", "lines", "list-item", "listbox", "listitem",
|
||||
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
|
||||
@ -505,11 +510,11 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
|
||||
"ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
|
||||
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
|
||||
"outside", "overlay", "overline", "padding", "padding-box", "painted",
|
||||
"paused", "persian", "plus-darker", "plus-lighter", "pointer", "portrait",
|
||||
"pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
|
||||
"radio", "read-only", "read-write", "read-write-plaintext-only", "relative",
|
||||
"repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
|
||||
"outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
|
||||
"painted", "page", "paused", "persian", "plus-darker", "plus-lighter", "pointer",
|
||||
"polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
|
||||
"radio", "read-only", "read-write", "read-write-plaintext-only", "rectangle", "region",
|
||||
"relative", "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
|
||||
"ridge", "right", "round", "row-resize", "rtl", "run-in", "running",
|
||||
"s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield",
|
||||
"searchfield-cancel-button", "searchfield-decoration",
|
||||
@ -580,7 +585,7 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
name: "css-base"
|
||||
name: "css"
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-scss", {
|
||||
@ -591,6 +596,12 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
valueKeywords: valueKeywords,
|
||||
allowNested: true,
|
||||
hooks: {
|
||||
":": function(stream) {
|
||||
if (stream.match(/\s*{/)) {
|
||||
return [null, "{"];
|
||||
}
|
||||
return false;
|
||||
},
|
||||
"$": function(stream) {
|
||||
stream.match(/^[\w-]+/);
|
||||
if (stream.peek() == ":") {
|
||||
@ -598,6 +609,11 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
}
|
||||
return ["variable", "variable"];
|
||||
},
|
||||
",": function(stream, state) {
|
||||
if (state.stack[state.stack.length - 1] == "propertyValue" && stream.match(/^ *\$/, false)) {
|
||||
return ["operator", ";"];
|
||||
}
|
||||
},
|
||||
"/": function(stream, state) {
|
||||
if (stream.eat("/")) {
|
||||
stream.skipToEnd();
|
||||
@ -618,6 +634,6 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
|
||||
}
|
||||
}
|
||||
},
|
||||
name: "css-base"
|
||||
name: "css"
|
||||
});
|
||||
})();
|
||||
|
@ -12,13 +12,20 @@
|
||||
}
|
||||
if (typeof template == "string") {
|
||||
dialog.innerHTML = template;
|
||||
} else {
|
||||
} 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) {
|
||||
closeNotification(this, null);
|
||||
var dialog = dialogDiv(this, template, options && options.bottom);
|
||||
var closed = false, me = this;
|
||||
function close() {
|
||||
@ -55,6 +62,7 @@
|
||||
});
|
||||
|
||||
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;
|
||||
@ -81,4 +89,33 @@
|
||||
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 duration = options && (options.duration === undefined ? 5000 : options.duration);
|
||||
var closed = false, doneTimer;
|
||||
|
||||
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, options.duration);
|
||||
});
|
||||
})();
|
||||
|
@ -44,7 +44,7 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
|
||||
if (close > -1) stream.backUp(cur.length - close);
|
||||
else if (m = cur.match(/<\/?$/)) {
|
||||
stream.backUp(cur.length);
|
||||
if (!stream.match(pat, false)) stream.match(cur[0]);
|
||||
if (!stream.match(pat, false)) stream.match(cur);
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
@ -21,7 +21,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
|
||||
"in": operator, "typeof": operator, "instanceof": operator,
|
||||
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
|
||||
"this": kw("this")
|
||||
"this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
|
||||
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C
|
||||
};
|
||||
|
||||
// Extend the 'normal' keywords with the TypeScript language extensions
|
||||
@ -30,7 +31,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
var tsKeywords = {
|
||||
// object-like things
|
||||
"interface": kw("interface"),
|
||||
"class": kw("class"),
|
||||
"extends": kw("extends"),
|
||||
"constructor": kw("constructor"),
|
||||
|
||||
@ -40,8 +40,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
"protected": kw("protected"),
|
||||
"static": kw("static"),
|
||||
|
||||
"super": kw("super"),
|
||||
|
||||
// types
|
||||
"string": type, "number": type, "bool": type, "any": type
|
||||
};
|
||||
@ -56,11 +54,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
|
||||
var isOperatorChar = /[+\-*&%=<>!?|~^]/;
|
||||
|
||||
function chain(stream, state, f) {
|
||||
state.tokenize = f;
|
||||
return f(stream, state);
|
||||
}
|
||||
|
||||
function nextUntilUnescaped(stream, end) {
|
||||
var escaped = false, next;
|
||||
while ((next = stream.next()) != null) {
|
||||
@ -78,49 +71,51 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
type = tp; content = cont;
|
||||
return style;
|
||||
}
|
||||
|
||||
function jsTokenBase(stream, state) {
|
||||
function tokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
if (ch == '"' || ch == "'")
|
||||
return chain(stream, state, jsTokenString(ch));
|
||||
else if (/[\[\]{}\(\),;\:\.]/.test(ch))
|
||||
if (ch == '"' || ch == "'") {
|
||||
state.tokenize = tokenString(ch);
|
||||
return state.tokenize(stream, state);
|
||||
} else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
|
||||
return ret("number", "number");
|
||||
} else if (ch == "." && stream.match("..")) {
|
||||
return ret("spread", "meta");
|
||||
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
|
||||
return ret(ch);
|
||||
else if (ch == "0" && stream.eat(/x/i)) {
|
||||
} else if (ch == "=" && stream.eat(">")) {
|
||||
return ret("=>");
|
||||
} else if (ch == "0" && stream.eat(/x/i)) {
|
||||
stream.eatWhile(/[\da-f]/i);
|
||||
return ret("number", "number");
|
||||
}
|
||||
else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
|
||||
} else if (/\d/.test(ch)) {
|
||||
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
|
||||
return ret("number", "number");
|
||||
}
|
||||
else if (ch == "/") {
|
||||
} else if (ch == "/") {
|
||||
if (stream.eat("*")) {
|
||||
return chain(stream, state, jsTokenComment);
|
||||
}
|
||||
else if (stream.eat("/")) {
|
||||
state.tokenize = tokenComment;
|
||||
return tokenComment(stream, state);
|
||||
} else if (stream.eat("/")) {
|
||||
stream.skipToEnd();
|
||||
return ret("comment", "comment");
|
||||
}
|
||||
else if (state.lastType == "operator" || state.lastType == "keyword c" ||
|
||||
/^[\[{}\(,;:]$/.test(state.lastType)) {
|
||||
} else if (state.lastType == "operator" || state.lastType == "keyword c" ||
|
||||
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
|
||||
nextUntilUnescaped(stream, "/");
|
||||
stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
|
||||
return ret("regexp", "string-2");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
stream.eatWhile(isOperatorChar);
|
||||
return ret("operator", null, stream.current());
|
||||
}
|
||||
}
|
||||
else if (ch == "#") {
|
||||
} else if (ch == "`") {
|
||||
state.tokenize = tokenQuasi;
|
||||
return tokenQuasi(stream, state);
|
||||
} else if (ch == "#") {
|
||||
stream.skipToEnd();
|
||||
return ret("error", "error");
|
||||
}
|
||||
else if (isOperatorChar.test(ch)) {
|
||||
} else if (isOperatorChar.test(ch)) {
|
||||
stream.eatWhile(isOperatorChar);
|
||||
return ret("operator", null, stream.current());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
|
||||
return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
|
||||
@ -128,19 +123,19 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
function jsTokenString(quote) {
|
||||
function tokenString(quote) {
|
||||
return function(stream, state) {
|
||||
if (!nextUntilUnescaped(stream, quote))
|
||||
state.tokenize = jsTokenBase;
|
||||
state.tokenize = tokenBase;
|
||||
return ret("string", "string");
|
||||
};
|
||||
}
|
||||
|
||||
function jsTokenComment(stream, state) {
|
||||
function tokenComment(stream, state) {
|
||||
var maybeEnd = false, ch;
|
||||
while (ch = stream.next()) {
|
||||
if (ch == "/" && maybeEnd) {
|
||||
state.tokenize = jsTokenBase;
|
||||
state.tokenize = tokenBase;
|
||||
break;
|
||||
}
|
||||
maybeEnd = (ch == "*");
|
||||
@ -148,6 +143,50 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
return ret("comment", "comment");
|
||||
}
|
||||
|
||||
function tokenQuasi(stream, state) {
|
||||
var escaped = false, next;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
|
||||
state.tokenize = tokenBase;
|
||||
break;
|
||||
}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
return ret("quasi", "string-2", stream.current());
|
||||
}
|
||||
|
||||
var brackets = "([{}])";
|
||||
// This is a crude lookahead trick to try and notice that we're
|
||||
// parsing the argument patterns for a fat-arrow function before we
|
||||
// actually hit the arrow token. It only works if the arrow is on
|
||||
// the same line as the arguments and there's no strange noise
|
||||
// (comments) in between. Fallback is to only notice when we hit the
|
||||
// arrow, and not declare the arguments as locals for the arrow
|
||||
// body.
|
||||
function findFatArrow(stream, state) {
|
||||
if (state.fatArrowAt) state.fatArrowAt = null;
|
||||
var arrow = stream.string.indexOf("=>", stream.start);
|
||||
if (arrow < 0) return;
|
||||
|
||||
var depth = 0, sawSomething = false;
|
||||
for (var pos = arrow - 1; pos >= 0; --pos) {
|
||||
var ch = stream.string.charAt(pos);
|
||||
var bracket = brackets.indexOf(ch);
|
||||
if (bracket >= 0 && bracket < 3) {
|
||||
if (!depth) { ++pos; break; }
|
||||
if (--depth == 0) break;
|
||||
} else if (bracket >= 3 && bracket < 6) {
|
||||
++depth;
|
||||
} else if (/[$\w]/.test(ch)) {
|
||||
sawSomething = true;
|
||||
} else if (sawSomething && !depth) {
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sawSomething && !depth) state.fatArrowAt = pos;
|
||||
}
|
||||
|
||||
// Parser
|
||||
|
||||
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true};
|
||||
@ -164,6 +203,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
function inScope(state, varname) {
|
||||
for (var v = state.localVars; v; v = v.next)
|
||||
if (v.name == varname) return true;
|
||||
for (var cx = state.context; cx; cx = cx.prev) {
|
||||
for (var v = cx.vars; v; v = v.next)
|
||||
if (v.name == varname) return true;
|
||||
}
|
||||
}
|
||||
|
||||
function parseJS(state, style, type, content, stream) {
|
||||
@ -210,7 +253,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
state.localVars = {name: varname, next: state.localVars};
|
||||
} else {
|
||||
if (inList(state.globalVars)) return;
|
||||
state.globalVars = {name: varname, next: state.globalVars};
|
||||
if (parserConfig.globalVars)
|
||||
state.globalVars = {name: varname, next: state.globalVars};
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,16 +296,15 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
};
|
||||
}
|
||||
|
||||
function statement(type) {
|
||||
if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
|
||||
function statement(type, value) {
|
||||
if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
|
||||
if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
|
||||
if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
|
||||
if (type == "{") return cont(pushlex("}"), block, poplex);
|
||||
if (type == ";") return cont();
|
||||
if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse);
|
||||
if (type == "function") return cont(functiondef);
|
||||
if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
|
||||
poplex, statement, poplex);
|
||||
if (type == "for") return cont(pushlex("form"), forspec, poplex, statement, poplex);
|
||||
if (type == "variable") return cont(pushlex("stat"), maybelabel);
|
||||
if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
|
||||
block, poplex, poplex);
|
||||
@ -269,6 +312,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
if (type == "default") return cont(expect(":"));
|
||||
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
|
||||
statement, poplex, popcontext);
|
||||
if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
|
||||
if (type == "class") return cont(pushlex("form"), className, objlit, poplex);
|
||||
if (type == "export") return cont(pushlex("form"), afterExport, poplex);
|
||||
if (type == "import") return cont(pushlex("form"), afterImport, poplex);
|
||||
return pass(pushlex("stat"), expression, expect(";"), poplex);
|
||||
}
|
||||
function expression(type) {
|
||||
@ -278,14 +325,20 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
return expressionInner(type, true);
|
||||
}
|
||||
function expressionInner(type, noComma) {
|
||||
if (cx.state.fatArrowAt == cx.stream.start) {
|
||||
var body = noComma ? arrowBodyNoComma : arrowBody;
|
||||
if (type == "(") return cont(pushcontext, commasep(pattern, ")"), expect("=>"), body, popcontext);
|
||||
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
|
||||
}
|
||||
|
||||
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
|
||||
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
|
||||
if (type == "function") return cont(functiondef);
|
||||
if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
|
||||
if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
|
||||
if (type == "operator") return cont(noComma ? expressionNoComma : expression);
|
||||
if (type == "[") return cont(pushlex("]"), commasep(expressionNoComma, "]"), poplex, maybeop);
|
||||
if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeop);
|
||||
if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
|
||||
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
|
||||
if (type == "[") return cont(pushlex("]"), expressionNoComma, maybeArrayComprehension, poplex, maybeop);
|
||||
if (type == "{") return cont(commasep(objprop, "}"), maybeop);
|
||||
return cont();
|
||||
}
|
||||
function maybeexpression(type) {
|
||||
@ -304,16 +357,40 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
function maybeoperatorNoComma(type, value, noComma) {
|
||||
var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
|
||||
var expr = noComma == false ? expression : expressionNoComma;
|
||||
if (value == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
|
||||
if (type == "operator") {
|
||||
if (/\+\+|--/.test(value)) return cont(me);
|
||||
if (value == "?") return cont(expression, expect(":"), expr);
|
||||
return cont(expr);
|
||||
}
|
||||
if (type == "quasi") { cx.cc.push(me); return quasi(value); }
|
||||
if (type == ";") return;
|
||||
if (type == "(") return cont(pushlex(")", "call"), commasep(expressionNoComma, ")"), poplex, me);
|
||||
if (type == "(") return cont(commasep(expressionNoComma, ")", "call"), me);
|
||||
if (type == ".") return cont(property, me);
|
||||
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
|
||||
}
|
||||
function quasi(value) {
|
||||
if (!value) debugger;
|
||||
if (value.slice(value.length - 2) != "${") return cont();
|
||||
return cont(expression, continueQuasi);
|
||||
}
|
||||
function continueQuasi(type) {
|
||||
if (type == "}") {
|
||||
cx.marked = "string-2";
|
||||
cx.state.tokenize = tokenQuasi;
|
||||
return cont();
|
||||
}
|
||||
}
|
||||
function arrowBody(type) {
|
||||
findFatArrow(cx.stream, cx.state);
|
||||
if (type == "{") return pass(statement);
|
||||
return pass(expression);
|
||||
}
|
||||
function arrowBodyNoComma(type) {
|
||||
findFatArrow(cx.stream, cx.state);
|
||||
if (type == "{") return pass(statement);
|
||||
return pass(expressionNoComma);
|
||||
}
|
||||
function maybelabel(type) {
|
||||
if (type == ":") return cont(poplex, statement);
|
||||
return pass(maybeoperatorComma, expect(";"), poplex);
|
||||
@ -327,16 +404,21 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
if (value == "get" || value == "set") return cont(getterSetter);
|
||||
} else if (type == "number" || type == "string") {
|
||||
cx.marked = type + " property";
|
||||
} else if (type == "[") {
|
||||
return cont(expression, expect("]"), afterprop);
|
||||
}
|
||||
if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expressionNoComma);
|
||||
if (atomicTypes.hasOwnProperty(type)) return cont(afterprop);
|
||||
}
|
||||
function getterSetter(type) {
|
||||
if (type == ":") return cont(expression);
|
||||
if (type != "variable") return cont(expect(":"), expression);
|
||||
if (type != "variable") return pass(afterprop);
|
||||
cx.marked = "property";
|
||||
return cont(functiondef);
|
||||
}
|
||||
function commasep(what, end) {
|
||||
function afterprop(type) {
|
||||
if (type == ":") return cont(expressionNoComma);
|
||||
if (type == "(") return pass(functiondef);
|
||||
}
|
||||
function commasep(what, end, info) {
|
||||
function proceed(type) {
|
||||
if (type == ",") {
|
||||
var lex = cx.state.lexical;
|
||||
@ -348,7 +430,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
}
|
||||
return function(type) {
|
||||
if (type == end) return cont();
|
||||
else return pass(what, proceed);
|
||||
if (info === false) return pass(what, proceed);
|
||||
return pass(pushlex(end, info), what, proceed, poplex);
|
||||
};
|
||||
}
|
||||
function block(type) {
|
||||
@ -356,67 +439,121 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
return pass(statement, block);
|
||||
}
|
||||
function maybetype(type) {
|
||||
if (type == ":") return cont(typedef);
|
||||
return pass();
|
||||
if (isTS && type == ":") return cont(typedef);
|
||||
}
|
||||
function typedef(type) {
|
||||
if (type == "variable"){cx.marked = "variable-3"; return cont();}
|
||||
return pass();
|
||||
}
|
||||
function vardef1(type, value) {
|
||||
if (type == "variable") {
|
||||
function vardef() {
|
||||
return pass(pattern, maybetype, maybeAssign, vardefCont);
|
||||
}
|
||||
function pattern(type, value) {
|
||||
if (type == "variable") { register(value); return cont(); }
|
||||
if (type == "[") return cont(commasep(pattern, "]"));
|
||||
if (type == "{") return cont(commasep(proppattern, "}"));
|
||||
}
|
||||
function proppattern(type, value) {
|
||||
if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
|
||||
register(value);
|
||||
return isTS ? cont(maybetype, vardef2) : cont(vardef2);
|
||||
return cont(maybeAssign);
|
||||
}
|
||||
return pass();
|
||||
if (type == "variable") cx.marked = "property";
|
||||
return cont(expect(":"), pattern, maybeAssign);
|
||||
}
|
||||
function vardef2(type, value) {
|
||||
if (value == "=") return cont(expressionNoComma, vardef2);
|
||||
if (type == ",") return cont(vardef1);
|
||||
function maybeAssign(_type, value) {
|
||||
if (value == "=") return cont(expressionNoComma);
|
||||
}
|
||||
function vardefCont(type) {
|
||||
if (type == ",") return cont(vardef);
|
||||
}
|
||||
function maybeelse(type, value) {
|
||||
if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex);
|
||||
}
|
||||
function forspec(type) {
|
||||
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"));
|
||||
}
|
||||
function forspec1(type) {
|
||||
if (type == "var") return cont(vardef1, expect(";"), forspec2);
|
||||
if (type == "var") return cont(vardef, expect(";"), forspec2);
|
||||
if (type == ";") return cont(forspec2);
|
||||
if (type == "variable") return cont(formaybein);
|
||||
if (type == "variable") return cont(formaybeinof);
|
||||
return pass(expression, expect(";"), forspec2);
|
||||
}
|
||||
function formaybein(_type, value) {
|
||||
if (value == "in") return cont(expression);
|
||||
function formaybeinof(_type, value) {
|
||||
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
|
||||
return cont(maybeoperatorComma, forspec2);
|
||||
}
|
||||
function forspec2(type, value) {
|
||||
if (type == ";") return cont(forspec3);
|
||||
if (value == "in") return cont(expression);
|
||||
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
|
||||
return pass(expression, expect(";"), forspec3);
|
||||
}
|
||||
function forspec3(type) {
|
||||
if (type != ")") cont(expression);
|
||||
}
|
||||
function functiondef(type, value) {
|
||||
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
|
||||
if (type == "variable") {register(value); return cont(functiondef);}
|
||||
if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext);
|
||||
if (type == "(") return cont(pushcontext, commasep(funarg, ")"), statement, popcontext);
|
||||
}
|
||||
function funarg(type, value) {
|
||||
if (type == "variable") {register(value); return isTS ? cont(maybetype) : cont();}
|
||||
function funarg(type) {
|
||||
if (type == "spread") return cont(funarg);
|
||||
return pass(pattern, maybetype);
|
||||
}
|
||||
function className(type, value) {
|
||||
if (type == "variable") {register(value); return cont(classNameAfter);}
|
||||
}
|
||||
function classNameAfter(_type, value) {
|
||||
if (value == "extends") return cont(expression);
|
||||
}
|
||||
function objlit(type) {
|
||||
if (type == "{") return cont(commasep(objprop, "}"));
|
||||
}
|
||||
function afterModule(type, value) {
|
||||
if (type == "string") return cont(statement);
|
||||
if (type == "variable") { register(value); return cont(maybeFrom); }
|
||||
}
|
||||
function afterExport(_type, value) {
|
||||
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
|
||||
if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
|
||||
return pass(statement);
|
||||
}
|
||||
function afterImport(type) {
|
||||
if (type == "string") return cont();
|
||||
return pass(importSpec, maybeFrom);
|
||||
}
|
||||
function importSpec(type, value) {
|
||||
if (type == "{") return cont(commasep(importSpec, "}"));
|
||||
if (type == "variable") register(value);
|
||||
return cont();
|
||||
}
|
||||
function maybeFrom(_type, value) {
|
||||
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
|
||||
}
|
||||
function maybeArrayComprehension(type) {
|
||||
if (type == "for") return pass(comprehension);
|
||||
if (type == ",") return cont(commasep(expressionNoComma, "]", false));
|
||||
return pass(commasep(expressionNoComma, "]", false));
|
||||
}
|
||||
function comprehension(type) {
|
||||
if (type == "for") return cont(forspec, comprehension);
|
||||
if (type == "if") return cont(expression, comprehension);
|
||||
}
|
||||
|
||||
// Interface
|
||||
|
||||
return {
|
||||
startState: function(basecolumn) {
|
||||
return {
|
||||
tokenize: jsTokenBase,
|
||||
lastType: null,
|
||||
var state = {
|
||||
tokenize: tokenBase,
|
||||
lastType: "sof",
|
||||
cc: [],
|
||||
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
|
||||
localVars: parserConfig.localVars,
|
||||
globalVars: parserConfig.globalVars,
|
||||
context: parserConfig.localVars && {vars: parserConfig.localVars},
|
||||
indented: 0
|
||||
};
|
||||
if (parserConfig.globalVars) state.globalVars = parserConfig.globalVars;
|
||||
return state;
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
@ -424,8 +561,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
if (!state.lexical.hasOwnProperty("align"))
|
||||
state.lexical.align = false;
|
||||
state.indented = stream.indentation();
|
||||
findFatArrow(stream, state);
|
||||
}
|
||||
if (state.tokenize != jsTokenComment && stream.eatSpace()) return null;
|
||||
if (state.tokenize != tokenComment && stream.eatSpace()) return null;
|
||||
var style = state.tokenize(stream, state);
|
||||
if (type == "comment") return style;
|
||||
state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
|
||||
@ -433,21 +571,21 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
if (state.tokenize == jsTokenComment) return CodeMirror.Pass;
|
||||
if (state.tokenize != jsTokenBase) return 0;
|
||||
if (state.tokenize == tokenComment) return CodeMirror.Pass;
|
||||
if (state.tokenize != tokenBase) return 0;
|
||||
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
|
||||
// Kludge to prevent 'maybelse' from blocking lexical scope pops
|
||||
for (var i = state.cc.length - 1; i >= 0; --i) {
|
||||
var c = state.cc[i];
|
||||
if (c == poplex) lexical = lexical.prev;
|
||||
else if (c != maybeelse || /^else\b/.test(textAfter)) break;
|
||||
else if (c != maybeelse) break;
|
||||
}
|
||||
if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
|
||||
if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
|
||||
lexical = lexical.prev;
|
||||
var type = lexical.type, closing = firstChar == type;
|
||||
|
||||
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0);
|
||||
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
|
||||
else if (type == "form" && firstChar == "{") return lexical.indented;
|
||||
else if (type == "form") return lexical.indented + indentUnit;
|
||||
else if (type == "stat")
|
||||
|
@ -8,6 +8,7 @@
|
||||
function findMatchingBracket(cm, where, strict) {
|
||||
var state = cm.state.matchBrackets;
|
||||
var maxScanLen = (state && state.maxScanLineLength) || 10000;
|
||||
var maxScanLines = (state && state.maxScanLines) || 100;
|
||||
|
||||
var cur = where || cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1;
|
||||
var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
|
||||
@ -32,7 +33,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i = cur.line, found, e = forward ? Math.min(i + 100, cm.lineCount()) : Math.max(-1, i - 100); i != e; i+=d) {
|
||||
for (var i = cur.line, found, e = forward ? Math.min(i + maxScanLines, cm.lineCount()) : Math.max(-1, i - maxScanLines); i != e; i+=d) {
|
||||
if (i == cur.line) found = scan(line, i, pos);
|
||||
else found = scan(cm.getLineHandle(i), i);
|
||||
if (found) break;
|
||||
|
@ -15,15 +15,18 @@
|
||||
(function() {
|
||||
var DEFAULT_MIN_CHARS = 2;
|
||||
var DEFAULT_TOKEN_STYLE = "matchhighlight";
|
||||
var DEFAULT_DELAY = 100;
|
||||
|
||||
function State(options) {
|
||||
if (typeof options == "object") {
|
||||
this.minChars = options.minChars;
|
||||
this.style = options.style;
|
||||
this.showToken = options.showToken;
|
||||
this.delay = options.delay;
|
||||
}
|
||||
if (this.style == null) this.style = DEFAULT_TOKEN_STYLE;
|
||||
if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS;
|
||||
if (this.delay == null) this.delay = DEFAULT_DELAY;
|
||||
this.overlay = this.timeout = null;
|
||||
}
|
||||
|
||||
@ -45,7 +48,7 @@
|
||||
function cursorActivity(cm) {
|
||||
var state = cm.state.matchHighlighter;
|
||||
clearTimeout(state.timeout);
|
||||
state.timeout = setTimeout(function() {highlightMatches(cm);}, 100);
|
||||
state.timeout = setTimeout(function() {highlightMatches(cm);}, state.delay);
|
||||
}
|
||||
|
||||
function highlightMatches(cm) {
|
||||
|
@ -83,6 +83,7 @@
|
||||
if (!cursor.find(rev)) return;
|
||||
}
|
||||
cm.setSelection(cursor.from(), cursor.to());
|
||||
cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
|
||||
state.posFrom = cursor.from(); state.posTo = cursor.to();
|
||||
});}
|
||||
function clearSearch(cm) {cm.operation(function() {
|
||||
@ -121,6 +122,7 @@
|
||||
(start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
|
||||
}
|
||||
cm.setSelection(cursor.from(), cursor.to());
|
||||
cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
|
||||
confirmDialog(cm, doReplaceConfirm, "Replace?",
|
||||
[function() {doReplace(match);}, advance]);
|
||||
};
|
||||
|
@ -69,8 +69,8 @@
|
||||
this.matches = function(reverse, pos) {
|
||||
var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(doc.getLine(ln));
|
||||
var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
|
||||
if (reverse ? offsetA >= pos.ch || offsetA != match.length
|
||||
: offsetA <= pos.ch || offsetA != line.length - match.length)
|
||||
if (reverse ? offsetA > pos.ch || offsetA != match.length
|
||||
: offsetA < pos.ch || offsetA != line.length - match.length)
|
||||
return;
|
||||
for (;;) {
|
||||
if (reverse ? !ln : ln == doc.lineCount() - 1) return;
|
||||
|
@ -76,7 +76,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
|
||||
tagName = "";
|
||||
var c;
|
||||
while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
|
||||
if (!tagName) return "error";
|
||||
if (!tagName) return "tag error";
|
||||
type = isClose ? "closeTag" : "openTag";
|
||||
state.tokenize = inTag;
|
||||
return "tag";
|
||||
@ -109,7 +109,9 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
|
||||
type = "equals";
|
||||
return null;
|
||||
} else if (ch == "<") {
|
||||
return "error";
|
||||
state.tokenize = inText;
|
||||
var next = state.tokenize(stream, state);
|
||||
return next ? next + " error" : "error";
|
||||
} else if (/[\'\"]/.test(ch)) {
|
||||
state.tokenize = inAttribute(ch);
|
||||
state.stringStartCol = stream.column();
|
||||
@ -261,7 +263,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
|
||||
function attribute(type) {
|
||||
if (type == "equals") return cont(attvalue, attributes);
|
||||
if (!Kludges.allowMissing) setStyle = "error";
|
||||
else if (type == "word") setStyle = "attribute";
|
||||
else if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
|
||||
return (type == "endTag" || type == "selfcloseTag") ? pass() : cont();
|
||||
}
|
||||
function attvalue(type) {
|
||||
@ -298,7 +300,9 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
|
||||
}
|
||||
}
|
||||
state.startOfLine = false;
|
||||
return setStyle || style;
|
||||
if (setStyle)
|
||||
style = setStyle == "error" ? style + " error" : setStyle;
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function(state, textAfter, fullLine) {
|
||||
|
@ -7,4 +7,66 @@
|
||||
|
||||
MT("comma-and-binop",
|
||||
"[keyword function](){ [keyword var] [def x] = [number 1] + [number 2], [def y]; }");
|
||||
|
||||
MT("destructuring",
|
||||
"([keyword function]([def a], [[[def b], [def c] ]]) {",
|
||||
" [keyword let] {[def d], [property foo]: [def c]=[number 10], [def x]} = [variable foo]([variable-2 a]);",
|
||||
" [[[variable-2 c], [variable y] ]] = [variable-2 c];",
|
||||
"})();");
|
||||
|
||||
MT("class",
|
||||
"[keyword class] [variable Point] [keyword extends] [variable SuperThing] {",
|
||||
" [[ [string-2 /expr/] ]]: [number 24],",
|
||||
" [property constructor]([def x], [def y]) {",
|
||||
" [keyword super]([string 'something']);",
|
||||
" [keyword this].[property x] = [variable-2 x];",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
MT("module",
|
||||
"[keyword module] [string 'foo'] {",
|
||||
" [keyword export] [keyword let] [def x] = [number 42];",
|
||||
" [keyword export] [keyword *] [keyword from] [string 'somewhere'];",
|
||||
"}");
|
||||
|
||||
MT("import",
|
||||
"[keyword function] [variable foo]() {",
|
||||
" [keyword import] [def $] [keyword from] [string 'jquery'];",
|
||||
" [keyword module] [def crypto] [keyword from] [string 'crypto'];",
|
||||
" [keyword import] { [def encrypt], [def decrypt] } [keyword from] [string 'crypto'];",
|
||||
"}");
|
||||
|
||||
MT("const",
|
||||
"[keyword function] [variable f]() {",
|
||||
" [keyword const] [[ [def a], [def b] ]] = [[ [number 1], [number 2] ]];",
|
||||
"}");
|
||||
|
||||
MT("for/of",
|
||||
"[keyword for]([keyword let] [variable of] [keyword of] [variable something]) {}");
|
||||
|
||||
MT("generator",
|
||||
"[keyword function*] [variable repeat]([def n]) {",
|
||||
" [keyword for]([keyword var] [def i] = [number 0]; [variable-2 i] < [variable-2 n]; ++[variable-2 i])",
|
||||
" [keyword yield] [variable-2 i];",
|
||||
"}");
|
||||
|
||||
MT("fatArrow",
|
||||
"[variable array].[property filter]([def a] => [variable-2 a] + [number 1]);",
|
||||
"[variable a];", // No longer in scope
|
||||
"[keyword let] [variable f] = ([[ [def a], [def b] ]], [def c]) => [variable-2 a] + [variable-2 c];",
|
||||
"[variable c];");
|
||||
|
||||
MT("spread",
|
||||
"[keyword function] [variable f]([def a], [meta ...][def b]) {",
|
||||
" [variable something]([variable-2 a], [meta ...][variable-2 b]);",
|
||||
"}");
|
||||
|
||||
MT("comprehension",
|
||||
"[keyword function] [variable f]() {",
|
||||
" [[ [variable x] + [number 1] [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];",
|
||||
" ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] === [string 'blue']));",
|
||||
"}");
|
||||
|
||||
MT("quasi",
|
||||
"[variable re][string-2 `fofdlakj${][variable x] + ([variable re][string-2 `foo`]) + [number 1][string-2 }fdsa`] + [number 2]");
|
||||
})();
|
||||
|
@ -59,6 +59,13 @@
|
||||
return {tokens: tokens, plain: plain};
|
||||
}
|
||||
|
||||
test.indentation = function(name, mode, tokens, modeName) {
|
||||
var data = parseTokens(tokens);
|
||||
return test((modeName || mode.name) + "_indent_" + name, function() {
|
||||
return compare(data.plain, data.tokens, mode, true);
|
||||
});
|
||||
};
|
||||
|
||||
test.mode = function(name, mode, tokens, modeName) {
|
||||
var data = parseTokens(tokens);
|
||||
return test((modeName || mode.name) + "_" + name, function() {
|
||||
@ -66,7 +73,7 @@
|
||||
});
|
||||
};
|
||||
|
||||
function compare(text, expected, mode) {
|
||||
function compare(text, expected, mode, compareIndentation) {
|
||||
|
||||
var expectedOutput = [];
|
||||
for (var i = 0; i < expected.length; i += 2) {
|
||||
@ -75,7 +82,7 @@
|
||||
expectedOutput.push(sty, expected[i + 1]);
|
||||
}
|
||||
|
||||
var observedOutput = highlight(text, mode);
|
||||
var observedOutput = highlight(text, mode, compareIndentation);
|
||||
|
||||
var pass, passStyle = "";
|
||||
pass = highlightOutputsEqual(expectedOutput, observedOutput);
|
||||
@ -114,7 +121,7 @@
|
||||
*
|
||||
* @return array of [style, token] pairs
|
||||
*/
|
||||
function highlight(string, mode) {
|
||||
function highlight(string, mode, compareIndentation) {
|
||||
var state = mode.startState()
|
||||
|
||||
var lines = string.replace(/\r\n/g,'\n').split('\n');
|
||||
@ -125,14 +132,15 @@
|
||||
if (line == "" && mode.blankLine) mode.blankLine(state);
|
||||
/* Start copied code from CodeMirror.highlight */
|
||||
while (!stream.eol()) {
|
||||
var style = mode.token(stream, state), substr = stream.current();
|
||||
if (style && style.indexOf(" ") > -1) style = style.split(' ').sort().join(' ');
|
||||
var compare = mode.token(stream, state), substr = stream.current();
|
||||
if(compareIndentation) compare = mode.indent(state) || null;
|
||||
else if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' ');
|
||||
|
||||
stream.start = stream.pos;
|
||||
if (pos && st[pos-2] == style && !newLine) {
|
||||
stream.start = stream.pos;
|
||||
if (pos && st[pos-2] == compare && !newLine) {
|
||||
st[pos-1] += substr;
|
||||
} else if (substr) {
|
||||
st[pos++] = style; st[pos++] = substr;
|
||||
st[pos++] = compare; st[pos++] = substr;
|
||||
}
|
||||
// Give up when line is ridiculously long
|
||||
if (stream.pos > 5000) {
|
||||
|
@ -1,5 +1,7 @@
|
||||
var Pos = CodeMirror.Pos;
|
||||
|
||||
CodeMirror.defaults.rtlMoveVisually = true;
|
||||
|
||||
function forEach(arr, f) {
|
||||
for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
|
||||
}
|
||||
@ -517,6 +519,24 @@ testCM("bookmarkCursor", function(cm) {
|
||||
is(cm.cursorCoords(Pos(4, 1)).left > pos41.left, "single-char bug");
|
||||
}, {value: "foo\nbar\n\n\nx\ny"});
|
||||
|
||||
testCM("multiBookmarkCursor", function(cm) {
|
||||
if (phantom) return;
|
||||
var ms = [], m;
|
||||
function add(insertLeft) {
|
||||
for (var i = 0; i < 3; ++i) {
|
||||
var node = document.createElement("span");
|
||||
node.innerHTML = "X";
|
||||
ms.push(cm.setBookmark(Pos(0, 1), {widget: node, insertLeft: insertLeft}));
|
||||
}
|
||||
}
|
||||
var base1 = cm.cursorCoords(Pos(0, 1)).left, base4 = cm.cursorCoords(Pos(0, 4)).left;
|
||||
add(true);
|
||||
is(Math.abs(base1 - cm.cursorCoords(Pos(0, 1)).left) < .1);
|
||||
while (m = ms.pop()) m.clear();
|
||||
add(false);
|
||||
is(Math.abs(base4 - cm.cursorCoords(Pos(0, 1)).left) < .1);
|
||||
}, {value: "abcdefg"});
|
||||
|
||||
testCM("getAllMarks", function(cm) {
|
||||
addDoc(cm, 10, 10);
|
||||
var m1 = cm.setBookmark(Pos(0, 2));
|
||||
@ -852,6 +872,17 @@ testCM("changedInlineWidget", function(cm) {
|
||||
is(hScroll.scrollWidth > hScroll.clientWidth);
|
||||
}, {value: "hello there"});
|
||||
|
||||
testCM("changedBookmark", function(cm) {
|
||||
cm.setSize("10em");
|
||||
var w = document.createElement("span");
|
||||
w.innerHTML = "x";
|
||||
var m = cm.setBookmark(Pos(0, 4), {widget: w});
|
||||
w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed";
|
||||
m.changed();
|
||||
var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0];
|
||||
is(hScroll.scrollWidth > hScroll.clientWidth);
|
||||
}, {value: "abcdefg"});
|
||||
|
||||
testCM("inlineWidget", function(cm) {
|
||||
var w = cm.setBookmark(Pos(0, 2), {widget: document.createTextNode("uu")});
|
||||
cm.setCursor(0, 2);
|
||||
@ -1130,7 +1161,7 @@ testCM("rtlMovement", function(cm) {
|
||||
prevX = cursor.offsetLeft;
|
||||
}
|
||||
});
|
||||
}, {rtlMoveVisually: true});
|
||||
});
|
||||
|
||||
// Verify that updating a line clears its bidi ordering
|
||||
testCM("bidiUpdate", function(cm) {
|
||||
@ -1311,6 +1342,7 @@ testCM("atomicMarker", function(cm) {
|
||||
eqPos(cm.getCursor(), Pos(8, 3));
|
||||
m.clear();
|
||||
m = atom(1, 1, 3, 8);
|
||||
cm.setCursor(Pos(0, 0));
|
||||
cm.setCursor(Pos(2, 0));
|
||||
eqPos(cm.getCursor(), Pos(3, 8));
|
||||
cm.execCommand("goCharLeft");
|
||||
@ -1509,3 +1541,22 @@ testCM("change_removedText", function(cm) {
|
||||
eq(removedText[0].join("\n"), "abc\nd");
|
||||
eq(removedText[1].join("\n"), "");
|
||||
});
|
||||
|
||||
testCM("lineStyleFromMode", function(cm) {
|
||||
CodeMirror.defineMode("test_mode", function() {
|
||||
return {token: function(stream) {
|
||||
if (stream.match(/^\[[^\]]*\]/)) return "line-brackets";
|
||||
if (stream.match(/^\([^\]]*\)/)) return "line-background-parens";
|
||||
stream.match(/^\s+|^\S+/);
|
||||
}};
|
||||
});
|
||||
cm.setOption("mode", "test_mode");
|
||||
var bracketElts = byClassName(cm.getWrapperElement(), "brackets");
|
||||
eq(bracketElts.length, 1);
|
||||
eq(bracketElts[0].nodeName, "PRE");
|
||||
is(!/brackets.*brackets/.test(bracketElts[0].className));
|
||||
var parenElts = byClassName(cm.getWrapperElement(), "parens");
|
||||
eq(parenElts.length, 1);
|
||||
eq(parenElts[0].nodeName, "DIV");
|
||||
is(!/parens.*parens/.test(parenElts[0].className));
|
||||
}, {value: "line1: [br] [br]\nline2: (par) (par)\nline3: nothing"});
|
||||
|
Loading…
Reference in New Issue
Block a user