text: /* eslint-disable import/no-nodejs-modules, import/no-commonjs, no-use-before-define */
  const gulp = require('gulp');
  const eslint = require('gulp-eslint');
  const replace = require('gulp-replace');
  const size = require('gulp-size');
  const streamify = require('gulp-streamify');
  const terser = require('gulp-terser');
  const zip = require('gulp-zip');
  const exec = require('child_process').exec;
  const karma = require('karma');
  const merge = require('merge-stream');
  const yargs = require('yargs');
  const path = require('path');
  const htmllint = require('gulp-htmllint');
  const typescript = require('gulp-typescript');
  const typedoc = require('gulp-typedoc');
  
  const pkg = require('./package.json');
  const tsProject = typescript.createProject('./tsconfig.json');
  
  const argv = yargs
  	.option('verbose', {default: false})
  	.argv;
  
  const srcDir = './src/';
  const outDir = './dist/';
  
  gulp.task('build', buildTask);
  gulp.task('package', packageTask);
  gulp.task('lint-html', lintHtmlTask);
  gulp.task('lint-js', lintJsTask);
  gulp.task('lint', gulp.parallel('lint-html', 'lint-js'));
  gulp.task('tsc', typescriptTask);
  gulp.task('docs', docsTask);
  gulp.task('unittest', unittestTask);
  gulp.task('test', gulp.parallel('lint', 'tsc', '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'));
  
  function run(bin, args) {
  	return new Promise((resolve, reject) => {
  		const exe = '"' + process.execPath + '"';
  		const src = require.resolve(bin);
  		const cmd = [exe, src].concat(args || []).join(' ');
  		const ps = exec(cmd);
  
  		ps.stdout.pipe(process.stdout);
  		ps.stderr.pipe(process.stderr);
  		ps.on('close', (error) => {
  			if (error) {
  				reject(error);
  			} else {
  				resolve();
  			}
  		});
  	});
  }
  
  function buildTask() {
  	return run('rollup/dist/bin/rollup', ['-c', argv.watch ? '--watch' : '']);
  }
  
  function packageTask() {
  	return merge(
  		// gather "regular" files landing in the package root
  		gulp.src([outDir + '*.js', outDir + '*.css', '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() {
  	const 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.
  	const options = {
  		rules: {
  			complexity: [1, 10],
  			'max-statements': [1, 30]
  		}
  	};
  
  	return gulp.src(files)
  		.pipe(eslint(options))
  		.pipe(eslint.format())
  		.pipe(eslint.failAfterError());
  }
  
  function typescriptTask() {
  	return tsProject.src()
  		.pipe(tsProject())
  		.js.pipe(gulp.dest('dist'));
  }
  
  function lintHtmlTask() {
  	return gulp.src('samples/**/*.html')
  		.pipe(htmllint({
  			failOnError: true,
  		}));
  }
  
  function docsTask(done) {
  	const bin = require.resolve('gitbook-cli/bin/gitbook.js');
  	const cmd = argv.watch ? 'serve' : 'build';
  
  	return run(bin, ['install', './'])
  		.then(() => run(bin, [cmd, './', './dist/docs']))
  		.then(() => {
  			const config = {
  				moduleResolution: 'Node',
  				target: 'ES6',
  				out: './dist/docs/typedoc'
  			};
  			gulp.src(['./src/**/*.js'], {read: false})
  				.pipe(typedoc(config, done));
  		}).catch((err) => {
  			done(new Error(err.stdout || err));
  		});
  }
  
  function unittestTask(done) {
  	// use `env.test` from `babel.config.json` for karma builds
  	process.env.NODE_ENV = 'test';
  	new karma.Server({
  		configFile: path.join(__dirname, 'karma.conf.js'),
  		singleRun: !argv.watch,
  		args: {
  			coverage: !!argv.coverage,
  			inputs: argv.inputs,
  			browsers: argv.browsers,
  			watch: argv.watch
  		}
  	},
  	// https://github.com/karma-runner/gulp-karma/issues/18
  	(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(terser())
  		.pipe(size({
  			showFiles: true,
  			gzip: true
  		}));
  }
  