expresser
Version:
A ready to use Node.js web app wrapper, built on top of Express.
130 lines (108 loc) • 4.76 kB
JavaScript
var url = require("url");
var fs = require("fs");
var Mincer = require("./mincer.js");
var Assets = require("./assets.js");
var connectAssets = module.exports = function(options, configureCallback) {
options = parseOptions(options || {});
var assets = new Assets(Mincer, options);
var compilationComplete = false;
var compilationError;
var waiting = [];
options.helperContext.css = assets.helper(tagWriters.css, "css");
options.helperContext.cssInline = assets.helper(tagWriters.cssInline, "css");
options.helperContext.js = assets.helper(tagWriters.js, "js");
options.helperContext.jsInline = assets.helper(tagWriters.jsInline, "js");
options.helperContext.assetPath = assets.helper(tagWriters.noop);
if (configureCallback) {
configureCallback(assets);
}
assets.compile(function(err) {
if (err) {
compilationError = err;
}
compilationComplete = true;
for (var i = 0; i < waiting.length; i++) {
waiting[i]();
};
});
var middleware = function(req, res, next) {
var path = url.parse(req.url).pathname.replace(/^\//, "");
if (path.toLowerCase().indexOf(options.localServePath.toLowerCase()) === 0) {
var serve = function(req, res, next) {
if (compilationError) {
next(compilationError);
} else {
assets.serveAsset(req, res, next);
}
};
if (compilationComplete) {
serve(req, res, next);
} else {
waiting.push(serve.bind(this, req, res, next));
}
} else {
next();
}
};
Object.keys(assets).forEach(function(method) {
middleware[method] = assets[method];
});
Object.keys(assets.__proto__).forEach(function(method) {
middleware.__proto__[method] = assets.__proto__[method];
});
return middleware;
};
module.exports.Mincer = Mincer
var parseOptions = module.exports._parseOptions = function(options) {
var isProduction = process.env.NODE_ENV === "production";
var isDevelopment = !isProduction;
var servePath = (options.servePath || "assets");
var servePathPathname = parseUrl(servePath).pathname || "/";
options.paths = arrayify(options.paths || options.src || ["assets/js", "assets/css"]);
options.helperContext = options.helperContext || global;
options.servePath = servePath.replace(/^\//, "").replace(/\/$/, "");
options.localServePath = options.localServePath || servePathPathname.replace(/^\//, "");
options.precompile = arrayify(options.precompile || ["*.*"]);
options.build = options.build != null ? options.build : isProduction;
options.buildDir = options.buildDir != null ? options.buildDir : "builtAssets";
options.compile = options.compile != null ? options.compile : true;
options.bundle = options.bundle != null ? options.bundle : isProduction;
options.compress = options.compress != null ? options.compress : isProduction;
options.sourceMaps = options.sourceMaps != null ? options.sourceMaps : isDevelopment;
options.gzip = options.gzip != null ? options.gzip : false;
options.fingerprinting = options.fingerprinting != null ? options.fingerprinting : isProduction;
options.embedMappingComments = options.embedMappingComments != null ? options.embedMappingComments : false;
options.noSourceMapProtection = options.noSourceMapProtection != null ? options.noSourceMapProtection : false;
if (options.buildDir.replace) {
options.buildDir = options.buildDir.replace(/^\//, "").replace(/\/$/, "");
}
return options;
};
var arrayify = module.exports._arrayify = function(target) {
return (target instanceof Array) ? target : [target];
};
var pasteAttr = function(attributes) {
return !!attributes ? ' ' + attributes : '';
};
var parseUrl = function(string) {
var parseQueryString = false;
var allowUrlWithoutProtocol = true;
return url.parse(string, parseQueryString, allowUrlWithoutProtocol);
};
var tagWriters = {
css: function(url, contentProvider, attr) {
return '<link rel="stylesheet" href="' + url + '"' + pasteAttr(attr) + ' />';
},
cssInline: function(url, contentProvider, attr) {
return '<style' + pasteAttr(attr) + '>' + contentProvider() + '</style>';
},
js: function(url, contentProvider, attr) {
return '<script src="' + url + '"' + pasteAttr(attr) + '></script>';
},
jsInline: function(url, contentProvider, attr) {
return '<script' + pasteAttr(attr) + '>' + contentProvider() + '</script>';
},
noop: function(url) {
return url;
},
};