<commit_before>var fs = require('fs');
var extend = require('util')._extend;
var path = require('path');
var crypto = require('crypto');
var onHeaders = require('on-headers');

var uglifyjs = require('uglify-js');
var cssmin = require('cssmin');
var sass;
var less;
var stylus;
var coffee;

var memCache = {};

var TYPE_TEXT = 0;
var TYPE_JS = 1;
var TYPE_CSS = 2;
var TYPE_SASS = 3;
var TYPE_LESS = 4;
var TYPE_STYLUS = 5;
var TYPE_COFFEE = 6;

function precompileError(err, type) {
    return JSON.stringify(err);
}

function minifyIt(type, options, content, callback) {
    if (typeof callback != 'function') {
        return;
    }

    switch(type) {
        case TYPE_JS:
            var result = content;
            try {
                if (!options.noMinify) {
                    var opt = extend({fromString: true}, options.uglify);
                    result = uglifyjs.minify(result, opt).code;
                }
            } catch(err) {
            }
            callback(result);
            break;
        case TYPE_CSS:
            var result = content;
            try {
                if (!options.noMinify) {
                    result = cssmin(content)
                }
            } catch(err) {
            }
            callback(result);
            break;
        case TYPE_SASS:
            if (!sass) {
                sass = require('node-sass');
            }
            var result;
            try {
                result = sass.renderSync({
                    data: content
                }).css;
                try {
                    if (!options.noMinify) {
                        result = cssmin(result);
                    }
                } catch(err) {
                }
            } catch(err) {
                result = precompileError(err, type);
            }
            callback(result);
            break;
        case TYPE_LESS:
            if (!less) {
                less = require('less');
            }
            less.render(content, function(err, output) {
                if (err) {
                    callback(precompileError(err, type));
                    return;
                }
                var result = output.css;
                try {
                    if (!options.noMinify) {
                        result = cssmin(result);
                    }
                } catch(err) {
                }
                callback(result);
            });
            break;
        case TYPE_STYLUS:
            if (!stylus) {
                stylus = require('stylus');
            }
            stylus.render(content, function(err, css) {
                if (err) {
                    callback(precompileError(err, type));
                    return;
                }
                var result = css;
                try {
                    if (!options.noMinify) {
                        result = cssmin(result);
                    }
                } catch(err) {
                }
                callback(result);
            });
            break;
        case TYPE_COFFEE:
            if (!coffee) {
                coffee = require('coffee-script');
            }
            var result;
            try {
                result = coffee.compile(content);
                try {
                    if (!options.noMinify) {
                        var opt = extend({fromString: true}, options.uglify);
                        result = uglifyjs.minify(result, opt).code;
                    }
                } catch(err) {
                }
            } catch(err) {
                result = precompileError(err, type);
            }
            callback(result);
            break;
        default:
            callback(content);
            break;
    }
}

function cacheGetFile(hash, callback) {
    if (typeof callback != 'function') {
        return;
    }

    var filepath = this.toString();

    fs.readFile(filepath + hash, { encoding: 'utf8' }, function(err, data) {
        if (err) {
            callback(err);
            return;
        }
        try {
            data = JSON.parse(data).content;
            callback(null, data);
        } catch(err) {
            callback(err);
        }
    });
}

function cachePutFile(hash, minized, callback) {
    var filepath = this.toString();

    // fix issue #3
    // not ended file writing will cause wrong responding.
    // using temp files can mostly avoid the case.

    fs.writeFile(filepath + hash + '.tmp', JSON.stringify({content:minized}), { encoding: 'utf8' }, function(err) {
        if (err) {
            return callback(err);
        }
        fs.rename(filepath + hash + '.tmp', filepath + hash, callback);
    });
}

function cacheGetMem(hash, callback) {
    if (typeof callback != 'function') {
        return;
    }

    if (typeof memCache[hash] == 'undefined') {
        callback(new Error('miss'));
    } else {
        callback(null, memCache[hash]);
    }
}

function cachePutMem(hash, minized, callback) {
    memCache[hash] = minized;

    if (typeof callback == 'function') {
        callback(null);
    }
}

