UNPKG

css-pipeline

Version:

roots extension for handling css production builds

188 lines (160 loc) 5.3 kB
// Generated by CoffeeScript 1.9.1 (function() { var CleanCSS, RootsUtil, _, crypto, fs, minimatch, path, yaml; fs = require('fs'); path = require('path'); _ = require('lodash'); minimatch = require('minimatch'); CleanCSS = require('clean-css'); crypto = require('crypto'); RootsUtil = require('roots-util'); yaml = require('js-yaml'); module.exports = function(opts) { var CSSPipeline; opts = _.defaults(opts, { files: 'assets/css/**', manifest: false, out: false, minify: false, hash: false, opts: {} }); opts.files = Array.prototype.concat(opts.files); return CSSPipeline = (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 CSSPipeline(roots) { var base; this.roots = roots; this.category = 'css-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.css = (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 "<link rel='stylesheet' href='" + p + "' />"; }).join("\n"); }; })(this); } /** * Minimatch runs against each path, quick and easy. */ CSSPipeline.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. */ CSSPipeline.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. */ CSSPipeline.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; } } } if (opts.minify) { all_contents = (new CleanCSS(opts.opts)).minify(all_contents).styles; } 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) }; }; /** * @private */ 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 fN, filePath; filePath = _this.util.output_path(f.relative).relative; fN = path.join(prefix, filePath.split('.')[0] + '.css'); return fN.replace(new RegExp('\\' + path.sep, 'g'), '/'); }; })(this)); }; return CSSPipeline; })(); }; }).call(this);