coffee-toaster
Version:
Minimalist manager and build system for CoffeeScript, an alternative for AMD's or CJS's OOP patterns, but with similar results. Made for those who dare to use class definitions in CoffeeScript while being able to easily inherit from external files. Powered with imports directives that use wildcards facilities, exposed scopes and excluded files filter options. The system can even use folders-as-namespaces to help you avoid naming collisions in architecture.
1,531 lines (1,383 loc) • 52.9 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, 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, 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 (fs.existsSync(filepath)) {
contents = fs.readFileSync(filepath, "utf-8");
try {
code = cs.compile(contents, {
bare: 1
});
fix_scope = /(^[\s\t]?)(toast)+(\()/mg;
code = code.replace(fix_scope, "$1this.$2$3");
eval(code);
} catch (err) {
error(err.message + " at 'toaster.coffee' config file.");
}
} 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, debug, folder, i, item, v, _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 (srcpath.substr(0, 1) !== "/") {
srcpath = "" + this.toaster.basepath + "/" + srcpath;
}
if (params.release === null) {
error('Release path not informed in config.');
return process.exit();
} else {
path = ((params.release.split('/')).slice(0, -1)).join('/');
if (!fs.existsSync("" + this.basepath + "/" + path)) {
error("Release folder does not exist:\n\t" + path.yellow);
return process.exit();
}
}
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
};
_ref7 = config.vendors;
for (i = _i = 0, _len = _ref7.length; _i < _len; i = ++_i) {
v = _ref7[i];
if ((v.substr(0, 1)) !== "/") {
config.vendors[i] = pn("" + this.basepath + "/" + v);
}
}
if (!(srcpath instanceof Object)) {
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 (folder.substr(0, 1 === !"/")) {
folder = pn("" + 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" + 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;
})();
__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 = fs.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.cp_dir = function(from, to) {
var dir, file_from, file_to, files, _i, _len, _ref, _results;
if ((from.slice(-1)) === "/") {
from = from.slice(0, -1);
}
if ((to.slice(-1)) === "/") {
to = to.slice(0, -1);
}
_ref = (files = this.find(from, /.*/, false));
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
file_from = _ref[_i];
file_to = file_from.replace(from, to);
dir = ((file_to.split('/')).slice(0, -1)).join('/');
if (!fs.existsSync(dir)) {
this.mkdir_p(dir);
}
_results.push(fs.writeFileSync(file_to, fs.readFileSync(file_from, "utf-8")));
}
return _results;
};
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, {
persistent: true,
interval: 30
}, function(curr, prev) {
var ctime, mtime;
mtime = curr.mtime.valueOf() !== prev.mtime.valueOf();
ctime = curr.ctime.valueOf() !== prev.ctime.valueOf();
if (curr.nlink === 0) {
return typeof onchange === "function" ? onchange({
type: "file",
path: filepath,
action: "deleted"
}) : void 0;
} else 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, {
persistent: true,
interval: 30
}, on_folder_change);
}
};
FsUtil._on_folder_change = function(folderpath, curr, prev) {
var a, b, diff, info, item, watcher, watchers, _i, _j, _len, _len1, _results;
if (!fs.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" && info.type === "folder") {
for (_j = 0, _len1 = watchers.length; _j < _len1; _j++) {
watcher = watchers[_j];
if (typeof watcher.onchange === "function") {
watcher.onchange(info);
}
}
_results.push(FsUtil.unwatch_folder(info.path));
} 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 = __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) {
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(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 = pn("" + this.alias + "/" + this.filepath);
}
this.filepath = this.filepath.replace(/^[\/]+/, "");
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, ".").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, "");
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 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 + ")";
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('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, _ref;
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;
_ref = toaster.utils, FnUtil = _ref.FnUtil, FsUtil = _ref.FsUtil, ArrayUtil = _ref.ArrayUtil, StringUtil = _ref.StringUtil;
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 = __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 = FsUtil.find(folder.path, /.coffee/);
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.build = function(header_code, footer_code) {
var ast, contents, f, files, i, include, namespaces, now, tmpl, vendors, _i, _len;
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)) {
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(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);
return log(("[" + now + "] " + 'Compiled'.bold + " " + this.debug).green);
}
};
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, _i, _len, _results;
folders = FsUtil.ls_folders(folderpath);
_results = [];
for (_i = 0, _len = folders.length; _i < _len; _i++) {
folder = folders[_i];
_results.push(this.build_ns_tree((tree[folder.match(/[^\/]+$/m)] = {}), folder));
}
return _results;
};
Builder.prototype.watch = function() {
var src, _i, _len, _ref1, _results,
_this = this;
_ref1 = this.config.src_folders;
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
src = _ref1[_i];
_results.push(FsUtil.watch_folder(src.path, /.coffee$/, FnUtil.proxy(function(src, info) {
var falias, file, fpath, include, ipath, item, msg, now, relative_path, s, type, _j, _len1, _ref2;
if (info.action === "watching") {
return;
}
if (info.type === "folder" && info.action === "created") {
return;
}
ipath = info.path;
fpath = src.path;
falias = src.alias || "";
include = true;
_ref2 = _this.exclude;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
item = _ref2[_j];
include &= !(new RegExp(item).test(ipath));
}
if (!include) {
return;
}
type = StringUtil.titleize(info.type);
relative_path = info.path.replace("" + fpath + "/", "" + falias + "/");
if (relative_path.substr(0, 1) === "/") {
relative_path = relative_path.substr(1);
}
now = (("" + (new Date)).match(/[0-9]{2}\:[0-9]{2}\:[0-9]{2}/))[0];
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;
log(("[" + now + "] " + 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;
log(("[" + now + "] " + msg + " " + info.path).red);
break;
case "updated":
file = ArrayUtil.find(_this.files, relative_path, "filepath");
file.item.getinfo();
msg = "" + (type + ' changed').bold;
log(("[" + now + "] " + msg + " " + info.path).cyan);
}
if (_this.toaster.before_build === null || _this.toaster.before_build()) {
_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, _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, folder_path, index, relative_path, release_path, _i, _len, _ref1;
release_path = this.debug.split("/").slice(0, -1).join("/");
release_path += "/toaster";
if (fs.existsSync(release_path)) {
FsUtil.rmdir_rf(release_path);
}
FsUtil.mkdir_p(release_path);
files = [];
_ref1 = this.files;
for (index = _i = 0, _len = _ref1.length; _i < _len; index = ++_i) {
file = _ref1[index];
relative_path = file.filepath.replace(".coffee", ".js");
absolute_path = "" + release_path + "/" + relative_path;
folder_path = absolute_path.split('/').slice(0, -1).join("/");
if (!fs.existsSync(folder_path)) {
FsUtil.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, 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() {
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 = 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 (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, 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 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 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);
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 = _