2 var path = require('path');
3 var os = require('os');
4 var dargs = require('dargs');
5 var async = require('async');
6 var chalk = require('chalk');
7 var spawn = require('cross-spawn');
8 var which = require('which');
9 var checkFilesSyntax = require('./lib/check');
10 var concurrencyCount = (os.cpus().length || 1) * 4;
12 module.exports = function (grunt) {
13 var checkBinary = function (cmd, errMsg) {
18 '\n' + errMsg + '\n' +
19 'More info: https://github.com/gruntjs/grunt-contrib-sass\n'
24 grunt.registerMultiTask('sass', 'Compile Sass to CSS', function () {
25 var cb = this.async();
26 var options = this.options();
28 if (options.bundleExec) {
30 'bundleExec options set but no Bundler executable found in your PATH.'
34 'You need to have Ruby and Sass installed and in your PATH for this task to work.'
39 options.concurrencyCount = concurrencyCount;
40 checkFilesSyntax(this.filesSrc, options, cb);
44 var passedArgs = dargs(options, {
45 excludes: ['bundleExec'],
49 async.eachLimit(this.files, concurrencyCount, function (file, next) {
50 var src = file.src[0];
52 if (path.basename(src)[0] === '_') {
62 // When the source file hasn't yet been compiled SASS will write an empty file.
63 // If this is the first time the file has been written we treat it as if `update` was not passed
64 if (!grunt.file.exists(file.dest)) {
65 // Find where the --update flag is and remove it
66 args.splice(args.indexOf('--update'), 1);
68 // The first two elements in args are the source and destination files,
69 // which are used to build a path that SASS recognizes, i.e. "source:destination"
70 args.push(args.shift() + ':' + args.shift());
76 if (options.bundleExec) {
78 args.unshift('exec', 'sass');
81 // If we're compiling scss or css files
82 if (path.extname(src) === '.css') {
86 // Make sure grunt creates the destination folders if they don't exist
87 if (!grunt.file.exists(file.dest)) {
88 grunt.file.write(file.dest, '');
91 grunt.verbose.writeln('Command: ' + bin + ' ' + args.join(' '));
93 var cp = spawn(bin, args, {stdio: 'inherit'});
95 cp.on('error', grunt.warn);
97 cp.on('close', function (code) {
99 grunt.warn('Exited with error code ' + code);
104 grunt.verbose.writeln('File ' + chalk.cyan(file.dest) + ' created');