be smarter with mode and theme loading

This commit is contained in:
Fabian Jakobs 2012-03-30 17:44:24 +02:00
commit 0fb6590f26
8 changed files with 251 additions and 87 deletions

View file

@ -49,6 +49,7 @@ var UndoManager = require("./undomanager").UndoManager;
var Renderer = require("./virtual_renderer").VirtualRenderer;
require("./worker/worker_client");
require("./config").init();
exports.edit = function(el) {
if (typeof(el) == "string") {

128
lib/ace/config.js Normal file
View file

@ -0,0 +1,128 @@
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
* Ajax.org B.V.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Fabian Jakobs <fabian AT ajax DOT org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
define(function(require, exports, module) {
"no use strict";
var lang = require("./lib/lang");
var global = (function() {
return this;
})();
var options = {
packaged: false,
workerPath: "",
modePath: "",
themePath: "",
suffix: ".js"
};
exports.get = function(key) {
if (!options.hasOwnProperty(key))
throw new Error("Unknown confik key: " + key);
return options[key];
};
exports.set = function(key, value) {
if (!options.hasOwnProperty(key))
throw new Error("Unknown confik key: " + key);
options[key] = value;
};
exports.all = function() {
return lang.copyObject(options);
};
exports.init = function() {
options.packaged = require.packaged || module.packaged || (global.define && define.packaged);
if (!global.document)
return "";
var scriptOptions = {};
var scriptUrl = "";
var suffix;
var scripts = document.getElementsByTagName("script");
for (var i=0; i<scripts.length; i++) {
var script = scripts[i];
var src = script.src || script.getAttribute("src");
if (!src) {
continue;
}
var attributes = script.attributes;
for (var j=0, l=attributes.length; j < l; j++) {
var attr = attributes[j];
if (attr.name.indexOf("data-ace-") === 0) {
scriptOptions[deHyphenate(attr.name.replace(/^data-ace-/, ""))] = attr.value;
}
}
var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace((-uncompressed)?(-noconflict)?\.js))(?:\?|$)/);
if (m) {
scriptUrl = m[1] || m[2];
suffix = m[3];
}
}
if (scriptUrl) {
scriptOptions.base = scriptOptions.base || scriptUrl;
scriptOptions.packaged = true;
}
scriptOptions.suffix = scriptOptions.suffix || suffix;
scriptOptions.workerPath = scriptOptions.workerPath || scriptOptions.base;
scriptOptions.modePath = scriptOptions.modePath || scriptOptions.base;
scriptOptions.themePath = scriptOptions.themePath || scriptOptions.base;
delete scriptOptions.base;
for (var key in scriptOptions)
if (typeof scriptOptions[key] !== "undefined")
exports.set(key, scriptOptions[key]);
};
function deHyphenate(str) {
return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); });
}
});

View file

@ -41,8 +41,10 @@
define(function(require, exports, module) {
"use strict";
var config = require("./config");
var oop = require("./lib/oop");
var lang = require("./lib/lang");
var net = require("./lib/net");
var EventEmitter = require("./lib/event_emitter").EventEmitter;
var Selection = require("./selection").Selection;
var TextMode = require("./mode/text").Mode;
@ -484,10 +486,61 @@ var EditSession = function(text, mode) {
this._emit("tokenizerUpdate", e);
};
this.$modes = {};
this._loadMode = function(mode, callback) {
if (this.$modes[mode])
return callback(this.$modes[mode]);
var _self = this;
var module;
try {
module = require(mode);
} catch (e) {};
if (module)
return done(module);
fetch(function() {
require([mode], done);
});
function done(module) {
if (_self.$modes[mode])
return callback(_self.$modes[mode]);
_self.$modes[mode] = new module.Mode();
callback(_self.$modes[mode]);
}
function fetch(callback) {
if (!config.get("packaged"))
return callback();
var base = mode.split("/").pop();
var filename = config.get("modePath") + "/mode-" + base + config.get("suffix");
net.loadScript(filename, callback);
}
};
this.$mode = null;
this.$origMode = null;
this.setMode = function(mode) {
this.$origMode = mode;
// load on demand
if (typeof mode === "string") {
var _self = this;
this._loadMode(mode, function(module) {
if (_self.$origMode !== mode)
return;
_self.setMode(module);
});
return;
}
if (this.$mode === mode) return;
this.$mode = mode;
this.$stopWorker();

View file

@ -45,6 +45,8 @@ var oop = require("./lib/oop");
var dom = require("./lib/dom");
var event = require("./lib/event");
var useragent = require("./lib/useragent");
var config = require("./config");
var net = require("./lib/net");
var GutterLayer = require("./layer/gutter").Gutter;
var MarkerLayer = require("./layer/marker").Marker;
var TextLayer = require("./layer/text").Text;
@ -803,14 +805,36 @@ var VirtualRenderer = function(container, theme) {
style.left = "-10000px";
};
this._loadTheme = function(name, callback) {
if (!config.get("packaged"))
return callback();
var base = name.split("/").pop();
var filename = config.get("themePath") + "/theme-" + base + config.get("suffix");
net.loadScript(filename, callback);
};
this.setTheme = function(theme) {
var _self = this;
this.$themeValue = theme;
if (!theme || typeof theme == "string") {
theme = theme || "ace/theme/textmate";
require([theme], function(theme) {
afterLoad(theme);
var moduleName = theme || "ace/theme/textmate";
var module;
try {
module = require(moduleName);
} catch (e) {};
if (module)
return afterLoad(module);
_self._loadTheme(moduleName, function() {
require([theme], function(module) {
if (_self.$themeValue !== theme)
return;
afterLoad(module);
});
});
} else {
afterLoad(theme);

View file

@ -40,14 +40,14 @@ define(function(require, exports, module) {
var oop = require("../lib/oop");
var EventEmitter = require("../lib/event_emitter").EventEmitter;
var config = require("../config");
var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
this.changeListener = this.changeListener.bind(this);
if (module.packaged) {
var base = this.$guessBasePath();
this.$worker = new Worker(base + packagedJs);
if (config.get("packaged")) {
this.$worker = new Worker(config.get("workerPath") + "/" + packagedJs);
}
else {
var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
@ -112,29 +112,6 @@ var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
return path;
};
this.$guessBasePath = function() {
if (require.aceBaseUrl)
return require.aceBaseUrl;
var scripts = document.getElementsByTagName("script");
for (var i=0; i<scripts.length; i++) {
var script = scripts[i];
var base = script.getAttribute("data-ace-base");
if (base)
return base.replace(/\/*$/, "/");
var src = script.src || script.getAttribute("src");
if (!src) {
continue;
}
var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);
if (m)
return m[1] || m[2];
}
return "";
};
this.terminate = function() {
this._emit("terminate", {});
this.$worker.terminate();