Gruntfile.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. module.exports = function(grunt) {
  2. // Load all grunt modules
  3. require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
  4. // Tell our Express server that Grunt launched it
  5. process.env.GRUNTED = true;
  6. // Project configuration.
  7. grunt.initConfig({
  8. pkg: grunt.file.readJSON('package.json'),
  9. settings: grunt.file.readJSON('./server_config/settings.json'),
  10. font: {
  11. icons: {
  12. src: ['front/src/fonts/svg-icons/*.svg'],
  13. destCss: 'front/src/less/icons.less',
  14. destFonts: 'front/src/fonts/icons.woff',
  15. // Optional: Custom routing of font filepaths for CSS
  16. cssRouter: function (fontpath) {
  17. var pathArray = fontpath.split('/');
  18. var fileName = pathArray[pathArray.length - 1];
  19. return '/fonts/' + fileName;
  20. }
  21. }
  22. },
  23. less: {
  24. all: {
  25. files: [
  26. {
  27. expand: true,
  28. cwd: 'front/src/less/',
  29. src: ['**/*.less'],
  30. dest: 'front/src/css/',
  31. ext: '.css'
  32. }
  33. ]
  34. }
  35. },
  36. replace: {
  37. dist: {
  38. options: {
  39. patterns: [
  40. {
  41. match: 'googleAnalyticsId',
  42. replacement: '<%= settings.googleAnalyticsId %>'
  43. },
  44. {
  45. match: 'version',
  46. replacement: 'v<%= pkg.version %>'
  47. }
  48. ]
  49. },
  50. files: [
  51. {expand: true, flatten: true, src: ['front/src/main.html'], dest: 'front/build/'}
  52. ]
  53. }
  54. },
  55. jshint: {
  56. all: [
  57. '*.js',
  58. 'app/lib/*.js',
  59. 'bin/*.js',
  60. 'lib/**/*.js',
  61. 'app/nodeControllers/*.js',
  62. 'app/public/scripts/*.js',
  63. 'phantomas_custom/**/*.js',
  64. 'test/**/*.js',
  65. 'front/src/js/**/*.js'
  66. ]
  67. },
  68. clean: {
  69. tmp: {
  70. src: ['.tmp']
  71. },
  72. dev: {
  73. src: ['front/src/css']
  74. },
  75. coverage: {
  76. src: ['.tmp', 'coverage/']
  77. },
  78. build: {
  79. src: ['front/build']
  80. }
  81. },
  82. copy: {
  83. beforeCoverage: {
  84. files: [
  85. {src: ['bin/server.js'], dest: '.tmp/'}
  86. ]
  87. },
  88. coverage: {
  89. files: [
  90. {src: ['test/**'], dest: 'coverage/'},
  91. {src: ['lib/metadata/**'], dest: 'coverage/'}
  92. ]
  93. },
  94. build: {
  95. files: [
  96. {src: ['./front/src/fonts/icons.woff'], dest: './front/build/fonts/icons.woff'},
  97. {src: ['./front/src/img/favicon.png'], dest: './front/build/img/favicon.png'},
  98. {src: ['./front/src/img/logo-large.png'], dest: './front/build/img/logo-large.png'},
  99. ]
  100. }
  101. },
  102. lineremover: {
  103. beforeCoverage: {
  104. files: {
  105. '.tmp/bin/cli.js': 'bin/cli.js'
  106. },
  107. options: {
  108. exclusionPattern: /#!\/usr\/bin\/env node/
  109. }
  110. }
  111. },
  112. blanket: {
  113. coverageApp: {
  114. src: ['app/'],
  115. dest: 'coverage/app/'
  116. },
  117. coverageLib: {
  118. src: ['lib/'],
  119. dest: 'coverage/lib/'
  120. },
  121. coverageBin: {
  122. src: ['.tmp/bin/'],
  123. dest: 'coverage/bin/'
  124. }
  125. },
  126. mochaTest: {
  127. test: {
  128. options: {
  129. reporter: 'spec',
  130. },
  131. src: ['coverage/test/core/*.js', 'coverage/test/api/*.js']
  132. },
  133. 'test-current-work': {
  134. options: {
  135. reporter: 'spec',
  136. },
  137. src: ['coverage/test/api/apiTest.js']
  138. },
  139. coverage: {
  140. options: {
  141. reporter: 'html-cov',
  142. quiet: true,
  143. captureFile: 'coverage/coverage.html'
  144. },
  145. src: ['coverage/test/core/*.js', 'coverage/test/api/*.js']
  146. }
  147. },
  148. env: {
  149. dev: {
  150. NODE_ENV: 'development'
  151. },
  152. builded: {
  153. NODE_ENV: 'production'
  154. }
  155. },
  156. express: {
  157. dev: {
  158. options: {
  159. port: 8383,
  160. server: './bin/server.js',
  161. serverreload: true,
  162. showStack: true
  163. }
  164. },
  165. builded: {
  166. options: {
  167. port: 8383,
  168. server: './bin/server.js',
  169. serverreload: true,
  170. showStack: true
  171. }
  172. },
  173. test: {
  174. options: {
  175. port: 8387,
  176. server: './coverage/bin/server.js',
  177. showStack: true
  178. }
  179. },
  180. testSuite: {
  181. options: {
  182. port: 8388,
  183. bases: 'test/www'
  184. }
  185. }
  186. },
  187. useminPrepare: {
  188. html: './front/src/main.html',
  189. options: {
  190. dest: './front/build',
  191. root: ['./', './front/src']
  192. }
  193. },
  194. usemin: {
  195. html: './front/build/main.html',
  196. css: './front/build/css/*.css',
  197. options: {
  198. assetsDirs: ['front/build'],
  199. patterns: {
  200. css: [[/(\/fonts\/icons\.woff)/gm, 'Replacing reference to icons.woff']]
  201. }
  202. }
  203. },
  204. htmlmin: {
  205. options: {
  206. removeComments: true,
  207. collapseWhitespace: true
  208. },
  209. main: {
  210. files: [{
  211. expand: true,
  212. cwd: './front/build/',
  213. src: 'main.html',
  214. flatten: true,
  215. dest: './front/build'
  216. }]
  217. },
  218. views: {
  219. files: [{
  220. expand: true,
  221. cwd: './front/src/views',
  222. src: '*.html',
  223. flatten: true,
  224. dest: '.tmp/views/'
  225. }]
  226. }
  227. },
  228. inline_angular_templates: {
  229. build: {
  230. options: {
  231. base: '.tmp',
  232. method: 'append'
  233. },
  234. files: {
  235. './front/build/main.html': ['.tmp/views/*.html']
  236. }
  237. }
  238. },
  239. filerev: {
  240. options: {
  241. algorithm: 'md5',
  242. length: 8
  243. },
  244. assets: {
  245. src: './front/build/*/*.*'
  246. }
  247. }
  248. });
  249. // Custom task: copies the test settings.json file to the coverage folder, and checks if there's no missing fields
  250. grunt.registerTask('copy-test-server-settings', function() {
  251. var mainSettingsFile = './server_config/settings.json';
  252. var testSettingsFile = './test/fixtures/settings.json';
  253. var mainSettings = grunt.file.readJSON(mainSettingsFile);
  254. var testSettings = grunt.file.readJSON(testSettingsFile);
  255. // Recursively compare keys of two objects (not the values)
  256. function compareKeys(original, copy, context) {
  257. for (var key in original) {
  258. if (!copy[key] && copy[key] !== '' && copy[key] !== 0) {
  259. grunt.fail.warn('Settings file ' + testSettingsFile + ' doesn\'t contain key ' + context + '.' + key);
  260. }
  261. if (original[key] !== null && typeof original[key] === 'object') {
  262. compareKeys(original[key], copy[key], context + '.' + key);
  263. }
  264. }
  265. }
  266. compareKeys(mainSettings, testSettings, 'settings');
  267. var outputFile = './coverage/server_config/settings.json';
  268. grunt.file.write(outputFile, JSON.stringify(testSettings, null, 4));
  269. grunt.log.ok('File ' + outputFile + ' created');
  270. });
  271. grunt.registerTask('icons', [
  272. 'font:icons',
  273. 'less',
  274. 'clean:tmp'
  275. ]);
  276. grunt.registerTask('build', [
  277. 'jshint',
  278. 'clean:build',
  279. 'copy:build',
  280. 'less',
  281. 'useminPrepare',
  282. 'concat',
  283. 'uglify',
  284. 'cssmin',
  285. 'replace',
  286. 'htmlmin:views',
  287. 'inline_angular_templates',
  288. 'filerev',
  289. 'usemin',
  290. 'htmlmin:main',
  291. 'clean:tmp'
  292. ]);
  293. grunt.registerTask('hint', [
  294. 'jshint'
  295. ]);
  296. grunt.registerTask('dev', [
  297. 'env:dev',
  298. 'express:dev'
  299. ]);
  300. grunt.registerTask('builded', [
  301. 'env:builded',
  302. 'express:builded'
  303. ]);
  304. grunt.registerTask('test', [
  305. 'build',
  306. 'jshint',
  307. 'express:testSuite',
  308. 'clean:coverage',
  309. 'copy-test-server-settings',
  310. 'lineremover:beforeCoverage',
  311. 'copy:beforeCoverage',
  312. 'blanket',
  313. 'copy:coverage',
  314. 'express:test',
  315. 'mochaTest:test',
  316. 'mochaTest:coverage',
  317. 'clean:tmp'
  318. ]);
  319. grunt.registerTask('test-current-work', [
  320. 'build',
  321. 'jshint',
  322. 'express:testSuite',
  323. 'clean:coverage',
  324. 'copy-test-server-settings',
  325. 'lineremover:beforeCoverage',
  326. 'copy:beforeCoverage',
  327. 'blanket',
  328. 'copy:coverage',
  329. 'express:test',
  330. 'mochaTest:test-current-work',
  331. 'clean:tmp'
  332. ]);
  333. };