Last active
June 21, 2021 04:12
-
-
Save OverZealous/8551946 to your computer and use it in GitHub Desktop.
Preliminary Gulpfile for replicating ngBoilerplate — Still a work in progress!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This file/module contains all configuration for the build process. | |
*/ | |
/** | |
* Load requires and directory resources | |
*/ | |
var join = require('path').join, | |
bowerrc = JSON.parse(require('fs').readFileSync('./.bowerrc', {encoding: 'utf8'})), | |
bowerJSON = bowerrc.json.replace(/^\.?\/?/, './'), | |
bower = require(bowerJSON), | |
pkg = require('./package.json'), | |
/** | |
* The `buildDir` folder is where our projects are compiled during | |
* development and the `compileDir` folder is where our app resides once it's | |
* completely built. | |
*/ | |
buildDir = 'build', | |
compileDir = 'compile', | |
vendorDir = bowerrc.directory, | |
templatesDir = 'templates', | |
indexFile = 'index.html', | |
jsDir = 'js', | |
cssDir = 'css', | |
assetsDir = 'assets'; | |
module.exports = { | |
buildDir: buildDir, | |
compileDir: compileDir, | |
// Relative paths to core files and folders for input and output | |
indexFile: indexFile, | |
jsDir: jsDir, | |
cssDir: cssDir, | |
assetsDir: assetsDir, | |
vendorDir: vendorDir, | |
templatesDir: templatesDir, | |
// allows settings reuse from package.json and bower.json | |
bowerJSON: bowerJSON, | |
bower: bower, | |
pkg: pkg, | |
/** | |
* This code is wrapped around the application code. It is used to "protect" | |
* the application code from the global scope. | |
*/ | |
moduleWrapper: { | |
header: '\n(function ( window, angular, undefined ) {\n\n', | |
footer: '\n})( window, window.angular );' | |
}, | |
/** | |
* Settings for the server task | |
* When run, this task will start a connect server on | |
* your build directory, great for livereload | |
*/ | |
server: { | |
port: 8081, // 0 = random port | |
host: null, // null/falsy means listen to all, but will auto open localhost | |
// Enable disable default auto open | |
// false: run with --open to open | |
// true: run with --no-open to not open, recommended if port is 0 | |
openByDefault: false, | |
// set to false to prevent request logging | |
// set to any non-`true` value to configure the logger | |
log: false, | |
// Live Reload server port | |
lrPort: 35729 | |
}, | |
/** | |
* Options passed into the various tasks. | |
* These are usually passed directly into the individual gulp plugins | |
*/ | |
taskOptions: { | |
csso: false, // set to true to prevent structural modifications | |
jshint: { | |
eqeqeq: true, | |
camelcase: true, | |
freeze: true, | |
immed: true, | |
latedef: true, | |
newcap: true, | |
undef: true, | |
unused: true, | |
browser: true, | |
globals: { | |
angular: false, | |
console: false | |
} | |
}, | |
less: {}, | |
recess: { | |
strictPropertyOrder: false, | |
noOverqualifying: false, | |
noUniversalSelectors: false | |
}, | |
uglify: {} | |
}, | |
/** | |
* This is a collection of file patterns that refer to our app code (the | |
* stuff in `src/`). These file paths are used in the configuration of | |
* build tasks. | |
* | |
* js - All project javascript, less tests | |
* jsunit - All the JS needed to run tests (in this setup, it uses the build results) | |
* tpl - contains our various templates | |
* html - just our main HTML file | |
* less - our main stylesheet | |
* assets - the rest of the files that are copied directly to the build | |
*/ | |
appFiles: { | |
js: [ 'src/**/!(app)*.js', 'src/**/*.js', '!src/**/*.spec.js', '!src/assets/**/*.js' ], | |
jsunit: [ join(buildDir, '/**/*.js'), 'src/**/*.spec.js', '!'+join(buildDir,'/assets/**/*.js'), '!'+join(buildDir, vendorDir, '**/*.js') ], | |
tpl: [ 'src/app/**/*.tpl.html', 'src/common/**/*.tpl.html' ], | |
html: join('src', indexFile), | |
less: 'src/less/main.less', | |
assets: join('src', assetsDir, '**/*.*') | |
}, | |
/** | |
* Similar to above, except this is the pattern of files to watch | |
* for live build and reloading. | |
*/ | |
watchFiles: { | |
js: [ 'src/**/*.js', '!src/**/*.spec.js', '!src/assets/**/*.js' ], | |
//jsunit: [ 'src/**/*.spec.js' ], // watch is handled by the karma plugin! | |
tpl: [ 'src/app/**/*.tpl.html', 'src/common/**/*.tpl.html' ], | |
html: [ join(buildDir, '**/*'), '!'+join(buildDir,indexFile), join('src',indexFile) ], | |
less: [ 'src/**/*.less' ], | |
assets: join('src',assetsDir,'**/*.*') | |
}, | |
/** | |
* This is a collection of files used during testing only. | |
*/ | |
testFiles: { | |
config: 'karma/karma.conf.js', | |
js: [ | |
'vendor/angular-mocks/angular-mocks.js' | |
] | |
}, | |
/** | |
* This contains files that are provided via bower. | |
* Vendor files under `js` are copied and minified, but not concatenated into the application | |
* js file. | |
* Vendor files under `jsConcat` are included in the application js file. | |
* Vendor files under `assets` are simply copied into the assets directory. | |
*/ | |
vendorFiles: { | |
js: [ | |
'vendor/angular/angular.js', | |
'vendor/firebase/firebase.js', | |
'vendor/angularfire/angularfire.js' | |
], | |
jsConcat: [ | |
'vendor/angular-bootstrap/ui-bootstrap-tpls.min.js', | |
'vendor/angular-ui-router/release/angular-ui-router.js', | |
'vendor/angular-ui-utils/modules/route/route.js' | |
], | |
assets: [ | |
] | |
}, | |
/** | |
* This contains details about files stored on a CDN, using gulp-cdnizer. | |
* file: glob or filename to match for replacement | |
* package: used to look up the version info of a bower package | |
* test: if provided, this will be used to fallback to the local file if the CDN fails to load | |
* cdn: template for the CDN filename | |
*/ | |
cdn: [ | |
{ | |
file: 'js/vendor/angular/angular.js', | |
package: 'angular', | |
test: 'window.angular', | |
cdn: '//ajax.googleapis.com/ajax/libs/angularjs/${ major }.${ minor }.${ patch }/angular.min.js' | |
} | |
] | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//<editor-fold desc="Node Requires, gulp, etc"> | |
var gulp = require('gulp'), | |
autoprefixer = require('gulp-autoprefixer'), | |
bump = require('gulp-bump'), | |
cdnizer = require('gulp-cdnizer'), | |
clean = require('gulp-clean'), | |
concat = require('gulp-concat'), | |
csso = require('gulp-csso'), | |
debug = require('gulp-debug'), | |
footer = require('gulp-footer'), | |
gutil = require('gulp-util'), | |
gzip = require('gulp-gzip'), | |
header = require('gulp-header'), | |
help = require('gulp-task-listing'), | |
_if = require('gulp-if'), | |
inject = require('gulp-inject'), | |
jshint = require('gulp-jshint'), | |
karma = require('gulp-karma'), | |
less = require('gulp-less'), | |
livereload = require('gulp-livereload'), | |
livereloadEmbed = require('gulp-embedlr'), | |
minifyHtml = require('gulp-minify-html'), | |
ngHtml2js = require('gulp-ng-html2js'), | |
ngmin = require('gulp-ngmin'), | |
plumber = require('gulp-plumber'), | |
recess = require('gulp-recess'), | |
rename = require('gulp-rename'), | |
rev = require('gulp-rev'), | |
tap = require('gulp-tap'), | |
uglify = require('gulp-uglify'), | |
watch = require('gulp-watch'), | |
_ = require('lodash'), | |
anysort = require('anysort'), | |
connect = require('connect'), | |
es = require('event-stream'), | |
fs = require('fs'), | |
http = require('http'), | |
lazypipe = require('lazypipe'), | |
open = require('open'), | |
path = require('path'), | |
runSequence = require('run-sequence'), | |
server = require('tiny-lr')(); | |
//</editor-fold> | |
/* | |
* TODO: | |
* - Banner for compressed JS/CSS | |
* - Changelog? | |
*/ | |
// Load user config and package data | |
var cfg = require('./build.config.js'); | |
// common variables | |
var concatName = cfg.pkg.name, | |
embedLR = false, | |
join = path.join; | |
//============================================= | |
// MAIN TASKS | |
//============================================= | |
gulp.task('default', ['watch']); | |
gulp.task('server-dist', ['compile'], function(cb) { | |
startServer(cfg.compileDir, cb); | |
}); | |
gulp.task('server', ['watch'], function(cb) { | |
startServer(cfg.buildDir, cb); | |
}); | |
gulp.task('build', function(cb) { | |
runSequence(['build-assets', 'build-scripts', 'build-styles'], ['build-html', 'test'], cb); | |
}); | |
gulp.task('watch', ['lr-server', 'build', 'test-watch'], function() { | |
watch({glob: cfg.watchFiles.js, emitOnGlob: false, name: 'JS'}) | |
.pipe(plumber()) | |
.pipe(jsBuildTasks()) | |
.pipe(livereload(server)); | |
watch({glob: cfg.watchFiles.tpl, emitOnGlob: false, name: 'Templates'}) | |
.pipe(plumber()) | |
.pipe(tplBuildTasks()) | |
.pipe(livereload(server)); | |
watch({glob: cfg.watchFiles.html, emitOnGlob: false, name: 'HTML'}, function() { | |
return buildHTML(); | |
}); | |
watch({glob: cfg.watchFiles.less, emitOnGlob: false, name: 'Styles'}, function() { | |
// run this way to ensure that a failed pipe doesn't break the watcher. | |
return buildStyles(); | |
}); | |
watch({glob: cfg.watchFiles.assets, emitOnGlob: false, name: 'Assets'}) | |
.pipe(gulp.dest(join(cfg.buildDir, cfg.assetsDir))); | |
}); | |
gulp.task('compile', function(cb) { | |
runSequence( | |
'compile-clean', | |
['compile-assets', 'compile-scripts', 'compile-styles'], | |
'compile-html', | |
cb | |
); | |
}); | |
gulp.task('clean', ['compile-clean', 'build-clean']); | |
gulp.task('help', help); | |
//============================================= | |
// UTILITIES | |
//============================================= | |
function readFile(filename) { | |
return fs.existsSync(filename) ? fs.readFileSync(filename, {encoding: 'utf8'}) : ''; | |
} | |
function insertRevGlob(f) { | |
// allows for rev'd filenames (which end with /-[0-9a-f]{8}.ext/ | |
return f.replace(/(\..*)$/, '?(-????????)$1'); | |
} | |
function startServer(root, cb) { | |
var devApp, devServer, devAddress, devHost, url, log=gutil.log, colors=gutil.colors; | |
devApp = connect(); | |
if(cfg.server.log) { | |
devApp.use(connect.logger(cfg.server.log===true ? 'dev' : cfg.server.log)); | |
} | |
devApp.use(connect.static(root)); | |
devServer = http.createServer(devApp).listen(cfg.server.port, cfg.server.host||undefined); | |
devServer.on('error', function(error) { | |
log(colors.underline(colors.red('ERROR'))+' Unable to start server!'); | |
cb(error); | |
}); | |
devServer.on('listening', function() { | |
devAddress = devServer.address(); | |
devHost = devAddress.address === '0.0.0.0' ? 'localhost' : devAddress.address; | |
url = 'http://' + devHost + ':' + devAddress.port + join('/', cfg.indexFile); | |
log(''); | |
log('Started dev server at '+colors.magenta(url)); | |
var openByDefault = cfg.server.openByDefault; | |
if(gutil.env.open || (openByDefault && gutil.env.open !== false)) { | |
log('Opening dev server URL in browser'); | |
if(openByDefault) { | |
log(colors.gray('(Run with --no-open to prevent automatically opening URL)')); | |
} | |
// Open the URL in the browser at this point. | |
open(url); | |
} else if(!openByDefault) { | |
log(colors.gray('(Run with --open to automatically open URL on startup)')); | |
} | |
log(''); | |
cb(); | |
}); | |
} | |
//============================================= | |
// SUB TASKS | |
//============================================= | |
//--------------------------------------------- | |
// HTML | |
//--------------------------------------------- | |
var buildHTML = function() { | |
var htmlFile = readFile(join(cfg.buildDir, cfg.indexFile)); | |
return gulp.src([join(cfg.buildDir, '/**/*.*'), '!' + join(cfg.buildDir, cfg.indexFile)], {read: false}) | |
.pipe(plumber()) | |
.pipe(inject(cfg.appFiles.html, { | |
addRootSlash: false, | |
sort: fileSorter, // see below | |
ignorePath: join('/',cfg.buildDir,'/') | |
})) | |
.pipe(_if(embedLR, livereloadEmbed({port: cfg.server.lrPort}))) | |
.pipe(gulp.dest(cfg.buildDir)) | |
.pipe(tap(function(file) { | |
var newHtmlFile = file.contents.toString(); | |
if(newHtmlFile !== htmlFile) { | |
htmlFile = newHtmlFile; | |
gulp.src(file.path).pipe(livereload(server)); | |
} | |
})); | |
}; | |
gulp.task('build-html', function() { | |
// NOTE: this task does NOT depend on buildScripts and buildStyles, | |
// therefore, it may incorrectly create the HTML file if called | |
// directly. | |
return buildHTML(); | |
}); | |
gulp.task('compile-html', function() { | |
// NOTE: this task does NOT depend on compileScripts and compileStyles, | |
// therefore, it may incorrectly create the HTML file if called | |
// directly. | |
return gulp.src([join(cfg.compileDir, '/**/*.*'), '!' + join(cfg.compileDir, cfg.indexFile)], {read: false}) | |
.pipe(inject(cfg.appFiles.html, { | |
addRootSlash: false, | |
sort: fileSorter, // see below | |
ignorePath: join('/', cfg.compileDir, '/') | |
})) | |
.pipe(cdnizer(cfg.cdn)) | |
.pipe(minifyHtml({empty:true,spare:true,quotes:true})) | |
.pipe(gulp.dest(cfg.compileDir)) | |
.pipe(gzip()) | |
.pipe(gulp.dest(cfg.compileDir)) | |
}); | |
// used by build-html to ensure correct file order during builds | |
var fileSorter = (function(){ | |
var as = anysort(_.flatten([ | |
// JS files are sorted by original vendor order, common, app, then everything else | |
cfg.vendorFiles.js.map(function(f){ return join(cfg.jsDir, insertRevGlob(f)); }), | |
cfg.vendorFiles.jsConcat.map(function(f){ return join(cfg.jsDir, insertRevGlob(f)); }), | |
join(cfg.jsDir, 'common/**/*.js'), | |
join(cfg.jsDir, 'app/**/!(app)*.js'), // exclude app.js so it comes last | |
join(cfg.jsDir, '**/*.js'), | |
// CSS order should be maintained via Less includes | |
join(cfg.cssDir, '**/*.css') | |
])); | |
return function(a,b){ return as(a.filepath, b.filepath) || a.filepath < b.filepath }; | |
})(); | |
//--------------------------------------------- | |
// JavaScript | |
//--------------------------------------------- | |
var jsFiles = function() { return gulp.src(cfg.appFiles.js); }, | |
jsBaseTasks = lazypipe() | |
.pipe(plumber) // jshint won't render parse errors without plumber | |
.pipe(function() { | |
return jshint(_.clone(cfg.taskOptions.jshint)); | |
}) | |
.pipe(jshint.reporter, 'jshint-stylish'), | |
jsBuildTasks = jsBaseTasks | |
.pipe(gulp.dest, join(cfg.buildDir, cfg.jsDir)), | |
tplFiles = function() { return gulp.src(cfg.appFiles.tpl); }, | |
tplBuildTasks = lazypipe() | |
.pipe(ngHtml2js, {moduleName: 'templates'}) | |
.pipe(gulp.dest, join(cfg.buildDir, cfg.jsDir, cfg.templatesDir)); | |
//noinspection FunctionWithInconsistentReturnsJS | |
gulp.task('build-scripts-vendor', function() { | |
var vendorFiles = [].concat(cfg.vendorFiles.js||[], cfg.vendorFiles.jsConcat||[]); | |
if(vendorFiles.length) { | |
return gulp.src(vendorFiles, {base: cfg.vendorDir}) | |
.pipe(gulp.dest(join(cfg.buildDir, cfg.jsDir, cfg.vendorDir))) | |
} | |
}); | |
gulp.task('build-scripts-app', function() { | |
return jsFiles().pipe(jsBuildTasks()); | |
}); | |
gulp.task('build-scripts-templates', function() { | |
return tplFiles().pipe(tplBuildTasks()); | |
}); | |
gulp.task('build-scripts', ['build-scripts-vendor', 'build-scripts-app', 'build-scripts-templates']); | |
gulp.task('compile-scripts', function() { | |
var appFiles, templates, files, concatFiles, vendorFiles; | |
appFiles = jsFiles() | |
.pipe(jsBaseTasks()) | |
.pipe(concat('appFiles.js')) // not used | |
.pipe(ngmin()) | |
.pipe(header(cfg.moduleWrapper.header)) | |
.pipe(footer(cfg.moduleWrapper.footer)); | |
templates = tplFiles() | |
.pipe(minifyHtml({empty: true, spare: true, quotes: true})) | |
.pipe(ngHtml2js({moduleName: 'templates'})) | |
.pipe(concat('templates.min.js')); // not used | |
files = [appFiles, templates]; | |
if(cfg.vendorFiles.jsConcat.length) { | |
files.unshift(gulp.src(cfg.vendorFiles.jsConcat)); | |
} | |
concatFiles = es.concat.apply(es, files) | |
.pipe(concat(concatName + '.js')) | |
.pipe(uglify(cfg.taskOptions.uglify)) | |
.pipe(rev()) | |
.pipe(gulp.dest(join(cfg.compileDir, cfg.jsDir))) | |
.pipe(gzip()) | |
.pipe(gulp.dest(join(cfg.compileDir, cfg.jsDir))); | |
if(cfg.vendorFiles.js.length) { | |
vendorFiles = gulp.src(cfg.vendorFiles.js, {base: cfg.vendorDir}) | |
.pipe(uglify(cfg.taskOptions.uglify)) | |
.pipe(rev()) | |
.pipe(gulp.dest(join(cfg.compileDir, cfg.jsDir, cfg.vendorDir))) | |
.pipe(gzip()) | |
.pipe(gulp.dest(join(cfg.compileDir, cfg.jsDir, cfg.vendorDir))); | |
return es.concat(vendorFiles, concatFiles); | |
} else { | |
return concatFiles; | |
} | |
}); | |
//--------------------------------------------- | |
// Less / CSS Styles | |
//--------------------------------------------- | |
var styleFiles = function() { return gulp.src(cfg.appFiles.less); }, | |
styleBaseTasks = lazypipe() | |
.pipe(recess, cfg.taskOptions.recess) | |
.pipe(less, cfg.taskOptions.less) | |
.pipe(autoprefixer), | |
buildStyles = function() { | |
return styleFiles() | |
.pipe( | |
styleBaseTasks() | |
// need to manually catch errors on recess/less :-( | |
.on('error', function() { | |
gutil.log(gutil.colors.red('Error')+' processing Less files.'); | |
}) | |
) | |
.pipe(gulp.dest(join(cfg.buildDir, cfg.cssDir))) | |
.pipe(livereload(server)) | |
}; | |
gulp.task('build-styles', function() { | |
return buildStyles(); | |
}); | |
gulp.task('compile-styles', function() { | |
return styleFiles() | |
.pipe(styleBaseTasks()) | |
.pipe(rename(concatName + '.css')) | |
.pipe(csso(cfg.taskOptions.csso)) | |
.pipe(rev()) | |
.pipe(gulp.dest(join(cfg.compileDir, cfg.cssDir))) | |
.pipe(gzip()) | |
.pipe(gulp.dest(join(cfg.compileDir, cfg.cssDir))) | |
}); | |
//--------------------------------------------- | |
// Unit Testing | |
//--------------------------------------------- | |
var testFiles = function() { | |
return gulp.src(_.flatten([cfg.vendorFiles.js, cfg.vendorFiles.jsConcat, cfg.testFiles.js, cfg.appFiles.jsunit])); | |
}; | |
gulp.task('test', ['build-scripts'], function() { | |
return testFiles() | |
.pipe(karma({ | |
configFile: cfg.testFiles.config | |
})) | |
}); | |
gulp.task('test-watch', ['build-scripts', 'test'], function() { | |
// NOT returned on purpose! | |
testFiles() | |
.pipe(karma({ | |
configFile: cfg.testFiles.config, | |
action: 'watch' | |
})) | |
}); | |
//--------------------------------------------- | |
// Assets | |
//--------------------------------------------- | |
// If you want to automate image compression, or font creation, | |
// this is the place to do it! | |
//noinspection FunctionWithInconsistentReturnsJS | |
gulp.task('build-assets-vendor', function() { | |
if(cfg.vendorFiles.assets.length) { | |
return gulp.src(cfg.vendorFiles.assets, {base: cfg.vendorDir}) | |
.pipe(gulp.dest(join(cfg.buildDir, cfg.assetsDir, cfg.vendorDir))) | |
} | |
}); | |
gulp.task('build-assets', ['build-assets-vendor'], function() { | |
return gulp.src(cfg.appFiles.assets) | |
.pipe(gulp.dest(join(cfg.buildDir, cfg.assetsDir))) | |
}); | |
//noinspection FunctionWithInconsistentReturnsJS | |
gulp.task('compile-assets-vendor', function() { | |
if(cfg.vendorFiles.assets.length) { | |
return gulp.src(cfg.vendorFiles.assets, {base: cfg.vendorDir}) | |
.pipe(gulp.dest(join(cfg.compileDir, cfg.assetsDir, cfg.vendorDir))) | |
} | |
}); | |
gulp.task('compile-assets', ['compile-assets-vendor'], function() { | |
return gulp.src(cfg.appFiles.assets) | |
.pipe(gulp.dest(join(cfg.compileDir, cfg.assetsDir))) | |
}); | |
//--------------------------------------------- | |
// Miscellaneous Tasks | |
//--------------------------------------------- | |
gulp.task('lr-server', function() { | |
embedLR = true; | |
server.listen(cfg.server.lrPort, function(err) { | |
if(err) { | |
console.log(err); | |
} | |
gutil.log('Started LiveReload server'); | |
}); | |
}); | |
gulp.task('build-clean', function() { | |
return gulp.src(cfg.buildDir, {read: false}).pipe(clean()); | |
}); | |
gulp.task('compile-clean', function() { | |
return gulp.src(cfg.compileDir, {read: false}).pipe(clean()); | |
}); | |
gulp.task('bump', function() { | |
var version = gutil.env['set-version'], | |
type = gutil.env.type, | |
msg = version ? ('Setting version to '+gutil.colors.yellow(version)) : ('Bumping '+gutil.colors.yellow(type||'patch') + ' version'); | |
gutil.log(''); | |
gutil.log(msg); | |
gutil.log(gutil.colors.gray('(You can set a specific version using --set-version <version>,')); | |
gutil.log(gutil.colors.gray(' or a specific type using --type <type>)')); | |
gutil.log(''); | |
return gulp.src(['./package.json', cfg.bowerJSON]) | |
.pipe(bump({type:type, version:version})) | |
.pipe(gulp.dest('./')); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"author": "Phil DeJarnett", | |
"name": "example", | |
"version": "0.0.1", | |
"homepage": "http://www.overzealous.com", | |
"licenses": { | |
"type": "", | |
"url": "" | |
}, | |
"bugs": "", | |
"repository": { | |
"type": "git", | |
"url": "" | |
}, | |
"dependencies": {}, | |
"devDependencies": { | |
"anysort": "~0.1.1", | |
"event-stream": "*", | |
"gulp": "3.*", | |
"gulp-autoprefixer": "*", | |
"gulp-cdnizer": "*", | |
"gulp-clean": "*", | |
"gulp-concat": "*", | |
"gulp-csso": "*", | |
"gulp-debug": "*", | |
"gulp-embedlr": "~0.5.2", | |
"gulp-footer": "*", | |
"gulp-gzip": "0.0.4", | |
"gulp-header": "*", | |
"gulp-if": "*", | |
"gulp-inject": "*", | |
"gulp-jshint": "*", | |
"gulp-karma": "*", | |
"gulp-less": "*", | |
"gulp-livereload": "*", | |
"gulp-minify-html": "*", | |
"gulp-ng-html2js": "*", | |
"gulp-ngmin": "*", | |
"gulp-plumber": "*", | |
"gulp-recess": "*", | |
"gulp-rename": "*", | |
"gulp-rev": "*", | |
"gulp-tap": "*", | |
"gulp-task-listing": "*", | |
"gulp-uglify": "*", | |
"gulp-util": "*", | |
"gulp-watch": "*", | |
"jshint-stylish": "*", | |
"lazypipe": "*", | |
"lodash": "~2.4.1", | |
"run-sequence": "*", | |
"tiny-lr": "0.0.5", | |
"connect": "~2.12.0", | |
"open": "0.0.4", | |
"gulp-bump": "~0.1.4" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment