diff --git a/app/generator.js b/app/generator.js
index 64db0c1a5..40e8e7b50 100644
--- a/app/generator.js
+++ b/app/generator.js
@@ -19,6 +19,12 @@ export default class Generator extends Base {
defaults: false
});
+ this.option('gulp', {
+ desc: 'Use experimental Gulp configuration',
+ type: Boolean,
+ defaults: false
+ });
+
this.option('app-suffix', {
desc: 'Allow a custom suffix to be added to the module name',
type: String,
@@ -129,6 +135,11 @@ export default class Generator extends Base {
this.filters[answers.router] = true;
this.filters.bootstrap = !!answers.bootstrap;
this.filters.uibootstrap = !!answers.uibootstrap;
+
+ this.scriptExt = answers.script === 'coffee' ? 'coffee' : 'js';
+ this.templateExt = answers.markup;
+ this.styleExt = answers.stylesheet;
+
cb();
}.bind(this));
},
@@ -243,7 +254,14 @@ export default class Generator extends Base {
this.log('\n# Project\n');
- this.prompt([{
+ this.prompt([/*{
+ type: 'list',
+ name: 'buildtool',
+ message: 'Would you like to use Gulp (experimental) instead of Grunt?',
+ choices: ['Grunt', 'Gulp'],
+ default: 0,
+ filter: val => val.toLowerCase()
+ }, */{
type: 'list',
name: 'testing',
message: 'What would you like to write tests with?',
@@ -268,10 +286,10 @@ export default class Generator extends Base {
return answers.testing === 'mocha';
}
}], function (answers) {
- /**
- * Default to grunt until gulp support is implemented
- */
- this.filters.grunt = true;
+ this.filters.grunt = !this.options['gulp'];
+ this.filters.gulp = !!this.options['gulp'];
+ // this.filters.grunt = answers.buildtool === 'grunt';
+ // this.filters.gulp = answers.buildtool === 'gulp';
this.filters[answers.testing] = true;
if (answers.testing === 'mocha') {
diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile(grunt).js
similarity index 100%
rename from app/templates/Gruntfile.js
rename to app/templates/Gruntfile(grunt).js
diff --git a/app/templates/_package.json b/app/templates/_package.json
index f070f4216..09d2e0ea6 100644
--- a/app/templates/_package.json
+++ b/app/templates/_package.json
@@ -37,7 +37,52 @@
},
"devDependencies": {
"autoprefixer": "^6.0.0",
- "babel-core": "^5.6.4",
+ "babel-core": "^5.6.4",<% if(filters.gulp) { %>
+ "del": "^2.0.2",
+ "gulp": "^3.9.0",
+ "gulp-add-src": "^0.2.0",
+ "gulp-angular-templatecache": "^1.7.0",
+ "gulp-autoprefixer": "2.3.1",<% if(filters.babel) { %>
+ "gulp-babel": "^5.1.0",<% } %>
+ "gulp-cache": "^0.2.10",
+ "gulp-concat": "^2.6.0",
+ "gulp-filter": "^2.0.2",
+ "gulp-imagemin": "^2.2.1",
+ "gulp-inject": "^1.3.1",
+ "gulp-jshint": "^1.11.0",<% if(filters.less) { %>
+ "gulp-less": "3.0.3",<% } %>
+ "gulp-livereload": "^3.8.0",
+ "gulp-load-plugins": "^1.0.0-rc.1",
+ "gulp-minify-css": "^1.1.6",
+ "gulp-mocha": "^2.1.3",
+ "gulp-ng-annotate": "^1.1.0",
+ "gulp-ng-constant": "^1.1.0",
+ "gulp-plumber": "^1.0.1",
+ "gulp-rename": "^1.2.2",
+ "gulp-rev": "^5.0.0",
+ "gulp-rev-replace": "^0.4.2",
+ "gulp-sort": "^1.1.1",
+ "gulp-sourcemaps": "^1.5.2",
+ "gulp-svgmin": "^1.1.2",
+ "gulp-uglify": "^1.2.0",
+ "gulp-useref": "^1.2.0",
+ "gulp-util": "^3.0.5",
+ "gulp-watch": "^4.3.5",<% if(filters.jade) { %>
+ "gulp-jade": "^1.0.1",<% } if(filters.stylus) { %>
+ "gulp-stylus": "^2.0.4",
+ "gulp-stylint": "^1.1.3",
+ "nib": "^1.1.0",<% } if(filters.sass) { %>
+ "gulp-sass": "^2.0.1",
+ "gulp-scss-lint": "^0.2.1",<% } if(filters.less) { %>
+ "gulp-less": "^3.0.3",
+ "gulp-recess": "^1.1.2",<% } if(filters.coffee) { %>
+ "gulp-coffeelint": "^0.5.0",
+ "gulp-coffee": "^2.3.1",<% } %>
+ "utile": "~0.3.0",
+ "nodemon": "^1.3.7",
+ "run-sequence": "^1.1.0",
+ "lazypipe": "^0.2.4",
+ "wiredep": "^2.2.2",<% } /*end gulp*/ if(filters.grunt) { %>
"grunt": "~0.4.5",
"grunt-wiredep": "^2.0.0",
"grunt-concurrent": "^2.0.1",
@@ -49,11 +94,9 @@
"grunt-contrib-jshint": "~0.11.2",
"grunt-contrib-uglify": "~0.11.0",
"grunt-contrib-watch": "~0.6.1",<% if (filters.jade) { %>
- "grunt-contrib-jade": "^0.15.0",
- "karma-ng-jade2js-preprocessor": "^0.2.0",<% } %><% if (filters.less) { %>
+ "grunt-contrib-jade": "^0.15.0",<% } %><% if (filters.less) { %>
"grunt-contrib-less": "^1.0.0",<% } %><% if(filters.babel) { %>
- "karma-babel-preprocessor": "^5.2.1",<% } %>
- "grunt-babel": "~5.0.0",
+ "grunt-babel": "~5.0.0",<% } %>
"grunt-google-cdn": "~0.4.0",
"grunt-jscs": "^2.1.0",
"grunt-newer": "^1.1.1",
@@ -73,39 +116,41 @@
"grunt-contrib-sass": "^0.9.0",<% } %><% if(filters.stylus) { %>
"grunt-contrib-stylus": "~0.22.0",<% } %>
"jit-grunt": "^0.9.1",
- "time-grunt": "^1.2.1",
"grunt-express-server": "^0.5.1",
"grunt-postcss": "~0.7.1",
"grunt-open": "~0.2.3",
+ "time-grunt": "^1.2.1",
+ "grunt-mocha-test": "~0.12.7",
+ "grunt-mocha-istanbul": "^3.0.1",<% } /*end grunt*/ %>
"open": "~0.0.4",
"jshint-stylish": "~2.1.0",
"connect-livereload": "^0.5.3",
- "mocha": "^2.2.5",
- "grunt-mocha-test": "~0.12.7",
- "grunt-mocha-istanbul": "^3.0.1",
"istanbul": "~0.4.1",
"chai": "^3.2.0",
"sinon": "^1.16.1",
"chai-as-promised": "^5.1.0",
"chai-things": "^0.2.0",
- "sinon-chai": "^2.8.0",<% if (filters.mocha) { %>
- "karma-mocha": "^0.2.0",
- "karma-chai-plugins": "^0.6.0",<% } if (filters.jasmine) { %>
- "jasmine-core": "^2.3.4",
- "karma-jasmine": "~0.3.0",
- "jasmine-spec-reporter": "^2.4.0",<% } %>
+ "karma": "~0.13.3",
"karma-ng-scenario": "~0.1.0",
"karma-firefox-launcher": "~0.1.6",
"karma-script-launcher": "~0.1.0",
"karma-chrome-launcher": "~0.2.0",
- "requirejs": "~2.1.11",
"karma-requirejs": "~0.2.2",
"karma-jade-preprocessor": "0.0.11",
- "phantomjs": "^1.9.18",
- "karma-phantomjs-launcher": "~0.2.0",
- "karma": "~0.13.3",
- "karma-ng-html2js-preprocessor": "~0.2.0",
+ "karma-phantomjs-launcher": "~0.2.0",<% if (filters.jade) { %>
+ "karma-ng-jade2js-preprocessor": "^0.2.0",<% } else { %>
+ "karma-ng-html2js-preprocessor": "~0.2.0",<% } %>
"karma-spec-reporter": "~0.0.20",
+ "sinon-chai": "^2.8.0",<% if (filters.mocha) { %>
+ "mocha": "^2.2.5",
+ "karma-mocha": "^0.2.0",
+ "karma-chai-plugins": "^0.6.0",<% } if (filters.jasmine) { %>
+ "jasmine-core": "^2.3.4",
+ "karma-jasmine": "~0.3.0",
+ "jasmine-spec-reporter": "^2.4.0",<% } if(filters.babel) { %>
+ "karma-babel-preprocessor": "^5.2.1",<% } %>
+ "requirejs": "~2.1.11",
+ "phantomjs": "^1.9.18",
"proxyquire": "^1.0.1",
"supertest": "^1.1.0"
},
@@ -115,7 +160,7 @@
},
"scripts": {
"start": "node server",
- "test": "grunt test",
+ "test": "<%= filters.grunt ? 'grunt' : 'gulp' %> test",
"update-webdriver": "node node_modules/grunt-protractor-runner/node_modules/protractor/bin/webdriver-manager update"
},
"private": true
diff --git a/app/templates/gulpfile.babel(gulp).js b/app/templates/gulpfile.babel(gulp).js
new file mode 100644
index 000000000..18f8d1d0e
--- /dev/null
+++ b/app/templates/gulpfile.babel(gulp).js
@@ -0,0 +1,478 @@
+// Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= rootGeneratorName() %> <%= rootGeneratorVersion() %>
+'use strict';
+
+import _ from 'lodash';
+import del from 'del';
+import gulp from 'gulp';
+import path from 'path';
+import gulpLoadPlugins from 'gulp-load-plugins';
+import http from 'http';
+import open from 'open';
+import lazypipe from 'lazypipe';
+import {stream as wiredep} from 'wiredep';
+import nodemon from 'nodemon';
+import runSequence from 'run-sequence';<% if(filters.stylus) { %>
+import nib from 'nib';<% } %>
+
+var plugins = gulpLoadPlugins();
+var config;
+
+const paths = {
+ appPath: require('./bower.json').appPath || 'client',
+ client: {
+ assets: 'client/assets/**/*',
+ images: 'client/assets/images/*',
+ scripts: [
+ 'client/**/*.<%= scriptExt %>',
+ '!client/bower_components/**/*.js'
+ ],
+ styles: ['client/{app,components}/**/*.<%= styleExt %>'],
+ mainStyle: 'client/app/app.<%= styleExt %>',
+ views: 'client/{app,components}/**/*.<%= templateExt %>',
+ mainView: 'client/index.html',
+ test: ['client/**/*.spec.<%= scriptExt %>'],
+ testRequire: [
+ 'client/bower_components/angular/angular.js',
+ 'client/bower_components/angular-mocks/angular-mocks.js',
+ 'client/bower_components/angular-resource/angular-resource.js',
+ 'client/bower_components/angular-cookies/angular-cookies.js',
+ 'client/bower_components/angular-sanitize/angular-sanitize.js',
+ 'client/bower_components/angular-route/angular-route.js',
+ 'client/**/*.spec.<%= scriptExt %>'
+ ],
+ bower: 'client/bower_components/'
+ },
+ server: {
+ scripts: ['server/**/*.<%= scriptExt %>'],
+ json: ['server/**/*.json'],
+ test: [
+ 'server/**/*.spec.js',
+ 'server/**/*.mock.js',
+ 'server/**/*.integration.js'
+ ]
+ },
+ karma: 'karma.conf.js',
+ dist: 'dist'
+};
+
+/********************
+ * Helper functions
+ ********************/
+
+function onServerLog(log) {
+ console.log(plugins.util.colors.white('[') +
+ plugins.util.colors.yellow('nodemon') +
+ plugins.util.colors.white('] ') +
+ log.message);
+}
+
+function checkAppReady(cb) {
+ var options = {
+ host: 'localhost',
+ port: config.port
+ };
+ http
+ .get(options, () => cb(true))
+ .on('error', () => cb(false));
+}
+
+// Call page until first success
+function whenServerReady(cb) {
+ var serverReady = false;
+ var appReadyInterval = setInterval(() =>
+ checkAppReady((ready) => {
+ if (!ready || serverReady) {
+ return;
+ }
+ clearInterval(appReadyInterval);
+ serverReady = true;
+ cb();
+ }),
+ 100);
+}
+
+/********************
+ * Reusable pipelines
+ ********************/
+
+let lintClientScripts = lazypipe()<% if(filters.coffee) { %>
+ .pipe(plugins.coffeelint)
+ .pipe(plugins.coffeelint.reporter);<% } else { %>
+ .pipe(plugins.jshint, 'client/.jshintrc')
+ .pipe(plugins.jshint.reporter, 'jshint-stylish');<% } %>
+
+let lintServerScripts = lazypipe()<% if(filters.coffee) { %>
+ .pipe(plugins.coffeelint)
+ .pipe(plugins.coffeelint.reporter);<% } else { %>
+ .pipe(plugins.jshint, 'server/.jshintrc')
+ .pipe(plugins.jshint.reporter, 'jshint-stylish');<% } %>
+
+let styles = lazypipe()
+ .pipe(plugins.sourcemaps.init)<% if(filters.stylus) { %>
+ .pipe(plugins.stylus, {
+ use: [nib()],
+ errors: true
+ })<% } if(filters.sass) { %>
+ .pipe(plugins.sass)<% } if(filters.less) { %>
+ .pipe(plugins.less)<% } %>
+ .pipe(plugins.autoprefixer, {browsers: ['last 1 version']})
+ .pipe(plugins.sourcemaps.write, '.');<% if(filters.babel || filters.coffee) { %>
+
+let transpile = lazypipe()
+ .pipe(plugins.sourcemaps.init)<% if(filters.babel) { %>
+ .pipe(plugins.babel)<% } else { %>
+ .pipe(plugins.coffee, {bare: true})<% } %>
+ .pipe(plugins.sourcemaps.write, '.');<% } %>
+
+/********************
+ * Env
+ ********************/
+
+gulp.task('env:all', () => {
+ let localConfig;
+ try {
+ localConfig = require('./server/config/local.env');
+ } catch (e) {
+ localConfig = {};
+ }
+ plugins.env({
+ vars: localConfig
+ });
+});
+gulp.task('env:test', () => {
+ plugins.env({
+ vars: {NODE_ENV: 'test'}
+ });
+});
+gulp.task('env:prod', () => {
+ plugins.env({
+ vars: {NODE_ENV: 'production'}
+ });
+});
+
+/********************
+ * Tasks
+ ********************/
+
+gulp.task('inject', cb => {
+ runSequence(['inject:js', 'inject:css', 'inject:<%= styleExt %>'], cb);
+});
+
+gulp.task('inject:js', () => {
+ return gulp.src(paths.client.mainView)
+ .pipe(plugins.inject(
+ gulp.src(_.union(paths.client.scripts, ['!client/**/*.spec.<%= scriptExt %>']), {read: false})
+ .pipe(plugins.sort()),
+ {
+ starttag: '',
+ endtag: '',
+ transform: (filepath) => ''
+ }))
+ .pipe(gulp.dest('client'));
+});
+
+gulp.task('inject:css', () => {
+ return gulp.src(paths.client.mainView)
+ .pipe(plugins.inject(
+ gulp.src('/client/**/*.css', {read: false})
+ .pipe(plugins.sort()),
+ {
+ starttag: '',
+ endtag: '',
+ transform: (filepath) => ''
+ }))
+ .pipe(gulp.dest('client'));
+});
+
+gulp.task('inject:<%= styleExt %>', () => {
+ return gulp.src('client/app/app.<%= styleExt %>')
+ .pipe(plugins.inject(
+ gulp.src(_.union(paths.client.styles, ['!' + paths.client.mainStyle]), {read: false})
+ .pipe(plugins.sort()),
+ {
+ starttag: '// injector',
+ endtag: '// endinjector',
+ transform: (filepath) => {
+ let newPath = filepath
+ .replace('/client/app/', '')
+ .replace('/client/components/', '../components/')
+ .replace(/_(.*).<%= styleExt %>/, (match, p1, offset, string) => p1)
+ .replace('.<%= styleExt %>', '');
+ return '@import \'' + newPath + '\';';
+ }
+ }))
+ .pipe(gulp.dest('client/app'));
+});
+
+gulp.task('styles', () => {
+ return gulp.src(paths.client.mainStyle)
+ .pipe(styles())
+ .pipe(gulp.dest('.tmp/app'));
+});<% if(filters.babel || filters.coffee) { %>
+
+gulp.task('transpile:client', () => {
+ return gulp.src(paths.client.scripts)
+ .pipe(transpile())
+ .pipe(gulp.dest('.tmp'));
+});<% } %>
+
+gulp.task('transpile:server', () => {
+ return gulp.src(_.union(paths.server.scripts, paths.server.json))
+ .pipe(transpile())
+ .pipe(gulp.dest(paths.dist + '/server'));
+});
+
+gulp.task('lint:scripts', cb => runSequence(['lint:scripts:client', 'lint:scripts:server'], cb));
+
+gulp.task('lint:scripts:client', () => {
+ return gulp.src(_.union(paths.client.scripts, _.map(paths.client.test, blob => '!' + blob)))
+ .pipe(lintClientScripts());
+});
+
+gulp.task('lint:scripts:server', () => {
+ return gulp.src(_.union(paths.server.scripts, _.map(paths.server.test, blob => '!' + blob)))
+ .pipe(lintServerScripts());
+});
+
+gulp.task('clean:tmp', () => del(['.tmp/**/*']));
+
+gulp.task('start:client', cb => {
+ whenServerReady(() => {
+ open('http://localhost:' + config.port);
+ cb();
+ });
+});
+
+gulp.task('start:server', () => {
+ process.env.NODE_ENV = process.env.NODE_ENV || 'development';
+ config = require('./server/config/environment');
+ nodemon('-w server server')
+ .on('log', onServerLog);
+});
+
+gulp.task('watch', () => {
+ var testFiles = _.union(paths.client.test, paths.server.test);
+
+ plugins.livereload.listen();
+
+ plugins.watch(paths.client.styles, () => { //['inject:<%= styleExt %>']
+ gulp.src(paths.client.mainStyle)
+ .pipe(plugins.plumber())
+ .pipe(styles())
+ .pipe(gulp.dest('.tmp/app'))
+ .pipe(plugins.livereload());
+ });
+
+ plugins.watch(paths.client.views)
+ .pipe(plugins.plumber())
+ .pipe(plugins.livereload());
+
+ plugins.watch(paths.client.scripts) //['inject:js']
+ .pipe(plugins.plumber())<% if(filters.babel || filters.coffee) { %>
+ .pipe(transpile())
+ .pipe(gulp.dest('.tmp'))<% } %>
+ .pipe(plugins.livereload());
+
+ plugins.watch(_.union(paths.server.scripts, testFiles))
+ .pipe(plugins.plumber())
+ .pipe(lintServerScripts())
+ .pipe(plugins.livereload());
+
+ gulp.watch('bower.json', ['wiredep:client']);
+});
+
+gulp.task('serve', cb => {
+ runSequence(['clean:tmp', 'constant'],
+ ['lint:scripts', 'inject'<% if(filters.jade) { %>, 'jade'<% } %>],
+ ['wiredep:client'],<% if(filters.babel || filters.coffee) { %>
+ ['transpile:client', 'styles'],<% } else { %>
+ 'styles',<% } %>
+ ['start:server', 'start:client'],
+ 'watch',
+ cb);
+});
+
+gulp.task('test', cb => {
+ return runSequence('test:server', 'test:client', cb);
+});
+
+gulp.task('test:server', cb => {
+ runSequence(
+ 'env:all',
+ 'env:test',
+ 'mocha:unit',
+ //'mocha:coverage',
+ cb);
+});
+
+gulp.task('mocha:unit', () => {
+ return gulp.src(paths.server.test)
+ .pipe(plugins.mocha({
+ reporter: 'spec',
+ require: [
+ './mocha.conf'
+ ]
+ }))
+ .once('end', function() {
+ process.exit();
+ });
+});
+
+gulp.task('test:client', () => {
+ let testFiles = _.union(paths.client.testRequire, paths.client.test);
+ return gulp.src(testFiles)
+ .pipe(plugins.karma({
+ configFile: paths.karma,
+ action: 'watch'
+ }));
+});
+
+// inject bower components
+gulp.task('wiredep:client', () => {
+ return gulp.src(paths.client.mainView)
+ .pipe(wiredep({
+ exclude: [
+ /bootstrap-sass-official/,
+ /bootstrap.js/,
+ /json3/,
+ /es5-shim/,
+ /bootstrap.css/,
+ /font-awesome.css/
+ ],
+ ignorePath: paths.appPath
+ }))
+ .pipe(gulp.dest('client/'));
+});
+
+gulp.task('wiredep:test', () => {
+ gulp.src(paths.karma)
+ .pipe(wiredep({
+ exclude: [
+ /bootstrap-sass-official/,
+ /bootstrap.js/,
+ '/json3/',
+ '/es5-shim/',
+ /bootstrap.css/,
+ /font-awesome.css/
+ ],
+ devDependencies: true
+ }))
+ .pipe(gulp.dest('./'));
+});
+
+/********************
+ * Build
+ ********************/
+
+//FIXME: looks like font-awesome isn't getting loaded
+gulp.task('build', cb => {
+ runSequence(
+ 'clean:dist',
+ 'inject',
+ 'wiredep:client',
+ [
+ 'build:images',
+ 'copy:extras',
+ 'copy:assets',
+ 'copy:server',
+ 'transpile:server',
+ 'build:client'
+ ],
+ cb);
+});
+
+gulp.task('clean:dist', () => del(['dist/**/*']));
+
+gulp.task('build:client', ['transpile:client', 'styles', 'html'], () => {
+ var appFilter = plugins.filter('**/app.js');
+ var jsFilter = plugins.filter('**/*.js');
+ var cssFilter = plugins.filter('**/*.css');
+ var htmlFilter = plugins.filter('**/*.html');<% if(filters.jade) { %>
+ var assetsFilter = plugins.filter('**/*.{js,css}');<% } %>
+
+ let assets = plugins.useref.assets({searchPath: ['client', '.tmp']});
+
+ return gulp.src(paths.mainView)<% if(filters.jade) { %>
+ .pipe(plugins.jade({pretty: true}))<% } %>
+ .pipe(assets)
+ .pipe(appFilter)
+ .pipe(plugins.addSrc.append('.tmp/templates.js'))
+ .pipe(plugins.concat('app/app.js'))
+ .pipe(appFilter.restore())
+ .pipe(jsFilter)
+ .pipe(plugins.ngAnnotate())
+ .pipe(plugins.uglify())
+ .pipe(jsFilter.restore())
+ .pipe(cssFilter)
+ .pipe(plugins.minifyCss({
+ cache: true,
+ processImportFrom: ['!fonts.googleapis.com']
+ }))
+ .pipe(cssFilter.restore())
+ .pipe(plugins.rev())
+ .pipe(assets.restore())
+ .pipe(plugins.revReplace())
+ .pipe(plugins.useref())<% if(filters.jade) { %>
+ .pipe(assetsFilter)<% } %>
+ .pipe(gulp.dest(paths.dist + '/client'));
+});
+
+gulp.task('html', function() {
+ return gulp.src('client/{app,components}/**/*.html')
+ .pipe(plugins.angularTemplatecache({
+ module: '<%= scriptAppName %>'
+ }))
+ .pipe(gulp.dest('.tmp'));
+});<% if (filters.jade) { %>
+gulp.task('jade', function() {
+ gulp.src(paths.client.views)
+ .pipe(plugins.jade())
+ .pipe(gulp.dest('.tmp'));
+});<% } %>
+
+gulp.task('constant', function() {
+ let sharedConfig = require('./server/config/environment/shared');
+ plugins.ngConstant({
+ name: '<%= scriptAppName %>.constants',
+ deps: [],
+ wrap: true,
+ stream: true,
+ constants: { appConfig: sharedConfig }
+ })
+ .pipe(plugins.rename({
+ basename: 'app.constant'
+ }))
+ .pipe(gulp.dest('client/app/'))
+})
+
+gulp.task('build:images', () => {
+ return gulp.src('client/assets/images/**/*')
+ .pipe(plugins.imagemin({
+ optimizationLevel: 5,
+ progressive: true,
+ interlaced: true
+ }))
+ .pipe(gulp.dest(paths.dist + '/client/assets/images'));
+});
+
+gulp.task('copy:extras', () => {
+ return gulp.src([
+ 'client/favicon.ico',
+ 'client/robots.txt'
+ ], { dot: true })
+ .pipe(gulp.dest(paths.dist + '/client'));
+});
+
+gulp.task('copy:assets', () => {
+ return gulp.src([paths.client.assets, '!' + paths.client.images])
+ .pipe(gulp.dest(paths.dist + '/client/assets'));
+});
+
+gulp.task('copy:server', () => {
+ return gulp.src([
+ 'package.json',
+ 'bower.json',
+ '.bowerrc'
+ ], {cwdbase: true})
+ .pipe(gulp.dest(paths.dist));
+});
diff --git a/readme.md b/readme.md
index 213fd4ca1..1a88fe332 100644
--- a/readme.md
+++ b/readme.md
@@ -41,7 +41,7 @@ Run `grunt` for building, `grunt serve` for preview, and `grunt serve:dist` for
**General**
-* Build Systems: `Grunt`, `Gulp` (Coming Soon)
+* Build Systems: `Grunt`, `Gulp` (experimental)
* Testing:
* `Jasmine`
* `Mocha + Chai + Sinon`
@@ -113,6 +113,7 @@ Options:
--skip-cache # Do not remember prompt answers Default: false
--skip-install # Do not install dependencies Default: false
--app-suffix # Allow a custom suffix to be added to the module name Default: App
+ --gulp # Use the experimental Gulp config instead of Grunt Default: false
Arguments:
name Type: String Required: false
diff --git a/test/test-file-creation.js b/test/test-file-creation.js
index 555036c94..b7bbe9b70 100644
--- a/test/test-file-creation.js
+++ b/test/test-file-creation.js
@@ -11,6 +11,7 @@ var recursiveReadDir = require('recursive-readdir');
describe('angular-fullstack generator', function () {
var gen, defaultOptions = {
+ buildtool: 'grunt',
script: 'js',
babel: true,
markup: 'html',