<commit_before>;(function() {
  'use strict';

  /** Load Node.js modules */
  var spawn = require('child_process').spawn,
      zlib = require('zlib');

  /** Load other modules */
  var _ = require('lodash/lodash.js'),
      preprocess = require('./pre-compile.js'),
      postprocess = require('./post-compile.js'),
      util = require('./util.js');

  /** Module shortcuts */
  var fs = util.fs,
      path = util.path;

  /** Used to detect the Node.js executable in command-line arguments */
  var reNode = RegExp('(?:^|' + path.sepEscaped + ')node(?:\\.exe)?$', 'i');

  /** The Closure Compiler optimization modes */
  var optimizationModes = {
    'simple': 'SIMPLE_OPTIMIZATIONS',
    'advanced': 'ADVANCED_OPTIMIZATIONS'
  };

  /*--------------------------------------------------------------------------*/

  /**
   * Minifies a given Lo-Dash `source` and invokes the `options.onComplete`
   * callback when finished. The `onComplete` callback is invoked with one
   * argument; (outputSource).
   *
   * @param {string|string[]} [source=''] The source to minify or array of commands.
   *  -o, --output - Write output to a given path/filename.
   *  -s, --silent - Skip status updates normally logged to the console.
   *  -t, --template - Applies template specific minifier options.
   *
   * @param {Object} [options={}] The options object.
   * @param {string} [options.outputPath] Write output to a given path/filename.
   * @param {boolean} [options.isSilent] Skip status updates normally logged to the console.
   * @param {boolean} [options.isTemplate] Applies template specific minifier options.
   * @param {Function} [options.onComplete] The function called once minification has finished.
   */
  function minify(source, options) {
    source || (source = '');
    options = _.cloneDeep(options || {});

    // used to specify the default minifer modes
    var defaultModes = ['simple', 'advanced', 'hybrid'];

    // convert commands to an options object
    if (_.isArray(source)) {
      options = source;

      // used to specify the source map URL
      var sourceMapURL;

      // used to report invalid command-line arguments
      var invalidArgs = _.reject(options.slice(reNode.test(options[0]) ? 2 : 0), function(value, index, options) {
        if (/^(?:-o|--output)$/.test(options[index - 1]) ||
            /^modes=.*$/.test(value)) {
          return true;
        }
        var result = _.contains([
          '-o', '--output',
          '-p', '--source-map',
          '-s', '--silent',
          '-t', '--template'
        ], value);

        if (!result && /^(?:-p|--source-map)$/.test(options[index - 1])) {
          sourceMapURL = value;
          return true;
        }
        return result;
      });

      // report invalid arguments
      if (!_.isEmpty(invalidArgs)) {
        console.log('\nInvalid argument' + (_.size(invalidArgs) > 1 ? 's' : '') + ' passed: ' + invalidArgs.join(', '));
        return;
      }
      var filePath = path.normalize(_.last(options)),
          outputPath = path.join(path.dirname(filePath), path.basename(filePath, '.js') + '.min.js');

      outputPath = _.reduce(options, function(result, value, index) {
        if (/-o|--output/.test(value)) {
          result = path.normalize(options[index + 1]);
          var dirname = path.dirname(result);
          fs.mkdirpSync(dirname);
          result = path.join(fs.realpathSync(dirname), path.basename(result));
        }
        return result;
      }, outputPath);

      options = {
        'filePath': filePath,
        'isMapped': getOption(options, '-p') || getOption(options, '--source-map'),
        'isSilent': getOption(options, '-s') || getOption(options, '--silent'),
        'isTemplate': getOption(options, '-t') || getOption(options, '--template'),
        'modes': getOption(options, 'modes', defaultModes),
        'outputPath': outputPath,
        'sourceMapURL': sourceMapURL
      };

      source = fs.readFileSync(filePath, 'utf8');
    }
    else {
      options.filePath = path.normalize(options.filePath);
      options.modes = _.result(options, 'modes', defaultModes);
      options.outputPath = path.normalize(options.outputPath);
    }
    if (options.isMapped) {
      _.pull(options.modes, 'advanced', 'hybrid');
    }
    if (options.isTemplate) {
      _.pull(options.modes, 'advanced');
    }
    new Minify(source, options);
  }

  /**
   * The Minify constructor used to keep state of each `minify` invocation.
   *
   * @private
   * @constructor
   * @param {string} source The source to minify.
   * @param {Object} options The options object.
   *  outputPath - Write output to a given path/filename.
   *  isSilent - Skip status updates normally logged to the console.
   *  isTemplate - Applies template specific minifier options.
   *  onComplete - The function called once minification has finished.
   */
  function Minify(source, options) {
    // juggle arguments
    if (_.isObject(source)) {
      options = source;
      source = options.source || '';
    }
    var modes = options.modes;
    source = preprocess(source, options);

    this.compiled = { 'simple': {}, 'advanced': {} };
    this.hybrid = { 'simple': {}, 'advanced': {} };
    this.uglified = {};

    this.filePath = options.filePath;
    this.isMapped = !!options.isMapped;
    this.isSilent = !!options.isSilent;
    this.isTemplate = !!options.isTemplate;
    this.modes = modes;
    this.outputPath = options.outputPath;
    this.source = source;
    this.sourceMapURL = options.sourceMapURL;

    this.onComplete = options.onComplete || function(data) {
      var outputPath = this.outputPath,
          sourceMap = data.sourceMap;

      fs.writeFileSync(outputPath, data.source, 'utf8');
      if (sourceMap) {
        fs.writeFileSync(getMapPath(outputPath), sourceMap, 'utf8');
      }
    };

    // begin the minification process
    if (this.isMapped) {
      uglify.call(this, source, 'UglifyJS', onUglify.bind(this));
    } else if (_.contains(modes, 'simple')) {
      closureCompiler.call(this, source, 'simple', onClosureSimpleCompile.bind(this));
    } else if (_.contains(modes, 'advanced')) {
      onClosureSimpleGzip.call(this);
    } else {
      onClosureAdvancedGzip.call(this);
    }
  }

  /*--------------------------------------------------------------------------*/

  /**
   * Asynchronously checks if Java is installed. The callback is invoked with
   * one argument; (success).
   *
   * @private
   * @param {Function} callback The function called once the status is resolved.
   */
  var checkJava = (function() {
    var result;
    return function(callback) {
      if (result != null) {
        _.defer(callback, result);
        return;
      }
      var java = spawn('java', ['-version']);

      java.stderr.on('data', function(data) {
        java.stderr.removeAllListeners('data');
        result = !!_.result(/java version "(.*?)"/.exec(data.toString()), 1);
        if (!result) {
          java.emit('error');
        }
        callback(result);
      });

      java.on('error', function() {
        console.warn('The Closure Compiler requires Java. Skipping...');
      });
    };
  }());

  /**
   * Resolves the source map path from the given output path.
   *<commit_msg>Add jsdoc type attribute to `checkJava`. [ci skip]<commit_after>;(function() {
  'use strict';

  /** Load Node.js modules */
  var spawn = require('child_process').spawn,
      zlib = require('zlib');

  /** Load other modules */
  var _ = require('lodash/lodash.js'),
      preprocess = require('./pre-compile.js'),
      postprocess = require('./post-compile.js'),
      util = require('./util.js');

  /** Module shortcuts */
  var fs = util.fs,
      path = util.path;

  /** Used to detect the Node.js executable in command-line arguments */
  var reNode = RegExp('(?:^|' + path.sepEscaped + ')node(?:\\.exe)?$', 'i');

  /** The Closure Compiler optimization modes */
  var optimizationModes = {
    'simple': 'SIMPLE_OPTIMIZATIONS',
    'advanced': 'ADVANCED_OPTIMIZATIONS'
  };

  /*--------------------------------------------------------------------------*/

  /**
   * Minifies a given Lo-Dash `source` and invokes the `options.onComplete`
   * callback when finished. The `onComplete` callback is invoked with one
   * argument; (outputSource).
   *
   * @param {string|string[]} [source=''] The source to minify or array of commands.
   *  -o, --output - Write output to a given path/filename.
   *  -s, --silent - Skip status updates normally logged to the console.
   *  -t, --template - Applies template specific minifier options.
   *
   * @param {Object} [options={}] The options object.
   * @param {string} [options.outputPath] Write output to a given path/filename.
   * @param {boolean} [options.isSilent] Skip status updates normally logged to the console.
   * @param {boolean} [options.isTemplate] Applies template specific minifier options.
   * @param {Function} [options.onComplete] The function called once minification has finished.
   */
  function minify(source, options) {
    source || (source = '');
    options = _.cloneDeep(options || {});

    // used to specify the default minifer modes
    var defaultModes = ['simple', 'advanced', 'hybrid'];

    // convert commands to an options object
    if (_.isArray(source)) {
      options = source;

      // used to specify the source map URL
      var sourceMapURL;

      // used to report invalid command-line arguments
      var invalidArgs = _.reject(options.slice(reNode.test(options[0]) ? 2 : 0), function(value, index, options) {
        if (/^(?:-o|--output)$/.test(options[index - 1]) ||
            /^modes=.*$/.test(value)) {
          return true;
        }
        var result = _.contains([
          '-o', '--output',
          '-p', '--source-map',
          '-s', '--silent',
          '-t', '--template'
        ], value);

        if (!result && /^(?:-p|--source-map)$/.test(options[index - 1])) {
          sourceMapURL = value;
          return true;
        }
        return result;
      });

      // report invalid arguments
      if (!_.isEmpty(invalidArgs)) {
        console.log('\nInvalid argument' + (_.size(invalidArgs) > 1 ? 's' : '') + ' passed: ' + invalidArgs.join(', '));
        return;
      }
      var filePath = path.normalize(_.last(options)),
          outputPath = path.join(path.dirname(filePath), path.basename(filePath, '.js') + '.min.js');

      outputPath = _.reduce(options, function(result, value, index) {
        if (/-o|--output/.test(value)) {
          result = path.normalize(options[index + 1]);
          var dirname = path.dirname(result);
          fs.mkdirpSync(dirname);
          result = path.join(fs.realpathSync(dirname), path.basename(result));
        }
        return result;
      }, outputPath);

      options = {
        'filePath': filePath,
        'isMapped': getOption(options, '-p') || getOption(options, '--source-map'),
        'isSilent': getOption(options, '-s') || getOption(options, '--silent'),
        'isTemplate': getOption(options, '-t') || getOption(options, '--template'),
        'modes': getOption(options, 'modes', defaultModes),
        'outputPath': outputPath,
        'sourceMapURL': sourceMapURL
      };

      source = fs.readFileSync(filePath, 'utf8');
    }
    else {
      options.filePath = path.normalize(options.filePath);
      options.modes = _.result(options, 'modes', defaultModes);
      options.outputPath = path.normalize(options.outputPath);
    }
    if (options.isMapped) {
      _.pull(options.modes, 'advanced', 'hybrid');
    }
    if (options.isTemplate) {
      _.pull(options.modes, 'advanced');
    }
    new Minify(source, options);
  }

  /**
   * The Minify constructor used to keep state of each `minify` invocation.
   *
   * @private
   * @constructor
   * @param {string} source The source to minify.
   * @param {Object} options The options object.
   *  outputPath - Write output to a given path/filename.
   *  isSilent - Skip status updates normally logged to the console.
   *  isTemplate - Applies template specific minifier options.
   *  onComplete - The function called once minification has finished.
   */
  function Minify(source, options) {
    // juggle arguments
    if (_.isObject(source)) {
      options = source;
      source = options.source || '';
    }
    var modes = options.modes;
    source = preprocess(source, options);

    this.compiled = { 'simple': {}, 'advanced': {} };
    this.hybrid = { 'simple': {}, 'advanced': {} };
    this.uglified = {};

    this.filePath = options.filePath;
    this.isMapped = !!options.isMapped;
    this.isSilent = !!options.isSilent;
    this.isTemplate = !!options.isTemplate;
    this.modes = modes;
    this.outputPath = options.outputPath;
    this.source = source;
    this.sourceMapURL = options.sourceMapURL;

    this.onComplete = options.onComplete || function(data) {
      var outputPath = this.outputPath,
          sourceMap = data.sourceMap;

      fs.writeFileSync(outputPath, data.source, 'utf8');
      if (sourceMap) {
        fs.writeFileSync(getMapPath(outputPath), sourceMap, 'utf8');
      }
    };

    // begin the minification process
    if (this.isMapped) {
      uglify.call(this, source, 'UglifyJS', onUglify.bind(this));
    } else if (_.contains(modes, 'simple')) {
      closureCompiler.call(this, source, 'simple', onClosureSimpleCompile.bind(this));
    } else if (_.contains(modes, 'advanced')) {
      onClosureSimpleGzip.call(this);
    } else {
      onClosureAdvancedGzip.call(this);
    }
  }

  /*--------------------------------------------------------------------------*/

  /**
   * Asynchronously checks if Java is installed. The callback is invoked with
   * one argument; (success).
   *
   * @private
   * @type Function
   * @param {Function} callback The function called once the status is resolved.
   */
  var checkJava = (function() {
    var result;
    return function(callback) {
      if (result != null) {
        _.defer(callback, result);
        return;
      }
      var java = spawn('java', ['-version']);

      java.stderr.on('data', function(data) {
        java.stderr.removeAllListeners('data');
        result = !!_.result(/java version "(.*?)"/.exec(data.toString()), 1);
        if (!result) {
          java.emit('error');
        }
        callback(result);
      });

      java.on('error', function() {
        console.warn('The Closure Compiler requires Java. Skipping...');
      });
    };
  }());

  /**
   * Resolves the source map path from the given output path.
   *
{'fraction_non_alphanumeric': 0.1703744267232528, 'fraction_numerical': 0.001505921007598056, 'mean_word_length': 2.4207445563099976, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, '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': '3043850', 'n_tokens_mistral': 4393, 'n_tokens_neox': 4240, 'n_words': 1083}