oj
Version:
A unified templating language for the people. Thirsty people.
1,499 lines (1,335 loc) • 46.3 kB
JavaScript
// Generated by CoffeeScript 1.6.2
(function() {
var basenameForExtensions, coffee, commonPath, compileDir, compileFile, compileJS, compilePath, csso, error, fileIsOutdated, findFile, fullPaths, isAppModule, isDirectory, isFile, isHiddenFile, isNodeModule, isOJDir, isOJFile, isOJPage, isRelativeModule, isUnsupportedNodeModule, isWatchFile, isWatched, jsdom, ls, lsOJ, lsWatch, m, mkdirp, nodeModulePaths, nodeModulesLinkMap, oj, pass, readFileSync, relativePathWithEscaping, resolveLink, spaces, stripBOM, success, tabs, triggerWatched, trimArgList, uglifyjs, unwatchAll, unwatchDir, url, verbose, verbosity, wait, watchCache, watchDir, watchFile, watchParents, wrapCSMessage, wrapJS, wrapJSMessage, _, _buildFileCache, _buildNativeCache, _buildNativeCacheFromModuleList, _buildRequireCache, _clearRequireCacheRecord, _createHook, _escapeSingleQuotes, _first, _getRequiresInSource, _hookRequire, _i, _insertAt, _len, _length, _nativeModuleCode, _nodeModuleUnsupported, _nodeModulesSupported, _ojModuleCode, _optionsForPath, _outputCombinedHtml, _outputCss, _outputDataToFileOrCallback, _outputFile, _outputHtml, _outputJs, _ref, _rememberModule, _rememberModuleDependencies, _requireCache, _requireCacheToHtml, _requireCacheToJS, _restoreRequireCache, _saveRequireCache, _startsWith, _timeStampFromStartTime, _trim, _unhookRequire;
_ref = ['path', 'fs', 'vm'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
m = _ref[_i];
global[m] = require(m);
}
_ = require('underscore');
coffee = require('coffee-script');
url = require('url');
mkdirp = require('mkdirp');
csso = require('csso');
uglifyjs = require('uglify-js');
jsdom = (require('jsdom')).jsdom;
global.jQuery = global.$ = require('jquery');
global.document = jsdom("<html><head></head><body></body></html>");
global.window = document.createWindow();
oj = require('../oj');
oj.isClient = false;
module.exports = oj;
oj.$ = global.$;
oj.codes = {
reset: '\u001b[0m',
black: '\u001b[30m',
red: '\u001b[31m',
green: '\u001b[32m',
yellow: '\u001b[33m',
blue: '\u001b[34m',
magenta: '\u001b[35m',
cyan: '\u001b[36m',
gray: '\u001b[37m'
};
if (require.extensions) {
coffee = require('coffee-script');
stripBOM = function(c) {
if (c.charCodeAt(0) === 0xFEFF) {
return c.slice(1);
} else {
return c;
}
};
wrapJS = function(code) {
return "(function(){with(oj.sandbox){" + code + "}}).call(this);";
};
wrapCSMessage = function(message, filepath) {
var _ref1, _ref2;
return "" + ((_ref1 = oj.codes) != null ? _ref1.red : void 0) + "coffee-script error in " + filepath + ": " + message + ((_ref2 = oj.codes) != null ? _ref2.reset : void 0);
};
wrapJSMessage = function(message, filepath) {
var _ref1, _ref2;
return "" + ((_ref1 = oj.codes) != null ? _ref1.red : void 0) + "javascript error in " + filepath + ": " + message + ((_ref2 = oj.codes) != null ? _ref2.reset : void 0);
};
compileJS = function(module, code, filepath) {
code = wrapJS(code);
global.oj = oj;
module._compile(code, filepath);
return delete global.oj;
};
require.extensions['.oj'] = function(module, filepath) {
var code, eJS;
code = stripBOM(fs.readFileSync(filepath, 'utf8'));
try {
return compileJS(module, code, filepath);
} catch (_error) {
eJS = _error;
eJS.message = wrapJSMessage(eJS.message, filepath);
throw eJS;
}
};
require.extensions['.ojc'] = function(module, filepath) {
var code, eCoffee, eJS;
code = stripBOM(fs.readFileSync(filepath, 'utf8'));
try {
code = coffee.compile(code, {
bare: true
});
} catch (_error) {
eCoffee = _error;
eCoffee.message = wrapCSMessage(eCoffee.message, filepath);
throw eCoffee;
}
try {
return compileJS(module, code, filepath);
} catch (_error) {
eJS = _error;
eJS.message = wrapJSMessage(eJS.message, filepath);
throw eJS;
}
};
}
oj.watch = function(filesOrDirectories, options) {
options = _.extend({}, options, {
args: filesOrDirectories,
watch: true,
write: true
});
return oj.command(options);
};
oj.build = function(filesOrDirectories, options) {
options = _.extend({}, options, {
args: filesOrDirectories,
watch: false,
write: true
});
return oj.command(options);
};
verbosity = null;
oj.command = function(options) {
var fullPath, _j, _len1, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9;
if (options == null) {
options = {};
}
verbosity = options.verbose || 1;
if ((_ref1 = options.test) == null) {
options.test = false;
}
if ((_ref2 = options.write) == null) {
options.write = !options.test;
}
if ((_ref3 = options.watch) == null) {
options.watch = false;
}
if ((_ref4 = options.all) == null) {
options.all = false;
}
if ((_ref5 = options.recurse) == null) {
options.recurse = true;
}
if ((_ref6 = options.include) == null) {
options.include = [];
}
if ((_ref7 = options.exclude) == null) {
options.exclude = [];
}
if ((_ref8 = options.output) == null) {
options.output = './public';
}
options.output = (path.resolve(process.cwd(), options.output)) + '/';
if (!((_.isArray(options.args)) && options.args.length > 0)) {
throw new Error('oj: no args found');
}
options.args = fullPaths(options.args, process.cwd());
_ref9 = options.args;
for (_j = 0, _len1 = _ref9.length; _j < _len1; _j++) {
fullPath = _ref9[_j];
compilePath(fullPath, _optionsForPath(fullPath, options), function(err, results) {
if (options.test) {
return console.log(results);
}
});
}
};
_optionsForPath = function(fullPath, options) {
var userSpecifiedInclude;
options = _.clone(options);
userSpecifiedInclude = (options.modules != null) || (options.html != null) || (options.css != null) || (options.js != null);
if (options.modulesDir) {
options.modulesDir = (path.resolve(fullPath, options.modulesDir)) + '/';
}
if (options.cssDir) {
options.cssDir = (path.resolve(fullPath, options.cssDir)) + '/';
}
if (!userSpecifiedInclude && fs.existsSync(options.modulesDir)) {
options.modules = false;
options.js = options.css = options.html = true;
} else if (options.all || !userSpecifiedInclude) {
options.modules = options.js = options.css = options.html = true;
}
return options;
};
compilePath = function(fullPath, options, cb) {
var includeDir;
if (options == null) {
options = {};
}
if (cb == null) {
cb = function() {};
}
if (isDirectory(fullPath)) {
return compileDir(fullPath, options, cb);
}
includeDir = path.dirname(fullPath);
return compileFile(fullPath, includeDir, options, cb);
};
compileDir = function(dirPath, options, cb) {
var _ref1;
if (options == null) {
options = {};
}
if (cb == null) {
cb = function() {};
}
options = _.clone(options);
if (!options.modulesDir) {
options.modulesDir = (path.resolve(dirPath, (_ref1 = options.modulesDir) != null ? _ref1 : './modules')) + '/';
}
lsWatch(dirPath, options, function(err, files, dirs) {
var d, f, _cb, _j, _k, _len1, _len2;
if (options.watch) {
for (_j = 0, _len1 = dirs.length; _j < _len1; _j++) {
d = dirs[_j];
watchDir(d, dirPath, options);
}
}
_cb = _.after(files.length, cb);
for (_k = 0, _len2 = files.length; _k < _len2; _k++) {
f = files[_k];
if (isOJPage(f)) {
compileFile(f, dirPath, options, _cb);
} else if (options.watch) {
watchFile(f, dirPath, options);
_cb();
}
}
});
};
nodeModulePaths = function(from) {
var dir, joiner, parts, paths, splitRe, tip, _j, _ref1;
from = path.resolve(from);
splitRe = (process.platform === 'win32' ? /[\/\\]/ : /\//);
joiner = (process.platform === 'win32' ? '\\' : '/');
paths = [];
parts = from.split(splitRe);
for (tip = _j = _ref1 = parts.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; tip = _ref1 <= 0 ? ++_j : --_j) {
if (parts[tip] === 'node_modules') {
continue;
}
dir = parts.slice(0, tip + 1).concat('node_modules').join(joiner);
paths.push(dir);
}
return paths;
};
resolveLink = function(linkPath, out) {
var e, newPath;
try {
newPath = fs.readlinkSync(linkPath);
return resolveLink(newPath, newPath);
} catch (_error) {
e = _error;
}
return out;
};
nodeModulesLinkMap = function(fileDir) {
var dir, dirs, e, linkPath, moduleName, modulePath, modules, out, _j, _k, _len1, _len2;
dirs = nodeModulePaths(fileDir);
out = {};
for (_j = 0, _len1 = dirs.length; _j < _len1; _j++) {
dir = dirs[_j];
try {
modules = fs.readdirSync(dir);
for (_k = 0, _len2 = modules.length; _k < _len2; _k++) {
moduleName = modules[_k];
modulePath = path.join(dir, moduleName);
linkPath = resolveLink(modulePath);
if (linkPath != null) {
out[linkPath + '/'] = modulePath + '/';
}
}
} catch (_error) {
e = _error;
}
}
return out;
};
basenameForExtensions = function(p, arrayOfExt) {
var ext, out, _j, _len1;
if (arrayOfExt == null) {
arrayOfExt = [];
}
out = path.basename(p);
for (_j = 0, _len1 = arrayOfExt.length; _j < _len1; _j++) {
ext = arrayOfExt[_j];
out = path.basename(out, ext);
}
return out;
};
compileFile = function(filePath, includeDir, options, cb) {
var cache, compileOptions, cssOption, eCompile, eRequire, ex, extOut, fileBaseName, fileDir, fileOut, hookCache, hookOriginalCache, htmlOption, includedModules, isMinify, moduleLinkMap, moduleParents, modules, ojml, outputDir, results, rootDir, startTime, subDir, _j, _k, _len1, _len2, _ref1, _ref2, _ref3;
if (options == null) {
options = {};
}
if (cb == null) {
cb = function() {};
}
options = _.clone(options);
startTime = process.hrtime();
_clearRequireCacheRecord('underscore');
if ((_ref1 = options.exclude) == null) {
options.exclude = [];
}
if (!isFile(filePath)) {
throw new Error('oj: file not found');
}
isMinify = (_ref2 = options.minify) != null ? _ref2 : false;
includedModules = options.include || [];
includedModules = includedModules.concat(['oj', 'jquery']);
rootDir = options.root || path.dirname(filePath);
fileDir = path.dirname(filePath);
if (options.modulesDir && _startsWith(filePath, options.modulesDir)) {
options.modules = true;
options.css = false;
options.html = false;
options.js = false;
} else if (options.cssDir && _startsWith(filePath, options.cssDir)) {
options.modules = false;
options.css = true;
options.html = false;
options.js = false;
}
if (!isDirectory(rootDir)) {
throw new Error('oj: root is not a directory');
}
if (options.watch) {
watchFile(filePath, includeDir, options);
}
verbose(2, "compiling " + filePath);
cache = {
modules: {},
files: {},
"native": {}
};
moduleLinkMap = nodeModulesLinkMap(fileDir);
modules = {};
moduleParents = {};
hookCache = {};
hookOriginalCache = {};
_hookRequire(modules, moduleLinkMap, hookCache, hookOriginalCache);
_saveRequireCache();
if (_.isArray(options.exclude)) {
_ref3 = options.exclude;
for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {
ex = _ref3[_j];
verbose(3, "excluding " + ex);
}
includedModules = _.difference(includedModules, options.exclude);
}
try {
for (_k = 0, _len2 = includedModules.length; _k < _len2; _k++) {
m = includedModules[_k];
if (isNodeModule(m)) {
_buildNativeCacheFromModuleList(cache["native"], [m], isMinify);
} else {
verbose(3, "including " + m);
require(m);
}
}
ojml = require(filePath);
} catch (_error) {
eRequire = _error;
verbose(1, eRequire.message);
_restoreRequireCache();
_unhookRequire(modules, hookCache, hookOriginalCache);
return;
}
_restoreRequireCache();
_unhookRequire(modules, hookCache, hookOriginalCache);
_rememberModuleDependencies(modules);
cssOption = !!options.css;
htmlOption = !!options.html;
compileOptions = {
minify: isMinify,
html: htmlOption,
cssMap: cssOption,
css: cssOption,
dom: false,
data: options.data
};
try {
results = oj.compile(compileOptions, ojml);
} catch (_error) {
eCompile = _error;
error("runtime error in " + filePath + ": " + eCompile.message);
return;
}
verbose(3, "caching " + filePath + " (" + (_length(modules)) + " files)");
cache = _buildRequireCache(modules, cache, isMinify);
fileBaseName = basenameForExtensions(filePath, ['.oj', '.ojc', 'ojlc']);
outputDir = options.output || process.cwd();
fileDir = path.dirname(filePath);
subDir = path.relative(includeDir, fileDir);
extOut = '.html';
if (options.css && !(options.html || options.js || options.modules)) {
extOut = '.css';
} else if ((options.js || options.modules) && !(options.html || options.css)) {
extOut = '.js';
}
fileOut = path.join(outputDir, subDir, fileBaseName + extOut);
options.info = _.extend({}, {
includeDir: includeDir,
startTime: startTime,
results: results,
cache: cache,
filePath: filePath,
fileDir: fileDir,
fileBaseName: fileBaseName,
outputDir: outputDir,
subDir: subDir,
extOut: extOut,
fileOut: fileOut,
isMinify: isMinify
});
_outputFile(options, cb);
};
_outputFile = function(options, cb) {
if (options.html && !(options.css || options.js || options.modules)) {
return _outputHtml(options, cb);
} else if (options.css && !(options.html || options.js || options.modules)) {
return _outputCss(options, cb);
} else if ((options.js || options.modules) && !(options.html || options.css)) {
return _outputJs(options, cb);
} else {
return _outputCombinedHtml(options, cb);
}
};
_outputCombinedHtml = function(options, cb) {
var cache, cacheLength, cssMap, fileOut, filePath, html, info, mediaMap, plugin, results, scriptHtml, scriptIndex, styleHTML, styleIndex, _ref1, _ref2;
info = options.info;
results = info.results;
filePath = info.filePath;
fileOut = info.fileOut;
html = results.html;
cssMap = results.cssMap;
cache = info.cache;
cacheLength = _length(cache.files) + _length(cache.modules) + _length(cache["native"]);
verbose(3, "serializing " + filePath + " (" + cacheLength + " files)");
scriptHtml = _requireCacheToHtml(cache, filePath, (_ref1 = options.minify) != null ? _ref1 : false, options);
if (!results.tags.html) {
error("validation error " + filePath + ": <html> tag is missing");
return;
} else if (!results.tags.head) {
error("validation error " + filePath + ": <head> tag is missing");
return;
} else if (!results.tags.body) {
error("validation error " + filePath + ": <body> tag is missing");
return;
}
scriptIndex = html.lastIndexOf('</body>');
html = _insertAt(html, scriptIndex, scriptHtml);
styleIndex = html.indexOf('</head>');
styleHTML = '';
_ref2 = results.cssMap;
for (plugin in _ref2) {
mediaMap = _ref2[plugin];
styleHTML += oj._styleTagFromMediaObject(plugin, mediaMap, options);
}
html = _insertAt(html, styleIndex, styleHTML);
return _outputDataToFileOrCallback(html, options, cb);
};
_outputCss = function(options, cb) {
return _outputDataToFileOrCallback(options.info.results.css, options, cb);
};
_outputHtml = function(options, cb) {
return _outputDataToFileOrCallback(options.info.results.html, options, cb);
};
_outputJs = function(options, cb) {
var info, js;
info = options.info;
js = _requireCacheToJS(info.cache, info.filePath, info.isMinify, options);
return _outputDataToFileOrCallback(js, options, cb);
};
_outputDataToFileOrCallback = function(data, options, cb) {
var dirOut, fileOut, filePath, info, timeStamp;
info = options.info;
fileOut = info.fileOut;
filePath = info.filePath;
fileOut = info.fileOut;
dirOut = path.dirname(fileOut);
if (mkdirp.sync(dirOut)) {
verbose(3, "mkdir " + dirOut);
}
timeStamp = _timeStampFromStartTime(info.startTime);
if (options.write) {
return fs.writeFile(fileOut, data, function(err) {
if (err) {
error("file writing error " + filePath + ": " + err);
return;
}
verbose(1, "compiled " + fileOut + timeStamp, 'cyan');
cb(null, data);
});
} else {
verbose(1, "compiled " + fileOut + timeStamp, 'cyan');
return cb(null, data);
}
};
_timeStampFromStartTime = function(startTime) {
var deltaTime, timeStamp;
deltaTime = process.hrtime(startTime);
return timeStamp = " (" + (deltaTime[0] + Math.round(10000 * deltaTime[1] / 1000000000) / 10000) + " sec)";
};
watchCache = {};
isWatched = function(fullPath) {
return watchCache[fullPath] != null;
};
triggerWatched = function(fullPath) {
var _ref1, _ref2;
return (_ref1 = watchCache[fullPath]) != null ? (_ref2 = _ref1._events) != null ? typeof _ref2.change === "function" ? _ref2.change() : void 0 : void 0 : void 0;
};
watchParents = {};
watchFile = function(filePath, includeDir, options) {
var compileTimeout, e, prevStats, timeEpsilon, timeLast, watcher, _onWatch, _rewatch, _unwatch, _watchErr;
if (options == null) {
options = {};
}
if (isWatched(filePath)) {
return;
}
prevStats = null;
compileTimeout = null;
_watchErr = function(e) {
if (e.code === 'ENOENT') {
try {
_rewatch();
return _compile();
} catch (_error) {
e = _error;
verbose(2, "unwatching missing file: " + filePath, 'yellow');
return _unwatch();
}
} else {
throw e;
}
};
timeLast = new Date(2000);
timeEpsilon = 2;
_onWatch = function() {
var e;
try {
clearTimeout(compileTimeout);
return compileTimeout = wait(0.025, function() {
var parent, parents, timeNow, _j, _len1, _results;
timeNow = new Date();
if ((timeNow - timeLast) / 1000 < timeEpsilon) {
return;
}
timeLast = timeNow;
if (!isOJPage(filePath)) {
parents = watchParents[filePath];
if (parents != null) {
_results = [];
for (_j = 0, _len1 = parents.length; _j < _len1; _j++) {
parent = parents[_j];
_results.push(triggerWatched(parent));
}
return _results;
}
} else {
return fs.stat(filePath, function(err, stats) {
if (err) {
return _watchErr(err);
}
verbose(2, "updating file " + filePath, 'yellow');
return compileFile(filePath, includeDir, options);
});
}
});
} catch (_error) {
e = _error;
verbose(1, 'unknown watch error on #{filePath}');
return _unwatch();
}
};
try {
verbose(2, "watching file " + filePath, 'yellow');
watcher = fs.watch(filePath, _onWatch);
watchCache[filePath] = watcher;
} catch (_error) {
e = _error;
_watchErr(e);
}
_rewatch = function() {
verbose(3, "rewatch file " + filePath, 'yellow');
_unwatch();
return watchCache[filePath] = watcher = fs.watch(filePath, _onWatch);
};
return _unwatch = function() {
if (isWatched(filePath)) {
watchCache[filePath].close();
}
return watchCache[filePath] = null;
};
};
watchDir = function(dir, includeDir, options) {
var compileTimeout, watcher;
if (isWatched(dir)) {
return;
}
compileTimeout = null;
verbose(2, "watching directory " + dir + "/", 'yellow');
watcher = fs.watch(dir, function(err) {
verbose(2, "updating directory " + dir + "/", 'yellow');
if (err && !isDirectory(dir)) {
return unwatchDir(dir);
}
return lsOJ(dir, options, function(err, files, dirs) {
var d, f, _j, _k, _len1, _len2, _results;
for (_j = 0, _len1 = dirs.length; _j < _len1; _j++) {
d = dirs[_j];
if (!isWatched(d)) {
watchDir(d);
}
}
_results = [];
for (_k = 0, _len2 = files.length; _k < _len2; _k++) {
f = files[_k];
if (!isWatched(f)) {
_results.push(compileFile(f, includeDir, options));
} else {
_results.push(void 0);
}
}
return _results;
});
});
watchCache[dir] = watcher;
};
unwatchDir = function(dir) {
verbose(2, "unwatching " + dir + "/", 'yellow');
if (isWatched(dir)) {
watchCache[dir].close();
}
watchCache[dir] = null;
};
unwatchAll = function() {
var k, _j, _len1, _ref1, _results;
verbose(2, "unwatching all files and directories", 'yellow');
_ref1 = _.keys(watchCache);
_results = [];
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
k = _ref1[_j];
if (watchCache[k] != null) {
watchCache[k].close();
_results.push(watchCache[k] = null);
} else {
_results.push(void 0);
}
}
return _results;
};
process.on('SIGINT', function() {
verbose(1, "\n");
unwatchAll();
verbose(1, "oj exited successfully.", 'cyan');
return process.exit();
});
success = function() {
return process.exit(0);
};
tabs = function(count) {
return Array(count + 1).join('\t');
};
spaces = function(count) {
return Array(count + 1).join(' ');
};
verbose = function(level, message, color) {
if (color == null) {
color = 'reset';
}
if (verbosity >= level) {
return console.log(oj.codes[color] + ("" + (spaces(4 * (level - 1))) + message) + oj.codes.reset);
}
};
error = function(message) {
var red, reset, _ref1, _ref2, _ref3, _ref4;
red = (_ref1 = (_ref2 = oj.codes) != null ? _ref2.red : void 0) != null ? _ref1 : '';
reset = (_ref3 = (_ref4 = oj.codes) != null ? _ref4.reset : void 0) != null ? _ref3 : '';
console.error("" + red + message + reset);
};
isFile = function(filePath) {
var e;
try {
return (fs.statSync(filePath)).isFile();
} catch (_error) {
e = _error;
return false;
}
};
isOJFile = function(filePath) {
var ext;
ext = path.extname(filePath);
return ext === '.oj' || ext === '.ojc';
};
isOJPage = function(filePath) {
var base, ext;
ext = path.extname(filePath);
base = path.basename(filePath);
return (isOJFile(filePath)) && base[0] !== '_' && base.slice(0, 2) !== 'oj' && !isHiddenFile(filePath);
};
isOJDir = function(dirPath, outputDir) {
var base;
base = path.basename(dirPath);
return base[0] !== '_' && base[0] !== '.' && base !== 'node_modules';
};
isWatchFile = function(filePath) {
var ext;
ext = path.extname(filePath);
return (isOJFile(filePath)) || ext === '.js' || ext === '.coffee' || ext === '.json';
};
isHiddenFile = function(file) {
return /^\.|~$/.test(file);
};
isDirectory = function(dirpath) {
var e;
try {
return (fs.statSync(dirpath)).isDirectory();
} catch (_error) {
e = _error;
return false;
}
};
relativePathWithEscaping = function(fullPath, relativeTo) {
return _escapeSingleQuotes('/' + path.relative(relativeTo, fullPath));
};
fullPaths = function(relativePaths, dir) {
return _.map(relativePaths, function(p) {
return path.resolve(dir, p);
});
};
commonPath = function(paths, seperator) {
var common, ixCommon, ixPart, p, part, parts, _j, _k, _len1, _len2;
if (seperator == null) {
seperator = '/';
}
if (paths.length === 1) {
return path.dirname(paths[0]);
}
common = paths[0].split(seperator);
ixCommon = common.length;
for (_j = 0, _len1 = paths.length; _j < _len1; _j++) {
p = paths[_j];
parts = p.split(seperator);
for (ixPart = _k = 0, _len2 = parts.length; _k < _len2; ixPart = ++_k) {
part = parts[ixPart];
if (common[ixPart] !== part || ixPart > ixCommon) {
break;
}
}
ixCommon = Math.min(ixPart, ixCommon);
}
if (ixCommon === 1 && paths[0][0] === seperator) {
return seperator;
} else if (ixCommon === 0) {
return null;
}
return (common.slice(0, ixCommon)).join(seperator);
};
lsOJ = function(paths, options, cb) {
if (options == null) {
options = {};
}
options = _.extend({}, {
recurse: options.recurse,
filterFile: (function(f) {
return isOJPage(f);
}),
filterDir: (function(d) {
return isOJDir(d);
})
});
ls(paths, options, function(err, files, dirs) {
return cb(err, files, dirs);
});
};
lsWatch = function(paths, options, cb) {
var lsOptions;
lsOptions = _.extend({}, {
recurse: options.recurse,
filterFile: isWatchFile,
filterDir: isOJDir
});
ls(paths, lsOptions, function(err, files, dirs) {
return cb(err, files, dirs);
});
};
ls = function(fullPath, options, cb, acc) {
var breakIfDone, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7;
if (_.isFunction(options)) {
cb = options;
options = {};
}
if (options == null) {
options = {};
}
if ((_ref1 = options.recurse) == null) {
options.recurse = false;
}
if ((_ref2 = options.filterFile) == null) {
options.filterFile = function() {
return true;
};
}
if ((_ref3 = options.filterDir) == null) {
options.filterDir = function() {
return true;
};
}
if ((_ref4 = options.recurseDepth) == null) {
options.recurseDepth = options.recurse ? Infinity : 1;
}
if (acc == null) {
acc = {};
}
if ((_ref5 = acc.files) == null) {
acc.files = [];
}
if ((_ref6 = acc.dirs) == null) {
acc.dirs = [];
}
if ((_ref7 = acc.pending) == null) {
acc.pending = 1;
}
breakIfDone = function() {
var dirs, files;
if (acc.pending === 0) {
files = _.uniq(acc.files);
dirs = _.uniq(acc.dirs);
cb(null, files, dirs);
}
};
fs.stat(fullPath, function(err, stat) {
if (err) {
return cb(err);
}
if (stat.isFile() && options.filterFile(fullPath)) {
acc.files.push(fullPath);
return breakIfDone(--acc.pending);
} else if (stat.isDirectory() && options.filterDir(fullPath)) {
acc.dirs.push(fullPath);
return fs.readdir(fullPath, function(errReadDir, paths) {
var fullPath_, options_, _j, _len1;
if (errReadDir) {
return cb(errReadDir);
}
if (!paths || paths.length === 0) {
return breakIfDone(--acc.pending);
}
acc.pending += paths.length;
paths = fullPaths(paths, fullPath);
if (options.recurseDepth > 0) {
options_ = _.clone(options);
options_.recurseDepth--;
for (_j = 0, _len1 = paths.length; _j < _len1; _j++) {
fullPath_ = paths[_j];
ls(fullPath_, options_, cb, acc);
}
}
return breakIfDone(--acc.pending);
});
} else {
return breakIfDone(--acc.pending);
}
});
};
readFileSync = function(filePath) {
return fs.readFileSync(filePath, 'utf8');
};
wait = function(seconds, fn) {
return setTimeout(fn, seconds * 1000);
};
trimArgList = function(v) {
return _trim(v.split(','));
};
_trim = function(any) {
var out;
if (_.isString(any)) {
return any.trim();
} else if (_.isArray(any)) {
out = _.map(any, function(v) {
return v.trim();
});
return _.reject(out, (function(v) {
return v === '' || v === null;
}));
} else {
return any;
}
};
_startsWith = function(strInput, strStart) {
if (!((_.isString(strInput)) && (_.isString(strStart)))) {
throw new Error('startsWith: argument error');
}
return strInput.length >= strStart.length && strInput.lastIndexOf(strStart, 0) === 0;
};
_escapeSingleQuotes = function(str) {
return str.replace(/'/g, "\\'");
};
_insertAt = function(str, ix, substr) {
return str.slice(0, ix) + substr + str.slice(ix);
};
_length = function(any) {
return any.length || _.keys(any).length;
};
oj._minifyJS = function(js, options) {
if (options == null) {
options = {};
}
if (options.filename) {
verbose(4, "minified " + options.filename);
}
if (options.minify) {
return uglifyjs(js);
} else {
return js;
}
};
oj._minifyCSS = function(css, options) {
if (options == null) {
options = {};
}
if (options.minify) {
return csso.justDoIt(css, true);
} else {
return css;
}
};
_hookRequire = function(modules, moduleLinkMap, hookCache, hookOriginalCache) {
var ext, handlers, hook;
if (hookCache == null) {
hookCache = {};
}
if (hookOriginalCache == null) {
hookOriginalCache = {};
}
handlers = require.extensions;
for (ext in handlers) {
hook = hookCache[ext] || (hookCache[ext] = _createHook(ext, modules, moduleLinkMap, hookCache, hookOriginalCache));
if (handlers[ext] !== hook) {
hookOriginalCache[ext] = handlers[ext];
handlers[ext] = hook;
}
}
};
_createHook = function(ext, modules, moduleLinkMap, hookCache, hookOriginalCache) {
return function(module, filename) {
var linkPath, moduleCompile, modulePath, rest;
for (linkPath in moduleLinkMap) {
modulePath = moduleLinkMap[linkPath];
if (0 === filename.indexOf(linkPath)) {
rest = filename.slice(linkPath.length);
filename = modulePath + rest;
}
}
if (!module.loaded) {
_rememberModule(modules, filename, null, module.parent.filename);
moduleCompile = module._compile;
module._compile = function(code) {
_rememberModule(modules, filename, code, module.parent.filename);
moduleCompile.apply(this, arguments);
};
}
hookOriginalCache[ext](module, filename);
return _hookRequire(modules, moduleLinkMap, hookCache, hookOriginalCache);
};
};
_unhookRequire = function(modules, hookCache, hookOriginalCache) {
var ext, handlers;
handlers = require.extensions;
for (ext in handlers) {
if (hookCache[ext] === handlers[ext]) {
handlers[ext] = hookOriginalCache[ext];
}
}
hookCache = null;
hookOriginalCache = null;
};
_rememberModule = function(modules, filename, code, parent) {
if (code) {
verbose(3, "requiring " + filename);
}
return modules[filename] = _.defaults({
code: code,
parent: parent
}, modules[filename] || {});
};
_rememberModuleDependencies = function(modules) {
var filename, module, _ref1, _results;
_results = [];
for (filename in modules) {
module = modules[filename];
if ((_ref1 = watchParents[filename]) == null) {
watchParents[filename] = [];
}
watchParents[filename].push(module.parent);
_results.push(watchParents[filename] = _.unique(watchParents[filename]));
}
return _results;
};
_nodeModulesSupported = {
oj: 1,
jquery: 1,
assert: 1,
console: 1,
crypto: 1,
events: 1,
freelist: 1,
path: 1,
punycode: 1,
querystring: 1,
string_decoder: 1,
tty: 1,
url: 1,
util: 1
};
_nodeModuleUnsupported = {
child_process: 1,
domain: 1,
fs: 1,
net: 1,
os: 1,
vm: 1,
buffer: 1
};
isNodeModule = function(module) {
return !!_nodeModulesSupported[module];
};
isUnsupportedNodeModule = function(module) {
return !!_nodeModuleUnsupported[module];
};
isAppModule = function(module) {
return (module.indexOf('/')) === -1;
};
isRelativeModule = function(module) {
return (module.indexOf('/')) !== -1;
};
_requireCache = null;
_saveRequireCache = function() {
return _requireCache = _.clone(require.cache);
};
_restoreRequireCache = function() {
var k, _results;
_results = [];
for (k in require.cache) {
if (_requireCache[k] == null) {
_results.push(delete require.cache[k]);
} else {
_results.push(void 0);
}
}
return _results;
};
_clearRequireCacheRecord = function(record) {
return delete require.cache[require.resolve(record)];
};
_getRequiresInSource = function(code) {
var match, out, r;
r = new RegExp("require\\s*\\(?\\s*[\"']([^\"']+)", 'g');
out = [];
while (match = r.exec(code)) {
out.push(match[1]);
}
return out;
};
_first = function(array, fn) {
var x, y, _j, _len1;
for (_j = 0, _len1 = array.length; _j < _len1; _j++) {
x = array[_j];
y = fn(x);
if (y) {
return y;
}
}
};
_buildRequireCache = function(modules, cache, isMinify) {
var code, data, fileLocation, filePath, modulePrefixes, pathComponents, _ref1;
for (fileLocation in modules) {
data = modules[fileLocation];
if (data.code == null) {
throw new Error('data.code is missing');
}
_buildFileCache(cache.files, fileLocation, data.code, isMinify);
modulePrefixes = nodeModulePaths(fileLocation);
pathComponents = _first(modulePrefixes, function(prefix) {
var moduleMain, moduleName, modulePath;
if (_startsWith(fileLocation, prefix + path.sep)) {
modulePath = (fileLocation.slice(prefix.length + 1)).split(path.sep);
moduleName = modulePath[0];
moduleMain = modulePath.slice(1).join(path.sep);
return {
modulesDir: prefix,
moduleName: moduleName,
moduleMain: moduleMain,
moduleParentPath: module.id
};
}
});
if (pathComponents) {
if (!cache.modules[pathComponents.modulesDir]) {
cache.modules[pathComponents.modulesDir] = {};
}
cache.modules[pathComponents.modulesDir][pathComponents.moduleName] = pathComponents.moduleMain;
}
_buildNativeCache(cache["native"], data.code, isMinify);
verbose(4, "stored " + fileLocation);
}
delete cache.files[require.resolve('../oj.js')];
cache.nativeFiles = cache["native"];
cache.moduleFiles = {};
cache.pageFiles = {};
_ref1 = cache.files;
for (filePath in _ref1) {
code = _ref1[filePath];
if (filePath.indexOf("/node_modules/") !== -1) {
cache.moduleFiles[filePath] = code;
} else {
cache.pageFiles[filePath] = code;
}
}
return cache;
};
_buildFileCache = function(_filesCache, fileName, code, isMinify) {
return _filesCache[fileName] = oj._minifyJS(code, {
filename: fileName,
minify: isMinify
});
};
pass = 1;
_buildNativeCache = function(nativeCache, code, isMinify) {
var moduleNameList;
moduleNameList = _getRequiresInSource(code);
return _buildNativeCacheFromModuleList(nativeCache, moduleNameList, isMinify);
};
_buildNativeCacheFromModuleList = function(nativeCache, moduleNameList, isMinify) {
var codeModule, moduleName;
while (moduleName = moduleNameList.shift()) {
if (nativeCache[moduleName]) {
continue;
}
if (moduleName === 'oj') {
nativeCache.oj = _ojModuleCode(isMinify);
} else if (isUnsupportedNodeModule(moduleName)) {
pass;
} else if (isNodeModule(moduleName)) {
codeModule = _nativeModuleCode(moduleName, isMinify);
nativeCache[moduleName] = codeModule;
moduleNameList = moduleNameList.concat(_getRequiresInSource(codeModule));
} else {
pass;
}
}
return null;
};
_ojModuleCode = function(isMinify) {
var code;
code = readFileSync(path.join(__dirname, "../oj.js"));
return oj._minifyJS(code, {
filename: 'oj',
minify: isMinify
});
};
_nativeModuleCode = function(moduleName, isMinify) {
var code;
verbose(3, "found " + moduleName);
return code = readFileSync(path.join(__dirname, "../modules/" + moduleName + ".js"));
};
_requireCacheToHtml = function(cache, filePath, isMinify, options) {
return "<script>\n" + (_requireCacheToJS(cache, filePath, isMinify, options)) + "\n</script>";
};
_requireCacheToJS = function(cache, filePath, isMinify, options) {
var clientDir, clientFile, code, commonDir, js, moduleDir, moduleName, nameToMain, newline, prefixWithRequire, _data, _fileToString, _find, _load, _moduleFiles, _modules, _modulesToString, _nativeFiles, _nativeModuleToString, _pageFiles, _ref1, _ref2, _ref3, _ref4, _run;
newline = isMinify ? '' : '\n';
commonDir = commonPath(_.keys(cache.files));
clientDir = '/' + path.relative(commonDir, path.dirname(filePath));
clientFile = path.join(clientDir, basenameForExtensions(filePath, ['.ojc', '.oj', '.coffee', '.js']));
_modulesToString = function(moduleDir, nameToMain) {
moduleDir = relativePathWithEscaping(moduleDir, commonDir);
return "M['" + moduleDir + "'] = " + (JSON.stringify(nameToMain)) + ";\n";
};
_nativeModuleToString = function(moduleName, code) {
moduleName = _escapeSingleQuotes(moduleName);
return "F['" + moduleName + "'] = (function(module,exports){(function(process,global,__dirname,__filename){" + newline + code + "})(P,G,'/','" + moduleName + "');});\n";
};
_fileToString = function(filePath, code, prefixWithRequire) {
var fileDir, fileName, out;
filePath = relativePathWithEscaping(filePath, commonDir);
fileDir = path.dirname(filePath);
fileName = path.basename(filePath);
out = prefixWithRequire ? "require." : "";
return out += "F['" + filePath + "'] = (function(module,exports){(function(require,process,global,__dirname,__filename){" + newline + code + "})(require.RR('" + filePath + "'),require.P,require.G,'" + fileDir + "','" + fileName + "');});" + newline + "\n";
};
_modules = "";
_ref1 = cache.modules;
for (moduleDir in _ref1) {
nameToMain = _ref1[moduleDir];
_modules += _modulesToString(moduleDir, nameToMain);
}
_moduleFiles = "";
_ref2 = cache.moduleFiles;
for (filePath in _ref2) {
code = _ref2[filePath];
_moduleFiles += _fileToString(filePath, code);
verbose(4, "serialized module file `" + filePath + "`");
}
_pageFiles = "";
prefixWithRequire = !options.modules;
_ref3 = cache.pageFiles;
for (filePath in _ref3) {
code = _ref3[filePath];
_pageFiles += _fileToString(filePath, code, prefixWithRequire);
verbose(4, "serialized page file `" + filePath + "`");
}
_nativeFiles = "";
_ref4 = cache["native"];
for (moduleName in _ref4) {
code = _ref4[moduleName];
_nativeFiles += _nativeModuleToString(moduleName, code);
verbose(4, "serialized native file '" + moduleName + "'");
}
_data = '';
if (!_.isEmpty(options.data)) {
_data = ',' + JSON.stringify(options.data);
}
_load = "oj.load('" + (_escapeSingleQuotes(clientFile)) + "'" + _data + ");";
_run = oj._minifyJS("function run(f){\n if(R[f] != null)\n return R[f];\n var eo = {},\n mo = {exports: eo};\n if(typeof F[f] != 'function')\n throw new Error(\"file not found (\" + f + \")\");\n F[f](mo,eo);\n return R[f] = mo.exports;\n }", {
minify: isMinify
});
_find = oj._minifyJS("function find(m,f){\n var r, dir, dm, ext, ex, i, loc;\n if (F[m] && !m.match(/\\//))\n return m;\n\n if (!!m.match(/\\//)) {\n r = oj._pathResolve(f, oj._pathJoin(oj._pathDirname(f), m));\n ext = ['', '.oj', '.ojc', '.js', '.coffee', '.json'];\n for(i = 0; i < ext.length; i++){\n ex = ext[i];\n if((loc = r + ex) && F[loc])\n return loc;\n else if ((loc = oj._pathJoin(r, 'index' + ex)) && F[loc])\n return loc;\n }\n } else {\n if (typeof oj !== 'undefined') {\n dir = oj._pathDirname(f);\n while(true) {\n dm = oj._pathJoin(dir, 'node_modules');\n if(M[dm] && M[dm][m])\n return oj._pathJoin(dm, m, M[dm][m]);\n if(dir == '/')\n break;\n dir = oj._pathResolve(dir, '..');\n }\n }\n }\n throw new Error(\"module not found (\" + m + \")\");\n }", {
minify: isMinify
});
js = "// Generated with oj v" + oj.version + "\n;(function(){";
if (options.modules) {
js += "var M = {}, F = {}, R = {}, P, G, RR;\n\n// Package modules\n" + _modules + "\n" + _moduleFiles + "\n// Native modules\n" + _nativeFiles + "\n// Define node environment: process P, global G and require factory RR\nP = {cwd: function(){return '/'}}\nG = {process: P,Buffer: {}}\nRR = function(f){\n var o = function(m){return run(find(m, f))};\n o.P = P; o.G = G; o.F = F; o.M = M, o.RR = RR;\n return o;\n " + _run + "\n " + _find + "\n};\n\n// Define require and oj\nrequire = RR('/');\noj = require('oj');\n";
}
if (options.js) {
js += "\n// Page files\n" + _pageFiles + "\n" + _load + "\n";
}
return js += "}).call(this);";
};
oj.__express = function(path, options, cb) {
var data;
data = _.omit(_.clone(options), 'settings', 'cache');
_.defaults(options, {
minify: options.minify,
write: false,
watch: false,
recurse: true,
modules: false,
html: true,
css: true,
js: true,
data: data
});
compilePath(path, options, cb);
};
oj.middleware = function(options) {
var urlModulesDir;
urlModulesDir = '/' + path.relative(options.publicDir, options.modulesDirDest);
return function(req, res, next) {
var baseFileName, fileRelativePath, outputFileDir, outputFilePath, urlPath;
if ('GET' !== req.method && 'HEAD' !== req.method) {
return next();
}
urlPath = url.parse(req.url).pathname;
if (/\.js$/.test(urlPath) && _startsWith(urlPath, urlModulesDir)) {
fileRelativePath = path.relative(urlModulesDir, urlPath);
outputFilePath = path.join(options.modulesDirDest, fileRelativePath);
outputFileDir = path.dirname(outputFilePath);
baseFileName = path.basename(urlPath, '.js');
return findFile(options.modulesDirSrc, baseFileName, ['.oj', '.ojc'], function(err, inputFilePath) {
var _middlewareCompileModule;
if (inputFilePath) {
if (options.force) {
_middlewareCompileModule();
} else {
fileIsOutdated(outputFilePath, inputFilePath, function(err, idOutdated) {
if (idOutdated) {
_middlewareCompileModule();
} else {
next();
}
});
}
return _middlewareCompileModule = function() {
var e, _ref1, _ref2;
try {
return compilePath(inputFilePath, {
output: outputFileDir,
force: (_ref1 = options.force) != null ? _ref1 : false,
minify: (_ref2 = options.minify) != null ? _ref2 : true,
html: 0,
css: 0,
js: 0,
write: 1,
modules: 1
}, function() {
return next();
});
} catch (_error) {
e = _error;
return next();
}
};
} else {
return next();
}
});
} else {
return next();
}
};
};
fileIsOutdated = function(fileDest, fileSource, cb) {
fs.stat(fileSource, function(errSource, statSource) {
if (errSource) {
return cb(errSource, null);
}
return fs.stat(fileDest, function(errDest, statDest) {
if (!errDest || errDest.code === 'ENOENT') {
return cb(null, !!errDest || statSource.mtime.getTime() > statDest.mtime.getTime());
} else {
return cb(errDest, null);
}
});
});
};
findFile = function(dir, baseFileName, extensions, cb) {
var ext, fileName;
if (!dir || !baseFileName || !extensions || !cb) {
return cb('findFile: invalid input');
}
ext = extensions.shift();
fileName = baseFileName + ext;
return (function(dir, fileName) {
return fs.stat(path.join(dir, fileName), function(err, statInfo) {
if (statInfo && statInfo.isFile()) {
return cb(null, path.join(dir, fileName));
} else if (extensions.length > 0) {
return findFile(dir, baseFileName, extensions, cb);
} else {
return cb(null, null);
}
});
})(dir, fileName);
};
}).call(this);