aboutsummaryrefslogtreecommitdiff
path: root/node_modules/express-minify/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/express-minify/index.js')
-rwxr-xr-xnode_modules/express-minify/index.js187
1 files changed, 187 insertions, 0 deletions
diff --git a/node_modules/express-minify/index.js b/node_modules/express-minify/index.js
new file mode 100755
index 0000000..aa199ec
--- /dev/null
+++ b/node_modules/express-minify/index.js
@@ -0,0 +1,187 @@
+var crypto = require('crypto');
+var onHeaders = require('on-headers');
+
+var Factory = function (options) {
+ return createMiddleware(options);
+};
+
+Factory.Cache = require('./cache.js');
+Factory.Minifier = require('./minifier.js');
+
+module.exports = Factory;
+
+var createMiddleware = function express_minify(options) {
+ options = options || {};
+
+ var js_match = options.js_match || /javascript/;
+ var css_match = options.css_match || /css/;
+ var sass_match = options.sass_match || /scss/;
+ var less_match = options.less_match || /less/;
+ var stylus_match = options.stylus_match || /stylus/;
+ var coffee_match = options.coffee_match || /coffeescript/;
+ var json_match = options.json_match || /json/;
+
+ var cache = new Factory.Cache(options.cache || false);
+ var minifier = new Factory.Minifier(options.uglifyJS, options.cssmin, options.onerror);
+
+ return function express_minify_middleware(req, res, next) {
+ var write = res.write;
+ var end = res.end;
+
+ var buf = null;
+ var type = Factory.Minifier.TYPE_TEXT;
+
+ onHeaders(res, function () {
+ if (req.method === 'HEAD') {
+ return;
+ }
+
+ if (res._skip) {
+ return;
+ }
+
+ var contentType = res.getHeader('Content-Type');
+ if (contentType === undefined) {
+ return;
+ }
+
+ // for sass, less, stylus, coffee module:
+ // null: module is found but not loaded
+ // false: module not found
+ // so we should not process false values, but allow null values
+ if (minifier.sass !== false && sass_match.test(contentType)) {
+ type = Factory.Minifier.TYPE_SASS;
+ res.setHeader('Content-Type', 'text/css');
+ } else if (minifier.less !== false && less_match.test(contentType)) {
+ type = Factory.Minifier.TYPE_LESS;
+ res.setHeader('Content-Type', 'text/css');
+ } else if (minifier.stylus !== false && stylus_match.test(contentType)) {
+ type = Factory.Minifier.TYPE_STYLUS;
+ res.setHeader('Content-Type', 'text/css');
+ } else if (minifier.coffee !== false && coffee_match.test(contentType)) {
+ type = Factory.Minifier.TYPE_COFFEE;
+ res.setHeader('Content-Type', 'text/javascript');
+ } else if (json_match.test(contentType)) {
+ type = Factory.Minifier.TYPE_JSON;
+ } else if (js_match.test(contentType)) {
+ type = Factory.Minifier.TYPE_JS;
+ } else if (css_match.test(contentType)) {
+ type = Factory.Minifier.TYPE_CSS;
+ }
+
+ if (type === Factory.Minifier.TYPE_TEXT) {
+ return;
+ }
+
+ if ((type === Factory.Minifier.TYPE_JS || type === Factory.Minifier.TYPE_CSS) && res._no_minify) {
+ return;
+ }
+
+ res.removeHeader('Content-Length');
+
+ // prepare the buffer
+ buf = [];
+ });
+
+ res.write = function (chunk, encoding) {
+ if (!this._header) {
+ this._implicitHeader();
+ }
+
+ if (buf === null) {
+ return write.call(this, chunk, encoding);
+ }
+
+ if (!this._hasBody) {
+ return true;
+ }
+
+ if (typeof chunk !== 'string' && !Buffer.isBuffer(chunk)) {
+ throw new TypeError('first argument must be a string or Buffer');
+ }
+
+ if (chunk.length === 0) {
+ return true;
+ }
+
+ // no chunked_encoding here
+ if (typeof chunk === 'string') {
+ chunk = new Buffer(chunk, encoding);
+ }
+
+ buf.push(chunk);
+ };
+
+ res.end = function (data, encoding) {
+ if (this.finished) {
+ return false;
+ }
+
+ if (!this._header) {
+ this._implicitHeader();
+ }
+
+ if (data && !this._hasBody) {
+ data = false;
+ }
+
+ if (buf === null) {
+ return end.call(this, data, encoding);
+ }
+
+ // TODO: implement hot-path optimization
+ if (data) {
+ this.write(data, encoding);
+ }
+
+ var buffer = Buffer.concat(buf);
+
+ // prepare uglify options
+ var uglifyOptions = {};
+ if (this._no_mangle) {
+ uglifyOptions.mangle = false;
+ }
+ if (this._uglifyMangle !== undefined) {
+ uglifyOptions.mangle = this._uglifyMangle;
+ }
+ if (this._uglifyOutput !== undefined) {
+ uglifyOptions.output = this._uglifyOutput;
+ }
+ if (this._uglifyCompress !== undefined) {
+ uglifyOptions.compress = this._uglifyCompress;
+ }
+
+ var minifyOptions = {
+ uglifyOpt: uglifyOptions,
+ noMinify: this._no_minify
+ };
+
+ var cacheKey = crypto.createHash('sha1').update(JSON.stringify(minifyOptions) + buffer).digest('hex').toString();
+ var self = this;
+
+ cache.layer.get(cacheKey, function (err, minized) {
+ if (err) {
+ // cache miss
+ minifier.compileAndMinify(type, minifyOptions, buffer.toString(encoding), function (err, minized) {
+ if (self._no_cache || err) {
+ // do not cache the response body
+ write.call(self, minized, 'utf8');
+ end.call(self);
+ } else {
+ cache.layer.put(cacheKey, minized, function () {
+ write.call(self, minized, 'utf8');
+ end.call(self);
+ });
+ }
+ });
+ } else {
+ // cache hit
+ write.call(self, minized, 'utf8');
+ end.call(self);
+ }
+ });
+ };
+
+ next();
+ };
+};