Gruntfile.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. 'use strict';
  2. var fs = require('fs');
  3. module.exports = function (grunt) {
  4. // Report the elapsed execution time of tasks.
  5. require('time-grunt')(grunt);
  6. var COMPRESS_FOR_TESTS = true;
  7. // Project configuration.
  8. grunt.initConfig({
  9. // Metadata required for build.
  10. build: grunt.file.readYAML('build/build.yml'),
  11. pkg: grunt.file.readJSON('package.json'),
  12. meta: {
  13. license: '<%= _.pluck(pkg.licenses, "type").join(", ") %>',
  14. copyright: 'Copyright (c) 2009-<%= grunt.template.today("yyyy") %>',
  15. banner: '/*!\n' +
  16. ' * Less - <%= pkg.description %> v<%= pkg.version %>\n' +
  17. ' * http://lesscss.org\n' +
  18. ' *\n' +
  19. ' * <%= meta.copyright %>, <%= pkg.author.name %> <<%= pkg.author.email %>>\n' +
  20. ' * Licensed under the <%= meta.license %> License.\n' +
  21. ' *\n' +
  22. ' */\n\n' +
  23. ' /**' +
  24. ' * @license <%= meta.license %>\n' +
  25. ' */\n\n'
  26. },
  27. shell: {
  28. options: {stdout: true, failOnError: true},
  29. test: {
  30. command: 'node test'
  31. },
  32. benchmark: {
  33. command: 'node benchmark/less-benchmark.js'
  34. },
  35. "sourcemap-test": {
  36. command: [
  37. 'node bin/lessc --source-map=test/sourcemaps/maps/import-map.map test/less/import.less test/sourcemaps/import.css',
  38. 'node bin/lessc --source-map test/less/sourcemaps/basic.less test/sourcemaps/basic.css'
  39. ].join('&&')
  40. }
  41. },
  42. browserify: {
  43. browser: {
  44. src: ['./lib/less-browser/bootstrap.js'],
  45. options: {
  46. exclude: ["promise"],
  47. require: ["promise/polyfill.js"],
  48. browserifyOptions: {
  49. standalone: 'less'
  50. }
  51. },
  52. dest: 'tmp/less.js'
  53. }
  54. },
  55. concat: {
  56. options: {
  57. stripBanners: 'all',
  58. banner: '<%= meta.banner %>'
  59. },
  60. browsertest: {
  61. src: COMPRESS_FOR_TESTS ? '<%= uglify.test.dest %>' : '<%= browserify.browser.dest %>',
  62. dest: 'test/browser/less.js'
  63. },
  64. dist: {
  65. src: '<%= browserify.browser.dest %>',
  66. dest: 'dist/less.js'
  67. },
  68. // Rhino
  69. rhino: {
  70. options: {
  71. banner: '/* Less.js v<%= pkg.version %> RHINO | <%= meta.copyright %>, <%= pkg.author.name %> <<%= pkg.author.email %>> */\n\n',
  72. footer: '' // override task-level footer
  73. },
  74. src: ['<%= build.rhino %>'],
  75. dest: 'dist/less-rhino.js'
  76. },
  77. // lessc for Rhino
  78. rhinolessc: {
  79. options: {
  80. banner: '/* Less.js v<%= pkg.version %> RHINO | <%= meta.copyright %>, <%= pkg.author.name %> <<%= pkg.author.email %>> */\n\n',
  81. footer: '' // override task-level footer
  82. },
  83. src: ['<%= build.rhinolessc %>'],
  84. dest: 'dist/lessc-rhino.js'
  85. }
  86. },
  87. uglify: {
  88. options: {
  89. banner: '<%= meta.banner %>',
  90. mangle: true,
  91. compress: {
  92. pure_getters: true
  93. }
  94. },
  95. dist: {
  96. src: ['<%= concat.dist.dest %>'],
  97. dest: 'dist/less.min.js'
  98. },
  99. test: {
  100. src: '<%= browserify.browser.dest %>',
  101. dest: 'tmp/less.min.js'
  102. }
  103. },
  104. jshint: {
  105. options: {jshintrc: '.jshintrc'},
  106. files: {
  107. src: [
  108. 'Gruntfile.js',
  109. 'lib/less/**/*.js',
  110. 'lib/less-node/**/*.js',
  111. 'lib/less-browser/**/*.js',
  112. 'lib/less-rhino/**/*.js',
  113. 'bin/lessc'
  114. ]
  115. }
  116. },
  117. jscs: {
  118. src: ["test/**/*.js", "lib/less*/**/*.js", "bin/lessc"],
  119. options: {
  120. config: ".jscsrc"
  121. }
  122. },
  123. connect: {
  124. server: {
  125. options: {
  126. port: 8081
  127. }
  128. }
  129. },
  130. jasmine: {
  131. options: {
  132. keepRunner: true,
  133. host: 'http://localhost:8081/',
  134. vendor: ['test/browser/jasmine-jsreporter.js', 'test/browser/common.js', 'test/browser/less.js'],
  135. template: 'test/browser/test-runner-template.tmpl'
  136. },
  137. main: {
  138. // src is used to build list of less files to compile
  139. src: ['test/less/*.less', '!test/less/javascript.less', '!test/less/urls.less', '!test/less/empty.less'],
  140. options: {
  141. helpers: 'test/browser/runner-main-options.js',
  142. specs: 'test/browser/runner-main-spec.js',
  143. outfile: 'tmp/browser/test-runner-main.html'
  144. }
  145. },
  146. legacy: {
  147. src: ['test/less/legacy/*.less'],
  148. options: {
  149. helpers: 'test/browser/runner-legacy-options.js',
  150. specs: 'test/browser/runner-legacy-spec.js',
  151. outfile: 'tmp/browser/test-runner-legacy.html'
  152. }
  153. },
  154. strictUnits: {
  155. src: ['test/less/strict-units/*.less'],
  156. options: {
  157. helpers: 'test/browser/runner-strict-units-options.js',
  158. specs: 'test/browser/runner-strict-units-spec.js',
  159. outfile: 'tmp/browser/test-runner-strict-units.html'
  160. }
  161. },
  162. errors: {
  163. src: ['test/less/errors/*.less', '!test/less/errors/javascript-error.less'],
  164. options: {
  165. timeout: 20000,
  166. helpers: 'test/browser/runner-errors-options.js',
  167. specs: 'test/browser/runner-errors-spec.js',
  168. outfile: 'tmp/browser/test-runner-errors.html'
  169. }
  170. },
  171. noJsErrors: {
  172. src: ['test/less/no-js-errors/*.less'],
  173. options: {
  174. helpers: 'test/browser/runner-no-js-errors-options.js',
  175. specs: 'test/browser/runner-no-js-errors-spec.js',
  176. outfile: 'tmp/browser/test-runner-no-js-errors.html'
  177. }
  178. },
  179. browser: {
  180. src: ['test/browser/less/*.less'],
  181. options: {
  182. helpers: 'test/browser/runner-browser-options.js',
  183. specs: 'test/browser/runner-browser-spec.js',
  184. outfile: 'tmp/browser/test-runner-browser.html'
  185. }
  186. },
  187. relativeUrls: {
  188. src: ['test/browser/less/relative-urls/*.less'],
  189. options: {
  190. helpers: 'test/browser/runner-relative-urls-options.js',
  191. specs: 'test/browser/runner-relative-urls-spec.js',
  192. outfile: 'tmp/browser/test-runner-relative-urls.html'
  193. }
  194. },
  195. rootpath: {
  196. src: ['test/browser/less/rootpath/*.less'],
  197. options: {
  198. helpers: 'test/browser/runner-rootpath-options.js',
  199. specs: 'test/browser/runner-rootpath-spec.js',
  200. outfile: 'tmp/browser/test-runner-rootpath.html'
  201. }
  202. },
  203. rootpathRelative: {
  204. src: ['test/browser/less/rootpath-relative/*.less'],
  205. options: {
  206. helpers: 'test/browser/runner-rootpath-relative-options.js',
  207. specs: 'test/browser/runner-rootpath-relative-spec.js',
  208. outfile: 'tmp/browser/test-runner-rootpath-relative.html'
  209. }
  210. },
  211. production: {
  212. src: ['test/browser/less/production/*.less'],
  213. options: {
  214. helpers: 'test/browser/runner-production-options.js',
  215. specs: 'test/browser/runner-production-spec.js',
  216. outfile: 'tmp/browser/test-runner-production.html'
  217. }
  218. },
  219. modifyVars: {
  220. src: ['test/browser/less/modify-vars/*.less'],
  221. options: {
  222. helpers: 'test/browser/runner-modify-vars-options.js',
  223. specs: 'test/browser/runner-modify-vars-spec.js',
  224. outfile: 'tmp/browser/test-runner-modify-vars.html'
  225. }
  226. },
  227. globalVars: {
  228. src: ['test/browser/less/global-vars/*.less'],
  229. options: {
  230. helpers: 'test/browser/runner-global-vars-options.js',
  231. specs: 'test/browser/runner-global-vars-spec.js',
  232. outfile: 'tmp/browser/test-runner-global-vars.html'
  233. }
  234. },
  235. postProcessor: {
  236. src: ['test/browser/less/postProcessor/*.less'],
  237. options: {
  238. helpers: 'test/browser/runner-postProcessor-options.js',
  239. specs: 'test/browser/runner-postProcessor.js',
  240. outfile: 'tmp/browser/test-runner-post-processor.html'
  241. }
  242. }
  243. },
  244. 'saucelabs-jasmine': {
  245. all: {
  246. options: {
  247. urls: ["post-processor", "global-vars", "modify-vars", "production", "rootpath-relative",
  248. "rootpath", "relative-urls", "browser", "no-js-errors", "legacy", "strict-units"
  249. ].map(function(testName) {
  250. return "http://localhost:8081/tmp/browser/test-runner-" + testName + ".html";
  251. }),
  252. testname: 'Sauce Unit Test for less.js',
  253. browsers: [{
  254. browserName: "chrome",
  255. version: '',
  256. platform: 'Windows 8'
  257. },
  258. {
  259. browserName: "firefox",
  260. version: '33',
  261. platform: 'Linux'
  262. },
  263. {
  264. browserName: "iPad",
  265. version: '8.0',
  266. platform: 'OS X 10.9',
  267. 'device-orientation': 'portrait'
  268. },
  269. {
  270. browserName: "internet explorer",
  271. version: '8',
  272. platform: 'Windows XP'
  273. },
  274. {
  275. browserName: "internet explorer",
  276. version: '9',
  277. platform: 'Windows 7'
  278. },
  279. {
  280. browserName: "internet explorer",
  281. version: '10',
  282. platform: 'Windows 7'
  283. },
  284. {
  285. browserName: "internet explorer",
  286. version: '11',
  287. platform: 'Windows 8.1'
  288. }],
  289. sauceConfig: {
  290. 'record-video': process.env.TRAVIS_BRANCH !== "master",
  291. 'record-screenshots': process.env.TRAVIS_BRANCH !== "master",
  292. 'idle-timeout': 100, 'max-duration': 120,
  293. build: process.env.TRAVIS_BRANCH === "master" ? process.env.TRAVIS_JOB_ID : undefined,
  294. tags: [process.env.TRAVIS_BUILD_NUMBER, process.env.TRAVIS_PULL_REQUEST, process.env.TRAVIS_BRANCH]
  295. },
  296. throttled: 3
  297. }
  298. }
  299. },
  300. // Clean the version of less built for the tests
  301. clean: {
  302. test: ['test/browser/less.js', 'tmp', 'test/less-bom'],
  303. "sourcemap-test": ['test/sourcemaps/*.css', 'test/sourcemaps/*.map'],
  304. sauce_log: ["sc_*.log"]
  305. }
  306. });
  307. // Load these plugins to provide the necessary tasks
  308. require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
  309. // Actually load this plugin's task(s).
  310. grunt.loadTasks('build/tasks');
  311. // by default, run tests
  312. grunt.registerTask('default', [
  313. 'test'
  314. ]);
  315. grunt.registerTask('updateBowerJson', function () {
  316. var bowerJson = require('./bower.json');
  317. bowerJson.version = grunt.config('pkg.version');
  318. fs.writeFileSync('./bower.json', JSON.stringify(bowerJson, null, 2));
  319. });
  320. // Release
  321. grunt.registerTask('dist', [
  322. 'browserify:browser',
  323. 'concat:dist',
  324. 'uglify:dist',
  325. 'updateBowerJson'
  326. ]);
  327. // Release Rhino Version
  328. grunt.registerTask('rhino', [
  329. 'browserify:rhino',
  330. 'concat:rhino',
  331. 'concat:rhinolessc'
  332. ]);
  333. // Create the browser version of less.js
  334. grunt.registerTask('browsertest-lessjs', [
  335. 'browserify:browser',
  336. 'uglify:test',
  337. 'concat:browsertest'
  338. ]);
  339. // Run all browser tests
  340. grunt.registerTask('browsertest', [
  341. 'browsertest-lessjs',
  342. 'connect',
  343. 'jasmine'
  344. ]);
  345. // setup a web server to run the browser tests in a browser rather than phantom
  346. grunt.registerTask('browsertest-server', [
  347. 'browsertest-lessjs',
  348. 'jasmine::build',
  349. 'connect::keepalive'
  350. ]);
  351. var previous_force_state = grunt.option("force");
  352. grunt.registerTask("force",function(set) {
  353. if (set === "on") {
  354. grunt.option("force",true);
  355. }
  356. else if (set === "off") {
  357. grunt.option("force",false);
  358. }
  359. else if (set === "restore") {
  360. grunt.option("force",previous_force_state);
  361. }
  362. });
  363. grunt.registerTask('sauce', [
  364. 'browsertest-lessjs',
  365. 'jasmine::build',
  366. 'connect',
  367. 'sauce-after-setup'
  368. ]);
  369. // setup a web server to run the browser tests in a browser rather than phantom
  370. grunt.registerTask('sauce-after-setup', [
  371. 'saucelabs-jasmine',
  372. 'clean:sauce_log'
  373. ]);
  374. var testTasks = [
  375. 'clean',
  376. 'jshint',
  377. 'jscs',
  378. 'shell:test',
  379. 'browsertest'
  380. ];
  381. if (isNaN(Number(process.env.TRAVIS_PULL_REQUEST, 10)) &&
  382. Number(process.env.TRAVIS_NODE_VERSION) === 0.11 &&
  383. (process.env.TRAVIS_BRANCH === "master" || process.env.TRAVIS_BRANCH === "sauce")) {
  384. testTasks.push("force:on");
  385. testTasks.push("sauce-after-setup");
  386. testTasks.push("force:off");
  387. }
  388. // Run all tests
  389. grunt.registerTask('test', testTasks);
  390. // generate a good test environment for testing sourcemaps
  391. grunt.registerTask('sourcemap-test', [
  392. 'clean:sourcemap-test',
  393. 'shell:sourcemap-test',
  394. 'connect::keepalive'
  395. ]);
  396. // Run benchmark
  397. grunt.registerTask('benchmark', [
  398. 'shell:benchmark'
  399. ]);
  400. };