js-pipeline
Version:
roots extension for handling js production builds
184 lines (158 loc) • 5.25 kB
JavaScript
// Generated by CoffeeScript 1.9.1
(function() {
var RootsUtil, UglifyJS, _, crypto, fs, minimatch, path, yaml;
fs = require('fs');
path = require('path');
_ = require('lodash');
minimatch = require('minimatch');
UglifyJS = require('uglify-js');
crypto = require('crypto');
RootsUtil = require('roots-util');
yaml = require('js-yaml');
module.exports = function(opts) {
var JSPipeline;
opts = _.defaults(opts, {
files: ['assets/js/**'],
manifest: false,
out: false,
minify: false,
hash: false,
opts: {}
});
opts.opts.fromString = true;
opts.opts.comments = true;
opts.files = Array.prototype.concat(opts.files);
return JSPipeline = (function() {
/**
* Sets up the custom category and view function.
* The view function grabs either the single output path or collects
* all non-ignored output paths for the input files and returns them
* as html link tags.
*
* @param {Function} @roots - Roots class instance
*/
var get_output_paths, load_manifest_file;
function JSPipeline(roots) {
var base;
this.roots = roots;
this.category = 'js-pipeline';
this.file_map = {};
this.util = new RootsUtil(this.roots);
if (opts.manifest) {
this.roots.config.ignores.push(opts.manifest);
this.manifest = load_manifest_file.call(this, opts.manifest);
}
this.files = this.manifest || opts.files;
if ((base = this.roots.config).locals == null) {
base.locals = {};
}
this.roots.config.locals.js = (function(_this) {
return function(prefix) {
var i, len, matcher, paths, ref;
if (prefix == null) {
prefix = '';
}
paths = [];
if (opts.out) {
paths.push("" + prefix + opts.out);
} else {
ref = _this.files;
for (i = 0, len = ref.length; i < len; i++) {
matcher = ref[i];
paths = paths.concat(get_output_paths.call(_this, matcher, prefix));
}
}
return paths.map(function(p) {
return "<script src='" + p + "'></script>";
}).join("\n");
};
})(this);
}
/**
* Minimatch runs against each path, quick and easy.
*/
JSPipeline.prototype.fs = function() {
return {
extract: true,
detect: (function(_this) {
return function(f) {
return _.any(_this.files, minimatch.bind(_this, f.relative));
};
})(this)
};
};
/**
* After compile, if concat is happening, grab the contents and save them
* away, then prevent write.
*/
JSPipeline.prototype.compile_hooks = function() {
return {
write: function() {
return !opts.out;
},
after_file: (function(_this) {
return function(ctx) {
if (opts.out) {
return _this.file_map[ctx.file.relative] = ctx.content;
}
};
})(this)
};
};
/**
* Write the output file if necessary.
*/
JSPipeline.prototype.category_hooks = function() {
return {
after: (function(_this) {
return function(ctx) {
var all_contents, content, file, hash, i, len, matcher, ref, ref1, res;
if (!opts.out) {
return;
}
all_contents = '';
ref = _this.files;
for (i = 0, len = ref.length; i < len; i++) {
matcher = ref[i];
ref1 = _this.file_map;
for (file in ref1) {
content = ref1[file];
if (minimatch(file, matcher)) {
all_contents += content + "\n";
}
}
}
if (opts.minify) {
all_contents = UglifyJS.minify(all_contents, opts.opts).code;
}
if (opts.hash) {
hash = crypto.createHash('md5').update(all_contents, 'utf8');
res = opts.out.split('.');
res.splice(-1, 0, hash.digest('hex'));
opts.out = res.join('.');
}
return _this.util.write(opts.out, all_contents);
};
})(this)
};
};
load_manifest_file = function(f) {
var res;
res = yaml.safeLoad(fs.readFileSync(path.join(this.roots.root, f), 'utf8'));
return res.map(function(m) {
return path.join(path.dirname(f), m);
});
};
get_output_paths = function(files, prefix) {
return this.util.files(files).map((function(_this) {
return function(f) {
var filePath;
filePath = _this.util.output_path(f.relative).relative;
return path.join(prefix, filePath.replace(path.extname(filePath), '.js'));
};
})(this));
};
return JSPipeline;
})();
};
}).call(this);