arozwalak
7/6/2015 - 8:17 AM

Javascript: Gulp config

Javascript: Gulp config

'use strict';

/* Setup Gulp
 ========================================================================== */

// Require
var gulp = require('gulp'),
    del = require('del'),
    fs = require('fs'),
    path = require('path'),
    _ = require('lodash'),
    rebase = require("rebase/tasks/gulp-rebase"),
    notifier = require('node-notifier'),
    runSequence = require('run-sequence'),
    sass = require('gulp-sass'),
    sourcemaps = require('gulp-sourcemaps'),
    autoprefixer = require('gulp-autoprefixer'),
    hologram = require('gulp-hologram'),
    plugins = require('gulp-load-plugins')(),
    filter = require('gulp-filter'),
    spritesmith = require('gulp.spritesmith'),
    uglify = require('gulp-uglify'),
    copy = require('gulp-copy'),
    browserSync = require('browser-sync').create(),
    debug = require('gulp-debug');


/* ========================================================================
 /* AT GULP
 ======================================================================== */
var at_config = {
    'src': 'src/ArsThanea/BebiProgramBundle/Resources',
    'destSrc': 'web/BebiProgram'
};

/* ==========================================================================
   Gulpfile

   Tasks:
   - gulp (builds for dev)
   - gulp build (builds for prod)
   - gulp at-watch
   - gulp browser-sync

   - gulp migrate
   - gulp cc (Clear Cache)
   - gulp fixperms
   - gulp maintenance
   - gulp apachectl
   ========================================================================== */

// Gulp Config
var showErrorNotifications = true,
    allowChmod = true;

// Project Config
var bowerComponentsPath = JSON.parse(fs.readFileSync(path.resolve(__dirname, '.bowerrc'))).directory;

var config = fs.readFileSync(path.resolve(__dirname, '.groundcontrolrc'), 'UTF-8'),
    vars = _.merge({
    'bowerComponentsPath': bowerComponentsPath
    }, JSON.parse(config).vars);

var resourcesPath = vars.resourcesPath;
var distPath = vars.distPath;

_.forEach(vars, function(value, key) {
    config = config.replace(new RegExp('\<\=\s*' + key + '\s*\>', 'ig'), value);
});

config = JSON.parse(config);

/* Errorhandling
   ========================================================================== */
var errorLogger, headerLines;

errorLogger = function(headerMessage,errorMessage){
    var header = headerLines(headerMessage);
        header += '\n             '+ headerMessage +'\n           ';
        header += headerLines(headerMessage);
        header += '\r\n \r\n';
        plugins.util.log(plugins.util.colors.red(header) + '             ' + errorMessage + '\r\n');

    if(showErrorNotifications){
        notifier.notify({
            'title': headerMessage,
            'message': errorMessage,
            'contentImage':  __dirname + "/gulp_error.png"
        });
    }
};

headerLines = function(message){
    var lines = '';
    for(var i = 0; i< (message.length + 4); i++){
        lines += '-';
    }
    return lines;
};


/* Add Async tag to script
   ========================================================================== */
var addAsyncTag = function (filepath) {
    if(config.js.addAsync === 'true') {
        return '<script src="' + filepath + '" async></script>';
    } else {
        return '<script src="' + filepath + '"></script>';
    }
};

/* Styles
   ========================================================================== */
gulp.task('styles', function() {
    return gulp.src(config.scss)
        .pipe(sourcemaps.init())
        .pipe(
            sass({
                style: 'compressed',
                errLogToConsole: true
            })
        )
        .on('error', function (err) {
            errorLogger('SASS Compilation Error', err.message);
        })
        .pipe(autoprefixer(config.browserSupport))
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest(config.dist.css))
        .pipe(plugins.size({
            title: 'css'
        }));
});

/* Javascript
   ========================================================================== */
// Jshint
gulp.task('jshint', function() {
    return gulp.src([config.js.app, '!' + resourcesPath + '/ui/js/vendors/**/*.js'])
        // Jshint
        .pipe(plugins.jshint())
        .pipe(plugins.jshint.reporter(require('jshint-stylish')));
});

