<commit_before>/* global __dirname */

// we can use sync safely here because it's just the gulp file
// gulp tasks prefer unregulated arrow-body-style
/* eslint-disable no-sync,arrow-body-style */

import File from 'vinyl';
import WebpackDevServer from 'webpack-dev-server';
import clean from 'gulp-rimraf';
import eslint from 'gulp-eslint';
// eslint-disable-next-line id-length
import fs from 'fs';
import gulp from 'gulp';
import minimist from 'minimist';
import mocha from 'gulp-mocha';
import open from 'gulp-open';
import path from 'path';
import replace from 'gulp-replace';
import runSequence from 'run-sequence';
import stylelint from 'gulp-stylelint';
import through from 'through';
import tsconfigGlob from 'tsconfig-glob';
import tslint from 'gulp-tslint';
import typings from 'gulp-typings';
import util from 'gulp-util';
import webpack from 'webpack';
import webpackStream from 'webpack-stream';


const args = minimist(process.argv);

const webpackAnalyzeUri = 'http://webpack.github.io/analyse/';

const config = {
  verbose: args.verbose || false,
  quiet: args.quiet || false,
  host: args.host || '0.0.0.0',
  port: args.port || 3000,
  publicPath: args.publicPath || '/',
  profile: args.profile || false,
  builds: {
    debug: 'debug',
    release: 'release',
    test: 'test',
    watch: 'watch',
  },
  files: {
    typings: 'typings.json',
    webpack: 'webpack.config.js',
    stats: 'stats.json',
    index: 'index.html',
  },
  dirs: {
    typings: path.join(__dirname, 'typings'),
    src: path.join(__dirname, 'src'),
    test: path.join(__dirname, 'test'),
    build: path.join(__dirname, 'build'),
    dist: args.dist || path.join(__dirname, 'dist'),
  },
  test: {
    reporter: args.reporter || 'spec',
  },
};

function log(...items) {
  if (config.quiet === false) {
    // eslint-disable-next-line prefer-reflect
    util.log.apply(null, items);
  }
}

if (config.verbose) {
  log('Gulp Config:', JSON.stringify(config, null, 2));
}

// Default build task
gulp.task('default', [ 'browser' ]);
// Default test task
gulp.task('test', (done) => {
  runSequence('lint', 'mocha', done);
});
// Default npm test task
gulp.task('npm:test', (done) => {
  runSequence('lint', 'webpack:test', 'mocha:run', 'deploy:all', done);
});

gulp.task('config', () => {
  util.log('Gulp Config:', config);
});

