123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- /*
- * grunt-contrib-sass
- * http://gruntjs.com/
- *
- * Copyright (c) 2013 Sindre Sorhus, contributors
- * Licensed under the MIT license.
- */
- 'use strict';
- var path = require('path');
- var dargs = require('dargs');
- var numCPUs = require('os').cpus().length || 1;
- var async = require('async');
- var chalk = require('chalk');
- var spawn = require('win-spawn');
- var which = require('which');
-
- module.exports = function (grunt) {
- var bannerCallback = function (filename, banner) {
- grunt.verbose.writeln('Writing CSS banner for ' + filename);
- grunt.file.write(filename, banner + grunt.util.linefeed + grunt.file.read(filename));
- };
-
- var checkBinary = function (cmd, errMess) {
- try {
- which.sync(cmd);
- } catch (err) {
- return grunt.warn(
- '\n' + errMess + '\n' +
- 'More info: https://github.com/gruntjs/grunt-contrib-sass\n'
- );
- }
- };
-
- var checkFiles = function (files, options, cb) {
- var failCount = 0;
- var filesToCheck = files.filter(function (src) {
- return path.basename(src)[0] !== '_' && grunt.file.exists(src);
- });
-
- async.eachLimit(filesToCheck, numCPUs, function (src, next) {
- var bin;
- var args;
-
- if (options.bundleExec) {
- bin = 'bundle';
- args = ['exec', 'sass', '--check', src];
- } else {
- bin = 'sass';
- args = ['--check', src];
- }
-
- grunt.verbose.writeln('Command: ' + bin + ' ' + args.join(' '));
-
- grunt.verbose.writeln('Checking file ' + chalk.cyan(src) + ' syntax.');
- spawn(bin, args, { stdio: 'inherit' })
- .on('error', grunt.warn)
- .on('close', function (code) {
- if (code > 0) {
- failCount++;
- grunt.log.error('Checking file ' + chalk.cyan(src) + ' - ' + chalk.red('failed') + '.');
- } else {
- grunt.verbose.ok('Checking file ' + chalk.cyan(src) + ' - ' + chalk.green('passed') + '.');
- }
-
- next();
- });
- }, function () {
- if (failCount > 0) {
- grunt.warn('Sass check failed for ' + failCount + ' files.');
- } else {
- grunt.log.ok('All ' + chalk.cyan(filesToCheck.length) + ' files passed.');
- }
-
- cb();
- });
- };
-
- grunt.registerMultiTask('sass', 'Compile Sass to CSS', function () {
- var cb = this.async();
- var options = this.options();
- var bundleExec = options.bundleExec;
- var banner;
- var passedArgs;
-
- if (bundleExec) {
- checkBinary('bundle',
- 'bundleExec options set but no Bundler executable found in your PATH.'
- );
- } else {
- checkBinary('sass',
- 'You need to have Ruby and Sass installed and in your PATH for this task to work.'
- );
- }
-
- if (options.check) {
- checkFiles(this.filesSrc, options, cb);
- return;
- }
-
- // Unset banner option if set
- if (options.banner) {
- banner = options.banner;
- delete options.banner;
- }
-
- passedArgs = dargs(options, ['bundleExec']);
-
- async.eachLimit(this.files, numCPUs, function (file, next) {
- var src = file.src[0];
-
- if (typeof src !== 'string') {
- src = file.orig.src[0];
- }
-
- if (!grunt.file.exists(src)) {
- grunt.log.warn('Source file "' + src + '" not found.');
- return next();
- }
-
- if (path.basename(src)[0] === '_') {
- return next();
- }
-
- var args = [
- src,
- file.dest
- ].concat(passedArgs);
-
- if (options.update) {
- // When the source file hasn't yet been compiled SASS will write an empty file.
- // If this is the first time the file has been written we treat it as a if update was not passed
- if (!grunt.file.exists(file.dest)) {
- // Find where the --update flag is and remove it.
- var index = args.indexOf('--update');
- args.splice(index, 1);
- } else {
- // The first two elements in args is our source and destination files,
- // we use those values to build a path that SASS recognizes namely: source:destination
- var sassPath = args.shift() + ':' + args.shift();
- args.push(sassPath);
- }
- }
-
- var bin = 'sass';
-
- if (bundleExec) {
- bin = 'bundle';
- args.unshift('exec', 'sass');
- }
-
- // If we're compiling scss or css files
- if (path.extname(src) === '.css') {
- args.push('--scss');
- }
-
- // Make sure grunt creates the destination folders if they don't exist
- if (!grunt.file.exists(file.dest)) {
- grunt.file.write(file.dest, '');
- }
-
- grunt.verbose.writeln('Command: ' + bin + ' ' + args.join(' '));
-
- var cp = spawn(bin, args, {stdio: 'inherit'});
-
- cp.on('error', function (err) {
- grunt.warn(err);
- });
-
- cp.on('close', function (code) {
- if (code > 0) {
- return grunt.warn('Exited with error code ' + code);
- }
-
- // Callback to insert banner
- if (banner) {
- bannerCallback(file.dest, banner);
- }
-
- grunt.verbose.writeln('File ' + chalk.cyan(file.dest) + ' created.');
- next();
- });
- }, cb);
- });
- };
|