use architect-build for building ace

This commit is contained in:
nightwing 2014-06-18 23:37:00 +04:00
commit d63863ac0c
3 changed files with 382 additions and 528 deletions

View file

@ -31,14 +31,13 @@
var fs = require("fs"); var fs = require("fs");
var path = require("path"); var path = require("path");
if (!fs.existsSync) var copy = require('architect-build/copy');
fs.existsSync = path.existsSync; var build = require('architect-build/build');
else var async = require("asyncjs");
path.existsSync = fs.existsSync;
var copy = require('dryice').copy;
var ACE_HOME = __dirname; var ACE_HOME = __dirname;
var BUILD_DIR = ACE_HOME + "/build"; var BUILD_DIR = ACE_HOME + "/build";
var CACHE = {};
function main(args) { function main(args) {
if (args.indexOf("updateModes") !== -1) { if (args.indexOf("updateModes") !== -1) {
@ -49,7 +48,7 @@ function main(args) {
if (x[0] == "-" && x[1] != "-") if (x[0] == "-" && x[1] != "-")
return "-" + x; return "-" + x;
return x; return x;
}); }).filter(Boolean);
if (args[2] && (args[2][0] != "-" || args[2].indexOf("h") != -1)) if (args[2] && (args[2][0] != "-" || args[2].indexOf("h") != -1))
type = args[2]; type = args[2];
@ -70,26 +69,15 @@ function main(args) {
} else if (type == "demo") { } else if (type == "demo") {
demo(); demo();
} else if (type == "full") { } else if (type == "full") {
demo(ace()); ace();
bookmarklet(); demo();
} else if (type == "highlighter") { } else if (type == "highlighter") {
var project = buildAce({ // TODO
coreOnly: true, }
exportModule: "ace/ext/static_highlight",
requires: ["ace/ext/static_highlight", "ace/theme/textmate"],
readFilters: [copy.filter.moduleDefines, function(a) {
console.log(a.substring(0, 2500))
return a
}]
})
copy({
source: project.result,
filter: getWriteFilters(project.options, "main"),
dest: BUILD_DIR + "/static_highlight.js"
});
} }
} }
function showHelp(type) {
console.log("--- Ace Dryice Build Tool ---"); console.log("--- Ace Dryice Build Tool ---");
console.log(""); console.log("");
console.log("Options:"); console.log("Options:");
@ -106,57 +94,23 @@ function main(args) {
console.log(" --nc namespace require"); console.log(" --nc namespace require");
console.log(" --s shrinkwrap (combines all output files into one)"); console.log(" --s shrinkwrap (combines all output files into one)");
console.log(""); console.log("");
if (BUILD_DIR) if (type)
console.log(" output generated in " + type + __dirname + "/" + BUILD_DIR) console.log(" output for " + type + " generated in " + BUILD_DIR);
} }
function ace() { function ace() {
console.log('# ace ---------');
// uncompressed
var project = buildAce({
compress: false,
noconflict: false
});
buildAce({
compress: false,
noconflict: true
});
// compressed
buildAce({
compress: true,
noconflict: false
});
buildAce({
compress: true,
noconflict: true
});
console.log('# ace License | Readme | Changelog ---------'); console.log('# ace License | Readme | Changelog ---------');
copy({ copy.file(ACE_HOME + "/build_support/editor.html", BUILD_DIR + "/editor.html");
source: ACE_HOME + "/build_support/editor.html", copy.file(ACE_HOME + "/LICENSE", BUILD_DIR + "/LICENSE");
dest: BUILD_DIR + "/editor.html" copy.file(ACE_HOME + "/ChangeLog.txt", BUILD_DIR + "/ChangeLog.txt");
});
copy({
source: ACE_HOME + "/LICENSE",
dest: BUILD_DIR + "/LICENSE"
});
copy({
source: ACE_HOME + "/ChangeLog.txt",
dest: BUILD_DIR + "/ChangeLog.txt"
});
return project; console.log('# ace ---------');
for (var i = 0; i < 4; i++)
buildAce({compress: i & 2, noconflict: i & 1});
} }
function demo(project) { function demo() {
project = project || buildAce({
compress: false,
noconflict: false,
coreOnly: true
});
console.log('# kitchen sink ---------'); console.log('# kitchen sink ---------');
var version, ref; var version, ref;
@ -177,78 +131,54 @@ function demo(project) {
.replace("%version%", version) .replace("%version%", version)
.replace("%commit%", ref) .replace("%commit%", ref)
); );
}; }
function fixDocPaths(data) { function fixDocPaths(data) {
return data.replace(/"(demo|build)\//g, "\""); return data.replace(/"(demo|build)\//g, "\"");
} }
copy({ copy(ACE_HOME + "/demo/kitchen-sink", BUILD_DIR + "/kitchen-sink", {
source: ACE_HOME + "/kitchen-sink.html", shallow: true,
dest: BUILD_DIR + "/kitchen-sink.html", replace: [changeComments, fixDocPaths],
filter: [changeComments, fixDocPaths] include: /\.(css|html)$/
}); });
copy({ copy(ACE_HOME +"/demo/kitchen-sink/docs/", BUILD_DIR + "/kitchen-sink/docs/");
source: ACE_HOME + "/demo/kitchen-sink/styles.css",
dest: BUILD_DIR + "/kitchen-sink/styles.css",
filter: [ changeComments ]
});
fs.readdirSync(ACE_HOME +"/demo/kitchen-sink/docs/").forEach(function(x) { copy.file(ACE_HOME + "/demo/kitchen-sink/logo.png", BUILD_DIR + "/kitchen-sink/logo.png");
copy({
source: ACE_HOME +"/demo/kitchen-sink/docs/" + x,
dest: BUILD_DIR + "/kitchen-sink/docs/" + x
});
});
var demo = copy.createDataObject(); buildSubmodule({}, {
require: ["kitchen-sink/demo"],
filters: [fixDocPaths],
projectType: "demo"
}, BUILD_DIR + "/kitchen-sink/demo");
project.assumeAllFilesLoaded(); copy(ACE_HOME + "/demo/", BUILD_DIR + "/demo/", {
copy({ shallow: true,
source: [{ exclude: /\s|requirejs/,
project: cloneProject(project), include: /\.(js|html)$/,
require: [ "kitchen-sink/demo" ] replace: function(source) {
}], if (!/^\s*</.test(source))
filter: getWriteFilters({filters:[fixDocPaths]}, "demo"),
dest: demo
});
copy({
source: demo,
dest: BUILD_DIR + "/kitchen-sink/demo.js",
});
copyFileSync(ACE_HOME + "/demo/kitchen-sink/logo.png", BUILD_DIR + "/kitchen-sink/logo.png");
fs.readdirSync(ACE_HOME + "/demo/").forEach(function(x) {
if (/\s|requirejs/.test(x) || !/\.(js|html)$/.test(x))
return;
copy({
source: ACE_HOME +"/demo/" + x,
dest: BUILD_DIR + "/demo/" + x,
filter: [function(source) {
if (/\.(js)$/.test(x))
return source; return source;
var removeRequireJS var removeRequireJS;
source = source.replace(/<script src="kitchen-sink\/require.js"[\s\S]+?require\(\[([^\]]+).*/, function(e, m) { source = source.replace(/<script src="kitchen-sink\/require.js"[\s\S]+?require\(\[([^\]]+).*/, function(e, m) {
removeRequireJS = true; removeRequireJS = true;
var scripts = m.split(/,\s*/); var scripts = m.split(/,\s*/);
var result = []; var result = [];
function comment(str) {result.push("<!-- " + str + " -->")}; function comment(str) {result.push("<!-- " + str + " -->")}
function script(str) {result.push('<script src="../src/' + str + '.js"></script>')} function script(str) {result.push('<script src="../src/' + str + '.js"></script>')}
scripts.forEach(function(s) { scripts.forEach(function(s) {
s = s.replace(/"/g, ""); s = s.replace(/"/g, "");
if (s == "ace/ace") { if (s == "ace/ace") {
comment("load ace") comment("load ace");
script("ace") script("ace");
} else { } else {
var extName = s.match(/[^/]*$/)[0]; var extName = s.match(/[^/]*$/)[0];
comment("load ace " + extName + " extension"); comment("load ace " + extName + " extension");
script("ext-" + extName); script("ext-" + extName);
} }
}); });
result.push("<script>") result.push("<script>");
return result.join("\n"); return result.join("\n");
}); });
if (removeRequireJS) if (removeRequireJS)
@ -257,8 +187,7 @@ function demo(project) {
console.log(e); return '"../'; console.log(e); return '"../';
}); });
return source; return source;
}] }
});
}); });
} }
@ -270,7 +199,7 @@ function jsFileList(path, filter) {
return fs.readdirSync(path).map(function(x) { return fs.readdirSync(path).map(function(x) {
if (x.slice(-3) == ".js" && !filter.test(x) && !/\s/.test(x)) if (x.slice(-3) == ".js" && !filter.test(x) && !/\s/.test(x))
return x.slice(0, -3); return x.slice(0, -3);
}).filter(function(x){ return !!x }); }).filter(Boolean);
} }
function workers(path) { function workers(path) {
@ -279,300 +208,241 @@ function workers(path) {
return x.slice(0, -7); return x.slice(0, -7);
}).filter(function(x) { return !!x; }); }).filter(function(x) { return !!x; });
} }
function modeList() { function modeList() {
return jsFileList("lib/ace/mode", /_highlight_rules|_test|_worker|xml_util|_outdent|behaviour|completions/) return jsFileList("lib/ace/mode", /_highlight_rules|_test|_worker|xml_util|_outdent|behaviour|completions/);
} }
function addSuffix(options) { function buildAceModule(opts, callback) {
if (options.suffix == null) { // calling buildAceModuleInternal many times in parallel is slow, so we use queue
options.suffix = ""; if (!buildAceModule.queue) {
if (options.compress) buildAceModule.queue = [];
options.suffix += "-min"; buildAceModule.dequeue = function() {
if (options.noconflict) if (buildAceModule.running) return;
options.suffix += "-noconflict"; var call = buildAceModule.queue.shift();
} if (call)
} buildAceModuleInternal.apply(null, call);
buildAceModule.running = call;
function getWriteFilters(options, projectType, main) {
var filters = [
copy.filter.moduleDefines,
removeUseStrict,
removeLicenceComments,
inlineTextModules
];
if (options.filters)
filters = filters.concat(options.filters);
if (options.noconflict)
filters.push(namespace(options.ns));
if (options.exportModule && projectType == "main" || projectType == "ext") {
filters.push(exportAce(options.ns, options.exportModule,
options.noconflict ? options.ns : "", projectType == "ext" && main));
}
if (options.compress)
filters.push(copy.filter.uglifyjs);
// copy.filter.uglifyjs.options.ascii_only = true; doesn't work with some uglify.js versions
filters.push(function(text) {
var text = text.replace(/[\x00-\x08\x0b\x0c\x0e\x19\x80-\uffff]/g, function(c) {
c = c.charCodeAt(0).toString(16);
if (c.length == 1)
return "\\x0" + c;
if (c.length == 2)
return "\\x" + c;
if (c.length == 3)
return "\\u0" + c;
return "\\u" + c;
});
return text;
});
return filters;
}
var buildAce = function(options) {
var aceProject = {
roots: [ACE_HOME + '/lib', ACE_HOME + '/demo'],
textPluginPattern: /^ace\/requirejs\/text!/
}; };
var defaults = {
targetDir: BUILD_DIR + "/src",
ns: "ace",
exportModule: "ace/ace",
requires: null,
compress: false,
noconflict: false,
suffix: null,
name: "ace",
modes: modeList(),
themes: jsFileList("lib/ace/theme"),
extensions: jsFileList("lib/ace/ext"),
workers: workers("lib/ace/mode"),
keybindings: ["vim", "emacs"],
readFilters: [copy.filter.moduleDefines]
};
for(var key in defaults)
if (!options.hasOwnProperty(key))
options[key] = defaults[key];
addSuffix(options);
if (!options.requires)
options.requires = [options.exportModule];
var targetDir = options.targetDir + options.suffix;
var name = options.name;
var project = copy.createCommonJsProject(aceProject);
project.options = options;
var ace = copy.createDataObject();
copy({
source: [ACE_HOME + "/build_support/mini_require.js"],
dest: ace
});
copy({
source: [{
project: project,
require: options.requires
}],
filter: options.readFilters,
dest: ace
});
if (options.coreOnly) {
project.result = ace;
return project;
}
copy({
source: ace,
filter: getWriteFilters(options, "main"),
dest: targetDir + '/' + name + ".js"
});
console.log('# ace extensions ---------');
project.assumeAllFilesLoaded();
options.extensions.forEach(function(ext) {
console.log("extensions " + ext);
copy({
source: [{
project: cloneProject(project),
require: [ 'ace/ext/' + ext ]
}],
filter: getWriteFilters(options, "ext", 'ace/ext/' + ext),
dest: targetDir + "/ext-" + ext + ".js"
});
});
console.log('# ace modes ---------');
project.assumeAllFilesLoaded();
options.modes.forEach(function(mode) {
console.log("mode " + mode);
addSnippetFile(mode, project, targetDir, options);
copy({
source: [{
project: cloneProject(project),
require: [ 'ace/mode/' + mode ]
}],
filter: getWriteFilters(options, "mode"),
dest: targetDir + "/mode-" + mode + ".js"
});
});
console.log('# ace themes ---------');
project.assumeAllFilesLoaded();
delete project.ignoredModules["ace/theme/textmate"];
delete project.ignoredModules["ace/requirejs/text!ace/theme/textmate.css"];
options.themes.forEach(function(theme) {
console.log("theme " + theme);
copy({
source: [{
project: cloneProject(project),
require: ["ace/theme/" + theme]
}],
filter: getWriteFilters(options, "theme"),
dest: targetDir + "/theme-" + theme.replace("_theme", "") + ".js"
});
});
// generateThemesModule(options.themes);
console.log('# ace key bindings ---------');
// copy key bindings
project.assumeAllFilesLoaded();
options.keybindings.forEach(function(keybinding) {
copy({
source: [{
project: cloneProject(project),
require: [ 'ace/keyboard/' + keybinding ]
}],
filter: getWriteFilters(options, "keybinding"),
dest: targetDir + "/keybinding-" + keybinding + ".js"
});
});
console.log('# ace worker ---------');
options.workers.forEach(function(mode) {
console.log("worker for " + mode + " mode");
var worker = copy.createDataObject();
var workerProject = copy.createCommonJsProject({
roots: [ ACE_HOME + '/lib' ],
textPluginPattern: /^ace\/requirejs\/text!/
});
copy({
source: [{
project: workerProject,
require: [
'ace/worker/worker',
'ace/mode/' + mode + '_worker'
]
}],
filter: getWriteFilters(options, "worker"),
dest: worker
});
copy({
source: [
worker
],
filter: options.compress ? [copy.filter.uglifyjs] : [],
dest: targetDir + "/worker-" + mode + ".js"
});
});
if (options.shrinkwrap) {
console.log('# combining files into one ---------');
copy({
source: { root:targetDir, exclude:/(^|\\|\/)worker\-[^\\\/]*\.js$/ },
dest: BUILD_DIR + '/ace-min.js'
});
} }
return project; buildAceModule.queue.push([opts, function(err, result) {
}; callback && callback(err, result);
buildAceModule.running = null;
buildAceModule.dequeue();
}]);
// silence annoying messages from dryice if (!buildAceModule.running) {
var buildAce = function(fn) { buildAceModule.dequeue();
return function() {
var log = console.log
console.log = function() {
if (typeof arguments[0] == "string" && /Ignoring requirement/.test(arguments[0]))
return;
log.apply(console, arguments);
}
var ret = fn.apply(null, arguments);
console.log = log;
return ret;
}
}(buildAce);
var addSnippetFile = function(modeName, project, targetDir, options) {
var snippetFilePath = ACE_HOME + "/lib/ace/snippets/" + modeName;
if (!fs.existsSync(snippetFilePath + ".js")) {
copy({
source: ACE_HOME + "/tool/snippets.tmpl.js",
dest: snippetFilePath + ".js",
filter: [
function(t) {return t.replace(/%modeName%/g, modeName);}
]
});
}
if (!fs.existsSync(snippetFilePath + ".snippets")) {
fs.writeFileSync(snippetFilePath + ".snippets", "")
}
copy({
source: [{
project: cloneProject(project),
require: [ 'ace/snippets/' + modeName ]
}],
filter: getWriteFilters(options, "mode"),
dest: targetDir + "/snippets/" + modeName + ".js"
});
}
var textModules = {}
var detectTextModules = function(input, source) {
if (!source)
throw new Error('Missing filename for text module');
if (typeof input !== 'string')
input = input.toString();
var module = source.isLocation ? source.path : source;
input = input.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
if (/\.css$/.test(module)) {
// remove unnecessary whitespace from css
input = input.replace(/\n\s+/g, "\n");
input = '"' + input.replace(/\r?\n/g, '\\\n') + '"';
} else { } else {
// but don't break other files! process.nextTick(buildAceModule.dequeue);
input = '"' + input.replace(/\r?\n/g, '\\n\\\n') + '"'; }
} }
textModules[module] = input;
return ""; function buildAceModuleInternal(opts, callback) {
var cache = opts.cache == undefined ? CACHE : opts.cache;
var key = opts.require + "|" + opts.compress + "|" + opts.projectType;
if (cache && cache.configs && cache.configs[key])
return write(null, cache.configs[key]);
var pathConfig = {
paths: {
ace: ACE_HOME + "/lib/ace",
"kitchen-sink": ACE_HOME + "/demo/kitchen-sink",
build_support: ACE_HOME + "/build_support",
},
root: ACE_HOME
}; };
detectTextModules.onRead = true;
copy.filter.addDefines = detectTextModules;
function inlineTextModules(text) { function write(err, result) {
var deps = []; if (opts.compress)
return text.replace(/, *['"]ace\/requirejs\/text!(.*?)['"]| require\(['"](?:ace|[.\/]+)\/requirejs\/text!(.*?)['"]\)/g, function(_, dep, call) { result.code = compress(result.code);
if (dep) {
deps.push(dep); if (cache && key) {
return ""; cache.configs = cache.configs || Object.create(null);
} else if (call) { cache.configs[key] = result;
result.sources = result.sources.map(function(pkg) {
return {deps: pkg.deps};
});
}
if (!opts.outputFile)
return callback(err, result);
var targetDir = BUILD_DIR + "/src";
if (opts.compress)
targetDir += "-min";
if (opts.noconflict)
targetDir += "-noconflict";
var to = /^([\\/]|\w:)/.test(opts.outputFile)
? opts.outputFile
: path.join(opts.outputFolder || targetDir, opts.outputFile);
var filters = [];
var ns = opts.ns || "ace";
if (opts.filters)
filters = filters.concat(opts.filters);
if (opts.noconflict)
filters.push(namespace(ns));
var projectType = opts.projectType;
if (projectType == "main" || projectType == "ext") {
filters.push(exportAce(ns, opts.require[0],
opts.noconflict ? ns : "", projectType == "ext"));
}
var code = result.code;
filters.forEach(function(f) { code = f(code); });
build.writeToFile({code: code}, {
outputFolder: path.dirname(to),
outputFile: path.basename(to),
}, function() {});
callback && callback(err, result);
}
build(opts.require, {
cache: cache,
quiet: opts.quiet,
pathConfig: pathConfig,
additional: opts.additional,
enableBrowser: true,
keepDepArrays: "all",
noArchitect: true,
compress: false,
ignore: opts.ignore || [],
withRequire: false,
basepath: ACE_HOME,
afterRead: [optimizeTextModules]
}, write);
}
function buildCore(options, extra, callback) {
options = extend(extra, options);
options.additional = [{
id: "build_support/mini_require",
order: -1000,
literal: true
}];
options.require =["ace/ace"];
options.projectType = "main";
options.ns = "ace";
buildAceModule(options, callback);
}
function buildSubmodule(options, extra, file, callback) {
options = extend(extra, options);
getLoadedFileList(options, function(coreFiles) {
options.outputFile = file + ".js";
options.ignore = coreFiles;
options.quiet = true;
buildAceModule(options, callback);
});
}
function buildAce(options) {
var snippetFiles = jsFileList("lib/ace/snippets");
var modeNames = modeList();
async.forEach([
buildCore.bind(null, options, {outputFile: "ace.js"}),
// modes
async.forEach.bind(null, modeNames, function(name, next) {
buildSubmodule(options, {
projectType: "mode",
require: ["ace/mode/" + name]
}, "mode-" + name, next);
}),
// snippets
async.forEach.bind(null, modeNames, function(name, next) {
if (snippetFiles.indexOf(name + ".js") == -1)
addSnippetFile(name);
buildSubmodule(options, {
require: ["ace/snippets/" + name],
}, "snippets/" + name, next);
}),
// themes
async.forEach.bind(null, jsFileList("lib/ace/theme"), function(name, next) {
buildSubmodule(options, {
projectType: "theme",
require: ["ace/theme/" + name]
}, "theme-" + name.replace("_theme", ""), next);
}),
// keybindings
async.forEach.bind(null, ["vim", "emacs"], function(name, next) {
buildSubmodule(options, {
projectType: "keybinding",
require: ["ace/keyboard/" + name ]
}, "keybinding-" + name, next);
}),
// extensions
async.forEach.bind(null, jsFileList("lib/ace/ext"), function(name, next) {
buildSubmodule(options, {
projectType: "ext",
require: ["ace/ext/" + name]
}, "ext-" + name, next);
}),
// workers
async.forEach.bind(null, workers("lib/ace/mode"), function(name, next) {
buildSubmodule(options, {
projectType: "worker",
require: ["ace/mode/" + name + "_worker"],
additional: [{
id: "ace/worker/worker",
loaderModule: true,
order: -1000
}],
}, "worker-" + name, next);
}),
], function(f, next) { f(next); });
}
function getLoadedFileList(options, callback, result) {
if (!result) {
return buildCore({}, {}, function(e, result) {
getLoadedFileList(options, callback, result);
});
}
var deps = Object.create(null);
result.sources.forEach(function(pkg) {
pkg.deps && pkg.deps.forEach(function(p) {
if (!deps[p]) deps[p] = 1;
});
});
delete deps["ace/theme/textmate"];
callback(Object.keys(deps));
}
function optimizeTextModules(sources) {
var textModules = {};
return sources.filter(function(pkg) {
if (!pkg.id) {
return true;
}
else if (pkg.id.indexOf("text!") > -1) {
detectTextModules(pkg);
return false;
}
else {
pkg.source = rewriteTextImports(pkg.source, pkg.deps);
return true;
}
}).map(function(pkg) {
if (pkg && pkg.deps) {
pkg.deps = pkg.deps && pkg.deps.filter(function(p) {
return p.indexOf("text!") == -1;
});
}
return pkg;
});
function rewriteTextImports(text, deps) {
return text.replace(/ require\(['"](?:ace|[.\/]+)\/requirejs\/text!(.*?)['"]\)/g, function(_, call) {
if (call) {
var dep;
deps.some(function(d) { deps.some(function(d) {
if (d.split("/").pop() == call.split("/").pop()) { if (d.split("/").pop() == call.split("/").pop()) {
dep = d; dep = d;
@ -586,80 +456,18 @@ function inlineTextModules(text) {
} }
}); });
} }
function detectTextModules(pkg) {
var CommonJsProject = copy.createCommonJsProject({roots:[]}).constructor; var input = pkg.source.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
CommonJsProject.prototype.getCurrentModules = function() { if (/\.css$/.test(pkg.id)) {
function isDep(child, parent) { // remove unnecessary whitespace from css
if (!modules[parent]) input = input.replace(/\n\s+/g, "\n");
return false; input = '"' + input.replace(/\r?\n/g, '\\\n') + '"';
var deps = modules[parent].deps; } else {
if (deps[child]) return true; // but don't break other files!
return Object.keys(deps).some(function(x) { input = '"' + input.replace(/\r?\n/g, '\\n\\\n') + '"';
return isDep(child, x)
});
} }
var depMap = {}, modules = this.currentModules; textModules[pkg.id] = input;
return Object.keys(this.currentModules).map(function(moduleName) {
module = modules[moduleName];
module.id = moduleName;
module.isSpecial = !/define\(\'[^']*',/.test(module.source);
return module;
}).sort(function(a, b) {
if (a.isSpecial) return -1;
if (b.isSpecial) return 1;
if (isDep(a.id, b.id)) return -1;
if (isDep(b.id, a.id)) return 1;
return Object.keys(a.deps).length - Object.keys(b.deps).length || a.id.localeCompare(b.id)
});
};
// TODO: replace with project.clone once it is fixed in dryice
function cloneProject(project) {
var clone = copy.createCommonJsProject({
roots: project.roots,
ignores: project.ignoreRequires,
textPluginPattern: project.textPluginPattern
});
Object.keys(project.currentModules).forEach(function(module) {
clone.currentModules[module] = project.currentModules[module];
});
Object.keys(project.ignoredModules).forEach(function(module) {
clone.ignoredModules[module] = project.ignoredModules[module];
});
return clone;
} }
function copyFileSync(srcFile, destFile) {
var BUF_LENGTH = 64*1024;
var buf = new Buffer(BUF_LENGTH);
var bytesRead = BUF_LENGTH;
var pos = 0;
var fdr = fs.openSync(srcFile, 'r');
var fdw = fs.openSync(destFile, 'w');
while (bytesRead === BUF_LENGTH) {
bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos);
fs.writeSync(fdw, buf, 0, bytesRead);
pos += bytesRead;
}
fs.closeSync(fdr);
fs.closeSync(fdw);
}
function quoteString(str) {
return '"' + str.replace(/\\/, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\\n") + '"';
}
function removeUseStrict(text) {
return text.replace(/['"]use strict['"];/g, "");
}
function removeLicenceComments(text) {
return text.replace(/(?:(;)|\n)\s*\/\*[\d\D]*?\*\/|\n\s*\/\/.*/g, "$1");
} }
function namespace(ns) { function namespace(ns) {
@ -667,44 +475,48 @@ function namespace(ns) {
text = text text = text
.toString() .toString()
.replace('var ACE_NAMESPACE = "";', 'var ACE_NAMESPACE = "' + ns +'";') .replace('var ACE_NAMESPACE = "";', 'var ACE_NAMESPACE = "' + ns +'";')
// .replace(/(\.define)|([,;\n]|^\s*?)define\(/g, function(_, a, b) {
// return a || b + ns + ".define(";
.replace(/(\.define)|\bdefine\(/g, function(_, a) { .replace(/(\.define)|\bdefine\(/g, function(_, a) {
return a || ns + ".define(" return a || ns + ".define(";
}); });
return text; return text;
}; };
} }
function exportAce(ns, module, requireBase, extModule) { function exportAce(ns, modules, requireBase, extModules) {
requireBase = requireBase || "window"; requireBase = requireBase || "window";
module = module || "ace/ace";
return function(text) { return function(text) {
/*globals REQUIRE_NS, MODULES, NS*/
var template = function() { var template = function() {
(function() { (function() {
REQUIRE_NS.require(["MODULE"], function(a) { REQUIRE_NS.require(MODULES, function(a) {
a && a.config.init(true); a && a.config.init(true);
if (!window.NS) if (!window.NS)
window.NS = a; window.NS = a;
for (var key in a) if (a.hasOwnProperty(key)) for (var key in a) if (a.hasOwnProperty(key))
NS[key] = a[key]; window.NS[key] = a[key];
}); });
})(); })();
}; };
if (extModule) { if (extModules) {
module = extModule;
template = function() { template = function() {
(function() { (function() {
REQUIRE_NS.require(["MODULE"], function() {}); REQUIRE_NS.require(MODULES, function() {});
})(); })();
}; };
} }
text = text.replace(/function init\(packaged\) {/, "init(true);$&\n"); text = text.replace(/function init\(packaged\) {/, "init(true);$&\n");
if (typeof modules == "string")
modules = [modules];
return (text + ";" + template return (text + ";" + template
.toString() .toString()
.replace(/MODULE/g, module) .replace(/MODULES/g, JSON.stringify(modules))
.replace(/REQUIRE_NS/g, requireBase) .replace(/REQUIRE_NS/g, requireBase)
.replace(/NS/g, ns) .replace(/NS/g, ns)
.slice(13, -1) .slice(13, -1)
@ -714,14 +526,14 @@ function exportAce(ns, module, requireBase, extModule) {
function updateModes() { function updateModes() {
modeList().forEach(function(m) { modeList().forEach(function(m) {
var filepath = __dirname + "/lib/ace/mode/" + m + ".js" var filepath = __dirname + "/lib/ace/mode/" + m + ".js";
var source = fs.readFileSync(filepath, "utf8"); var source = fs.readFileSync(filepath, "utf8");
if (!/this.\$id\s*=\s*"/.test(source)) if (!/this.\$id\s*=\s*"/.test(source))
source = source.replace(/\n([ \t]*)(\}\).call\(\w*Mode.prototype\))/, '\n$1 this.$id = "";\n$1$2'); source = source.replace(/\n([ \t]*)(\}\).call\(\w*Mode.prototype\))/, '\n$1 this.$id = "";\n$1$2');
source = source.replace(/(this.\$id\s*=\s*)"[^"]*"/, '$1"ace/mode/' + m + '"'); source = source.replace(/(this.\$id\s*=\s*)"[^"]*"/, '$1"ace/mode/' + m + '"');
fs.writeFileSync(filepath, source, "utf8") fs.writeFileSync(filepath, source, "utf8");
}) });
} }
function generateThemesModule(themes) { function generateThemesModule(themes) {
@ -733,6 +545,42 @@ function generateThemesModule(themes) {
fs.writeFileSync(__dirname + '/lib/ace/ext/themelist_utils/themes.js', themelist, 'utf8'); fs.writeFileSync(__dirname + '/lib/ace/ext/themelist_utils/themes.js', themelist, 'utf8');
} }
function addSnippetFile(modeName) {
var snippetFilePath = ACE_HOME + "/lib/ace/snippets/" + modeName;
if (!fs.existsSync(snippetFilePath + ".js")) {
copy.file(ACE_HOME + "/tool/snippets.tmpl.js", snippetFilePath + ".js", function(t) {
return t.replace(/%modeName%/g, modeName);
});
}
if (!fs.existsSync(snippetFilePath + ".snippets")) {
fs.writeFileSync(snippetFilePath + ".snippets", "");
}
}
function compress(text) {
return asciify(require("dryice").copy.filter.uglifyjs(text));
// copy.filter.uglifyjs.options.ascii_only = true; doesn't work with some uglify.js versions
function asciify(text) {
return text.replace(/[\x00-\x08\x0b\x0c\x0e\x19\x80-\uffff]/g, function(c) {
c = c.charCodeAt(0).toString(16);
if (c.length == 1)
return "\\x0" + c;
if (c.length == 2)
return "\\x" + c;
if (c.length == 3)
return "\\u0" + c;
return "\\u" + c;
});
}
}
function extend(base, extra) {
Object.keys(extra).forEach(function(k) {
base[k] = extra[k];
});
return base;
}
if (!module.parent) if (!module.parent)
main(process.argv); main(process.argv);
else else

View file

@ -29,14 +29,20 @@
}</pre> }</pre>
<script src="../demo/kitchen-sink/require.js"></script> <script src="../demo/kitchen-sink/require.js"></script>
<script src="../build/src/ace.js" charset="utf-8"></script>
<script> <script>
require.config({paths: {ace: "../build/src"}})
define('testace', ['ace/ace'],
function(ace, langtools) {
console.log("This is the testace module");
var editor = ace.edit("editor"); var editor = ace.edit("editor");
editor.setTheme("ace/theme/twilight"); editor.setTheme("ace/theme/twilight");
editor.session.setMode("ace/mode/javascript"); editor.session.setMode("ace/mode/javascript");
require(["ace/requirejs/text!src/ace"], function(e){ require(["ace/requirejs/text!src/ace"], function(e){
editor.setValue(e); editor.setValue(e);
}) })
}
);
require(['testace'])
</script> </script>
</body> </body>

View file

@ -17,7 +17,7 @@
"asyncjs": "0.0.x", "asyncjs": "0.0.x",
"jsdom": "0.2.x", "jsdom": "0.2.x",
"amd-loader": "~0.0.4", "amd-loader": "~0.0.4",
"dryice": "0.4.10" "dryice": "0.4.11"
}, },
"mappings": { "mappings": {
"ace": "." "ace": "."