coffee-toaster
Version:
Minimalist build system for CoffeeScript.
1,534 lines (1,378 loc) • 50.7 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, growl, icon_error, icon_warn, interval, log, msgs, process_msgs, queue_msg, start_worker, stop_worker, warn,
__slice = [].slice,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__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.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;
})();
__t('toaster.utils').FsUtil = (function() {
var ArrayUtil, FnUtil, fs, path, pn;
function FsUtil() {}
path = require("path");
fs = require("fs");
pn = (require("path")).normalize;
FnUtil = toaster.utils.FnUtil;
ArrayUtil = toaster.utils.ArrayUtil;
FsUtil.rmdir_rf = function(folderpath, root) {
var file, files, stats, _i, _len;
if (root == null) {
root = true;
}
files = fs.readdirSync(folderpath);
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
file = "" + folderpath + "/" + file;
stats = fs.lstatSync(file);
if (stats.isDirectory()) {
FsUtil.rmdir_rf(file, false);
fs.rmdirSync(file);
} else {
fs.unlinkSync(file);
}
}
if (root) {
return fs.rmdirSync(folderpath);
}
};
FsUtil.mkdir_p = function(folderpath) {
var exists, folder, folders, index, _i, _len;
if ((folderpath.slice(-1)) === "/") {
folderpath = folderpath.slice(0, -1);
}
folders = folderpath.split("/");
for (index = _i = 0, _len = folders.length; _i < _len; index = ++_i) {
folder = folders[index];
if ((folder = folders.slice(0, index + 1).join("/")) === "") {
continue;
}
exists = path.existsSync(folder);
if (exists && index === folders.length - 1) {
throw new Error(error("Folder exists: " + folder.red));
return false;
} else if (!exists) {
fs.mkdirSync(folder, '0755');
}
}
return true;
};
FsUtil.find = function(folderpath, pattern, include_dirs) {
var file, filepath, files, found, found_under, _i, _len;
if (include_dirs == null) {
include_dirs = false;
}
found = [];
files = fs.readdirSync(folderpath);
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
filepath = pn("" + folderpath + "/" + file);
if (fs.lstatSync(filepath).isDirectory()) {
if (include_dirs && filepath.match(pattern)) {
found = found.concat(filepath);
}
found_under = FsUtil.find(filepath, pattern, include_dirs);
found = found.concat(found_under);
} else {
if (filepath.match(pattern)) {
found.push(filepath);
}
}
}
return found;
};
FsUtil.ls_folders = function(folderpath) {
var file, filepath, files, found, _i, _len;
found = [];
files = fs.readdirSync(folderpath);
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
filepath = "" + folderpath + "/" + file;
if (fs.lstatSync(filepath).isDirectory()) {
found.push(filepath);
}
}
return found;
};
FsUtil.take_snapshot = function(folderpath) {
var file, filepath, files, found, type, _i, _len;
found = [];
files = fs.readdirSync(folderpath);
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
filepath = "" + folderpath + "/" + file;
if (fs.lstatSync(filepath).isDirectory()) {
type = "folder";
} else {
type = "file";
}
found.push({
type: type,
path: filepath
});
}
return found;
};
FsUtil.watch_file = function(filepath, onchange, dispatch_create) {
var _this = this;
filepath = pn(filepath);
FsUtil.unwatch_file(filepath);
if (dispatch_create) {
if (typeof onchange === "function") {
onchange({
type: "file",
path: filepath,
action: "created"
});
}
}
if (typeof onchange === "function") {
onchange({
type: "file",
path: filepath,
action: "watching"
});
}
return fs.watchFile(filepath, {
interval: 250
}, function(curr, prev) {
var ctime, mtime;
mtime = curr.mtime.valueOf() !== prev.mtime.valueOf();
ctime = curr.ctime.valueOf() !== prev.ctime.valueOf();
if (mtime || ctime) {
return typeof onchange === "function" ? onchange({
type: "file",
path: filepath,
action: "updated"
}) : void 0;
}
});
};
FsUtil.unwatch_file = function(filepath, onchange) {
FsUtil.watched[filepath] = false;
return fs.unwatchFile(filepath);
};
FsUtil.snapshots = {};
FsUtil.watchers = {};
FsUtil.watched = {};
FsUtil.watch_folder = function(folderpath, filter_regexp, onchange, dispatch_create) {
var item, on_folder_change, watchers, _i, _len, _ref;
if (FsUtil.watchers[folderpath]) {
watchers = FsUtil.watchers[folderpath];
} else {
watchers = FsUtil.watchers[folderpath] = [];
}
folderpath = pn(folderpath);
if (typeof onchange === "function") {
onchange({
type: "folder",
path: folderpath,
action: "watching"
});
}
FsUtil.snapshots[folderpath] = FsUtil.take_snapshot(folderpath);
_ref = FsUtil.snapshots[folderpath];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
item = _ref[_i];
if (item.type === "folder") {
if (dispatch_create) {
onchange({
type: item.type,
path: item.path,
action: "created"
});
}
FsUtil.watch_folder(item.path, filter_regexp, onchange, dispatch_create);
} else if (filter_regexp === null || filter_regexp.test(item.path)) {
if (dispatch_create) {
onchange({
type: item.type,
path: item.path,
action: "created"
});
}
FsUtil.watch_file(item.path, onchange);
}
}
watchers.push({
folderpath: folderpath,
filter: filter_regexp,
onchange: onchange,
dispatch_create: dispatch_create
});
if (!FsUtil.watched[folderpath]) {
FsUtil.watched[folderpath] = true;
on_folder_change = FnUtil.proxy(FsUtil._on_folder_change, folderpath);
fs.unwatchFile(folderpath);
return fs.watchFile(folderpath, {
interval: 250
}, on_folder_change);
}
};
FsUtil._on_folder_change = function(folderpath, curr, prev) {
var a, b, diff, info, item, watcher, watchers, _i, _j, _k, _len, _len1, _len2, _results;
if (!path.existsSync(folderpath)) {
return;
}
a = FsUtil.snapshots[folderpath];
b = FsUtil.snapshots[folderpath] = FsUtil.take_snapshot(folderpath);
diff = ArrayUtil.diff(a, b, "path");
if (!diff.length) {
return;
}
watchers = FsUtil.watchers[folderpath];
_results = [];
for (_i = 0, _len = diff.length; _i < _len; _i++) {
item = diff[_i];
info = item.item;
info.action = item.action;
if (info.action === "created") {
if (info.type === "file") {
_results.push((function() {
var _j, _len1, _results1;
_results1 = [];
for (_j = 0, _len1 = watchers.length; _j < _len1; _j++) {
watcher = watchers[_j];
if (watcher.filter.test(info.path)) {
if (typeof watcher.onchange === "function") {
watcher.onchange(info);
}
_results1.push(FsUtil.watch_file(info.path, watcher.onchange));
} else {
_results1.push(void 0);
}
}
return _results1;
})());
} else if (info.type === "folder") {
_results.push((function() {
var _j, _len1, _results1;
_results1 = [];
for (_j = 0, _len1 = watchers.length; _j < _len1; _j++) {
watcher = watchers[_j];
if (typeof watcher.onchange === "function") {
watcher.onchange(info);
}
_results1.push(FsUtil.watch_folder(info.path, watcher.filter, watcher.onchange, true));
}
return _results1;
})());
} else {
_results.push(void 0);
}
} else if (info.action === "deleted") {
if (info.type === "file") {
for (_j = 0, _len1 = watchers.length; _j < _len1; _j++) {
watcher = watchers[_j];
if (watcher.filter.test(info.path)) {
if (typeof watcher.onchange === "function") {
watcher.onchange(info);
}
}
}
fs.unwatchFile(info.path);
_results.push(FsUtil.watched[info.path] = false);
} else if (info.type === "folder") {
for (_k = 0, _len2 = watchers.length; _k < _len2; _k++) {
watcher = watchers[_k];
if (typeof watcher.onchange === "function") {
watcher.onchange(info);
}
}
_results.push(FsUtil.unwatch_folder(info.path));
} else {
_results.push(void 0);
}
} else {
_results.push(void 0);
}
}
return _results;
};
FsUtil.unwatch_folder = function(folderpath, onchange) {
var exists, item, list, watcher_path, _ref, _ref1, _results;
_ref = FsUtil.watchers;
for (watcher_path in _ref) {
list = _ref[watcher_path];
if (new RegExp("^" + folderpath).test(watcher_path)) {
FsUtil.watchers[watcher_path] = null;
}
}
_ref1 = FsUtil.watched;
_results = [];
for (item in _ref1) {
exists = _ref1[item];
if (exists && new RegExp("^" + folderpath).test(item)) {
FsUtil.watched[item] = false;
_results.push(fs.unwatchFile(item));
} else {
_results.push(void 0);
}
}
return _results;
};
return FsUtil;
}).call(this);
growl = require('growl');
icon_warn = '/Users/nybras/Dropbox/Workspace/serpentem/coffee-toaster/images/warning.png';
icon_error = '/Users/nybras/Dropbox/Workspace/serpentem/coffee-toaster/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) {
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) {
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, pn;
fs = require("fs");
path = require('path');
pn = path.normalize;
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() {
var baseclass, item, klass, repl, requirements, rgx, rgx_ext, _i, _j, _len, _len1, _ref, _ref1, _results;
this.raw = fs.readFileSync(this.realpath, "utf-8");
this.dependencies_collapsed = [];
this.baseclasses = [];
this.filepath = this.realpath.replace(this.folderpath, "").substr(1);
if (this.alias != null) {
this.filepath = pn("" + this.alias + "/" + this.filepath);
}
this.filename = /[\w-]+\.[\w-]+/.exec(this.filepath)[0];
this.filefolder = this.filepath.replace("/" + this.filename, "") + "/";
this.namespace = "";
if (this.filepath.indexOf("/") === -1) {
this.filefolder = "";
}
this.namespace = this.filefolder.replace(/\//g, ".").slice(0, -1);
rgx = /^(\s*)(class)+\s(\w+)(\s+(extends)\s+([\w.]+))?/gm;
rgx_ext = /(^|=\s*)(class)\s(\w+)\s(extends)\s(\\w+)\s*$/gm;
if (this.raw.match(rgx) != null) {
this.classpath = this.classname;
if (this.namespace !== "" && this.builder.packaging) {
repl = "$1$2 __t('" + this.namespace + "').$3$4";
this.raw = this.raw.replace(rgx, repl);
this.classpath = "" + this.namespace + "." + this.classname;
}
this.classname = this.raw.match(rgx)[3];
_ref1 = (_ref = this.raw.match(rgx_ext)) != null ? _ref : [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
klass = _ref1[_i];
baseclass = klass.match(rgx_ext)[5];
this.baseclasses.push(baseclass);
}
}
if (/(#<<\s)(.*)/g.test(this.raw)) {
requirements = this.raw.match(/(#<<\s)(.*)/g);
_results = [];
for (_j = 0, _len1 = requirements.length; _j < _len1; _j++) {
item = requirements[_j];
item = /(#<<\s)(.*)/.exec(item)[2];
item = item.replace(/\s/g, "");
item = [].concat(item.split(","));
_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(-1) !== "*") {
this.dependencies.push("" + 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 dependency management 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 + ")";
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').boolean('c').describe('c', "Compile the entire project, without watching it.").alias('d', 'debug').boolean('d')["default"]('d', false).describe('d', 'Debug mode (compile js files individually)').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, FsUtil, Script, StringUtil, cs, fs, missing, path, uglify, uglify_parser;
fs = require('fs');
path = require('path');
cs = require("coffee-script");
uglify = require("uglify-js").uglify;
uglify_parser = require("uglify-js").parser;
Script = toaster.core.Script;
FnUtil = toaster.utils.FnUtil;
FsUtil = toaster.utils.FsUtil;
ArrayUtil = toaster.utils.ArrayUtil;
StringUtil = toaster.utils.StringUtil;
Builder.prototype._toaster_helper = "__t = ( ns )->\n curr = null\n parts = [].concat = ns.split \".\"\n for part, index in parts\n if curr == null\n curr = eval part\n continue\n else\n unless curr[ part ]?\n curr = curr[ part ] = {}\n else\n curr = curr[ part ]\n curr";
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.build_namespaces_declaration = __bind(this.build_namespaces_declaration, 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, _ref, _results;
this.files = this.config.files;
_ref = this.config.src_folders;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
folder = _ref[_i];
result = FsUtil.find(folder.path, /.coffee/);
fpath = folder.path;
falias = folder.alias;
_results.push((function() {
var _j, _k, _len1, _len2, _ref1, _results1;
_results1 = [];
for (_j = 0, _len1 = result.length; _j < _len1; _j++) {
file = result[_j];
include = true;
_ref1 = this.exclude;
for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
item = _ref1[_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.build = function(header_code, footer_code) {
var ast, contents, f, files, helper, i, include, namespaces, now, tmpl, vendors, _i, _len;
if (header_code == null) {
header_code = "";
}
if (footer_code == null) {
footer_code = "";
}
namespaces = this.build_namespaces();
if (this.packaging) {
helper = cs.compile(this._toaster_helper, {
bare: true
});
} else {
helper = "";
}
vendors = this.merge_vendors();
contents = [];
if (vendors !== "") {
contents.push(vendors);
}
if (this.packaging) {
contents.push(helper);
}
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();
now = "" + (now.getHours()) + ":" + (now.getMinutes()) + ":" + (now.getSeconds());
log(("" + 'Compiled'.bold + " " + this.release + " @ " + now).green);
if (this.cli.argv.d && (this.debug != null)) {
files = this.compile_for_debug();
for (i = _i = 0, _len = files.length; _i < _len; i = ++_i) {
f = files[i];
include = "" + this.httpfolder + "/toaster/" + f;
tmpl = this._include_tmpl.replace("%SRC%", include);
files[i] = tmpl;
}
contents = [];
if (vendors !== "") {
contents.push(vendors);
}
if (this.packaging) {
contents.push(helper);
}
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);
now = new Date();
now = "" + (now.getHours()) + ":" + (now.getMinutes()) + ":" + (now.getSeconds());
return log(("" + 'Compiled'.bold + " " + this.debug + " @ " + now).green);
}
};
Builder.prototype.build_namespaces = function(after_build_namespaces) {
var folder, name, namespaces, subfolder, subfolders, _i, _j, _len, _len1, _ref;
namespaces = "";
_ref = this.config.src_folders;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
folder = _ref[_i];
if (folder.alias != null) {
namespaces += this.build_namespaces_declaration(folder.alias);
} else {
subfolders = FsUtil.ls_folders(folder.path);
for (_j = 0, _len1 = subfolders.length; _j < _len1; _j++) {
subfolder = subfolders[_j];
name = subfolder.match(/[^\/]+$/m);
namespaces += this.build_namespaces_declaration(name);
}
}
}
return namespaces;
};
Builder.prototype.build_namespaces_declaration = function(name) {
var declaration;
declaration = "";
if (this.packaging) {
declaration += "var " + name + " = ";
}
if (this.expose != null) {
declaration += "" + this.expose + "." + name + " = ";
}
if (declaration.length) {
declaration += "{};\n";
}
return declaration;
};
Builder.prototype.watch = function() {
var src, _i, _len, _ref, _results,
_this = this;
_ref = this.config.src_folders;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
src = _ref[_i];
_results.push(FsUtil.watch_folder(src.path, /.coffee$/, FnUtil.proxy(function(src, info) {
var falias, file, fpath, ipath, msg, relative_path, s, type;
if (info.action === "watching") {
return;
}
if (info.type === "folder" && info.action === "created") {
return;
}
ipath = info.path;
fpath = src.path;
falias = src.alias || "";
type = StringUtil.titleize(info.type);
relative_path = info.path.replace("" + fpath + "/", "" + falias + "/");
if (relative_path.substr(0, 1) === "/") {
relative_path = relative_path.substr(1);
}
switch (info.action) {
case "created":
if (info.type === "file") {
s = new Script(_this, fpath, ipath, falias, _this.cli);
_this.files.push(s);
}
msg = "" + ('New ' + info.type + ' created').bold.cyan;
log("" + msg + " " + info.path.green);
break;
case "deleted":
file = ArrayUtil.find(_this.files, relative_path, "filepath");
if (file === null) {
return;
}
_this.files.splice(file.index, 1);
msg = "" + (type + ' deleted, stop watching').bold.red;
log("" + msg + " " + info.path.red);
break;
case "updated":
file = ArrayUtil.find(_this.files, relative_path, "filepath");
file.item.getinfo();
msg = "" + (type + ' changed').bold.cyan;
log("" + msg + " " + info.path.cyan);
}
_this.build();
return typeof after_watch === "function" ? after_watch() : void 0;
}, src)));
}
return _results;
};
Builder.prototype.compile = function() {
var file, msg, output, _i, _j, _len, _len1, _ref, _ref1;
_ref = this.files;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
file = _ref[_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;
}
}
_ref1 = this.files;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
file = _ref1[_j];
file.expand_dependencies();
}
this.reorder();
output = ((function() {
var _k, _len2, _ref2, _results;
_ref2 = this.files;
_results = [];
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
file = _ref2[_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, folder_path, index, msg, relative_path, release_path, _i, _len, _ref;
release_path = this.release.split("/").slice(0, -1).join("/");
release_path += "/toaster";
if (path.existsSync(release_path)) {
FsUtil.rmdir_rf(release_path);
}
FsUtil.mkdir_p(release_path);
files = [];
_ref = this.files;
for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
file = _ref[index];
relative_path = file.filepath.replace(".coffee", ".js");
absolute_path = "" + release_path + "/" + relative_path;
folder_path = absolute_path.split('/').slice(0, -1).join("/");
if (!path.existsSync(folder_path)) {
FsUtil.mkdir_p(folder_path);
}
try {
fs.writeFileSync(absolute_path, cs.compile(file.raw, {
bare: this.bare
}));
} catch (err) {
msg = err.message.replace('"', '\\"');
console.log("MSG:::: " + msg);
msg = ("" + msg.white + " at file: ") + ("" + file.filepath).bold.red;
error(msg);
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, _ref, _ref1, _results;
if (cycling == null) {
cycling = false;
}
if (cycling === false) {
this.missing = {};
}
_ref = this.files;
_results = [];
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
file = _ref[i];
if (!file.dependencies.length && !file.baseclasses.length) {
continue;
}
_ref1 = file.dependencies;
for (index = _j = 0, _len1 = _ref1.length; _j < _len1; index = ++_j) {
filepath = _ref1[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, _ref2, _results1;
_ref2 = file.baseclasses;
_results1 = [];
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
bc = _ref2[_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, _ref;
buffer = [];
_ref = this.vendors;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
vendor = _ref[_i];
if (path.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, pn;
__extends(Config, _super);
path = require("path");
pn = path.normalize;
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(folderpath) {
var q1, q2, q3,
_this = this;
if ((folderpath != null) && folderpath !== true) {
this.basepath = "" + this.basepath + "/" + folderpath;
}
log("" + 'Let\'s toast this sly little project! :)'.grey.bold);
log(". With this as your basepath: " + this.basepath.cyan);
log(". Please, tell me:");
q1 = "\tWhere's your src folder? (i.e. src): ";
q2 = "\tWhere do you want your release file? (i.e. www/js/app.js) : ";
q3 = "\tStarting 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 = pn("" + 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);
buffer = buffer.replace("%release%", release);
buffer = buffer.replace("%debug%", debug);
buffer = buffer.replace("%httpfolder%", httpfolder);
if (path.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, path, pn;
__extends(Project, _super);
path = require("path");
pn = path.normalize;
fs = require("fs");
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 q1, q2, q3, target,
_this = this;
if (!folderpath || folderpath === true) {
return error("You need to inform a target path!\n" + "\ttoaster -n myawesomeapp".green);
}
if (folderpath.substr(0, 1) !== "/") {
target = "" + this.basepath + "/" + folderpath;
} else {
target = folderpath;
}
if ((name != null) && (src != null) && (release != null)) {
return this.scaffold(target, 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(target, $src, $release, $httpfolder);
return process.exit();
});
});
});
};
Project.prototype.scaffold = function(target, src, release, httpfolder) {
var releasedir, releasefile, srcdir, vendorsdir;
srcdir = pn("" + target + "/" + src);
vendorsdir = pn("" + target + "/vendors");
releasefile = pn("" + target + "/" + release);
releasedir = releasefile.split("/").slice(0, -1).join("/");
if (FsUtil.mkdir_p(target)) {
log("" + 'Created'.green.bold + " " + target);
}
if (FsUtil.mkdir_p(srcdir)) {
log("" + 'Created'.green.bold + " " + srcdir);
}
if (FsUtil.mkdir_p(vendorsdir)) {
log("" + 'Created'.green.bold + " " + vendorsdir);
}
if (FsUtil.mkdir_p(releasedir)) {
log("" + 'Created'.green.bold + " " + releasedir);
}
srcdir = srcdir.replace(target, "").substr(1);
releasefile = releasefile.replace(target, "").substr(1);
return new toaster.generators.Config(target).write(srcdir, releasefile, httpfolder);
};
return Project;
})(toaster.generators.Question);
__t('toaster').Toast = (function() {
var colors, cs, exec, fs, path, pn;
fs = require("fs");
path = require("path");
pn = path.normalize;
exec = (require("child_process")).exec;
colors = require('colors');
cs = require("coffee-script");
Toast.prototype.builders = [];
function Toast(toaster) {
var code, config, config_file, contents, filepath, fix_scope, item, _i, _len, _ref;
this.toaster = toaster;
this.toast = __bind(this.toast, this);
this.basepath = this.toaster.basepath;
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 || pn("" + this.basepath + "/toaster.coffee");
if (path.existsSync(filepath)) {
contents = fs.readFileSync(filepath, "utf-8");
fix_scope = /(^[\s\t]?)(toast)+(\()/mg;
code = cs.compile(contents, {
bare: 1
});
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, config, folder, item, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8;
if (params == null) {
params = {};
}
if (srcpath instanceof Object) {
params = srcpath;
} else if (srcpath.substr(0, 1) !== "/") {
srcpath = "" + this.toaster.basepath + "/" + srcpath;
}
debug = params.debug ? pn("" + this.basepath + "/" + params.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: pn("" + this.basepath + "/" + params.release),
debug: debug
};
if (!(srcpath instanceof Object)) {
config.src_folders.push({
path: srcpath,
alias: params.alias || null
});
}
if (params.folders != null) {
_ref7 = params.folders;
for (folder in _ref7) {
alias = _ref7[folder];
if (folder.substr(0, 1 === !"/")) {
folder = pn("" + this.basepath + "/" + folder + "/");
}
config.src_folders.push({
path: folder,
alias: alias
});
}
}
_ref8 = config.src_folders;
for (_i = 0, _len = _ref8.length; _i < _len; _i++) {
item = _ref8[_i];
if (!path.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" + pn("" + this.basepath + "/toaster.coffee").yellow);
return process.exit();
}
}
return this.builders.push(new toaster.core.Builder(this.toaster, this.toaster.cli, config));
};
return Toast;
})();
exports.run = function() {
return new Toaster;
};
exports.toaster = toaster;
exports.Toaster = Toaster = (function() {
var colors, exec, fs, path, pn;
fs = require("fs");
path = require("path");
pn = path.normalize;
exec = (require("child_process")).exec;
colors = require('colors');
function Toaster(basedir, options, skip_initial_build) {
var config, contents, filepath, k, schema, v;
if (options == null) {
options = null;
}
if (skip_initial_build == null) {
skip_initial_build = false;
}
this.basepath = basedir || path.resolve(".");
this.cli = new toaster.Cli(options);
if (options != null) {
for (k in options) {
v = options[k];
this.cli.argv[k] = v;
}
}
if (this.cli.argv.v) {
filepath = pn(__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(this.cli.argv.i);
} else if (this.cli.argv.w || this.cli.argv.c) {
config = options && options.config ? options.config : null;
this.toast = new toaster.Toast(this);
if (!skip