Gruntfile.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. module.exports = function(grunt) {
  2. var _ = require('underscore');
  3. // Load required NPM tasks.
  4. // You must first run `npm install` in the project's root directory to get these dependencies.
  5. grunt.loadNpmTasks('grunt-contrib-concat');
  6. grunt.loadNpmTasks('grunt-contrib-uglify');
  7. grunt.loadNpmTasks('grunt-contrib-copy');
  8. grunt.loadNpmTasks('grunt-contrib-compress');
  9. grunt.loadNpmTasks('grunt-contrib-clean');
  10. grunt.loadNpmTasks('grunt-contrib-jshint');
  11. grunt.loadNpmTasks('grunt-contrib-cssmin');
  12. grunt.loadNpmTasks('grunt-jscs-checker');
  13. grunt.loadNpmTasks('grunt-shell');
  14. grunt.loadNpmTasks('grunt-karma');
  15. grunt.loadNpmTasks('grunt-bump');
  16. grunt.loadNpmTasks('lumbar');
  17. // This will eventually get passed to grunt.initConfig()
  18. // Initialize multitasks...
  19. var config = {
  20. concat: {},
  21. uglify: {},
  22. cssmin: {},
  23. copy: {},
  24. compress: {},
  25. shell: {},
  26. clean: {
  27. temp: 'build/temp'
  28. }
  29. };
  30. // for the "meta" template variable (<%= meta.whatever %>)
  31. config.meta = grunt.file.readJSON('fullcalendar.jquery.json');
  32. // The "grunt" command with no arguments
  33. grunt.registerTask('default', 'dist');
  34. // Builds all distributable files, for a new release possibly
  35. grunt.registerTask('dist', [
  36. 'clean',
  37. 'modules',
  38. 'languages',
  39. 'karma:single',
  40. 'archiveDist',
  41. 'cdnjsDist'
  42. ]);
  43. // Bare minimum for debugging
  44. grunt.registerTask('dev', [
  45. 'shell:assume-unchanged',
  46. 'lumbar:build',
  47. 'languages'
  48. ]);
  49. /* FullCalendar Modules
  50. ----------------------------------------------------------------------------------------------------*/
  51. grunt.registerTask('modules', 'Build the FullCalendar modules', [
  52. 'jscs:srcModules',
  53. 'clean:modules',
  54. 'lumbar:build',
  55. 'concat:moduleVariables',
  56. 'jshint:builtModules',
  57. 'uglify:modules',
  58. 'cssmin:modules'
  59. ]);
  60. // assemble modules
  61. config.lumbar = {
  62. build: {
  63. build: 'lumbar.json',
  64. output: 'dist', // a directory. lumbar doesn't like trailing slash
  65. background: false // lumbar complains otherwise
  66. },
  67. watch: {
  68. watch: 'lumbar.json',
  69. output: 'dist', // a directory. lumbar doesn't like trailing slash
  70. background: false, // lumbar complains otherwise
  71. sourceMap: true
  72. }
  73. };
  74. // replace template variables (<%= %>), IN PLACE
  75. config.concat.moduleVariables = {
  76. options: {
  77. process: true // replace
  78. },
  79. expand: true,
  80. cwd: 'dist/',
  81. src: [ '*.js', '*.css' ],
  82. dest: 'dist/'
  83. };
  84. // create minified versions of JS
  85. config.uglify.modules = {
  86. options: {
  87. preserveComments: 'some' // keep comments starting with /*!
  88. },
  89. expand: true,
  90. src: 'dist/fullcalendar.js', // only do it for fullcalendar.js
  91. ext: '.min.js'
  92. };
  93. // create minified versions of CSS
  94. config.cssmin.modules = {
  95. expand: true,
  96. src: 'dist/fullcalendar.css', // only do it for fullcalendar.css
  97. ext: '.min.css'
  98. };
  99. config.clean.modules = [
  100. 'dist/*.{js,css,map}', // maps created by lumbar sourceMap
  101. 'dist/src' // created by lumbar sourceMap
  102. ];
  103. /* Languages
  104. ----------------------------------------------------------------------------------------------------*/
  105. grunt.registerTask('languages', [
  106. 'jscs:srcLanguages',
  107. 'jshint:srcLanguages',
  108. 'clean:languages',
  109. 'generateLanguages',
  110. 'uglify:languages',
  111. 'uglify:languagesAll'
  112. ]);
  113. config.generateLanguages = {
  114. moment: grunt.file.expand('lib/moment/{locale,lang}/')[0], // lang directory is pre-moment-2.8
  115. datepicker: 'lib/jquery-ui/ui/i18n/',
  116. fullCalendar: 'lang/',
  117. dest: 'build/temp/lang/',
  118. allDest: 'build/temp/lang-all.js'
  119. };
  120. config.uglify.languages = {
  121. expand: true,
  122. cwd: 'build/temp/lang/',
  123. src: '*.js',
  124. dest: 'dist/lang/'
  125. };
  126. config.uglify.languagesAll = {
  127. src: 'build/temp/lang-all.js',
  128. dest: 'dist/lang-all.js'
  129. };
  130. config.clean.languages = [
  131. 'build/temp/lang',
  132. 'build/temp/lang-all.js',
  133. 'dist/lang',
  134. 'dist/lang-all.js'
  135. ];
  136. /* Automated Tests
  137. ----------------------------------------------------------------------------------------------------*/
  138. config.karma = {
  139. options: {
  140. configFile: 'build/karma.conf.js'
  141. },
  142. url: {}, // visit a URL in a browser
  143. headless: { browsers: [ 'PhantomJS' ] },
  144. single: { browsers: [ 'PhantomJS' ], singleRun: true, autoWatch: false }
  145. };
  146. /* Archive
  147. ----------------------------------------------------------------------------------------------------*/
  148. grunt.registerTask('archive', 'Create a distributable ZIP archive', [
  149. 'modules',
  150. 'languages',
  151. 'karma:single',
  152. 'archiveDist'
  153. ]);
  154. grunt.registerTask('archiveDist', [
  155. 'clean:archive',
  156. 'copy:archiveModules',
  157. 'copy:archiveLanguages',
  158. 'copy:archiveLanguagesAll',
  159. 'copy:archiveMoment',
  160. 'copy:archiveJQuery',
  161. 'concat:archiveJQueryUI',
  162. 'copy:archiveDemos',
  163. 'copy:archiveDemoTheme',
  164. 'copy:archiveMisc',
  165. 'compress:archive'
  166. ]);
  167. // copy FullCalendar modules into ./fullcalendar/ directory
  168. config.copy.archiveModules = {
  169. expand: true,
  170. cwd: 'dist/',
  171. src: [ '*.js', '*.css' ],
  172. dest: 'build/temp/archive/'
  173. };
  174. config.copy.archiveLanguages = {
  175. expand: true,
  176. cwd: 'dist/lang/',
  177. src: '*.js',
  178. dest: 'build/temp/archive/lang/'
  179. };
  180. config.copy.archiveLanguagesAll = {
  181. src: 'dist/lang-all.js',
  182. dest: 'build/temp/archive/lang-all.js'
  183. };
  184. config.copy.archiveMoment = {
  185. src: 'lib/moment/min/moment.min.js',
  186. dest: 'build/temp/archive/lib/moment.min.js'
  187. };
  188. config.copy.archiveJQuery = {
  189. src: 'lib/jquery/dist/jquery.min.js',
  190. dest: 'build/temp/archive/lib/jquery.min.js'
  191. };
  192. config.concat.archiveJQueryUI = {
  193. src: [
  194. 'lib/jquery-ui/ui/minified/core.min.js',
  195. 'lib/jquery-ui/ui/minified/widget.min.js',
  196. 'lib/jquery-ui/ui/minified/mouse.min.js',
  197. 'lib/jquery-ui/ui/minified/draggable.min.js'
  198. ],
  199. dest: 'build/temp/archive/lib/jquery-ui.custom.min.js'
  200. };
  201. // copy demo files into ./demos/ directory
  202. config.copy.archiveDemos = {
  203. options: {
  204. processContent: function(content) {
  205. content = content.replace(/((?:src|href)=['"])([^'"]*)(['"])/g, function(m0, m1, m2, m3) {
  206. return m1 + transformDemoPath(m2) + m3;
  207. });
  208. return content;
  209. }
  210. },
  211. src: 'demos/**',
  212. dest: 'build/temp/archive/'
  213. };
  214. // copy the "cupertino" jquery-ui theme into the demo directory (for demos/theme.html)
  215. config.copy.archiveDemoTheme = {
  216. expand: true,
  217. cwd: 'lib/jquery-ui/themes/cupertino/',
  218. src: [ 'jquery-ui.min.css', 'images/*' ],
  219. dest: 'build/temp/archive/lib/cupertino/'
  220. };
  221. // in demo HTML, rewrites paths to work in the archive
  222. function transformDemoPath(path) {
  223. path = path.replace('../lib/moment/moment.js', '../lib/moment.min.js');
  224. path = path.replace('../lib/jquery/dist/jquery.js', '../lib/jquery.min.js');
  225. path = path.replace('../lib/jquery-ui/jquery-ui.js', '../lib/jquery-ui.custom.min.js');
  226. path = path.replace('../lib/jquery-ui/themes/cupertino/', '../lib/cupertino/');
  227. path = path.replace('../dist/', '../');
  228. path = path.replace('/fullcalendar.js', '/fullcalendar.min.js');
  229. return path;
  230. }
  231. // copy license and changelog
  232. config.copy.archiveMisc = {
  233. files: {
  234. 'build/temp/archive/license.txt': 'license.txt',
  235. 'build/temp/archive/changelog.txt': 'changelog.md'
  236. }
  237. };
  238. // create the ZIP
  239. config.compress.archive = {
  240. options: {
  241. archive: 'dist/<%= meta.name %>-<%= meta.version %>.zip'
  242. },
  243. expand: true,
  244. cwd: 'build/temp/archive/',
  245. src: '**',
  246. dest: '<%= meta.name %>-<%= meta.version %>/' // have a top-level directory in the ZIP file
  247. };
  248. config.clean.archive = [
  249. 'build/temp/archive',
  250. 'dist/*.zip'
  251. ];
  252. /* Release Utilities
  253. ----------------------------------------------------------------------------------------------------*/
  254. config.bump = { // changes the version number in the configs
  255. options: {
  256. files: [
  257. 'package.json',
  258. 'bower.json',
  259. 'fullcalendar.jquery.json'
  260. ],
  261. commit: false,
  262. createTag: false,
  263. push: false
  264. }
  265. };
  266. /* CDNJS (http://cdnjs.com/)
  267. ----------------------------------------------------------------------------------------------------*/
  268. grunt.registerTask('cdnjs', 'Build files for CDNJS\'s hosted version of FullCalendar', [
  269. 'modules',
  270. 'languages',
  271. 'karma:single',
  272. 'cdnjsDist'
  273. ]);
  274. grunt.registerTask('cdnjsDist', [
  275. 'clean:cdnjs',
  276. 'copy:cdnjsModules',
  277. 'copy:cdnjsLanguages',
  278. 'copy:cdnjsLanguagesAll',
  279. 'cdnjsConfig'
  280. ]);
  281. config.copy.cdnjsModules = {
  282. expand: true,
  283. cwd: 'dist/',
  284. src: [ '*.js', '*.css' ],
  285. dest: 'dist/cdnjs/<%= meta.version %>/'
  286. };
  287. config.copy.cdnjsLanguages = {
  288. expand: true,
  289. cwd: 'dist/lang/',
  290. src: '*.js',
  291. dest: 'dist/cdnjs/<%= meta.version %>/lang/'
  292. };
  293. config.copy.cdnjsLanguagesAll = {
  294. src: 'dist/lang-all.js',
  295. dest: 'dist/cdnjs/<%= meta.version %>/lang-all.js'
  296. };
  297. grunt.registerTask('cdnjsConfig', function() {
  298. var jqueryConfig = grunt.file.readJSON('fullcalendar.jquery.json');
  299. var cdnjsConfig = grunt.file.readJSON('build/cdnjs.json');
  300. grunt.file.write(
  301. 'dist/cdnjs/package.json',
  302. JSON.stringify(
  303. _.extend({}, jqueryConfig, cdnjsConfig), // combine 2 configs
  304. null, // replace
  305. 2 // indent
  306. )
  307. );
  308. });
  309. config.clean.cdnjs = 'dist/cdnjs';
  310. /* Linting and Code Style Checking
  311. ----------------------------------------------------------------------------------------------------*/
  312. grunt.registerTask('check', 'Lint and check code style', [
  313. 'jscs',
  314. 'jshint:srcModules', // so we can fix most quality errors in their original files
  315. 'lumbar:build',
  316. 'jshint' // will run srcModules again but oh well
  317. ]);
  318. // configs located elsewhere
  319. config.jshint = require('./build/jshint.conf');
  320. config.jscs = require('./build/jscs.conf');
  321. /* dist & git hacks
  322. ----------------------------------------------------------------------------------------------------
  323. // These shell commands are used to force/unforce git from thinking that files have changed.
  324. // Used to ignore changes when dist files are overwritten, but not committed, during development.
  325. */
  326. config.shell['assume-unchanged'] = {
  327. command: 'git update-index --assume-unchanged `git ls-files dist`'
  328. };
  329. config.shell['no-assume-unchanged'] = {
  330. command: 'git update-index --no-assume-unchanged `git ls-files dist`'
  331. };
  332. config.shell['list-assume-unchanged'] = {
  333. command: 'git ls-files -v | grep \'^h\''
  334. };
  335. // finally, give grunt the config object...
  336. grunt.initConfig(config);
  337. grunt.loadTasks('./build/tasks/');
  338. };