sass.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * grunt-contrib-sass
  3. * http://gruntjs.com/
  4. *
  5. * Copyright (c) 2013 Sindre Sorhus, contributors
  6. * Licensed under the MIT license.
  7. */
  8. 'use strict';
  9. var path = require('path');
  10. var dargs = require('dargs');
  11. var numCPUs = require('os').cpus().length || 1;
  12. var async = require('async');
  13. var chalk = require('chalk');
  14. var spawn = require('win-spawn');
  15. var which = require('which');
  16. module.exports = function (grunt) {
  17. var bannerCallback = function (filename, banner) {
  18. grunt.verbose.writeln('Writing CSS banner for ' + filename);
  19. grunt.file.write(filename, banner + grunt.util.linefeed + grunt.file.read(filename));
  20. };
  21. var checkBinary = function (cmd, errMess) {
  22. try {
  23. which.sync(cmd);
  24. } catch (err) {
  25. return grunt.warn(
  26. '\n' + errMess + '\n' +
  27. 'More info: https://github.com/gruntjs/grunt-contrib-sass\n'
  28. );
  29. }
  30. };
  31. grunt.registerMultiTask('sass', 'Compile Sass to CSS', function () {
  32. var cb = this.async();
  33. var options = this.options();
  34. var bundleExec = options.bundleExec;
  35. var banner;
  36. var passedArgs;
  37. if (bundleExec) {
  38. checkBinary('bundle',
  39. 'bundleExec options set but no Bundler executable found in your PATH.'
  40. );
  41. } else {
  42. checkBinary('sass',
  43. 'You need to have Ruby and Sass installed and in your PATH for this task to work.'
  44. );
  45. }
  46. // Unset banner option if set
  47. if (options.banner) {
  48. banner = options.banner;
  49. delete options.banner;
  50. }
  51. passedArgs = dargs(options, ['bundleExec']);
  52. async.eachLimit(this.files, numCPUs, function (file, next) {
  53. var src = file.src[0];
  54. if (typeof src !== 'string') {
  55. src = file.orig.src[0];
  56. }
  57. if (!grunt.file.exists(src)) {
  58. grunt.log.warn('Source file "' + src + '" not found.');
  59. return next();
  60. }
  61. if (path.basename(src)[0] === '_') {
  62. return next();
  63. }
  64. var args = [
  65. src,
  66. file.dest
  67. ].concat(passedArgs);
  68. var bin = 'sass';
  69. if (bundleExec) {
  70. bin = 'bundle';
  71. args.unshift('exec', 'sass');
  72. }
  73. // If we're compiling scss or css files
  74. if (path.extname(src) === '.css') {
  75. args.push('--scss');
  76. }
  77. // Make sure grunt creates the destination folders if they don't exist
  78. if(!grunt.file.exists(file.dest)) {
  79. grunt.file.write(file.dest, '');
  80. }
  81. grunt.verbose.writeln('Command: ' + bin + ' ' + args.join(' '));
  82. var cp = spawn(bin, args, {stdio: 'inherit'});
  83. cp.on('error', function (err) {
  84. grunt.warn(err);
  85. });
  86. cp.on('close', function (code) {
  87. if (code > 0) {
  88. return grunt.warn('Exited with error code ' + code);
  89. }
  90. // Callback to insert banner
  91. if (banner) {
  92. bannerCallback(file.dest, banner);
  93. }
  94. grunt.verbose.writeln('File ' + chalk.cyan(file.dest) + ' created.');
  95. next();
  96. });
  97. }, cb);
  98. });
  99. };