You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
3.1 KiB

  1. /*
  2. * grunt-contrib-less
  3. * http://gruntjs.com/
  4. *
  5. * Copyright (c) 2012 Tyler Kellen, contributors
  6. * Licensed under the MIT license.
  7. */
  8. 'use strict';
  9. module.exports = function(grunt) {
  10. var path = require('path');
  11. var less = require('less');
  12. var lessOptions = {
  13. parse: ['paths', 'optimization', 'filename', 'strictImports', 'dumpLineNumbers'],
  14. render: ['compress', 'yuicompress']
  15. };
  16. grunt.registerMultiTask('less', 'Compile LESS files to CSS', function() {
  17. var done = this.async();
  18. var options = this.options();
  19. grunt.verbose.writeflags(options, 'Options');
  20. if (this.files.length < 1) {
  21. grunt.log.warn('Destination not written because no source files were provided.');
  22. }
  23. grunt.util.async.forEachSeries(this.files, function(f, nextFileObj) {
  24. var destFile = f.dest;
  25. var files = f.src.filter(function(filepath) {
  26. // Warn on and remove invalid source files (if nonull was set).
  27. if (!grunt.file.exists(filepath)) {
  28. grunt.log.warn('Source file "' + filepath + '" not found.');
  29. return false;
  30. } else {
  31. return true;
  32. }
  33. });
  34. if (files.length === 0) {
  35. if (f.src.length < 1) {
  36. grunt.log.warn('Destination not written because no source files were found.');
  37. }
  38. // No src files, goto next target. Warn would have been issued above.
  39. return nextFileObj();
  40. }
  41. var compiled = [];
  42. grunt.util.async.concatSeries(files, function(file, next) {
  43. compileLess(file, options, function(css, err) {
  44. if (!err) {
  45. compiled.push(css);
  46. next();
  47. } else {
  48. nextFileObj(err);
  49. }
  50. });
  51. }, function() {
  52. if (compiled.length < 1) {
  53. grunt.log.warn('Destination not written because compiled files were empty.');
  54. } else {
  55. grunt.file.write(destFile, compiled.join(grunt.util.normalizelf(grunt.util.linefeed)));
  56. grunt.log.writeln('File ' + destFile.cyan + ' created.');
  57. }
  58. nextFileObj();
  59. });
  60. }, done);
  61. });
  62. var compileLess = function(srcFile, options, callback) {
  63. options = grunt.util._.extend({filename: srcFile}, options);
  64. options.paths = options.paths || [path.dirname(srcFile)];
  65. var css;
  66. var srcCode = grunt.file.read(srcFile);
  67. var parser = new less.Parser(grunt.util._.pick(options, lessOptions.parse));
  68. parser.parse(srcCode, function(parse_err, tree) {
  69. if (parse_err) {
  70. lessError(parse_err);
  71. callback('',true);
  72. }
  73. try {
  74. css = tree.toCSS(grunt.util._.pick(options, lessOptions.render));
  75. callback(css, null);
  76. } catch (e) {
  77. lessError(e);
  78. callback(css, true);
  79. }
  80. });
  81. };
  82. var formatLessError = function(e) {
  83. var pos = '[' + 'L' + e.line + ':' + ('C' + e.column) + ']';
  84. return e.filename + ': ' + pos + ' ' + e.message;
  85. };
  86. var lessError = function(e) {
  87. var message = less.formatError ? less.formatError(e) : formatLessError(e);
  88. grunt.log.error(message);
  89. grunt.fail.warn('Error compiling LESS.');
  90. };
  91. };