// Production
gulp.task('scripts-prod', ['jshint'], function() {
    return gulp.src(config.js.footer)
        // Uglify
        .pipe(plugins.uglify({
            mangle: {
            except: ['jQuery']
            }
        }))
        .on('error', function (err){
            errorLogger('Javascript Error', err.message);
        })

        // Concat
        .pipe(plugins.concat('footer.min.js'))

        // Revision
        .pipe(plugins.rev())

        // Set destination
        .pipe(gulp.dest(config.dist.js))

        // Show total size of js
        .pipe(plugins.size({
            title: 'js'
        }));
});

gulp.task('inject-prod-scripts', ['scripts-prod'], function() {
    return gulp.src('src/' + config.project.mainBundlePath + '/Resources/views/' + config.project.mainJsInclude.folder + '/' + config.project.mainJsInclude.fileName)
        // Inject
        .pipe(plugins.inject(gulp.src(config.dist.js + '/**/*.js'), {
            transform: addAsyncTag,
            ignorePath: '/web'
        }))

        // Chmod for local use
        .pipe(plugins.if(allowChmod, plugins.chmod(777)))

        // Write
        .pipe(gulp.dest('src/' + config.project.mainBundlePath + '/Resources/views/' + config.project.mainJsInclude.folder + '/'));
});


// Development
gulp.task('scripts-dev', ['jshint'], function() {
    return gulp.src(config.js.footer)
        // Write
        .pipe(gulp.dest(config.dist.js));
});

gulp.task('inject-dev-scripts', ['scripts-dev'], function() {
    var files = gulp.src(config.js.footer, {read: false});

    return gulp.src('src/' + config.project.mainBundlePath + '/Resources/views/' + config.project.mainJsInclude.folder + '/' + config.project.mainJsInclude.fileName)
        // Inject
        .pipe(plugins.inject(files))

        // Rebase
        .pipe(rebase({
            script: {
            '(\/[^"]*\/)': '/frontend/js/'
            }
        }))

        // Write
        .pipe(gulp.dest('app/Resources/' + config.project.mainBundleName + '/views/' + config.project.mainJsInclude.folder + '/'));
});

/* Images
   ========================================================================== */
gulp.task('images', function() {
    return gulp.src(config.img)
        // Only optimize changed images
        .pipe(plugins.changed(config.dist.img))

        // Imagemin
        .pipe(plugins.imagemin({
            optimizationLevel: 3,
            progressive: true,
            svgoPlugins: [{
                removeViewBox: false
            }]
        }))

        // Set destination
        .pipe(gulp.dest(config.dist.img))

        // Show total size of images
        .pipe(plugins.size({
            title: 'images'
        }));
});


/* Fonts
   ========================================================================== */
gulp.task('fonts', function() {
    return gulp.src(config.fonts)
        // Set destination
        .pipe(gulp.dest(config.dist.fonts))

        // Show total size of fonts
        .pipe(plugins.size({
            title: 'fonts'
        }));
});


/* Styleguide
   ========================================================================== */
// Hologram
gulp.task('styleguide', function() {
    return gulp.src(config.styleguideFolder + '/config.yml')
        // Hologram
        .pipe(debug({title: 'styleguide:'}))
        .pipe(hologram());
});


// Inject scripts
gulp.task('styleguide-prod-js', function() {
    return gulp.src(config.dist.styleguide + '/*.html')
        // Inject
        .pipe(plugins.inject(gulp.src(config.dist.js + '/**/*.js'), {
            ignorePath: '/web'
        }))

        // Write
        .pipe(gulp.dest(config.dist.styleguide));
});

gulp.task('styleguide-dev-js', function() {
    var files = gulp.src(config.js.footer, {read: false});

    return gulp.src(config.dist.styleguide + '/*.html')
        // Inject
        .pipe(plugins.inject(files))

        // Rebase
        .pipe(rebase({
            script: {
            '(\/[^"]*\/)': '/frontend/js/'
            }
        }))

        // Write
        .pipe(gulp.dest(config.dist.styleguide));
});




/* Clean/clear
   ========================================================================== */
gulp.task('clean', function(done) {
    del([
        distPath + '**',
        'app/Resources/' + config.project.mainBundleName + '/views/' + config.project.mainJsInclude.folder + '/' + config.project.mainJsInclude.fileName
    ], done);
});




/* Default tasks
   ========================================================================== */