module.exports = 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 cache = options.cache || false;

    var cache_get = cacheGetMem;
    var cache_put = cachePutMem;

    if (cache) {
        cache = path.normalize(cache + '/').toString();

        fs.writeFile(cache + 'test.tmp', new Date().getTime().toString(), function(err) {
            if (err) {
                console.log('WARNING: express-minify cache directory is not valid or is not writeable.');
                return;
            }

            //Consider deleting the test file?

            //OK: rewrite functions
            cache_get = function() {
                return cacheGetFile.apply(cache, arguments);
            };
            cache_put = function() {
                return cachePutFile.apply(cache, arguments);
            };
        });
    }

    return function middleware(req, res, next) {
        var _storeHeader = res._storeHeader;

        var write = res.write;
        var end = res.end;

        var buf = null;
        var type = TYPE_TEXT;

        onHeaders(res, function() {
            if (req.method === 'HEAD') {
                return;
            }

            if (res._skip) {
                return;
            }

            var contentType = res.getHeader('Content-Type');
            if (contentType === undefined) {
                return;
            }

            if (sass_match.test(contentType)) {
                type = TYPE_SASS;
                res.setHeader('Content-Type', 'text/css');
            } else if (less_match.test(contentType)) {
                type = TYPE_LESS;
                res.setHeader('Content-Type', 'text/css');
            } else if (stylus_match.test(contentType)) {
                type = TYPE_STYLUS;
                res.setHeader('Content-Type', 'text/css');
            } else if (coffee_match.test(contentType)) {
                type = TYPE_COFFEE;
                res.setHeader('Content-Type', 'text/javascript');
            } else if (js_match.test(contentType)) {
                type = TYPE_JS;
            } else if (css_match.test(contentType)) {
                type = TYPE_CSS;
            }

            if (type === TYPE_TEXT) {<commit_msg>update mime type of javascript<commit_after>var fs = require('fs');
var extend = require('util')._extend;
var path = require('path');
var crypto = require('crypto');
var onHeaders = require('on-headers');

var uglifyjs = require('uglify-js');
var cssmin = require('cssmin');
var sass;
var less;
var stylus;
var coffee;

var memCache = {};

var TYPE_TEXT = 0;
var TYPE_JS = 1;
var TYPE_CSS = 2;
var TYPE_SASS = 3;
var TYPE_LESS = 4;
var TYPE_STYLUS = 5;
var TYPE_COFFEE = 6;

function precompileError(err, type) {
    return JSON.stringify(err);
}

function minifyIt(type, options, content, callback) {
    if (typeof callback != 'function') {
        return;
    }

    switch(type) {
        case TYPE_JS:
            var result = content;
            try {
                if (!options.noMinify) {
                    var opt = extend({fromString: true}, options.uglify);
                    result = uglifyjs.minify(result, opt).code;
                }
            } catch(err) {
            }
            callback(result);
            break;
        case TYPE_CSS:
            var result = content;
            try {
                if (!options.noMinify) {
                    result = cssmin(content)
                }
            } catch(err) {
            }
            callback(result);
            break;
        case TYPE_SASS:
            if (!sass) {
                sass = require('node-sass');
            }
            var result;
            try {
                result = sass.renderSync({
                    data: content
                }).css;
                try {
                    if (!options.noMinify) {
                        result = cssmin(result);
                    }
                } catch(err) {
                }
            } catch(err) {
                result = precompileError(err, type);
            }
            callback(result);
            break;
        case TYPE_LESS:
            if (!less) {
                less = require('less');
            }
            less.render(content, function(err, output) {
                if (err) {
                    callback(precompileError(err, type));
                    return;
                }
                var result = output.css;
                try {
                    if (!options.noMinify) {
                        result = cssmin(result);
                    }
                } catch(err) {
                }
                callback(result);
            });
            break;
        case TYPE_STYLUS:
            if (!stylus) {
                stylus = require('stylus');
            }
            stylus.render(content, function(err, css) {
                if (err) {
                    callback(precompileError(err, type));
                    return;
                }
                var result = css;
                try {
                    if (!options.noMinify) {
                        result = cssmin(result);
                    }
                } catch(err) {
                }
                callback(result);
            });
            break;
        case TYPE_COFFEE:
            if (!coffee) {
                coffee = require('coffee-script');
            }
            var result;
            try {
                result = coffee.compile(content);
                try {
                    if (!options.noMinify) {
                        var opt = extend({fromString: true}, options.uglify);
                        result = uglifyjs.minify(result, opt).code;
                    }
                } catch(err) {
                }
            } catch(err) {
                result = precompileError(err, type);
            }
            callback(result);
            break;
        default:
            callback(content);
            break;
    }
}

function cacheGetFile(hash, callback) {
    if (typeof callback != 'function') {
        return;
    }

    var filepath = this.toString();

    fs.readFile(filepath + hash, { encoding: 'utf8' }, function(err, data) {
        if (err) {
            callback(err);
            return;
        }
        try {
            data = JSON.parse(data).content;
            callback(null, data);
        } catch(err) {
            callback(err);
        }
    });
}

function cachePutFile(hash, minized, callback) {
    var filepath = this.toString();

    // fix issue #3
    // not ended file writing will cause wrong responding.
    // using temp files can mostly avoid the case.

    fs.writeFile(filepath + hash + '.tmp', JSON.stringify({content:minized}), { encoding: 'utf8' }, function(err) {
        if (err) {
            return callback(err);
        }
        fs.rename(filepath + hash + '.tmp', filepath + hash, callback);
    });
}

function cacheGetMem(hash, callback) {
    if (typeof callback != 'function') {
        return;
    }

    if (typeof memCache[hash] == 'undefined') {
        callback(new Error('miss'));
    } else {
        callback(null, memCache[hash]);
    }
}

function cachePutMem(hash, minized, callback) {
    memCache[hash] = minized;

    if (typeof callback == 'function') {
        callback(null);
    }
}

module.exports = 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 cache = options.cache || false;

    var cache_get = cacheGetMem;
    var cache_put = cachePutMem;

    if (cache) {
        cache = path.normalize(cache + '/').toString();

        fs.writeFile(cache + 'test.tmp', new Date().getTime().toString(), function(err) {
            if (err) {
                console.log('WARNING: express-minify cache directory is not valid or is not writeable.');
                return;
            }

            //Consider deleting the test file?

            //OK: rewrite functions
            cache_get = function() {
                return cacheGetFile.apply(cache, arguments);
            };
            cache_put = function() {
                return cachePutFile.apply(cache, arguments);
            };
        });
    }

    return function middleware(req, res, next) {
        var _storeHeader = res._storeHeader;

        var write = res.write;
        var end = res.end;

        var buf = null;
        var type = TYPE_TEXT;

        onHeaders(res, function() {
            if (req.method === 'HEAD') {
                return;
            }

            if (res._skip) {
                return;
            }

            var contentType = res.getHeader('Content-Type');
            if (contentType === undefined) {
                return;
            }

            if (sass_match.test(contentType)) {
                type = TYPE_SASS;
                res.setHeader('Content-Type', 'text/css');
            } else if (less_match.test(contentType)) {
                type = TYPE_LESS;
                res.setHeader('Content-Type', 'text/css');
            } else if (stylus_match.test(contentType)) {
                type = TYPE_STYLUS;
                res.setHeader('Content-Type', 'text/css');
            } else if (coffee_match.test(contentType)) {
                type = TYPE_COFFEE;
                res.setHeader('Content-Type', 'application/javascript');
            } else if (js_match.test(contentType)) {
                type = TYPE_JS;
            } else if (css_match.test(contentType)) {
                type = TYPE_CSS;
            }

            if (type === TYPE_TEXT) {
{'fraction_non_alphanumeric': 0.11475195822454308, 'fraction_numerical': 0.0013054830287206266, 'mean_word_length': 1.3301901140684411, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1582356', 'n_tokens_mistral': 4286, 'n_tokens_neox': 4069, 'n_words': 932}