c9-core/plugins/c9.static/cdn.cli.js

303 wiersze
13 KiB
JavaScript

define(function(require, exports, module) {
"use strict";
main.consumes = ["cdn.build"];
return main;
function main(options, imports, register) {
var build = imports["cdn.build"];
var fs = require("fs");
var path = require("path");
var mkdirp = require("mkdirp");
var async = require("async");
var moduleDeps = require("architect-build/module-deps");
var root = path.join(build.cacheDir, build.version);
var cache = {};
build.setCache(cache);
build.getPathConfig(build.version, function(err, pathConfig) {
if (err) return done(err);
var pending = 1;
if (options.skin && options.config) {
build.buildSkin(options.config, options.skin, pathConfig, save(["skin", options.config, options.skin + ".css"]));
} else if (options.config) {
var seen = Object.create(null);
var configs = options.config.split(/,\s*/).filter(function(x) {
if (seen[x]) return false;
return seen[x] = true;
});
var configCache = options.skipDuplicates && { duplicates: []};
var usedPlugins = options.copyStaticResources && Object.create(null);
(function buildConfig() {
var config = configs.shift();
if (!config) {
var series = [];
if (usedPlugins)
series.push(copyStaticResources.bind(null, usedPlugins, pathConfig));
if (configCache && configCache.duplicates.length)
series.push(fs.writeFile.bind(fs, path.join(root, "config", "duplicates"), configCache.duplicates.join(" "), "utf8"));
series.push(done.bind(null, null));
return async.series(series);
}
var skins = options.withSkins;
if (skins === true || skins === "all")
skins = ["dark", "light", "dark-gray", "light-gray", "flat-light", "flat-dark", "jett-dark"];
else
skins = skins ? skins.split(/,\s*/) : [];
build.buildConfig(config, pathConfig, function(err, result) {
save(["config", path.basename(config) + ".js"], function next(err) {
if (err) return done(err);
var skin = skins.pop();
if (!skin) return buildConfig();
build.buildSkin({
sources: result.sources,
config: [],
}, skin, pathConfig, save(["skin", config, skin + ".css"], next));
})(err, result);
}, function(configName, data) {
var pluginPaths = data.map(function(p) {
return typeof p == "string" ? p : p.packagePath;
}).filter(Boolean).sort();
if (usedPlugins) {
pluginPaths.forEach(function(p) {
usedPlugins[p] = true;
});
}
if (!configCache) return;
if (!configCache.defaultConfig) {
configCache.defaultConfig = Object.create(null);
pluginPaths.forEach(function(p) {
configCache.defaultConfig[p] = true;
});
return false;
}
var isDuplicate = pluginPaths.every(function(p) {
return configCache.defaultConfig[p];
});
if (!isDuplicate) return false;
configCache.duplicates.push(configName);
process.nextTick(buildConfig);
return true;
});
})();
} else if (options.worker) {
build.buildWorker(options.worker, pathConfig, save(["worker", options.worker + ".js"]));
} else if (options.module) {
if (options.module === "ace") {
listAceModules(pathConfig, function(module, next) {
if (next) pending++;
build.buildAce(module, pathConfig, function(err, result) {
save(["modules", module + ".js"], function(err) {
warn(err);
done();
})(err, result);
if (next) process.nextTick(next); // start building next without waiting for write
});
});
} else if (options.module.match(/^ace\//)) {
build.buildAce(options.module, pathConfig, save(["modules", options.module + ".js"]));
} else {
build.buildModule(options.module, pathConfig, save(["modules", options.module + ".js"]));
}
} else {
done(new Error("unknown action"));
}
function warn(err) {
if (err) console.warn(err);
}
function save(nameParts, cb) {
return function(err, result) {
if (err) return cb(err);
var code = result.code;
nameParts.unshift(root);
writeFile(nameParts, code, cb || done);
if (result.sources && options.compressOutputDirPrefix) {
// compress and save in parallel
pending++;
var compress = require("architect-build/compress");
code = compress.withCache(result.sources, {
cache: cache,
obfuscate: options.obfuscate,
exclude: /(jsoniq|xquery)\.js$/
}).code;
nameParts[0] += "/" + options.compressOutputDirPrefix;
writeFile(nameParts, code, done);
}
if (result.sources) {
pending++;
async.forEach(result.sources, function(pkg, next) {
var deps = moduleDeps.getSubmodules(pkg.source, pkg.id);
if (pkg.submodules)
deps = deps.concat(pkg.submodules);
if (!deps.length)
return next();
async.forEach(deps, function(moduleName, next) {
console.log(moduleName, pkg.id);
build.buildModule(moduleName, pathConfig, save(["modules", moduleName + ".js"], next));
}, next);
}, done);
}
};
}
function writeFile(filename, code, cb) {
if (typeof filename != "string")
filename = path.join.apply(path, filename);
mkdirp(path.dirname(filename), function(err) {
if (err) return cb(err);
fs.writeFile(filename, code, "utf8", function(err) {
if (err) return cb(err);
console.log("file saved at", filename);
cb && cb();
});
});
}
function done(err) {
if (err) {
console.error(err, err.stack);
console.trace();
process.exit(1);
}
pending--;
if (pending <= 0)
process.exit();
}
});
function listAceModules(pathConfig, cb) {
var result = [
"plugins/c9.ide.ace.keymaps/vim/keymap",
"plugins/c9.ide.ace.keymaps/emacs/keymap",
"plugins/c9.ide.ace.keymaps/sublime/keymap",
"plugins/c9.ide.theme.jett/ace.themes/jett"
];
// FIXME: this could be resolved via pathConfig:
var pathMap = {
"ace": __dirname + "/../node_modules/ace/lib/ace",
"plugins": __dirname + "/../../plugins",
"plugins/salesforce.language": __dirname + "/../../node_modules/salesforce.language",
"plugins/salesforce.sync": __dirname + "/../../node_modules/salesforce.sync"
};
var packages = [
"ace",
"plugins/salesforce.language",
"plugins/salesforce.sync",
];
function toFsPath(id) {
var testPath = id, tail = "";
while (testPath) {
if (pathMap[testPath])
return pathMap[testPath] + tail;
var i = testPath.lastIndexOf("/");
if (i === -1) break;
tail = testPath.substr(i) + tail;
testPath = testPath.slice(0, i);
}
throw new Error("Cannot map path " + id);
}
function readPackage(name, type, excludePattern) {
if (!excludePattern)
excludePattern = /_test/;
var targetPath = name + "/" + type;
var sourcePath = toFsPath(targetPath);
try {
var files = fs.readdirSync(sourcePath);
} catch (e) {
if (e.code === "ENOENT") return;
else throw e;
}
files = files.filter(function(p) {
return !excludePattern.test(p)
&& !/[\s#]/.test(p)
&& /\.js$/.test(p);
});
files.forEach(function(p) {
result.push(targetPath + "/" + p.replace(/.js$/, ""));
});
}
packages.forEach(function(name) {
var isAce = (name === "ace");
var modesExcludePattern = /_highlight_rules|_test|_worker|xml_util|_outdent|behaviour|completions/;
readPackage(name, (isAce ? "mode" : "modes"), modesExcludePattern);
readPackage(name, (isAce ? "theme" : "themes"));
readPackage(name, "ext");
readPackage(name, "snippets");
});
function take() {
var p = result.pop();
console.log("building ", p, result.length);
cb(p, result.length && take);
}
take();
}
function copyStaticResources(usedPlugins, pathConfig, next) {
var moduleDeps = require("architect-build/module-deps");
var copy = require('architect-build/copy');
// todo: use usedPlugins to filter out some of unneeded deps
var roots = pathConfig.pathMap;
Object.keys(roots).filter(function(p) {
return !/(c9.docker|docs|smith|vfs-socket|engine.io|msgpack.js)$/.test(p);
}).forEach(function(p) {
var absPath = moduleDeps.resolveModulePath(p, pathConfig.pathMap);
if (/^\/lib\/ace/.test(p))
return;
if (!cache.files) {
console.error("Config is empty");
process.exit(1);
}
copy(absPath, root + "/static/" + p, {
include: /^(remarkable.min.js|runners_list.js|builders_list.js|rusha.min.js|bootstrap.js)$/,
exclude: function(name, dir) {
if (/\.css$/.test(name)) {
if (!cache.files[dir + "/" + name]) {
console.log("\x1b [1A\x1b[0K", "adding file ", dir + "/" + name);
return false;
}
}
if (name == "node_modules" && /plugins\/[^\/\\]+/.test(dir))
return true;
if (/^(LICENSE|README.md)$/.test(name))
return true;
return /\.(jsx?|css|less|xml|ejs|prv|pub|sh)$|(^|[/])^(mock|example|\.[^/]*|package.json)[/]?$/.test(name);
},
onDir: function(e) { console.log("\x1b [1A\x1b[0K" + e); }
});
});
next();
}
}
});