1 // BUG Symlink not working
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');
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 var exec = require('child_process').exec
16 var argv = require('yargs').argv;
18 // == PATH STRINGS ========
19 var appdir = "./app/"; // Warning to not forget trailling '/'
20 config=require (appdir + "etc/_Config"); // upload user local preferences if any
22 var frontend= appdir + config.FRONTEND;
25 application : frontend,
26 scripts : frontend+'/**/*.js',
27 appStyles : [frontend+'/**/*.scss', '!'+frontend+'/styles/*.scss'],
28 globalStyles: [frontend+'/styles/*.scss'],
32 frontend+'/**/*.jpeg',
35 'bower_components/leaflet/dist/images/*.png'
37 index : frontend+'/index.html',
38 partials : [frontend + '/**/*.html', '!' + frontend +'/index.html'],
39 distDev : './dist.dev',
40 distProd : './dist.prod',
43 'bower_components/bootstrap-sass/assets/stylesheets'
45 fonts: ['bower_components/**/*.woff'],
46 favicon: frontend+'/images/favicon.ico',
47 wgtconfig: 'config.xml'
50 // add bower files to global styles
51 bowerFiles('**/*.css').forEach(function(p) {
52 paths.globalStyles.unshift(p);
55 paths['distAppDev'] = paths.distDev + config.URLBASE;
56 paths['distAppProd'] = paths.distProd + config.URLBASE;
58 // Run node in debug mode in developpement mode ?
59 var nodeopts = config.DEBUG !== undefined ? '--debug='+config.DEBUG : '';
61 // == PIPE SEGMENTS ========
64 pipes.orderedVendorScripts = function() {
65 return plugins.order(['jquery.js', 'bootstrap.js','leaflet-src.js','tween.js','steelseries.js']);
68 pipes.minifiedFileName = function() {
69 return plugins.rename(function (path) {
70 path.extname = '.min' + path.extname;
74 pipes.validatedAppScripts = function() {
75 return gulp.src(paths.scripts)
76 .pipe(plugins.replace('@@APPNAME@@', config.APPNAME))
77 .pipe(plugins.replace('@@APPVER@@', config.APPVER))
78 .pipe(plugins.jshint())
79 .pipe(plugins.jshint.reporter('jshint-stylish'));
82 pipes.builtAppScriptsDev = function() {
83 return pipes.validatedAppScripts()
84 .pipe(gulp.dest(paths.distAppDev));
87 pipes.builtAppScriptsProd = function() {
88 var scriptedPartials = pipes.scriptedPartials();
89 var validatedAppScripts = pipes.validatedAppScripts();
90 return es.merge(scriptedPartials, validatedAppScripts)
91 .pipe(plugins.sourcemaps.init())
92 .pipe(plugins.concat(config.APPNAME+'.min.js'))
93 .pipe(plugins.uglify({compress: {drop_console: true}}))
94 .pipe(plugins.sourcemaps.write())
95 .pipe(gulp.dest(paths.distAppProd+'/js'));
98 pipes.builtVendorScriptsDev = function() {
99 return gulp.src(bowerFiles('**/*.js'))
100 .pipe(gulp.dest( paths.distDev +'/bower_components'));
103 pipes.builtVendorScriptsProd = function() {
104 return gulp.src(bowerFiles('**/*.js'))
105 .pipe(pipes.orderedVendorScripts())
106 .pipe(plugins.concat('vendor.min.js'))
107 .pipe(plugins.uglify())
108 .pipe(gulp.dest(paths.distProd+ '/bower_components'));
112 pipes.validatedPartials = function() {
113 return gulp.src(paths.partials)
114 .pipe(plugins.htmlhint({'doctype-first': false}))
115 .pipe(plugins.htmlhint.reporter());
118 pipes.builtPartialsDev = function() {
119 return pipes.validatedPartials()
120 .pipe(gulp.dest(paths.distAppDev));
123 pipes.scriptedPartials = function() {
124 return pipes.validatedPartials()
125 .pipe(plugins.htmlhint.failReporter())
126 .pipe(plugins.htmlmin({collapseWhitespace: true, removeComments: true}));
129 pipes.builtAppStylesDev = function() {
130 return gulp.src(paths.appStyles)
131 .pipe(plugins.sass({includePaths: paths.sass}))
132 .pipe(gulp.dest(paths.distAppDev + '/styles'));
135 pipes.builtglobalStylesDev = function() {
136 return gulp.src(paths.globalStyles)
137 .pipe(plugins.sass({includePaths: paths.sass}))
138 .pipe(gulp.dest(paths.distDev + '/global_styles'));
141 pipes.builtAppStylesProd = function() {
142 return gulp.src(paths.appStyles)
143 .pipe(plugins.sourcemaps.init())
144 .pipe(plugins.sass({includePaths: paths.sass}))
145 // .pipe(debug({title: '***** appStyle:'}))
146 .pipe(plugins.cleanCss())
147 .pipe(plugins.concat(config.APPNAME+'.css'))
148 .pipe(plugins.sourcemaps.write())
149 .pipe(pipes.minifiedFileName())
150 .pipe(gulp.dest(paths.distAppProd));
153 pipes.builtglobalStylesProd = function() {
154 return gulp.src(paths.globalStyles)
155 .pipe(plugins.sourcemaps.init())
156 .pipe(plugins.sass({includePaths: paths.sass}))
157 .pipe(plugins.cleanCss())
158 .pipe(plugins.sourcemaps.write())
159 .pipe(pipes.minifiedFileName())
160 .pipe(rename(function (path) {path.dirname="";return path;}))
161 .pipe(plugins.concat('output.min.css'))
162 .pipe(gulp.dest(paths.distProd + '/global_styles'));
165 pipes.processedFontsDev = function() {
166 return gulp.src(paths.fonts)
167 .pipe(rename(function (path) {path.dirname="";return path;}))
168 .pipe(gulp.dest(paths.distDev+'/bower_components'));
171 pipes.processedFontsProd = function() {
172 return gulp.src(paths.fonts)
173 .pipe(rename(function (path) {path.dirname="";return path;}))
174 .pipe(gulp.dest(paths.distProd+'/bower_components'));
178 pipes.processedImagesDev = function() {
179 return gulp.src(paths.images)
180 .pipe(rename(function(path) { path.dirname=""; return path; }))
181 .pipe(gulp.dest(paths.distAppDev+"/images/"));
184 pipes.processedFaviconDev = function() {
185 return gulp.src(paths.favicon)
186 .pipe(gulp.dest(paths.distDev));
189 pipes.processedImagesProd = function() {
190 return gulp.src(paths.images)
191 .pipe(rename(function(path) { path.dirname=""; return path; }))
194 svgoPlugins: [{removeViewBox: false}],
197 .pipe(gulp.dest(paths.distAppProd+"/images/"));
200 pipes.processedFaviconProd = function() {
201 return gulp.src(paths.favicon)
202 .pipe(gulp.dest(paths.distProd));
205 // Create an Symlink when config.URLBASE exist
206 pipes.createDevSymLink = function() {
207 return gulp.src(paths.distDev).pipe(symlink(paths.distDev+config.URLBASE, {force: true}));
210 pipes.createProdSymLink = function() {
211 return gulp.src(paths.distProd).pipe(symlink(paths.distDev+config.URLBASE,{force: true}));
214 pipes.validatedIndex = function() {
215 return gulp.src(paths.index)
216 .pipe(plugins.replace('@@APPNAME@@', config.APPNAME))
217 .pipe(plugins.replace('@@APPVER@@', config.APPVER))
218 .pipe(plugins.replace('@@URLBASE@@', config.URLBASE))
219 .pipe(plugins.htmlhint())
220 .pipe(plugins.htmlhint.reporter());
223 pipes.builtIndexDev = function() {
225 var orderedVendorScripts = pipes.builtVendorScriptsDev()
226 .pipe(pipes.orderedVendorScripts());
228 var orderedAppScripts = pipes.builtAppScriptsDev();
230 var appStyles = pipes.builtAppStylesDev();
231 var globalStyles = pipes.builtglobalStylesDev();
233 return pipes.validatedIndex()
234 // Vendor and Global should have absolute path to rootdir application one are relative to BaseURL
235 .pipe(plugins.inject(orderedVendorScripts, {relative: false, ignorePath: "/dist.dev", name: 'bower'}))
236 .pipe(plugins.inject(globalStyles, {relative: false, ignorePath: "/dist.dev", name:'vendor'}))
237 .pipe(gulp.dest(paths.distAppDev)) // write first to get relative path for inject
238 .pipe(plugins.inject(orderedAppScripts, {relative: true}))
239 .pipe(plugins.inject(appStyles, {relative: true, name: 'appli'}))
240 .pipe(gulp.dest(paths.distAppDev));
243 pipes.builtIndexProd = function() {
245 var vendorScripts= pipes.builtVendorScriptsProd();
246 var appScripts = pipes.builtAppScriptsProd();
247 var appStyles = pipes.builtAppStylesProd();
248 var globalStyles = pipes.builtglobalStylesProd();
250 return pipes.validatedIndex()
251 // Vendor and Global should have absolute path to rootdir application one are relative to BaseURL
252 .pipe(plugins.inject(vendorScripts, {relative: false, ignorePath: "/dist.prod", name: 'bower'}))
253 .pipe(plugins.inject(globalStyles, {relative: false, ignorePath: "/dist.prod", name:'vendor'}))
254 .pipe(gulp.dest(paths.distAppProd)) // write first to get relative path for inject
255 .pipe(plugins.inject(appScripts, {relative: true}))
256 .pipe(plugins.inject(appStyles, {relative: true, name:'appli'}))
257 .pipe(plugins.htmlmin({collapseWhitespace: true, removeComments: true}))
258 .pipe(gulp.dest(paths.distAppProd));
261 pipes.builtAppDev = function() {
262 return es.merge(pipes.builtIndexDev(), pipes.builtPartialsDev(), pipes.processedFaviconDev(), pipes.processedImagesDev(), pipes.processedFontsDev() )
263 .pipe(pipes.doRsync("Dev"));
266 pipes.builtAppProd = function() {
267 return es.merge(pipes.builtIndexProd(), pipes.processedFaviconProd(), pipes.processedImagesProd(), pipes.processedFontsProd())
268 .pipe(pipes.doRsync("Prod"));
271 pipes.widgetConfig = function(type) {
272 var dst=paths["dist"+type];
273 var content="."+config.URLBASE+"/index.html";
274 content=content.replace(/\/+/g,"/");
275 return gulp.src(paths.wgtconfig+".in")
276 .pipe(plugins.replace('@@APPNAME@@', config.APPNAME))
277 .pipe(plugins.replace('@@APPVER@@', config.APPVER))
278 .pipe(plugins.replace('@@CONTENT@@', content))
279 .pipe(plugins.rename("config.xml"))
280 .pipe(gulp.dest(dst))
283 pipes.widgetPack = function(type,cb) {
284 var dst=paths["dist"+type];
285 var wgtfile=config.APPNAME+"_"+type+".wgt"
288 "wgtpkg-pack -f -o "+wgtfile+" "+dst,
289 function(err,stdout,stderr) {
296 pipes.doRsync=function(type) {
297 var dst=paths["dist"+type];
298 if (!argv.host) return plugins.empty();
300 return plugins.rsync({
304 destination: "/usr/share/afm/applications/"+config.APPNAME+"/"+config.APPVER+"/htdocs/",
313 // Add a task to render the output
314 gulp.task('help', taskListing.withFilters(/-/));
316 // clean, build of production environement
317 gulp.task('build', ['clean-build-app-prod']);
319 // removes all compiled dev files
320 gulp.task('clean-dev', function() {
321 var deferred = Q.defer();
322 del(paths.distDev, function() {
325 return deferred.promise;
328 // removes all compiled production files
329 gulp.task('clean-prod', function() {
330 var deferred = Q.defer();
331 del(paths.distProd, function() {
334 return deferred.promise;
337 // checks html source files for syntax errors
338 gulp.task('validate-partials', pipes.validatedPartials);
340 // checks index.html for syntax errors
341 gulp.task('validate-index', pipes.validatedIndex);
343 // moves html source files into the dev environment
344 gulp.task('build-partials-dev', pipes.builtPartialsDev);
346 // converts partials to javascript using html2js
347 gulp.task('convert-partials-to-js', pipes.scriptedPartials);
349 // runs jshint on the app scripts
350 gulp.task('validate-app-scripts', pipes.validatedAppScripts);
352 // moves app scripts into the dev environment
353 gulp.task('build-app-scripts-dev', pipes.builtAppScriptsDev);
355 // concatenates, uglifies, and moves app scripts and partials into the prod environment
356 gulp.task('build-app-scripts-prod', pipes.builtAppScriptsProd);
358 // compiles app sass and moves to the dev environment
359 gulp.task('build-app-styles-dev', pipes.builtAppStylesDev);
361 // compiles and minifies app sass to css and moves to the prod environment
362 gulp.task('build-app-styles-prod', pipes.builtAppStylesProd);
364 // moves vendor scripts into the dev environment
365 gulp.task('build-vendor-scripts-dev', pipes.builtVendorScriptsDev);
367 // concatenates, uglifies, and moves vendor scripts into the prod environment
368 gulp.task('build-vendor-scripts-prod', pipes.builtVendorScriptsProd);
370 // validates and injects sources into index.html and moves it to the dev environment
371 gulp.task('build-index-dev', pipes.builtIndexDev);
373 // validates and injects sources into index.html, minifies and moves it to the dev environment
374 gulp.task('build-index-prod', pipes.builtIndexProd);
376 // builds a complete dev environment
377 gulp.task('build-app-dev', pipes.builtAppDev);
379 // builds a complete prod environment
380 gulp.task('build-app-prod', pipes.builtAppProd);
382 // cleans and builds a complete dev environment
383 gulp.task('clean-build-app-dev', ['clean-dev'], pipes.builtAppDev);
385 // cleans and builds a complete prod environment
386 gulp.task('clean-build-app-prod', ['clean-prod'], pipes.builtAppProd);
388 // clean, build, and watch live changes to the dev environment
389 gulp.task('watch-dev', ['clean-build-app-dev'], function() {
392 gulp.watch(paths.index, function() {
393 return pipes.builtIndexDev()
394 .pipe(pipes.doRsync("Dev"))
395 .pipe(plugins.livereload());
399 gulp.watch(paths.scripts, function() {
400 return pipes.builtAppScriptsDev()
401 .pipe(pipes.doRsync("Dev"))
402 .pipe(plugins.livereload());
405 // watch html partials
406 gulp.watch(paths.partials, function() {
407 return pipes.builtPartialsDev()
408 .pipe(pipes.doRsync("Dev"))
409 .pipe(plugins.livereload());
413 gulp.watch(paths.images, function() {
414 return pipes.processedImagesDev()
415 .pipe(pipes.doRsync("Dev"))
416 .pipe(plugins.livereload());
420 gulp.watch(paths.appStyles, function() {
421 return pipes.builtAppStylesDev()
422 .pipe(pipes.doRsync("Dev"))
423 .pipe(plugins.livereload());
425 gulp.watch(paths.globalStyles, function() {
426 return pipes.builtglobalStylesDev()
427 .pipe(pipes.doRsync("Dev"))
428 .pipe(plugins.livereload());
433 // clean, build, and watch live changes to the prod environment
434 gulp.task('watch-prod', ['clean-build-app-prod'], function() {
437 gulp.watch(paths.index, function() {
438 return pipes.builtIndexProd()
439 .pipe(pipes.doRsync("Prod"))
440 .pipe(plugins.livereload());
444 gulp.watch(paths.scripts, function() {
445 return pipes.builtAppScriptsProd()
446 .pipe(pipes.doRsync("Prod"))
447 .pipe(plugins.livereload());
450 // watch hhtml partials
451 gulp.watch(paths.partials, function() {
452 return pipes.builtAppScriptsProd()
453 .pipe(pipes.doRsync("Prod"))
454 .pipe(plugins.livereload());
458 gulp.watch(paths.images, function() {
459 return pipes.processedImagesProd()
460 .pipe(pipes.doRsync("Prod"))
461 .pipe(plugins.livereload());
465 gulp.watch(paths.appStyles, function() {
466 return pipes.builtAppStylesProd()
467 .pipe(pipes.doRsync("Prod"))
468 .pipe(plugins.livereload());
470 gulp.watch(paths.globalStyles, function() {
471 return pipes.builtglobalStylesProd()
472 .pipe(pipes.doRsync("Prod"))
473 .pipe(plugins.livereload());
478 gulp.task('widget-config-dev', ['build-app-dev'], function() { return pipes.widgetConfig("Dev"); });
479 gulp.task('widget-config-prod', ['build-app-prod'], function() { return pipes.widgetConfig("Prod"); });
480 gulp.task('widget-dev', ['widget-config-dev'], function(cb) { return pipes.widgetPack("Dev",cb); });
481 gulp.task('widget-prod', ['widget-config-prod'], function(cb) { return pipes.widgetPack("Prod",cb); });
483 // default task builds for prod
484 gulp.task('default', ['widget-prod']);