var gulp = require('gulp'); var concat = require('gulp-concat'); var eslint = require('gulp-eslint'); var file = require('gulp-file'); var insert = require('gulp-insert'); var replace = require('gulp-replace'); var size = require('gulp-size'); var streamify = require('gulp-streamify'); var uglify = require('gulp-uglify'); var util = require('gulp-util'); var zip = require('gulp-zip'); var exec = require('child-process-promise').exec; var karma = require('karma'); var browserify = require('browserify'); var source = require('vinyl-source-stream'); var merge = require('merge-stream'); var collapse = require('bundle-collapser/plugin'); var yargs = require('yargs'); var path = require('path'); var fs = require('fs'); var htmllint = require('gulp-htmllint'); var pkg = require('./package.json'); var argv = yargs .option('force-output', {default: false}) .option('silent-errors', {default: false}) .option('verbose', {default: false}) .argv; var srcDir = './src/'; var outDir = './dist/'; var header = "/*!\n" + " * Chart.js\n" + " * http://chartjs.org/\n" + " * Version: {{ version }}\n" + " *\n" + " * Copyright " + (new Date().getFullYear()) + " Chart.js Contributors\n" + " * Released under the MIT license\n" + " * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md\n" + " */\n"; if (argv.verbose) { util.log("Gulp running with options: " + JSON.stringify(argv, null, 2)); } gulp.task('bower', bowerTask); gulp.task('build', buildTask); gulp.task('package', packageTask); gulp.task('watch', watchTask); gulp.task('lint-html', lintHtmlTask); gulp.task('lint-js', lintJsTask); gulp.task('lint', gulp.parallel('lint-html', 'lint-js')); gulp.task('docs', docsTask); gulp.task('unittest', unittestTask); gulp.task('test', gulp.parallel('lint', 'unittest')); gulp.task('library-size', librarySizeTask); gulp.task('module-sizes', moduleSizesTask); gulp.task('size', gulp.parallel('library-size', 'module-sizes')); gulp.task('default', gulp.parallel('build', 'watch')); /** * Generates the bower.json manifest file which will be pushed along release tags. * Specs: https://github.com/bower/spec/blob/master/json.md */ function bowerTask() { var json = JSON.stringify({ name: pkg.name, description: pkg.description, homepage: pkg.homepage, license: pkg.license, version: pkg.version, main: outDir + "Chart.js", ignore: [ '.github', '.codeclimate.yml', '.gitignore', '.npmignore', '.travis.yml', 'scripts' ] }, null, 2); return file('bower.json', json, { src: true }) .pipe(gulp.dest('./')); } function buildTask() { var errorHandler = function (err) { if(argv.forceOutput) { var browserError = 'console.error("Gulp: ' + err.toString() + '")'; ['Chart', 'Chart.min', 'Chart.bundle', 'Chart.bundle.min'].forEach(function(fileName) { fs.writeFileSync(outDir+fileName+'.js', browserError); }); } if(argv.silentErrors) { util.log(util.colors.red('[Error]'), err.toString()); this.emit('end'); } else { throw err; } } var bundled = browserify('./src/chart.js', { standalone: 'Chart' }) .plugin(collapse) .bundle() .on('error', errorHandler) .pipe(source('Chart.bundle.js')) .pipe(insert.prepend(header)) .pipe(streamify(replace('{{ version }}', pkg.version))) .pipe(gulp.dest(outDir)) .pipe(streamify(uglify())) .pipe(insert.prepend(header)) .pipe(streamify(replace('{{ version }}', pkg.version))) .pipe(streamify(concat('Chart.bundle.min.js'))) .pipe(gulp.dest(outDir)); var nonBundled = browserify('./src/chart.js', { standalone: 'Chart' }) .ignore('moment') .plugin(collapse) .bundle() .on('error', errorHandler) .pipe(source('Chart.js')) .pipe(insert.prepend(header)) .pipe(streamify(replace('{{ version }}', pkg.version))) .pipe(gulp.dest(outDir)) .pipe(streamify(uglify())) .pipe(insert.prepend(header)) .pipe(streamify(replace('{{ version }}', pkg.version))) .pipe(streamify(concat('Chart.min.js'))) .pipe(gulp.dest(outDir)); return merge(bundled, nonBundled); } function packageTask() { return merge( // gather "regular" files landing in the package root gulp.src([outDir + '*.js', 'LICENSE.md']), // since we moved the dist files one folder up (package root), we need to rewrite // samples src="../dist/ to src="../ and then copy them in the /samples directory. gulp.src('./samples/**/*', { base: '.' }) .pipe(streamify(replace(/src="((?:\.\.\/)+)dist\//g, 'src="$1'))) ) // finally, create the zip archive .pipe(zip('Chart.js.zip')) .pipe(gulp.dest(outDir)); } function lintJsTask() { var files = [ 'samples/**/*.html', 'samples/**/*.js', 'src/**/*.js', 'test/**/*.js' ]; // NOTE(SB) codeclimate has 'complexity' and 'max-statements' eslint rules way too strict // compare to what the current codebase can support, and since it's not straightforward // to fix, let's turn them as warnings and rewrite code later progressively. var options = { rules: { 'complexity': [1, 10], 'max-statements': [1, 30] } }; return gulp.src(files) .pipe(eslint(options)) .pipe(eslint.format()) .pipe(eslint.failAfterError()); } function lintHtmlTask() { return gulp.src('samples/**/*.html') .pipe(htmllint({ failOnError: true, })); } function docsTask(done) { var script = require.resolve('gitbook-cli/bin/gitbook.js'); var cmd = '"' + process.execPath + '"'; exec([cmd, script, 'install', './'].join(' ')).then(() => { return exec([cmd, script, argv.watch ? 'serve' : 'build', './', './dist/docs'].join(' ')); }).then(() => { done(); }).catch((err) => { done(new Error(err.stdout || err)); }) } function unittestTask(done) { new karma.Server({ configFile: path.join(__dirname, 'karma.conf.js'), singleRun: !argv.watch, args: { coverage: !!argv.coverage, inputs: argv.inputs ? argv.inputs.split(';') : ['./test/specs/**/*.js'] } }, // https://github.com/karma-runner/gulp-karma/issues/18 function(error) { error = error ? new Error('Karma returned with the error code: ' + error) : undefined; done(error); }).start(); } function librarySizeTask() { return gulp.src('dist/Chart.bundle.min.js') .pipe(size({ gzip: true })); } function moduleSizesTask() { return gulp.src(srcDir + '**/*.js') .pipe(uglify()) .pipe(size({ showFiles: true, gzip: true })); } function watchTask() { return gulp.watch('./src/**', gulp.parallel('build')); }