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
17 // addon for Foundation6
18 var router = require('front-router');
20 // == PATH STRINGS ========
21 var appdir = "./"; // Warning to not forget trailling '/'
22 config=require (appdir + "etc/_Config"); // upload user local preferences if any
24 var frontend= appdir + config.FRONTEND;
27 application : frontend,
28 scripts : frontend+'/**/*.js',
29 appStyles : [frontend+'/**/*.scss', '!'+frontend+'/styles/*/*-conf.scss'],
30 globalStyles: [frontend+'/styles/**/*.scss'],
31 images : [frontend+'/**/*.png',frontend+'/**/*.jpg',frontend+'/**/*.jpeg',frontend+'/**/*.svg',frontend+'/**/*.ttf'],
32 index : frontend+'/index.html',
33 partials : [frontend + '/**/*.html', '!' + frontend +'/index.html'],
34 distDev : './dist.dev',
35 distProd : './dist.prod',
36 sass: [frontend+'/styles', 'bower_components/foundation-apps/scss','bower_components/foundation-icon-fonts'],
37 fonts: ['bower_components/**/*.woff'],
38 favicon: frontend+'/favicon.ico',
39 wgtconfig: 'config.xml'
42 paths['distAppDev'] = paths.distDev + config.URLBASE;
43 paths['distAppProd'] = paths.distProd + config.URLBASE;
45 // Run node in debug mode in developpement mode ?
46 var nodeopts = config.DEBUG !== undefined ? '--debug='+config.DEBUG : '';
48 // == PIPE SEGMENTS ========
51 pipes.orderedVendorScripts = function() {
52 return plugins.order(['jquery.js', 'angular.js']);
55 pipes.orderedAppScripts = function() {
56 return plugins.angularFilesort();
59 pipes.minifiedFileName = function() {
60 return plugins.rename(function (path) {
61 path.extname = '.min' + path.extname;
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'));
72 pipes.builtAppScriptsDev = function() {
73 return pipes.validatedAppScripts()
74 .pipe(gulp.dest(paths.distAppDev));
77 pipes.builtAppScriptsProd = function() {
78 var scriptedPartials = pipes.scriptedPartials();
79 var validatedAppScripts = pipes.validatedAppScripts();
80 return es.merge(scriptedPartials, validatedAppScripts)
81 .pipe(plugins.ngAnnotate())
82 .pipe(pipes.orderedAppScripts())
83 .pipe(plugins.sourcemaps.init())
84 .pipe(plugins.concat(config.APPNAME+'.min.js'))
85 .pipe(plugins.uglify({compress: {drop_console: true}}))
86 .pipe(plugins.sourcemaps.write())
87 .pipe(gulp.dest(paths.distAppProd));
90 pipes.builtVendorScriptsDev = function() {
91 return gulp.src(bowerFiles())
92 .pipe(gulp.dest( paths.distDev +'/bower_components'));
95 pipes.builtVendorScriptsProd = function() {
96 return gulp.src(bowerFiles('**/*.js'))
97 .pipe(pipes.orderedVendorScripts())
98 .pipe(plugins.concat('vendor.min.js'))
99 .pipe(plugins.uglify())
100 .pipe(gulp.dest(paths.distProd+ '/bower_components'));
104 pipes.validatedPartials = function() {
105 return gulp.src(paths.partials)
106 .pipe(plugins.htmlhint({'doctype-first': false}))
107 .pipe(router({path: paths.application+'/etc/routes.js', root: paths.application}))
108 .pipe(plugins.htmlhint.reporter());
111 pipes.builtPartialsDev = function() {
112 return pipes.validatedPartials()
113 .pipe(gulp.dest(paths.distAppDev));
116 pipes.scriptedPartials = function() {
117 return pipes.validatedPartials()
118 .pipe(plugins.htmlhint.failReporter())
119 .pipe(plugins.htmlmin({collapseWhitespace: true, removeComments: true}))
120 .pipe(plugins.ngHtml2js({
121 moduleName: config.APPNAME,
122 template: "(function() {"
123 + "angular.module('<%= moduleName %>').run(['$templateCache', function($templateCache) {"
124 + "$templateCache.put('<%= template.url %>',\n '<%= template.escapedContent %>');"
130 pipes.builtAppStylesDev = function() {
131 return gulp.src(paths.appStyles)
132 .pipe(plugins.sass({includePaths: paths.sass}))
133 .pipe(gulp.dest(paths.distAppDev + '/styles'));
136 pipes.builtglobalStylesDev = function() {
137 return gulp.src(paths.globalStyles)
138 .pipe(plugins.sass({includePaths: paths.sass}))
139 .pipe(gulp.dest(paths.distDev + '/global_styles'));
142 pipes.builtAppStylesProd = function() {
143 return gulp.src(paths.appStyles)
144 .pipe(plugins.sourcemaps.init())
145 .pipe(plugins.sass({includePaths: frontend + '/styles'}))
146 // .pipe(debug({title: '***** appStyle:'}))
147 .pipe(plugins.cleanCss())
148 .pipe(plugins.concat(config.APPNAME+'.css'))
149 .pipe(plugins.sourcemaps.write())
150 .pipe(pipes.minifiedFileName())
151 .pipe(gulp.dest(paths.distAppProd));
154 pipes.builtglobalStylesProd = function() {
155 return gulp.src(paths.globalStyles)
156 .pipe(plugins.sourcemaps.init())
157 .pipe(plugins.sass({includePaths: paths.sass}))
158 .pipe(plugins.cleanCss())
159 .pipe(plugins.sourcemaps.write())
160 .pipe(pipes.minifiedFileName())
161 .pipe(rename(function (path) {path.dirname="";return path;}))
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(gulp.dest(paths.distAppDev));
183 pipes.processedFaviconDev = function() {
184 return gulp.src(paths.favicon)
185 .pipe(gulp.dest(paths.distDev));
188 pipes.processedImagesProd = function() {
189 return gulp.src(paths.images)
192 svgoPlugins: [{removeViewBox: false}],
195 .pipe(gulp.dest(paths.distAppProd));
198 pipes.processedFaviconProd = function() {
199 return gulp.src(paths.favicon)
200 .pipe(gulp.dest(paths.distProd));
203 // Create an Symlink when config.URLBASE exist
204 pipes.createDevSymLink = function() {
205 return gulp.src(paths.distDev).pipe(symlink(paths.distDev+config.URLBASE, {force: true}));
208 pipes.createProdSymLink = function() {
209 return gulp.src(paths.distProd).pipe(symlink(paths.distDev+config.URLBASE,{force: true}));
212 pipes.validatedIndex = function() {
213 return gulp.src(paths.index)
214 .pipe(plugins.replace('@@APPNAME@@', config.APPNAME))
215 .pipe(plugins.replace('@@URLBASE@@', config.URLBASE))
216 .pipe(plugins.htmlhint())
217 .pipe(plugins.htmlhint.reporter());
220 pipes.builtIndexDev = function() {
222 var orderedVendorScripts = pipes.builtVendorScriptsDev()
223 .pipe(pipes.orderedVendorScripts());
225 var orderedAppScripts = pipes.builtAppScriptsDev()
226 .pipe(pipes.orderedAppScripts());
228 var appStyles = pipes.builtAppStylesDev();
229 var globalStyles = pipes.builtglobalStylesDev();
231 return pipes.validatedIndex()
232 // Vendor and Global should have absolute path to rootdir application one are relative to BaseURL
233 .pipe(plugins.inject(orderedVendorScripts, {relative: false, ignorePath: "/dist.dev", name: 'bower'}))
234 .pipe(plugins.inject(globalStyles, {relative: false, ignorePath: "/dist.dev", name:'vendor'}))
235 .pipe(gulp.dest(paths.distAppDev)) // write first to get relative path for inject
236 .pipe(plugins.inject(orderedAppScripts, {relative: true}))
237 .pipe(plugins.inject(appStyles, {relative: true, name: 'appli'}))
238 .pipe(gulp.dest(paths.distAppDev));
241 pipes.builtIndexProd = function() {
243 var vendorScripts= pipes.builtVendorScriptsProd();
244 var appScripts = pipes.builtAppScriptsProd();
245 var appStyles = pipes.builtAppStylesProd();
246 var globalStyles = pipes.builtglobalStylesProd();
248 return pipes.validatedIndex()
249 // Vendor and Global should have absolute path to rootdir application one are relative to BaseURL
250 .pipe(plugins.inject(vendorScripts, {relative: false, ignorePath: "/dist.prod", name: 'bower'}))
251 .pipe(plugins.inject(globalStyles, {relative: false, ignorePath: "/dist.prod", name:'vendor'}))
252 .pipe(gulp.dest(paths.distAppProd)) // write first to get relative path for inject
253 .pipe(plugins.inject(appScripts, {relative: true}))
254 .pipe(plugins.inject(appStyles, {relative: true, name:'appli'}))
255 .pipe(plugins.htmlmin({collapseWhitespace: true, removeComments: true}))
256 .pipe(gulp.dest(paths.distAppProd));
259 pipes.builtAppDev = function() {
260 return es.merge(pipes.builtIndexDev(), pipes.builtPartialsDev(), pipes.processedFaviconDev(), pipes.processedImagesDev(), pipes.processedFontsDev() );
263 pipes.builtAppProd = function() {
264 return es.merge(pipes.builtIndexProd(), pipes.processedFaviconProd(), pipes.processedImagesProd(), pipes.processedFontsProd());
267 pipes.widgetConfig = function(type) {
268 var dst=paths["dist"+type];
269 var content="."+config.URLBASE+"/index.html";
270 content=content.replace(/\/+/g,"/");
271 return gulp.src(paths.wgtconfig+".in")
272 .pipe(plugins.replace('@@APPNAME@@', config.APPNAME))
273 .pipe(plugins.replace('@@CONTENT@@', content))
274 .pipe(plugins.rename("config.xml"))
275 .pipe(gulp.dest(dst))
278 pipes.widgetPack = function(type,cb) {
279 var dst=paths["dist"+type];
280 var wgtfile=config.APPNAME+"_"+type+".wgt"
283 "wgtpkg-pack -f -o "+wgtfile+" "+dst,
284 function(err,stdout,stderr) {
293 // Add a task to render the output
294 gulp.task('help', taskListing.withFilters(/-/));
296 // clean, build of production environement
297 gulp.task('build', ['clean-build-app-prod']);
299 // removes all compiled dev files
300 gulp.task('clean-dev', function() {
301 var deferred = Q.defer();
302 del(paths.distDev, function() {
305 return deferred.promise;
308 // removes all compiled production files
309 gulp.task('clean-prod', function() {
310 var deferred = Q.defer();
311 del(paths.distProd, function() {
314 return deferred.promise;
317 // checks html source files for syntax errors
318 gulp.task('validate-partials', pipes.validatedPartials);
320 // checks index.html for syntax errors
321 gulp.task('validate-index', pipes.validatedIndex);
323 // moves html source files into the dev environment
324 gulp.task('build-partials-dev', pipes.builtPartialsDev);
326 // converts partials to javascript using html2js
327 gulp.task('convert-partials-to-js', pipes.scriptedPartials);
329 // runs jshint on the app scripts
330 gulp.task('validate-app-scripts', pipes.validatedAppScripts);
332 // moves app scripts into the dev environment
333 gulp.task('build-app-scripts-dev', pipes.builtAppScriptsDev);
335 // concatenates, uglifies, and moves app scripts and partials into the prod environment
336 gulp.task('build-app-scripts-prod', pipes.builtAppScriptsProd);
338 // compiles app sass and moves to the dev environment
339 gulp.task('build-app-styles-dev', pipes.builtAppStylesDev);
341 // compiles and minifies app sass to css and moves to the prod environment
342 gulp.task('build-app-styles-prod', pipes.builtAppStylesProd);
344 // moves vendor scripts into the dev environment
345 gulp.task('build-vendor-scripts-dev', pipes.builtVendorScriptsDev);
347 // concatenates, uglifies, and moves vendor scripts into the prod environment
348 gulp.task('build-vendor-scripts-prod', pipes.builtVendorScriptsProd);
350 // validates and injects sources into index.html and moves it to the dev environment
351 gulp.task('build-index-dev', pipes.builtIndexDev);
353 // validates and injects sources into index.html, minifies and moves it to the dev environment
354 gulp.task('build-index-prod', pipes.builtIndexProd);
356 // builds a complete dev environment
357 gulp.task('build-app-dev', pipes.builtAppDev);
359 // builds a complete prod environment
360 gulp.task('build-app-prod', pipes.builtAppProd);
362 // cleans and builds a complete dev environment
363 gulp.task('clean-build-app-dev', ['clean-dev'], pipes.builtAppDev);
365 // cleans and builds a complete prod environment
366 gulp.task('clean-build-app-prod', ['clean-prod'], pipes.builtAppProd);
368 // clean, build, and watch live changes to the dev environment
369 gulp.task('watch-dev', ['clean-build-app-dev'], function() {
372 gulp.watch(paths.scripts, function() {
373 return pipes.builtAppScriptsDev()
374 .pipe(plugins.livereload());
377 // watch html partials
378 gulp.watch(paths.partials, function() {
379 return pipes.builtPartialsDev()
380 .pipe(plugins.livereload());
384 gulp.watch(paths.images, function() {
385 return pipes.processedImagesDev()
386 .pipe(plugins.livereload());
390 gulp.watch(paths.appStyles, function() {
391 return pipes.builtAppStylesDev()
392 .pipe(plugins.livereload());
397 // clean, build, and watch live changes to the prod environment
398 gulp.task('watch-prod', ['clean-build-app-prod'], function() {
401 gulp.watch(paths.index, function() {
402 return pipes.builtIndexProd()
403 .pipe(plugins.livereload());
407 gulp.watch(paths.scripts, function() {
408 return pipes.builtAppScriptsProd()
409 .pipe(plugins.livereload());
412 // watch hhtml partials
413 gulp.watch(paths.partials, function() {
414 return pipes.builtAppScriptsProd()
415 .pipe(plugins.livereload());
419 gulp.watch(paths.images, function() {
420 return pipes.processedImagesProd()
421 .pipe(plugins.livereload());
425 gulp.watch(paths.appStyles, function() {
426 return pipes.builtAppStylesProd()
427 .pipe(plugins.livereload());
432 gulp.task('widget-config-dev', ['build-app-dev'], function() { return pipes.widgetConfig("Dev"); });
433 gulp.task('widget-config-prod', ['build-app-prod'], function() { return pipes.widgetConfig("Prod"); });
434 gulp.task('widget-dev', ['widget-config-dev'], function(cb) { return pipes.widgetPack("Dev",cb); });
435 gulp.task('widget-prod', ['widget-config-prod'], function(cb) { return pipes.widgetPack("Prod",cb); });
437 // default task builds for prod
438 gulp.task('default', ['widget-prod']);