// Watch
gulp.task('watch', function() {
    // Livereload
   plugins.livereload.listen();
   gulp.watch(config.liveReloadFiles).on('change', function(file) {
       plugins.livereload.changed(file.path);
       runSequence('styleguide', 'styleguide-dev-js');
   });

    // Styles
    gulp.watch(config.scss, ['styles']);

    // Scripts
    gulp.watch(config.js.app, ['inject-dev-scripts']);

    // Images
    gulp.watch(config.img, ['images']);
});


// Build
gulp.task('build', function(done) {
    runSequence(
        'clean',
        'atsyles',
        ['clear-symfony-cache', 'styles', 'inject-prod-scripts', 'images', 'fonts'],
        'styleguide-prod-js',
    done);
});


// Build Deploy
gulp.task('build-deploy', function() {
    allowChmod = false;

    gulp.start('build');
});


// Default
gulp.task('default', function(done) {
    runSequence(
        'clean',
        'atstyles',
        ['clear-symfony-cache', 'styles', 'inject-dev-scripts', 'images', 'fonts'],
        'styleguide-dev-js',
    done);
});

gulp.task('default-watch',['default', 'watch'], function() {});




/* Other tasks
   ========================================================================== */
// Clear symfony cache
gulp.task('clear-symfony-cache', plugins.shell.task([
    'rm -rf app/cache/*'
]));


// Migrate
gulp.task('migrate', plugins.shell.task([
    'app/console doctrine:migrations:migrate --no-interaction'
]));

// reindex search
gulp.task('reindex', plugins.shell.task([
    'app/console kuma:search:populate full'
]));

// Clear Cache
gulp.task('cc', plugins.shell.task([
    'php app/console cache:clear --ansi',
    'php app/console assetic:dump --ansi',
    'php app/console assets:install web --symlink --ansi'
]));

// Install for Bower & npm
gulp.task('install_npm_bower', plugins.shell.task([
    'npm install',
    'bower install'
]));

/* SPRITES // TODO: retina!
 ========================================================================== */
gulp.task('sprites', function () {
    var spriteData = gulp.src(at_config.src + '/ui/img/sprite/*.png')
        .pipe(spritesmith({
                    padding: 10,
                    retinaSrcFilter: [at_config.src + '/ui/img/sprite/*-2x.png'],
                    imgName: 'sprite.png',
                    retinaImgName: 'sprite-2x.png',
                    imgPath: '/BebiProgram/img/sprite.png',
                    retinaImgPath:  '/BebiProgram/img/sprite-2x.png',
                    cssName: '_sprite.scss'
            })
        );

    spriteData.css.pipe(gulp.dest(at_config.src + '/ui/scss/_partials/'));
    spriteData.img.pipe(gulp.dest(at_config.src + '/ui/img/'));
});

/* SASS
 ========================================================================== */
gulp.task('sass', function () {
    return gulp.src(at_config.src + '/ui/scss/**/*.scss')
        .pipe(sourcemaps.init())
        .pipe(
            sass({
                style: 'compressed',
                errLogToConsole: true
            })
        )
        .on('error', function (err) {
            console.log('Sass error:', err.message);

            if(showErrorNotifications){
                notifier.notify({
                    'title': 'SASS ERROR',
                    'message': err.message
                });
            }

            this.emit('end');
        })
        .pipe(autoprefixer('last 3 version'))
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest(at_config.destSrc + '/css'));
});

gulp.task('atstyles', function () {
    runSequence('sprites', 'sass', 'styleguide');
});

/* WATCH
 ========================================================================== */
gulp.task('at-watch', function() {
    gulp.watch([at_config.src + '/ui/img/sprite/*.png'], ['sprites']);
    gulp.watch([at_config.src + '/ui/scss/**/*.scss'], ['sass', 'styleguide', function () { browserSync.reload('*.css')}]);
    gulp.watch([at_config.src + '/ui/js/**/*.js'], browserSync.reload);
    gulp.watch([at_config.src + '/views/**/*.twig'], browserSync.reload);
    gulp.watch(['app/DoctrineMigrations/*.php'], ['migrate', function () { browserSync.reload }]);
});

/* BROWSER SYNC
 ========================================================================== */
gulp.task('browser-sync', ['at-watch'], function() {
    browserSync.init({
        proxy: "bebiprogram.loc",
        open: false,
        ghostMode: false
    });
});

gulp.task('browser-sync2', ['at-watch'], function() {
    browserSync.init({
        proxy: "localhost:8000",
        open: false,
        ghostMode: false
    });
});