diff --git a/gulp/modules/add-watch-for-file-reload.js b/gulp/modules/add-watch-for-file-reload.js new file mode 100644 index 00000000..cdd71ce7 --- /dev/null +++ b/gulp/modules/add-watch-for-file-reload.js @@ -0,0 +1,22 @@ +module.exports = function(gulp, config, browserSync, changeEvent) { + + function addWatchForFileReload(isDev) { + /** + * Add watches to build and reload using browser-sync. + * Use this XOR the browser-sync option.files, not both. + * @param {Boolean} isDev - dev or build mode + */ + if (isDev) { + gulp.watch([config.less], ['styles', browserSync.reload]); + gulp.watch([config.client + '**/*', '!' + config.less], browserSync.reload) + .on('change', function(event) { changeEvent(event); }); + } + else { + gulp.watch([config.less, config.js, config.html], ['build', browserSync.reload]) + .on('change', function(event) { changeEvent(event); }); + } + } + + return addWatchForFileReload; + +}; diff --git a/gulp/modules/bytediff-formatter.js b/gulp/modules/bytediff-formatter.js new file mode 100644 index 00000000..8290a438 --- /dev/null +++ b/gulp/modules/bytediff-formatter.js @@ -0,0 +1,18 @@ +module.exports = function (formatPercent) { + + /** + * Formatter for bytediff to display the size changes after processing + * @param {Object} data - byte data + * @return {String} Difference in bytes, formatted + */ + function bytediffFormatter(data) { + var difference = (data.savings > 0) ? ' smaller.' : ' larger.'; + return data.fileName + ' went from ' + + (data.startSize / 1000).toFixed(2) + ' kB to ' + + (data.endSize / 1000).toFixed(2) + ' kB and is ' + + formatPercent(1 - data.percent, 2) + '%' + difference; + } + + return bytediffFormatter; + +}; \ No newline at end of file diff --git a/gulp/modules/change-event.js b/gulp/modules/change-event.js new file mode 100644 index 00000000..dad220c1 --- /dev/null +++ b/gulp/modules/change-event.js @@ -0,0 +1,13 @@ +module.exports = function (log, config) { + /** + * When files change, log it + * @param {Object} event - event that fired + */ + function changeEvent(event) { + var srcPattern = new RegExp('/.*(?=/' + config.source + ')/'); + log('File ' + event.path.replace(srcPattern, '') + ' ' + event.type); + } + + return changeEvent; + +}; diff --git a/gulp/modules/clean.js b/gulp/modules/clean.js new file mode 100644 index 00000000..e7a63889 --- /dev/null +++ b/gulp/modules/clean.js @@ -0,0 +1,15 @@ +module.exports = function (util, log, del) { + + /** + * Delete all files in a given path + * @param {Array} path - array of paths to delete + * @param {Function} done - callback when complete + */ + function clean(path, done) { + log('Cleaning: ' + util.colors.blue(path)); + del(path, done); + } + + return clean; + +}; \ No newline at end of file diff --git a/gulp/modules/config.js b/gulp/modules/config.js new file mode 100644 index 00000000..76c2b38c --- /dev/null +++ b/gulp/modules/config.js @@ -0,0 +1,181 @@ +module.exports = function(bowerConfiguration) { + var client = 'src/client/'; + var server = './src/server/'; + var clientApp = client + 'app/'; + var report = './report/'; + var root = './'; + var specRunnerFile = 'specs.html'; + var temp = './.tmp/'; + var wiredep = require('wiredep'); + var bowerFiles = wiredep({devDependencies: true})['js']; + var bower = { + json: bowerConfiguration, + directory: './bower_components/', + ignorePath: '../..' + }; + var nodeModules = 'node_modules'; + + var config = { + /** + * File paths + */ + // all javascript that we want to vet + alljs: [ + './src/**/*.js', + './*.js' + ], + build: './build/', + client: client, + css: temp + 'styles.css', + fonts: bower.directory + 'font-awesome/fonts/**/*.*', + html: client + '**/*.html', + htmltemplates: clientApp + '**/*.html', + images: client + 'images/**/*.*', + index: client + 'index.html', + // app js, with no specs + js: [ + clientApp + '**/*.module.js', + clientApp + '**/*.js', + '!' + clientApp + '**/*.spec.js' + ], + jsOrder: [ + '**/app.module.js', + '**/*.module.js', + '**/*.js' + ], + less: client + 'styles/styles.less', + report: report, + root: root, + server: server, + source: 'src/', + stubsjs: [ + bower.directory + 'angular-mocks/angular-mocks.js', + client + 'stubs/**/*.js' + ], + temp: temp, + + /** + * optimized files + */ + optimized: { + app: 'app.js', + lib: 'lib.js' + }, + + /** + * plato + */ + plato: {js: clientApp + '**/*.js'}, + + /** + * browser sync + */ + browserReloadDelay: 1000, + + /** + * template cache + */ + templateCache: { + file: 'templates.js', + options: { + module: 'app.core', + root: 'app/', + standAlone: false + } + }, + + /** + * Bower and NPM files + */ + bower: bower, + packages: [ + './package.json', + './bower.json' + ], + + /** + * specs.html, our HTML spec runner + */ + specRunner: client + specRunnerFile, + specRunnerFile: specRunnerFile, + + /** + * The sequence of the injections into specs.html: + * 1 testlibraries + * mocha setup + * 2 bower + * 3 js + * 4 spechelpers + * 5 specs + * 6 templates + */ + testlibraries: [ + nodeModules + '/mocha/mocha.js', + nodeModules + '/chai/chai.js', + nodeModules + '/sinon-chai/lib/sinon-chai.js' + ], + specHelpers: [client + 'test-helpers/*.js'], + specs: [clientApp + '**/*.spec.js'], + serverIntegrationSpecs: [client + '/tests/server-integration/**/*.spec.js'], + + /** + * Node settings + */ + nodeServer: './src/server/app.js', + defaultPort: '7203' + }; + + /** + * wiredep and bower settings + */ + config.getWiredepDefaultOptions = function() { + var options = { + bowerJson: config.bower.json, + directory: config.bower.directory, + ignorePath: config.bower.ignorePath + }; + return options; + }; + + /** + * karma settings + */ + config.karma = getKarmaOptions(); + + return config; + + //////////////// + + function getKarmaOptions() { + var options = { + files: [].concat( + bowerFiles, + config.specHelpers, + clientApp + '**/*.module.js', + clientApp + '**/*.js', + temp + config.templateCache.file, + config.serverIntegrationSpecs + ), + exclude: [], + coverage: { + dir: report + 'coverage', + reporters: [ + // reporters not supporting the `file` property + {type: 'html', subdir: 'report-html'}, + {type: 'lcov', subdir: 'report-lcov'}, + // reporters supporting the `file` property, use `subdir` to directly + // output them in the `dir` directory. + // omit `file` to output to the console. + // {type: 'cobertura', subdir: '.', file: 'cobertura.txt'}, + // {type: 'lcovonly', subdir: '.', file: 'report-lcovonly.txt'}, + // {type: 'teamcity', subdir: '.', file: 'teamcity.txt'}, + //{type: 'text'}, //, subdir: '.', file: 'text.txt'}, + {type: 'text-summary'} //, subdir: '.', file: 'text-summary.txt'} + ] + }, + preprocessors: {} + }; + options.preprocessors[clientApp + '**/!(*.spec)+(.js)'] = ['coverage']; + return options; + } +}; diff --git a/gulp/modules/error-logger.js b/gulp/modules/error-logger.js new file mode 100644 index 00000000..24ba39a0 --- /dev/null +++ b/gulp/modules/error-logger.js @@ -0,0 +1,13 @@ +module.exports = function (log) { + /** + * Log an error message and emit the end of a task + */ + function errorLogger(error) { + log('*** Start of Error ***'); + log(error); + log('*** End of Error ***'); + this.emit('end'); + } + + return errorLogger; +}; diff --git a/gulp/modules/format-percent.js b/gulp/modules/format-percent.js new file mode 100644 index 00000000..a243221a --- /dev/null +++ b/gulp/modules/format-percent.js @@ -0,0 +1,15 @@ +module.exports = function () { + + /** + * Format a number as a percentage + * @param {Number} num Number to format as a percent + * @param {Number} precision Precision of the decimal + * @return {String} Formatted perentage + */ + function formatPercent(num, precision) { + return (num * 100).toFixed(precision); + } + + return formatPercent; + +}; \ No newline at end of file diff --git a/gulp/modules/get-header.js b/gulp/modules/get-header.js new file mode 100644 index 00000000..a2386869 --- /dev/null +++ b/gulp/modules/get-header.js @@ -0,0 +1,25 @@ +module.exports = function (Package, header) { + + /** + * Format and return the header for files + * @return {String} Formatted file header + */ + function getHeader() { + // var pkg = require('./package.json'); + var template = ['/**', + ' * <%= pkg.name %> - <%= pkg.description %>', + ' * @authors <%= pkg.authors %>', + ' * @version v<%= pkg.version %>', + ' * @link <%= pkg.homepage %>', + ' * @license <%= pkg.license %>', + ' */', + '' + ].join('\n'); + return header(template, { + pkg: Package + }); + } + + return getHeader; + +}; diff --git a/gulp/modules/get-node-options.js b/gulp/modules/get-node-options.js new file mode 100644 index 00000000..31dce4f7 --- /dev/null +++ b/gulp/modules/get-node-options.js @@ -0,0 +1,18 @@ +module.exports = function (config) { + + function getNodeOptions(isDev) { + var port = process.env.PORT || config.defaultPort; + return { + script: config.nodeServer, + delayTime: 1, + env: { + 'PORT': port, + 'NODE_ENV': isDev ? 'dev' : 'build' + }, + watch: [config.server] + }; + } + + return getNodeOptions; + +}; \ No newline at end of file diff --git a/gulp/modules/inject-file.js b/gulp/modules/inject-file.js new file mode 100644 index 00000000..72f51197 --- /dev/null +++ b/gulp/modules/inject-file.js @@ -0,0 +1,21 @@ +module.exports = function (gulp, $inject, orderSrc) { + + /** + * Inject files in a sorted sequence at a specified inject label + * @param {Array} src glob pattern for source files + * @param {String} label The label name + * @param {Array} order glob pattern for sort order of the files + * @returns {Stream} The stream + */ + function _inject(src, label, orderPattern) { + var options = {read: false}; + if (label) { + options.name = 'inject:' + label; + } + + return $inject(orderSrc(src, orderPattern), options); + } + + return _inject; + +}; diff --git a/gulp/modules/log.js b/gulp/modules/log.js new file mode 100644 index 00000000..514a5cb2 --- /dev/null +++ b/gulp/modules/log.js @@ -0,0 +1,19 @@ +module.exports = function (util) { + /** + * Log a message or series of messages using chalk's blue color. + * Can pass in a string, object or array. + */ + function log(msg) { + if (typeof(msg) === 'object') { + for (var item in msg) { + if (msg.hasOwnProperty(item)) { + util.log(util.colors.blue(msg[item])); + } + } + } else { + util.log(util.colors.blue(msg)); + } + } + + return log; +}; diff --git a/gulp/modules/notify.js b/gulp/modules/notify.js new file mode 100644 index 00000000..371d9020 --- /dev/null +++ b/gulp/modules/notify.js @@ -0,0 +1,21 @@ +module.exports = function (_) { + + var path = require('path'); + + /** + * Show OS level notification using node-notifier + */ + function notify(options) { + var notifier = require('node-notifier'); + var notifyOptions = { + sound: 'Bottle', + contentImage: path.join(__dirname, 'gulp.png'), + icon: path.join(__dirname, 'gulp.png') + }; + _.assign(notifyOptions, options); + notifier.notify(notifyOptions); + } + + return notify; + +}; diff --git a/gulp/modules/order-src.js b/gulp/modules/order-src.js new file mode 100644 index 00000000..944cd8e7 --- /dev/null +++ b/gulp/modules/order-src.js @@ -0,0 +1,18 @@ +module.exports = function (gulp, $if, order) { + /** + * Order a stream + * @param {Stream} src The gulp.src stream + * @param {Array} order Glob array pattern + * @returns {Stream} The ordered stream + */ + function orderSrc (src, orderPattern) { + + //order = order || ['**/*']; + return gulp + .src(src) + .pipe($if(orderPattern, order(orderPattern))); + } + + return orderSrc; + +}; \ No newline at end of file diff --git a/gulp/modules/run-node-inspector.js b/gulp/modules/run-node-inspector.js new file mode 100644 index 00000000..9881bd41 --- /dev/null +++ b/gulp/modules/run-node-inspector.js @@ -0,0 +1,12 @@ +module.exports = function (log) { + + function runNodeInspector() { + log('Running node-inspector.'); + log('Browse to http://localhost:8080/debug?port=5858'); + var exec = require('child_process').exec; + exec('node-inspector'); + } + + return runNodeInspector; + +}; diff --git a/gulp/modules/serve.js b/gulp/modules/serve.js new file mode 100644 index 00000000..30c0069a --- /dev/null +++ b/gulp/modules/serve.js @@ -0,0 +1,46 @@ +module.exports = function (args, getNodeOptions, nodemon, log, browserSync, runNodeInspector, config, startBrowserSync) { + /** + * serve the code + * --debug-brk or --debug + * --nosync + * @param {Boolean} isDev - dev or build mode + * @param {Boolean} specRunner - server spec runner html + */ + function serve(isDev, specRunner) { + var debug = args.debug || args.debugBrk; + var debugMode = args.debug ? '--debug' : args.debugBrk ? '--debug-brk' : ''; + var nodeOptions = getNodeOptions(isDev); + + if (debug) { + runNodeInspector(); + nodeOptions.nodeArgs = [debugMode + '=5858']; + } + + if (args.verbose) { + console.log(nodeOptions); + } + + return nodemon(nodeOptions) + .on('restart', ['vet'], function(ev) { + log('*** nodemon restarted'); + log('files changed:\n' + ev); + setTimeout(function() { + browserSync.notify('reloading now ...'); + browserSync.reload({stream: false}); + }, config.browserReloadDelay); + }) + .on('start', function () { + log('*** nodemon started'); + startBrowserSync(isDev, specRunner); + }) + .on('crash', function () { + log('*** nodemon crashed: script crashed for some reason'); + }) + .on('exit', function () { + log('*** nodemon exited cleanly'); + }); + } + + + return serve; +}; diff --git a/gulp/modules/start-browser-sync.js b/gulp/modules/start-browser-sync.js new file mode 100644 index 00000000..4eb65eb3 --- /dev/null +++ b/gulp/modules/start-browser-sync.js @@ -0,0 +1,56 @@ +module.exports = function (gulp, args, browserSync, config, changeEvent, log) { + + /** + * Start BrowserSync + * --nosync will avoid browserSync + */ + function startBrowserSync(isDev, specRunner) { + if (args.nosync || browserSync.active) { + return; + } + var port = process.env.PORT || config.defaultPort; + + log('Starting BrowserSync on port ' + port); + + // If build: watches the files, builds, and restarts browser-sync. + // If dev: watches less, compiles it to css, browser-sync handles reload + if (isDev) { + gulp.watch([config.less], ['styles']) + .on('change', changeEvent); + } else { + gulp.watch([config.less, config.js, config.html], ['browserSyncReload']) + .on('change', changeEvent); + } + + var options = { + proxy: 'localhost:' + port, + port: 3000, + files: isDev ? [ + config.client + '**/*.*', + '!' + config.less, + config.temp + '**/*.css' + ] : [], + ghostMode: { // these are the defaults t,f,t,t + clicks: true, + location: false, + forms: true, + scroll: true + }, + injectChanges: true, + logFileChanges: true, + logLevel: 'debug', + logPrefix: 'gulp-patterns', + notify: true, + reloadDelay: 0 //1000 + } ; + if (specRunner) { + options.startPath = config.specRunnerFile; + } + + browserSync(options); + } + + return startBrowserSync; + + +}; diff --git a/gulp/modules/start-plato-visualizer.js b/gulp/modules/start-plato-visualizer.js new file mode 100644 index 00000000..39014307 --- /dev/null +++ b/gulp/modules/start-plato-visualizer.js @@ -0,0 +1,34 @@ +module.exports = function (gulp, log, config, glob, args) { + + /** + * Start Plato inspector and visualizer + */ + function startPlatoVisualizer(done) { + log('Running Plato'); + + var files = glob.sync(config.plato.js); + var excludeFiles = /.*\.spec\.js/; + var plato = require('plato'); + + var options = { + title: 'Plato Inspections Report', + exclude: excludeFiles + }; + var outputDir = config.report + '/plato'; + + plato.inspect(files, outputDir, options, platoCompleted); + + function platoCompleted(report) { + var overview = plato.getOverviewReport(report); + if (args.verbose) { + log(overview.summary); + } + if (done) { done(); } + } + } + + return startPlatoVisualizer; + +}; + + diff --git a/gulp/modules/start-tests.js b/gulp/modules/start-tests.js new file mode 100644 index 00000000..a945b7cf --- /dev/null +++ b/gulp/modules/start-tests.js @@ -0,0 +1,51 @@ +module.exports = function (gulp, config, args, log, basePath) { + + /** + * Start the tests using karma. + * @param {boolean} singleRun - True means run once and end (CI), or keep running (dev) + * @param {Function} done - Callback to fire when karma is done + * @return {undefined} + */ + function startTests(singleRun, done) { + var child; + var excludeFiles = []; + var fork = require('child_process').fork; + var karma = require('karma').server; + var serverSpecs = config.serverIntegrationSpecs; + + if (args.startServers) { + log('Starting servers'); + var savedEnv = process.env; + savedEnv.NODE_ENV = 'dev'; + savedEnv.PORT = 8888; + child = fork(config.nodeServer); + } else { + if (serverSpecs && serverSpecs.length) { + excludeFiles = serverSpecs; + } + } + + karma.start({ + configFile: basePath('karma.conf.js'), + exclude: excludeFiles, + singleRun: !!singleRun + }, karmaCompleted); + + //////////////// + + function karmaCompleted(karmaResult) { + log('Karma completed'); + if (child) { + log('shutting down the child process'); + child.kill(); + } + if (karmaResult === 1) { + done('karma: tests failed with code ' + karmaResult); + } else { + done(); + } + } + } + + return startTests; +}; diff --git a/gulp/tasks/autotest.js b/gulp/tasks/autotest.js new file mode 100644 index 00000000..090a008b --- /dev/null +++ b/gulp/tasks/autotest.js @@ -0,0 +1,12 @@ +module.exports = function (gulp, startTests) { + + gulp.task('autotest', function(done) { + /** + * Run specs and wait. + * Watch for file changes and re-run tests on each change + * To start servers and run midway specs as well: + * gulp autotest --startServers + */ + startTests(false /*singleRun*/ , done); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/browser-sync-loaded.js b/gulp/tasks/browser-sync-loaded.js new file mode 100644 index 00000000..8c2e8265 --- /dev/null +++ b/gulp/tasks/browser-sync-loaded.js @@ -0,0 +1,9 @@ +module.exports = function (gulp, browserSync) { + gulp.task('browserSyncReload', ['optimize'], function () { + /** + * Optimize the code and re-load browserSync + */ + browserSync.reload(); + }); + // gulp.task('browserSyncReload', ['optimize'], browserSync.reload); +}; \ No newline at end of file diff --git a/gulp/tasks/build-specs.js b/gulp/tasks/build-specs.js new file mode 100644 index 00000000..49c3aa23 --- /dev/null +++ b/gulp/tasks/build-specs.js @@ -0,0 +1,29 @@ +module.exports = function (gulp, config, args, injectFile, log, wiredep) { + + gulp.task('build-specs', ['templatecache'], function(done) { + /** + * Inject all the spec files into the specs.html + * @return {Stream} + */ + log('building the spec runner'); + + var templateCache = config.temp + config.templateCache.file; + var options = config.getWiredepDefaultOptions(); + var specs = config.specs; + + if (args.startServers) { + specs = [].concat(specs, config.serverIntegrationSpecs); + } + options.devDependencies = true; + + return gulp + .src(config.specRunner) + .pipe(wiredep.stream(options)) + .pipe(injectFile(config.js, '', config.jsOrder)) + .pipe(injectFile(config.testlibraries, 'testlibraries')) + .pipe(injectFile(config.specHelpers, 'spechelpers')) + .pipe(injectFile(specs, 'specs', ['**/*'])) + .pipe(injectFile(templateCache, 'templates')) + .pipe(gulp.dest(config.client)); + }); +}; diff --git a/gulp/tasks/build.js b/gulp/tasks/build.js new file mode 100644 index 00000000..20ad3e95 --- /dev/null +++ b/gulp/tasks/build.js @@ -0,0 +1,20 @@ +module.exports = function (gulp, log, del, notify, config) { + + gulp.task('build', ['optimize', 'images', 'fonts'], function() { + /** + * Build everything + * This is separate so we can run tests on + * optimize before handling image or fonts + */ + log('Building everything'); + + var msg = { + title: 'gulp build', + subtitle: 'Deployed to the build folder', + message: 'Running `gulp serve-build`' + }; + del(config.temp); + log(msg); + notify(msg); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/bump.js b/gulp/tasks/bump.js new file mode 100644 index 00000000..08df015b --- /dev/null +++ b/gulp/tasks/bump.js @@ -0,0 +1,31 @@ +module.exports = function (gulp, args, config, print, bump, log) { + + gulp.task('bump', function() { + /** + * Bump the version + * --type=pre will bump the prerelease version *.*.*-x + * --type=patch or no flag will bump the patch version *.*.x + * --type=minor will bump the minor version *.x.* + * --type=major will bump the major version x.*.* + * --version=1.2.3 will bump to a specific version and ignore other flags + */ + var msg = 'Bumping versions'; + var type = args.type; + var version = args.ver; + var options = {}; + if (version) { + options.version = version; + msg += ' to ' + version; + } else { + options.type = type; + msg += ' for a ' + type; + } + log(msg); + + return gulp + .src(config.packages) + .pipe(print()) + .pipe(bump(options)) + .pipe(gulp.dest(config.root)); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/clean-code.js b/gulp/tasks/clean-code.js new file mode 100644 index 00000000..9e96763e --- /dev/null +++ b/gulp/tasks/clean-code.js @@ -0,0 +1,15 @@ +module.exports = function (gulp, config, clean) { + + gulp.task('clean-code', function(done) { + /** + * Remove all js and html from the build and temp folders + * @param {Function} done - callback when complete + */ + var files = [].concat( + config.temp + '**/*.js', + config.build + 'js/**/*.js', + config.build + '**/*.html' + ); + clean(files, done); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/clean-fonts.js b/gulp/tasks/clean-fonts.js new file mode 100644 index 00000000..d704e6ec --- /dev/null +++ b/gulp/tasks/clean-fonts.js @@ -0,0 +1,10 @@ +module.exports = function (gulp, config, clean) { + + gulp.task('clean-fonts', function(done) { + /** + * Remove all fonts from the build folder + * @param {Function} done - callback when complete + */ + clean(config.build + 'fonts/**/*.*', done); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/clean-images.js b/gulp/tasks/clean-images.js new file mode 100644 index 00000000..183a7eae --- /dev/null +++ b/gulp/tasks/clean-images.js @@ -0,0 +1,10 @@ +module.exports = function (gulp, config, clean) { + + gulp.task('clean-images', function(done) { + /** + * Remove all images from the build folder + * @param {Function} done - callback when complete + */ + clean(config.build + 'images/**/*.*', done); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/clean-styles.js b/gulp/tasks/clean-styles.js new file mode 100644 index 00000000..5ffe02fd --- /dev/null +++ b/gulp/tasks/clean-styles.js @@ -0,0 +1,14 @@ +module.exports = function (gulp, config, clean) { + + gulp.task('clean-styles', function(done) { + /** + * Remove all styles from the build and temp folders + * @param {Function} done - callback when complete + */ + var files = [].concat( + config.temp + '**/*.css', + config.build + 'styles/**/*.css' + ); + clean(files, done); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/clean.js b/gulp/tasks/clean.js new file mode 100644 index 00000000..8bb74eee --- /dev/null +++ b/gulp/tasks/clean.js @@ -0,0 +1,12 @@ +module.exports = function (gulp, config, util, log, del) { + + gulp.task('clean', function(done) { + /** + * Remove all files from the build, temp, and reports folders + * @param {Function} done - callback when complete + */ + var delconfig = [].concat(config.build, config.temp, config.report); + log('Cleaning: ' + util.colors.blue(delconfig)); + del(delconfig, done); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/default.js b/gulp/tasks/default.js new file mode 100644 index 00000000..9401b062 --- /dev/null +++ b/gulp/tasks/default.js @@ -0,0 +1,3 @@ +module.exports = function (gulp) { + gulp.task('default', ['help']); +}; \ No newline at end of file diff --git a/gulp/tasks/fonts.js b/gulp/tasks/fonts.js new file mode 100644 index 00000000..263178fb --- /dev/null +++ b/gulp/tasks/fonts.js @@ -0,0 +1,15 @@ +module.exports = function (gulp, log, config) { + + /** + * Copy fonts + * @return {Stream} + */ + gulp.task('fonts', ['clean-fonts'], function() { + log('Copying fonts'); + + return gulp + .src(config.fonts) + .pipe(gulp.dest(config.build + 'fonts')); + }); + +}; \ No newline at end of file diff --git a/gulp/tasks/images.js b/gulp/tasks/images.js new file mode 100644 index 00000000..fbd4709b --- /dev/null +++ b/gulp/tasks/images.js @@ -0,0 +1,17 @@ +module.exports = function (gulp, imagemin, log, config) { + + gulp.task('images', ['clean-images'], function() { + + /** + * Compress images + * @return {Stream} + */ + + log('Compressing and copying images'); + + return gulp + .src(config.images) + .pipe(imagemin({optimizationLevel: 4})) + .pipe(gulp.dest(config.build + 'images')); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/inject.js b/gulp/tasks/inject.js new file mode 100644 index 00000000..c00693bd --- /dev/null +++ b/gulp/tasks/inject.js @@ -0,0 +1,11 @@ +module.exports = function (gulp, config, injectFile, log) { + + gulp.task('inject', ['wiredep', 'styles', 'templatecache'], function() { + log('Wire up css into the html, after files are ready'); + + return gulp + .src(config.index) + .pipe(injectFile(config.css)) + .pipe(gulp.dest(config.client)); + }); +}; diff --git a/gulp/tasks/less-watcher.js b/gulp/tasks/less-watcher.js new file mode 100644 index 00000000..f79b0a69 --- /dev/null +++ b/gulp/tasks/less-watcher.js @@ -0,0 +1,6 @@ +module.exports = function (gulp, config) { + + gulp.task('less-watcher', function() { + gulp.watch([config.less], ['styles']); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/optimize.js b/gulp/tasks/optimize.js new file mode 100644 index 00000000..32462f47 --- /dev/null +++ b/gulp/tasks/optimize.js @@ -0,0 +1,48 @@ +module.exports = function (gulp, config, useref, filter, plumber, injectFile , csso, + ngAnnotate, uglify, getHeader, rev, revReplace, log) { + + gulp.task('optimize', ['inject', 'test'], function() { + /** + * Optimize all files, move to a build folder, + * and inject them into the new index.html + * @return {Stream} + */ + log('Optimizing the js, css, and html'); + + var assets = useref.assets({searchPath: './'}); + // Filters are named for the gulp-useref path + var cssFilter = filter('**/*.css'); + var jsAppFilter = filter('**/' + config.optimized.app); + var jslibFilter = filter('**/' + config.optimized.lib); + + var templateCache = config.temp + config.templateCache.file; + + return gulp + .src(config.index) + .pipe(plumber()) + .pipe(injectFile(templateCache, 'templates')) + .pipe(assets) // Gather all assets from the html with useref + // Get the css + .pipe(cssFilter) + .pipe(csso()) + .pipe(cssFilter.restore()) + // Get the custom javascript + .pipe(jsAppFilter) + .pipe(ngAnnotate({add: true})) + .pipe(uglify()) + .pipe(getHeader()) + .pipe(jsAppFilter.restore()) + // Get the vendor javascript + .pipe(jslibFilter) + .pipe(uglify()) // another option is to override wiredep to use min files + .pipe(jslibFilter.restore()) + // Take inventory of the file names for future rev numbers + .pipe(rev()) + // Apply the concat and file replacement with useref + .pipe(assets.restore()) + .pipe(useref()) + // Replace the file names in the html with rev numbers + .pipe(revReplace()) + .pipe(gulp.dest(config.build)); + }); +}; diff --git a/gulp/tasks/plato.js b/gulp/tasks/plato.js new file mode 100644 index 00000000..75eda18e --- /dev/null +++ b/gulp/tasks/plato.js @@ -0,0 +1,13 @@ +module.exports = function (gulp, startPlatoVisualizer, log) { + + gulp.task('plato', function(done) { + /** + * Create a visualizer report + */ + log('Analyzing source with Plato'); + log('Browse to /report/plato/index.html to see Plato results'); + + startPlatoVisualizer(done); + }); + +}; \ No newline at end of file diff --git a/gulp/tasks/serve-build.js b/gulp/tasks/serve-build.js new file mode 100644 index 00000000..f941d3bb --- /dev/null +++ b/gulp/tasks/serve-build.js @@ -0,0 +1,11 @@ +module.exports = function (gulp, serve) { + + gulp.task('serve-build', ['build'], function() { + /** + * serve the build environment + * --debug-brk or --debug + * --nosync + */ + serve(false /*isDev*/); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/serve-dev.js b/gulp/tasks/serve-dev.js new file mode 100644 index 00000000..a1a43a6d --- /dev/null +++ b/gulp/tasks/serve-dev.js @@ -0,0 +1,11 @@ +module.exports = function (gulp, serve) { + + gulp.task('serve-dev', ['inject'], function() { + /** + * serve the dev environment + * --debug-brk or --debug + * --nosync + */ + serve(true /*isDev*/); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/serve-specs.js b/gulp/tasks/serve-specs.js new file mode 100644 index 00000000..9eb3979c --- /dev/null +++ b/gulp/tasks/serve-specs.js @@ -0,0 +1,11 @@ +module.exports = function (gulp, serve, log) { + gulp.task('serve-specs', ['build-specs'], function(done) { + /** + * Run the spec runner + * @return {Stream} + */ + log('run the spec runner'); + serve(true /* isDev */, true /* specRunner */); + done(); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/styles.js b/gulp/tasks/styles.js new file mode 100644 index 00000000..8bce5429 --- /dev/null +++ b/gulp/tasks/styles.js @@ -0,0 +1,18 @@ +module.exports = function (gulp, config, log, plumber, less, autoprefixer) { + gulp.task('styles', ['clean-styles'], function() { + /** + * Compile less to css + * @return {Stream} + */ + log('Compiling Less --> CSS'); + + return gulp + .src(config.less) + .pipe(plumber()) // exit gracefully if something fails after this + .pipe(less()) + // .on('error', errorLogger) // more verbose and dupe output. requires emit. + .pipe(autoprefixer({browsers: ['last 2 version', '> 5%']})) + .pipe(gulp.dest(config.temp)); + }); + +}; \ No newline at end of file diff --git a/gulp/tasks/templatecache.js b/gulp/tasks/templatecache.js new file mode 100644 index 00000000..c3094d2e --- /dev/null +++ b/gulp/tasks/templatecache.js @@ -0,0 +1,21 @@ +module.exports = function (gulp, angularTemplatecache, bytediffFormatter, $if, minifyHtml, bytediff, args, config, log) { + + gulp.task('templatecache', ['clean-code'], function() { + /** + * Create $templateCache from the html templates + * @return {Stream} + */ + log('Creating an AngularJS $templateCache'); + + return gulp + .src(config.htmltemplates) + .pipe($if(args.verbose, bytediff.start())) + .pipe(minifyHtml({empty: true})) + .pipe($if(args.verbose, bytediff.stop(bytediffFormatter))) + .pipe(angularTemplatecache( + config.templateCache.file, + config.templateCache.options + )) + .pipe(gulp.dest(config.temp)); + }); +}; \ No newline at end of file diff --git a/gulp/tasks/test.js b/gulp/tasks/test.js new file mode 100644 index 00000000..2da28da1 --- /dev/null +++ b/gulp/tasks/test.js @@ -0,0 +1,12 @@ +module.exports = function (gulp, startTests) { + + gulp.task('test', ['vet', 'templatecache'], function(done) { + /** + * Run specs once and exit + * To start servers and run midway specs as well: + * gulp test --startServers + * @return {Stream} + */ + startTests(true /*singleRun*/ , done); + }); +}; diff --git a/gulp/tasks/vet.js b/gulp/tasks/vet.js new file mode 100644 index 00000000..83e454b0 --- /dev/null +++ b/gulp/tasks/vet.js @@ -0,0 +1,19 @@ +module.exports = function (gulp, config, $if, args, jshint, jscs, log, print) { + + gulp.task('vet', function() { + /** + * vet the code and create coverage report + * @return {Stream} + */ + log('Analyzing source with JSHint and JSCS'); + + return gulp + .src(config.alljs) + .pipe($if(args.verbose, print())) + .pipe(jshint()) + .pipe(jshint.reporter('jshint-stylish', {verbose: true})) + .pipe(jshint.reporter('fail')) + .pipe(jscs()); + }); + +}; diff --git a/gulp/tasks/wiredep.js b/gulp/tasks/wiredep.js new file mode 100644 index 00000000..6cce628e --- /dev/null +++ b/gulp/tasks/wiredep.js @@ -0,0 +1,20 @@ +module.exports = function (gulp, config, args, injectFile, log) { + gulp.task('wiredep', function() { + /** + * Wire-up the bower dependencies + * @return {Stream} + */ + log('Wiring the bower dependencies into the html'); + + var wiredep = require('wiredep').stream; + var options = config.getWiredepDefaultOptions(); + + // Only include stubs if flag is enabled + var js = args.stubs ? [].concat(config.js, config.stubsjs) : config.js; + return gulp + .src(config.index) + .pipe(wiredep(options)) + .pipe(injectFile(js, '', config.jsOrder)) + .pipe(gulp.dest(config.client)); + }); +}; diff --git a/gulpfile.js b/gulpfile.js index e2afca37..738d6201 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,16 +1,4 @@ -var args = require('yargs').argv; -var browserSync = require('browser-sync'); -var config = require('./gulp.config')(); -var del = require('del'); -var glob = require('glob'); var gulp = require('gulp'); -var path = require('path'); -var _ = require('lodash'); -var $ = require('gulp-load-plugins')({lazy: true}); - -var colors = $.util.colors; -var envenv = $.util.env; -var port = process.env.PORT || config.defaultPort; /** * yargs variables can be passed in to alter the behavior, when present. @@ -23,687 +11,25 @@ var port = process.env.PORT || config.defaultPort; * --startServers: Will start servers for midway tests on the test task. */ -/** - * List the available gulp tasks - */ -gulp.task('help', $.taskListing); -gulp.task('default', ['help']); - -/** - * vet the code and create coverage report - * @return {Stream} - */ -gulp.task('vet', function() { - log('Analyzing source with JSHint and JSCS'); - - return gulp - .src(config.alljs) - .pipe($.if(args.verbose, $.print())) - .pipe($.jshint()) - .pipe($.jshint.reporter('jshint-stylish', {verbose: true})) - .pipe($.jshint.reporter('fail')) - .pipe($.jscs()); -}); - -/** - * Create a visualizer report - */ -gulp.task('plato', function(done) { - log('Analyzing source with Plato'); - log('Browse to /report/plato/index.html to see Plato results'); - - startPlatoVisualizer(done); -}); - -/** - * Compile less to css - * @return {Stream} - */ -gulp.task('styles', ['clean-styles'], function() { - log('Compiling Less --> CSS'); - - return gulp - .src(config.less) - .pipe($.plumber()) // exit gracefully if something fails after this - .pipe($.less()) -// .on('error', errorLogger) // more verbose and dupe output. requires emit. - .pipe($.autoprefixer({browsers: ['last 2 version', '> 5%']})) - .pipe(gulp.dest(config.temp)); -}); - -/** - * Copy fonts - * @return {Stream} - */ -gulp.task('fonts', ['clean-fonts'], function() { - log('Copying fonts'); - - return gulp - .src(config.fonts) - .pipe(gulp.dest(config.build + 'fonts')); -}); - -/** - * Compress images - * @return {Stream} - */ -gulp.task('images', ['clean-images'], function() { - log('Compressing and copying images'); - - return gulp - .src(config.images) - .pipe($.imagemin({optimizationLevel: 4})) - .pipe(gulp.dest(config.build + 'images')); -}); - -gulp.task('less-watcher', function() { - gulp.watch([config.less], ['styles']); -}); - -/** - * Create $templateCache from the html templates - * @return {Stream} - */ -gulp.task('templatecache', ['clean-code'], function() { - log('Creating an AngularJS $templateCache'); - - return gulp - .src(config.htmltemplates) - .pipe($.if(args.verbose, $.bytediff.start())) - .pipe($.minifyHtml({empty: true})) - .pipe($.if(args.verbose, $.bytediff.stop(bytediffFormatter))) - .pipe($.angularTemplatecache( - config.templateCache.file, - config.templateCache.options - )) - .pipe(gulp.dest(config.temp)); -}); - -/** - * Wire-up the bower dependencies - * @return {Stream} - */ -gulp.task('wiredep', function() { - log('Wiring the bower dependencies into the html'); - - var wiredep = require('wiredep').stream; - var options = config.getWiredepDefaultOptions(); - - // Only include stubs if flag is enabled - var js = args.stubs ? [].concat(config.js, config.stubsjs) : config.js; - - return gulp - .src(config.index) - .pipe(wiredep(options)) - .pipe(inject(js, '', config.jsOrder)) - .pipe(gulp.dest(config.client)); -}); - -gulp.task('inject', ['wiredep', 'styles', 'templatecache'], function() { - log('Wire up css into the html, after files are ready'); - - return gulp - .src(config.index) - .pipe(inject(config.css)) - .pipe(gulp.dest(config.client)); -}); - -/** - * Run the spec runner - * @return {Stream} - */ -gulp.task('serve-specs', ['build-specs'], function(done) { - log('run the spec runner'); - serve(true /* isDev */, true /* specRunner */); - done(); -}); - -/** - * Inject all the spec files into the specs.html - * @return {Stream} - */ -gulp.task('build-specs', ['templatecache'], function(done) { - log('building the spec runner'); - - var wiredep = require('wiredep').stream; - var templateCache = config.temp + config.templateCache.file; - var options = config.getWiredepDefaultOptions(); - var specs = config.specs; - - if (args.startServers) { - specs = [].concat(specs, config.serverIntegrationSpecs); - } - options.devDependencies = true; - - return gulp - .src(config.specRunner) - .pipe(wiredep(options)) - .pipe(inject(config.js, '', config.jsOrder)) - .pipe(inject(config.testlibraries, 'testlibraries')) - .pipe(inject(config.specHelpers, 'spechelpers')) - .pipe(inject(specs, 'specs', ['**/*'])) - .pipe(inject(templateCache, 'templates')) - .pipe(gulp.dest(config.client)); -}); - -/** - * Build everything - * This is separate so we can run tests on - * optimize before handling image or fonts - */ -gulp.task('build', ['optimize', 'images', 'fonts'], function() { - log('Building everything'); - - var msg = { - title: 'gulp build', - subtitle: 'Deployed to the build folder', - message: 'Running `gulp serve-build`' - }; - del(config.temp); - log(msg); - notify(msg); -}); - -/** - * Optimize all files, move to a build folder, - * and inject them into the new index.html - * @return {Stream} - */ -gulp.task('optimize', ['inject', 'test'], function() { - log('Optimizing the js, css, and html'); - - var assets = $.useref.assets({searchPath: './'}); - // Filters are named for the gulp-useref path - var cssFilter = $.filter('**/*.css'); - var jsAppFilter = $.filter('**/' + config.optimized.app); - var jslibFilter = $.filter('**/' + config.optimized.lib); - - var templateCache = config.temp + config.templateCache.file; - - return gulp - .src(config.index) - .pipe($.plumber()) - .pipe(inject(templateCache, 'templates')) - .pipe(assets) // Gather all assets from the html with useref - // Get the css - .pipe(cssFilter) - .pipe($.csso()) - .pipe(cssFilter.restore()) - // Get the custom javascript - .pipe(jsAppFilter) - .pipe($.ngAnnotate({add: true})) - .pipe($.uglify()) - .pipe(getHeader()) - .pipe(jsAppFilter.restore()) - // Get the vendor javascript - .pipe(jslibFilter) - .pipe($.uglify()) // another option is to override wiredep to use min files - .pipe(jslibFilter.restore()) - // Take inventory of the file names for future rev numbers - .pipe($.rev()) - // Apply the concat and file replacement with useref - .pipe(assets.restore()) - .pipe($.useref()) - // Replace the file names in the html with rev numbers - .pipe($.revReplace()) - .pipe(gulp.dest(config.build)); -}); - -/** - * Remove all files from the build, temp, and reports folders - * @param {Function} done - callback when complete - */ -gulp.task('clean', function(done) { - var delconfig = [].concat(config.build, config.temp, config.report); - log('Cleaning: ' + $.util.colors.blue(delconfig)); - del(delconfig, done); -}); - -/** - * Remove all fonts from the build folder - * @param {Function} done - callback when complete - */ -gulp.task('clean-fonts', function(done) { - clean(config.build + 'fonts/**/*.*', done); -}); - -/** - * Remove all images from the build folder - * @param {Function} done - callback when complete - */ -gulp.task('clean-images', function(done) { - clean(config.build + 'images/**/*.*', done); -}); - -/** - * Remove all styles from the build and temp folders - * @param {Function} done - callback when complete - */ -gulp.task('clean-styles', function(done) { - var files = [].concat( - config.temp + '**/*.css', - config.build + 'styles/**/*.css' - ); - clean(files, done); -}); - -/** - * Remove all js and html from the build and temp folders - * @param {Function} done - callback when complete - */ -gulp.task('clean-code', function(done) { - var files = [].concat( - config.temp + '**/*.js', - config.build + 'js/**/*.js', - config.build + '**/*.html' - ); - clean(files, done); -}); - -/** - * Run specs once and exit - * To start servers and run midway specs as well: - * gulp test --startServers - * @return {Stream} - */ -gulp.task('test', ['vet', 'templatecache'], function(done) { - startTests(true /*singleRun*/ , done); -}); - -/** - * Run specs and wait. - * Watch for file changes and re-run tests on each change - * To start servers and run midway specs as well: - * gulp autotest --startServers - */ -gulp.task('autotest', function(done) { - startTests(false /*singleRun*/ , done); -}); - -/** - * serve the dev environment - * --debug-brk or --debug - * --nosync - */ -gulp.task('serve-dev', ['inject'], function() { - serve(true /*isDev*/); -}); - -/** - * serve the build environment - * --debug-brk or --debug - * --nosync - */ -gulp.task('serve-build', ['build'], function() { - serve(false /*isDev*/); -}); - -/** - * Bump the version - * --type=pre will bump the prerelease version *.*.*-x - * --type=patch or no flag will bump the patch version *.*.x - * --type=minor will bump the minor version *.x.* - * --type=major will bump the major version x.*.* - * --version=1.2.3 will bump to a specific version and ignore other flags - */ -gulp.task('bump', function() { - var msg = 'Bumping versions'; - var type = args.type; - var version = args.ver; - var options = {}; - if (version) { - options.version = version; - msg += ' to ' + version; - } else { - options.type = type; - msg += ' for a ' + type; +var di = require('gulp-di')(gulp, { + pattern : ['gulp.*', 'gulp-*', 'browser-sync', '!gulp-di', 'wiredep', 'glob', 'del', 'lodash'], + rename : { + 'lodash' : '_', + 'gulp-if' : '$if', + 'gulp-inject' : '$inject' } - log(msg); - - return gulp - .src(config.packages) - .pipe($.print()) - .pipe($.bump(options)) - .pipe(gulp.dest(config.root)); }); -/** - * Optimize the code and re-load browserSync - */ -gulp.task('browserSyncReload', ['optimize'], browserSync.reload); - -//////////////// - -/** - * Add watches to build and reload using browser-sync. - * Use this XOR the browser-sync option.files, not both. - * @param {Boolean} isDev - dev or build mode - */ -//function addWatchForFileReload(isDev) { -// if (isDev) { -// gulp.watch([config.less], ['styles', browserSync.reload]); -// gulp.watch([config.client + '**/*', '!' + config.less], browserSync.reload) -// .on('change', function(event) { changeEvent(event); }); -// } -// else { -// gulp.watch([config.less, config.js, config.html], ['build', browserSync.reload]) -// .on('change', function(event) { changeEvent(event); }); -// } -//} - -/** - * When files change, log it - * @param {Object} event - event that fired - */ -function changeEvent(event) { - var srcPattern = new RegExp('/.*(?=/' + config.source + ')/'); - log('File ' + event.path.replace(srcPattern, '') + ' ' + event.type); -} - -/** - * Delete all files in a given path - * @param {Array} path - array of paths to delete - * @param {Function} done - callback when complete - */ -function clean(path, done) { - log('Cleaning: ' + $.util.colors.blue(path)); - del(path, done); -} - -/** - * Inject files in a sorted sequence at a specified inject label - * @param {Array} src glob pattern for source files - * @param {String} label The label name - * @param {Array} order glob pattern for sort order of the files - * @returns {Stream} The stream - */ -function inject(src, label, order) { - var options = {read: false}; - if (label) { - options.name = 'inject:' + label; - } - - return $.inject(orderSrc(src, order), options); -} - -/** - * Order a stream - * @param {Stream} src The gulp.src stream - * @param {Array} order Glob array pattern - * @returns {Stream} The ordered stream - */ -function orderSrc (src, order) { - //order = order || ['**/*']; - return gulp - .src(src) - .pipe($.if(order, $.order(order))); -} - -/** - * serve the code - * --debug-brk or --debug - * --nosync - * @param {Boolean} isDev - dev or build mode - * @param {Boolean} specRunner - server spec runner html - */ -function serve(isDev, specRunner) { - var debug = args.debug || args.debugBrk; - var debugMode = args.debug ? '--debug' : args.debugBrk ? '--debug-brk' : ''; - var nodeOptions = getNodeOptions(isDev); - - if (debug) { - runNodeInspector(); - nodeOptions.nodeArgs = [debugMode + '=5858']; - } - - if (args.verbose) { - console.log(nodeOptions); - } - - return $.nodemon(nodeOptions) - .on('restart', ['vet'], function(ev) { - log('*** nodemon restarted'); - log('files changed:\n' + ev); - setTimeout(function() { - browserSync.notify('reloading now ...'); - browserSync.reload({stream: false}); - }, config.browserReloadDelay); - }) - .on('start', function () { - log('*** nodemon started'); - startBrowserSync(isDev, specRunner); - }) - .on('crash', function () { - log('*** nodemon crashed: script crashed for some reason'); - }) - .on('exit', function () { - log('*** nodemon exited cleanly'); - }); -} - -function getNodeOptions(isDev) { - return { - script: config.nodeServer, - delayTime: 1, - env: { - 'PORT': port, - 'NODE_ENV': isDev ? 'dev' : 'build' - }, - watch: [config.server] - }; -} +// var colors = $.util.colors; +// var envenv = $.util.env; -function runNodeInspector() { - log('Running node-inspector.'); - log('Browse to http://localhost:8080/debug?port=5858'); - var exec = require('child_process').exec; - exec('node-inspector'); -} - -/** - * Start BrowserSync - * --nosync will avoid browserSync - */ -function startBrowserSync(isDev, specRunner) { - if (args.nosync || browserSync.active) { - return; - } - - log('Starting BrowserSync on port ' + port); - - // If build: watches the files, builds, and restarts browser-sync. - // If dev: watches less, compiles it to css, browser-sync handles reload - if (isDev) { - gulp.watch([config.less], ['styles']) - .on('change', changeEvent); - } else { - gulp.watch([config.less, config.js, config.html], ['browserSyncReload']) - .on('change', changeEvent); - } - - var options = { - proxy: 'localhost:' + port, - port: 3000, - files: isDev ? [ - config.client + '**/*.*', - '!' + config.less, - config.temp + '**/*.css' - ] : [], - ghostMode: { // these are the defaults t,f,t,t - clicks: true, - location: false, - forms: true, - scroll: true - }, - injectChanges: true, - logFileChanges: true, - logLevel: 'debug', - logPrefix: 'gulp-patterns', - notify: true, - reloadDelay: 0 //1000 - } ; - if (specRunner) { - options.startPath = config.specRunnerFile; - } - - browserSync(options); -} - -/** - * Start Plato inspector and visualizer - */ -function startPlatoVisualizer(done) { - log('Running Plato'); - - var files = glob.sync(config.plato.js); - var excludeFiles = /.*\.spec\.js/; - var plato = require('plato'); - - var options = { - title: 'Plato Inspections Report', - exclude: excludeFiles - }; - var outputDir = config.report + '/plato'; - - plato.inspect(files, outputDir, options, platoCompleted); - - function platoCompleted(report) { - var overview = plato.getOverviewReport(report); - if (args.verbose) { - log(overview.summary); - } - if (done) { done(); } - } -} - -/** - * Start the tests using karma. - * @param {boolean} singleRun - True means run once and end (CI), or keep running (dev) - * @param {Function} done - Callback to fire when karma is done - * @return {undefined} - */ -function startTests(singleRun, done) { - var child; - var excludeFiles = []; - var fork = require('child_process').fork; - var karma = require('karma').server; - var serverSpecs = config.serverIntegrationSpecs; - - if (args.startServers) { - log('Starting servers'); - var savedEnv = process.env; - savedEnv.NODE_ENV = 'dev'; - savedEnv.PORT = 8888; - child = fork(config.nodeServer); - } else { - if (serverSpecs && serverSpecs.length) { - excludeFiles = serverSpecs; - } - } - - karma.start({ - configFile: __dirname + '/karma.conf.js', - exclude: excludeFiles, - singleRun: !!singleRun - }, karmaCompleted); - - //////////////// - - function karmaCompleted(karmaResult) { - log('Karma completed'); - if (child) { - log('shutting down the child process'); - child.kill(); - } - if (karmaResult === 1) { - done('karma: tests failed with code ' + karmaResult); - } else { - done(); - } - } -} - -/** - * Formatter for bytediff to display the size changes after processing - * @param {Object} data - byte data - * @return {String} Difference in bytes, formatted - */ -function bytediffFormatter(data) { - var difference = (data.savings > 0) ? ' smaller.' : ' larger.'; - return data.fileName + ' went from ' + - (data.startSize / 1000).toFixed(2) + ' kB to ' + - (data.endSize / 1000).toFixed(2) + ' kB and is ' + - formatPercent(1 - data.percent, 2) + '%' + difference; -} - -/** - * Log an error message and emit the end of a task - */ -function errorLogger(error) { - log('*** Start of Error ***'); - log(error); - log('*** End of Error ***'); - this.emit('end'); -} - -/** - * Format a number as a percentage - * @param {Number} num Number to format as a percent - * @param {Number} precision Precision of the decimal - * @return {String} Formatted perentage - */ -function formatPercent(num, precision) { - return (num * 100).toFixed(precision); -} - -/** - * Format and return the header for files - * @return {String} Formatted file header - */ -function getHeader() { - var pkg = require('./package.json'); - var template = ['/**', - ' * <%= pkg.name %> - <%= pkg.description %>', - ' * @authors <%= pkg.authors %>', - ' * @version v<%= pkg.version %>', - ' * @link <%= pkg.homepage %>', - ' * @license <%= pkg.license %>', - ' */', - '' - ].join('\n'); - return $.header(template, { - pkg: pkg - }); -} - -/** - * Log a message or series of messages using chalk's blue color. - * Can pass in a string, object or array. - */ -function log(msg) { - if (typeof(msg) === 'object') { - for (var item in msg) { - if (msg.hasOwnProperty(item)) { - $.util.log($.util.colors.blue(msg[item])); - } - } - } else { - $.util.log($.util.colors.blue(msg)); - } -} - -/** - * Show OS level notification using node-notifier - */ -function notify(options) { - var notifier = require('node-notifier'); - var notifyOptions = { - sound: 'Bottle', - contentImage: path.join(__dirname, 'gulp.png'), - icon: path.join(__dirname, 'gulp.png') - }; - _.assign(notifyOptions, options); - notifier.notify(notifyOptions); -} +di +.provide({ + args : require('yargs').argv, + bowerConfiguration : require('./bower.json') +}) +.tasks('./gulp/tasks') +.modules('./gulp/modules') +.resolve(); module.exports = gulp; diff --git a/package.json b/package.json index 1b8c5f7d..a607129f 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "compression": "^1.1.0", "cors": "^2.2.0", "express": "^4.9.3", + "gulp-di": "0.0.1", "morgan": "^1.1.1", "serve-favicon": "^2.0.1" },