coffee-toaster
Version:
Minimalist build system for CoffeeScript.
1,395 lines (1,247 loc) • 45.5 kB
JavaScript
var __t;
__t = function(ns) {
var curr, index, part, parts, _i, _len;
curr = null;
parts = [].concat = ns.split(".");
for (index = _i = 0, _len = parts.length; _i < _len; index = ++_i) {
part = parts[index];
if (curr === null) {
curr = eval(part);
continue;
} else {
if (curr[part] == null) {
curr = curr[part] = {};
} else {
curr = curr[part];
}
}
}
return curr;
};
var toaster = exports.toaster = {};
(function() {
var Toaster, debug, error, exec, fs, growl, icon_error, icon_warn, interval, log, msgs, os, path, process_msgs, queue_msg, start_worker, stop_worker, warn,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__slice = [].slice,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
__t('toaster').Toast = (function() {
var colors, cs, exec, fs, fsu, path;
fs = require("fs");
fsu = require("fs-util");
path = require("path");
exec = (require("child_process")).exec;
colors = require('colors');
cs = require("coffee-script");
Toast.prototype.builders = null;
function Toast(toaster) {
var code, config, config_file, contents, filepath, fix_scope, item, watcher, _i, _len, _ref,
_this = this;
this.toaster = toaster;
this.toast = __bind(this.toast, this);
this.basepath = this.toaster.basepath;
this.builders = [];
if ((config = this.toaster.cli.argv["config"]) != null) {
if (!(config instanceof Object)) {
config = JSON.parse(config);
}
_ref = [].concat(config);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
item = _ref[_i];
this.toast(item);
}
} else {
config_file = this.toaster.cli.argv["config-file"];
filepath = config_file || path.join(this.basepath, "toaster.coffee");
if (this.toaster.cli.argv.w) {
watcher = fsu.watch(filepath);
watcher.on('change', function(f) {
var now;
now = (("" + (new Date)).match(/[0-9]{2}\:[0-9]{2}\:[0-9]{2}/))[0];
log(("[" + now + "] " + 'Changed'.bold + " " + filepath).cyan);
watcher.close();
return _this.toaster.reset();
});
}
if (fs.existsSync(filepath)) {
contents = fs.readFileSync(filepath, "utf-8");
try {
code = cs.compile(contents, {
bare: 1
});
} catch (err) {
error(err.message + " at 'toaster.coffee' config file.");
}
fix_scope = /(^[\s\t]?)(toast)+(\()/mg;
code = code.replace(fix_scope, "$1this.$2$3");
eval(code);
} else {
error("File not found: ".yellow + (" " + filepath.red + "\n") + "Try running:".yellow + " toaster -i".green + " or type".yellow + (" " + 'toaster -h'.green + " ") + "for more info".yellow);
}
}
}
Toast.prototype.toast = function(srcpath, params) {
var alias, builder, config, debug, dir, folder, i, item, v, vpath, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9;
if (params == null) {
params = {};
}
if (srcpath instanceof Object) {
params = srcpath;
} else if ((path.resolve(srcpath)) !== srcpath) {
folder = path.join(this.basepath, srcpath);
}
if (params.release === null) {
error('Release path not informed in config.');
return process.exit();
} else {
dir = path.dirname(params.release);
if (!fs.existsSync(path.join(this.basepath, dir))) {
error("Release folder does not exist:\n\t" + dir.yellow);
return process.exit();
}
}
if (params.debug) {
debug = path.join(this.basepath, params.debug);
} else {
debug = null;
}
config = {
is_building: false,
basepath: this.basepath,
src_folders: [],
files: [],
vendors: (_ref = params.vendors) != null ? _ref : [],
exclude: (_ref1 = params.exclude) != null ? _ref1 : [],
bare: (_ref2 = params.bare) != null ? _ref2 : false,
packaging: (_ref3 = params.packaging) != null ? _ref3 : true,
expose: (_ref4 = params.expose) != null ? _ref4 : null,
minify: (_ref5 = params.minify) != null ? _ref5 : true,
httpfolder: (_ref6 = params.httpfolder) != null ? _ref6 : "",
release: path.join(this.basepath, params.release),
debug: debug
};
_ref7 = config.vendors;
for (i = _i = 0, _len = _ref7.length; _i < _len; i = ++_i) {
v = _ref7[i];
vpath = config.vendors[i] = path.resolve(v);
if ((path.resolve(vpath)) !== vpath) {
config.vendors[i] = path.join(this.basepath, v);
}
}
if (!(srcpath instanceof Object)) {
srcpath = path.resolve(path.join(this.basepath, srcpath));
config.src_folders.push({
path: srcpath,
alias: params.alias || null
});
}
if (params.folders != null) {
_ref8 = params.folders;
for (folder in _ref8) {
alias = _ref8[folder];
if ((path.resolve(folder)) !== folder) {
folder = path.join(this.basepath, folder);
}
config.src_folders.push({
path: folder,
alias: alias
});
}
}
_ref9 = config.src_folders;
for (_j = 0, _len1 = _ref9.length; _j < _len1; _j++) {
item = _ref9[_j];
if (!fs.existsSync(item.path)) {
error(("Source folder doens't exist:\n\t" + item.path.red + "\n") + ("Check your " + 'toaster.coffee'.yellow + " and try again.") + "\n\t" + (path.join(this.basepath, "toaster.coffee")).yellow);
return process.exit();
}
}
builder = new toaster.core.Builder(this.toaster, this.toaster.cli, config);
return this.builders.push(builder);
};
return Toast;
})();
__t('toaster.generators').Question = (function() {
function Question() {}
Question.prototype.ask = function(question, format, fn) {
var stdin, stdout,
_this = this;
stdin = process.stdin;
stdout = process.stdout;
stdout.write("" + question + " ");
return stdin.once('data', function(data) {
var msg, rule;
data = data.toString().trim();
if (format.test(data)) {
return fn(data.trim());
} else {
msg = "" + 'Invalid entry, it should match:'.red;
rule = "" + (format.toString().cyan);
stdout.write("\t" + msg + " " + rule + "\n");
return _this.ask(question, format, fn);
}
}).resume();
};
return Question;
})();
__t('toaster.utils').ArrayUtil = (function() {
function ArrayUtil() {}
ArrayUtil.find = function(source, search, by_property) {
var k, p, v, _i, _j, _k, _len, _len1, _len2;
if (!by_property) {
for (k = _i = 0, _len = source.length; _i < _len; k = ++_i) {
v = source[k];
if (v === search) {
return {
item: v,
index: k
};
}
}
} else {
by_property = [].concat(by_property);
for (k = _j = 0, _len1 = source.length; _j < _len1; k = ++_j) {
v = source[k];
for (_k = 0, _len2 = by_property.length; _k < _len2; _k++) {
p = by_property[_k];
if (search === v[p]) {
return {
item: v,
index: k
};
}
}
}
}
return null;
};
ArrayUtil.find_all = function(source, search, by_property, regexp, unique) {
var item, k, p, v, _i, _j, _k, _len, _len1, _len2, _output, _unique;
_output = [];
_unique = {};
if (by_property === null) {
for (k = _i = 0, _len = source.length; _i < _len; k = ++_i) {
v = source[k];
if (regexp) {
if (search.test(v)) {
item = {
item: v,
index: k
};
}
} else {
if (search === v) {
item = {
item: v,
index: k
};
}
}
if (item) {
_output.push(item);
}
}
} else {
by_property = [].concat(by_property);
for (k = _j = 0, _len1 = source.length; _j < _len1; k = ++_j) {
v = source[k];
for (_k = 0, _len2 = by_property.length; _k < _len2; _k++) {
p = by_property[_k];
item = null;
if (regexp) {
if (search.test(v[p])) {
if (unique && !_unique[k]) {
item = {
item: v,
index: k
};
} else if (unique === !true) {
item = {
item: v,
index: k
};
}
}
} else {
if (search === v[p]) {
item = {
item: v,
index: k
};
}
}
if (item) {
_unique[k] = true;
_output.push(item);
}
}
}
}
return _output;
};
ArrayUtil.diff = function(a, b, by_property) {
var diff, item, search, _i, _j, _len, _len1;
if (a == null) {
a = [];
}
if (b == null) {
b = [];
}
diff = [];
for (_i = 0, _len = a.length; _i < _len; _i++) {
item = a[_i];
search = by_property != null ? item[by_property] : item;
if (!ArrayUtil.has(b, search, by_property)) {
diff.push({
item: item,
action: "deleted"
});
}
}
for (_j = 0, _len1 = b.length; _j < _len1; _j++) {
item = b[_j];
search = by_property != null ? item[by_property] : item;
if (!ArrayUtil.has(a, search, by_property)) {
diff.push({
item: item,
action: "created"
});
}
}
return diff;
};
ArrayUtil.has = function(source, search, by_property) {
return ArrayUtil.find(source, search, by_property) != null;
};
ArrayUtil.replace_into = function(src, index, items) {
items = [].concat(items);
src.splice(index, 1);
while (items.length) {
src.splice(index++, 0, items.shift());
}
return src;
};
return ArrayUtil;
})();
__t('toaster.utils').FnUtil = (function() {
function FnUtil() {}
FnUtil.proxy = function() {
var fn, params;
fn = arguments[0], params = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
return function() {
var inner_params;
inner_params = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return fn.apply(null, params.concat(inner_params));
};
};
return FnUtil;
})();
os = require('os');
growl = os.platform() === 'win32' ? null : require('growl');
icon_warn = __dirname + '/../images/warning.png';
icon_error = __dirname + '/../images/error.png';
log = function(msg, send_to_growl) {
if (send_to_growl == null) {
send_to_growl = false;
}
console.log(msg);
return msg;
};
debug = function(msg, send_to_growl) {
if (send_to_growl == null) {
send_to_growl = false;
}
msg = log("" + msg.magenta);
return msg;
};
error = function(msg, send_to_growl, file) {
if (send_to_growl == null) {
send_to_growl = true;
}
if (file == null) {
file = null;
}
msg = log("ERROR ".bold.red + msg);
if (send_to_growl && (growl != null)) {
msg = msg.replace(/\[\d{2}m/g, "");
msg = msg.replace(/(\[\dm)([^\s]+)/ig, "<$2>$3");
queue_msg({
msg: msg,
opts: {
title: 'Coffee Toaster',
image: icon_error
}
});
}
return msg;
};
warn = function(msg, send_to_growl) {
if (send_to_growl == null) {
send_to_growl = true;
}
msg = log("WARNING ".bold.yellow + msg);
if (send_to_growl && (growl != null)) {
msg = msg.replace(/\[\d{2}m/g, "");
msg = msg.replace(/(\[\dm)([^\s]+)/ig, "<$2>$3");
queue_msg({
msg: msg,
opts: {
title: 'Coffee Toaster',
image: icon_warn
}
});
}
return msg;
};
msgs = [];
interval = null;
start_worker = function() {
if (interval == null) {
interval = setInterval(process_msgs, 150);
return process_msgs();
}
};
stop_worker = function() {
if (interval != null) {
clearInterval(interval);
return interval = null;
}
};
queue_msg = function(msg) {
msgs.push(msg);
return start_worker();
};
process_msgs = function() {
var msg;
if (msgs.length) {
msg = msgs.shift();
return growl.notify(msg.msg, msg.opts);
} else {
return stop_worker();
}
};
__t('toaster.utils').StringUtil = (function() {
function StringUtil() {}
StringUtil.titleize = function(str) {
var index, word, words, _i, _len;
words = str.match(/[a-z]+/gi);
for (index = _i = 0, _len = words.length; _i < _len; index = ++_i) {
word = words[index];
words[index] = StringUtil.ucasef(word);
}
return words.join(" ");
};
StringUtil.ucasef = function(str) {
var output;
output = str.substr(0, 1).toUpperCase();
return output += str.substr(1).toLowerCase();
};
return StringUtil;
})();
__t('toaster.core').Script = (function() {
var ArrayUtil, cs, fs, path;
fs = require("fs");
path = require('path');
cs = require("coffee-script");
ArrayUtil = toaster.utils.ArrayUtil;
function Script(builder, folderpath, realpath, alias, opts) {
this.builder = builder;
this.folderpath = folderpath;
this.realpath = realpath;
this.alias = alias;
this.opts = opts;
this.getinfo();
}
Script.prototype.getinfo = function(declare_ns) {
var baseclass, decl, extending, item, klass, name, repl, requirements, rgx, rgx_ext, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
if (declare_ns == null) {
declare_ns = true;
}
this.raw = fs.readFileSync(this.realpath, "utf-8");
this.dependencies_collapsed = [];
this.baseclasses = [];
this.filepath = this.realpath.replace(this.folderpath, '');
if (this.alias != null) {
this.filepath = path.join(path.sep, this.alias, this.filepath);
}
this.filename = path.basename(this.filepath);
this.filefolder = path.dirname(this.filepath);
this.namespace = "";
if (this.filepath.indexOf(path.sep) === -1) {
this.filefolder = "";
}
this.namespace = this.filefolder.replace(new RegExp("\\" + path.sep, "g"), ".");
this.namespace = this.namespace.replace(/^\.?(.*)\.?$/g, "$1");
rgx = /^(class)+\s+([^\s]+)+(\s(extends)\s+([\w.]+))?/mg;
rgx_ext = /(^|=\s*)(class)\s(\w+)\s(extends)\s(\\w+)\s*$/gm;
if (this.raw.match(rgx) != null) {
if (this.namespace !== "" && this.builder.packaging) {
_ref = [].concat(this.raw.match(rgx));
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
decl = _ref[_i];
name = decl.match(/class\s([^\s]+)/);
name = (name[1].split('.')).pop();
extending = decl.match(/(\sextends\s[^\s]+$)/m);
if (extending) {
extending = extending[0];
}
extending || (extending = "");
repl = "class " + this.namespace + "." + name + extending;
if (decl !== repl) {
this.raw = this.raw.replace(decl, repl);
fs.writeFileSync(this.realpath, this.raw);
}
}
this.classpath = "" + this.namespace + "." + this.classname;
}
this.classname = this.raw.match(rgx)[3];
_ref2 = (_ref1 = this.raw.match(rgx_ext)) != null ? _ref1 : [];
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
klass = _ref2[_j];
baseclass = klass.match(rgx_ext)[5];
this.baseclasses.push(baseclass);
}
}
if (/(#<<\s)(.*)/g.test(this.raw)) {
requirements = this.raw.match(/(#<<\s)(.*)/g);
_results = [];
for (_k = 0, _len2 = requirements.length; _k < _len2; _k++) {
item = requirements[_k];
item = /(#<<\s)(.*)/.exec(item)[2];
item = item.replace(/\s/g, "");
if (path.sep === "\\") {
item = item.replace(/(\/)/g, "\\");
}
_results.push(this.dependencies_collapsed = this.dependencies_collapsed.concat(item));
}
return _results;
}
};
Script.prototype.expand_dependencies = function() {
var dependency, expanded, files, found, index, reg, _i, _j, _len, _len1, _ref;
files = this.builder.files;
this.dependencies = [];
_ref = this.dependencies_collapsed;
for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
dependency = _ref[index];
if ((dependency.substr(0, 1)) === path.sep) {
dependency = dependency.substr(1);
}
if (dependency.substr(-1) !== "*") {
this.dependencies.push("" + path.sep + dependency + ".coffee");
continue;
}
reg = new RegExp(dependency.replace(/(\/|\\)/g, "\\$1"));
found = ArrayUtil.find_all(files, reg, "filepath", true, true);
if (found.length <= 0) {
warn(("Nothing found inside " + ("'" + dependency).white + "'").yellow);
continue;
}
for (_j = 0, _len1 = found.length; _j < _len1; _j++) {
expanded = found[_j];
if (expanded.item.filepath !== this.filepath) {
this.dependencies.push(expanded.item.filepath);
}
}
}
return this.dependencies;
};
return Script;
})();
__t('toaster').Cli = (function() {
var optimist;
optimist = require('optimist');
function Cli() {
var usage;
usage = "" + 'CoffeeToaster'.bold + "\n";
usage += " Minimalist build system for CoffeeScript\n\n".grey;
usage += "" + 'Usage:' + "\n";
usage += " toaster [" + 'options'.green + "] [" + 'path'.green + "]\n\n";
usage += "" + 'Examples:' + "\n";
usage += " toaster -n myawsomeapp (" + 'required'.red + ")\n";
usage += " toaster -i [myawsomeapp] (" + 'optional'.green + ")\n";
usage += " toaster -w [myawsomeapp] (" + 'optional'.green + ")\n";
usage += " toaster -wd [myawsomeapp] (" + 'optional'.green + ")";
this.argv = (this.opts = optimist.usage(usage).alias('n', 'new').describe('n', "Scaffold a very basic new App").alias('i', 'init').describe('i', "Create a config (toaster.coffee) file").alias('w', 'watch').describe('w', "Start watching/compiling your project").alias('c', 'compile').describe('c', "Compile the entire project, without watching it.").alias('d', 'debug').describe('d', 'Debug mode (compile js files individually)').alias('a', 'autorun').describe('a', 'Execute the script in node.js after compilation').alias('j', 'config').string('j').describe('j', "Config file formatted as a json-string.").alias('f', 'config-file').string('f').describe('f', "Path to a different config file.").alias('v', 'version').describe('v', '').alias('h', 'help').describe('h', '')).argv;
}
return Cli;
})();
__t('toaster.core').Builder = (function() {
var ArrayUtil, FnUtil, Script, StringUtil, cp, cs, fs, fsu, missing, path, uglify, uglify_parser, _ref;
fs = require('fs');
fsu = require('fs-util');
path = require('path');
cs = require("coffee-script");
cp = require("child_process");
uglify = require("uglify-js").uglify;
uglify_parser = require("uglify-js").parser;
Script = toaster.core.Script;
_ref = toaster.utils, FnUtil = _ref.FnUtil, ArrayUtil = _ref.ArrayUtil, StringUtil = _ref.StringUtil;
Builder.prototype.watchers = null;
Builder.prototype._include_tmpl = "document.write('<scri'+'pt src=\"%SRC%\"></scr'+'ipt>')";
function Builder(toaster, cli, config) {
this.toaster = toaster;
this.cli = cli;
this.config = config;
this.merge_vendors = __bind(this.merge_vendors, this);
this.on_fs_change = __bind(this.on_fs_change, this);
this.build = __bind(this.build, this);
this.vendors = this.config.vendors;
this.bare = this.config.bare;
this.packaging = this.config.packaging;
this.expose = this.config.expose;
this.minify = this.config.minify;
this.exclude = [].concat(this.config.exclude);
this.httpfolder = this.config.httpfolder;
this.release = this.config.release;
this.debug = this.config.debug;
this.init();
if (this.cli.argv.w) {
this.watch();
}
}
Builder.prototype.init = function() {
var falias, file, folder, fpath, include, item, result, s, _i, _len, _ref1, _results;
this.files = this.config.files;
_ref1 = this.config.src_folders;
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
folder = _ref1[_i];
result = fsu.find(folder.path, /.coffee$/m);
fpath = folder.path;
falias = folder.alias;
_results.push((function() {
var _j, _k, _len1, _len2, _ref2, _results1;
_results1 = [];
for (_j = 0, _len1 = result.length; _j < _len1; _j++) {
file = result[_j];
include = true;
_ref2 = this.exclude;
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
item = _ref2[_k];
include &= !(new RegExp(item).test(file));
}
if (include) {
s = new Script(this, fpath, file, falias, this.cli);
_results1.push(this.files.push(s));
} else {
_results1.push(void 0);
}
}
return _results1;
}).call(this));
}
return _results;
};
Builder.prototype.reset = function() {
var watcher, _i, _len, _ref1, _results;
_ref1 = this.watchers;
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
watcher = _ref1[_i];
_results.push(watcher.close());
}
return _results;
};
Builder.prototype.build = function(header_code, footer_code) {
var args, ast, contents, f, files, i, include, namespaces, now, tmpl, vendors, _i, _j, _len, _ref1;
if (header_code == null) {
header_code = "";
}
if (footer_code == null) {
footer_code = "";
}
namespaces = this.build_namespaces();
vendors = this.merge_vendors();
contents = [];
if (vendors !== "") {
contents.push(vendors);
}
if (this.packaging) {
contents.push(namespaces);
}
if (header_code !== "") {
contents.push(header_code);
}
contents.push(this.compile());
if (header_code !== "") {
contents.push(footer_code);
}
contents = contents.join('\n');
if (this.minify) {
ast = uglify_parser.parse(contents);
ast = uglify.ast_mangle(ast);
ast = uglify.ast_squeeze(ast);
contents = uglify.gen_code(ast);
}
fs.writeFileSync(this.release, contents);
now = (("" + (new Date)).match(/[0-9]{2}\:[0-9]{2}\:[0-9]{2}/))[0];
log(("[" + now + "] " + 'Compiled'.bold + " " + this.release).green);
if (this.cli.argv.d && (this.debug != null) && !this.cli.argv.a) {
files = this.compile_for_debug();
for (i = _i = 0, _len = files.length; _i < _len; i = ++_i) {
f = files[i];
include = path.normalize("" + this.httpfolder + "/toaster/" + f);
if (path.sep === "\\") {
include = include.replace(/\\/g, "\/");
}
tmpl = this._include_tmpl.replace("%SRC%", include);
files[i] = tmpl;
}
contents = [];
if (vendors !== "") {
contents.push(vendors);
}
if (this.packaging) {
contents.push(namespaces);
}
if (header_code !== "") {
contents.push(header_code);
}
contents.push(files.join("\n"));
if (header_code !== "") {
contents.push(footer_code);
}
contents = contents.join('\n');
fs.writeFileSync(this.debug, contents);
log(("[" + now + "] " + 'Compiled'.bold + " " + this.debug).green);
}
if (this.cli.argv.a) {
args = [];
if (process.argv.length > 3) {
for (i = _j = 3, _ref1 = process.argv.length; _j < _ref1; i = _j += 1) {
args.push(process.argv[i]);
}
}
if (this.child != null) {
log("Application restarted:".blue);
this.child.kill('SIGHUP');
} else {
log("Application started:".blue);
}
if (this.cli.argv.d) {
return this.child = cp.fork(this.release, args, {
execArgv: ['--debug-brk']
});
} else {
return this.child = cp.fork(this.release, args);
}
}
};
Builder.prototype.build_namespaces = function() {
var buffer, folder, name, scope, t, tree, _i, _len, _ref1;
tree = {};
_ref1 = this.config.src_folders;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
folder = _ref1[_i];
if (folder.alias != null) {
t = (tree[folder.alias] = {});
}
this.build_ns_tree(t || tree, folder.path);
}
buffer = "";
for (name in tree) {
scope = tree[name];
buffer += "var " + name + " = ";
if (this.expose != null) {
buffer += "" + this.expose + "." + name + " = ";
}
buffer += (JSON.stringify(scope, null, '')).replace(/\"/g, "'");
buffer += ";\n";
}
return buffer;
};
Builder.prototype.build_ns_tree = function(tree, folderpath) {
var folder, folders, include, item, _i, _j, _len, _len1, _ref1, _results;
folders = fsu.ls(folderpath);
_results = [];
for (_i = 0, _len = folders.length; _i < _len; _i++) {
folder = folders[_i];
include = true;
_ref1 = this.exclude;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
item = _ref1[_j];
include &= !(new RegExp(item).test(folder));
}
if (include) {
_results.push(this.build_ns_tree((tree[folder.match(/[^\/\\]+$/m)] = {}), folder));
} else {
_results.push(void 0);
}
}
return _results;
};
Builder.prototype.watch = function() {
var src, temp, vendor, watcher, _i, _j, _len, _len1, _ref1, _ref2, _results;
this.watchers = [];
_ref1 = this.config.src_folders;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
src = _ref1[_i];
this.watchers.push((watcher = fsu.watch(src.path, /.coffee$/m)));
watcher.on('create', FnUtil.proxy(this.on_fs_change, src, 'create'));
watcher.on('change', FnUtil.proxy(this.on_fs_change, src, 'change'));
watcher.on('delete', FnUtil.proxy(this.on_fs_change, src, 'delete'));
}
_ref2 = this.vendors;
_results = [];
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
vendor = _ref2[_j];
temp = fsu.watch(vendor);
temp.on('create', FnUtil.proxy(this.on_fs_change, src, 'create'));
temp.on('change', FnUtil.proxy(this.on_fs_change, src, 'change'));
_results.push(temp.on('delete', FnUtil.proxy(this.on_fs_change, src, 'delete')));
}
return _results;
};
Builder.prototype.on_fs_change = function(src, ev, f) {
var falias, file, fpath, include, item, msg, now, relative_path, s, spath, type, _i, _len, _ref1;
if (f.type === "dir" && ev === "create") {
return;
}
fpath = f.location;
spath = src.path;
if (src.alias != null) {
falias = path.sep + src.alias;
} else {
falias = '';
}
include = true;
_ref1 = this.exclude;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
item = _ref1[_i];
include &= !(new RegExp(item).test(fpath));
}
if (!include) {
return;
}
type = StringUtil.titleize(f.type);
relative_path = fpath.replace(spath, falias);
now = (("" + (new Date)).match(/[0-9]{2}\:[0-9]{2}\:[0-9]{2}/))[0];
switch (ev) {
case "create":
if (f.type === "file") {
s = new Script(this, spath, fpath, falias, this.cli);
this.files.push(s);
}
msg = "" + ('New ' + f.type + ' created').bold;
log(("[" + now + "] " + msg + " " + f.location).cyan);
break;
case "delete":
file = ArrayUtil.find(this.files, relative_path, "filepath");
if (file === null) {
return;
}
this.files.splice(file.index, 1);
msg = "" + (type + ' deleted, stop watching').bold;
log(("[" + now + "] " + msg + " " + f.location).red);
break;
case "change":
file = ArrayUtil.find(this.files, relative_path, "filepath");
if (file === null) {
warn("CHANGED FILE IS APPARENTLY NULL...");
} else {
file.item.getinfo();
msg = "" + (type + ' changed').bold;
log(("[" + now + "] " + msg + " " + f.location).cyan);
}
}
if (this.toaster.before_build === null || this.toaster.before_build()) {
return this.build();
}
};
Builder.prototype.compile = function() {
var file, msg, output, _i, _j, _len, _len1, _ref1, _ref2;
_ref1 = this.files;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
file = _ref1[_i];
try {
cs.compile(file.raw);
} catch (err) {
msg = err.message.replace('"', '\\"');
msg = ("" + msg.white + " at file: ") + ("" + file.filepath).bold.red;
error(msg);
return null;
}
}
_ref2 = this.files;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
file = _ref2[_j];
file.expand_dependencies();
}
this.reorder();
output = ((function() {
var _k, _len2, _ref3, _results;
_ref3 = this.files;
_results = [];
for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {
file = _ref3[_k];
_results.push(file.raw);
}
return _results;
}).call(this)).join("\n");
return output = cs.compile(output, {
bare: this.bare
});
};
Builder.prototype.compile_for_debug = function() {
var absolute_path, file, files, find, folder_path, index, relative_path, release_path, _i, _len, _ref1;
release_path = path.dirname(this.debug);
release_path = path.join(release_path, "toaster");
if (fs.existsSync(release_path)) {
fsu.rm_rf(release_path);
}
fsu.mkdir_p(release_path);
files = [];
_ref1 = this.files;
for (index = _i = 0, _len = _ref1.length; _i < _len; index = ++_i) {
file = _ref1[index];
find = "" + this.toaster.basepath + path.sep;
relative_path = file.filepath.replace(find, "");
relative_path = relative_path.replace(".coffee", ".js");
absolute_path = path.resolve(path.join(release_path, relative_path));
folder_path = path.dirname(absolute_path);
if (!fs.existsSync(folder_path)) {
fsu.mkdir_p(folder_path);
}
try {
fs.writeFileSync(absolute_path, cs.compile(file.raw, {
bare: this.bare
}));
} catch (err) {
continue;
}
files.push(relative_path);
}
return files;
};
missing = {};
Builder.prototype.reorder = function(cycling) {
var bc, dependency, dependency_index, file, file_index, filepath, found, i, index, not_found, _i, _j, _len, _len1, _ref1, _ref2, _results;
if (cycling == null) {
cycling = false;
}
if (cycling === false) {
this.missing = {};
}
_ref1 = this.files;
_results = [];
for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {
file = _ref1[i];
if (!file.dependencies.length && !file.baseclasses.length) {
continue;
}
_ref2 = file.dependencies;
for (index = _j = 0, _len1 = _ref2.length; _j < _len1; index = ++_j) {
filepath = _ref2[index];
dependency = ArrayUtil.find(this.files, filepath, "filepath");
if (dependency != null) {
dependency_index = dependency.index;
}
if (dependency_index < i && (dependency != null)) {
continue;
}
if (dependency != null) {
if (ArrayUtil.has(dependency.item.dependencies, file.filepath)) {
file.dependencies.splice(index, 1);
warn("Circular dependency found between ".yellow + filepath.grey.bold + " and ".yellow + file.filepath.grey.bold);
continue;
} else {
this.files.splice(index, 0, dependency.item);
this.files.splice(dependency.index + 1, 1);
this.reorder(true);
break;
}
} else if (this.missing[filepath] !== true) {
this.missing[filepath] = true;
file.dependencies.push(filepath);
file.dependencies.splice(index, 1);
warn(("" + 'Dependency'.yellow + " " + filepath.bold.grey + " ") + ("" + 'not found for file'.yellow + " ") + file.filepath.grey.bold);
}
}
file_index = ArrayUtil.find(this.files, file.filepath, "filepath");
file_index = file_index.index;
_results.push((function() {
var _k, _len2, _ref3, _results1;
_ref3 = file.baseclasses;
_results1 = [];
for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {
bc = _ref3[_k];
found = ArrayUtil.find(this.files, bc, "classname");
not_found = (found === null) || (found.index > file_index);
if (not_found && !this.missing[bc]) {
this.missing[bc] = true;
_results1.push(warn("Base class ".yellow + ("" + bc + " ").bold.grey + "not found for class ".yellow + ("" + file.classname + " ").bold.grey + "in file ".yellow + file.filepath.bold.grey));
} else {
_results1.push(void 0);
}
}
return _results1;
}).call(this));
}
return _results;
};
Builder.prototype.merge_vendors = function() {
var buffer, vendor, _i, _len, _ref1;
buffer = [];
_ref1 = this.vendors;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
vendor = _ref1[_i];
if (fs.existsSync(vendor)) {
buffer.push(fs.readFileSync(vendor, 'utf-8'));
} else {
warn("Vendor not found at ".white + vendor.yellow.bold);
}
}
return buffer.join("\n");
};
return Builder;
})();
__t('toaster.generators').Config = (function(_super) {
var fs, path;
__extends(Config, _super);
path = require("path");
fs = require("fs");
Config.prototype.tpl = "# => SRC FOLDER\ntoast '%src%'\n\n # EXCLUDED FOLDERS (optional)\n # exclude: ['folder/to/exclude', 'another/folder/to/exclude', ... ]\n\n # => VENDORS (optional)\n # vendors: ['vendors/x.js', 'vendors/y.js', ... ]\n\n # => OPTIONS (optional, default values listed)\n # bare: false\n # packaging: true\n # expose: ''\n # minify: true\n\n # => HTTPFOLDER (optional), RELEASE / DEBUG (required)\n httpfolder: '%httpfolder%'\n release: '%release%'\n debug: '%debug%'";
function Config(basepath) {
this.basepath = basepath;
this.write = __bind(this.write, this);
this.create = __bind(this.create, this);
}
Config.prototype.create = function() {
var q1, q2, q3,
_this = this;
q1 = "Path to your src folder? [src] : ";
q2 = "Path to your release file? [www/js/app.js] : ";
q3 = "Starting from your webroot '/', what's the folderpath to " + "reach your release file? (i.e. js) (optional) : ";
return this.ask(q1.magenta, /.+/, function(src) {
return _this.ask(q2.magenta, /.+/, function(release) {
return _this.ask(q3.cyan, /.*/, function(httpfolder) {
return _this.write(src, release, httpfolder);
});
});
});
};
Config.prototype.write = function(src, release, httpfolder) {
var buffer, filename, filepath, parts, question, rgx,
_this = this;
filepath = path.join(this.basepath, "toaster.coffee");
rgx = /(\/)?((\w+)(\.*)(\w+$))/;
parts = rgx.exec(release);
filename = parts[2];
if (filename.indexOf(".") > 0) {
debug = release.replace(rgx, "$1$3-debug$4$5");
} else {
debug = "" + release + "-debug";
}
buffer = this.tpl.replace("%src%", src.replace(/\\/g, "\/"));
buffer = buffer.replace("%release%", release.replace(/\\/g, "\/"));
buffer = buffer.replace("%debug%", debug.replace(/\\/g, "\/"));
buffer = buffer.replace("%httpfolder%", httpfolder.replace(/\\/g, "\/"));
if (fs.existsSync(filepath)) {
question = "\tDo you want to overwrite the file: " + filepath.yellow;
question += " ? [y/N] : ".white;
return this.ask(question, /.*?/, function(overwrite) {
if (overwrite.match(/y/i)) {
_this.save(filepath, buffer);
return process.exit();
}
});
} else {
this.save(filepath, buffer);
return process.exit();
}
};
Config.prototype.save = function(filepath, contents) {
fs.writeFileSync(filepath, contents);
log("" + 'Created'.green.bold + " " + filepath);
return process.exit();
};
return Config;
})(toaster.generators.Question);
__t('toaster.generators').Project = (function(_super) {
var FsUtil, fs, fsu, path;
__extends(Project, _super);
path = require("path");
fs = require("fs");
fsu = require('fs-util');
FsUtil = toaster.utils.FsUtil;
function Project(basepath) {
this.basepath = basepath;
this.scaffold = __bind(this.scaffold, this);
}
Project.prototype.create = function(folderpath, name, src, release) {
var error_msg, q1, q2, q3,
_this = this;
if ((typeof folderpath) !== 'string') {
error_msg = "You need to inform a target path!\n";
error_msg += "\ttoaster -n myawesomeapp".green;
return error(error_msg);
}
if ((name != null) && (src != null) && (release != null)) {
return this.scaffold(folderpath, name, src, release);
}
q1 = "Path to your src folder? [src] : ";
q2 = "Path to your release file? [www/js/app.js] : ";
q3 = "Starting from your webroot '/', what's the folderpath to " + "reach your release file? (i.e. js) (optional) : ";
return this.ask(q1.magenta, /.*/, function(src) {
if (src == null) {
src = null;
}
return _this.ask(q2.magenta, /.*/, function(release) {
if (release == null) {
release = null;
}
return _this.ask(q3.cyan, /.*/, function(httpfolder) {
var $httpfolder, $release, $src;
if (httpfolder == null) {
httpfolder = null;
}
$src = src || "src";
$release = release || "www/js/app.js";
if (src === '' && release === '' && httpfolder === '') {
$httpfolder = 'js';
} else {
$httpfolder = httpfolder || "";
}
_this.scaffold(folderpath, $src, $release, $httpfolder);
return process.exit();
});
});
});
};
Project.prototype.scaffold = function(target, src, release, httpfolder) {
var config, releasedir, releasefile, srcdir, vendorsdir;
target = path.resolve(target);
srcdir = path.join(target, src);
vendorsdir = path.join(target, "vendors");
releasefile = path.join(target, release);
releasedir = path.dirname(releasefile);
if (fsu.mkdir_p(target)) {
log("" + 'Created'.green.bold + " " + target);
}
if (fsu.mkdir_p(srcdir)) {
log("" + 'Created'.green.bold + " " + srcdir);
}
if (fsu.mkdir_p(vendorsdir)) {
log("" + 'Created'.green.bold + " " + vendorsdir);
}
if (fsu.mkdir_p(releasedir)) {
log("" + 'Created'.green.bold + " " + releasedir);
}
srcdir = srcdir.replace(target, "").substr(1);
releasefile = releasefile.replace(target, "").substr(1);
config = new toaster.generators.Config(target);
return config.write(srcdir, releasefile, httpfolder);
};
return Project;
})(toaster.generators.Question);
fs = require('fs');
path = require('path');
exec = (require("child_process")).exec;
__t('toaster.misc').InjectNS = (function() {
function InjectNS(builders) {
var builder, f, _i, _j, _len, _len1, _ref, _ref1;
this.builders = builders;
console.log("Declaring namespaces for files...");
_ref = this.builders;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
builder = _ref[_i];
_ref1 = builder.files;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
f = _ref1[_j];
f.getinfo(true);
fs.writeFileSync(f.realpath, f.raw);
f.getinfo(false);
console.log(f.realpath);
}
}
console.log("...done.");
}
return InjectNS;
})();
exports.run = function() {
return new Toaster;
};
exports.toaster = toaster;
exports.Toaster = Toaster = (function() {
var colors, fsu;
fs = require("fs");
fsu = require("fs-util");
path = require("path");
exec = (require("child_process")).exec;
colors = require('colors');
Toaster.prototype.before_build = null;
function Toaster(basedir, options, skip_initial_build) {
var base, config, contents, filepath, flag, k, schema, v, _i, _len, _ref;
if (options == null) {
options = null;
}
if (skip_initial_build == null) {
skip_initial_build = false;
}
this.basepath = path.resolve(basedir || ".");
this.cli = new toaster.Cli(options);
_ref = 'nicwd'.split('');
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
flag = _ref[_i];
if (typeof (base = this.cli.argv[flag]) === 'string') {
this.basepath = path.resolve(base);
break;
}
}
if (options != null) {
for (k in options) {
v = options[k];
this.cli.argv[k] = v;
}
}
if (this.cli.argv.v) {
filepath = path.join(__dirname, "/../package.json");
contents = fs.readFileSync(filepath, "utf-8");
schema = JSON.parse(contents);
return log(schema.version);
} else if (this.cli.argv.n) {
new toaster.generators.Project(this.basepath).create(this.cli.argv.n);
} else if (this.cli.argv.i) {
new toaster.generators.Config(this.basepath).create();
} else if (this.cli.argv.ns) {
this.toast = new toaster.Toast(this);
new toaster.misc.InjectNS(this.toast.builders);
} else if ((base = this.cli.argv.w || this.cli.argv.c || this.cli.argv.a)) {
config = options && options.config ? options.config : null;
this.toast = new toaster.Toast(this);
if (!skip_initial_build) {
this.build();
}
} else {
return log(this.cli.opts.help());
}
}
Toaster.prototype.build = function(header_code, footer_code) {
var builder, _i, _len, _ref, _results;
if (header_code == null) {
header_code = "";
}
if (footer_code == null) {
footer_code = "";
}
_ref = this.toast.builders;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
builder = _ref[_i];
_results.push(builder.build(header_code, footer_code));
}
return _results;
};
Toaster.prototype.reset = function() {
var builder, _i, _len, _ref;
_ref = this.toast.builders;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
builder = _ref[_i];
builder.reset();
}
return exports.run();
};
return Toaster;
})();
}).call(this);