compile.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. var pkg = require('../package');
  2. module.exports = function (grunt) {
  3. 'use strict';
  4. var dev = !!grunt.option('dev');
  5. var path, cssPath, libraries, librariesCache, librariesPath, versions, latestVersion;
  6. // Helper function for falling back to a Bootstrap variables file.
  7. var resolveVariables = function (file, backup) {
  8. if (backup === true) grunt.verbose.write('Checking for backup variables file...');
  9. if (!grunt.file.exists(path.join(librariesPath, file))) {
  10. if (backup === true) grunt.verbose.warn();
  11. grunt.verbose.writeln("Missing " + file);
  12. file = false;
  13. if (backup && backup !== true) {
  14. file = resolveVariables(backup, true);
  15. if (file) grunt.verbose.writeln("Using: " + file);
  16. }
  17. return file;
  18. }
  19. else if (backup === true) grunt.verbose.ok();
  20. return file;
  21. };
  22. // Register the "compile" task.
  23. grunt.registerTask('compile', 'Compiles the Drupal/Bootstrap override CSS files for the base theme.', function () {
  24. var cwd = process.cwd();
  25. path = require('path');
  26. cssPath = path.join(cwd, pkg.paths.css);
  27. librariesCache = path.join(cwd, pkg.caches.libraries);
  28. librariesPath = path.join(cwd, pkg.paths.libraries);
  29. if (!grunt.file.exists(librariesCache) || !grunt.file.isDir(librariesPath)) {
  30. return grunt.fail.fatal('No libraries detected. Please run `grunt sync`.');
  31. }
  32. libraries = grunt.file.readJSON(librariesCache);
  33. if (!libraries.bootstrap || !libraries.bootswatch) {
  34. return grunt.fail.fatal('Invalid libraries cache. Please run `grunt sync`.');
  35. }
  36. versions = Object.keys(libraries.bootstrap);
  37. latestVersion = [].concat(versions).pop();
  38. grunt.config.set('latestVersion', latestVersion);
  39. // Register a private sub-task. Doing this inside the main task prevents
  40. // this private sub-task from being executed directly and also prevents it
  41. // from showing up on the list of available tasks on --help.
  42. grunt.registerTask('compile:overrides', function () {
  43. var done = this.async();
  44. var total = {count: 0};
  45. var less = require('less');
  46. var LessPluginAutoPrefix = require('less-plugin-autoprefix');
  47. var LessPluginCleanCSS = require('less-plugin-clean-css');
  48. var lessPlugins = [
  49. new LessPluginCleanCSS({
  50. advanced: true
  51. }),
  52. new LessPluginAutoPrefix({
  53. browsers: [
  54. "Android 2.3",
  55. "Android >= 4",
  56. "Chrome >= 20",
  57. "Firefox >= 24",
  58. "Explorer >= 8",
  59. "iOS >= 6",
  60. "Opera >= 12",
  61. "Safari >= 6"
  62. ],
  63. map: true
  64. })
  65. ];
  66. var queue = require('queue')({concurrency: 1, timeout: 60000});
  67. // Iterate over libraries.
  68. for (var library in libraries) {
  69. if (!libraries.hasOwnProperty(library) || (dev && library !== 'bootstrap')) continue;
  70. // Iterate over versions.
  71. for (var version in libraries[library]) {
  72. if (!libraries[library].hasOwnProperty(version) || (dev && version !== latestVersion)) continue;
  73. // Iterate over themes.
  74. for (var i = 0; i < libraries[library][version].length; i++) {
  75. // Queue LESS compilations.
  76. (function (library, versions, version, theme, total) {
  77. queue.push(function (done) {
  78. var lessPaths = [path.join(librariesPath)];
  79. var latestVersion = [].concat(versions).pop();
  80. var latestVariables = path.join(latestVersion, 'bootstrap', 'less', 'variables.less');
  81. var themeVariables = path.join(version, library, (library === 'bootstrap' ? 'less' : theme), 'variables.less');
  82. var backupVariables = path.join(version, 'bootstrap', 'less', 'variables.less');
  83. var fileName = (library === 'bootstrap' ? 'overrides.min.css' : 'overrides-' + theme + '.min.css');
  84. var outputFile = path.join(cssPath, version, fileName);
  85. // Resolve the variable files.
  86. latestVariables = resolveVariables(latestVariables);
  87. if (!latestVariables) return done(false);
  88. themeVariables = resolveVariables(themeVariables, backupVariables);
  89. if (!themeVariables) return grunt.fail.fatal("Unable to create: " + outputFile);
  90. var options = {
  91. filename: outputFile,
  92. paths: lessPaths,
  93. plugins: lessPlugins
  94. };
  95. var imports = [
  96. // First, import the latest bootstrap (missing variables).
  97. '@import "' + latestVariables + '"',
  98. // Then, override variables with theme.
  99. '@import "' + themeVariables + '"',
  100. // Finally, import the base-theme overrides.
  101. '@import "' + path.join('starterkits', 'less', 'less', 'overrides.less') + '"'
  102. ];
  103. grunt.log.debug("\noptions: " + JSON.stringify(options, null, 2));
  104. grunt.log.debug(imports.join("\n"));
  105. less.render(imports.join(';') + ';', options)
  106. .then(function (output) {
  107. total.count++;
  108. grunt.log.writeln('Compiled '.green + path.join(version, fileName).white.bold);
  109. grunt.file.write(outputFile, output.css);
  110. done();
  111. }, function (e) {
  112. if (e.type === 'Parse') {
  113. grunt.log.error("File:\t".red + e.filename.red);
  114. grunt.log.error("Line:\t".red + [e.line, e.column].join(':').red);
  115. grunt.log.error("Code:\t".red + e.extract.join('').white.bold);
  116. grunt.log.writeln();
  117. }
  118. return grunt.fail.fatal(e);
  119. })
  120. ;
  121. });
  122. })(library, Object.keys(libraries[library]), version, libraries[library][version][i], total);
  123. }
  124. }
  125. }
  126. // Start LESS compilations queues.
  127. queue.start(function (e) {
  128. // Report how many files were compiled.
  129. grunt.log.ok(grunt.util.pluralize(total.count, '1 file compiled./' + total.count + ' files compiled.'));
  130. return done(e);
  131. });
  132. });
  133. // Run necessary sub-tasks.
  134. var subtask = (dev ? 'dev' : 'css');
  135. grunt.task.run([
  136. 'clean:' + subtask,
  137. 'compile:overrides'
  138. ]);
  139. });
  140. }