UNPKG

3.06 kBJavaScriptView Raw
1'use strict';
2var path = require('path');
3var os = require('os');
4var dargs = require('dargs');
5var async = require('async');
6var chalk = require('chalk');
7var spawn = require('cross-spawn');
8var which = require('which');
9var checkFilesSyntax = require('./lib/check');
10var concurrencyCount = (os.cpus().length || 1) * 4;
11
12module.exports = function (grunt) {
13 var checkBinary = function (cmd, errMsg) {
14 try {
15 which.sync(cmd);
16 } catch (err) {
17 return grunt.warn(
18 '\n' + errMsg + '\n' +
19 'More info: https://github.com/gruntjs/grunt-contrib-sass\n'
20 );
21 }
22 };
23
24 grunt.registerMultiTask('sass', 'Compile Sass to CSS', function () {
25 var cb = this.async();
26 var options = this.options();
27
28 if (options.bundleExec) {
29 checkBinary('bundle',
30 'bundleExec options set but no Bundler executable found in your PATH.'
31 );
32 } else {
33 checkBinary('sass',
34 'You need to have Ruby and Sass installed and in your PATH for this task to work.'
35 );
36 }
37
38 if (options.check) {
39 options.concurrencyCount = concurrencyCount;
40 checkFilesSyntax(this.filesSrc, options, cb);
41 return;
42 }
43
44 var passedArgs = dargs(options, {
45 excludes: ['bundleExec'],
46 ignoreFalse: true
47 });
48
49 async.eachLimit(this.files, concurrencyCount, function (file, next) {
50 var src = file.src[0];
51
52 if (path.basename(src)[0] === '_') {
53 return next();
54 }
55
56 var args = [
57 src,
58 file.dest
59 ].concat(passedArgs);
60
61 if (options.update) {
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);
67 } else {
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());
71 }
72 }
73
74 var bin = 'sass';
75
76 if (options.bundleExec) {
77 bin = 'bundle';
78 args.unshift('exec', 'sass');
79 }
80
81 // If we're compiling scss or css files
82 if (path.extname(src) === '.css') {
83 args.push('--scss');
84 }
85
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, '');
89 }
90
91 grunt.verbose.writeln('Command: ' + bin + ' ' + args.join(' '));
92
93 var cp = spawn(bin, args, {stdio: 'inherit'});
94
95 cp.on('error', grunt.warn);
96
97 cp.on('close', function (code) {
98 if (code > 0) {
99 grunt.warn('Exited with error code ' + code);
100 next();
101 return;
102 }
103
104 grunt.verbose.writeln('File ' + chalk.cyan(file.dest) + ' created');
105 next();
106 });
107 }, cb);
108 });
109};