From 7506f0e1825fad348ee8f448c33a07d80df3a27b Mon Sep 17 00:00:00 2001 From: Pawel Wszola Date: Wed, 30 Apr 2014 23:46:03 +0200 Subject: [PATCH] feat(gen): add support for Gulp Add an option to use Gulp instead of Grunt --- app/index.js | 47 +++++-- templates/common/Gulpfile.js | 219 +++++++++++++++++++++++++++++++++ templates/common/_package.json | 34 ++++- 3 files changed, 290 insertions(+), 10 deletions(-) create mode 100644 templates/common/Gulpfile.js diff --git a/app/index.js b/app/index.js index d210c8486..cef5c4881 100644 --- a/app/index.js +++ b/app/index.js @@ -119,15 +119,43 @@ Generator.prototype.welcome = function welcome() { } }; -Generator.prototype.askForCompass = function askForCompass() { +Generator.prototype.askForGulp = function askForGulp() { var cb = this.async(); this.prompt([{ + type: 'confirm', + name: 'gulp', + message: 'Would you like to use Gulp (experimental) instead of Grunt?', + default: false + }], function (props) { + this.gulp = props.gulp; + + cb(); + }.bind(this)); +}; + +Generator.prototype.askForStyles = function askForStyles() { + var gulp = this.gulp; + var cb = this.async(); + + this.prompt([{ + type: 'confirm', + name: 'sass', + message: 'Would you like to use Sass?', + default: true, + when: function () { + return gulp; + } + }, { type: 'confirm', name: 'compass', message: 'Would you like to use Sass (with Compass)?', - default: true + default: true, + when: function () { + return !gulp; + } }], function (props) { + this.sass = props.sass; this.compass = props.compass; cb(); @@ -136,20 +164,21 @@ Generator.prototype.askForCompass = function askForCompass() { Generator.prototype.askForBootstrap = function askForBootstrap() { var compass = this.compass; + var gulp = this.gulp; var cb = this.async(); this.prompt([{ type: 'confirm', name: 'bootstrap', - message: 'Would you like to include Bootstrap?', + message: 'Would you like to include Twitter Bootstrap?', default: true }, { type: 'confirm', name: 'compassBootstrap', - message: 'Would you like to use the Sass version of Bootstrap?', + message: 'Would you like to use the Sass version of Twitter Bootstrap?', default: true, when: function (props) { - return props.bootstrap && compass; + return !gulp && (props.bootstrap && compass); } }], function (props) { this.bootstrap = props.bootstrap; @@ -223,7 +252,7 @@ Generator.prototype.readIndex = function readIndex() { }; Generator.prototype.bootstrapFiles = function bootstrapFiles() { - var sass = this.compass; + var sass = this.compass || this.sass; var mainFile = 'main.' + (sass ? 's' : '') + 'css'; if (this.bootstrap && !sass) { @@ -255,7 +284,11 @@ Generator.prototype.packageFiles = function () { this.coffee = this.env.options.coffee; this.template('../../templates/common/_bower.json', 'bower.json'); this.template('../../templates/common/_package.json', 'package.json'); - this.template('../../templates/common/Gruntfile.js', 'Gruntfile.js'); + if (this.gulp) { + this.template('../../templates/common/Gulpfile.js', 'Gulpfile.js'); + } else { + this.template('../../templates/common/Gruntfile.js', 'Gruntfile.js'); + } }; Generator.prototype.imageFiles = function () { diff --git a/templates/common/Gulpfile.js b/templates/common/Gulpfile.js new file mode 100644 index 000000000..53f89a143 --- /dev/null +++ b/templates/common/Gulpfile.js @@ -0,0 +1,219 @@ +// Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= pkg.name %> <%= pkg.version %> +'use strict'; + +var gulp = require('gulp'); +var $ = require('gulp-load-plugins')(); +var openURL = require('open'); +var lazypipe = require('lazypipe'); +var wiredep = require('wiredep').stream; +var runSequence = require('run-sequence'); + +var yeoman = { + app: require('./bower.json').appPath || 'app', + dist: 'dist' +}; + +var paths = { + scripts: [yeoman.app + '/scripts/**/*.<% if (coffee) { %>coffee<% } else { %>js<% } %>'], + styles: [yeoman.app + '/styles/**/*.<% if (sass) { %>scss<% } else { %>css<% } %>'], + test: ['test/spec/**/*.<% if (coffee) { %>coffee<% } else { %>js<% } %>'], + testRequire: [ + yeoman.app + '/bower_components/angular/angular.js', + yeoman.app + '/bower_components/angular-mocks/angular-mocks.js', + yeoman.app + '/bower_components/angular-resource/angular-resource.js', + yeoman.app + '/bower_components/angular-cookies/angular-cookies.js', + yeoman.app + '/bower_components/angular-sanitize/angular-sanitize.js', + yeoman.app + '/bower_components/angular-route/angular-route.js',<% if (coffee) { %> + 'test/mock/**/*.coffee', + 'test/spec/**/*.coffee'<% } else { %> + 'test/mock/**/*.js', + 'test/spec/**/*.js'<% } %> + ], + karma: 'karma.conf.js', + views: { + main: yeoman.app + '/index.html', + files: [yeoman.app + '/views/**/*.html'] + } +}; + +//////////////////////// +// Reusable pipelines // +//////////////////////// + +var lintScripts = lazypipe()<% if (coffee) { %> + .pipe($.coffeelint) + .pipe($.coffeelint.reporter);<% } else { %> + .pipe($.jshint, '.jshintrc') + .pipe($.jshint.reporter, 'jshint-stylish');<% } %> + +var styles = lazypipe()<% if (sass) { %> + .pipe($.rubySass, { + style: 'expanded', + precision: 10 + })<% } %> + .pipe($.autoprefixer, 'last 1 version') + .pipe(gulp.dest, '.tmp/styles'); + +/////////// +// Tasks // +/////////// + +gulp.task('styles', function () { + return gulp.src(paths.styles) + .pipe(styles()); +});<% if (coffee) { %> + +gulp.task('coffee', function() { + return gulp.src(paths.scripts) + .pipe(lintScripts()) + .pipe($.coffee({bare: true}).on('error', $.util.log)) + .pipe(gulp.dest('.tmp/scripts')); +});<% } %> + +gulp.task('lint:scripts', function () { + return gulp.src(paths.scripts) + .pipe(lintScripts()); +}); + +gulp.task('clean:tmp', function () { + return gulp.src('.tmp', {read: false}).pipe($.clean()); +}); + +gulp.task('start:client', ['start:server', <% if (coffee) { %>'coffee', <% } %>'styles'], function () { + openURL('http://localhost:9000'); +}); + +gulp.task('start:server', function() { + $.connect.server({ + root: [yeoman.app, '.tmp'], + livereload: true, + // Change this to '0.0.0.0' to access the server from outside. + port: 9000 + }); +}); + +gulp.task('start:server:test', function() { + $.connect.server({ + root: ['test', yeoman.app, '.tmp'], + livereload: true, + port: 9001 + }); +}); + +gulp.task('watch', function () { + + $.watch({glob: paths.styles}) + .pipe($.plumber()) + .pipe(styles()) + .pipe($.connect.reload()); + + $.watch({glob: paths.views.files}) + .pipe($.plumber()) + .pipe($.connect.reload()); + + $.watch({glob: paths.scripts}) + .pipe($.plumber()) + .pipe(lintScripts())<% if (coffee) { %> + .pipe($.coffee({bare: true}).on('error', $.util.log)) + .pipe(gulp.dest('.tmp/scripts'))<% } %> + .pipe($.connect.reload()); + + $.watch({glob: paths.test}) + .pipe($.plumber()) + .pipe(lintScripts()); + + gulp.watch('bower.json', ['bower']); +}); + +gulp.task('serve', function (callback) { + runSequence('clean:tmp', + ['lint:scripts'], + ['start:client'], + 'watch', callback); +}); + +gulp.task('serve:prod', function() { + $.connect.server({ + root: [yeoman.dist], + livereload: true, + port: 9000 + }); +}); + +gulp.task('test', ['start:server:test'], function () { + var testToFiles = paths.testRequire.concat(paths.scripts, paths.test); + return gulp.src(testToFiles) + .pipe($.karma({ + configFile: paths.karma, + action: 'watch' + })); +}); + +// inject bower components +gulp.task('bower', function () { + return gulp.src(paths.views.main) + .pipe(wiredep({ + directory: yeoman.app + '/bower_components', + ignorePath: '..' + })) + .pipe(gulp.dest(yeoman.app + '/views')); +}); + +/////////// +// Build // +/////////// + +gulp.task('build', function (callback) { + runSequence('clean:dist', + ['images', 'copy:extras', 'copy:fonts', 'client:build'], + callback); +}); + +gulp.task('clean:dist', function () { + return gulp.src('dist', {read: false}).pipe($.clean()); +}); + +gulp.task('client:build', ['html', 'styles'], function () { + var jsFilter = $.filter('**/*.js'); + var cssFilter = $.filter('**/*.css'); + + return gulp.src(paths.views.main) + .pipe($.useref.assets({searchPath: [yeoman.app, '.tmp']})) + .pipe(jsFilter) + .pipe($.ngmin()) + .pipe($.uglify()) + .pipe(jsFilter.restore()) + .pipe(cssFilter) + .pipe($.minifyCss({cache: true})) + .pipe(cssFilter.restore()) + .pipe($.rev()) + .pipe($.useref.restore()) + .pipe($.revReplace()) + .pipe($.useref()) + .pipe(gulp.dest(yeoman.dist)); +}); + +gulp.task('html', function () { + return gulp.src(yeoman.app + '/views/**/*') + .pipe(gulp.dest(yeoman.dist + '/views')); +}); + +gulp.task('images', function () { + return gulp.src(yeoman.app + '/images/**/*') + .pipe($.cache($.imagemin({ + optimizationLevel: 5, + progressive: true, + interlaced: true + }))) + .pipe(gulp.dest(yeoman.dist + '/images')); +}); + +gulp.task('copy:extras', function () { + return gulp.src(yeoman.app + '/*/.*', { dot: true }) + .pipe(gulp.dest(yeoman.dist)); +}); + +gulp.task('copy:fonts', function () { + return gulp.src(yeoman.app + '/fonts/**/*') + .pipe(gulp.dest(yeoman.dist + '/fonts')); +}); diff --git a/templates/common/_package.json b/templates/common/_package.json index b629261bd..042cde65e 100644 --- a/templates/common/_package.json +++ b/templates/common/_package.json @@ -2,7 +2,35 @@ "name": "<%= _.slugify(appname) %>", "version": "0.0.0", "dependencies": {}, - "devDependencies": { + "devDependencies": {<% if (gulp) { %> + "gulp": "^3.6.2", + "gulp-connect": "^2.0.5", + "gulp-autoprefixer": "0.0.7", + "gulp-cache": "^0.1.3", + "gulp-clean": "^0.2.4", + "gulp-filter": "^0.4.1", + "gulp-imagemin": "^0.5.0", + "gulp-jshint": "^1.5.5", + "gulp-karma": "0.0.4", + "gulp-load-plugins": "^0.5.0", + "gulp-plumber": "^0.6.1", + "gulp-minify-css": "^0.3.4", + "gulp-rev": "^0.3.2", + "gulp-rev-replace": "^0.1.0", + "gulp-uglify": "^0.2.1", + "gulp-useref": "^0.4.2", + "gulp-util": "^2.2.14", + "gulp-watch": "^0.6.2", + "jshint-stylish": "^0.1.5", + "run-sequence": "^0.3.6", + "wiredep": "^1.4.4", + "lazypipe": "^0.2.1", + "gulp-ngmin": "^0.2.0", + "utile": "~0.2.1", + "open": "0.0.5",<% if (sass) { %> + "gulp-ruby-sass": "^0.4.3",<% } %><% if (coffee) { %> + "gulp-coffeelint": "^0.3.2", + "gulp-coffee": "^1.4.2",<% } %><% } else { %> "grunt": "~0.4.1", "grunt-autoprefixer": "~0.4.0", "grunt-bower-install": "~1.0.0", @@ -25,9 +53,9 @@ "grunt-rev": "~0.1.0", "grunt-svgmin": "~0.2.0", "grunt-usemin": "~2.0.0", - "jshint-stylish": "~0.1.3", "load-grunt-tasks": "~0.4.0", - "time-grunt": "~0.2.1" + "time-grunt": "~0.2.1",<% } %> + "jshint-stylish": "~0.1.3" }, "engines": { "node": ">=0.10.0"