Add gitlab issue/merge request templates
[src/app-framework-demo.git] / afb-client / gulpfile.js
1 // BUG Symlink not working
2
3 var gulp = require('gulp');
4 var debug = require('gulp-debug');
5 var plugins = require('gulp-load-plugins')();
6 var del = require('del');
7 var es = require('event-stream');
8 var bowerFiles = require('main-bower-files');
9 var print = require('gulp-print');
10 var Q = require('q');
11 var imagemin = require('gulp-imagemin'), pngquant = require('imagemin-pngquant');
12 var taskListing = require('gulp-task-listing');
13 var symlink = require('gulp-sym');
14 var rename = require("gulp-rename");
15
16 // addon for Foundation6
17 var router   = require('front-router');
18
19 // == PATH STRINGS ========
20 var appdir  = "./app/";   // Warning to not forget trailling '/'
21 config=require (appdir + "etc/_Config"); // upload user local preferences if any
22
23 // Run node in debug mode in developpement mode ?
24 var nodeopts = config.DEBUG !== undefined ? '--debug='+config.DEBUG : ''; 
25 var frontend= appdir + config.FRONTEND;
26
27 var paths = {
28     application : frontend,
29     scripts     : frontend+'/**/*.js',
30     appStyles   : [frontend+'/**/*.scss', '!'+frontend+'/styles/*/*-conf.scss'],
31     globalStyles: [frontend+'/styles/**/*.scss'],
32     images      : [frontend+'/**/*.png',frontend+'/**/*.jpg',frontend+'/**/*.jpeg',frontend+'/**/*.svg',frontend+'/**/*.ttf'],
33     index       : frontend+'/index.html',
34     partials    : [frontend + '/**/*.html', '!' + frontend +'/index.html'],
35     distDev     : './dist.dev',
36     distProd    : './dist.prod',
37     sass:  [frontend+'/styles', 'bower_components/foundation-apps/scss','bower_components/foundation-icon-fonts'],
38     fonts: ['bower_components/**/*.woff'],
39     favicon: frontend+'/favicon.ico'
40 };
41
42 paths['distAppDev']  = paths.distDev + config.URLBASE;
43 paths['distAppProd'] = paths.distProd + config.URLBASE;
44
45 // Run node in debug mode in developpement mode ?
46 var nodeopts = config.DEBUG !== undefined ? '--debug='+config.DEBUG : ''; 
47
48 // == PIPE SEGMENTS ========
49 var pipes = {};
50
51 pipes.orderedVendorScripts = function() {
52     return plugins.order(['jquery.js', 'angular.js']);
53 };
54
55 pipes.orderedAppScripts = function() {
56     return plugins.angularFilesort();
57 };
58
59 pipes.minifiedFileName = function() {
60     return plugins.rename(function (path) {
61         path.extname = '.min' + path.extname;
62     });
63 };
64
65 pipes.validatedAppScripts = function() {
66     return gulp.src(paths.scripts)
67         .pipe(plugins.replace('@@APPNAME@@', config.APPNAME))
68         .pipe(plugins.jshint())
69         .pipe(plugins.jshint.reporter('jshint-stylish'));
70 };
71
72 pipes.builtAppScriptsDev = function() {
73     return pipes.validatedAppScripts()
74         .pipe(gulp.dest(paths.distAppDev));
75 };
76
77 pipes.builtAppScriptsProd = function() {
78     var scriptedPartials = pipes.scriptedPartials();
79     var validatedAppScripts = pipes.validatedAppScripts();
80
81     return es.merge(scriptedPartials, validatedAppScripts)
82         .pipe(plugins.ngAnnotate())
83         .pipe(pipes.orderedAppScripts())
84         .pipe(plugins.sourcemaps.init())
85         .pipe(plugins.concat(config.APPNAME+'.min.js'))
86         .pipe(plugins.uglify({compress: {drop_console: true}}))
87         .pipe(plugins.sourcemaps.write())
88         .pipe(gulp.dest(paths.distAppProd));
89 };
90
91 pipes.builtVendorScriptsDev = function() {
92     return gulp.src(bowerFiles())
93         .pipe(gulp.dest( paths.distDev +'/bower_components'));
94 };
95
96 pipes.builtVendorScriptsProd = function() {
97     return gulp.src(bowerFiles('**/*.js'))
98         .pipe(pipes.orderedVendorScripts())
99         .pipe(plugins.concat('vendor.min.js'))
100         .pipe(plugins.uglify())
101         .pipe(gulp.dest(paths.distProd+ '/bower_components'));
102 };
103
104
105 pipes.validatedPartials = function() {
106     return gulp.src(paths.partials)
107         .pipe(plugins.htmlhint({'doctype-first': false}))
108         .pipe(router({path: paths.application+'/etc/routes.js', root: paths.application}))
109         .pipe(plugins.htmlhint.reporter());
110 };
111
112 pipes.builtPartialsDev = function() {
113     return pipes.validatedPartials()
114         .pipe(gulp.dest(paths.distAppDev));
115 };
116
117 pipes.scriptedPartials = function() {
118     return pipes.validatedPartials()
119         .pipe(plugins.htmlhint.failReporter())
120         .pipe(plugins.htmlmin({collapseWhitespace: true, removeComments: true}))
121         .pipe(plugins.ngHtml2js({
122             moduleName: config.APPNAME,
123             template: "(function() {"
124                + "angular.module('<%= moduleName %>').run(['$templateCache', function($templateCache) {"
125                + "$templateCache.put('<%= template.url %>',\n    '<%= template.escapedContent %>');"
126                + "}]);\n"
127                + "})();\n"
128         }));    
129 };
130
131 pipes.builtAppStylesDev = function() {
132     return gulp.src(paths.appStyles)
133         .pipe(plugins.sass({includePaths: paths.sass}))
134         .pipe(gulp.dest(paths.distAppDev + '/styles'));
135 };
136
137 pipes.builtglobalStylesDev = function() {
138     return gulp.src(paths.globalStyles)
139         .pipe(plugins.sass({includePaths: paths.sass}))
140         .pipe(gulp.dest(paths.distDev  + '/global_styles'));
141 };
142
143 pipes.builtAppStylesProd = function() {
144     return gulp.src(paths.appStyles)
145         .pipe(plugins.sourcemaps.init())
146         .pipe(plugins.sass({includePaths: frontend + '/styles'}))
147         // .pipe(debug({title: '***** appStyle:'}))
148         .pipe(plugins.minifyCss())
149         .pipe(plugins.concat(config.APPNAME+'.css'))
150         .pipe(plugins.sourcemaps.write())
151         .pipe(pipes.minifiedFileName())
152         .pipe(gulp.dest(paths.distAppProd));
153 };
154
155 pipes.builtglobalStylesProd = function() {
156     return gulp.src(paths.globalStyles)
157         .pipe(plugins.sourcemaps.init())
158         .pipe(plugins.sass({includePaths: paths.sass}))
159         .pipe(plugins.minifyCss())
160         .pipe(plugins.sourcemaps.write())
161         .pipe(pipes.minifiedFileName())
162         .pipe(rename(function (path) {path.dirname="";return path;}))
163         .pipe(gulp.dest(paths.distProd + '/global_styles'));
164 };
165
166 pipes.processedFontsDev = function() {
167     return gulp.src(paths.fonts)
168         .pipe(rename(function (path) {path.dirname="";return path;}))
169         .pipe(gulp.dest(paths.distDev+'/bower_components'));
170 };
171
172 pipes.processedFontsProd = function() {
173     return gulp.src(paths.fonts)
174         .pipe(rename(function (path) {path.dirname="";return path;}))
175         .pipe(gulp.dest(paths.distProd+'/bower_components'));
176 };
177
178
179 pipes.processedImagesDev = function() {
180     return gulp.src(paths.images)
181         .pipe(gulp.dest(paths.distAppDev));
182 };
183
184 pipes.processedFaviconDev = function() {
185     return gulp.src(paths.favicon)
186         .pipe(gulp.dest(paths.distDev));
187 };
188
189 pipes.processedImagesProd = function() {
190     return gulp.src(paths.images)
191        .pipe(imagemin({
192             progressive: true,
193             svgoPlugins: [{removeViewBox: false}],
194             use: [pngquant()]
195         }))
196         .pipe(gulp.dest(paths.distAppProd));
197 };
198
199 pipes.processedFaviconProd = function() {
200     return gulp.src(paths.favicon)
201         .pipe(gulp.dest(paths.distProd));
202 };
203
204 // Create an Symlink when config.URLBASE exist
205 pipes.createDevSymLink = function() {
206     return gulp.src(paths.distDev).pipe(symlink(paths.distDev+config.URLBASE, {force: true}));
207 };
208
209 pipes.createProdSymLink = function() {
210     return gulp.src(paths.distProd).pipe(symlink(paths.distDev+config.URLBASE,{force: true}));
211 };
212
213 pipes.validatedIndex = function() {
214     return gulp.src(paths.index)       
215         .pipe(plugins.replace('@@APPNAME@@', config.APPNAME))
216         .pipe(plugins.replace('@@URLBASE@@', config.URLBASE))
217         .pipe(plugins.htmlhint())
218         .pipe(plugins.htmlhint.reporter());
219 };
220
221 pipes.builtIndexDev = function() {
222
223     var orderedVendorScripts = pipes.builtVendorScriptsDev()
224         .pipe(pipes.orderedVendorScripts());
225
226     var orderedAppScripts = pipes.builtAppScriptsDev()
227         .pipe(pipes.orderedAppScripts());
228
229     var appStyles    = pipes.builtAppStylesDev();
230     var globalStyles = pipes.builtglobalStylesDev();
231
232     return pipes.validatedIndex()
233          // Vendor and Global should have absolute path to rootdir application one are relative to BaseURL
234         .pipe(plugins.inject(orderedVendorScripts, {relative: false, ignorePath: "/dist.dev", name: 'bower'}))
235         .pipe(plugins.inject(globalStyles, {relative: false, ignorePath: "/dist.dev", name:'vendor'}))
236         .pipe(gulp.dest(paths.distAppDev)) // write first to get relative path for inject
237         .pipe(plugins.inject(orderedAppScripts, {relative: true}))
238         .pipe(plugins.inject(appStyles, {relative: true, name: 'appli'}))
239         .pipe(gulp.dest(paths.distAppDev));
240 };
241
242 pipes.builtIndexProd = function() {
243
244     var vendorScripts= pipes.builtVendorScriptsProd();
245     var appScripts   = pipes.builtAppScriptsProd();
246     var appStyles    = pipes.builtAppStylesProd();
247     var globalStyles = pipes.builtglobalStylesProd();
248
249     return pipes.validatedIndex()
250          // Vendor and Global should have absolute path to rootdir application one are relative to BaseURL
251         .pipe(plugins.inject(vendorScripts, {relative: false, ignorePath: "/dist.prod", name: 'bower'}))
252         .pipe(plugins.inject(globalStyles, {relative: false, ignorePath: "/dist.prod", name:'vendor'}))
253         .pipe(gulp.dest(paths.distAppProd)) // write first to get relative path for inject
254         .pipe(plugins.inject(appScripts, {relative: true}))
255         .pipe(plugins.inject(appStyles, {relative: true, name:'appli'}))
256         .pipe(plugins.htmlmin({collapseWhitespace: true, removeComments: true}))
257         .pipe(gulp.dest(paths.distAppProd));
258 };
259
260 pipes.builtAppDev = function() {
261     return es.merge(pipes.builtIndexDev(), pipes.builtPartialsDev(), pipes.processedFaviconDev(), pipes.processedImagesDev(), pipes.processedFontsDev() );
262 };
263
264 pipes.builtAppProd = function() {
265     return es.merge(pipes.builtIndexProd(), pipes.processedFaviconProd(), pipes.processedImagesProd(), pipes.processedFontsProd());
266 };
267
268
269 // == TASKS ========
270
271 // Add a task to render the output 
272 gulp.task('help', taskListing.withFilters(/-/));
273    
274 // clean, build of production environement
275 gulp.task('build', ['clean-build-app-prod']);
276
277 // removes all compiled dev files
278 gulp.task('clean-dev', function() {
279     var deferred = Q.defer();
280     del(paths.distDev, function() {
281         deferred.resolve();
282     });
283     return deferred.promise;
284 });
285
286 // removes all compiled production files
287 gulp.task('clean-prod', function() {
288     var deferred = Q.defer();
289     del(paths.distProd, function() {
290         deferred.resolve();
291     });
292     return deferred.promise;
293 });
294
295 // checks html source files for syntax errors
296 gulp.task('validate-partials', pipes.validatedPartials);
297
298 // checks index.html for syntax errors
299 gulp.task('validate-index', pipes.validatedIndex);
300
301 // moves html source files into the dev environment
302 gulp.task('build-partials-dev', pipes.builtPartialsDev);
303
304 // converts partials to javascript using html2js
305 gulp.task('convert-partials-to-js', pipes.scriptedPartials);
306
307 // runs jshint on the app scripts
308 gulp.task('validate-app-scripts', pipes.validatedAppScripts);
309
310 // moves app scripts into the dev environment
311 gulp.task('build-app-scripts-dev', pipes.builtAppScriptsDev);
312
313 // concatenates, uglifies, and moves app scripts and partials into the prod environment
314 gulp.task('build-app-scripts-prod', pipes.builtAppScriptsProd);
315
316 // compiles app sass and moves to the dev environment
317 gulp.task('build-app-styles-dev', pipes.builtAppStylesDev);
318
319 // compiles and minifies app sass to css and moves to the prod environment
320 gulp.task('build-app-styles-prod', pipes.builtAppStylesProd);
321
322 // moves vendor scripts into the dev environment
323 gulp.task('build-vendor-scripts-dev', pipes.builtVendorScriptsDev);
324
325 // concatenates, uglifies, and moves vendor scripts into the prod environment
326 gulp.task('build-vendor-scripts-prod', pipes.builtVendorScriptsProd);
327
328 // validates and injects sources into index.html and moves it to the dev environment
329 gulp.task('build-index-dev', pipes.builtIndexDev);
330
331 // validates and injects sources into index.html, minifies and moves it to the dev environment
332 gulp.task('build-index-prod', pipes.builtIndexProd);
333
334 // builds a complete dev environment
335 gulp.task('build-app-dev', pipes.builtAppDev);
336
337 // builds a complete prod environment
338 gulp.task('build-app-prod', pipes.builtAppProd);
339
340 // cleans and builds a complete dev environment
341 gulp.task('clean-build-app-dev', ['clean-dev'], pipes.builtAppDev);
342
343 // cleans and builds a complete prod environment
344 gulp.task('clean-build-app-prod', ['clean-prod'], pipes.builtAppProd);
345
346 // clean, build, and watch live changes to the dev environment
347 gulp.task('watch-dev', ['clean-build-app-dev'], function() {
348
349     // watch app scripts
350     gulp.watch(paths.scripts, function() {
351         return pipes.builtAppScriptsDev()
352             .pipe(plugins.livereload());
353     });
354
355     // watch html partials
356     gulp.watch(paths.partials, function() {
357         return pipes.builtPartialsDev()
358             .pipe(plugins.livereload());
359     });
360     
361     // watch Images
362     gulp.watch(paths.images, function() {
363         return pipes.processedImagesDev()
364             .pipe(plugins.livereload());
365     });
366
367     // watch styles
368     gulp.watch(paths.appStyles, function() {
369         return pipes.builtAppStylesDev()
370             .pipe(plugins.livereload());
371     });
372
373 });
374
375 // clean, build, and watch live changes to the prod environment
376 gulp.task('watch-prod', ['clean-build-app-prod'], function() {
377
378     // watch index
379     gulp.watch(paths.index, function() {
380         return pipes.builtIndexProd()
381             .pipe(plugins.livereload());
382     });
383
384     // watch app scripts
385     gulp.watch(paths.scripts, function() {
386         return pipes.builtAppScriptsProd()
387             .pipe(plugins.livereload());
388     });
389
390     // watch hhtml partials
391     gulp.watch(paths.partials, function() {
392         return pipes.builtAppScriptsProd()
393             .pipe(plugins.livereload());
394     });
395     
396     // watch Images
397     gulp.watch(paths.images, function() {
398         return pipes.processedImagesProd()
399             .pipe(plugins.livereload());
400     });
401
402     // watch styles
403     gulp.watch(paths.appStyles, function() {
404         return pipes.builtAppStylesProd()
405             .pipe(plugins.livereload());
406     });
407     
408 });
409
410 // default task builds for prod
411 gulp.task('default', ['clean-build-app-prod']);