diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index d4f8387..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,111 +0,0 @@ -'use strict'; - -module.exports = function(grunt) { - - require('load-grunt-tasks')(grunt); - - grunt.initConfig({ - clean: { - dist: 'dist', - }, - '6to5': { - options: { - blacklist: ['generators'], - }, - src: { - expand: true, - cwd: 'src', - src: ['**/*.js', '!bin/skeleton/**/*.js', '!bin/client/**'], - dest: 'dist', - }, - }, - copy: { - src: { - expand: true, - cwd: 'src', - src: ['**', '!**/*.js', 'bin/skeleton/**/*.js', 'bin/client/**'], - dest: 'dist', - }, - }, - jshint: { - options: { - jshintrc: true, - }, - src: [ - 'src/**/*.js', - '!src/bin/client/traceur-runtime.js', - '!src/bin/skeleton/src/templates/default/resources/js/vendor/**/*.js', - ], - }, - jscs: { - options: { - config: '.jscsrc', - esnext: true, - reporter: 'inline', - }, - src: [ - 'src/**/*.js', - '!src/bin/client/traceur-runtime.js', - '!src/bin/skeleton/src/templates/default/resources/js/vendor/**/*.js', - ], - }, - mochaTest: { - options: { - timeout: 5000, - bail: true, - clearRequireCache: true, // necessary for `watch` task - }, - src: 'dist/test/*.js', - }, - watch: { - options: { - spawn: false, // faster than `spawn: true`, also necessary for incremental build - }, - // This Gruntfile auto-reload is buggy (tested in Windows) - // configFiles: { - // options: { - // reload: true, - // }, - // files: ['Gruntfile.js', '.jshintrc', '.jscsrc'], - // }, - js: { - options: { - event: ['added', 'changed'], - }, - files: ['src/**/*.js', '!src/bin/skeleton/**/*.js', '!src/bin/client/**'], - tasks: ['lint', '6to5', 'mochaTest'], - }, - copy: { - options: { - event: ['added', 'changed'], - }, - files: ['src/**', '!src/**/*.js', 'src/bin/skeleton/**/*.js', 'src/bin/client/**'], - tasks: ['copy', 'mochaTest'], - }, - clean: { - options: { - event: 'deleted', - }, - files: 'src/**', - tasks: ['clean', 'mochaTest'], - }, - }, - }); - - grunt.event.on('watch', function(action, filepath, target) { - filepath = filepath.replace(/\\/g, '/'); - if (target === 'js') { - grunt.config('6to5.src.src', filepath.replace(/^src\//, '')); - grunt.config('jshint.src', filepath); - grunt.config('jscs.src', filepath); - } else if (target === 'copy') { - grunt.config('copy.src.src', filepath.replace(/^src\//, '')); - } else if (target === 'clean') { - grunt.config('clean.dist', filepath.replace(/^src/, 'dist')); - } - }); - - grunt.registerTask('lint', ['jshint', 'jscs']); - grunt.registerTask('build', ['lint', 'clean', '6to5', 'copy', 'mochaTest']); - grunt.registerTask('default', ['build', 'watch']); -}; diff --git a/build.js b/build.js new file mode 100644 index 0000000..06426a7 --- /dev/null +++ b/build.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports = { + srcBase: 'src/', + src: { + js: ['**/*.js', '!bin/skeleton/**', '!bin/client/**'] + }, + distBase: 'dist/', + config: { + jscs: { configPath: '.jscsrc', esnext: true }, + '6to5': { blacklist: ['generators'] }, + mocha: { bail: true, timeout: 5000 } + } +}; diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..050a98d --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,112 @@ +'use strict'; + +// [TEMP] workaround gulp-jscs Windows issue - https://github.com/es6rocks/slush-es6/issues/4 +if (require('os').platform() === 'win32') process.argv.push('--no-color'); + +var path = require('path'), + gulp = require('gulp'), + plugins = require('gulp-load-plugins')(), + rimraf = require('rimraf'), + through = require('through'), + mergeStream = require('merge-stream'), + reverseStream = require('reversepoint'), + uniqueStream = require('unique-stream'), + lazypipe = require('lazypipe'), + chalk = require('chalk'), + build = require('./build'), + copySrc = ['**'].concat(negateGlobs(build.src.js)), + writePipe = lazypipe() + .pipe(gulp.dest, build.distBase), + jsPipe = lazypipe() + .pipe(plugins.jshint) + .pipe(plugins.jshint.reporter, 'jshint-stylish') + .pipe(plugins.jshint.reporter, 'fail') + .pipe(plugins.jscs, build.config.jscs) + .pipe(plugins['6to5'], build.config['6to5']) + .pipe(writePipe), + runTests = lazypipe() + .pipe(gulp.src, build.distBase + 'test/*.js', { read: false }) + .pipe(plugins.mocha, build.config.mocha); + +function negateGlobs(globs) { + return globs.map(function(glob) { + return ~glob.lastIndexOf('!', 0) ? glob.slice(1) : '!' + glob; + }); +} + +function prefixGlobs(globs, prefix) { + return globs.map(function(glob) { + return ~glob.lastIndexOf('!', 0) ? '!' + prefix + glob.slice(1) : prefix + glob; + }); +} + +function runAfterEnd(cb) { + // This is basically a passThrough stream for the callback's stream. + // It waits until all data is finished being piped into it and discards this data, + // then passes through the data from the stream provided by the callback. + return through(function() {}, function() { + var cbStream = cb(); + ['data', 'end'/*, 'error'*/].forEach(function(event) { + cbStream.on(event, this.emit.bind(this, event)); + }, this); + }); +} + +gulp.task('build', function() { + rimraf.sync(build.distBase); + return mergeStream( + gulp.src(prefixGlobs(build.src.js, build.srcBase), { base: build.srcBase }).pipe(jsPipe()), + gulp.src(prefixGlobs(copySrc, build.srcBase), { base: build.srcBase }).pipe(writePipe()) + ) + .pipe(runAfterEnd(runTests)); +}); + +// `neverEnd` receives a task conclusion callback which is never called as to signal that this watch task should never end. +// We don't return gulp-watch's endless stream as it would fail the task in the first stream error. +gulp.task('default', ['build'], function(neverEnd) { + // The odd indentation here is to better illustrate the stream branching/forking flow. + // Diagram reference: https://github.com/es6rocks/slush-es6/issues/5#issue-52701608 + var uniqueFilter = lazypipe() + .pipe(reverseStream) + .pipe(uniqueStream, 'path'), + + existsFilter = lazypipe() + .pipe(plugins.filter, filterEvent.bind(null, ['changed', 'added'])), + + handleJs = lazypipe() + .pipe(plugins.filter, build.src.js) + .pipe(jsPipe), + + handleCopy = lazypipe() + .pipe(plugins.filter, copySrc) + .pipe(writePipe), + + handleDeletion = lazypipe() + .pipe(plugins.filter, filterEvent.bind(null, ['deleted'])) + .pipe(plugins.rename, function(filePath) { + // we can't change/remove the filePath's `base`, so cd out of it in the dirname + filePath.dirname = path.join(path.relative(build.srcBase, '.'), build.distBase, filePath.dirname); + }) + .pipe(plugins.rimraf); + + function filterEvent(events, file) { + return ~events.indexOf(file.event); + } + + plugins.watch(build.srcBase + '**', { base: build.srcBase }, plugins.batch(function(files) { + files = files.pipe(uniqueFilter()); + var existingFiles = files.pipe(existsFilter()); + + return mergeStream( + existingFiles.pipe(handleJs()), + existingFiles.pipe(handleCopy()), + files.pipe(handleDeletion()) + ) + .pipe(runAfterEnd(runTests)); + }, function(err) { + // [TEMP] makeshift error reporting for gulp-jscs until gulp-jscs implements proper reporters + console.error(err.message); + })).on('ready', function() { + plugins.util.log('Watching ' + chalk.magenta(build.srcBase) + ' directory for changes...'); + }); +}); diff --git a/package.json b/package.json index f23c0df..34db9cd 100755 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "co": "~3.0.5", "co-prompt": "^1.0.0", "commander": "~2.2.0", + "gulp-6to5": "^1.0.2", "less": "^1.7.5", "markdown-extra": "^0.1.0", "marked": "~0.3.2", @@ -40,23 +41,31 @@ "v8-argv": "^0.2.0" }, "devDependencies": { - "grunt": "^0.4.5", - "grunt-6to5": "^1.0.1", - "grunt-cli": "^0.1.13", - "grunt-contrib-clean": "^0.6.0", - "grunt-contrib-copy": "^0.7.0", - "grunt-contrib-jshint": "^0.10.0", - "grunt-contrib-watch": "^0.6.1", - "grunt-jscs": "^0.8.1", - "grunt-mocha-test": "^0.12.2", - "load-grunt-tasks": "^1.0.0", - "should": "^4.0.4" + "chalk": "^0.5.1", + "gulp": "^3.8.10", + "gulp-batch": "^1.0.4", + "gulp-filter": "^1.0.2", + "gulp-jscs": "^1.3.1", + "gulp-jshint": "^1.9.0", + "gulp-load-plugins": "^0.8.0", + "gulp-mocha": "^2.0.0", + "gulp-rename": "^1.2.0", + "gulp-rimraf": "^0.1.1", + "gulp-util": "^3.0.1", + "gulp-watch": "^3.0.0", + "jshint-stylish": "^1.0.0", + "lazypipe": "^0.2.2", + "merge-stream": "^0.1.6", + "reversepoint": "^0.2.1", + "should": "^4.4.1", + "through": "^2.3.6", + "unique-stream": "^1.0.0" }, "author": "Jaydson Gomes (http://jaydson.org/)", "license": "MIT", "scripts": { - "dev": "grunt", - "prepublish": "npm i grunt-6to5 && npm test", - "test": "grunt build" + "dev": "node --harmony ./node_modules/gulp/bin/gulp", + "prepublish": "npm i gulp-6to5 && npm test", + "test": "node --harmony ./node_modules/gulp/bin/gulp build" } } diff --git a/src/bin/cli/program.js b/src/bin/cli/program.js index fef9826..9587cd2 100644 --- a/src/bin/cli/program.js +++ b/src/bin/cli/program.js @@ -1,4 +1,4 @@ -require('grunt-6to5/node_modules/6to5/polyfill'); +require('gulp-6to5/node_modules/6to5/polyfill'); var program = require('commander'); import { version } from '../config';