зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
57c4378df9
|
@ -190,7 +190,7 @@ var developerHUD = {
|
|||
* metrics, and how to notify the front-end when metrics have changed.
|
||||
*/
|
||||
function Target(frame, actor) {
|
||||
this._frame = frame;
|
||||
this.frame = frame;
|
||||
this.actor = actor;
|
||||
this.metrics = new Map();
|
||||
this._appName = null;
|
||||
|
@ -198,15 +198,8 @@ function Target(frame, actor) {
|
|||
|
||||
Target.prototype = {
|
||||
|
||||
get frame() {
|
||||
let frame = this._frame;
|
||||
let systemapp = document.querySelector('#systemapp');
|
||||
|
||||
return (frame === systemapp ? getContentWindow() : frame);
|
||||
},
|
||||
|
||||
get manifest() {
|
||||
return this._frame.appManifestURL;
|
||||
return this.frame.appManifestURL;
|
||||
},
|
||||
|
||||
get appName() {
|
||||
|
|
|
@ -82,10 +82,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "SafeMode",
|
|||
|
||||
window.performance.measure('gecko-shell-jsm-loaded', 'gecko-shell-loadstart');
|
||||
|
||||
function getContentWindow() {
|
||||
return shell.contentBrowser.contentWindow;
|
||||
}
|
||||
|
||||
function debug(str) {
|
||||
dump(' -*- Shell.js: ' + str + '\n');
|
||||
}
|
||||
|
@ -388,7 +384,7 @@ var shell = {
|
|||
CaptivePortalLoginHelper.init();
|
||||
|
||||
this.contentBrowser.src = homeURL;
|
||||
this.isHomeLoaded = false;
|
||||
this._isEventListenerReady = false;
|
||||
|
||||
window.performance.mark('gecko-shell-system-frame-set');
|
||||
|
||||
|
@ -480,6 +476,13 @@ var shell = {
|
|||
this.contentBrowser.setVisible(true);
|
||||
}
|
||||
break;
|
||||
case 'load':
|
||||
if (content.document.location == 'about:blank') {
|
||||
return;
|
||||
}
|
||||
content.removeEventListener('load', this, true);
|
||||
this.notifyContentWindowLoaded();
|
||||
break;
|
||||
case 'mozbrowserloadstart':
|
||||
if (content.document.location == 'about:blank') {
|
||||
this.contentBrowser.addEventListener('mozbrowserlocationchange', this, true);
|
||||
|
@ -586,9 +589,12 @@ var shell = {
|
|||
break;
|
||||
case 'MozAfterPaint':
|
||||
window.removeEventListener('MozAfterPaint', this);
|
||||
this.sendChromeEvent({
|
||||
// This event should be sent before System app returns with
|
||||
// system-message-listener-ready mozContentEvent, because it's on
|
||||
// the critical launch path of the app.
|
||||
SystemAppProxy._sendCustomEvent('mozChromeEvent', {
|
||||
type: 'system-first-paint'
|
||||
});
|
||||
}, /* noPending */ true);
|
||||
break;
|
||||
case 'unload':
|
||||
this.stop();
|
||||
|
@ -610,6 +616,14 @@ var shell = {
|
|||
|
||||
// Send an event to a specific window, document or element.
|
||||
sendEvent: function shell_sendEvent(target, type, details) {
|
||||
if (target === this.contentBrowser) {
|
||||
// We must ask SystemAppProxy to send the event in this case so
|
||||
// that event would be dispatched from frame.contentWindow instead of
|
||||
// on the System app frame.
|
||||
SystemAppProxy._sendCustomEvent(type, details);
|
||||
return;
|
||||
}
|
||||
|
||||
let doc = target.document || target.ownerDocument || target;
|
||||
let event = doc.createEvent('CustomEvent');
|
||||
event.initCustomEvent(type, true, true, details ? details : {});
|
||||
|
@ -617,21 +631,10 @@ var shell = {
|
|||
},
|
||||
|
||||
sendCustomEvent: function shell_sendCustomEvent(type, details) {
|
||||
let target = getContentWindow();
|
||||
let payload = details ? Cu.cloneInto(details, target) : {};
|
||||
this.sendEvent(target, type, payload);
|
||||
SystemAppProxy._sendCustomEvent(type, details);
|
||||
},
|
||||
|
||||
sendChromeEvent: function shell_sendChromeEvent(details) {
|
||||
if (!this.isHomeLoaded) {
|
||||
if (!('pendingChromeEvents' in this)) {
|
||||
this.pendingChromeEvents = [];
|
||||
}
|
||||
|
||||
this.pendingChromeEvents.push(details);
|
||||
return;
|
||||
}
|
||||
|
||||
this.sendCustomEvent("mozChromeEvent", details);
|
||||
},
|
||||
|
||||
|
@ -672,6 +675,7 @@ var shell = {
|
|||
this.contentBrowser.removeEventListener('mozbrowserlocationchange', this, true);
|
||||
|
||||
let content = this.contentBrowser.contentWindow;
|
||||
content.addEventListener('load', this, true);
|
||||
|
||||
this.reportCrash(true);
|
||||
|
||||
|
@ -685,28 +689,7 @@ var shell = {
|
|||
Cu.import('resource://gre/modules/OperatorApps.jsm');
|
||||
#endif
|
||||
|
||||
content.addEventListener('load', function shell_homeLoaded() {
|
||||
content.removeEventListener('load', shell_homeLoaded);
|
||||
shell.isHomeLoaded = true;
|
||||
|
||||
if (Services.prefs.getBoolPref('b2g.orientation.animate')) {
|
||||
Cu.import('resource://gre/modules/OrientationChangeHandler.jsm');
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
libcutils.property_set('sys.boot_completed', '1');
|
||||
#endif
|
||||
|
||||
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
|
||||
|
||||
SystemAppProxy.setIsReady();
|
||||
if ('pendingChromeEvents' in shell) {
|
||||
shell.pendingChromeEvents.forEach((shell.sendChromeEvent).bind(shell));
|
||||
}
|
||||
delete shell.pendingChromeEvents;
|
||||
});
|
||||
|
||||
shell.handleCmdLine();
|
||||
this.handleCmdLine();
|
||||
},
|
||||
|
||||
handleCmdLine: function shell_handleCmdLine() {
|
||||
|
@ -727,6 +710,38 @@ var shell = {
|
|||
}
|
||||
#endif
|
||||
},
|
||||
|
||||
// This gets called when window.onload fires on the System app content window,
|
||||
// which means things in <html> are parsed and statically referenced <script>s
|
||||
// and <script defer>s are loaded and run.
|
||||
notifyContentWindowLoaded: function shell_notifyContentWindowLoaded() {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
libcutils.property_set('sys.boot_completed', '1');
|
||||
#endif
|
||||
|
||||
// This will cause Gonk Widget to remove boot animation from the screen
|
||||
// and reveals the page.
|
||||
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
|
||||
|
||||
SystemAppProxy.setIsLoaded();
|
||||
},
|
||||
|
||||
// This gets called when the content sends us system-message-listener-ready
|
||||
// mozContentEvent, OR when an observer message tell us we should consider
|
||||
// the content as ready.
|
||||
notifyEventListenerReady: function shell_notifyEventListenerReady() {
|
||||
if (this._isEventListenerReady) {
|
||||
Cu.reportError('shell.js: SystemApp has already been declared as being ready.');
|
||||
return;
|
||||
}
|
||||
this._isEventListenerReady = true;
|
||||
|
||||
if (Services.prefs.getBoolPref('b2g.orientation.animate')) {
|
||||
Cu.import('resource://gre/modules/OrientationChangeHandler.jsm');
|
||||
}
|
||||
|
||||
SystemAppProxy.setIsReady();
|
||||
}
|
||||
};
|
||||
|
||||
Services.obs.addObserver(function onFullscreenOriginChange(subject, topic, data) {
|
||||
|
@ -734,11 +749,13 @@ Services.obs.addObserver(function onFullscreenOriginChange(subject, topic, data)
|
|||
fullscreenorigin: data });
|
||||
}, "fullscreen-origin-change", false);
|
||||
|
||||
DOMApplicationRegistry.registryStarted.then(function () {
|
||||
shell.sendChromeEvent({ type: 'webapps-registry-start' });
|
||||
});
|
||||
DOMApplicationRegistry.registryReady.then(function () {
|
||||
shell.sendChromeEvent({ type: 'webapps-registry-ready' });
|
||||
// This event should be sent before System app returns with
|
||||
// system-message-listener-ready mozContentEvent, because it's on
|
||||
// the critical launch path of the app.
|
||||
SystemAppProxy._sendCustomEvent('mozChromeEvent', {
|
||||
type: 'webapps-registry-ready'
|
||||
}, /* noPending */ true);
|
||||
});
|
||||
|
||||
Services.obs.addObserver(function onBluetoothVolumeChange(subject, topic, data) {
|
||||
|
@ -752,6 +769,10 @@ Services.obs.addObserver(function(subject, topic, data) {
|
|||
shell.sendCustomEvent('mozmemorypressure');
|
||||
}, 'memory-pressure', false);
|
||||
|
||||
Services.obs.addObserver(function(subject, topic, data) {
|
||||
shell.notifyEventListenerReady();
|
||||
}, 'system-message-listener-ready', false);
|
||||
|
||||
var permissionMap = new Map([
|
||||
['unknown', Services.perms.UNKNOWN_ACTION],
|
||||
['allow', Services.perms.ALLOW_ACTION],
|
||||
|
|
|
@ -13,8 +13,10 @@ this.EXPORTED_SYMBOLS = ['SystemAppProxy'];
|
|||
|
||||
var SystemAppProxy = {
|
||||
_frame: null,
|
||||
_isLoaded: false,
|
||||
_isReady: false,
|
||||
_pendingEvents: [],
|
||||
_pendingLoadedEvents: [],
|
||||
_pendingReadyEvents: [],
|
||||
_pendingListeners: [],
|
||||
|
||||
// To call when a new system app iframe is created
|
||||
|
@ -34,18 +36,38 @@ var SystemAppProxy = {
|
|||
return this._frame;
|
||||
},
|
||||
|
||||
// To call when the load event of the System app document is triggered.
|
||||
// i.e. everything that is not lazily loaded are run and done.
|
||||
setIsLoaded: function () {
|
||||
if (this._isLoaded) {
|
||||
Cu.reportError('SystemApp has already been declared as being loaded.');
|
||||
}
|
||||
this._isLoaded = true;
|
||||
|
||||
// Dispatch all events being queued while the system app was still loading
|
||||
this._pendingLoadedEvents
|
||||
.forEach(([type, details]) =>
|
||||
this._sendCustomEvent(type, details, true));
|
||||
this._pendingLoadedEvents = [];
|
||||
},
|
||||
|
||||
// To call when it is ready to receive events
|
||||
// i.e. when system-message-listener-ready mozContentEvent is sent.
|
||||
setIsReady: function () {
|
||||
if (!this._isLoaded) {
|
||||
Cu.reportError('SystemApp.setIsLoaded() should be called before setIsReady().');
|
||||
}
|
||||
|
||||
if (this._isReady) {
|
||||
Cu.reportError('SystemApp has already been declared as being ready.');
|
||||
}
|
||||
this._isReady = true;
|
||||
|
||||
// Dispatch all events being queued while the system app was still loading
|
||||
this._pendingEvents
|
||||
// Dispatch all events being queued while the system app was still not ready
|
||||
this._pendingReadyEvents
|
||||
.forEach(([type, details]) =>
|
||||
this._sendCustomEvent(type, details));
|
||||
this._pendingEvents = [];
|
||||
this._pendingReadyEvents = [];
|
||||
},
|
||||
|
||||
/*
|
||||
|
@ -62,6 +84,9 @@ var SystemAppProxy = {
|
|||
* @param details The event details.
|
||||
* @param noPending Set to true to emit this event even before the system
|
||||
* app is ready.
|
||||
* Event is always pending if the app is not loaded yet.
|
||||
*
|
||||
* @returns event? Dispatched event, or null if the event is pending.
|
||||
*/
|
||||
_sendCustomEvent: function systemApp_sendCustomEvent(type,
|
||||
details,
|
||||
|
@ -69,10 +94,22 @@ var SystemAppProxy = {
|
|||
target) {
|
||||
let content = this._frame ? this._frame.contentWindow : null;
|
||||
|
||||
// If the system app isn't loaded yet,
|
||||
// queue events until someone calls setIsLoaded
|
||||
if (!content || !this._isLoaded) {
|
||||
if (noPending) {
|
||||
this._pendingLoadedEvents.push([type, details]);
|
||||
} else {
|
||||
this._pendingReadyEvents.push([type, details]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the system app isn't ready yet,
|
||||
// queue events until someone calls setIsReady
|
||||
if (!content || (!this._isReady && !noPending)) {
|
||||
this._pendingEvents.push([type, details]);
|
||||
if (!this._isReady && !noPending) {
|
||||
this._pendingReadyEvents.push([type, details]);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -87,6 +124,10 @@ var SystemAppProxy = {
|
|||
payload = details ? Cu.cloneInto(details, content) : {};
|
||||
}
|
||||
|
||||
if ((target || content) === this._frame.contentWindow) {
|
||||
dump('XXX FIXME : Dispatch a ' + type + ': ' + details.type + "\n");
|
||||
}
|
||||
|
||||
event.initCustomEvent(type, true, false, payload);
|
||||
(target || content).dispatchEvent(event);
|
||||
|
||||
|
|
|
@ -27,10 +27,11 @@ function next() {
|
|||
// Listen for events received by the system app document
|
||||
// to ensure that we receive all of them, in an expected order and time
|
||||
var isLoaded = false;
|
||||
var isReady = false;
|
||||
var n = 0;
|
||||
function listener(event) {
|
||||
if (!isLoaded) {
|
||||
assert.ok(false, "Received event before the iframe is ready");
|
||||
assert.ok(false, "Received event before the iframe is loaded");
|
||||
return;
|
||||
}
|
||||
n++;
|
||||
|
@ -41,16 +42,34 @@ function listener(event) {
|
|||
assert.equal(event.type, "custom");
|
||||
assert.equal(event.detail.name, "second");
|
||||
|
||||
next(); // call checkEventDispatching
|
||||
next(); // call checkEventPendingBeforeLoad
|
||||
} else if (n == 3) {
|
||||
if (!isReady) {
|
||||
assert.ok(false, "Received event before the iframe is loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
assert.equal(event.type, "custom");
|
||||
assert.equal(event.detail.name, "third");
|
||||
} else if (n == 4) {
|
||||
if (!isReady) {
|
||||
assert.ok(false, "Received event before the iframe is loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
assert.equal(event.type, "mozChromeEvent");
|
||||
assert.equal(event.detail.name, "fourth");
|
||||
|
||||
next(); // call checkEventDispatching
|
||||
} else if (n == 5) {
|
||||
assert.equal(event.type, "custom");
|
||||
assert.equal(event.detail.name, "fifth");
|
||||
} else if (n === 6) {
|
||||
assert.equal(event.type, "mozChromeEvent");
|
||||
assert.equal(event.detail.name, "sixth");
|
||||
} else if (n === 7) {
|
||||
assert.equal(event.type, "custom");
|
||||
assert.equal(event.detail.name, "seventh");
|
||||
assert.equal(event.target, customEventTarget);
|
||||
|
||||
next(); // call checkEventListening();
|
||||
|
@ -72,8 +91,8 @@ var steps = [
|
|||
|
||||
function earlyEvents() {
|
||||
// Immediately try to send events
|
||||
SystemAppProxy.dispatchEvent({ name: "first" });
|
||||
SystemAppProxy._sendCustomEvent("custom", { name: "second" });
|
||||
SystemAppProxy._sendCustomEvent("mozChromeEvent", { name: "first" }, true);
|
||||
SystemAppProxy._sendCustomEvent("custom", { name: "second" }, true);
|
||||
next();
|
||||
},
|
||||
|
||||
|
@ -110,7 +129,7 @@ var steps = [
|
|||
// Declare that the iframe is now loaded.
|
||||
// That should dispatch early events
|
||||
isLoaded = true;
|
||||
SystemAppProxy.setIsReady();
|
||||
SystemAppProxy.setIsLoaded();
|
||||
assert.ok(true, "Frame declared as loaded");
|
||||
|
||||
let gotFrame = SystemAppProxy.getFrame();
|
||||
|
@ -123,13 +142,24 @@ var steps = [
|
|||
frame.setAttribute("src", "data:text/html,system app");
|
||||
},
|
||||
|
||||
function checkEventPendingBeforeLoad() {
|
||||
// Frame is loaded but not ready,
|
||||
// these events should queue before the System app is ready.
|
||||
SystemAppProxy._sendCustomEvent("custom", { name: "third" });
|
||||
SystemAppProxy.dispatchEvent({ name: "fourth" });
|
||||
|
||||
isReady = true;
|
||||
SystemAppProxy.setIsReady();
|
||||
// Once this 4th event is received, we will run checkEventDispatching
|
||||
},
|
||||
|
||||
function checkEventDispatching() {
|
||||
// Send events after the iframe is ready,
|
||||
// they should be dispatched right away
|
||||
SystemAppProxy._sendCustomEvent("custom", { name: "third" });
|
||||
SystemAppProxy.dispatchEvent({ name: "fourth" });
|
||||
SystemAppProxy._sendCustomEvent("custom", { name: "fifth" }, false, customEventTarget);
|
||||
// Once this 5th event is received, we will run checkEventListening
|
||||
SystemAppProxy._sendCustomEvent("custom", { name: "fifth" });
|
||||
SystemAppProxy.dispatchEvent({ name: "sixth" });
|
||||
SystemAppProxy._sendCustomEvent("custom", { name: "seventh" }, false, customEventTarget);
|
||||
// Once this 7th event is received, we will run checkEventListening
|
||||
},
|
||||
|
||||
function checkEventListening() {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c0a6d4e8501368db8e5d6029a41db985ef1252a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f345f6a015709beeb2ca3955cab077fcaa959d3b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c0a6d4e8501368db8e5d6029a41db985ef1252a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f345f6a015709beeb2ca3955cab077fcaa959d3b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c0a6d4e8501368db8e5d6029a41db985ef1252a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f345f6a015709beeb2ca3955cab077fcaa959d3b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c0a6d4e8501368db8e5d6029a41db985ef1252a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f345f6a015709beeb2ca3955cab077fcaa959d3b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c0a6d4e8501368db8e5d6029a41db985ef1252a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f345f6a015709beeb2ca3955cab077fcaa959d3b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c0a6d4e8501368db8e5d6029a41db985ef1252a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f345f6a015709beeb2ca3955cab077fcaa959d3b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c0a6d4e8501368db8e5d6029a41db985ef1252a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f345f6a015709beeb2ca3955cab077fcaa959d3b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c0a6d4e8501368db8e5d6029a41db985ef1252a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f345f6a015709beeb2ca3955cab077fcaa959d3b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "4c0a6d4e8501368db8e5d6029a41db985ef1252a",
|
||||
"git_revision": "f345f6a015709beeb2ca3955cab077fcaa959d3b",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "61c5a1255e159b89caebf736d3c009a3778a5c42",
|
||||
"revision": "83e7fd1f9ab848025ef06f1283ad95fe5005f26c",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c0a6d4e8501368db8e5d6029a41db985ef1252a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f345f6a015709beeb2ca3955cab077fcaa959d3b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c0a6d4e8501368db8e5d6029a41db985ef1252a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f345f6a015709beeb2ca3955cab077fcaa959d3b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c0a6d4e8501368db8e5d6029a41db985ef1252a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f345f6a015709beeb2ca3955cab077fcaa959d3b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
|
|
|
@ -1141,7 +1141,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
<binding id="urlbar-rich-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-rich-result-popup">
|
||||
|
||||
<content ignorekeys="true" level="top" consumeoutsideclicks="never"
|
||||
aria-owns="search-suggestions-notification richlistbox">
|
||||
aria-owns="richlistbox">
|
||||
<xul:hbox anonid="search-suggestions-notification"
|
||||
align="center"
|
||||
role="alert"
|
||||
|
|
|
@ -27,3 +27,6 @@ content/shared/js/views.js
|
|||
standalone/content/js/standaloneRoomViews.js
|
||||
standalone/content/js/webapp.js
|
||||
ui/ui-showcase.js
|
||||
# Don't need to check the built tree
|
||||
standalone/dist
|
||||
|
||||
|
|
|
@ -3,3 +3,4 @@ node_modules
|
|||
*.pyc
|
||||
content/config.js
|
||||
content/VERSION.txt
|
||||
dist
|
||||
|
|
|
@ -21,6 +21,24 @@ install: npm_install
|
|||
npm_install:
|
||||
@npm install
|
||||
|
||||
# build the dist dir, which contains a production version of the code and
|
||||
# assets
|
||||
.PHONY: dist
|
||||
dist:
|
||||
cp -pr content dist
|
||||
NODE_ENV="production" $(NODE_LOCAL_BIN)/webpack \
|
||||
-p -v --display-errors
|
||||
sed 's#webappEntryPoint.js#js/standalone.js#' \
|
||||
< content/index.html > dist/index.html
|
||||
|
||||
.PHONY: distclean
|
||||
distclean:
|
||||
rm -fr dist
|
||||
|
||||
.PHONY: distserver
|
||||
distserver: remove_old_config dist
|
||||
LOOP_CONTENT_DIR=dist node server.js
|
||||
|
||||
test:
|
||||
@echo "Not implemented yet."
|
||||
|
||||
|
|
|
@ -18,15 +18,37 @@
|
|||
<link rel="localization" href="l10n/{locale}/loop.properties">
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
function insertScript(url) {
|
||||
function insertScript(url, sync) {
|
||||
var node = document.createElement("script");
|
||||
var sibling = document.getElementsByTagName("script")[0];
|
||||
node.async = 1;
|
||||
node.async = !sync;
|
||||
node.src = url;
|
||||
sibling.parentNode.insertBefore(node, sibling);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously load the supplied script into the DOM (using <script>).
|
||||
* Eventually, we probably want to do a full build step even for
|
||||
* development, after which this can go away.
|
||||
*
|
||||
* Instead of having to specify the scripts we need here, and in
|
||||
* some webpack config file for bundling, we specify them in
|
||||
* webappEntryPoint.js, which require()s them. Webpack handles that
|
||||
* during bundling, but for the current dev-server setup, where we don't
|
||||
* (yet) have a full build step, we need to provide a require() function.
|
||||
*
|
||||
* @param webpackUrl - a URL, possibly preceded by webpack loader syntax.
|
||||
* webpack loader syntax is stripped off
|
||||
*
|
||||
*/
|
||||
function require(url) {
|
||||
var devTimeUrl = url.replace(/^script!/, '');
|
||||
var devTimeUrl = devTimeUrl.replace(/^imports.*!/, '');
|
||||
var devTimeUrl = devTimeUrl.replace(/^exports.*!/, '');
|
||||
insertScript(devTimeUrl, true);
|
||||
}
|
||||
|
||||
(function() {
|
||||
// window.navigator.doNotTrack "yes" is for old versions of FF
|
||||
// window.navigator.doNotTrack "1" is for current versions of FF + Chrome + Opera
|
||||
// window.doNotTrack is Safari + IE11
|
||||
|
@ -120,34 +142,11 @@
|
|||
// We don't use the SDK's CSS. This will prevent spurious 404 errors.
|
||||
window.OTProperties.cssURL = "about:blank";
|
||||
</script>
|
||||
<script type="text/javascript" src="shared/libs/sdk.js"></script>
|
||||
<script type="text/javascript" src="libs/l10n-gaia-02ca67948fe8.js"></script>
|
||||
<script type="text/javascript" src="shared/libs/react-0.12.2.js"></script>
|
||||
<script type="text/javascript" src="shared/libs/lodash-3.9.3.js"></script>
|
||||
<script type="text/javascript" src="shared/libs/backbone-1.2.1.js"></script>
|
||||
|
||||
<!-- app scripts -->
|
||||
<script type="text/javascript" src="config.js"></script>
|
||||
<script type="text/javascript" src="shared/js/utils.js"></script>
|
||||
<script type="text/javascript" src="shared/js/crypto.js"></script>
|
||||
<script type="text/javascript" src="shared/js/mixins.js"></script>
|
||||
<script type="text/javascript" src="shared/js/actions.js"></script>
|
||||
<script type="text/javascript" src="shared/js/validate.js"></script>
|
||||
<script type="text/javascript" src="shared/js/dispatcher.js"></script>
|
||||
<script type="text/javascript" src="shared/js/websocket.js"></script>
|
||||
<script type="text/javascript" src="shared/js/otSdkDriver.js"></script>
|
||||
<script type="text/javascript" src="shared/js/store.js"></script>
|
||||
<script type="text/javascript" src="shared/js/activeRoomStore.js"></script>
|
||||
<script type="text/javascript" src="shared/js/views.js"></script>
|
||||
<script type="text/javascript" src="shared/js/textChatStore.js"></script>
|
||||
<script type="text/javascript" src="shared/js/textChatView.js"></script>
|
||||
<script type="text/javascript" src="shared/js/urlRegExps.js"></script>
|
||||
<script type="text/javascript" src="shared/js/linkifiedTextView.js"></script>
|
||||
<script type="text/javascript" src="js/standaloneAppStore.js"></script>
|
||||
<script type="text/javascript" src="js/standaloneMozLoop.js"></script>
|
||||
<script type="text/javascript" src="js/standaloneRoomViews.js"></script>
|
||||
<script type="text/javascript" src="js/standaloneMetricsStore.js"></script>
|
||||
<script type="text/javascript" src="js/webapp.js"></script>
|
||||
|
||||
<!-- note that for 'make dist', webappEntryPoint.js is replaced by -->
|
||||
<!-- the standalone.js bundle -->
|
||||
<script type="text/javascript" src="webappEntryPoint.js"></script>
|
||||
|
||||
<script>
|
||||
// Wait for all the localization notes to load
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
// When processed by webpack, this file bundles up all the JS for the
|
||||
// standalone client.
|
||||
//
|
||||
// When loaded by the development server, index.html supplies a require
|
||||
// function to load these.
|
||||
|
||||
// Right now, these are manually ordered so that all dependencies are
|
||||
// satisfied. Before long, we'd like to convert these into real modules
|
||||
// and/or better shims, and push the dependencies down into the modules
|
||||
// themselves so that this manual management step goes away.
|
||||
|
||||
// To get started, we're using webpack's script loader to load these things in
|
||||
// as-is.
|
||||
|
||||
/* global require */
|
||||
|
||||
// The OpenTok SDK tries to do some heuristic detection of require and
|
||||
// assumes a node environment if it's present, which confuses webpack, so
|
||||
// we turn that off by forcing require to false in that context.
|
||||
require("imports?require=>false!shared/libs/sdk.js");
|
||||
|
||||
require("script!./libs/l10n-gaia-02ca67948fe8.js");
|
||||
|
||||
// Ultimately, we'll likely want to pull the vendor libraries from npm, as that
|
||||
// makes upgrading easier, and it's generally better practice to minify the
|
||||
// "source" versions of libraries rather than built artifacts. We probably do
|
||||
// want to minify them ourselves since this allows for better dead-code
|
||||
// elimination, but that can be a bit of judgement call.
|
||||
require("exports?_!shared/libs/lodash-3.9.3.js");
|
||||
|
||||
// Note that anything that uses the script loader doesn't get minified, so
|
||||
// these need to be shimmed to use to other loaders (easiest first cut) or
|
||||
// turned into real modules:
|
||||
require("script!shared/libs/backbone-1.2.1.js");
|
||||
require("script!shared/libs/react-0.12.2.js");
|
||||
|
||||
require("script!shared/js/utils.js");
|
||||
require("script!shared/js/crypto.js");
|
||||
require("script!shared/js/mixins.js");
|
||||
require("script!shared/js/actions.js");
|
||||
require("script!shared/js/validate.js");
|
||||
require("script!shared/js/dispatcher.js");
|
||||
require("script!shared/js/websocket.js");
|
||||
require("script!shared/js/otSdkDriver.js");
|
||||
require("script!shared/js/store.js");
|
||||
require("script!shared/js/activeRoomStore.js");
|
||||
require("script!shared/js/views.js");
|
||||
require("script!shared/js/urlRegExps.js");
|
||||
require("script!shared/js/textChatStore.js");
|
||||
require("script!shared/js/textChatView.js");
|
||||
require("script!shared/js/linkifiedTextView.js");
|
||||
|
||||
require("script!./js/standaloneAppStore.js");
|
||||
require("script!./js/standaloneMozLoop.js");
|
||||
require("script!./js/standaloneRoomViews.js");
|
||||
require("script!./js/standaloneMetricsStore.js");
|
||||
require("script!./js/webapp.js");
|
|
@ -12,9 +12,14 @@
|
|||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"compression": "1.5.x",
|
||||
"eslint": "1.2.x",
|
||||
"eslint-plugin-react": "3.2.x",
|
||||
"express": "4.x"
|
||||
"exports-loader": "0.6.x",
|
||||
"express": "4.x",
|
||||
"imports-loader": "0.6.x",
|
||||
"script-loader": "0.6.x",
|
||||
"webpack": "1.12.x"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "make test",
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
var express = require("express");
|
||||
var app = express();
|
||||
|
||||
// make dev-server performance more similar to the production server by using
|
||||
// gzip compression
|
||||
var compression = require("compression");
|
||||
app.use(compression());
|
||||
|
||||
var path = require("path");
|
||||
|
||||
var port = process.env.PORT || 3000;
|
||||
|
@ -20,6 +25,10 @@ var feedbackApiUrl = process.env.LOOP_FEEDBACK_API_URL ||
|
|||
var feedbackProductName = process.env.LOOP_FEEDBACK_PRODUCT_NAME || "Loop";
|
||||
var loopServerUrl = process.env.LOOP_SERVER_URL || "http://localhost:5000";
|
||||
|
||||
// This is typically overridden with "dist" so that it's possible to test the
|
||||
// optimized version, once it's been built to the "dist" directory
|
||||
var standaloneContentDir = process.env.LOOP_CONTENT_DIR || "content";
|
||||
|
||||
// Remove trailing slashes as double slashes in the url can confuse the server
|
||||
// responses.
|
||||
if (loopServerUrl[loopServerUrl.length - 1] === "/") {
|
||||
|
@ -70,10 +79,11 @@ app.use("/standalone/content", express.static(path.join(__dirname, "content")));
|
|||
// does what we need for running in the github loop-client context, the second one
|
||||
// handles running in the hg repo under mozilla-central and is used so that the shared
|
||||
// files are in the right location.
|
||||
app.use("/content", express.static(path.join(__dirname, "content")));
|
||||
app.use("/content", express.static(path.join(__dirname, standaloneContentDir)));
|
||||
app.use("/content", express.static(path.join(__dirname, "..", "content")));
|
||||
// These two are based on the above, but handle call urls, that have a /c/ in them.
|
||||
app.use("/content/c", express.static(path.join(__dirname, "content")));
|
||||
app.use("/content/c", express.static(path.join(__dirname,
|
||||
standaloneContentDir)));
|
||||
app.use("/content/c", express.static(path.join(__dirname, "..", "content")));
|
||||
|
||||
// Two lines for the same reason as /content above.
|
||||
|
@ -85,7 +95,7 @@ app.use("/test", express.static(path.join(__dirname, "..", "test")));
|
|||
function serveIndex(req, res) {
|
||||
"use strict";
|
||||
|
||||
return res.sendfile(path.join(__dirname, "content", "index.html"));
|
||||
return res.sendFile(path.join(__dirname, standaloneContentDir, "index.html"));
|
||||
}
|
||||
|
||||
app.get(/^\/content\/[\w\-]+$/, serveIndex);
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/* eslint-env node */
|
||||
|
||||
// Webpack hurts to debug (lots of trial-and-error), so put non-trivial
|
||||
// functionality in other script logic whenever practical.
|
||||
|
||||
var path = require("path");
|
||||
var webpack = require("webpack");
|
||||
|
||||
function getSharedDir() {
|
||||
"use strict";
|
||||
|
||||
var fs = require("fs");
|
||||
|
||||
// relative path to the shared directory in m-c
|
||||
var mozillaCentralShared =
|
||||
path.resolve(path.join(__dirname, "..", "content", "shared"));
|
||||
|
||||
try {
|
||||
// if this doesn't blow up...
|
||||
fs.statSync(mozillaCentralShared);
|
||||
|
||||
// that directory is there, so return it
|
||||
return mozillaCentralShared;
|
||||
|
||||
} catch (ex) {
|
||||
// otherwise, assume that we're in loop-client, where the shared
|
||||
// directory is in the content directory
|
||||
return path.join(__dirname, "content", "shared");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See http://webpack.github.io/docs/configuration.html on how this works.
|
||||
* Make generous use of a search engine and stack overflow to interpret
|
||||
* those docs.
|
||||
*/
|
||||
module.exports = {
|
||||
entry: "./content/webappEntryPoint.js",
|
||||
|
||||
// We want the shared modules to be available without the requirer needing
|
||||
// to know the path to them, especially that path is different in
|
||||
// mozilla-central and loop-client.
|
||||
resolve: {
|
||||
alias: {
|
||||
shared: getSharedDir()
|
||||
}
|
||||
},
|
||||
|
||||
output: {
|
||||
filename: "standalone.js",
|
||||
path: path.join(__dirname, "dist", "js"),
|
||||
// Reduce false-positive warnings when viewing in editors which read
|
||||
// our eslint config files (which disallows tabs).
|
||||
sourcePrefix: " "
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
// XXX I'd _like_ to only suppress the warnings for vendor code, since
|
||||
// we're not likely to fix those. However, since:
|
||||
//
|
||||
// * this seems to be hard
|
||||
// * the consensus seems to be that these warnings are
|
||||
// aren't terribly high value
|
||||
// * training people to ignore warnings is pretty much always a bad
|
||||
// plan
|
||||
//
|
||||
// we suppress them everywhere
|
||||
warnings: false
|
||||
}
|
||||
})
|
||||
]
|
||||
};
|
|
@ -56,6 +56,10 @@ function test() {
|
|||
]);
|
||||
checkState({ frame: 0, source: 0, line: 5 });
|
||||
|
||||
// Need to refocus the stack frame due to a focus bug in e10s
|
||||
// (See Bug 1205482)
|
||||
focusCurrentStackFrame();
|
||||
|
||||
yield promise.all([
|
||||
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES),
|
||||
waitForSourceAndCaret(gPanel, "-02.js", 6),
|
||||
|
@ -64,13 +68,16 @@ function test() {
|
|||
]);
|
||||
checkState({ frame: 1, source: 1, line: 6 });
|
||||
|
||||
// Need to refocus the stack frame due to a focus bug in e10s
|
||||
// (See Bug 1205482)
|
||||
focusCurrentStackFrame();
|
||||
|
||||
yield promise.all([
|
||||
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES),
|
||||
waitForSourceAndCaret(gPanel, "-01.js", 5),
|
||||
waitForEditorLocationSet(gPanel),
|
||||
EventUtils.sendKey("HOME", gDebugger)
|
||||
]);
|
||||
|
||||
checkState({ frame: 0, source: 0, line: 5 });
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1732,7 +1732,7 @@ var Scratchpad = {
|
|||
this._onPaste = WebConsoleUtils.pasteHandlerGen(this.editor.container.contentDocument.body,
|
||||
document.querySelector('#scratchpad-notificationbox'),
|
||||
msg, okstring);
|
||||
editorElement.addEventListener("paste", this._onPaste);
|
||||
editorElement.addEventListener("paste", this._onPaste, true);
|
||||
editorElement.addEventListener("drop", this._onPaste);
|
||||
this.editor.on("saveRequested", () => this.saveFile());
|
||||
this.editor.focus();
|
||||
|
@ -1808,7 +1808,7 @@ var Scratchpad = {
|
|||
CloseObserver.uninit();
|
||||
if (this._onPaste) {
|
||||
let editorElement = document.querySelector("#scratchpad-editor");
|
||||
editorElement.removeEventListener("paste", this._onPaste);
|
||||
editorElement.removeEventListener("paste", this._onPaste, true);
|
||||
editorElement.removeEventListener("drop", this._onPaste);
|
||||
this._onPaste = null;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (C) 2013 by Marijn Haverbeke <marijnh@gmail.com>
|
||||
Copyright (C) 2015 by Marijn Haverbeke <marijnh@gmail.com> and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -5,7 +5,7 @@ code, and optionally help with indentation.
|
|||
|
||||
# Upgrade
|
||||
|
||||
Currently used version is 4.2.0. To upgrade, download a new version of
|
||||
Currently used version is 5.7.0. 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].
|
||||
|
||||
|
@ -41,73 +41,40 @@ below.
|
|||
|
||||
# License
|
||||
|
||||
The following files in this directory are licensed according to the contents
|
||||
in the LICENSE file:
|
||||
|
||||
* codemirror.css
|
||||
* codemirror.js
|
||||
* comment/comment.js
|
||||
* comment/continue-comment.js
|
||||
* activeline.js
|
||||
* dialog/dialog.css
|
||||
* dialog/dialog.js
|
||||
* edit/closebrackets.js
|
||||
* edit/closetag.js
|
||||
* edit/continuelist.js
|
||||
* edit/matchbrackets.js
|
||||
* edit/matchtags.js
|
||||
* edit/trailingspace.js
|
||||
* fold/foldcode.js
|
||||
* fold/brace-fold.js
|
||||
* fold/comment-fold.js
|
||||
* fold/xml-fold.js
|
||||
* fold/foldgutter.js
|
||||
* hint/show-hint.js
|
||||
* keymap/emacs.js
|
||||
* keymap/sublime.js
|
||||
* keymap/vim.js
|
||||
* mode/xml.js
|
||||
* mode/css.js
|
||||
* mode/javascript.js
|
||||
* mode/clike.js
|
||||
* mode/htmlmixed.js
|
||||
* search/match-highlighter.js
|
||||
* search/search.js
|
||||
* search/searchcursor.js
|
||||
* tern/tern.js
|
||||
* tern/tern.css
|
||||
* test/codemirror.html
|
||||
* test/cm_comment_test.js
|
||||
* test/cm_doc_test.js
|
||||
* test/cm_driver.js
|
||||
* test/cm_mode_javascript_test.js
|
||||
* test/cm_mode_test.css
|
||||
* test/cm_mode_test.js
|
||||
* test/cm_multi_test.js
|
||||
* test/cm_search_test.js
|
||||
* test/cm_test.js
|
||||
* test/cm_sublime_test.js
|
||||
* test/cm_vim_test.js
|
||||
* test/cm_emacs_test.js
|
||||
The following files in this directory and devtools/client/sourceeditor/test/codemirror/
|
||||
are licensed according to the contents in the LICENSE file.
|
||||
|
||||
# Localization patches
|
||||
|
||||
diff --git a/devtools/client/sourceeditor/codemirror/search/search.js b/devtools/client/sourceeditor/codemirror/search/search.js
|
||||
--- a/devtools/client/sourceeditor/codemirror/search/search.js
|
||||
+++ b/devtools/client/sourceeditor/codemirror/search/search.js
|
||||
@@ -62,19 +62,31 @@
|
||||
if (isRE) {
|
||||
query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i");
|
||||
if (query.test("")) query = /x^/;
|
||||
} else if (query == "") {
|
||||
query = /x^/;
|
||||
diff --git a/devtools/client/sourceeditor/codemirror/addon/search/search.js b/devtools/client/sourceeditor/codemirror/addon/search/search.js
|
||||
--- a/devtools/client/sourceeditor/codemirror/addon/search/search.js
|
||||
+++ b/devtools/client/sourceeditor/codemirror/addon/search/search.js
|
||||
@@ -92,32 +92,47 @@
|
||||
} else {
|
||||
query = parseString(query)
|
||||
}
|
||||
if (typeof query == "string" ? query == "" : query.test(""))
|
||||
query = /x^/;
|
||||
return query;
|
||||
}
|
||||
|
||||
- var queryDialog =
|
||||
- 'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
|
||||
- 'Search: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
|
||||
+ var queryDialog;
|
||||
function doSearch(cm, rev) {
|
||||
|
||||
function startSearch(cm, state, query) {
|
||||
state.queryText = query;
|
||||
state.query = parseQuery(query);
|
||||
cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
|
||||
state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
|
||||
cm.addOverlay(state.overlay);
|
||||
if (cm.showMatchesOnScrollbar) {
|
||||
if (state.annotate) { state.annotate.clear(); state.annotate = null; }
|
||||
state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
|
||||
}
|
||||
}
|
||||
|
||||
function doSearch(cm, rev, persistent) {
|
||||
+ if (!queryDialog) {
|
||||
+ let doc = cm.getWrapperElement().ownerDocument;
|
||||
+ let inp = doc.createElement("input");
|
||||
|
@ -123,14 +90,15 @@ diff --git a/devtools/client/sourceeditor/codemirror/search/search.js b/devtools
|
|||
+ queryDialog.appendChild(inp);
|
||||
+ queryDialog.style.display = "flex";
|
||||
+ }
|
||||
+
|
||||
var state = getSearchState(cm);
|
||||
if (state.query) return findNext(cm, rev);
|
||||
dialog(cm, queryDialog, "Search for:", cm.getSelection(), function(query) {
|
||||
cm.operation(function() {
|
||||
if (!query || state.query) return;
|
||||
state.query = parseQuery(query);
|
||||
cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
|
||||
state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
|
||||
var q = cm.getSelection() || state.lastQuery;
|
||||
if (persistent && cm.openDialog) {
|
||||
var hiding = null
|
||||
persistentDialog(cm, queryDialog, q, function(query, event) {
|
||||
CodeMirror.e_stop(event);
|
||||
if (!query) return;
|
||||
|
||||
# Footnotes
|
||||
|
||||
|
|
13
devtools/client/sourceeditor/codemirror/addon/comment/comment.js
поставляемый
Normal file → Executable file
13
devtools/client/sourceeditor/codemirror/addon/comment/comment.js
поставляемый
Normal file → Executable file
|
@ -109,7 +109,7 @@
|
|||
CodeMirror.defineExtension("uncomment", function(from, to, options) {
|
||||
if (!options) options = noOptions;
|
||||
var self = this, mode = self.getModeAt(from);
|
||||
var end = Math.min(to.line, self.lastLine()), start = Math.min(from.line, end);
|
||||
var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
|
||||
|
||||
// Try finding line comments
|
||||
var lineString = options.lineComment || mode.lineComment, lines = [];
|
||||
|
@ -153,6 +153,17 @@
|
|||
!/comment/.test(self.getTokenTypeAt(Pos(end, close + 1))))
|
||||
return false;
|
||||
|
||||
// Avoid killing block comments completely outside the selection.
|
||||
// Positions of the last startString before the start of the selection, and the first endString after it.
|
||||
var lastStart = startLine.lastIndexOf(startString, from.ch);
|
||||
var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length);
|
||||
if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false;
|
||||
// Positions of the first endString after the end of the selection, and the last startString before it.
|
||||
firstEnd = endLine.indexOf(endString, to.ch);
|
||||
var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch);
|
||||
lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart;
|
||||
if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false;
|
||||
|
||||
self.operation(function() {
|
||||
self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)),
|
||||
Pos(end, close + endString.length));
|
||||
|
|
4
devtools/client/sourceeditor/codemirror/addon/dialog/dialog.css
поставляемый
Normal file → Executable file
4
devtools/client/sourceeditor/codemirror/addon/dialog/dialog.css
поставляемый
Normal file → Executable file
|
@ -1,11 +1,11 @@
|
|||
.CodeMirror-dialog {
|
||||
position: absolute;
|
||||
left: 0; right: 0;
|
||||
background: white;
|
||||
background: inherit;
|
||||
z-index: 15;
|
||||
padding: .1em .8em;
|
||||
overflow: hidden;
|
||||
color: #333;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.CodeMirror-dialog-top {
|
||||
|
|
58
devtools/client/sourceeditor/codemirror/addon/dialog/dialog.js
поставляемый
Normal file → Executable file
58
devtools/client/sourceeditor/codemirror/addon/dialog/dialog.js
поставляемый
Normal file → Executable file
|
@ -15,11 +15,11 @@
|
|||
var wrap = cm.getWrapperElement();
|
||||
var dialog;
|
||||
dialog = wrap.appendChild(document.createElement("div"));
|
||||
if (bottom) {
|
||||
if (bottom)
|
||||
dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
|
||||
} else {
|
||||
else
|
||||
dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
|
||||
}
|
||||
|
||||
if (typeof template == "string") {
|
||||
dialog.innerHTML = template;
|
||||
} else { // Assuming it's a detached DOM element.
|
||||
|
@ -35,40 +35,61 @@
|
|||
}
|
||||
|
||||
CodeMirror.defineExtension("openDialog", function(template, callback, options) {
|
||||
if (!options) options = {};
|
||||
|
||||
closeNotification(this, null);
|
||||
var dialog = dialogDiv(this, template, options && options.bottom);
|
||||
|
||||
var dialog = dialogDiv(this, template, options.bottom);
|
||||
var closed = false, me = this;
|
||||
function close() {
|
||||
function close(newVal) {
|
||||
if (typeof newVal == 'string') {
|
||||
inp.value = newVal;
|
||||
} else {
|
||||
if (closed) return;
|
||||
closed = true;
|
||||
dialog.parentNode.removeChild(dialog);
|
||||
me.focus();
|
||||
|
||||
if (options.onClose) options.onClose(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
var inp = dialog.getElementsByTagName("input")[0], button;
|
||||
if (inp) {
|
||||
if (options && options.value) inp.value = options.value;
|
||||
if (options.value) {
|
||||
inp.value = options.value;
|
||||
if (options.selectValueOnOpen !== false) {
|
||||
inp.select();
|
||||
}
|
||||
}
|
||||
|
||||
if (options.onInput)
|
||||
CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});
|
||||
if (options.onKeyUp)
|
||||
CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
|
||||
|
||||
CodeMirror.on(inp, "keydown", function(e) {
|
||||
if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
|
||||
if (e.keyCode == 13 || e.keyCode == 27) {
|
||||
if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {
|
||||
inp.blur();
|
||||
CodeMirror.e_stop(e);
|
||||
close();
|
||||
me.focus();
|
||||
if (e.keyCode == 13) callback(inp.value);
|
||||
}
|
||||
if (e.keyCode == 13) callback(inp.value, e);
|
||||
});
|
||||
if (options && options.onKeyUp) {
|
||||
CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
|
||||
}
|
||||
if (options && options.value) inp.value = options.value;
|
||||
|
||||
if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
|
||||
|
||||
inp.focus();
|
||||
CodeMirror.on(inp, "blur", close);
|
||||
} else if (button = dialog.getElementsByTagName("button")[0]) {
|
||||
CodeMirror.on(button, "click", function() {
|
||||
close();
|
||||
me.focus();
|
||||
});
|
||||
|
||||
if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);
|
||||
|
||||
button.focus();
|
||||
CodeMirror.on(button, "blur", close);
|
||||
}
|
||||
return close;
|
||||
});
|
||||
|
@ -113,8 +134,8 @@
|
|||
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;
|
||||
var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;
|
||||
|
||||
function close() {
|
||||
if (closed) return;
|
||||
|
@ -127,7 +148,10 @@
|
|||
CodeMirror.e_preventDefault(e);
|
||||
close();
|
||||
});
|
||||
|
||||
if (duration)
|
||||
doneTimer = setTimeout(close, options.duration);
|
||||
doneTimer = setTimeout(close, duration);
|
||||
|
||||
return close;
|
||||
});
|
||||
});
|
||||
|
|
238
devtools/client/sourceeditor/codemirror/addon/edit/closebrackets.js
поставляемый
Normal file → Executable file
238
devtools/client/sourceeditor/codemirror/addon/edit/closebrackets.js
поставляемый
Normal file → Executable file
|
@ -9,38 +9,52 @@
|
|||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
var DEFAULT_BRACKETS = "()[]{}''\"\"";
|
||||
var DEFAULT_EXPLODE_ON_ENTER = "[]{}";
|
||||
var SPACE_CHAR_REGEX = /\s/;
|
||||
var defaults = {
|
||||
pairs: "()[]{}''\"\"",
|
||||
triples: "",
|
||||
explode: "[]{}"
|
||||
};
|
||||
|
||||
var Pos = CodeMirror.Pos;
|
||||
|
||||
CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
|
||||
if (old != CodeMirror.Init && old)
|
||||
cm.removeKeyMap("autoCloseBrackets");
|
||||
if (!val) return;
|
||||
var pairs = DEFAULT_BRACKETS, explode = DEFAULT_EXPLODE_ON_ENTER;
|
||||
if (typeof val == "string") pairs = val;
|
||||
else if (typeof val == "object") {
|
||||
if (val.pairs != null) pairs = val.pairs;
|
||||
if (val.explode != null) explode = val.explode;
|
||||
if (old && old != CodeMirror.Init) {
|
||||
cm.removeKeyMap(keyMap);
|
||||
cm.state.closeBrackets = null;
|
||||
}
|
||||
if (val) {
|
||||
cm.state.closeBrackets = val;
|
||||
cm.addKeyMap(keyMap);
|
||||
}
|
||||
var map = buildKeymap(pairs);
|
||||
if (explode) map.Enter = buildExplodeHandler(explode);
|
||||
cm.addKeyMap(map);
|
||||
});
|
||||
|
||||
function charsAround(cm, pos) {
|
||||
var str = cm.getRange(Pos(pos.line, pos.ch - 1),
|
||||
Pos(pos.line, pos.ch + 1));
|
||||
return str.length == 2 ? str : null;
|
||||
function getOption(conf, name) {
|
||||
if (name == "pairs" && typeof conf == "string") return conf;
|
||||
if (typeof conf == "object" && conf[name] != null) return conf[name];
|
||||
return defaults[name];
|
||||
}
|
||||
|
||||
function buildKeymap(pairs) {
|
||||
var map = {
|
||||
name : "autoCloseBrackets",
|
||||
Backspace: function(cm) {
|
||||
if (cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||
var bind = defaults.pairs + "`";
|
||||
var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
|
||||
for (var i = 0; i < bind.length; i++)
|
||||
keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i));
|
||||
|
||||
function handler(ch) {
|
||||
return function(cm) { return handleChar(cm, ch); };
|
||||
}
|
||||
|
||||
function getConfig(cm) {
|
||||
var deflt = cm.state.closeBrackets;
|
||||
if (!deflt) return null;
|
||||
var mode = cm.getModeAt(cm.getCursor());
|
||||
return mode.closeBrackets || deflt;
|
||||
}
|
||||
|
||||
function handleBackspace(cm) {
|
||||
var conf = getConfig(cm);
|
||||
if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||
|
||||
var pairs = getOption(conf, "pairs");
|
||||
var ranges = cm.listSelections();
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
if (!ranges[i].empty()) return CodeMirror.Pass;
|
||||
|
@ -52,81 +66,17 @@
|
|||
cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
|
||||
}
|
||||
}
|
||||
};
|
||||
var closingBrackets = "";
|
||||
for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
|
||||
if (left != right) closingBrackets += right;
|
||||
map["'" + left + "'"] = function(cm) {
|
||||
if (cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||
var ranges = cm.listSelections(), type, next;
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
var range = ranges[i], cur = range.head, curType;
|
||||
if (left == "'" && cm.getTokenTypeAt(cur) == "comment")
|
||||
return CodeMirror.Pass;
|
||||
var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
|
||||
if (!range.empty())
|
||||
curType = "surround";
|
||||
else if (left == right && next == right) {
|
||||
if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left)
|
||||
curType = "skipThree";
|
||||
else
|
||||
curType = "skip";
|
||||
} else if (left == right && cur.ch > 1 &&
|
||||
cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left &&
|
||||
(cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left))
|
||||
curType = "addFour";
|
||||
else if (left == right && CodeMirror.isWordChar(next))
|
||||
return CodeMirror.Pass;
|
||||
else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next))
|
||||
curType = "both";
|
||||
else
|
||||
return CodeMirror.Pass;
|
||||
if (!type) type = curType;
|
||||
else if (type != curType) return CodeMirror.Pass;
|
||||
}
|
||||
|
||||
cm.operation(function() {
|
||||
if (type == "skip") {
|
||||
cm.execCommand("goCharRight");
|
||||
} else if (type == "skipThree") {
|
||||
for (var i = 0; i < 3; i++)
|
||||
cm.execCommand("goCharRight");
|
||||
} else if (type == "surround") {
|
||||
var sels = cm.getSelections();
|
||||
for (var i = 0; i < sels.length; i++)
|
||||
sels[i] = left + sels[i] + right;
|
||||
cm.replaceSelections(sels, "around");
|
||||
} else if (type == "both") {
|
||||
cm.replaceSelection(left + right, null);
|
||||
cm.execCommand("goCharLeft");
|
||||
} else if (type == "addFour") {
|
||||
cm.replaceSelection(left + left + left + left, "before");
|
||||
cm.execCommand("goCharRight");
|
||||
}
|
||||
});
|
||||
};
|
||||
if (left != right) map["'" + right + "'"] = function(cm) {
|
||||
var ranges = cm.listSelections();
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
var range = ranges[i];
|
||||
if (!range.empty() ||
|
||||
cm.getRange(range.head, Pos(range.head.line, range.head.ch + 1)) != right)
|
||||
return CodeMirror.Pass;
|
||||
}
|
||||
cm.execCommand("goCharRight");
|
||||
};
|
||||
})(pairs.charAt(i), pairs.charAt(i + 1));
|
||||
return map;
|
||||
}
|
||||
function handleEnter(cm) {
|
||||
var conf = getConfig(cm);
|
||||
var explode = conf && getOption(conf, "explode");
|
||||
if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||
|
||||
function buildExplodeHandler(pairs) {
|
||||
return function(cm) {
|
||||
if (cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||
var ranges = cm.listSelections();
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
if (!ranges[i].empty()) return CodeMirror.Pass;
|
||||
var around = charsAround(cm, ranges[i].head);
|
||||
if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
|
||||
if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
|
||||
}
|
||||
cm.operation(function() {
|
||||
cm.replaceSelection("\n\n", null);
|
||||
|
@ -138,6 +88,108 @@
|
|||
cm.indentLine(line + 1, null, true);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function contractSelection(sel) {
|
||||
var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
|
||||
return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
|
||||
head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))};
|
||||
}
|
||||
|
||||
function handleChar(cm, ch) {
|
||||
var conf = getConfig(cm);
|
||||
if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||
|
||||
var pairs = getOption(conf, "pairs");
|
||||
var pos = pairs.indexOf(ch);
|
||||
if (pos == -1) return CodeMirror.Pass;
|
||||
var triples = getOption(conf, "triples");
|
||||
|
||||
var identical = pairs.charAt(pos + 1) == ch;
|
||||
var ranges = cm.listSelections();
|
||||
var opening = pos % 2 == 0;
|
||||
|
||||
var type, next;
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
var range = ranges[i], cur = range.head, curType;
|
||||
var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
|
||||
if (opening && !range.empty()) {
|
||||
curType = "surround";
|
||||
} else if ((identical || !opening) && next == ch) {
|
||||
if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
|
||||
curType = "skipThree";
|
||||
else
|
||||
curType = "skip";
|
||||
} else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
|
||||
cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch &&
|
||||
(cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != ch)) {
|
||||
curType = "addFour";
|
||||
} else if (identical) {
|
||||
if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, ch)) curType = "both";
|
||||
else return CodeMirror.Pass;
|
||||
} else if (opening && (cm.getLine(cur.line).length == cur.ch ||
|
||||
isClosingBracket(next, pairs) ||
|
||||
/\s/.test(next))) {
|
||||
curType = "both";
|
||||
} else {
|
||||
return CodeMirror.Pass;
|
||||
}
|
||||
if (!type) type = curType;
|
||||
else if (type != curType) return CodeMirror.Pass;
|
||||
}
|
||||
|
||||
var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
|
||||
var right = pos % 2 ? ch : pairs.charAt(pos + 1);
|
||||
cm.operation(function() {
|
||||
if (type == "skip") {
|
||||
cm.execCommand("goCharRight");
|
||||
} else if (type == "skipThree") {
|
||||
for (var i = 0; i < 3; i++)
|
||||
cm.execCommand("goCharRight");
|
||||
} else if (type == "surround") {
|
||||
var sels = cm.getSelections();
|
||||
for (var i = 0; i < sels.length; i++)
|
||||
sels[i] = left + sels[i] + right;
|
||||
cm.replaceSelections(sels, "around");
|
||||
sels = cm.listSelections().slice();
|
||||
for (var i = 0; i < sels.length; i++)
|
||||
sels[i] = contractSelection(sels[i]);
|
||||
cm.setSelections(sels);
|
||||
} else if (type == "both") {
|
||||
cm.replaceSelection(left + right, null);
|
||||
cm.triggerElectric(left + right);
|
||||
cm.execCommand("goCharLeft");
|
||||
} else if (type == "addFour") {
|
||||
cm.replaceSelection(left + left + left + left, "before");
|
||||
cm.execCommand("goCharRight");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isClosingBracket(ch, pairs) {
|
||||
var pos = pairs.lastIndexOf(ch);
|
||||
return pos > -1 && pos % 2 == 1;
|
||||
}
|
||||
|
||||
function charsAround(cm, pos) {
|
||||
var str = cm.getRange(Pos(pos.line, pos.ch - 1),
|
||||
Pos(pos.line, pos.ch + 1));
|
||||
return str.length == 2 ? str : null;
|
||||
}
|
||||
|
||||
// Project the token type that will exists after the given char is
|
||||
// typed, and use it to determine whether it would cause the start
|
||||
// of a string token.
|
||||
function enteringString(cm, pos, ch) {
|
||||
var line = cm.getLine(pos.line);
|
||||
var token = cm.getTokenAt(pos);
|
||||
if (/\bstring2?\b/.test(token.type)) return false;
|
||||
var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4);
|
||||
stream.pos = stream.start = token.start;
|
||||
for (;;) {
|
||||
var type1 = cm.getMode().token(stream, token.state);
|
||||
if (stream.pos >= pos.ch + 1) return /\bstring2?\b/.test(type1);
|
||||
stream.start = stream.pos;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
40
devtools/client/sourceeditor/codemirror/addon/edit/closetag.js
поставляемый
Normal file → Executable file
40
devtools/client/sourceeditor/codemirror/addon/edit/closetag.js
поставляемый
Normal file → Executable file
|
@ -94,23 +94,51 @@
|
|||
}
|
||||
}
|
||||
|
||||
function autoCloseSlash(cm) {
|
||||
if (cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||
function autoCloseCurrent(cm, typingSlash) {
|
||||
var ranges = cm.listSelections(), replacements = [];
|
||||
var head = typingSlash ? "/" : "</";
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
if (!ranges[i].empty()) return CodeMirror.Pass;
|
||||
var pos = ranges[i].head, tok = cm.getTokenAt(pos);
|
||||
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
|
||||
if (tok.type == "string" || tok.string.charAt(0) != "<" ||
|
||||
tok.start != pos.ch - 1 || inner.mode.name != "xml" ||
|
||||
!state.context || !state.context.tagName ||
|
||||
if (typingSlash && (tok.type == "string" || tok.string.charAt(0) != "<" ||
|
||||
tok.start != pos.ch - 1))
|
||||
return CodeMirror.Pass;
|
||||
// Kludge to get around the fact that we are not in XML mode
|
||||
// when completing in JS/CSS snippet in htmlmixed mode. Does not
|
||||
// work for other XML embedded languages (there is no general
|
||||
// way to go from a mixed mode to its current XML state).
|
||||
var replacement;
|
||||
if (inner.mode.name != "xml") {
|
||||
if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript")
|
||||
replacement = head + "script";
|
||||
else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css")
|
||||
replacement = head + "style";
|
||||
else
|
||||
return CodeMirror.Pass;
|
||||
} else {
|
||||
if (!state.context || !state.context.tagName ||
|
||||
closingTagExists(cm, state.context.tagName, pos, state))
|
||||
return CodeMirror.Pass;
|
||||
replacements[i] = "/" + state.context.tagName + ">";
|
||||
replacement = head + state.context.tagName;
|
||||
}
|
||||
if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">";
|
||||
replacements[i] = replacement;
|
||||
}
|
||||
cm.replaceSelections(replacements);
|
||||
ranges = cm.listSelections();
|
||||
for (var i = 0; i < ranges.length; i++)
|
||||
if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
|
||||
cm.indentLine(ranges[i].head.line);
|
||||
}
|
||||
|
||||
function autoCloseSlash(cm) {
|
||||
if (cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||
return autoCloseCurrent(cm, true);
|
||||
}
|
||||
|
||||
CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); };
|
||||
|
||||
function indexOf(collection, elt) {
|
||||
if (collection.indexOf) return collection.indexOf(elt);
|
||||
for (var i = 0, e = collection.length; i < e; ++i)
|
||||
|
|
29
devtools/client/sourceeditor/codemirror/addon/edit/continuelist.js
поставляемый
Normal file → Executable file
29
devtools/client/sourceeditor/codemirror/addon/edit/continuelist.js
поставляемый
Normal file → Executable file
|
@ -11,27 +11,40 @@
|
|||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
var listRE = /^(\s*)([*+-]|(\d+)\.)(\s*)/,
|
||||
unorderedBullets = "*+-";
|
||||
var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)([.)]))(\s*)/,
|
||||
emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)[.)])(\s*)$/,
|
||||
unorderedListRE = /[*+-]\s/;
|
||||
|
||||
CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
|
||||
if (cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||
var ranges = cm.listSelections(), replacements = [];
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
var pos = ranges[i].head, match;
|
||||
var inList = cm.getStateAfter(pos.line).list !== false;
|
||||
var pos = ranges[i].head;
|
||||
var eolState = cm.getStateAfter(pos.line);
|
||||
var inList = eolState.list !== false;
|
||||
var inQuote = eolState.quote !== 0;
|
||||
|
||||
if (!ranges[i].empty() || !inList || !(match = cm.getLine(pos.line).match(listRE))) {
|
||||
var line = cm.getLine(pos.line), match = listRE.exec(line);
|
||||
if (!ranges[i].empty() || (!inList && !inQuote) || !match) {
|
||||
cm.execCommand("newlineAndIndent");
|
||||
return;
|
||||
}
|
||||
var indent = match[1], after = match[4];
|
||||
var bullet = unorderedBullets.indexOf(match[2]) >= 0
|
||||
if (emptyListRE.test(line)) {
|
||||
cm.replaceRange("", {
|
||||
line: pos.line, ch: 0
|
||||
}, {
|
||||
line: pos.line, ch: pos.ch + 1
|
||||
});
|
||||
replacements[i] = "\n";
|
||||
} else {
|
||||
var indent = match[1], after = match[5];
|
||||
var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0
|
||||
? match[2]
|
||||
: (parseInt(match[3], 10) + 1) + ".";
|
||||
: (parseInt(match[3], 10) + 1) + match[4];
|
||||
|
||||
replacements[i] = "\n" + indent + bullet + after;
|
||||
}
|
||||
}
|
||||
|
||||
cm.replaceSelections(replacements);
|
||||
};
|
||||
|
|
2
devtools/client/sourceeditor/codemirror/addon/edit/matchbrackets.js
поставляемый
Normal file → Executable file
2
devtools/client/sourceeditor/codemirror/addon/edit/matchbrackets.js
поставляемый
Normal file → Executable file
|
@ -81,7 +81,7 @@
|
|||
if (marks.length) {
|
||||
// Kludge to work around the IE bug from issue #1193, where text
|
||||
// input stops going to the textare whever this fires.
|
||||
if (ie_lt8 && cm.state.focused) cm.display.input.focus();
|
||||
if (ie_lt8 && cm.state.focused) cm.focus();
|
||||
|
||||
var clear = function() {
|
||||
cm.operation(function() {
|
||||
|
|
4
devtools/client/sourceeditor/codemirror/addon/fold/foldcode.js
поставляемый
Normal file → Executable file
4
devtools/client/sourceeditor/codemirror/addon/fold/foldcode.js
поставляемый
Normal file → Executable file
|
@ -142,4 +142,8 @@
|
|||
return editorOptions[name];
|
||||
return defaultOptions[name];
|
||||
}
|
||||
|
||||
CodeMirror.defineExtension("foldOption", function(options, name) {
|
||||
return getOption(this, options, name);
|
||||
});
|
||||
});
|
||||
|
|
1
devtools/client/sourceeditor/codemirror/addon/fold/foldgutter.css
поставляемый
Normal file → Executable file
1
devtools/client/sourceeditor/codemirror/addon/fold/foldgutter.css
поставляемый
Normal file → Executable file
|
@ -10,7 +10,6 @@
|
|||
}
|
||||
.CodeMirror-foldgutter-open,
|
||||
.CodeMirror-foldgutter-folded {
|
||||
color: #555;
|
||||
cursor: pointer;
|
||||
}
|
||||
.CodeMirror-foldgutter-open:after {
|
||||
|
|
30
devtools/client/sourceeditor/codemirror/addon/fold/foldgutter.js
поставляемый
Normal file → Executable file
30
devtools/client/sourceeditor/codemirror/addon/fold/foldgutter.js
поставляемый
Normal file → Executable file
|
@ -52,13 +52,13 @@
|
|||
function isFolded(cm, line) {
|
||||
var marks = cm.findMarksAt(Pos(line));
|
||||
for (var i = 0; i < marks.length; ++i)
|
||||
if (marks[i].__isFold && marks[i].find().from.line == line) return true;
|
||||
if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i];
|
||||
}
|
||||
|
||||
function marker(spec) {
|
||||
if (typeof spec == "string") {
|
||||
var elt = document.createElement("div");
|
||||
elt.className = spec;
|
||||
elt.className = spec + " CodeMirror-guttermarker-subtle";
|
||||
return elt;
|
||||
} else {
|
||||
return spec.cloneNode(true);
|
||||
|
@ -67,14 +67,16 @@
|
|||
|
||||
function updateFoldInfo(cm, from, to) {
|
||||
var opts = cm.state.foldGutter.options, cur = from;
|
||||
var minSize = cm.foldOption(opts, "minFoldSize");
|
||||
var func = cm.foldOption(opts, "rangeFinder");
|
||||
cm.eachLine(from, to, function(line) {
|
||||
var mark = null;
|
||||
if (isFolded(cm, cur)) {
|
||||
mark = marker(opts.indicatorFolded);
|
||||
} else {
|
||||
var pos = Pos(cur, 0), func = opts.rangeFinder || CodeMirror.fold.auto;
|
||||
var pos = Pos(cur, 0);
|
||||
var range = func && func(cm, pos);
|
||||
if (range && range.from.line + 1 < range.to.line)
|
||||
if (range && range.to.line - range.from.line >= minSize)
|
||||
mark = marker(opts.indicatorOpen);
|
||||
}
|
||||
cm.setGutterMarker(line, opts.gutter, mark);
|
||||
|
@ -92,20 +94,28 @@
|
|||
}
|
||||
|
||||
function onGutterClick(cm, line, gutter) {
|
||||
var opts = cm.state.foldGutter.options;
|
||||
var state = cm.state.foldGutter;
|
||||
if (!state) return;
|
||||
var opts = state.options;
|
||||
if (gutter != opts.gutter) return;
|
||||
cm.foldCode(Pos(line, 0), opts.rangeFinder);
|
||||
var folded = isFolded(cm, line);
|
||||
if (folded) folded.clear();
|
||||
else cm.foldCode(Pos(line, 0), opts.rangeFinder);
|
||||
}
|
||||
|
||||
function onChange(cm) {
|
||||
var state = cm.state.foldGutter, opts = cm.state.foldGutter.options;
|
||||
var state = cm.state.foldGutter;
|
||||
if (!state) return;
|
||||
var opts = state.options;
|
||||
state.from = state.to = 0;
|
||||
clearTimeout(state.changeUpdate);
|
||||
state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600);
|
||||
}
|
||||
|
||||
function onViewportChange(cm) {
|
||||
var state = cm.state.foldGutter, opts = cm.state.foldGutter.options;
|
||||
var state = cm.state.foldGutter;
|
||||
if (!state) return;
|
||||
var opts = state.options;
|
||||
clearTimeout(state.changeUpdate);
|
||||
state.changeUpdate = setTimeout(function() {
|
||||
var vp = cm.getViewport();
|
||||
|
@ -127,7 +137,9 @@
|
|||
}
|
||||
|
||||
function onFold(cm, from) {
|
||||
var state = cm.state.foldGutter, line = from.line;
|
||||
var state = cm.state.foldGutter;
|
||||
if (!state) return;
|
||||
var line = from.line;
|
||||
if (line >= state.from && line < state.to)
|
||||
updateFoldInfo(cm, line, line + 1);
|
||||
}
|
||||
|
|
3
devtools/client/sourceeditor/codemirror/addon/fold/xml-fold.js
поставляемый
Normal file → Executable file
3
devtools/client/sourceeditor/codemirror/addon/fold/xml-fold.js
поставляемый
Normal file → Executable file
|
@ -151,8 +151,9 @@
|
|||
if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return;
|
||||
var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch);
|
||||
var start = end && toTagStart(iter);
|
||||
if (!end || end == "selfClose" || !start || cmp(iter, pos) > 0) return;
|
||||
if (!end || !start || cmp(iter, pos) > 0) return;
|
||||
var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]};
|
||||
if (end == "selfClose") return {open: here, close: null, at: "open"};
|
||||
|
||||
if (start[1]) { // closing tag
|
||||
return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"};
|
||||
|
|
153
devtools/client/sourceeditor/codemirror/addon/hint/show-hint.js
поставляемый
Normal file → Executable file
153
devtools/client/sourceeditor/codemirror/addon/hint/show-hint.js
поставляемый
Normal file → Executable file
|
@ -30,29 +30,39 @@
|
|||
|
||||
if (this.state.completionActive) this.state.completionActive.close();
|
||||
var completion = this.state.completionActive = new Completion(this, options);
|
||||
var getHints = completion.options.hint;
|
||||
if (!getHints) return;
|
||||
if (!completion.options.hint) return;
|
||||
|
||||
CodeMirror.signal(this, "startCompletion", this);
|
||||
if (getHints.async)
|
||||
getHints(this, function(hints) { completion.showHints(hints); }, completion.options);
|
||||
else
|
||||
return completion.showHints(getHints(this, completion.options));
|
||||
completion.update(true);
|
||||
});
|
||||
|
||||
function Completion(cm, options) {
|
||||
this.cm = cm;
|
||||
this.options = this.buildOptions(options);
|
||||
this.widget = this.onClose = null;
|
||||
this.widget = null;
|
||||
this.debounce = 0;
|
||||
this.tick = 0;
|
||||
this.startPos = this.cm.getCursor();
|
||||
this.startLen = this.cm.getLine(this.startPos.line).length;
|
||||
|
||||
var self = this;
|
||||
cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
|
||||
}
|
||||
|
||||
var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
|
||||
return setTimeout(fn, 1000/60);
|
||||
};
|
||||
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
|
||||
|
||||
Completion.prototype = {
|
||||
close: function() {
|
||||
if (!this.active()) return;
|
||||
this.cm.state.completionActive = null;
|
||||
this.tick = null;
|
||||
this.cm.off("cursorActivity", this.activityFunc);
|
||||
|
||||
if (this.widget && this.data) CodeMirror.signal(this.data, "close");
|
||||
if (this.widget) this.widget.close();
|
||||
if (this.onClose) this.onClose();
|
||||
CodeMirror.signal(this.cm, "endCompletion", this.cm);
|
||||
},
|
||||
|
||||
|
@ -69,74 +79,51 @@
|
|||
this.close();
|
||||
},
|
||||
|
||||
showHints: function(data) {
|
||||
if (!data || !data.list.length || !this.active()) return this.close();
|
||||
cursorActivity: function() {
|
||||
if (this.debounce) {
|
||||
cancelAnimationFrame(this.debounce);
|
||||
this.debounce = 0;
|
||||
}
|
||||
|
||||
if (this.options.completeSingle && data.list.length == 1)
|
||||
this.pick(data, 0);
|
||||
else
|
||||
this.showWidget(data);
|
||||
var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
|
||||
if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
|
||||
pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
|
||||
(pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
|
||||
this.close();
|
||||
} else {
|
||||
var self = this;
|
||||
this.debounce = requestAnimationFrame(function() {self.update();});
|
||||
if (this.widget) this.widget.disable();
|
||||
}
|
||||
},
|
||||
|
||||
showWidget: function(data) {
|
||||
update: function(first) {
|
||||
if (this.tick == null) return;
|
||||
if (!this.options.hint.async) {
|
||||
this.finishUpdate(this.options.hint(this.cm, this.options), first);
|
||||
} else {
|
||||
var myTick = ++this.tick, self = this;
|
||||
this.options.hint(this.cm, function(data) {
|
||||
if (self.tick == myTick) self.finishUpdate(data, first);
|
||||
}, this.options);
|
||||
}
|
||||
},
|
||||
|
||||
finishUpdate: function(data, first) {
|
||||
if (this.data) CodeMirror.signal(this.data, "update");
|
||||
if (data && this.data && CodeMirror.cmpPos(data.from, this.data.from)) data = null;
|
||||
this.data = data;
|
||||
|
||||
var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
|
||||
if (this.widget) this.widget.close();
|
||||
if (data && data.list.length) {
|
||||
if (picked && data.list.length == 1) {
|
||||
this.pick(data, 0);
|
||||
} else {
|
||||
this.widget = new Widget(this, data);
|
||||
CodeMirror.signal(data, "shown");
|
||||
|
||||
var debounce = 0, completion = this, finished;
|
||||
var closeOn = this.options.closeCharacters;
|
||||
var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;
|
||||
|
||||
var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
|
||||
return setTimeout(fn, 1000/60);
|
||||
};
|
||||
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
|
||||
|
||||
function done() {
|
||||
if (finished) return;
|
||||
finished = true;
|
||||
completion.close();
|
||||
completion.cm.off("cursorActivity", activity);
|
||||
if (data) CodeMirror.signal(data, "close");
|
||||
}
|
||||
|
||||
function update() {
|
||||
if (finished) return;
|
||||
CodeMirror.signal(data, "update");
|
||||
var getHints = completion.options.hint;
|
||||
if (getHints.async)
|
||||
getHints(completion.cm, finishUpdate, completion.options);
|
||||
else
|
||||
finishUpdate(getHints(completion.cm, completion.options));
|
||||
}
|
||||
function finishUpdate(data_) {
|
||||
data = data_;
|
||||
if (finished) return;
|
||||
if (!data || !data.list.length) return done();
|
||||
if (completion.widget) completion.widget.close();
|
||||
completion.widget = new Widget(completion, data);
|
||||
}
|
||||
|
||||
function clearDebounce() {
|
||||
if (debounce) {
|
||||
cancelAnimationFrame(debounce);
|
||||
debounce = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function activity() {
|
||||
clearDebounce();
|
||||
var pos = completion.cm.getCursor(), line = completion.cm.getLine(pos.line);
|
||||
if (pos.line != startPos.line || line.length - pos.ch != startLen - startPos.ch ||
|
||||
pos.ch < startPos.ch || completion.cm.somethingSelected() ||
|
||||
(pos.ch && closeOn.test(line.charAt(pos.ch - 1)))) {
|
||||
completion.close();
|
||||
} else {
|
||||
debounce = requestAnimationFrame(update);
|
||||
if (completion.widget) completion.widget.close();
|
||||
}
|
||||
}
|
||||
this.cm.on("cursorActivity", activity);
|
||||
this.onClose = done;
|
||||
},
|
||||
|
||||
buildOptions: function(options) {
|
||||
|
@ -201,6 +188,7 @@
|
|||
function Widget(completion, data) {
|
||||
this.completion = completion;
|
||||
this.data = data;
|
||||
this.picked = false;
|
||||
var widget = this, cm = completion.cm;
|
||||
|
||||
var hints = this.hints = document.createElement("ul");
|
||||
|
@ -228,9 +216,9 @@
|
|||
(completion.options.container || document.body).appendChild(hints);
|
||||
var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
|
||||
if (overlapY > 0) {
|
||||
var height = box.bottom - box.top, curTop = box.top - (pos.bottom - pos.top);
|
||||
var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
|
||||
if (curTop - height > 0) { // Fits above cursor
|
||||
hints.style.top = (top = curTop - height) + "px";
|
||||
hints.style.top = (top = pos.top - height) + "px";
|
||||
below = false;
|
||||
} else if (height > winH) {
|
||||
hints.style.height = (winH - 5) + "px";
|
||||
|
@ -243,7 +231,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
var overlapX = box.left - winW;
|
||||
var overlapX = box.right - winW;
|
||||
if (overlapX > 0) {
|
||||
if (box.right - box.left > winW) {
|
||||
hints.style.width = (winW - 5) + "px";
|
||||
|
@ -315,6 +303,13 @@
|
|||
cm.off("scroll", this.onScroll);
|
||||
},
|
||||
|
||||
disable: function() {
|
||||
this.completion.cm.removeKeyMap(this.keyMap);
|
||||
var widget = this;
|
||||
this.keyMap = {Enter: function() { widget.picked = true; }};
|
||||
this.completion.cm.addKeyMap(this.keyMap);
|
||||
},
|
||||
|
||||
pick: function() {
|
||||
this.completion.pick(this.data, this.selectedHint);
|
||||
},
|
||||
|
@ -357,18 +352,20 @@
|
|||
|
||||
CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
|
||||
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
|
||||
var to = CodeMirror.Pos(cur.line, token.end);
|
||||
if (token.string && /\w/.test(token.string[token.string.length - 1])) {
|
||||
var term = token.string, from = CodeMirror.Pos(cur.line, token.start);
|
||||
} else {
|
||||
var term = "", from = to;
|
||||
}
|
||||
var found = [];
|
||||
for (var i = 0; i < options.words.length; i++) {
|
||||
var word = options.words[i];
|
||||
if (word.slice(0, token.string.length) == token.string)
|
||||
if (word.slice(0, term.length) == term)
|
||||
found.push(word);
|
||||
}
|
||||
|
||||
if (found.length) return {
|
||||
list: found,
|
||||
from: CodeMirror.Pos(cur.line, token.start),
|
||||
to: CodeMirror.Pos(cur.line, token.end)
|
||||
};
|
||||
if (found.length) return {list: found, from: from, to: to};
|
||||
});
|
||||
|
||||
CodeMirror.commands.autocomplete = CodeMirror.showHint;
|
||||
|
|
32
devtools/client/sourceeditor/codemirror/addon/search/match-highlighter.js
поставляемый
Normal file → Executable file
32
devtools/client/sourceeditor/codemirror/addon/search/match-highlighter.js
поставляемый
Normal file → Executable file
|
@ -8,12 +8,15 @@
|
|||
// document.
|
||||
//
|
||||
// The option can be set to true to simply enable it, or to a
|
||||
// {minChars, style, showToken} object to explicitly configure it.
|
||||
// minChars is the minimum amount of characters that should be
|
||||
// {minChars, style, wordsOnly, showToken, delay} object to explicitly
|
||||
// configure it. minChars is the minimum amount of characters that should be
|
||||
// selected for the behavior to occur, and style is the token style to
|
||||
// apply to the matches. This will be prefixed by "cm-" to create an
|
||||
// actual CSS class name. showToken, when enabled, will cause the
|
||||
// current token to be highlighted when nothing is selected.
|
||||
// actual CSS class name. If wordsOnly is enabled, the matches will be
|
||||
// highlighted only if the selected text is a word. showToken, when enabled,
|
||||
// will cause the current token to be highlighted when nothing is selected.
|
||||
// delay is used to specify how much time to wait, in milliseconds, before
|
||||
// highlighting the matches.
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
|
@ -28,6 +31,7 @@
|
|||
var DEFAULT_MIN_CHARS = 2;
|
||||
var DEFAULT_TOKEN_STYLE = "matchhighlight";
|
||||
var DEFAULT_DELAY = 100;
|
||||
var DEFAULT_WORDS_ONLY = false;
|
||||
|
||||
function State(options) {
|
||||
if (typeof options == "object") {
|
||||
|
@ -35,10 +39,12 @@
|
|||
this.style = options.style;
|
||||
this.showToken = options.showToken;
|
||||
this.delay = options.delay;
|
||||
this.wordsOnly = options.wordsOnly;
|
||||
}
|
||||
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;
|
||||
if (this.wordsOnly == null) this.wordsOnly = DEFAULT_WORDS_ONLY;
|
||||
this.overlay = this.timeout = null;
|
||||
}
|
||||
|
||||
|
@ -81,12 +87,30 @@
|
|||
}
|
||||
var from = cm.getCursor("from"), to = cm.getCursor("to");
|
||||
if (from.line != to.line) return;
|
||||
if (state.wordsOnly && !isWord(cm, from, to)) return;
|
||||
var selection = cm.getRange(from, to).replace(/^\s+|\s+$/g, "");
|
||||
if (selection.length >= state.minChars)
|
||||
cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style));
|
||||
});
|
||||
}
|
||||
|
||||
function isWord(cm, from, to) {
|
||||
var str = cm.getRange(from, to);
|
||||
if (str.match(/^\w+$/) !== null) {
|
||||
if (from.ch > 0) {
|
||||
var pos = {line: from.line, ch: from.ch - 1};
|
||||
var chr = cm.getRange(pos, from);
|
||||
if (chr.match(/\W/) === null) return false;
|
||||
}
|
||||
if (to.ch < cm.getLine(from.line).length) {
|
||||
var pos = {line: to.line, ch: to.ch + 1};
|
||||
var chr = cm.getRange(to, pos);
|
||||
if (chr.match(/\W/) === null) return false;
|
||||
}
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
function boundariesAround(stream, re) {
|
||||
return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) &&
|
||||
(stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos)));
|
||||
|
|
125
devtools/client/sourceeditor/codemirror/addon/search/search.js
поставляемый
Normal file → Executable file
125
devtools/client/sourceeditor/codemirror/addon/search/search.js
поставляемый
Normal file → Executable file
|
@ -18,6 +18,7 @@
|
|||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
function searchOverlay(query, caseInsensitive) {
|
||||
if (typeof query == "string")
|
||||
query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
|
||||
|
@ -39,39 +40,78 @@
|
|||
}
|
||||
|
||||
function SearchState() {
|
||||
this.posFrom = this.posTo = this.query = null;
|
||||
this.posFrom = this.posTo = this.lastQuery = this.query = null;
|
||||
this.overlay = null;
|
||||
}
|
||||
|
||||
function getSearchState(cm) {
|
||||
return cm.state.search || (cm.state.search = new SearchState());
|
||||
}
|
||||
|
||||
function queryCaseInsensitive(query) {
|
||||
return typeof query == "string" && query == query.toLowerCase();
|
||||
}
|
||||
|
||||
function getSearchCursor(cm, query, pos) {
|
||||
// Heuristic: if the query string is all lowercase, do a case insensitive search.
|
||||
return cm.getSearchCursor(query, pos, queryCaseInsensitive(query));
|
||||
}
|
||||
|
||||
function persistentDialog(cm, text, deflt, f) {
|
||||
cm.openDialog(text, f, {
|
||||
value: deflt,
|
||||
selectValueOnOpen: true,
|
||||
closeOnEnter: false,
|
||||
onClose: function() { clearSearch(cm); }
|
||||
});
|
||||
}
|
||||
|
||||
function dialog(cm, text, shortText, deflt, f) {
|
||||
if (cm.openDialog) cm.openDialog(text, f, {value: deflt});
|
||||
if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
|
||||
else f(prompt(shortText, deflt));
|
||||
}
|
||||
|
||||
function confirmDialog(cm, text, shortText, fs) {
|
||||
if (cm.openConfirm) cm.openConfirm(text, fs);
|
||||
else if (confirm(shortText)) fs[0]();
|
||||
}
|
||||
|
||||
function parseString(string) {
|
||||
return string.replace(/\\(.)/g, function(_, ch) {
|
||||
if (ch == "n") return "\n"
|
||||
if (ch == "r") return "\r"
|
||||
return ch
|
||||
})
|
||||
}
|
||||
|
||||
function parseQuery(query) {
|
||||
var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
|
||||
if (isRE) {
|
||||
query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i");
|
||||
if (query.test("")) query = /x^/;
|
||||
} else if (query == "") {
|
||||
query = /x^/;
|
||||
try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
|
||||
catch(e) {} // Not a regular expression after all, do a string search
|
||||
} else {
|
||||
query = parseString(query)
|
||||
}
|
||||
if (typeof query == "string" ? query == "" : query.test(""))
|
||||
query = /x^/;
|
||||
return query;
|
||||
}
|
||||
|
||||
var queryDialog;
|
||||
function doSearch(cm, rev) {
|
||||
|
||||
function startSearch(cm, state, query) {
|
||||
state.queryText = query;
|
||||
state.query = parseQuery(query);
|
||||
cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
|
||||
state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
|
||||
cm.addOverlay(state.overlay);
|
||||
if (cm.showMatchesOnScrollbar) {
|
||||
if (state.annotate) { state.annotate.clear(); state.annotate = null; }
|
||||
state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
|
||||
}
|
||||
}
|
||||
|
||||
function doSearch(cm, rev, persistent) {
|
||||
if (!queryDialog) {
|
||||
let doc = cm.getWrapperElement().ownerDocument;
|
||||
let inp = doc.createElement("input");
|
||||
|
@ -87,21 +127,37 @@
|
|||
queryDialog.appendChild(inp);
|
||||
queryDialog.style.display = "flex";
|
||||
}
|
||||
|
||||
var state = getSearchState(cm);
|
||||
if (state.query) return findNext(cm, rev);
|
||||
dialog(cm, queryDialog, "Search for:", cm.getSelection(), function(query) {
|
||||
cm.operation(function() {
|
||||
if (!query || state.query) return;
|
||||
state.query = parseQuery(query);
|
||||
cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
|
||||
state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
|
||||
cm.addOverlay(state.overlay);
|
||||
var q = cm.getSelection() || state.lastQuery;
|
||||
if (persistent && cm.openDialog) {
|
||||
var hiding = null
|
||||
persistentDialog(cm, queryDialog, q, function(query, event) {
|
||||
CodeMirror.e_stop(event);
|
||||
if (!query) return;
|
||||
if (query != state.queryText) startSearch(cm, state, query);
|
||||
if (hiding) hiding.style.opacity = 1
|
||||
findNext(cm, event.shiftKey, function(_, to) {
|
||||
var dialog
|
||||
if (to.line < 3 && document.querySelector &&
|
||||
(dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) &&
|
||||
dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top)
|
||||
(hiding = dialog).style.opacity = .4
|
||||
})
|
||||
});
|
||||
} else {
|
||||
dialog(cm, queryDialog, "Search for:", q, function(query) {
|
||||
if (query && !state.query) cm.operation(function() {
|
||||
startSearch(cm, state, query);
|
||||
state.posFrom = state.posTo = cm.getCursor();
|
||||
findNext(cm, rev);
|
||||
});
|
||||
});
|
||||
}
|
||||
function findNext(cm, rev) {cm.operation(function() {
|
||||
}
|
||||
|
||||
function findNext(cm, rev, callback) {cm.operation(function() {
|
||||
var state = getSearchState(cm);
|
||||
var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
|
||||
if (!cursor.find(rev)) {
|
||||
|
@ -109,26 +165,26 @@
|
|||
if (!cursor.find(rev)) return;
|
||||
}
|
||||
cm.setSelection(cursor.from(), cursor.to());
|
||||
cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
|
||||
cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20);
|
||||
state.posFrom = cursor.from(); state.posTo = cursor.to();
|
||||
if (callback) callback(cursor.from(), cursor.to())
|
||||
});}
|
||||
|
||||
function clearSearch(cm) {cm.operation(function() {
|
||||
var state = getSearchState(cm);
|
||||
state.lastQuery = state.query;
|
||||
if (!state.query) return;
|
||||
state.query = null;
|
||||
state.query = state.queryText = null;
|
||||
cm.removeOverlay(state.overlay);
|
||||
if (state.annotate) { state.annotate.clear(); state.annotate = null; }
|
||||
});}
|
||||
|
||||
var replaceQueryDialog =
|
||||
'Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
|
||||
var replacementQueryDialog = 'With: <input type="text" style="width: 10em"/>';
|
||||
var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
|
||||
function replace(cm, all) {
|
||||
dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) {
|
||||
if (!query) return;
|
||||
query = parseQuery(query);
|
||||
dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
|
||||
if (all) {
|
||||
' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
|
||||
var replacementQueryDialog = 'With: <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
|
||||
var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>All</button> <button>Stop</button>";
|
||||
|
||||
function replaceAll(cm, query, text) {
|
||||
cm.operation(function() {
|
||||
for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
|
||||
if (typeof query != "string") {
|
||||
|
@ -137,6 +193,19 @@
|
|||
} else cursor.replace(text);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function replace(cm, all) {
|
||||
if (cm.getOption("readOnly")) return;
|
||||
var query = cm.getSelection() || getSearchState(cm).lastQuery;
|
||||
var dialogText = all ? "Replace all:" : "Replace:"
|
||||
dialog(cm, dialogText + replaceQueryDialog, dialogText, query, function(query) {
|
||||
if (!query) return;
|
||||
query = parseQuery(query);
|
||||
dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
|
||||
text = parseString(text)
|
||||
if (all) {
|
||||
replaceAll(cm, query, text)
|
||||
} else {
|
||||
clearSearch(cm);
|
||||
var cursor = getSearchCursor(cm, query, cm.getCursor());
|
||||
|
@ -150,7 +219,8 @@
|
|||
cm.setSelection(cursor.from(), cursor.to());
|
||||
cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
|
||||
confirmDialog(cm, doReplaceConfirm, "Replace?",
|
||||
[function() {doReplace(match);}, advance]);
|
||||
[function() {doReplace(match);}, advance,
|
||||
function() {replaceAll(cm, query, text)}]);
|
||||
};
|
||||
var doReplace = function(match) {
|
||||
cursor.replace(typeof query == "string" ? text :
|
||||
|
@ -164,6 +234,7 @@
|
|||
}
|
||||
|
||||
CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
|
||||
CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);};
|
||||
CodeMirror.commands.findNext = doSearch;
|
||||
CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
|
||||
CodeMirror.commands.clearSearch = clearSearch;
|
||||
|
|
10
devtools/client/sourceeditor/codemirror/addon/search/searchcursor.js
поставляемый
Normal file → Executable file
10
devtools/client/sourceeditor/codemirror/addon/search/searchcursor.js
поставляемый
Normal file → Executable file
|
@ -107,7 +107,7 @@
|
|||
var from = Pos(pos.line, cut);
|
||||
for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln)
|
||||
if (target[i] != fold(doc.getLine(ln))) return;
|
||||
if (doc.getLine(ln).slice(0, origTarget[last].length) != target[last]) return;
|
||||
if (fold(doc.getLine(ln).slice(0, origTarget[last].length)) != target[last]) return;
|
||||
return {from: from, to: Pos(ln, origTarget[last].length)};
|
||||
}
|
||||
};
|
||||
|
@ -148,10 +148,10 @@
|
|||
from: function() {if (this.atOccurrence) return this.pos.from;},
|
||||
to: function() {if (this.atOccurrence) return this.pos.to;},
|
||||
|
||||
replace: function(newText) {
|
||||
replace: function(newText, origin) {
|
||||
if (!this.atOccurrence) return;
|
||||
var lines = CodeMirror.splitLines(newText);
|
||||
this.doc.replaceRange(lines, this.pos.from, this.pos.to);
|
||||
this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin);
|
||||
this.pos.to = Pos(this.pos.from.line + lines.length - 1,
|
||||
lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
|
||||
}
|
||||
|
@ -177,9 +177,9 @@
|
|||
});
|
||||
|
||||
CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
|
||||
var ranges = [], next;
|
||||
var ranges = [];
|
||||
var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold);
|
||||
while (next = cur.findNext()) {
|
||||
while (cur.findNext()) {
|
||||
if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break;
|
||||
ranges.push({anchor: cur.from(), head: cur.to()});
|
||||
}
|
||||
|
|
4
devtools/client/sourceeditor/codemirror/addon/selection/active-line.js
поставляемый
Normal file → Executable file
4
devtools/client/sourceeditor/codemirror/addon/selection/active-line.js
поставляемый
Normal file → Executable file
|
@ -49,7 +49,9 @@
|
|||
function updateActiveLines(cm, ranges) {
|
||||
var active = [];
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
var line = cm.getLineHandleVisualStart(ranges[i].head.line);
|
||||
var range = ranges[i];
|
||||
if (!range.empty()) continue;
|
||||
var line = cm.getLineHandleVisualStart(range.head.line);
|
||||
if (active[active.length - 1] != line) active.push(line);
|
||||
}
|
||||
if (sameArray(cm.state.activeLines, active)) return;
|
||||
|
|
1
devtools/client/sourceeditor/codemirror/addon/tern/tern.css
поставляемый
Normal file → Executable file
1
devtools/client/sourceeditor/codemirror/addon/tern/tern.css
поставляемый
Normal file → Executable file
|
@ -1,6 +1,7 @@
|
|||
.CodeMirror-Tern-completion {
|
||||
padding-left: 22px;
|
||||
position: relative;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.CodeMirror-Tern-completion:before {
|
||||
position: absolute;
|
||||
|
|
64
devtools/client/sourceeditor/codemirror/addon/tern/tern.js
поставляемый
Normal file → Executable file
64
devtools/client/sourceeditor/codemirror/addon/tern/tern.js
поставляемый
Normal file → Executable file
|
@ -59,6 +59,7 @@
|
|||
this.options = options || {};
|
||||
var plugins = this.options.plugins || (this.options.plugins = {});
|
||||
if (!plugins.doc_comment) plugins.doc_comment = true;
|
||||
this.docs = Object.create(null);
|
||||
if (this.options.useWorker) {
|
||||
this.server = new WorkerServer(this);
|
||||
} else {
|
||||
|
@ -69,7 +70,6 @@
|
|||
plugins: plugins
|
||||
});
|
||||
}
|
||||
this.docs = Object.create(null);
|
||||
this.trackChange = function(doc, change) { trackChange(self, doc, change); };
|
||||
|
||||
this.cachedArgHints = null;
|
||||
|
@ -106,7 +106,9 @@
|
|||
cm.showHint({hint: this.getHint});
|
||||
},
|
||||
|
||||
showType: function(cm, pos, cb) { showType(this, cm, pos, cb); },
|
||||
showType: function(cm, pos, c) { showContextInfo(this, cm, pos, "type", c); },
|
||||
|
||||
showDocs: function(cm, pos, c) { showContextInfo(this, cm, pos, "documentation", c); },
|
||||
|
||||
updateArgHints: function(cm) { updateArgHints(this, cm); },
|
||||
|
||||
|
@ -122,12 +124,21 @@
|
|||
var self = this;
|
||||
var doc = findDoc(this, cm.getDoc());
|
||||
var request = buildRequest(this, doc, query, pos);
|
||||
var extraOptions = request.query && this.options.queryOptions && this.options.queryOptions[request.query.type]
|
||||
if (extraOptions) for (var prop in extraOptions) request.query[prop] = extraOptions[prop];
|
||||
|
||||
this.server.request(request, function (error, data) {
|
||||
if (!error && self.options.responseFilter)
|
||||
data = self.options.responseFilter(doc, query, request, error, data);
|
||||
c(error, data);
|
||||
});
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
if (this.worker) {
|
||||
this.worker.terminate();
|
||||
this.worker = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -205,7 +216,7 @@
|
|||
var completion = data.completions[i], className = typeToIcon(completion.type);
|
||||
if (data.guess) className += " " + cls + "guess";
|
||||
completions.push({text: completion.name + after,
|
||||
displayText: completion.name,
|
||||
displayText: completion.displayName || completion.name,
|
||||
className: className,
|
||||
data: completion});
|
||||
}
|
||||
|
@ -239,8 +250,8 @@
|
|||
|
||||
// Type queries
|
||||
|
||||
function showType(ts, cm, pos, cb) {
|
||||
ts.request(cm, "type", function(error, data) {
|
||||
function showContextInfo(ts, cm, pos, queryName, c) {
|
||||
ts.request(cm, queryName, function(error, data) {
|
||||
if (error) return showError(ts, cm, error);
|
||||
if (ts.options.typeTip) {
|
||||
var tip = ts.options.typeTip(data);
|
||||
|
@ -250,11 +261,13 @@
|
|||
tip.appendChild(document.createTextNode(" — " + data.doc));
|
||||
if (data.url) {
|
||||
tip.appendChild(document.createTextNode(" "));
|
||||
tip.appendChild(elt("a", null, "[docs]")).href = data.url;
|
||||
var child = tip.appendChild(elt("a", null, "[docs]"));
|
||||
child.href = data.url;
|
||||
child.target = "_blank";
|
||||
}
|
||||
}
|
||||
tempTooltip(cm, tip);
|
||||
if (cb) cb();
|
||||
tempTooltip(cm, tip, ts);
|
||||
if (c) c();
|
||||
}, pos);
|
||||
}
|
||||
|
||||
|
@ -431,8 +444,8 @@
|
|||
|
||||
function atInterestingExpression(cm) {
|
||||
var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos);
|
||||
if (tok.start < pos.ch && (tok.type == "comment" || tok.type == "string")) return false;
|
||||
return /\w/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
|
||||
if (tok.start < pos.ch && tok.type == "comment") return false;
|
||||
return /[\w)\]]/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
|
||||
}
|
||||
|
||||
// Variable renaming
|
||||
|
@ -453,11 +466,12 @@
|
|||
ts.request(cm, {type: "refs"}, function(error, data) {
|
||||
if (error) return showError(ts, cm, error);
|
||||
var ranges = [], cur = 0;
|
||||
var curPos = cm.getCursor();
|
||||
for (var i = 0; i < data.refs.length; i++) {
|
||||
var ref = data.refs[i];
|
||||
if (ref.file == name) {
|
||||
ranges.push({anchor: ref.start, head: ref.end});
|
||||
if (cmpPos(cur, ref.start) >= 0 && cmpPos(cur, ref.end) <= 0)
|
||||
if (cmpPos(curPos, ref.start) >= 0 && cmpPos(curPos, ref.end) <= 0)
|
||||
cur = ranges.length - 1;
|
||||
}
|
||||
}
|
||||
|
@ -579,16 +593,34 @@
|
|||
|
||||
// Tooltips
|
||||
|
||||
function tempTooltip(cm, content) {
|
||||
function tempTooltip(cm, content, ts) {
|
||||
if (cm.state.ternTooltip) remove(cm.state.ternTooltip);
|
||||
var where = cm.cursorCoords();
|
||||
var tip = makeTooltip(where.right + 1, where.bottom, content);
|
||||
var tip = cm.state.ternTooltip = makeTooltip(where.right + 1, where.bottom, content);
|
||||
function maybeClear() {
|
||||
old = true;
|
||||
if (!mouseOnTip) clear();
|
||||
}
|
||||
function clear() {
|
||||
cm.state.ternTooltip = null;
|
||||
if (!tip.parentNode) return;
|
||||
cm.off("cursorActivity", clear);
|
||||
cm.off('blur', clear);
|
||||
cm.off('scroll', clear);
|
||||
fadeOut(tip);
|
||||
}
|
||||
setTimeout(clear, 1700);
|
||||
var mouseOnTip = false, old = false;
|
||||
CodeMirror.on(tip, "mousemove", function() { mouseOnTip = true; });
|
||||
CodeMirror.on(tip, "mouseout", function(e) {
|
||||
if (!CodeMirror.contains(tip, e.relatedTarget || e.toElement)) {
|
||||
if (old) clear();
|
||||
else mouseOnTip = false;
|
||||
}
|
||||
});
|
||||
setTimeout(maybeClear, ts.options.hintDelay ? ts.options.hintDelay : 1700);
|
||||
cm.on("cursorActivity", clear);
|
||||
cm.on('blur', clear);
|
||||
cm.on('scroll', clear);
|
||||
}
|
||||
|
||||
function makeTooltip(x, y, content) {
|
||||
|
@ -613,7 +645,7 @@
|
|||
if (ts.options.showError)
|
||||
ts.options.showError(cm, msg);
|
||||
else
|
||||
tempTooltip(cm, String(msg));
|
||||
tempTooltip(cm, String(msg), ts);
|
||||
}
|
||||
|
||||
function closeArgHints(ts) {
|
||||
|
@ -629,7 +661,7 @@
|
|||
// Worker wrapper
|
||||
|
||||
function WorkerServer(ts) {
|
||||
var worker = new Worker(ts.options.workerScript);
|
||||
var worker = ts.worker = new Worker(ts.options.workerScript);
|
||||
worker.postMessage({type: "init",
|
||||
defs: ts.options.defs,
|
||||
plugins: ts.options.plugins,
|
||||
|
|
82
devtools/client/sourceeditor/codemirror/keymap/emacs.js
поставляемый
Normal file → Executable file
82
devtools/client/sourceeditor/codemirror/keymap/emacs.js
поставляемый
Normal file → Executable file
|
@ -132,8 +132,8 @@
|
|||
};
|
||||
}
|
||||
|
||||
function findEnd(cm, by, dir) {
|
||||
var pos = cm.getCursor(), prefix = getPrefix(cm);
|
||||
function findEnd(cm, pos, by, dir) {
|
||||
var prefix = getPrefix(cm);
|
||||
if (prefix < 0) { dir = -dir; prefix = -prefix; }
|
||||
for (var i = 0; i < prefix; ++i) {
|
||||
var newPos = by(cm, pos, dir);
|
||||
|
@ -145,14 +145,31 @@
|
|||
|
||||
function move(by, dir) {
|
||||
var f = function(cm) {
|
||||
cm.extendSelection(findEnd(cm, by, dir));
|
||||
cm.extendSelection(findEnd(cm, cm.getCursor(), by, dir));
|
||||
};
|
||||
f.motion = true;
|
||||
return f;
|
||||
}
|
||||
|
||||
function killTo(cm, by, dir) {
|
||||
kill(cm, cm.getCursor(), findEnd(cm, by, dir), true);
|
||||
var selections = cm.listSelections(), cursor;
|
||||
var i = selections.length;
|
||||
while (i--) {
|
||||
cursor = selections[i].head;
|
||||
kill(cm, cursor, findEnd(cm, cursor, by, dir), true);
|
||||
}
|
||||
}
|
||||
|
||||
function killRegion(cm) {
|
||||
if (cm.somethingSelected()) {
|
||||
var selections = cm.listSelections(), selection;
|
||||
var i = selections.length;
|
||||
while (i--) {
|
||||
selection = selections[i];
|
||||
kill(cm, selection.anchor, selection.head);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function addPrefix(cm, digit) {
|
||||
|
@ -256,7 +273,7 @@
|
|||
|
||||
// Actual keymap
|
||||
|
||||
var keyMap = CodeMirror.keyMap.emacs = {
|
||||
var keyMap = CodeMirror.keyMap.emacs = CodeMirror.normalizeKeyMap({
|
||||
"Ctrl-W": function(cm) {kill(cm, cm.getCursor("start"), cm.getCursor("end"));},
|
||||
"Ctrl-K": repeated(function(cm) {
|
||||
var start = cm.getCursor(), end = cm.clipPos(Pos(start.line));
|
||||
|
@ -283,9 +300,9 @@
|
|||
"Ctrl-F": move(byChar, 1), "Ctrl-B": move(byChar, -1),
|
||||
"Right": move(byChar, 1), "Left": move(byChar, -1),
|
||||
"Ctrl-D": function(cm) { killTo(cm, byChar, 1); },
|
||||
"Delete": function(cm) { killTo(cm, byChar, 1); },
|
||||
"Delete": function(cm) { killRegion(cm) || killTo(cm, byChar, 1); },
|
||||
"Ctrl-H": function(cm) { killTo(cm, byChar, -1); },
|
||||
"Backspace": function(cm) { killTo(cm, byChar, -1); },
|
||||
"Backspace": function(cm) { killRegion(cm) || killTo(cm, byChar, -1); },
|
||||
|
||||
"Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1),
|
||||
"Alt-D": function(cm) { killTo(cm, byWord, 1); },
|
||||
|
@ -309,7 +326,8 @@
|
|||
"Ctrl-Alt-F": move(byExpr, 1), "Ctrl-Alt-B": move(byExpr, -1),
|
||||
|
||||
"Shift-Ctrl-Alt-2": function(cm) {
|
||||
cm.setSelection(findEnd(cm, byExpr, 1), cm.getCursor());
|
||||
var cursor = cm.getCursor();
|
||||
cm.setSelection(findEnd(cm, cursor, byExpr, 1), cursor);
|
||||
},
|
||||
"Ctrl-Alt-T": function(cm) {
|
||||
var leftStart = byExpr(cm, cm.getCursor(), -1), leftEnd = byExpr(cm, leftStart, 1);
|
||||
|
@ -353,43 +371,35 @@
|
|||
"Alt-/": "autocomplete",
|
||||
"Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto",
|
||||
|
||||
"Alt-G": function(cm) {cm.setOption("keyMap", "emacs-Alt-G");},
|
||||
"Ctrl-X": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-X");},
|
||||
"Ctrl-Q": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-Q");},
|
||||
"Ctrl-U": addPrefixMap
|
||||
};
|
||||
|
||||
CodeMirror.keyMap["emacs-Ctrl-X"] = {
|
||||
"Tab": function(cm) {
|
||||
cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit"));
|
||||
},
|
||||
"Ctrl-X": function(cm) {
|
||||
cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor"));
|
||||
},
|
||||
|
||||
"Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": repeated("undo"), "K": "close",
|
||||
"Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); },
|
||||
auto: "emacs", nofallthrough: true, disableInput: true
|
||||
};
|
||||
|
||||
CodeMirror.keyMap["emacs-Alt-G"] = {
|
||||
"G": function(cm) {
|
||||
"Alt-G G": function(cm) {
|
||||
var prefix = getPrefix(cm, true);
|
||||
if (prefix != null && prefix > 0) return cm.setCursor(prefix - 1);
|
||||
|
||||
getInput(cm, "Goto line", function(str) {
|
||||
var num;
|
||||
if (str && !isNaN(num = Number(str)) && num == num|0 && num > 0)
|
||||
if (str && !isNaN(num = Number(str)) && num == (num|0) && num > 0)
|
||||
cm.setCursor(num - 1);
|
||||
});
|
||||
},
|
||||
auto: "emacs", nofallthrough: true, disableInput: true
|
||||
};
|
||||
|
||||
CodeMirror.keyMap["emacs-Ctrl-Q"] = {
|
||||
"Tab": repeated("insertTab"),
|
||||
auto: "emacs", nofallthrough: true
|
||||
};
|
||||
"Ctrl-X Tab": function(cm) {
|
||||
cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit"));
|
||||
},
|
||||
"Ctrl-X Ctrl-X": function(cm) {
|
||||
cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor"));
|
||||
},
|
||||
"Ctrl-X Ctrl-S": "save",
|
||||
"Ctrl-X Ctrl-W": "save",
|
||||
"Ctrl-X S": "saveAll",
|
||||
"Ctrl-X F": "open",
|
||||
"Ctrl-X U": repeated("undo"),
|
||||
"Ctrl-X K": "close",
|
||||
"Ctrl-X Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); },
|
||||
"Ctrl-X H": "selectAll",
|
||||
|
||||
"Ctrl-Q Tab": repeated("insertTab"),
|
||||
"Ctrl-U": addPrefixMap
|
||||
});
|
||||
|
||||
var prefixMap = {"Ctrl-G": clearPrefix};
|
||||
function regPrefix(d) {
|
||||
|
|
93
devtools/client/sourceeditor/codemirror/keymap/sublime.js
поставляемый
Normal file → Executable file
93
devtools/client/sourceeditor/codemirror/keymap/sublime.js
поставляемый
Normal file → Executable file
|
@ -17,7 +17,8 @@
|
|||
var map = CodeMirror.keyMap.sublime = {fallthrough: "default"};
|
||||
var cmds = CodeMirror.commands;
|
||||
var Pos = CodeMirror.Pos;
|
||||
var ctrl = CodeMirror.keyMap["default"] == CodeMirror.keyMap.pcDefault ? "Ctrl-" : "Cmd-";
|
||||
var mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault;
|
||||
var ctrl = mac ? "Cmd-" : "Ctrl-";
|
||||
|
||||
// This is not exactly Sublime's algorithm. I couldn't make heads or tails of that.
|
||||
function findPosSubword(doc, start, dir) {
|
||||
|
@ -54,7 +55,9 @@
|
|||
cmds[map["Alt-Left"] = "goSubwordLeft"] = function(cm) { moveSubword(cm, -1); };
|
||||
cmds[map["Alt-Right"] = "goSubwordRight"] = function(cm) { moveSubword(cm, 1); };
|
||||
|
||||
cmds[map[ctrl + "Up"] = "scrollLineUp"] = function(cm) {
|
||||
var scrollLineCombo = mac ? "Ctrl-Alt-" : "Ctrl-";
|
||||
|
||||
cmds[map[scrollLineCombo + "Up"] = "scrollLineUp"] = function(cm) {
|
||||
var info = cm.getScrollInfo();
|
||||
if (!cm.somethingSelected()) {
|
||||
var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local");
|
||||
|
@ -63,7 +66,7 @@
|
|||
}
|
||||
cm.scrollTo(null, info.top - cm.defaultTextHeight());
|
||||
};
|
||||
cmds[map[ctrl + "Down"] = "scrollLineDown"] = function(cm) {
|
||||
cmds[map[scrollLineCombo + "Down"] = "scrollLineDown"] = function(cm) {
|
||||
var info = cm.getScrollInfo();
|
||||
if (!cm.somethingSelected()) {
|
||||
var visibleTopLine = cm.lineAtHeight(info.top, "local")+1;
|
||||
|
@ -186,7 +189,9 @@
|
|||
});
|
||||
};
|
||||
|
||||
cmds[map["Shift-" + ctrl + "Up"] = "swapLineUp"] = function(cm) {
|
||||
var swapLineCombo = mac ? "Cmd-Ctrl-" : "Shift-Ctrl-";
|
||||
|
||||
cmds[map[swapLineCombo + "Up"] = "swapLineUp"] = function(cm) {
|
||||
var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = [];
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
var range = ranges[i], from = range.from().line - 1, to = range.to().line;
|
||||
|
@ -212,7 +217,7 @@
|
|||
});
|
||||
};
|
||||
|
||||
cmds[map["Shift-" + ctrl + "Down"] = "swapLineDown"] = function(cm) {
|
||||
cmds[map[swapLineCombo + "Down"] = "swapLineDown"] = function(cm) {
|
||||
var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1;
|
||||
for (var i = ranges.length - 1; i >= 0; i--) {
|
||||
var range = ranges[i], from = range.to().line + 1, to = range.from().line;
|
||||
|
@ -383,9 +388,7 @@
|
|||
|
||||
map["Alt-Q"] = "wrapLines";
|
||||
|
||||
var mapK = CodeMirror.keyMap["sublime-Ctrl-K"] = {auto: "sublime", nofallthrough: true};
|
||||
|
||||
map[ctrl + "K"] = function(cm) {cm.setOption("keyMap", "sublime-Ctrl-K");};
|
||||
var cK = ctrl + "K ";
|
||||
|
||||
function modifyWordOrSelection(cm, mod) {
|
||||
cm.operation(function() {
|
||||
|
@ -406,9 +409,30 @@
|
|||
});
|
||||
}
|
||||
|
||||
mapK[ctrl + "Backspace"] = "delLineLeft";
|
||||
map[cK + ctrl + "Backspace"] = "delLineLeft";
|
||||
|
||||
cmds[mapK[ctrl + "K"] = "delLineRight"] = function(cm) {
|
||||
cmds[map["Backspace"] = "smartBackspace"] = function(cm) {
|
||||
if (cm.somethingSelected()) return CodeMirror.Pass;
|
||||
|
||||
var cursor = cm.getCursor();
|
||||
var toStartOfLine = cm.getRange({line: cursor.line, ch: 0}, cursor);
|
||||
var column = CodeMirror.countColumn(toStartOfLine, null, cm.getOption("tabSize"));
|
||||
var indentUnit = cm.getOption("indentUnit");
|
||||
|
||||
if (toStartOfLine && !/\S/.test(toStartOfLine) && column % indentUnit == 0) {
|
||||
var prevIndent = new Pos(cursor.line,
|
||||
CodeMirror.findColumn(toStartOfLine, column - indentUnit, indentUnit));
|
||||
|
||||
// If no smart delete is happening (due to tab sizing) just do a regular delete
|
||||
if (prevIndent.ch == cursor.ch) return CodeMirror.Pass;
|
||||
|
||||
return cm.replaceRange("", prevIndent, cursor, "+delete");
|
||||
} else {
|
||||
return CodeMirror.Pass;
|
||||
}
|
||||
};
|
||||
|
||||
cmds[map[cK + ctrl + "K"] = "delLineRight"] = function(cm) {
|
||||
cm.operation(function() {
|
||||
var ranges = cm.listSelections();
|
||||
for (var i = ranges.length - 1; i >= 0; i--)
|
||||
|
@ -417,22 +441,22 @@
|
|||
});
|
||||
};
|
||||
|
||||
cmds[mapK[ctrl + "U"] = "upcaseAtCursor"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "U"] = "upcaseAtCursor"] = function(cm) {
|
||||
modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); });
|
||||
};
|
||||
cmds[mapK[ctrl + "L"] = "downcaseAtCursor"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "L"] = "downcaseAtCursor"] = function(cm) {
|
||||
modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); });
|
||||
};
|
||||
|
||||
cmds[mapK[ctrl + "Space"] = "setSublimeMark"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "Space"] = "setSublimeMark"] = function(cm) {
|
||||
if (cm.state.sublimeMark) cm.state.sublimeMark.clear();
|
||||
cm.state.sublimeMark = cm.setBookmark(cm.getCursor());
|
||||
};
|
||||
cmds[mapK[ctrl + "A"] = "selectToSublimeMark"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "A"] = "selectToSublimeMark"] = function(cm) {
|
||||
var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
|
||||
if (found) cm.setSelection(cm.getCursor(), found);
|
||||
};
|
||||
cmds[mapK[ctrl + "W"] = "deleteToSublimeMark"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "W"] = "deleteToSublimeMark"] = function(cm) {
|
||||
var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
|
||||
if (found) {
|
||||
var from = cm.getCursor(), to = found;
|
||||
|
@ -441,7 +465,7 @@
|
|||
cm.replaceRange("", from, to);
|
||||
}
|
||||
};
|
||||
cmds[mapK[ctrl + "X"] = "swapWithSublimeMark"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "X"] = "swapWithSublimeMark"] = function(cm) {
|
||||
var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
|
||||
if (found) {
|
||||
cm.state.sublimeMark.clear();
|
||||
|
@ -449,13 +473,13 @@
|
|||
cm.setCursor(found);
|
||||
}
|
||||
};
|
||||
cmds[mapK[ctrl + "Y"] = "sublimeYank"] = function(cm) {
|
||||
cmds[map[cK + ctrl + "Y"] = "sublimeYank"] = function(cm) {
|
||||
if (cm.state.sublimeKilled != null)
|
||||
cm.replaceSelection(cm.state.sublimeKilled, null, "paste");
|
||||
};
|
||||
|
||||
mapK[ctrl + "G"] = "clearBookmarks";
|
||||
cmds[mapK[ctrl + "C"] = "showInCenter"] = function(cm) {
|
||||
map[cK + ctrl + "G"] = "clearBookmarks";
|
||||
cmds[map[cK + ctrl + "C"] = "showInCenter"] = function(cm) {
|
||||
var pos = cm.cursorCoords(null, "local");
|
||||
cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2);
|
||||
};
|
||||
|
@ -481,7 +505,7 @@
|
|||
});
|
||||
};
|
||||
|
||||
function findAndGoTo(cm, forward) {
|
||||
function getTarget(cm) {
|
||||
var from = cm.getCursor("from"), to = cm.getCursor("to");
|
||||
if (CodeMirror.cmpPos(from, to) == 0) {
|
||||
var word = wordAt(cm, from);
|
||||
|
@ -489,9 +513,14 @@
|
|||
from = word.from;
|
||||
to = word.to;
|
||||
}
|
||||
return {from: from, to: to, query: cm.getRange(from, to), word: word};
|
||||
}
|
||||
|
||||
var query = cm.getRange(from, to);
|
||||
var cur = cm.getSearchCursor(query, forward ? to : from);
|
||||
function findAndGoTo(cm, forward) {
|
||||
var target = getTarget(cm);
|
||||
if (!target) return;
|
||||
var query = target.query;
|
||||
var cur = cm.getSearchCursor(query, forward ? target.to : target.from);
|
||||
|
||||
if (forward ? cur.findNext() : cur.findPrevious()) {
|
||||
cm.setSelection(cur.from(), cur.to());
|
||||
|
@ -500,16 +529,29 @@
|
|||
: cm.clipPos(Pos(cm.lastLine())));
|
||||
if (forward ? cur.findNext() : cur.findPrevious())
|
||||
cm.setSelection(cur.from(), cur.to());
|
||||
else if (word)
|
||||
cm.setSelection(from, to);
|
||||
else if (target.word)
|
||||
cm.setSelection(target.from, target.to);
|
||||
}
|
||||
};
|
||||
cmds[map[ctrl + "F3"] = "findUnder"] = function(cm) { findAndGoTo(cm, true); };
|
||||
cmds[map["Shift-" + ctrl + "F3"] = "findUnderPrevious"] = function(cm) { findAndGoTo(cm,false); };
|
||||
cmds[map["Alt-F3"] = "findAllUnder"] = function(cm) {
|
||||
var target = getTarget(cm);
|
||||
if (!target) return;
|
||||
var cur = cm.getSearchCursor(target.query);
|
||||
var matches = [];
|
||||
var primaryIndex = -1;
|
||||
while (cur.findNext()) {
|
||||
matches.push({anchor: cur.from(), head: cur.to()});
|
||||
if (cur.from().line <= target.from.line && cur.from().ch <= target.from.ch)
|
||||
primaryIndex++;
|
||||
}
|
||||
cm.setSelections(matches, primaryIndex);
|
||||
};
|
||||
|
||||
map["Shift-" + ctrl + "["] = "fold";
|
||||
map["Shift-" + ctrl + "]"] = "unfold";
|
||||
mapK[ctrl + "0"] = mapK[ctrl + "j"] = "unfoldAll";
|
||||
map[cK + ctrl + "0"] = map[cK + ctrl + "j"] = "unfoldAll";
|
||||
|
||||
map[ctrl + "I"] = "findIncremental";
|
||||
map["Shift-" + ctrl + "I"] = "findIncrementalReverse";
|
||||
|
@ -517,4 +559,5 @@
|
|||
map["F3"] = "findNext";
|
||||
map["Shift-F3"] = "findPrev";
|
||||
|
||||
CodeMirror.normalizeKeyMap(map);
|
||||
});
|
||||
|
|
2843
devtools/client/sourceeditor/codemirror/keymap/vim.js
поставляемый
Normal file → Executable file
2843
devtools/client/sourceeditor/codemirror/keymap/vim.js
поставляемый
Normal file → Executable file
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
140
devtools/client/sourceeditor/codemirror/lib/codemirror.css
поставляемый
Normal file → Executable file
140
devtools/client/sourceeditor/codemirror/lib/codemirror.css
поставляемый
Normal file → Executable file
|
@ -4,10 +4,7 @@
|
|||
/* Set height, width, borders, and global font properties here */
|
||||
font-family: monospace;
|
||||
height: 300px;
|
||||
}
|
||||
.CodeMirror-scroll {
|
||||
/* Set scrolling behaviour here */
|
||||
overflow: auto;
|
||||
color: black;
|
||||
}
|
||||
|
||||
/* PADDING */
|
||||
|
@ -36,28 +33,60 @@
|
|||
min-width: 20px;
|
||||
text-align: right;
|
||||
color: #999;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.CodeMirror-guttermarker { color: black; }
|
||||
.CodeMirror-guttermarker-subtle { color: #999; }
|
||||
|
||||
/* CURSOR */
|
||||
|
||||
.CodeMirror div.CodeMirror-cursor {
|
||||
.CodeMirror-cursor {
|
||||
border-left: 1px solid black;
|
||||
border-right: none;
|
||||
width: 0;
|
||||
}
|
||||
/* Shown when moving in bi-directional text */
|
||||
.CodeMirror div.CodeMirror-secondarycursor {
|
||||
border-left: 1px solid silver;
|
||||
}
|
||||
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
|
||||
.cm-fat-cursor .CodeMirror-cursor {
|
||||
width: auto;
|
||||
border: 0;
|
||||
background: #7e7;
|
||||
}
|
||||
/* Can style cursor different in overwrite (non-insert) mode */
|
||||
div.CodeMirror-overwrite div.CodeMirror-cursor {}
|
||||
.cm-fat-cursor div.CodeMirror-cursors {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.cm-tab { display: inline-block; }
|
||||
.cm-animate-fat-cursor {
|
||||
width: auto;
|
||||
border: 0;
|
||||
-webkit-animation: blink 1.06s steps(1) infinite;
|
||||
-moz-animation: blink 1.06s steps(1) infinite;
|
||||
animation: blink 1.06s steps(1) infinite;
|
||||
background-color: #7e7;
|
||||
}
|
||||
@-moz-keyframes blink {
|
||||
0% {}
|
||||
50% { background-color: transparent; }
|
||||
100% {}
|
||||
}
|
||||
@-webkit-keyframes blink {
|
||||
0% {}
|
||||
50% { background-color: transparent; }
|
||||
100% {}
|
||||
}
|
||||
@keyframes blink {
|
||||
0% {}
|
||||
50% { background-color: transparent; }
|
||||
100% {}
|
||||
}
|
||||
|
||||
/* Can style cursor different in overwrite (non-insert) mode */
|
||||
.CodeMirror-overwrite .CodeMirror-cursor {}
|
||||
|
||||
.cm-tab { display: inline-block; text-decoration: inherit; }
|
||||
|
||||
.CodeMirror-ruler {
|
||||
border-left: 1px solid #ccc;
|
||||
|
@ -66,6 +95,15 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
|
|||
|
||||
/* DEFAULT THEME */
|
||||
|
||||
.cm-s-default .cm-header {color: blue;}
|
||||
.cm-s-default .cm-quote {color: #090;}
|
||||
.cm-negative {color: #d44;}
|
||||
.cm-positive {color: #292;}
|
||||
.cm-header, .cm-strong {font-weight: bold;}
|
||||
.cm-em {font-style: italic;}
|
||||
.cm-link {text-decoration: underline;}
|
||||
.cm-strikethrough {text-decoration: line-through;}
|
||||
|
||||
.cm-s-default .cm-keyword {color: #708;}
|
||||
.cm-s-default .cm-atom {color: #219;}
|
||||
.cm-s-default .cm-number {color: #164;}
|
||||
|
@ -85,22 +123,19 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
|
|||
.cm-s-default .cm-bracket {color: #997;}
|
||||
.cm-s-default .cm-tag {color: #170;}
|
||||
.cm-s-default .cm-attribute {color: #00c;}
|
||||
.cm-s-default .cm-header {color: blue;}
|
||||
.cm-s-default .cm-quote {color: #090;}
|
||||
.cm-s-default .cm-hr {color: #999;}
|
||||
.cm-s-default .cm-link {color: #00c;}
|
||||
|
||||
.cm-negative {color: #d44;}
|
||||
.cm-positive {color: #292;}
|
||||
.cm-header, .cm-strong {font-weight: bold;}
|
||||
.cm-em {font-style: italic;}
|
||||
.cm-link {text-decoration: underline;}
|
||||
|
||||
.cm-s-default .cm-error {color: #f00;}
|
||||
.cm-invalidchar {color: #f00;}
|
||||
|
||||
.CodeMirror-composing { border-bottom: 2px solid; }
|
||||
|
||||
/* Default styles for common addons */
|
||||
|
||||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
|
||||
.CodeMirror-activeline-background {background: #e8f2ff;}
|
||||
|
||||
/* STOP */
|
||||
|
@ -109,14 +144,13 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||
the editor. You probably shouldn't touch them. */
|
||||
|
||||
.CodeMirror {
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll {
|
||||
overflow: scroll !important; /* Things will break if this is overridden */
|
||||
/* 30px is the magic margin used to hide the element's real scrollbars */
|
||||
/* See overflow: hidden in .CodeMirror */
|
||||
margin-bottom: -30px; margin-right: -30px;
|
||||
|
@ -124,14 +158,10 @@ 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;
|
||||
border-right: 30px solid transparent;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||
|
@ -161,29 +191,42 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||
|
||||
.CodeMirror-gutters {
|
||||
position: absolute; left: 0; top: 0;
|
||||
padding-bottom: 30px;
|
||||
z-index: 3;
|
||||
}
|
||||
.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;
|
||||
margin-bottom: -30px;
|
||||
/* Hack to make IE7 behave */
|
||||
*zoom:1;
|
||||
*display:inline;
|
||||
}
|
||||
.CodeMirror-gutter-wrapper {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
background: none !important;
|
||||
border: none !important;
|
||||
}
|
||||
.CodeMirror-gutter-background {
|
||||
position: absolute;
|
||||
top: 0; bottom: 0;
|
||||
z-index: 4;
|
||||
}
|
||||
.CodeMirror-gutter-elt {
|
||||
position: absolute;
|
||||
cursor: default;
|
||||
z-index: 4;
|
||||
}
|
||||
.CodeMirror-gutter-wrapper {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.CodeMirror-lines {
|
||||
cursor: text;
|
||||
min-height: 1px; /* prevents collapsing before first draw */
|
||||
}
|
||||
.CodeMirror pre {
|
||||
/* Reset some styles that the rest of the page might have set */
|
||||
|
@ -200,6 +243,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||
z-index: 2;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.CodeMirror-wrap pre {
|
||||
word-wrap: break-word;
|
||||
|
@ -221,8 +265,18 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||
|
||||
.CodeMirror-widget {}
|
||||
|
||||
.CodeMirror-wrap .CodeMirror-scroll {
|
||||
overflow-x: hidden;
|
||||
.CodeMirror-code {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Force content-box sizing for the elements where we expect it */
|
||||
.CodeMirror-scroll,
|
||||
.CodeMirror-sizer,
|
||||
.CodeMirror-gutter,
|
||||
.CodeMirror-gutters,
|
||||
.CodeMirror-linenumber {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.CodeMirror-measure {
|
||||
|
@ -232,19 +286,19 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
.CodeMirror-measure pre { position: static; }
|
||||
|
||||
.CodeMirror div.CodeMirror-cursor {
|
||||
position: absolute;
|
||||
border-right: none;
|
||||
width: 0;
|
||||
}
|
||||
.CodeMirror-cursor { position: absolute; }
|
||||
.CodeMirror-measure pre { position: static; }
|
||||
|
||||
div.CodeMirror-cursors {
|
||||
visibility: hidden;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
z-index: 3;
|
||||
}
|
||||
div.CodeMirror-dragcursors {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-focused div.CodeMirror-cursors {
|
||||
visibility: visible;
|
||||
}
|
||||
|
@ -252,6 +306,8 @@ div.CodeMirror-cursors {
|
|||
.CodeMirror-selected { background: #d9d9d9; }
|
||||
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
|
||||
.CodeMirror-crosshair { cursor: crosshair; }
|
||||
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
|
||||
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
|
||||
|
||||
.cm-searching {
|
||||
background: #ffa;
|
||||
|
@ -270,3 +326,9 @@ div.CodeMirror-cursors {
|
|||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
/* See issue #2901 */
|
||||
.cm-tab-wrap-hack:after { content: ''; }
|
||||
|
||||
/* Help users use markselection to safely style text background */
|
||||
span.CodeMirror-selectedtext { background: none; }
|
||||
|
|
3326
devtools/client/sourceeditor/codemirror/lib/codemirror.js
поставляемый
Normal file → Executable file
3326
devtools/client/sourceeditor/codemirror/lib/codemirror.js
поставляемый
Normal file → Executable file
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
286
devtools/client/sourceeditor/codemirror/mode/clike.js
поставляемый
Normal file → Executable file
286
devtools/client/sourceeditor/codemirror/mode/clike.js
поставляемый
Normal file → Executable file
|
@ -16,14 +16,19 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
|
||||
dontAlignCalls = parserConfig.dontAlignCalls,
|
||||
keywords = parserConfig.keywords || {},
|
||||
types = parserConfig.types || {},
|
||||
builtin = parserConfig.builtin || {},
|
||||
blockKeywords = parserConfig.blockKeywords || {},
|
||||
defKeywords = parserConfig.defKeywords || {},
|
||||
atoms = parserConfig.atoms || {},
|
||||
hooks = parserConfig.hooks || {},
|
||||
multiLineStrings = parserConfig.multiLineStrings;
|
||||
multiLineStrings = parserConfig.multiLineStrings,
|
||||
indentStatements = parserConfig.indentStatements !== false,
|
||||
indentSwitch = parserConfig.indentSwitch !== false,
|
||||
namespaceSeparator = parserConfig.namespaceSeparator;
|
||||
var isOperatorChar = /[+\-*&%=<>!?|\/]/;
|
||||
|
||||
var curPunc;
|
||||
var curPunc, isDefKeyword;
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
|
@ -57,12 +62,17 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
stream.eatWhile(isOperatorChar);
|
||||
return "operator";
|
||||
}
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
|
||||
if (namespaceSeparator) while (stream.match(namespaceSeparator))
|
||||
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
|
||||
|
||||
var cur = stream.current();
|
||||
if (keywords.propertyIsEnumerable(cur)) {
|
||||
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
|
||||
if (defKeywords.propertyIsEnumerable(cur)) isDefKeyword = true;
|
||||
return "keyword";
|
||||
}
|
||||
if (types.propertyIsEnumerable(cur)) return "variable-3";
|
||||
if (builtin.propertyIsEnumerable(cur)) {
|
||||
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
|
||||
return "builtin";
|
||||
|
@ -103,9 +113,12 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
this.align = align;
|
||||
this.prev = prev;
|
||||
}
|
||||
function isStatement(type) {
|
||||
return type == "statement" || type == "switchstatement" || type == "namespace";
|
||||
}
|
||||
function pushContext(state, col, type) {
|
||||
var indent = state.indented;
|
||||
if (state.context && state.context.type == "statement")
|
||||
if (state.context && isStatement(state.context.type) && !isStatement(type))
|
||||
indent = state.context.indented;
|
||||
return state.context = new Context(indent, col, type, null, state.context);
|
||||
}
|
||||
|
@ -116,6 +129,19 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
return state.context = state.context.prev;
|
||||
}
|
||||
|
||||
function typeBefore(stream, state) {
|
||||
if (state.prevToken == "variable" || state.prevToken == "variable-3") return true;
|
||||
if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, stream.start))) return true;
|
||||
}
|
||||
|
||||
function isTopScope(context) {
|
||||
for (;;) {
|
||||
if (!context || context.type == "top") return true;
|
||||
if (context.type == "}" && context.prev.type != "namespace") return false;
|
||||
context = context.prev;
|
||||
}
|
||||
}
|
||||
|
||||
// Interface
|
||||
|
||||
return {
|
||||
|
@ -124,7 +150,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
tokenize: null,
|
||||
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
|
||||
indented: 0,
|
||||
startOfLine: true
|
||||
startOfLine: true,
|
||||
prevToken: null
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -136,39 +163,69 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
state.startOfLine = true;
|
||||
}
|
||||
if (stream.eatSpace()) return null;
|
||||
curPunc = null;
|
||||
curPunc = isDefKeyword = null;
|
||||
var style = (state.tokenize || tokenBase)(stream, state);
|
||||
if (style == "comment" || style == "meta") return style;
|
||||
if (ctx.align == null) ctx.align = true;
|
||||
|
||||
if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
|
||||
if ((curPunc == ";" || curPunc == ":" || curPunc == ","))
|
||||
while (isStatement(state.context.type)) popContext(state);
|
||||
else if (curPunc == "{") pushContext(state, stream.column(), "}");
|
||||
else if (curPunc == "[") pushContext(state, stream.column(), "]");
|
||||
else if (curPunc == "(") pushContext(state, stream.column(), ")");
|
||||
else if (curPunc == "}") {
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
while (isStatement(ctx.type)) ctx = popContext(state);
|
||||
if (ctx.type == "}") ctx = popContext(state);
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
while (isStatement(ctx.type)) ctx = popContext(state);
|
||||
}
|
||||
else if (curPunc == ctx.type) popContext(state);
|
||||
else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
|
||||
pushContext(state, stream.column(), "statement");
|
||||
else if (indentStatements &&
|
||||
(((ctx.type == "}" || ctx.type == "top") && curPunc != ";") ||
|
||||
(isStatement(ctx.type) && curPunc == "newstatement"))) {
|
||||
var type = "statement";
|
||||
if (curPunc == "newstatement" && indentSwitch && stream.current() == "switch")
|
||||
type = "switchstatement";
|
||||
else if (style == "keyword" && stream.current() == "namespace")
|
||||
type = "namespace";
|
||||
pushContext(state, stream.column(), type);
|
||||
}
|
||||
|
||||
if (style == "variable" &&
|
||||
((state.prevToken == "def" ||
|
||||
(parserConfig.typeFirstDefinitions && typeBefore(stream, state) &&
|
||||
isTopScope(state.context) && stream.match(/^\s*\(/, false)))))
|
||||
style = "def";
|
||||
|
||||
if (hooks.token) {
|
||||
var result = hooks.token(stream, state, style);
|
||||
if (result !== undefined) style = result;
|
||||
}
|
||||
|
||||
if (style == "def" && parserConfig.styleDefs === false) style = "variable";
|
||||
|
||||
state.startOfLine = false;
|
||||
state.prevToken = isDefKeyword ? "def" : style || curPunc;
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
|
||||
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
|
||||
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
|
||||
if (isStatement(ctx.type) && firstChar == "}") ctx = ctx.prev;
|
||||
var closing = firstChar == ctx.type;
|
||||
if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
|
||||
else if (ctx.align && (!dontAlignCalls || ctx.type != ")")) return ctx.column + (closing ? 0 : 1);
|
||||
else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
|
||||
else return ctx.indented + (closing ? 0 : indentUnit);
|
||||
var switchBlock = ctx.prev && ctx.prev.type == "switchstatement";
|
||||
if (isStatement(ctx.type))
|
||||
return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
|
||||
if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
|
||||
return ctx.column + (closing ? 0 : 1);
|
||||
if (ctx.type == ")" && !closing)
|
||||
return ctx.indented + statementIndentUnit;
|
||||
|
||||
return ctx.indented + (closing ? 0 : indentUnit) +
|
||||
(!closing && switchBlock && !/^(?:case|default)\b/.test(textAfter) ? indentUnit : 0);
|
||||
},
|
||||
|
||||
electricChars: "{}",
|
||||
electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/,
|
||||
blockCommentStart: "/*",
|
||||
blockCommentEnd: "*/",
|
||||
lineComment: "//",
|
||||
|
@ -181,9 +238,10 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
|
||||
"double static else struct entry switch extern typedef float union for unsigned " +
|
||||
"goto while enum void const signed volatile";
|
||||
var cKeywords = "auto if break case register continue return default do sizeof " +
|
||||
"static else struct switch extern typedef float union for " +
|
||||
"goto while enum const volatile";
|
||||
var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t";
|
||||
|
||||
function cppHook(stream, state) {
|
||||
if (!state.startOfLine) return false;
|
||||
|
@ -203,11 +261,21 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
return "meta";
|
||||
}
|
||||
|
||||
function pointerHook(_stream, state) {
|
||||
if (state.prevToken == "variable-3") return "variable-3";
|
||||
return false;
|
||||
}
|
||||
|
||||
function cpp14Literal(stream) {
|
||||
stream.eatWhile(/[\w\.']/);
|
||||
return "number";
|
||||
}
|
||||
|
||||
function cpp11StringHook(stream, state) {
|
||||
stream.backUp(1);
|
||||
// Raw strings.
|
||||
if (stream.match(/(R|u8R|uR|UR|LR)/)) {
|
||||
var match = stream.match(/"(.{0,16})\(/);
|
||||
var match = stream.match(/"([^\s\\()]{0,16})\(/);
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
|
@ -227,6 +295,11 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
return false;
|
||||
}
|
||||
|
||||
function cppLooksLikeConstructor(word) {
|
||||
var lastTwo = /(\w+)::(\w+)$/.exec(word);
|
||||
return lastTwo && lastTwo[1] == lastTwo[2];
|
||||
}
|
||||
|
||||
// C#-style strings where "" escapes a quote.
|
||||
function tokenAtString(stream, state) {
|
||||
var next;
|
||||
|
@ -242,13 +315,13 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
// C++11 raw string literal is <prefix>"<delim>( anything )<delim>", where
|
||||
// <delim> can be a string up to 16 characters long.
|
||||
function tokenRawString(stream, state) {
|
||||
var closingSequence = new RegExp(".*?\\)" + state.cpp11RawStringDelim + '"');
|
||||
var match = stream.match(closingSequence);
|
||||
if (match) {
|
||||
// Escape characters that have special regex meanings.
|
||||
var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&');
|
||||
var match = stream.match(new RegExp(".*?\\)" + delim + '"'));
|
||||
if (match)
|
||||
state.tokenize = null;
|
||||
} else {
|
||||
else
|
||||
stream.skipToEnd();
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
|
@ -260,6 +333,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
words.push(prop);
|
||||
}
|
||||
add(mode.keywords);
|
||||
add(mode.types);
|
||||
add(mode.builtin);
|
||||
add(mode.atoms);
|
||||
if (words.length) {
|
||||
|
@ -274,38 +348,70 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords),
|
||||
types: words(cTypes + " bool _Complex _Bool float_t double_t intptr_t intmax_t " +
|
||||
"int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t " +
|
||||
"uint32_t uint64_t"),
|
||||
blockKeywords: words("case do else for if switch while struct"),
|
||||
atoms: words("null"),
|
||||
hooks: {"#": cppHook},
|
||||
defKeywords: words("struct"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("null true false"),
|
||||
hooks: {"#": cppHook, "*": pointerHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def(["text/x-c++src", "text/x-c++hdr"], {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
|
||||
keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try explicit new " +
|
||||
"static_cast typeid catch operator template typename class friend private " +
|
||||
"this using const_cast inline public throw virtual delete mutable protected " +
|
||||
"wchar_t alignas alignof constexpr decltype nullptr noexcept thread_local final " +
|
||||
"alignas alignof constexpr decltype nullptr noexcept thread_local final " +
|
||||
"static_assert override"),
|
||||
types: words(cTypes + " bool wchar_t"),
|
||||
blockKeywords: words("catch class do else finally for if struct switch try while"),
|
||||
defKeywords: words("class namespace struct enum union"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null"),
|
||||
hooks: {
|
||||
"#": cppHook,
|
||||
"*": pointerHook,
|
||||
"u": cpp11StringHook,
|
||||
"U": cpp11StringHook,
|
||||
"L": cpp11StringHook,
|
||||
"R": cpp11StringHook
|
||||
"R": cpp11StringHook,
|
||||
"0": cpp14Literal,
|
||||
"1": cpp14Literal,
|
||||
"2": cpp14Literal,
|
||||
"3": cpp14Literal,
|
||||
"4": cpp14Literal,
|
||||
"5": cpp14Literal,
|
||||
"6": cpp14Literal,
|
||||
"7": cpp14Literal,
|
||||
"8": cpp14Literal,
|
||||
"9": cpp14Literal,
|
||||
token: function(stream, state, style) {
|
||||
if (style == "variable" && stream.peek() == "(" &&
|
||||
(state.prevToken == ";" || state.prevToken == null ||
|
||||
state.prevToken == "}") &&
|
||||
cppLooksLikeConstructor(stream.current()))
|
||||
return "def";
|
||||
}
|
||||
},
|
||||
namespaceSeparator: "::",
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def("text/x-java", {
|
||||
name: "clike",
|
||||
keywords: words("abstract assert boolean break byte case catch char class const continue default " +
|
||||
"do double else enum extends final finally float for goto if implements import " +
|
||||
"instanceof int interface long native new package private protected public " +
|
||||
"return short static strictfp super switch synchronized this throw throws transient " +
|
||||
"try void volatile while"),
|
||||
keywords: words("abstract assert break case catch class const continue default " +
|
||||
"do else enum extends final finally float for goto if implements import " +
|
||||
"instanceof interface native new package private protected public " +
|
||||
"return static strictfp super switch synchronized this throw throws transient " +
|
||||
"try volatile while"),
|
||||
types: words("byte short int long float double boolean char void Boolean Byte Character Double Float " +
|
||||
"Integer Long Number Object Short String StringBuffer StringBuilder Void"),
|
||||
blockKeywords: words("catch class do else finally for if switch try while"),
|
||||
defKeywords: words("class interface package enum"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null"),
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
|
@ -315,20 +421,23 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
},
|
||||
modeProps: {fold: ["brace", "import"]}
|
||||
});
|
||||
|
||||
def("text/x-csharp", {
|
||||
name: "clike",
|
||||
keywords: words("abstract as base break case catch checked class const continue" +
|
||||
keywords: words("abstract as async await base break case catch checked class const continue" +
|
||||
" default delegate do else enum event explicit extern finally fixed for" +
|
||||
" foreach goto if implicit in interface internal is lock namespace new" +
|
||||
" operator out override params private protected public readonly ref return sealed" +
|
||||
" sizeof stackalloc static struct switch this throw try typeof unchecked" +
|
||||
" unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
|
||||
" global group into join let orderby partial remove select set value var yield"),
|
||||
blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
|
||||
builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
|
||||
" Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
|
||||
types: words("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func" +
|
||||
" Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32" +
|
||||
" UInt64 bool byte char decimal double short int long object" +
|
||||
" sbyte float string ushort uint ulong"),
|
||||
blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
|
||||
defKeywords: words("class interface namespace struct var"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null"),
|
||||
hooks: {
|
||||
"@": function(stream, state) {
|
||||
|
@ -341,6 +450,19 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
function tokenTripleString(stream, state) {
|
||||
var escaped = false;
|
||||
while (!stream.eol()) {
|
||||
if (!escaped && stream.match('"""')) {
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
escaped = stream.next() == "\\" && !escaped;
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
def("text/x-scala", {
|
||||
name: "clike",
|
||||
keywords: words(
|
||||
|
@ -348,51 +470,67 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
/* scala */
|
||||
"abstract case catch class def do else extends false final finally for forSome if " +
|
||||
"implicit import lazy match new null object override package private protected return " +
|
||||
"sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
|
||||
"sealed super this throw trait try type val var while with yield _ : = => <- <: " +
|
||||
"<% >: # @ " +
|
||||
|
||||
/* package scala */
|
||||
"assert assume require print println printf readLine readBoolean readByte readShort " +
|
||||
"readChar readInt readLong readFloat readDouble " +
|
||||
|
||||
":: #:: "
|
||||
),
|
||||
types: words(
|
||||
"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
|
||||
"Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
|
||||
"Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
|
||||
"Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
|
||||
"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
|
||||
"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector " +
|
||||
|
||||
/* package java.lang */
|
||||
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
|
||||
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
|
||||
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
|
||||
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
|
||||
|
||||
|
||||
),
|
||||
multiLineStrings: true,
|
||||
blockKeywords: words("catch class do else finally for forSome if match switch try while"),
|
||||
defKeywords: words("class def object package trait type val var"),
|
||||
atoms: words("true false null"),
|
||||
indentStatements: false,
|
||||
indentSwitch: false,
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
},
|
||||
'"': function(stream, state) {
|
||||
if (!stream.match('""')) return false;
|
||||
state.tokenize = tokenTripleString;
|
||||
return state.tokenize(stream, state);
|
||||
},
|
||||
"'": function(stream) {
|
||||
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
|
||||
return "atom";
|
||||
}
|
||||
}
|
||||
},
|
||||
modeProps: {closeBrackets: {triples: '"'}}
|
||||
});
|
||||
|
||||
def(["x-shader/x-vertex", "x-shader/x-fragment"], {
|
||||
name: "clike",
|
||||
keywords: words("float int bool void " +
|
||||
"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
|
||||
"mat2 mat3 mat4 " +
|
||||
"sampler1D sampler2D sampler3D samplerCube " +
|
||||
"sampler1DShadow sampler2DShadow" +
|
||||
keywords: words("sampler1D sampler2D sampler3D samplerCube " +
|
||||
"sampler1DShadow sampler2DShadow " +
|
||||
"const attribute uniform varying " +
|
||||
"break continue discard return " +
|
||||
"for while do if else struct " +
|
||||
"in out inout"),
|
||||
types: words("float int bool void " +
|
||||
"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
|
||||
"mat2 mat3 mat4"),
|
||||
blockKeywords: words("for while do if else struct"),
|
||||
builtin: words("radians degrees sin cos tan asin acos atan " +
|
||||
"pow exp log exp2 sqrt inversesqrt " +
|
||||
"abs sign floor ceil fract mod min max clamp mix step smootstep " +
|
||||
"abs sign floor ceil fract mod min max clamp mix step smoothstep " +
|
||||
"length distance dot cross normalize ftransform faceforward " +
|
||||
"reflect refract matrixCompMult " +
|
||||
"lessThan lessThanEqual greaterThan greaterThanEqual " +
|
||||
|
@ -409,12 +547,12 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
"gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
|
||||
"gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
|
||||
"gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
|
||||
"gl_FogCoord " +
|
||||
"gl_FogCoord gl_PointCoord " +
|
||||
"gl_Position gl_PointSize gl_ClipVertex " +
|
||||
"gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
|
||||
"gl_TexCoord gl_FogFragCoord " +
|
||||
"gl_FragCoord gl_FrontFacing " +
|
||||
"gl_FragColor gl_FragData gl_FragDepth " +
|
||||
"gl_FragData gl_FragDepth " +
|
||||
"gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
|
||||
"gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
|
||||
"gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
|
||||
|
@ -432,6 +570,48 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
|||
"gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
|
||||
"gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
|
||||
"gl_MaxDrawBuffers"),
|
||||
indentSwitch: false,
|
||||
hooks: {"#": cppHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def("text/x-nesc", {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords + "as atomic async call command component components configuration event generic " +
|
||||
"implementation includes interface module new norace nx_struct nx_union post provides " +
|
||||
"signal task uses abstract extends"),
|
||||
types: words(cTypes),
|
||||
blockKeywords: words("case do else for if switch while struct"),
|
||||
atoms: words("null true false"),
|
||||
hooks: {"#": cppHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def("text/x-objectivec", {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " +
|
||||
"inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
|
||||
types: words(cTypes),
|
||||
atoms: words("YES NO NULL NILL ON OFF true false"),
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$]/);
|
||||
return "keyword";
|
||||
},
|
||||
"#": cppHook
|
||||
},
|
||||
modeProps: {fold: "brace"}
|
||||
});
|
||||
|
||||
def("text/x-squirrel", {
|
||||
name: "clike",
|
||||
keywords: words("base break clone continue const default delete enum extends function in class" +
|
||||
" foreach local resume return this throw typeof yield constructor instanceof static"),
|
||||
types: words(cTypes),
|
||||
blockKeywords: words("case catch class else for foreach if switch try while"),
|
||||
defKeywords: words("function local class"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null"),
|
||||
hooks: {"#": cppHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
|
|
@ -12,18 +12,24 @@
|
|||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("css", function(config, parserConfig) {
|
||||
var provided = parserConfig;
|
||||
if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
|
||||
parserConfig.inline = provided.inline;
|
||||
|
||||
var indentUnit = config.indentUnit,
|
||||
tokenHooks = parserConfig.tokenHooks,
|
||||
documentTypes = parserConfig.documentTypes || {},
|
||||
mediaTypes = parserConfig.mediaTypes || {},
|
||||
mediaFeatures = parserConfig.mediaFeatures || {},
|
||||
mediaValueKeywords = parserConfig.mediaValueKeywords || {},
|
||||
propertyKeywords = parserConfig.propertyKeywords || {},
|
||||
nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
|
||||
fontProperties = parserConfig.fontProperties || {},
|
||||
counterDescriptors = parserConfig.counterDescriptors || {},
|
||||
colorKeywords = parserConfig.colorKeywords || {},
|
||||
valueKeywords = parserConfig.valueKeywords || {},
|
||||
fontProperties = parserConfig.fontProperties || {},
|
||||
allowNested = parserConfig.allowNested;
|
||||
allowNested = parserConfig.allowNested,
|
||||
supportsAtComponent = parserConfig.supportsAtComponent === true;
|
||||
|
||||
var type, override;
|
||||
function ret(style, tp) { type = tp; return style; }
|
||||
|
@ -57,6 +63,11 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
if (/[\d.]/.test(stream.peek())) {
|
||||
stream.eatWhile(/[\w.%]/);
|
||||
return ret("number", "unit");
|
||||
} else if (stream.match(/^-[\w\\\-]+/)) {
|
||||
stream.eatWhile(/[\w\\\-]/);
|
||||
if (stream.match(/^\s*:/, false))
|
||||
return ret("variable-2", "variable-definition");
|
||||
return ret("variable-2", "variable");
|
||||
} else if (stream.match(/^\w+-/)) {
|
||||
return ret("meta", "meta");
|
||||
}
|
||||
|
@ -66,7 +77,9 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
return ret("qualifier", "qualifier");
|
||||
} else if (/[:;{}\[\]\(\)]/.test(ch)) {
|
||||
return ret(null, ch);
|
||||
} else if (ch == "u" && stream.match("rl(")) {
|
||||
} else if ((ch == "u" && stream.match(/rl(-prefix)?\(/)) ||
|
||||
(ch == "d" && stream.match("omain(")) ||
|
||||
(ch == "r" && stream.match("egexp("))) {
|
||||
stream.backUp(1);
|
||||
state.tokenize = tokenParenthesized;
|
||||
return ret("property", "word");
|
||||
|
@ -110,12 +123,13 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
this.prev = prev;
|
||||
}
|
||||
|
||||
function pushContext(state, stream, type) {
|
||||
state.context = new Context(type, stream.indentation() + indentUnit, state.context);
|
||||
function pushContext(state, stream, type, indent) {
|
||||
state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context);
|
||||
return type;
|
||||
}
|
||||
|
||||
function popContext(state) {
|
||||
if (state.context.prev)
|
||||
state.context = state.context.prev;
|
||||
return state.context.type;
|
||||
}
|
||||
|
@ -148,10 +162,15 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
return pushContext(state, stream, "block");
|
||||
} else if (type == "}" && state.context.prev) {
|
||||
return popContext(state);
|
||||
} else if (type == "@media") {
|
||||
return pushContext(state, stream, "media");
|
||||
} else if (type == "@font-face") {
|
||||
return "font_face_before";
|
||||
} else if (supportsAtComponent && /@component/.test(type)) {
|
||||
return pushContext(state, stream, "atComponentBlock");
|
||||
} else if (/^@(-moz-)?document$/.test(type)) {
|
||||
return pushContext(state, stream, "documentTypes");
|
||||
} else if (/^@(media|supports|(-moz-)?document|import)$/.test(type)) {
|
||||
return pushContext(state, stream, "atBlock");
|
||||
} else if (/^@(font-face|counter-style)/.test(type)) {
|
||||
state.stateArg = type;
|
||||
return "restricted_atBlock_before";
|
||||
} else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
|
||||
return "keyframes";
|
||||
} else if (type && type.charAt(0) == "@") {
|
||||
|
@ -182,7 +201,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
override = "string-2";
|
||||
return "maybeprop";
|
||||
} else if (allowNested) {
|
||||
override = stream.match(/^\s*:/, false) ? "property" : "tag";
|
||||
override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
|
||||
return "block";
|
||||
} else {
|
||||
override += " error";
|
||||
|
@ -229,6 +248,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
if (type == "{" || type == "}") return popAndPass(type, stream, state);
|
||||
if (type == ")") return popContext(state);
|
||||
if (type == "(") return pushContext(state, stream, "parens");
|
||||
if (type == "interpolation") return pushContext(state, stream, "interpolation");
|
||||
if (type == "word") wordAsValue(stream);
|
||||
return "parens";
|
||||
};
|
||||
|
@ -241,47 +261,84 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
return pass(type, stream, state);
|
||||
};
|
||||
|
||||
states.media = function(type, stream, state) {
|
||||
if (type == "(") return pushContext(state, stream, "media_parens");
|
||||
if (type == "}") return popAndPass(type, stream, state);
|
||||
states.documentTypes = function(type, stream, state) {
|
||||
if (type == "word" && documentTypes.hasOwnProperty(stream.current())) {
|
||||
override = "tag";
|
||||
return state.context.type;
|
||||
} else {
|
||||
return states.atBlock(type, stream, state);
|
||||
}
|
||||
};
|
||||
|
||||
states.atBlock = function(type, stream, state) {
|
||||
if (type == "(") return pushContext(state, stream, "atBlock_parens");
|
||||
if (type == "}" || type == ";") return popAndPass(type, stream, state);
|
||||
if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
|
||||
|
||||
if (type == "word") {
|
||||
var word = stream.current().toLowerCase();
|
||||
if (word == "only" || word == "not" || word == "and")
|
||||
if (word == "only" || word == "not" || word == "and" || word == "or")
|
||||
override = "keyword";
|
||||
else if (mediaTypes.hasOwnProperty(word))
|
||||
override = "attribute";
|
||||
else if (mediaFeatures.hasOwnProperty(word))
|
||||
override = "property";
|
||||
else if (mediaValueKeywords.hasOwnProperty(word))
|
||||
override = "keyword";
|
||||
else if (propertyKeywords.hasOwnProperty(word))
|
||||
override = "property";
|
||||
else if (nonStandardPropertyKeywords.hasOwnProperty(word))
|
||||
override = "string-2";
|
||||
else if (valueKeywords.hasOwnProperty(word))
|
||||
override = "atom";
|
||||
else if (colorKeywords.hasOwnProperty(word))
|
||||
override = "keyword";
|
||||
else
|
||||
override = "error";
|
||||
}
|
||||
return state.context.type;
|
||||
};
|
||||
|
||||
states.media_parens = function(type, stream, state) {
|
||||
if (type == ")") return popContext(state);
|
||||
if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
|
||||
return states.media(type, stream, state);
|
||||
states.atComponentBlock = function(type, stream, state) {
|
||||
if (type == "}")
|
||||
return popAndPass(type, stream, state);
|
||||
if (type == "{")
|
||||
return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false);
|
||||
if (type == "word")
|
||||
override = "error";
|
||||
return state.context.type;
|
||||
};
|
||||
|
||||
states.font_face_before = function(type, stream, state) {
|
||||
states.atBlock_parens = function(type, stream, state) {
|
||||
if (type == ")") return popContext(state);
|
||||
if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
|
||||
return states.atBlock(type, stream, state);
|
||||
};
|
||||
|
||||
states.restricted_atBlock_before = function(type, stream, state) {
|
||||
if (type == "{")
|
||||
return pushContext(state, stream, "font_face");
|
||||
return pushContext(state, stream, "restricted_atBlock");
|
||||
if (type == "word" && state.stateArg == "@counter-style") {
|
||||
override = "variable";
|
||||
return "restricted_atBlock_before";
|
||||
}
|
||||
return pass(type, stream, state);
|
||||
};
|
||||
|
||||
states.font_face = function(type, stream, state) {
|
||||
if (type == "}") return popContext(state);
|
||||
states.restricted_atBlock = function(type, stream, state) {
|
||||
if (type == "}") {
|
||||
state.stateArg = null;
|
||||
return popContext(state);
|
||||
}
|
||||
if (type == "word") {
|
||||
if (!fontProperties.hasOwnProperty(stream.current().toLowerCase()))
|
||||
if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
|
||||
(state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
|
||||
override = "error";
|
||||
else
|
||||
override = "property";
|
||||
return "maybeprop";
|
||||
}
|
||||
return "font_face";
|
||||
return "restricted_atBlock";
|
||||
};
|
||||
|
||||
states.keyframes = function(type, stream, state) {
|
||||
|
@ -301,15 +358,17 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
states.interpolation = function(type, stream, state) {
|
||||
if (type == "}") return popContext(state);
|
||||
if (type == "{" || type == ";") return popAndPass(type, stream, state);
|
||||
if (type != "variable") override = "error";
|
||||
if (type == "word") override = "variable";
|
||||
else if (type != "variable" && type != "(" && type != ")") override = "error";
|
||||
return "interpolation";
|
||||
};
|
||||
|
||||
return {
|
||||
startState: function(base) {
|
||||
return {tokenize: null,
|
||||
state: "top",
|
||||
context: new Context("top", base || 0, null)};
|
||||
state: parserConfig.inline ? "block" : "top",
|
||||
stateArg: null,
|
||||
context: new Context(parserConfig.inline ? "block" : "top", base || 0, null)};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
|
@ -328,12 +387,18 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
var cx = state.context, ch = textAfter && textAfter.charAt(0);
|
||||
var indent = cx.indent;
|
||||
if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
|
||||
if (cx.prev &&
|
||||
(ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") ||
|
||||
ch == ")" && (cx.type == "parens" || cx.type == "media_parens") ||
|
||||
ch == "{" && (cx.type == "at" || cx.type == "media"))) {
|
||||
indent = cx.indent - indentUnit;
|
||||
if (cx.prev) {
|
||||
if (ch == "}" && (cx.type == "block" || cx.type == "top" ||
|
||||
cx.type == "interpolation" || cx.type == "restricted_atBlock")) {
|
||||
// Resume indentation from parent context.
|
||||
cx = cx.prev;
|
||||
indent = cx.indent;
|
||||
} else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
|
||||
ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
|
||||
// Dedent relative to current context.
|
||||
indent = Math.max(0, cx.indent - indentUnit);
|
||||
cx = cx.prev;
|
||||
}
|
||||
}
|
||||
return indent;
|
||||
},
|
||||
|
@ -353,6 +418,10 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
return keys;
|
||||
}
|
||||
|
||||
var documentTypes_ = [
|
||||
"domain", "regexp", "url", "url-prefix"
|
||||
], documentTypes = keySet(documentTypes_);
|
||||
|
||||
var mediaTypes_ = [
|
||||
"all", "aural", "braille", "handheld", "print", "projection", "screen",
|
||||
"tty", "tv", "embossed"
|
||||
|
@ -366,9 +435,16 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
"min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
|
||||
"max-color", "color-index", "min-color-index", "max-color-index",
|
||||
"monochrome", "min-monochrome", "max-monochrome", "resolution",
|
||||
"min-resolution", "max-resolution", "scan", "grid"
|
||||
"min-resolution", "max-resolution", "scan", "grid", "orientation",
|
||||
"device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
|
||||
"pointer", "any-pointer", "hover", "any-hover"
|
||||
], mediaFeatures = keySet(mediaFeatures_);
|
||||
|
||||
var mediaValueKeywords_ = [
|
||||
"landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
|
||||
"interlace", "progressive"
|
||||
], mediaValueKeywords = keySet(mediaValueKeywords_);
|
||||
|
||||
var propertyKeywords_ = [
|
||||
"align-content", "align-items", "align-self", "alignment-adjust",
|
||||
"alignment-baseline", "anchor-point", "animation", "animation-delay",
|
||||
|
@ -461,13 +537,23 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
"glyph-orientation-vertical", "text-anchor", "writing-mode"
|
||||
], propertyKeywords = keySet(propertyKeywords_);
|
||||
|
||||
var nonStandardPropertyKeywords = [
|
||||
var nonStandardPropertyKeywords_ = [
|
||||
"scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
|
||||
"scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
|
||||
"scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
|
||||
"searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
|
||||
"searchfield-results-decoration", "zoom"
|
||||
], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords);
|
||||
], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
|
||||
|
||||
var fontProperties_ = [
|
||||
"font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
|
||||
"font-stretch", "font-weight", "font-style"
|
||||
], fontProperties = keySet(fontProperties_);
|
||||
|
||||
var counterDescriptors_ = [
|
||||
"additive-symbols", "fallback", "negative", "pad", "prefix", "range",
|
||||
"speak-as", "suffix", "symbols", "system"
|
||||
], counterDescriptors = keySet(counterDescriptors_);
|
||||
|
||||
var colorKeywords_ = [
|
||||
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
|
||||
|
@ -491,54 +577,57 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
|
||||
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
|
||||
"papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
|
||||
"purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown", "salmon",
|
||||
"sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
|
||||
"purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
|
||||
"salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
|
||||
"slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
|
||||
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
|
||||
"whitesmoke", "yellow", "yellowgreen"
|
||||
], colorKeywords = keySet(colorKeywords_);
|
||||
|
||||
var valueKeywords_ = [
|
||||
"above", "absolute", "activeborder", "activecaption", "afar",
|
||||
"after-white-space", "ahead", "alias", "all", "all-scroll", "alternate",
|
||||
"above", "absolute", "activeborder", "additive", "activecaption", "afar",
|
||||
"after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
|
||||
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
|
||||
"arabic-indic", "armenian", "asterisks", "auto", "avoid", "avoid-column", "avoid-page",
|
||||
"arabic-indic", "armenian", "asterisks", "attr", "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",
|
||||
"both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
|
||||
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
|
||||
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
|
||||
"cell", "center", "checkbox", "circle", "cjk-earthly-branch",
|
||||
"cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
|
||||
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
|
||||
"col-resize", "collapse", "column", "compact", "condensed", "contain", "content",
|
||||
"content-box", "context-menu", "continuous", "copy", "cover", "crop",
|
||||
"cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal",
|
||||
"col-resize", "collapse", "column", "column-reverse", "compact", "condensed", "contain", "content",
|
||||
"content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
|
||||
"cross", "crosshair", "currentcolor", "cursive", "cyclic", "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",
|
||||
"disc", "discard", "disclosure-closed", "disclosure-open", "document",
|
||||
"dot-dash", "dot-dot-dash",
|
||||
"dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
|
||||
"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",
|
||||
"ethiopic-halehame-gez", "ethiopic-halehame-om-et",
|
||||
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
|
||||
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et",
|
||||
"ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed",
|
||||
"extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes",
|
||||
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
|
||||
"ethiopic-numeric", "ew-resize", "expanded", "extends", "extra-condensed",
|
||||
"extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
|
||||
"forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
|
||||
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
|
||||
"help", "hidden", "hide", "higher", "highlight", "highlighttext",
|
||||
"hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
|
||||
"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", "keep-all", "khmer",
|
||||
"inline-block", "inline-flex", "inline-table", "inset", "inside", "intrinsic", "invert",
|
||||
"italic", "japanese-formal", "japanese-informal", "justify", "kannada",
|
||||
"katakana", "katakana-iroha", "keep-all", "khmer",
|
||||
"korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
|
||||
"landscape", "lao", "large", "larger", "left", "level", "lighter",
|
||||
"line-through", "linear", "lines", "list-item", "listbox", "listitem",
|
||||
"line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
|
||||
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
|
||||
"lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
|
||||
"lower-roman", "lowercase", "ltr", "malayalam", "match",
|
||||
"lower-roman", "lowercase", "ltr", "malayalam", "match", "matrix", "matrix3d",
|
||||
"media-controls-background", "media-current-time-display",
|
||||
"media-fullscreen-button", "media-mute-button", "media-play-button",
|
||||
"media-return-to-realtime-button", "media-rewind-button",
|
||||
|
@ -550,46 +639,50 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
"mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
|
||||
"narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
|
||||
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
|
||||
"ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
|
||||
"ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
|
||||
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
|
||||
"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",
|
||||
"painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter",
|
||||
"pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
|
||||
"progress", "push-button", "radial-gradient", "radio", "read-only",
|
||||
"read-write", "read-write-plaintext-only", "rectangle", "region",
|
||||
"relative", "repeat", "repeating-linear-gradient",
|
||||
"repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
|
||||
"rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
|
||||
"rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running",
|
||||
"s-resize", "sans-serif", "scale", "scale3d", "scaleX", "scaleY", "scaleZ",
|
||||
"scroll", "scrollbar", "se-resize", "searchfield",
|
||||
"searchfield-cancel-button", "searchfield-decoration",
|
||||
"searchfield-results-button", "searchfield-results-decoration",
|
||||
"semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
|
||||
"single", "skip-white-space", "slide", "slider-horizontal",
|
||||
"simp-chinese-formal", "simp-chinese-informal", "single",
|
||||
"skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
|
||||
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
|
||||
"small", "small-caps", "small-caption", "smaller", "solid", "somali",
|
||||
"source-atop", "source-in", "source-out", "source-over", "space", "square",
|
||||
"square-button", "start", "static", "status-bar", "stretch", "stroke",
|
||||
"sub", "subpixel-antialiased", "super", "sw-resize", "table",
|
||||
"source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square",
|
||||
"square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
|
||||
"subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table",
|
||||
"table-caption", "table-cell", "table-column", "table-column-group",
|
||||
"table-footer-group", "table-header-group", "table-row", "table-row-group",
|
||||
"tamil",
|
||||
"telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
|
||||
"thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
|
||||
"threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
|
||||
"tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
|
||||
"trad-chinese-formal", "trad-chinese-informal",
|
||||
"translate", "translate3d", "translateX", "translateY", "translateZ",
|
||||
"transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
|
||||
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
|
||||
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
|
||||
"vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
|
||||
"var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
|
||||
"visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
|
||||
"window", "windowframe", "windowtext", "x-large", "x-small", "xor",
|
||||
"window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
|
||||
"xx-large", "xx-small"
|
||||
], valueKeywords = keySet(valueKeywords_);
|
||||
|
||||
var fontProperties_ = [
|
||||
"font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
|
||||
"font-stretch", "font-weight", "font-style"
|
||||
], fontProperties = keySet(fontProperties_);
|
||||
|
||||
var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_)
|
||||
.concat(nonStandardPropertyKeywords).concat(colorKeywords_).concat(valueKeywords_);
|
||||
var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_)
|
||||
.concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_)
|
||||
.concat(valueKeywords_);
|
||||
CodeMirror.registerHelper("hintWords", "css", allWords);
|
||||
|
||||
function tokenCComment(stream, state) {
|
||||
|
@ -604,30 +697,18 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
return ["comment", "comment"];
|
||||
}
|
||||
|
||||
function tokenSGMLComment(stream, state) {
|
||||
if (stream.skipTo("-->")) {
|
||||
stream.match("-->");
|
||||
state.tokenize = null;
|
||||
} else {
|
||||
stream.skipToEnd();
|
||||
}
|
||||
return ["comment", "comment"];
|
||||
}
|
||||
|
||||
CodeMirror.defineMIME("text/css", {
|
||||
documentTypes: documentTypes,
|
||||
mediaTypes: mediaTypes,
|
||||
mediaFeatures: mediaFeatures,
|
||||
mediaValueKeywords: mediaValueKeywords,
|
||||
propertyKeywords: propertyKeywords,
|
||||
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||
fontProperties: fontProperties,
|
||||
counterDescriptors: counterDescriptors,
|
||||
colorKeywords: colorKeywords,
|
||||
valueKeywords: valueKeywords,
|
||||
fontProperties: fontProperties,
|
||||
tokenHooks: {
|
||||
"<": function(stream, state) {
|
||||
if (!stream.match("!--")) return false;
|
||||
state.tokenize = tokenSGMLComment;
|
||||
return tokenSGMLComment(stream, state);
|
||||
},
|
||||
"/": function(stream, state) {
|
||||
if (!stream.eat("*")) return false;
|
||||
state.tokenize = tokenCComment;
|
||||
|
@ -640,6 +721,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
CodeMirror.defineMIME("text/x-scss", {
|
||||
mediaTypes: mediaTypes,
|
||||
mediaFeatures: mediaFeatures,
|
||||
mediaValueKeywords: mediaValueKeywords,
|
||||
propertyKeywords: propertyKeywords,
|
||||
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||
colorKeywords: colorKeywords,
|
||||
|
@ -659,7 +741,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
}
|
||||
},
|
||||
":": function(stream) {
|
||||
if (stream.match(/\s*{/))
|
||||
if (stream.match(/\s*\{/))
|
||||
return [null, "{"];
|
||||
return false;
|
||||
},
|
||||
|
@ -681,6 +763,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
CodeMirror.defineMIME("text/x-less", {
|
||||
mediaTypes: mediaTypes,
|
||||
mediaFeatures: mediaFeatures,
|
||||
mediaValueKeywords: mediaValueKeywords,
|
||||
propertyKeywords: propertyKeywords,
|
||||
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||
colorKeywords: colorKeywords,
|
||||
|
@ -700,6 +783,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
}
|
||||
},
|
||||
"@": function(stream) {
|
||||
if (stream.eat("{")) return [null, "interpolation"];
|
||||
if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
|
||||
stream.eatWhile(/[\w\\\-]/);
|
||||
if (stream.match(/^\s*:/, false))
|
||||
|
@ -714,4 +798,26 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
|
|||
helperType: "less"
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-gss", {
|
||||
documentTypes: documentTypes,
|
||||
mediaTypes: mediaTypes,
|
||||
mediaFeatures: mediaFeatures,
|
||||
propertyKeywords: propertyKeywords,
|
||||
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||
fontProperties: fontProperties,
|
||||
counterDescriptors: counterDescriptors,
|
||||
colorKeywords: colorKeywords,
|
||||
valueKeywords: valueKeywords,
|
||||
supportsAtComponent: true,
|
||||
tokenHooks: {
|
||||
"/": function(stream, state) {
|
||||
if (!stream.eat("*")) return false;
|
||||
state.tokenize = tokenCComment;
|
||||
return tokenCComment(stream, state);
|
||||
}
|
||||
},
|
||||
name: "css",
|
||||
helperType: "gss"
|
||||
});
|
||||
|
||||
});
|
||||
|
|
178
devtools/client/sourceeditor/codemirror/mode/htmlmixed.js
поставляемый
Normal file → Executable file
178
devtools/client/sourceeditor/codemirror/mode/htmlmixed.js
поставляемый
Normal file → Executable file
|
@ -9,98 +9,129 @@
|
|||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
|
||||
var htmlMode = CodeMirror.getMode(config, {name: "xml",
|
||||
htmlMode: true,
|
||||
multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
|
||||
multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});
|
||||
var cssMode = CodeMirror.getMode(config, "css");
|
||||
var defaultTags = {
|
||||
script: [
|
||||
["lang", /(javascript|babel)/i, "javascript"],
|
||||
["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, "javascript"],
|
||||
["type", /./, "text/plain"],
|
||||
[null, null, "javascript"]
|
||||
],
|
||||
style: [
|
||||
["lang", /^css$/i, "css"],
|
||||
["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"],
|
||||
["type", /./, "text/plain"],
|
||||
[null, null, "css"]
|
||||
]
|
||||
};
|
||||
|
||||
var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
|
||||
scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
|
||||
mode: CodeMirror.getMode(config, "javascript")});
|
||||
if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
|
||||
var conf = scriptTypesConf[i];
|
||||
scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
|
||||
}
|
||||
scriptTypes.push({matches: /./,
|
||||
mode: CodeMirror.getMode(config, "text/plain")});
|
||||
|
||||
function html(stream, state) {
|
||||
var tagName = state.htmlState.tagName;
|
||||
var style = htmlMode.token(stream, state.htmlState);
|
||||
if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
|
||||
// Script block: mode to change to depends on type attribute
|
||||
var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
|
||||
scriptType = scriptType ? scriptType[1] : "";
|
||||
if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
|
||||
for (var i = 0; i < scriptTypes.length; ++i) {
|
||||
var tp = scriptTypes[i];
|
||||
if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
|
||||
if (tp.mode) {
|
||||
state.token = script;
|
||||
state.localMode = tp.mode;
|
||||
state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
|
||||
state.token = css;
|
||||
state.localMode = cssMode;
|
||||
state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
|
||||
}
|
||||
return style;
|
||||
}
|
||||
function maybeBackup(stream, pat, style) {
|
||||
var cur = stream.current();
|
||||
var close = cur.search(pat), m;
|
||||
if (close > -1) stream.backUp(cur.length - close);
|
||||
else if (m = cur.match(/<\/?$/)) {
|
||||
var cur = stream.current(), close = cur.search(pat);
|
||||
if (close > -1) {
|
||||
stream.backUp(cur.length - close);
|
||||
} else if (cur.match(/<\/?$/)) {
|
||||
stream.backUp(cur.length);
|
||||
if (!stream.match(pat, false)) stream.match(cur);
|
||||
}
|
||||
return style;
|
||||
}
|
||||
function script(stream, state) {
|
||||
if (stream.match(/^<\/\s*script\s*>/i, false)) {
|
||||
state.token = html;
|
||||
state.localState = state.localMode = null;
|
||||
return html(stream, state);
|
||||
}
|
||||
return maybeBackup(stream, /<\/\s*script\s*>/,
|
||||
state.localMode.token(stream, state.localState));
|
||||
}
|
||||
function css(stream, state) {
|
||||
if (stream.match(/^<\/\s*style\s*>/i, false)) {
|
||||
state.token = html;
|
||||
state.localState = state.localMode = null;
|
||||
return html(stream, state);
|
||||
}
|
||||
return maybeBackup(stream, /<\/\s*style\s*>/,
|
||||
cssMode.token(stream, state.localState));
|
||||
|
||||
var attrRegexpCache = {};
|
||||
function getAttrRegexp(attr) {
|
||||
var regexp = attrRegexpCache[attr];
|
||||
if (regexp) return regexp;
|
||||
return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*");
|
||||
}
|
||||
|
||||
function getAttrValue(stream, attr) {
|
||||
var pos = stream.pos, match;
|
||||
while (pos >= 0 && stream.string.charAt(pos) !== "<") pos--;
|
||||
if (pos < 0) return pos;
|
||||
if (match = stream.string.slice(pos, stream.pos).match(getAttrRegexp(attr)))
|
||||
return match[2];
|
||||
return "";
|
||||
}
|
||||
|
||||
function getTagRegexp(tagName, anchored) {
|
||||
return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i");
|
||||
}
|
||||
|
||||
function addTags(from, to) {
|
||||
for (var tag in from) {
|
||||
var dest = to[tag] || (to[tag] = []);
|
||||
var source = from[tag];
|
||||
for (var i = source.length - 1; i >= 0; i--)
|
||||
dest.unshift(source[i])
|
||||
}
|
||||
}
|
||||
|
||||
function findMatchingMode(tagInfo, stream) {
|
||||
for (var i = 0; i < tagInfo.length; i++) {
|
||||
var spec = tagInfo[i];
|
||||
if (!spec[0] || spec[1].test(getAttrValue(stream, spec[0]))) return spec[2];
|
||||
}
|
||||
}
|
||||
|
||||
CodeMirror.defineMode("htmlmixed", function (config, parserConfig) {
|
||||
var htmlMode = CodeMirror.getMode(config, {
|
||||
name: "xml",
|
||||
htmlMode: true,
|
||||
multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
|
||||
multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag
|
||||
});
|
||||
|
||||
var tags = {};
|
||||
var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes;
|
||||
addTags(defaultTags, tags);
|
||||
if (configTags) addTags(configTags, tags);
|
||||
if (configScript) for (var i = configScript.length - 1; i >= 0; i--)
|
||||
tags.script.unshift(["type", configScript[i].matches, configScript[i].mode])
|
||||
|
||||
function html(stream, state) {
|
||||
var tagName = state.htmlState.tagName;
|
||||
var tagInfo = tagName && tags[tagName.toLowerCase()];
|
||||
|
||||
var style = htmlMode.token(stream, state.htmlState), modeSpec;
|
||||
|
||||
if (tagInfo && /\btag\b/.test(style) && stream.current() === ">" &&
|
||||
(modeSpec = findMatchingMode(tagInfo, stream))) {
|
||||
var mode = CodeMirror.getMode(config, modeSpec);
|
||||
var endTagA = getTagRegexp(tagName, true), endTag = getTagRegexp(tagName, false);
|
||||
state.token = function (stream, state) {
|
||||
if (stream.match(endTagA, false)) {
|
||||
state.token = html;
|
||||
state.localState = state.localMode = null;
|
||||
return null;
|
||||
}
|
||||
return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState));
|
||||
};
|
||||
state.localMode = mode;
|
||||
state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, ""));
|
||||
}
|
||||
return style;
|
||||
};
|
||||
|
||||
return {
|
||||
startState: function() {
|
||||
startState: function () {
|
||||
var state = htmlMode.startState();
|
||||
return {token: html, localMode: null, localState: null, htmlState: state};
|
||||
},
|
||||
|
||||
copyState: function(state) {
|
||||
if (state.localState)
|
||||
var local = CodeMirror.copyState(state.localMode, state.localState);
|
||||
copyState: function (state) {
|
||||
var local;
|
||||
if (state.localState) {
|
||||
local = CodeMirror.copyState(state.localMode, state.localState);
|
||||
}
|
||||
return {token: state.token, localMode: state.localMode, localState: local,
|
||||
htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
token: function (stream, state) {
|
||||
return state.token(stream, state);
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
indent: function (state, textAfter) {
|
||||
if (!state.localMode || /^\s*<\//.test(textAfter))
|
||||
return htmlMode.indent(state.htmlState, textAfter);
|
||||
else if (state.localMode.indent)
|
||||
|
@ -109,12 +140,11 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
|
|||
return CodeMirror.Pass;
|
||||
},
|
||||
|
||||
innerMode: function(state) {
|
||||
innerMode: function (state) {
|
||||
return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
|
||||
}
|
||||
};
|
||||
}, "xml", "javascript", "css");
|
||||
|
||||
CodeMirror.defineMIME("text/html", "htmlmixed");
|
||||
}, "xml", "javascript", "css");
|
||||
|
||||
CodeMirror.defineMIME("text/html", "htmlmixed");
|
||||
});
|
||||
|
|
113
devtools/client/sourceeditor/codemirror/mode/javascript.js
поставляемый
Normal file → Executable file
113
devtools/client/sourceeditor/codemirror/mode/javascript.js
поставляемый
Normal file → Executable file
|
@ -19,6 +19,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
var jsonldMode = parserConfig.jsonld;
|
||||
var jsonMode = parserConfig.json || jsonldMode;
|
||||
var isTS = parserConfig.typescript;
|
||||
var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
|
||||
|
||||
// Tokenizer
|
||||
|
||||
|
@ -31,12 +32,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
|
||||
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
|
||||
"var": kw("var"), "const": kw("var"), "let": kw("var"),
|
||||
"function": kw("function"), "catch": kw("catch"),
|
||||
"async": kw("async"), "function": kw("function"), "catch": kw("catch"),
|
||||
"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"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
|
||||
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C
|
||||
"this": kw("this"), "class": kw("class"), "super": kw("atom"),
|
||||
"await": C, "yield": C, "export": kw("export"), "import": kw("import"), "extends": C
|
||||
};
|
||||
|
||||
// Extend the 'normal' keywords with the TypeScript language extensions
|
||||
|
@ -104,6 +105,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
} else if (ch == "0" && stream.eat(/x/i)) {
|
||||
stream.eatWhile(/[\da-f]/i);
|
||||
return ret("number", "number");
|
||||
} else if (ch == "0" && stream.eat(/o/i)) {
|
||||
stream.eatWhile(/[0-7]/i);
|
||||
return ret("number", "number");
|
||||
} else if (ch == "0" && stream.eat(/b/i)) {
|
||||
stream.eatWhile(/[01]/i);
|
||||
return ret("number", "number");
|
||||
} else if (/\d/.test(ch)) {
|
||||
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
|
||||
return ret("number", "number");
|
||||
|
@ -117,7 +124,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
} else if (state.lastType == "operator" || state.lastType == "keyword c" ||
|
||||
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
|
||||
readRegexp(stream);
|
||||
stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
|
||||
stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
|
||||
return ret("regexp", "string-2");
|
||||
} else {
|
||||
stream.eatWhile(isOperatorChar);
|
||||
|
@ -132,8 +139,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
} else if (isOperatorChar.test(ch)) {
|
||||
stream.eatWhile(isOperatorChar);
|
||||
return ret("operator", "operator", stream.current());
|
||||
} else {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
} else if (wordRE.test(ch)) {
|
||||
stream.eatWhile(wordRE);
|
||||
var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
|
||||
return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
|
||||
ret("variable", "variable", word);
|
||||
|
@ -202,8 +209,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
if (--depth == 0) break;
|
||||
} else if (bracket >= 3 && bracket < 6) {
|
||||
++depth;
|
||||
} else if (/[$\w]/.test(ch)) {
|
||||
} else if (wordRE.test(ch)) {
|
||||
sawSomething = true;
|
||||
} else if (/["'\/]/.test(ch)) {
|
||||
return;
|
||||
} else if (sawSomething && !depth) {
|
||||
++pos;
|
||||
break;
|
||||
|
@ -238,7 +247,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
var cc = state.cc;
|
||||
// Communicate our context to the combinators.
|
||||
// (Less wasteful than consing up a hundred closures on every call.)
|
||||
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
|
||||
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
|
||||
|
||||
if (!state.lexical.hasOwnProperty("align"))
|
||||
state.lexical.align = true;
|
||||
|
@ -298,6 +307,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
var result = function() {
|
||||
var state = cx.state, indent = state.indented;
|
||||
if (state.lexical.type == "stat") indent = state.lexical.indented;
|
||||
else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
|
||||
indent = outer.indented;
|
||||
state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
|
||||
};
|
||||
result.lex = true;
|
||||
|
@ -342,10 +353,9 @@ 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);
|
||||
if (type == "class") return cont(pushlex("form"), className, poplex);
|
||||
if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
|
||||
if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
|
||||
return pass(pushlex("stat"), expression, expect(";"), poplex);
|
||||
}
|
||||
function expression(type) {
|
||||
|
@ -363,6 +373,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
|
||||
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
|
||||
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
|
||||
if (type == "async") return cont(expression);
|
||||
if (type == "function") return cont(functiondef, maybeop);
|
||||
if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
|
||||
if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
|
||||
|
@ -388,7 +399,7 @@ 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 == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
|
||||
if (type == "operator") {
|
||||
if (/\+\+|--/.test(value)) return cont(me);
|
||||
if (value == "?") return cont(expression, expect(":"), expr);
|
||||
|
@ -414,13 +425,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
}
|
||||
function arrowBody(type) {
|
||||
findFatArrow(cx.stream, cx.state);
|
||||
if (type == "{") return pass(statement);
|
||||
return pass(expression);
|
||||
return pass(type == "{" ? statement : expression);
|
||||
}
|
||||
function arrowBodyNoComma(type) {
|
||||
findFatArrow(cx.stream, cx.state);
|
||||
if (type == "{") return pass(statement);
|
||||
return pass(expressionNoComma);
|
||||
return pass(type == "{" ? statement : expressionNoComma);
|
||||
}
|
||||
function maybelabel(type) {
|
||||
if (type == ":") return cont(poplex, statement);
|
||||
|
@ -430,15 +439,20 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
if (type == "variable") {cx.marked = "property"; return cont();}
|
||||
}
|
||||
function objprop(type, value) {
|
||||
if (type == "variable") {
|
||||
if (type == "async") {
|
||||
return cont(objprop);
|
||||
} else if (type == "variable" || cx.style == "keyword") {
|
||||
cx.marked = "property";
|
||||
if (value == "get" || value == "set") return cont(getterSetter);
|
||||
return cont(afterprop);
|
||||
} else if (type == "number" || type == "string") {
|
||||
cx.marked = jsonldMode ? "property" : (type + " property");
|
||||
cx.marked = jsonldMode ? "property" : (cx.style + " property");
|
||||
return cont(afterprop);
|
||||
} else if (type == "jsonld-keyword") {
|
||||
return cont(afterprop);
|
||||
} else if (type == "[") {
|
||||
return cont(expression, expect("]"), afterprop);
|
||||
}
|
||||
if (atomicTypes.hasOwnProperty(type)) return cont(afterprop);
|
||||
}
|
||||
function getterSetter(type) {
|
||||
if (type != "variable") return pass(afterprop);
|
||||
|
@ -476,8 +490,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
function maybetype(type) {
|
||||
if (isTS && type == ":") return cont(typedef);
|
||||
}
|
||||
function maybedefault(_, value) {
|
||||
if (value == "=") return cont(expressionNoComma);
|
||||
}
|
||||
function typedef(type) {
|
||||
if (type == "variable"){cx.marked = "variable-3"; return cont();}
|
||||
if (type == "variable") {cx.marked = "variable-3"; return cont();}
|
||||
}
|
||||
function vardef() {
|
||||
return pass(pattern, maybetype, maybeAssign, vardefCont);
|
||||
|
@ -532,20 +549,36 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
}
|
||||
function funarg(type) {
|
||||
if (type == "spread") return cont(funarg);
|
||||
return pass(pattern, maybetype);
|
||||
return pass(pattern, maybetype, maybedefault);
|
||||
}
|
||||
function className(type, value) {
|
||||
if (type == "variable") {register(value); return cont(classNameAfter);}
|
||||
}
|
||||
function classNameAfter(_type, value) {
|
||||
if (value == "extends") return cont(expression);
|
||||
function classNameAfter(type, value) {
|
||||
if (value == "extends") return cont(expression, classNameAfter);
|
||||
if (type == "{") return cont(pushlex("}"), classBody, poplex);
|
||||
}
|
||||
function objlit(type) {
|
||||
if (type == "{") return contCommasep(objprop, "}");
|
||||
function classBody(type, value) {
|
||||
if (type == "variable" || cx.style == "keyword") {
|
||||
if (value == "static") {
|
||||
cx.marked = "keyword";
|
||||
return cont(classBody);
|
||||
}
|
||||
function afterModule(type, value) {
|
||||
if (type == "string") return cont(statement);
|
||||
if (type == "variable") { register(value); return cont(maybeFrom); }
|
||||
cx.marked = "property";
|
||||
if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);
|
||||
return cont(functiondef, classBody);
|
||||
}
|
||||
if (value == "*") {
|
||||
cx.marked = "keyword";
|
||||
return cont(classBody);
|
||||
}
|
||||
if (type == ";") return cont(classBody);
|
||||
if (type == "}") return cont();
|
||||
}
|
||||
function classGetterSetter(type) {
|
||||
if (type != "variable") return pass();
|
||||
cx.marked = "property";
|
||||
return cont();
|
||||
}
|
||||
function afterExport(_type, value) {
|
||||
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
|
||||
|
@ -559,7 +592,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
function importSpec(type, value) {
|
||||
if (type == "{") return contCommasep(importSpec, "}");
|
||||
if (type == "variable") register(value);
|
||||
return cont();
|
||||
if (value == "*") cx.marked = "keyword";
|
||||
return cont(maybeAs);
|
||||
}
|
||||
function maybeAs(_type, value) {
|
||||
if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
|
||||
}
|
||||
function maybeFrom(_type, value) {
|
||||
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
|
||||
|
@ -570,7 +607,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
}
|
||||
function maybeArrayComprehension(type) {
|
||||
if (type == "for") return pass(comprehension, expect("]"));
|
||||
if (type == ",") return cont(commasep(expressionNoComma, "]"));
|
||||
if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
|
||||
return pass(commasep(expressionNoComma, "]"));
|
||||
}
|
||||
function comprehension(type) {
|
||||
|
@ -578,6 +615,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
if (type == "if") return cont(expression, comprehension);
|
||||
}
|
||||
|
||||
function isContinuedStatement(state, textAfter) {
|
||||
return state.lastType == "operator" || state.lastType == "," ||
|
||||
isOperatorChar.test(textAfter.charAt(0)) ||
|
||||
/[,.]/.test(textAfter.charAt(0));
|
||||
}
|
||||
|
||||
// Interface
|
||||
|
||||
return {
|
||||
|
@ -629,18 +672,19 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
else if (type == "form" && firstChar == "{") return lexical.indented;
|
||||
else if (type == "form") return lexical.indented + indentUnit;
|
||||
else if (type == "stat")
|
||||
return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? statementIndent || indentUnit : 0);
|
||||
return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
|
||||
else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
|
||||
return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
|
||||
else if (lexical.align) return lexical.column + (closing ? 0 : 1);
|
||||
else return lexical.indented + (closing ? 0 : indentUnit);
|
||||
},
|
||||
|
||||
electricChars: ":{}",
|
||||
electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
|
||||
blockCommentStart: jsonMode ? null : "/*",
|
||||
blockCommentEnd: jsonMode ? null : "*/",
|
||||
lineComment: jsonMode ? null : "//",
|
||||
fold: "brace",
|
||||
closeBrackets: "()[]{}''\"\"``",
|
||||
|
||||
helperType: jsonMode ? "json" : "javascript",
|
||||
jsonldMode: jsonldMode,
|
||||
|
@ -648,11 +692,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
|||
};
|
||||
});
|
||||
|
||||
CodeMirror.registerHelper("wordChars", "javascript", /[\\w$]/);
|
||||
CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
|
||||
|
||||
CodeMirror.defineMIME("text/javascript", "javascript");
|
||||
CodeMirror.defineMIME("text/ecmascript", "javascript");
|
||||
CodeMirror.defineMIME("application/javascript", "javascript");
|
||||
CodeMirror.defineMIME("application/x-javascript", "javascript");
|
||||
CodeMirror.defineMIME("application/ecmascript", "javascript");
|
||||
CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
|
||||
CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
|
||||
|
|
|
@ -21,7 +21,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
|
|||
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
|
||||
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
|
||||
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
|
||||
'track': true, 'wbr': true},
|
||||
'track': true, 'wbr': true, 'menuitem': true},
|
||||
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
|
||||
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
|
||||
'th': true, 'tr': true},
|
||||
|
@ -109,6 +109,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
inText.isInText = true;
|
||||
|
||||
function inTag(stream, state) {
|
||||
var ch = stream.next();
|
||||
|
|
|
@ -606,6 +606,7 @@ Editor.prototype = {
|
|||
let cm = editors.get(this);
|
||||
this.alignLine(line, align);
|
||||
cm.setCursor({line: line, ch: ch});
|
||||
this.emit("cursorActivity");
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1024,6 +1025,7 @@ Editor.prototype = {
|
|||
this.setupAutoCompletion();
|
||||
} else {
|
||||
cm.setOption(o, v);
|
||||
this.config[o] = v;
|
||||
}
|
||||
|
||||
if (o === "enableCodeFolding") {
|
||||
|
|
|
@ -9,6 +9,9 @@ namespace = "comment_";
|
|||
}
|
||||
|
||||
var simpleProg = "function foo() {\n return bar;\n}";
|
||||
var inlineBlock = "foo(/* bar */ true);";
|
||||
var inlineBlocks = "foo(/* bar */ true, /* baz */ false);";
|
||||
var multiLineInlineBlock = ["above();", "foo(/* bar */ true);", "below();"];
|
||||
|
||||
test("block", "javascript", function(cm) {
|
||||
cm.blockComment(Pos(0, 3), Pos(3, 0), {blockCommentLead: " *"});
|
||||
|
@ -19,6 +22,17 @@ namespace = "comment_";
|
|||
cm.uncomment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"});
|
||||
}, simpleProg, simpleProg);
|
||||
|
||||
test("blockToggle2", "javascript", function(cm) {
|
||||
cm.setCursor({line: 0, ch: 7 /* inside the block comment */});
|
||||
cm.execCommand("toggleComment");
|
||||
}, inlineBlock, "foo(bar true);");
|
||||
|
||||
// This test should work but currently fails.
|
||||
// test("blockToggle3", "javascript", function(cm) {
|
||||
// cm.setCursor({line: 0, ch: 7 /* inside the first block comment */});
|
||||
// cm.execCommand("toggleComment");
|
||||
// }, inlineBlocks, "foo(bar true, /* baz */ false);");
|
||||
|
||||
test("line", "javascript", function(cm) {
|
||||
cm.lineComment(Pos(1, 1), Pos(1, 1));
|
||||
}, simpleProg, "function foo() {\n// return bar;\n}");
|
||||
|
@ -36,6 +50,29 @@ namespace = "comment_";
|
|||
cm.blockComment(Pos(0, 0), Pos(1));
|
||||
}, "def blah()\n return hah\n", "# def blah()\n# return hah\n");
|
||||
|
||||
test("ignoreExternalBlockComments", "javascript", function(cm) {
|
||||
cm.execCommand("toggleComment");
|
||||
}, inlineBlocks, "// " + inlineBlocks);
|
||||
|
||||
test("ignoreExternalBlockComments2", "javascript", function(cm) {
|
||||
cm.setCursor({line: 0, ch: null /* eol */});
|
||||
cm.execCommand("toggleComment");
|
||||
}, inlineBlocks, "// " + inlineBlocks);
|
||||
|
||||
test("ignoreExternalBlockCommentsMultiLineAbove", "javascript", function(cm) {
|
||||
cm.setSelection({line: 0, ch: 0}, {line: 1, ch: 1});
|
||||
cm.execCommand("toggleComment");
|
||||
}, multiLineInlineBlock.join("\n"), ["// " + multiLineInlineBlock[0],
|
||||
"// " + multiLineInlineBlock[1],
|
||||
multiLineInlineBlock[2]].join("\n"));
|
||||
|
||||
test("ignoreExternalBlockCommentsMultiLineBelow", "javascript", function(cm) {
|
||||
cm.setSelection({line: 1, ch: 13 /* after end of block comment */}, {line: 2, ch: 1});
|
||||
cm.execCommand("toggleComment");
|
||||
}, multiLineInlineBlock.join("\n"), [multiLineInlineBlock[0],
|
||||
"// " + multiLineInlineBlock[1],
|
||||
"// " + multiLineInlineBlock[2]].join("\n"));
|
||||
|
||||
test("commentRange", "javascript", function(cm) {
|
||||
cm.blockComment(Pos(1, 2), Pos(1, 13), {fullLines: false});
|
||||
}, simpleProg, "function foo() {\n /*return bar;*/\n}");
|
||||
|
|
|
@ -76,7 +76,7 @@ function runTests(callback) {
|
|||
}
|
||||
}
|
||||
if (!threw) {
|
||||
if (expFail) callback("fail", test.name, message || "expected failure, but succeeded");
|
||||
if (expFail) callback("fail", test.name, message || "expected failure, but passed");
|
||||
else callback("ok", test.name, message);
|
||||
}
|
||||
if (!quit) { // Run next test
|
||||
|
|
|
@ -128,11 +128,20 @@
|
|||
sim("clearMark", "abcde", Pos(0, 2), "Ctrl-Space", "Ctrl-F", "Ctrl-F",
|
||||
"Ctrl-G", "Ctrl-W", txt("abcde"));
|
||||
|
||||
testCM("saveRequested", function(cm) {
|
||||
sim("delRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Delete", txt("cde"));
|
||||
sim("backspaceRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Backspace", txt("cde"));
|
||||
|
||||
testCM("save", function(cm) {
|
||||
var saved = false;
|
||||
CodeMirror.commands.save = function(cm) { saved = cm.getValue(); };
|
||||
cm.triggerOnKeyDown(fakeEvent("Ctrl-X"));
|
||||
cm.triggerOnKeyDown(fakeEvent("Ctrl-S"));
|
||||
is(saved, "hi");
|
||||
}, {value: "hi", keyMap: "emacs"});
|
||||
|
||||
testCM("gotoInvalidLineFloat", function(cm) {
|
||||
cm.openDialog = function(_, cb) { cb("2.2"); };
|
||||
cm.triggerOnKeyDown(fakeEvent("Alt-G"));
|
||||
cm.triggerOnKeyDown(fakeEvent("G"));
|
||||
}, {value: "1\n2\n3\n4", keyMap: "emacs"});
|
||||
})();
|
||||
|
|
63
devtools/client/sourceeditor/test/codemirror/mode/javascript/test.js
поставляемый
Normal file → Executable file
63
devtools/client/sourceeditor/test/codemirror/mode/javascript/test.js
поставляемый
Normal file → Executable file
|
@ -1,3 +1,6 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
var mode = CodeMirror.getMode({indentUnit: 2}, "javascript");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
|
||||
|
@ -14,25 +17,26 @@
|
|||
" [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];",
|
||||
"})();");
|
||||
|
||||
MT("class_body",
|
||||
"[keyword class] [variable Foo] {",
|
||||
" [property constructor]() {}",
|
||||
" [property sayName]() {",
|
||||
" [keyword return] [string-2 `foo${][variable foo][string-2 }oo`];",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
MT("class",
|
||||
"[keyword class] [variable Point] [keyword extends] [variable SuperThing] {",
|
||||
" [[ [string-2 /expr/] ]]: [number 24],",
|
||||
" [property get] [property prop]() { [keyword return] [number 24]; }",
|
||||
" [property constructor]([def x], [def y]) {",
|
||||
" [keyword super]([string 'something']);",
|
||||
" [keyword this].[property x] [operator =] [variable-2 x];",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
MT("module",
|
||||
"[keyword module] [string 'foo'] {",
|
||||
" [keyword export] [keyword let] [def x] [operator =] [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'];",
|
||||
"}");
|
||||
|
||||
|
@ -50,6 +54,12 @@
|
|||
" [keyword yield] [variable-2 i];",
|
||||
"}");
|
||||
|
||||
MT("quotedStringAddition",
|
||||
"[keyword let] [variable f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c];");
|
||||
|
||||
MT("quotedFatArrow",
|
||||
"[keyword let] [variable f] [operator =] [variable a] [operator +] [string '=>'] [operator +] [variable c];");
|
||||
|
||||
MT("fatArrow",
|
||||
"[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);",
|
||||
"[variable a];", // No longer in scope
|
||||
|
@ -70,6 +80,9 @@
|
|||
MT("quasi",
|
||||
"[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");
|
||||
|
||||
MT("quasi_no_function",
|
||||
"[variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");
|
||||
|
||||
MT("indent_statement",
|
||||
"[keyword var] [variable x] [operator =] [number 10]",
|
||||
"[variable x] [operator +=] [variable y] [operator +]",
|
||||
|
@ -104,6 +117,28 @@
|
|||
" [keyword debugger];",
|
||||
"}");
|
||||
|
||||
MT("indent_else",
|
||||
"[keyword for] (;;)",
|
||||
" [keyword if] ([variable foo])",
|
||||
" [keyword if] ([variable bar])",
|
||||
" [number 1];",
|
||||
" [keyword else]",
|
||||
" [number 2];",
|
||||
" [keyword else]",
|
||||
" [number 3];");
|
||||
|
||||
MT("indent_funarg",
|
||||
"[variable foo]([number 10000],",
|
||||
" [keyword function]([def a]) {",
|
||||
" [keyword debugger];",
|
||||
"};");
|
||||
|
||||
MT("indent_below_if",
|
||||
"[keyword for] (;;)",
|
||||
" [keyword if] ([variable foo])",
|
||||
" [number 1];",
|
||||
"[number 2];");
|
||||
|
||||
MT("multilinestring",
|
||||
"[keyword var] [variable x] [operator =] [string 'foo\\]",
|
||||
"[string bar'];");
|
||||
|
@ -111,6 +146,18 @@
|
|||
MT("scary_regexp",
|
||||
"[string-2 /foo[[/]]bar/];");
|
||||
|
||||
MT("indent_strange_array",
|
||||
"[keyword var] [variable x] [operator =] [[",
|
||||
" [number 1],,",
|
||||
" [number 2],",
|
||||
"]];",
|
||||
"[number 10];");
|
||||
|
||||
MT("param_default",
|
||||
"[keyword function] [variable foo]([def x] [operator =] [string-2 `foo${][number 10][string-2 }bar`]) {",
|
||||
" [keyword return] [variable-2 x];",
|
||||
"}");
|
||||
|
||||
var jsonld_mode = CodeMirror.getMode(
|
||||
{indentUnit: 2},
|
||||
{name: "javascript", jsonld: true}
|
||||
|
|
|
@ -3,7 +3,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]);
|
||||
for (var i = 0, e = arr.length; i < e; ++i) f(arr[i], i);
|
||||
}
|
||||
|
||||
function addDoc(cm, width, height) {
|
||||
|
@ -359,6 +359,15 @@ testCM("undoSelectionAsBefore", function(cm) {
|
|||
eq(cm.getSelection(), "abc");
|
||||
});
|
||||
|
||||
testCM("selectionChangeConfusesHistory", function(cm) {
|
||||
cm.replaceSelection("abc", null, "dontmerge");
|
||||
cm.operation(function() {
|
||||
cm.setCursor(Pos(0, 0));
|
||||
cm.replaceSelection("abc", null, "dontmerge");
|
||||
});
|
||||
eq(cm.historySize().undo, 2);
|
||||
});
|
||||
|
||||
testCM("markTextSingleLine", function(cm) {
|
||||
forEach([{a: 0, b: 1, c: "", f: 2, t: 5},
|
||||
{a: 0, b: 4, c: "", f: 0, t: 2},
|
||||
|
@ -507,6 +516,17 @@ testCM("deleteSpanCollapsedInclusiveLeft", function(cm) {
|
|||
cm.replaceRange("", from, to);
|
||||
}, {value: "abc\nX\ndef"});
|
||||
|
||||
testCM("markTextCSS", function(cm) {
|
||||
function present() {
|
||||
var spans = cm.display.lineDiv.getElementsByTagName("span");
|
||||
for (var i = 0; i < spans.length; i++)
|
||||
if (spans[i].style.color == "cyan" && span[i].textContent == "cdefg") return true;
|
||||
}
|
||||
var m = cm.markText(Pos(0, 2), Pos(0, 6), {css: "color: cyan"});
|
||||
m.clear();
|
||||
is(!present());
|
||||
}, {value: "abcdefgh"});
|
||||
|
||||
testCM("bookmark", function(cm) {
|
||||
function p(v) { return v && Pos(v[0], v[1]); }
|
||||
forEach([{a: [1, 0], b: [1, 1], c: "", d: [1, 4]},
|
||||
|
@ -591,6 +611,14 @@ testCM("getAllMarks", function(cm) {
|
|||
eq(cm.getAllMarks().length, 2);
|
||||
});
|
||||
|
||||
testCM("setValueClears", function(cm) {
|
||||
cm.addLineClass(0, "wrap", "foo");
|
||||
var mark = cm.markText(Pos(0, 0), Pos(1, 1), {inclusiveLeft: true, inclusiveRight: true});
|
||||
cm.setValue("foo");
|
||||
is(!cm.lineInfo(0).wrapClass);
|
||||
is(!mark.find());
|
||||
}, {value: "a\nb"});
|
||||
|
||||
testCM("bug577", function(cm) {
|
||||
cm.setValue("a\nb");
|
||||
cm.clearHistory();
|
||||
|
@ -653,7 +681,7 @@ testCM("selectAllNoScroll", function(cm) {
|
|||
});
|
||||
|
||||
testCM("selectionPos", function(cm) {
|
||||
if (phantom) return;
|
||||
if (phantom || cm.getOption("inputStyle") != "textarea") return;
|
||||
cm.setSize(100, 100);
|
||||
addDoc(cm, 200, 100);
|
||||
cm.setSelection(Pos(1, 100), Pos(98, 100));
|
||||
|
@ -783,6 +811,7 @@ testCM("collapsedRangeCoordsChar", function(cm) {
|
|||
}, {value: "123456\nabcdef\nghijkl\nmnopqr\n"});
|
||||
|
||||
testCM("collapsedRangeBetweenLinesSelected", function(cm) {
|
||||
if (cm.getOption("inputStyle") != "textarea") return;
|
||||
var widget = document.createElement("span");
|
||||
widget.textContent = "\u2194";
|
||||
cm.markText(Pos(0, 3), Pos(1, 0), {replacedWith: widget});
|
||||
|
@ -975,6 +1004,14 @@ testCM("wrappingInlineWidget", function(cm) {
|
|||
eq(curR.bottom, cur1.bottom);
|
||||
}, {value: "1 2 3 xxx 4", lineWrapping: true});
|
||||
|
||||
testCM("showEmptyWidgetSpan", function(cm) {
|
||||
var marker = cm.markText(Pos(0, 2), Pos(0, 2), {
|
||||
clearWhenEmpty: false,
|
||||
replacedWith: document.createTextNode("X")
|
||||
});
|
||||
eq(cm.display.view[0].text.textContent, "abXc");
|
||||
}, {value: "abc"});
|
||||
|
||||
testCM("changedInlineWidget", function(cm) {
|
||||
cm.setSize("10em");
|
||||
var w = document.createElement("span");
|
||||
|
@ -1063,6 +1100,7 @@ testCM("measureEndOfLine", function(cm) {
|
|||
}, {mode: "text/html", value: "<!-- foo barrr -->", lineWrapping: true}, ie_lt8 || opera_lt10);
|
||||
|
||||
testCM("scrollVerticallyAndHorizontally", function(cm) {
|
||||
if (cm.getOption("inputStyle") != "textarea") return;
|
||||
cm.setSize(100, 100);
|
||||
addDoc(cm, 40, 40);
|
||||
cm.setCursor(39);
|
||||
|
@ -1291,10 +1329,11 @@ testCM("verticalMovementCommandsWrapping", function(cm) {
|
|||
lineWrapping: true});
|
||||
|
||||
testCM("rtlMovement", function(cm) {
|
||||
if (cm.getOption("inputStyle") != "textarea") return;
|
||||
forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج",
|
||||
"خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر", "خ ة ق",
|
||||
"<img src=\"/בדיקה3.jpg\">"], function(line) {
|
||||
var inv = line.charAt(0) == "خ";
|
||||
"<img src=\"/בדיקה3.jpg\">", "يتم السحب في 05 فبراير 2014"], function(line) {
|
||||
var inv = line.charCodeAt(0) > 128;
|
||||
cm.setValue(line + "\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart");
|
||||
var cursors = byClassName(cm.getWrapperElement(), "CodeMirror-cursors")[0];
|
||||
var cursor = cursors.firstChild;
|
||||
|
@ -1360,7 +1399,7 @@ testCM("lineChangeEvents", function(cm) {
|
|||
});
|
||||
|
||||
testCM("scrollEntirelyToRight", function(cm) {
|
||||
if (phantom) return;
|
||||
if (phantom || cm.getOption("inputStyle") != "textarea") return;
|
||||
addDoc(cm, 500, 2);
|
||||
cm.setCursor(Pos(0, 500));
|
||||
var wrap = cm.getWrapperElement(), cur = byClassName(wrap, "CodeMirror-cursor")[0];
|
||||
|
@ -1407,27 +1446,79 @@ testCM("lineWidgetCautiousRedraw", function(cm) {
|
|||
is(!redrawn);
|
||||
}, {value: "123\n456"});
|
||||
|
||||
|
||||
var knownScrollbarWidth;
|
||||
function scrollbarWidth(measure) {
|
||||
if (knownScrollbarWidth != null) return knownScrollbarWidth;
|
||||
var div = document.createElement('div');
|
||||
div.style.cssText = "width: 50px; height: 50px; overflow-x: scroll";
|
||||
document.body.appendChild(div);
|
||||
knownScrollbarWidth = div.offsetHeight - div.clientHeight;
|
||||
document.body.removeChild(div);
|
||||
return knownScrollbarWidth || 0;
|
||||
}
|
||||
|
||||
testCM("lineWidgetChanged", function(cm) {
|
||||
addDoc(cm, 2, 300);
|
||||
cm.setSize(null, cm.defaultTextHeight() * 50);
|
||||
var halfScrollbarWidth = scrollbarWidth(cm.display.measure)/2;
|
||||
cm.setOption('lineNumbers', true);
|
||||
cm.setSize(600, cm.defaultTextHeight() * 50);
|
||||
cm.scrollTo(null, cm.heightAtLine(125, "local"));
|
||||
|
||||
var expectedWidgetHeight = 60;
|
||||
var expectedLinesInWidget = 3;
|
||||
function w() {
|
||||
var node = document.createElement("div");
|
||||
node.style.cssText = "background: yellow; height: 50px;";
|
||||
// we use these children with just under half width of the line to check measurements are made with correct width
|
||||
// when placed in the measure div.
|
||||
// If the widget is measured at a width much narrower than it is displayed at, the underHalf children will span two lines and break the test.
|
||||
// If the widget is measured at a width much wider than it is displayed at, the overHalf children will combine and break the test.
|
||||
// Note that this test only checks widgets where coverGutter is true, because these require extra styling to get the width right.
|
||||
// It may also be worthwhile to check this for non-coverGutter widgets.
|
||||
// Visually:
|
||||
// Good:
|
||||
// | ------------- display width ------------- |
|
||||
// | ------- widget-width when measured ------ |
|
||||
// | | -- under-half -- | | -- under-half -- | |
|
||||
// | | --- over-half --- | |
|
||||
// | | --- over-half --- | |
|
||||
// Height: measured as 3 lines, same as it will be when actually displayed
|
||||
|
||||
// Bad (too narrow):
|
||||
// | ------------- display width ------------- |
|
||||
// | ------ widget-width when measured ----- | < -- uh oh
|
||||
// | | -- under-half -- | |
|
||||
// | | -- under-half -- | | < -- when measured, shoved to next line
|
||||
// | | --- over-half --- | |
|
||||
// | | --- over-half --- | |
|
||||
// Height: measured as 4 lines, more than expected . Will be displayed as 3 lines!
|
||||
|
||||
// Bad (too wide):
|
||||
// | ------------- display width ------------- |
|
||||
// | -------- widget-width when measured ------- | < -- uh oh
|
||||
// | | -- under-half -- | | -- under-half -- | |
|
||||
// | | --- over-half --- | | --- over-half --- | | < -- when measured, combined on one line
|
||||
// Height: measured as 2 lines, less than expected. Will be displayed as 3 lines!
|
||||
|
||||
var barelyUnderHalfWidthHtml = '<div style="display: inline-block; height: 1px; width: '+(285 - halfScrollbarWidth)+'px;"></div>';
|
||||
var barelyOverHalfWidthHtml = '<div style="display: inline-block; height: 1px; width: '+(305 - halfScrollbarWidth)+'px;"></div>';
|
||||
node.innerHTML = new Array(3).join(barelyUnderHalfWidthHtml) + new Array(3).join(barelyOverHalfWidthHtml);
|
||||
node.style.cssText = "background: yellow;font-size:0;line-height: " + (expectedWidgetHeight/expectedLinesInWidget) + "px;";
|
||||
return node;
|
||||
}
|
||||
var info0 = cm.getScrollInfo();
|
||||
var w0 = cm.addLineWidget(0, w());
|
||||
var w150 = cm.addLineWidget(150, w());
|
||||
var w300 = cm.addLineWidget(300, w());
|
||||
var w0 = cm.addLineWidget(0, w(), { coverGutter: true });
|
||||
var w150 = cm.addLineWidget(150, w(), { coverGutter: true });
|
||||
var w300 = cm.addLineWidget(300, w(), { coverGutter: true });
|
||||
var info1 = cm.getScrollInfo();
|
||||
eq(info0.height + 150, info1.height);
|
||||
eq(info0.top + 50, info1.top);
|
||||
w0.node.style.height = w150.node.style.height = w300.node.style.height = "10px";
|
||||
eq(info0.height + (3 * expectedWidgetHeight), info1.height);
|
||||
eq(info0.top + expectedWidgetHeight, info1.top);
|
||||
expectedWidgetHeight = 12;
|
||||
w0.node.style.lineHeight = w150.node.style.lineHeight = w300.node.style.lineHeight = (expectedWidgetHeight/expectedLinesInWidget) + "px";
|
||||
w0.changed(); w150.changed(); w300.changed();
|
||||
var info2 = cm.getScrollInfo();
|
||||
eq(info0.height + 30, info2.height);
|
||||
eq(info0.top + 10, info2.top);
|
||||
eq(info0.height + (3 * expectedWidgetHeight), info2.height);
|
||||
eq(info0.top + expectedWidgetHeight, info2.top);
|
||||
});
|
||||
|
||||
testCM("getLineNumber", function(cm) {
|
||||
|
@ -1472,33 +1563,48 @@ testCM("jumpTheGap", function(cm) {
|
|||
}, {lineWrapping: true, value: "abc\ndef\nghi\njkl\n"});
|
||||
|
||||
testCM("addLineClass", function(cm) {
|
||||
function cls(line, text, bg, wrap) {
|
||||
function cls(line, text, bg, wrap, gutter) {
|
||||
var i = cm.lineInfo(line);
|
||||
eq(i.textClass, text);
|
||||
eq(i.bgClass, bg);
|
||||
eq(i.wrapClass, wrap);
|
||||
if (typeof i.handle.gutterClass !== 'undefined') {
|
||||
eq(i.handle.gutterClass, gutter);
|
||||
}
|
||||
}
|
||||
cm.addLineClass(0, "text", "foo");
|
||||
cm.addLineClass(0, "text", "bar");
|
||||
cm.addLineClass(1, "background", "baz");
|
||||
cm.addLineClass(1, "wrap", "foo");
|
||||
cls(0, "foo bar", null, null);
|
||||
cls(1, null, "baz", "foo");
|
||||
cm.addLineClass(1, "gutter", "gutter-class");
|
||||
cls(0, "foo bar", null, null, null);
|
||||
cls(1, null, "baz", "foo", "gutter-class");
|
||||
var lines = cm.display.lineDiv;
|
||||
eq(byClassName(lines, "foo").length, 2);
|
||||
eq(byClassName(lines, "bar").length, 1);
|
||||
eq(byClassName(lines, "baz").length, 1);
|
||||
eq(byClassName(lines, "gutter-class").length, 2); // Gutter classes are reflected in 2 nodes
|
||||
cm.removeLineClass(0, "text", "foo");
|
||||
cls(0, "bar", null, null);
|
||||
cls(0, "bar", null, null, null);
|
||||
cm.removeLineClass(0, "text", "foo");
|
||||
cls(0, "bar", null, null);
|
||||
cls(0, "bar", null, null, null);
|
||||
cm.removeLineClass(0, "text", "bar");
|
||||
cls(0, null, null, null);
|
||||
|
||||
cm.addLineClass(1, "wrap", "quux");
|
||||
cls(1, null, "baz", "foo quux");
|
||||
cls(1, null, "baz", "foo quux", "gutter-class");
|
||||
cm.removeLineClass(1, "wrap");
|
||||
cls(1, null, "baz", null);
|
||||
}, {value: "hohoho\n"});
|
||||
cls(1, null, "baz", null, "gutter-class");
|
||||
cm.removeLineClass(1, "gutter", "gutter-class");
|
||||
eq(byClassName(lines, "gutter-class").length, 0);
|
||||
cls(1, null, "baz", null, null);
|
||||
|
||||
cm.addLineClass(1, "gutter", "gutter-class");
|
||||
cls(1, null, "baz", null, "gutter-class");
|
||||
cm.removeLineClass(1, "gutter", "gutter-class");
|
||||
cls(1, null, "baz", null, null);
|
||||
|
||||
}, {value: "hohoho\n", lineNumbers: true});
|
||||
|
||||
testCM("atomicMarker", function(cm) {
|
||||
addDoc(cm, 10, 10);
|
||||
|
@ -1558,9 +1664,19 @@ testCM("selectionBias", function(cm) {
|
|||
eqPos(cm.getCursor(), Pos(0, 1));
|
||||
cm.setCursor(Pos(0, 4));
|
||||
cm.setCursor(Pos(0, 2), null, {bias: 1});
|
||||
eqPos(cm.getCursor(), Pos(0, 3), "A");
|
||||
eqPos(cm.getCursor(), Pos(0, 3));
|
||||
}, {value: "12345"});
|
||||
|
||||
testCM("selectionHomeEnd", function(cm) {
|
||||
cm.markText(Pos(1, 0), Pos(1, 1), {atomic: true, inclusiveLeft: true});
|
||||
cm.markText(Pos(1, 3), Pos(1, 4), {atomic: true, inclusiveRight: true});
|
||||
cm.setCursor(Pos(1, 2));
|
||||
cm.execCommand("goLineStart");
|
||||
eqPos(cm.getCursor(), Pos(1, 1));
|
||||
cm.execCommand("goLineEnd");
|
||||
eqPos(cm.getCursor(), Pos(1, 3));
|
||||
}, {value: "ab\ncdef\ngh"});
|
||||
|
||||
testCM("readOnlyMarker", function(cm) {
|
||||
function mark(ll, cl, lr, cr, at) {
|
||||
return cm.markText(Pos(ll, cl), Pos(lr, cr),
|
||||
|
@ -1904,6 +2020,18 @@ testCM("alwaysMergeSelEventWithChangeOrigin", function(cm) {
|
|||
eq(cm.getValue(), "Va");
|
||||
}, {value: "a"});
|
||||
|
||||
testCM("getTokenAt", function(cm) {
|
||||
var tokPlus = cm.getTokenAt(Pos(0, 2));
|
||||
eq(tokPlus.type, "operator");
|
||||
eq(tokPlus.string, "+");
|
||||
var toks = cm.getLineTokens(0);
|
||||
eq(toks.length, 3);
|
||||
forEach([["number", "1"], ["operator", "+"], ["number", "2"]], function(expect, i) {
|
||||
eq(toks[i].type, expect[0]);
|
||||
eq(toks[i].string, expect[1]);
|
||||
});
|
||||
}, {value: "1+2", mode: "javascript"});
|
||||
|
||||
testCM("getTokenTypeAt", function(cm) {
|
||||
eq(cm.getTokenTypeAt(Pos(0, 0)), "number");
|
||||
eq(cm.getTokenTypeAt(Pos(0, 6)), "string");
|
||||
|
@ -1916,3 +2044,99 @@ testCM("getTokenTypeAt", function(cm) {
|
|||
eq(byClassName(cm.getWrapperElement(), "cm-foo").length, 1);
|
||||
eq(cm.getTokenTypeAt(Pos(0, 6)), "string");
|
||||
}, {value: "1 + 'foo'", mode: "javascript"});
|
||||
|
||||
testCM("resizeLineWidget", function(cm) {
|
||||
addDoc(cm, 200, 3);
|
||||
var widget = document.createElement("pre");
|
||||
widget.innerHTML = "imwidget";
|
||||
widget.style.background = "yellow";
|
||||
cm.addLineWidget(1, widget, {noHScroll: true});
|
||||
cm.setSize(40);
|
||||
is(widget.parentNode.offsetWidth < 42);
|
||||
});
|
||||
|
||||
testCM("combinedOperations", function(cm) {
|
||||
var place = document.getElementById("testground");
|
||||
var other = CodeMirror(place, {value: "123"});
|
||||
try {
|
||||
cm.operation(function() {
|
||||
cm.addLineClass(0, "wrap", "foo");
|
||||
other.addLineClass(0, "wrap", "foo");
|
||||
});
|
||||
eq(byClassName(cm.getWrapperElement(), "foo").length, 1);
|
||||
eq(byClassName(other.getWrapperElement(), "foo").length, 1);
|
||||
cm.operation(function() {
|
||||
cm.removeLineClass(0, "wrap", "foo");
|
||||
other.removeLineClass(0, "wrap", "foo");
|
||||
});
|
||||
eq(byClassName(cm.getWrapperElement(), "foo").length, 0);
|
||||
eq(byClassName(other.getWrapperElement(), "foo").length, 0);
|
||||
} finally {
|
||||
place.removeChild(other.getWrapperElement());
|
||||
}
|
||||
}, {value: "abc"});
|
||||
|
||||
testCM("eventOrder", function(cm) {
|
||||
var seen = [];
|
||||
cm.on("change", function() {
|
||||
if (!seen.length) cm.replaceSelection(".");
|
||||
seen.push("change");
|
||||
});
|
||||
cm.on("cursorActivity", function() {
|
||||
cm.replaceSelection("!");
|
||||
seen.push("activity");
|
||||
});
|
||||
cm.replaceSelection("/");
|
||||
eq(seen.join(","), "change,change,activity,change");
|
||||
});
|
||||
|
||||
testCM("splitSpaces_nonspecial", function(cm) {
|
||||
eq(byClassName(cm.getWrapperElement(), "cm-invalidchar").length, 0);
|
||||
}, {
|
||||
specialChars: /[\u00a0]/,
|
||||
value: "spaces -> <- between"
|
||||
});
|
||||
|
||||
test("core_rmClass", function() {
|
||||
var node = document.createElement("div");
|
||||
node.className = "foo-bar baz-quux yadda";
|
||||
CodeMirror.rmClass(node, "quux");
|
||||
eq(node.className, "foo-bar baz-quux yadda");
|
||||
CodeMirror.rmClass(node, "baz-quux");
|
||||
eq(node.className, "foo-bar yadda");
|
||||
CodeMirror.rmClass(node, "yadda");
|
||||
eq(node.className, "foo-bar");
|
||||
CodeMirror.rmClass(node, "foo-bar");
|
||||
eq(node.className, "");
|
||||
node.className = " foo ";
|
||||
CodeMirror.rmClass(node, "foo");
|
||||
eq(node.className, "");
|
||||
});
|
||||
|
||||
test("core_addClass", function() {
|
||||
var node = document.createElement("div");
|
||||
CodeMirror.addClass(node, "a");
|
||||
eq(node.className, "a");
|
||||
CodeMirror.addClass(node, "a");
|
||||
eq(node.className, "a");
|
||||
CodeMirror.addClass(node, "b");
|
||||
eq(node.className, "a b");
|
||||
CodeMirror.addClass(node, "a");
|
||||
CodeMirror.addClass(node, "b");
|
||||
eq(node.className, "a b");
|
||||
});
|
||||
|
||||
testCM("lineSeparator", function(cm) {
|
||||
eq(cm.lineCount(), 3);
|
||||
eq(cm.getLine(1), "bar\r");
|
||||
eq(cm.getLine(2), "baz\rquux");
|
||||
cm.setOption("lineSeparator", "\r");
|
||||
eq(cm.lineCount(), 5);
|
||||
eq(cm.getLine(4), "quux");
|
||||
eq(cm.getValue(), "foo\rbar\r\rbaz\rquux");
|
||||
eq(cm.getValue("\n"), "foo\nbar\n\nbaz\nquux");
|
||||
cm.setOption("lineSeparator", null);
|
||||
cm.setValue("foo\nbar\r\nbaz\rquux");
|
||||
eq(cm.lineCount(), 4);
|
||||
}, {value: "foo\nbar\r\nbaz\rquux",
|
||||
lineSeparator: "\n"});
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -116,7 +116,8 @@
|
|||
running = false, // Flag that states tests are running
|
||||
quit = false, // Flag to quit tests ASAP
|
||||
verbose = false, // Adds message for *every* test to output
|
||||
phantom = false;
|
||||
phantom = false,
|
||||
Pos = CodeMirror.Pos; // Required for VIM tests
|
||||
|
||||
function runHarness(){
|
||||
if (running) {
|
||||
|
|
|
@ -30,7 +30,7 @@ const SAVE_ERROR = "error-save";
|
|||
|
||||
// max update frequency in ms (avoid potential typing lag and/or flicker)
|
||||
// @see StyleEditor.updateStylesheet
|
||||
const UPDATE_STYLESHEET_THROTTLE_DELAY = 500;
|
||||
const UPDATE_STYLESHEET_DELAY = 500;
|
||||
|
||||
// Pref which decides if CSS autocompletion is enabled in Style Editor or not.
|
||||
const AUTOCOMPLETION_PREF = "devtools.styleeditor.autocompletion-enabled";
|
||||
|
@ -108,6 +108,7 @@ function StyleSheetEditor(styleSheet, win, file, isNew, walker, highlighter) {
|
|||
this.markLinkedFileBroken = this.markLinkedFileBroken.bind(this);
|
||||
this.saveToFile = this.saveToFile.bind(this);
|
||||
this.updateStyleSheet = this.updateStyleSheet.bind(this);
|
||||
this._updateStyleSheet = this._updateStyleSheet.bind(this);
|
||||
this._onMouseMove = this._onMouseMove.bind(this);
|
||||
|
||||
this._focusOnSourceEditorReady = false;
|
||||
|
@ -469,22 +470,15 @@ StyleSheetEditor.prototype = {
|
|||
|
||||
/**
|
||||
* Queue a throttled task to update the live style sheet.
|
||||
*
|
||||
* @param boolean immediate
|
||||
* Optional. If true the update is performed immediately.
|
||||
*/
|
||||
updateStyleSheet: function(immediate) {
|
||||
updateStyleSheet: function() {
|
||||
if (this._updateTask) {
|
||||
// cancel previous queued task not executed within throttle delay
|
||||
this._window.clearTimeout(this._updateTask);
|
||||
}
|
||||
|
||||
if (immediate) {
|
||||
this._updateStyleSheet();
|
||||
} else {
|
||||
this._updateTask = this._window.setTimeout(this._updateStyleSheet.bind(this),
|
||||
UPDATE_STYLESHEET_THROTTLE_DELAY);
|
||||
}
|
||||
this._updateTask = this._window.setTimeout(this._updateStyleSheet,
|
||||
UPDATE_STYLESHEET_DELAY);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -38,9 +38,6 @@ function disableRadio() {
|
|||
}
|
||||
|
||||
addMessageListener('prepare-network', function(message) {
|
||||
//RIL DOM events will be pending until RIL receiveing system-message-listener-ready event.
|
||||
Services.obs.notifyObservers(null, 'system-message-listener-ready', null);
|
||||
|
||||
connection.addEventListener('datachange', function onDataChange() {
|
||||
if (connection.data.connected) {
|
||||
connection.removeEventListener('datachange', onDataChange);
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.mozilla.gecko.home.BrowserSearch.OnEditSuggestionListener;
|
|||
import org.mozilla.gecko.home.BrowserSearch.OnSearchListener;
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
import org.mozilla.gecko.preferences.GeckoPreferences;
|
||||
import org.mozilla.gecko.util.DrawableUtil;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.widget.AnimatedHeightLayout;
|
||||
|
@ -25,6 +26,7 @@ import android.database.Cursor;
|
|||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -68,6 +70,9 @@ class SearchEngineRow extends AnimatedHeightLayout {
|
|||
// Selected suggestion view
|
||||
private int mSelectedView;
|
||||
|
||||
// android:backgroundTint only works in Android 21 and higher so we can't do this statically in the xml
|
||||
private Drawable mSearchHistorySuggestionIcon;
|
||||
|
||||
// Maximums for suggestions
|
||||
private int mMaxSavedSuggestions;
|
||||
private int mMaxSearchSuggestions;
|
||||
|
@ -135,6 +140,7 @@ class SearchEngineRow extends AnimatedHeightLayout {
|
|||
mUserEnteredView.setOnClickListener(mClickListener);
|
||||
|
||||
mUserEnteredTextView = (TextView) findViewById(R.id.suggestion_text);
|
||||
mSearchHistorySuggestionIcon = DrawableUtil.tintDrawable(getContext(), R.drawable.icon_most_recent_empty, R.color.tabs_tray_icon_grey);
|
||||
|
||||
// Suggestion limits
|
||||
mMaxSavedSuggestions = getResources().getInteger(R.integer.max_saved_suggestions);
|
||||
|
@ -153,7 +159,12 @@ class SearchEngineRow extends AnimatedHeightLayout {
|
|||
|
||||
private void setSuggestionOnView(View v, String suggestion, boolean isUserSavedSearch) {
|
||||
final ImageView historyIcon = (ImageView) v.findViewById(R.id.suggestion_item_icon);
|
||||
historyIcon.setVisibility(isUserSavedSearch ? View.VISIBLE : View.GONE);
|
||||
if (isUserSavedSearch) {
|
||||
historyIcon.setImageDrawable(mSearchHistorySuggestionIcon);
|
||||
historyIcon.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
historyIcon.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
final TextView suggestionText = (TextView) v.findViewById(R.id.suggestion_text);
|
||||
suggestionText.setText(suggestion);
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true">
|
||||
<shape>
|
||||
<gradient android:angle="90"
|
||||
android:startColor="@color/action_orange"
|
||||
android:endColor="@color/fennec_ui_orange"
|
||||
android:type="linear"/>
|
||||
<corners android:radius="4dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="@color/toolbar_grey"/>
|
||||
<corners android:radius="4dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
|
@ -8,5 +8,5 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:minHeight="@dimen/search_row_height"
|
||||
android:duplicateParentState="true"
|
||||
android:paddingTop="7dp"
|
||||
android:paddingBottom="7dp"/>
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"/>
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
<org.mozilla.gecko.widget.FaviconView android:id="@+id/suggestion_icon"
|
||||
android:layout_width="@dimen/favicon_bg"
|
||||
android:layout_height="@dimen/favicon_bg"
|
||||
android:layout_marginLeft="10dip"
|
||||
android:layout_marginRight="10dip"
|
||||
android:layout_marginLeft="16dip"
|
||||
android:layout_marginRight="16dip"
|
||||
android:layout_centerVertical="true"
|
||||
android:minWidth="@dimen/favicon_bg"
|
||||
android:minHeight="@dimen/favicon_bg"/>
|
||||
|
@ -19,7 +19,6 @@
|
|||
android:layout_centerVertical="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="10dip"
|
||||
android:duplicateParentState="true">
|
||||
|
||||
<include layout="@layout/suggestion_item"
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!-- For reasons unknown, the minHeight attribute is required to keep suggestion_user_entered the same size as all other
|
||||
search suggestion buttons-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:minHeight="32dp"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/suggestion_selector"
|
||||
android:background="@drawable/search_suggestion_button"
|
||||
android:gravity="center_vertical"
|
||||
android:clickable="true"
|
||||
android:padding="7dp">
|
||||
android:padding="5dp">
|
||||
|
||||
<ImageView android:id="@+id/suggestion_item_icon"
|
||||
android:src="@drawable/icon_most_recent_empty"
|
||||
|
@ -22,7 +25,7 @@
|
|||
<TextView android:id="@+id/suggestion_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/placeholder_active_grey"
|
||||
android:textColor="@color/text_and_tabs_tray_grey"
|
||||
android:textSize="14sp"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_gravity="center_vertical"/>
|
||||
|
|
|
@ -32,6 +32,9 @@ if (cm) {
|
|||
var SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Services.prefs.setBoolPref(SECURITY_PREF, true);
|
||||
// RIL DOM events and mozChromeEvents will be pending until
|
||||
// this observer message is sent.
|
||||
Services.obs.notifyObservers(null, 'system-message-listener-ready', null);
|
||||
|
||||
function openWindow(aEvent) {
|
||||
var popupIframe = aEvent.detail.frameElement;
|
||||
|
|
|
@ -71,6 +71,10 @@ Data-choices notification
|
|||
|
||||
This is the data submission master kill switch. If disabled, no policy is shown or upload takes place, ever.
|
||||
|
||||
``datareporting.policy.dataSubmissionEnabled.v2``
|
||||
|
||||
If disabled, FHR v2 data will not be sent to Mozilla servers. Telemetry v4 data submission will not be affected. This is like ``datareporting.policy.dataSubmissionEnabled``, but only affects FHR - Telemetry upload will not be disabled.
|
||||
|
||||
``datareporting.policy.dataSubmissionPolicyNotifiedTime``
|
||||
|
||||
Records the date user was shown the policy. This preference is also used on Android.
|
||||
|
|
|
@ -47,7 +47,6 @@ const PREFS_WHITELIST = [
|
|||
"browser.fixup.",
|
||||
"browser.history_expire_",
|
||||
"browser.link.open_newwindow",
|
||||
"browser.newtab.url",
|
||||
"browser.places.",
|
||||
"browser.privatebrowsing.",
|
||||
"browser.search.context.loadInBackground",
|
||||
|
|
Загрузка…
Ссылка в новой задаче