gulp.task('help', () => {
  /* eslint-disable max-len */
  util.log(`*** Gulp Help ***

Command Line Overrides:
  ${ util.colors.cyan('--verbose') }          : print webpack module details and stats after bundling (${ util.colors.magenta(config.verbose) })
  ${ util.colors.cyan('--quiet') }            : do not print any extra build details (${ util.colors.magenta(config.quiet) })
  ${ util.colors.cyan('--profile') }          : provides webpack build profiling in ${ util.colors.magenta(config.files.stats) } (${ util.colors.magenta(config.profile) })
  ${ util.colors.cyan('--lib') }       ${ util.colors.yellow('<path>') } : override lib directory (${ util.colors.magenta(config.dirs.lib) })
  ${ util.colors.cyan('--dist') }      ${ util.colors.yellow('<path>') } : override dist directory (${ util.colors.magenta(config.dirs.dist) })
  ${ util.colors.cyan('--reporter') }  ${ util.colors.yellow('<name>') } : mocha test reporter (${ util.colors.magenta(config.test.reporter) })
             options : ${ [ 'spec', 'list', 'progress', 'dot', 'min' ].map((x) => util.colors.magenta(x)).join(', ') }

Run ${ util.colors.cyan('gulp --tasks') } to see complete task hierarchy

Tasks:
  ${ util.colors.cyan('gulp') } will build a ${ util.colors.yellow('debug') } bundle, start a webpack development server, and open a browser window
  ${ util.colors.cyan('gulp test') } will build a ${ util.colors.yellow('test') } bundle and run mocha against the tests (alias for ${ util.colors.cyan('gulp mocha') })
  ${ util.colors.cyan('gulp help') } will print this help text
  ${ util.colors.cyan('gulp config') } will print the gulp build configuration

  ${ util.colors.cyan('gulp clean') } will delete all files in ${ util.colors.magenta(config.dirs.typings) }, ${ util.colors.magenta(config.dirs.build) }, ${ util.colors.magenta(config.dirs.dist) }
       ${ [ 'typings', 'build', 'dist', 'all' ].map((x) => util.colors.cyan(`clean:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp typings') } will install typescript definition files via the typings utility (alias for ${ util.colors.cyan('gulp typings:install') })
  ${ util.colors.cyan('gulp typings:ensure') } will run ${ util.colors.cyan('typings:install') } if ${ util.colors.magenta(config.dirs.typings) } is missing

  ${ util.colors.cyan('gulp tsconfig:glob') } will expand ${ util.colors.yellow('filesGlob') } in ${ util.colors.magenta('tsconfig.json') }

  ${ util.colors.cyan('gulp lint') } will lint the source files with ${ util.colors.yellow('eslint') }, ${ util.colors.yellow('tslint') }, and ${ util.colors.yellow('stylelint') }
       ${ [ 'es', 'ts', 'style', 'all' ].map((x) => util.colors.cyan(`lint:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp webpack') } will build the ${ util.colors.yellow('debug') } bundle using webpack (alias for ${ util.colors.cyan('gulp webpack:debug') })
       ${ [ 'debug', 'release', 'test', 'all' ].map((x) => util.colors.cyan(`webpack:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp mocha') } will build the ${ util.colors.yellow('test') } bundle and run mocha against the tests
  ${ util.colors.cyan('gulp mocha:run') } will run mocha against the current ${ util.colors.yellow('test') } bundle

  ${ util.colors.cyan('gulp watch') } will start a webpack development server
  ${ util.colors.cyan('gulp watch:mocha') } will start webpack in ${ util.colors.magenta('watch') } mode, and run all tests after any detected change
  ${ util.colors.cyan('gulp watch:lint') } will watch source files for changes and run ${ util.colors.cyan('lint') } after any detected change
  ${ util.colors.cyan('gulp watch:dist') } will watch source files for changes and run ${ util.colors.cyan('dist') } after any detected change
       ${ [ 'debug', 'release' ].map((x) => util.colors.cyan(`watch:dist:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp index') } will copy (and transform) the ${ util.colors.magenta(config.files.index) } file for builds
       ${ [ 'debug', 'release', 'watch', 'all' ].map((x) => util.colors.cyan(`index:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp browser') } will open a browser window for a build
       ${ [ 'debug', 'release', 'watch' ].map((x) => util.colors.cyan(`browser:${ x }`)).join(', ') }
  ${ util.colors.cyan('gulp browser:stats') } will open a browser window to ${ util.colors.underline.blue(webpackAnalyzeUri) }

  ${ util.colors.cyan('gulp dist') } will deploy release bundles to ${ util.colors.magenta(config.dirs.dist) }
       ${ [ 'debug', 'release', 'all' ].map((x) => util.colors.cyan(`dist:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp deploy') } will bundle and deploy release bundles to ${ util.colors.magenta(config.dirs.dist) }
       ${ [ 'debug', 'release', 'all' ].map((x) => util.colors.cyan(`deploy:${ x }`)).join(', ') }
`);
  /* eslint-enable max-len */
});

gulp.task('clean', [ 'clean:all' ]);
gulp.task('clean:all', [ 'clean:typings', 'clean:build', 'clean:dist' ]);

gulp.task('clean:typings', () => {
  const target = config.dirs.typings;

  log('Cleaning', util.colors.magenta(target));

  return gulp
    .src(target, { read: false })
    .pipe(clean());
});

gulp.task('clean:build', () => {
  const target = config.dirs.build;

  log('Cleaning', util.colors.magenta(target));

  return gulp
    .src(target, { read: false })
    .pipe(clean());
});

gulp.task('clean:dist', () => {
  const target = config.dirs.dist;
  let force = false;

  log('Cleaning', util.colors.magenta(target));

  if (args.dist) {
    force = true;
  }

  return gulp
    .src(target, { read: false })
    .pipe(clean({ force }));
});

gulp.task('typings', [ 'typings:install' ]);

gulp.task('typings:install', () => {
  const target = path.join(__dirname, config.files.typings);

  log('Installing Typings from', util.colors.magenta(target));

  return gulp
    .src(target)
    .pipe(typings());
});

gulp.task('typings:reinstall', [ 'clean:typings' ], (done) => {
  runSequence('typings:install', done);
});

gulp.task('typings:ensure', (done) => {
  let count = 0;

  return gulp
    .src(path.join(config.dirs.typings, '**', '*.d.ts'), { read: false })
    .pipe(through(() => {
      ++count;
    }, () => {
      if (count === 0) {
        runSequence('typings:install', done);

        return;
      }

      log('Found', util.colors.magenta(count), 'typescript definitions');

      done();
    }));
});

gulp.task('tsconfig:glob', [ 'typings:ensure' ], () => {
  log('Globbing', util.colors.magenta(path.join(__dirname, 'tsconfig.json')));

  // eslint-disable-next-line id-match
  return tsconfigGlob({ configPath: __dirname, indent: 2 });
});

gulp.task('lint', [ 'lint:all' ]);

gulp.task('lint:all', [ 'lint:ts', 'lint:es', 'lint:style:css', 'lint:style:less' ]);

gulp.task('lint:es', () => {
  log('Linting with ESLint...');

  return gulp
    .src([
      path.join(config.dirs.src, '**', '*.js'),
      path.join(config.dirs.test, '**', '*.js'),
      path.join(__dirname, '*.js'),
    ])
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failOnError());
});

gulp.task('lint:ts', () => {
  log('Linting with TSLint...');

  return gulp
    .src([
      path.join(config.dirs.src, '**', '*.ts'),
      path.join(config.dirs.src, '**', '*.tsx'),
      path.join(config.dirs.test, '**', '*.ts'),
    ])
    // eslint-disable-next-line global-require
    .pipe(tslint({ configuration: require('tslint').findConfiguration() }))
    .pipe(tslint.report('verbose', { emitError: true, summarizeFailureOutput: true }));
});

gulp.task('lint:style', [ 'lint:style:less', 'lint:style:css' ]);

gulp.task('lint:style:less', () => {
  log('Linting with Stylelint:Less...');

  return gulp
    .src(path.join(config.dirs.src, '**', '*.less'))
    .pipe(stylelint({
      syntax: 'less',
      failAfterError: true,
      reporters: [
        { formatter: 'string', console: true },
      ],
    }));
});

gulp.task('lint:style:css', () => {
  log('Linting with Stylelint:CSS...');

  return gulp
    .src(path.join(config.dirs.src, '**', '*.css'))
    .pipe(stylelint({
      failAfterError: true,
      reporters: [
        { formatter: 'string', console: true },
      ],
    }));
});

function getWebpackConfig(build, uglify) {
  // dynamic loading of the webpack config
  // eslint-disable-next-line global-require
  const webpackConfig = require(path.join(__dirname, build === config.builds.test ? build : '', config.files.webpack));

  if (build === config.builds.debug) {
    webpackConfig.plugins[0].definitions.DEBUG = true;
    webpackConfig.debug = true;
  } else if (build === config.builds.release) {
    if (uglify === true) {
      webpackConfig.output.filename = util.replaceExtension(webpackConfig.output.filename, '.min.js');
    }
    webpackConfig.plugins[0].definitions.RELEASE = true;
    webpackConfig.plugins[0].definitions['process.env'] = {
      'NODE_ENV': JSON.stringify('production'),
    };
    webpackConfig.plugins.push(new webpack.optimize.DedupePlugin());

    if (uglify) {
      webpackConfig.plugins.push(
        new webpack.optimize.UglifyJsPlugin({
          minimize: true,
          comments: false,
          compress: {
            warnings: false,
          },
        })
      );
    }
  }

  return webpackConfig;
}

function printAssets(jsonStats, build) {
  const outputPath = path.join(config.dirs.build, build);
  const assets = jsonStats.assetsByChunkName;

  for (const chunk in assets) {
    const asset = assets[chunk];

    if (Array.isArray(asset)) {
      for (const i in asset) {
        log(util.colors.magenta(path.join(outputPath, asset[i])));
      }
    } else {
      log(util.colors.magenta(path.join(outputPath, asset)));
    }
  }
}

function logWebpackIssues(jsonStats) {
  const warnings = jsonStats.warnings || [];
  const errors = jsonStats.errors || [];

  if (warnings.length) {
    log(`${ util.colors.yellow('Warnings') }:
${ warnings.map((x) => x.replace(/[\r\n]/g, '').trim()).join('\r\n') }`);
  }

  if (errors.length) {
    log(`${ util.colors.red('Errors') }:
${ errors.map((x) => x.replace(/[\r\n]/g, '').trim()).join('\r\n') }`);<commit_msg>adding warning and error counts to the gulp build log<commit_after>/* global __dirname */

// we can use sync safely here because it's just the gulp file
// gulp tasks prefer unregulated arrow-body-style
/* eslint-disable no-sync,arrow-body-style */

import File from 'vinyl';
import WebpackDevServer from 'webpack-dev-server';
import clean from 'gulp-rimraf';
import eslint from 'gulp-eslint';
// eslint-disable-next-line id-length
import fs from 'fs';
import gulp from 'gulp';
import minimist from 'minimist';
import mocha from 'gulp-mocha';
import open from 'gulp-open';
import path from 'path';
import replace from 'gulp-replace';
import runSequence from 'run-sequence';
import stylelint from 'gulp-stylelint';
import through from 'through';
import tsconfigGlob from 'tsconfig-glob';
import tslint from 'gulp-tslint';
import typings from 'gulp-typings';
import util from 'gulp-util';
import webpack from 'webpack';
import webpackStream from 'webpack-stream';


const args = minimist(process.argv);

const webpackAnalyzeUri = 'http://webpack.github.io/analyse/';

const config = {
  verbose: args.verbose || false,
  quiet: args.quiet || false,
  host: args.host || '0.0.0.0',
  port: args.port || 3000,
  publicPath: args.publicPath || '/',
  profile: args.profile || false,
  builds: {
    debug: 'debug',
    release: 'release',
    test: 'test',
    watch: 'watch',
  },
  files: {
    typings: 'typings.json',
    webpack: 'webpack.config.js',
    stats: 'stats.json',
    index: 'index.html',
  },
  dirs: {
    typings: path.join(__dirname, 'typings'),
    src: path.join(__dirname, 'src'),
    test: path.join(__dirname, 'test'),
    build: path.join(__dirname, 'build'),
    dist: args.dist || path.join(__dirname, 'dist'),
  },
  test: {
    reporter: args.reporter || 'spec',
  },
};

function log(...items) {
  if (config.quiet === false) {
    // eslint-disable-next-line prefer-reflect
    util.log.apply(null, items);
  }
}

if (config.verbose) {
  log('Gulp Config:', JSON.stringify(config, null, 2));
}

// Default build task
gulp.task('default', [ 'browser' ]);
// Default test task
gulp.task('test', (done) => {
  runSequence('lint', 'mocha', done);
});
// Default npm test task
gulp.task('npm:test', (done) => {
  runSequence('lint', 'webpack:test', 'mocha:run', 'deploy:all', done);
});

gulp.task('config', () => {
  util.log('Gulp Config:', config);
});

gulp.task('help', () => {
  /* eslint-disable max-len */
  util.log(`*** Gulp Help ***

Command Line Overrides:
  ${ util.colors.cyan('--verbose') }          : print webpack module details and stats after bundling (${ util.colors.magenta(config.verbose) })
  ${ util.colors.cyan('--quiet') }            : do not print any extra build details (${ util.colors.magenta(config.quiet) })
  ${ util.colors.cyan('--profile') }          : provides webpack build profiling in ${ util.colors.magenta(config.files.stats) } (${ util.colors.magenta(config.profile) })
  ${ util.colors.cyan('--lib') }       ${ util.colors.yellow('<path>') } : override lib directory (${ util.colors.magenta(config.dirs.lib) })
  ${ util.colors.cyan('--dist') }      ${ util.colors.yellow('<path>') } : override dist directory (${ util.colors.magenta(config.dirs.dist) })
  ${ util.colors.cyan('--reporter') }  ${ util.colors.yellow('<name>') } : mocha test reporter (${ util.colors.magenta(config.test.reporter) })
             options : ${ [ 'spec', 'list', 'progress', 'dot', 'min' ].map((x) => util.colors.magenta(x)).join(', ') }

Run ${ util.colors.cyan('gulp --tasks') } to see complete task hierarchy

Tasks:
  ${ util.colors.cyan('gulp') } will build a ${ util.colors.yellow('debug') } bundle, start a webpack development server, and open a browser window
  ${ util.colors.cyan('gulp test') } will build a ${ util.colors.yellow('test') } bundle and run mocha against the tests (alias for ${ util.colors.cyan('gulp mocha') })
  ${ util.colors.cyan('gulp help') } will print this help text
  ${ util.colors.cyan('gulp config') } will print the gulp build configuration

  ${ util.colors.cyan('gulp clean') } will delete all files in ${ util.colors.magenta(config.dirs.typings) }, ${ util.colors.magenta(config.dirs.build) }, ${ util.colors.magenta(config.dirs.dist) }
       ${ [ 'typings', 'build', 'dist', 'all' ].map((x) => util.colors.cyan(`clean:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp typings') } will install typescript definition files via the typings utility (alias for ${ util.colors.cyan('gulp typings:install') })
  ${ util.colors.cyan('gulp typings:ensure') } will run ${ util.colors.cyan('typings:install') } if ${ util.colors.magenta(config.dirs.typings) } is missing

  ${ util.colors.cyan('gulp tsconfig:glob') } will expand ${ util.colors.yellow('filesGlob') } in ${ util.colors.magenta('tsconfig.json') }

  ${ util.colors.cyan('gulp lint') } will lint the source files with ${ util.colors.yellow('eslint') }, ${ util.colors.yellow('tslint') }, and ${ util.colors.yellow('stylelint') }
       ${ [ 'es', 'ts', 'style', 'all' ].map((x) => util.colors.cyan(`lint:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp webpack') } will build the ${ util.colors.yellow('debug') } bundle using webpack (alias for ${ util.colors.cyan('gulp webpack:debug') })
       ${ [ 'debug', 'release', 'test', 'all' ].map((x) => util.colors.cyan(`webpack:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp mocha') } will build the ${ util.colors.yellow('test') } bundle and run mocha against the tests
  ${ util.colors.cyan('gulp mocha:run') } will run mocha against the current ${ util.colors.yellow('test') } bundle

  ${ util.colors.cyan('gulp watch') } will start a webpack development server
  ${ util.colors.cyan('gulp watch:mocha') } will start webpack in ${ util.colors.magenta('watch') } mode, and run all tests after any detected change
  ${ util.colors.cyan('gulp watch:lint') } will watch source files for changes and run ${ util.colors.cyan('lint') } after any detected change
  ${ util.colors.cyan('gulp watch:dist') } will watch source files for changes and run ${ util.colors.cyan('dist') } after any detected change
       ${ [ 'debug', 'release' ].map((x) => util.colors.cyan(`watch:dist:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp index') } will copy (and transform) the ${ util.colors.magenta(config.files.index) } file for builds
       ${ [ 'debug', 'release', 'watch', 'all' ].map((x) => util.colors.cyan(`index:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp browser') } will open a browser window for a build
       ${ [ 'debug', 'release', 'watch' ].map((x) => util.colors.cyan(`browser:${ x }`)).join(', ') }
  ${ util.colors.cyan('gulp browser:stats') } will open a browser window to ${ util.colors.underline.blue(webpackAnalyzeUri) }

  ${ util.colors.cyan('gulp dist') } will deploy release bundles to ${ util.colors.magenta(config.dirs.dist) }
       ${ [ 'debug', 'release', 'all' ].map((x) => util.colors.cyan(`dist:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp deploy') } will bundle and deploy release bundles to ${ util.colors.magenta(config.dirs.dist) }
       ${ [ 'debug', 'release', 'all' ].map((x) => util.colors.cyan(`deploy:${ x }`)).join(', ') }
`);
  /* eslint-enable max-len */
});

gulp.task('clean', [ 'clean:all' ]);
gulp.task('clean:all', [ 'clean:typings', 'clean:build', 'clean:dist' ]);

gulp.task('clean:typings', () => {
  const target = config.dirs.typings;

  log('Cleaning', util.colors.magenta(target));

  return gulp
    .src(target, { read: false })
    .pipe(clean());
});

gulp.task('clean:build', () => {
  const target = config.dirs.build;

  log('Cleaning', util.colors.magenta(target));

  return gulp
    .src(target, { read: false })
    .pipe(clean());
});

gulp.task('clean:dist', () => {
  const target = config.dirs.dist;
  let force = false;

  log('Cleaning', util.colors.magenta(target));

  if (args.dist) {
    force = true;
  }

  return gulp
    .src(target, { read: false })
    .pipe(clean({ force }));
});

gulp.task('typings', [ 'typings:install' ]);

gulp.task('typings:install', () => {
  const target = path.join(__dirname, config.files.typings);

  log('Installing Typings from', util.colors.magenta(target));

  return gulp
    .src(target)
    .pipe(typings());
});

gulp.task('typings:reinstall', [ 'clean:typings' ], (done) => {
  runSequence('typings:install', done);
});

gulp.task('typings:ensure', (done) => {
  let count = 0;

  return gulp
    .src(path.join(config.dirs.typings, '**', '*.d.ts'), { read: false })
    .pipe(through(() => {
      ++count;
    }, () => {
      if (count === 0) {
        runSequence('typings:install', done);

        return;
      }

      log('Found', util.colors.magenta(count), 'typescript definitions');

      done();
    }));
});

gulp.task('tsconfig:glob', [ 'typings:ensure' ], () => {
  log('Globbing', util.colors.magenta(path.join(__dirname, 'tsconfig.json')));

  // eslint-disable-next-line id-match
  return tsconfigGlob({ configPath: __dirname, indent: 2 });
});

gulp.task('lint', [ 'lint:all' ]);

gulp.task('lint:all', [ 'lint:ts', 'lint:es', 'lint:style:css', 'lint:style:less' ]);

gulp.task('lint:es', () => {
  log('Linting with ESLint...');

  return gulp
    .src([
      path.join(config.dirs.src, '**', '*.js'),
      path.join(config.dirs.test, '**', '*.js'),
      path.join(__dirname, '*.js'),
    ])
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failOnError());
});

gulp.task('lint:ts', () => {
  log('Linting with TSLint...');

  return gulp
    .src([
      path.join(config.dirs.src, '**', '*.ts'),
      path.join(config.dirs.src, '**', '*.tsx'),
      path.join(config.dirs.test, '**', '*.ts'),
    ])
    // eslint-disable-next-line global-require
    .pipe(tslint({ configuration: require('tslint').findConfiguration() }))
    .pipe(tslint.report('verbose', { emitError: true, summarizeFailureOutput: true }));
});

gulp.task('lint:style', [ 'lint:style:less', 'lint:style:css' ]);

gulp.task('lint:style:less', () => {
  log('Linting with Stylelint:Less...');

  return gulp
    .src(path.join(config.dirs.src, '**', '*.less'))
    .pipe(stylelint({
      syntax: 'less',
      failAfterError: true,
      reporters: [
        { formatter: 'string', console: true },
      ],
    }));
});

gulp.task('lint:style:css', () => {
  log('Linting with Stylelint:CSS...');

  return gulp
    .src(path.join(config.dirs.src, '**', '*.css'))
    .pipe(stylelint({
      failAfterError: true,
      reporters: [
        { formatter: 'string', console: true },
      ],
    }));
});

function getWebpackConfig(build, uglify) {
  // dynamic loading of the webpack config
  // eslint-disable-next-line global-require
  const webpackConfig = require(path.join(__dirname, build === config.builds.test ? build : '', config.files.webpack));

  if (build === config.builds.debug) {
    webpackConfig.plugins[0].definitions.DEBUG = true;
    webpackConfig.debug = true;
  } else if (build === config.builds.release) {
    if (uglify === true) {
      webpackConfig.output.filename = util.replaceExtension(webpackConfig.output.filename, '.min.js');
    }
    webpackConfig.plugins[0].definitions.RELEASE = true;
    webpackConfig.plugins[0].definitions['process.env'] = {
      'NODE_ENV': JSON.stringify('production'),
    };
    webpackConfig.plugins.push(new webpack.optimize.DedupePlugin());

    if (uglify) {
      webpackConfig.plugins.push(
        new webpack.optimize.UglifyJsPlugin({
          minimize: true,
          comments: false,
          compress: {
            warnings: false,
          },
        })
      );
    }
  }

  return webpackConfig;
}

function printAssets(jsonStats, build) {
  const outputPath = path.join(config.dirs.build, build);
  const assets = jsonStats.assetsByChunkName;

  for (const chunk in assets) {
    const asset = assets[chunk];

    if (Array.isArray(asset)) {
      for (const i in asset) {
        log(util.colors.magenta(path.join(outputPath, asset[i])));
      }
    } else {
      log(util.colors.magenta(path.join(outputPath, asset)));
    }
  }
}

function logWebpackIssues(jsonStats) {
  const warnings = jsonStats.warnings || [];
  const errors = jsonStats.errors || [];

  if (warnings.length) {
    log(`${ util.colors.yellow(`${warnings.length} Warnings`) }:
${ warnings.map((x) => x.replace(/[\r\n]/g, '').trim()).join('\r\n') }`);
  }

  if (errors.length) {
    log(`${ util.colors.red(`${errors.length} Errors`) }:
${ errors.map((x) => x.replace(/[\r\n]/g, '').trim()).join('\r\n') }`);
{'fraction_non_alphanumeric': 0.20115449370640584, 'fraction_numerical': 0.001202597610839413, 'mean_word_length': 3.6560283687943262, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1630227', 'n_tokens_mistral': 8557, 'n_tokens_neox': 8468, 'n_words': 1773}