UNPKG

css-pipeline

Version:

roots extension for handling css production builds

109 lines (83 loc) 2.86 kB
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 = (opts) -> opts = _.defaults opts, files: 'assets/css/**' manifest: false out: false minify: false hash: false opts: {} opts.files = Array.prototype.concat(opts.files) class CSSPipeline ###* * 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 ### constructor: (@roots) -> @category = 'css-pipeline' @file_map = {} @util = new RootsUtil(@roots) if opts.manifest @roots.config.ignores.push(opts.manifest) opts.manifest = load_manifest_file.call(@, opts.manifest) @files = opts.manifest or opts.files @roots.config.locals ?= {} @roots.config.locals.css = => paths = [] if opts.out paths.push(opts.out) else for matcher in @files paths = paths.concat(get_output_paths.call(@, matcher)) paths.map((p) -> "<link rel='stylesheet' href='#{p}' />").join("\n") ###* * Minimatch runs against each path, quick and easy. ### fs: -> extract: true detect: (f) => _.any(@files, minimatch.bind(@, f.relative)) ###* * After compile, if concat is happening, grab the contents and save them * away, then prevent write. ### compile_hooks: -> write: -> !opts.out after_file: (ctx) => if opts.out then @file_map[ctx.file.relative] = ctx.content ###* * Write the output file if necessary. ### category_hooks: -> after: (ctx) => if not opts.out then return all_contents = '' for matcher in @files for file, content of @file_map when minimatch(file, matcher) all_contents += content if opts.minify all_contents = (new CleanCSS(opts.opts)).minify(all_contents) 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('.') @util.write(opts.out, all_contents) ###* * @private ### load_manifest_file = (f) -> res = yaml.safeLoad(fs.readFileSync(path.join(@roots.root, f), 'utf8')) res.map((m) -> path.join(path.dirname(f), m)) get_output_paths = (files) -> @util.files(files).map((f) => path.sep + @util.output_path(f.relative, 'css').relative)