Modernizr/Modernizr

View on GitHub
bin/modernizr

Summary

Maintainability
Test Coverage
#!/usr/bin/env node
'use strict';

var fs = require('fs');
var _ = require('lodash');
var path = require('path');
var mkdirp = require('mkdirp');
var Modernizr = require(path.resolve(__dirname + '/../lib/cli.js'));
var yargs = require('yargs')
  .options('h', {
    alias: 'help',
    describe: 'Print Help'
  })
  .options('V', {
    alias: ['v', 'version'],
    describe: 'Print the version and exit'
  })
  .options('f', {
    alias: 'features',
    describe: 'comma separated list of feature detects'
  })
  .options('o', {
    alias: 'options',
    describe: 'comma separated list of extensibility options'
  })
  .options('c', {
    alias: 'config',
    describe: 'Path to a JSON file containing Modernizr configuration. See lib/config-all.json for an example'
  })
  .options('d', {
    alias: 'dest',
    describe: 'Path to write the Modernizr build file to. Defaults to ./modernizr.js'
  })
  .options('m', {
    alias: 'metadata',
    describe: 'Path to where the Modernizr feature-detect metadata should be saved. Defaults to ./metadata.json'
  })
  .options('u', {
    alias: 'uglify',
    describe: 'uglify/minify the output'
  })
  .options('s', {
    alias: 'scriptGlobalName',
    describe: 'Script global variable where Modernizr is attached. Defaults to window'
  })
  .options('q', {
    alias: 'quiet',
    describe: 'Silence all output'
  });
var argv = yargs.argv;
var cwd = process.cwd();
var dest = cwd + '/modernizr.js';
var configPath;
var config;

function log() {
  if (!argv.q) {
    console.log.apply(console, arguments);
  }
}
function stringify(obj, minified) {
  var replacer = function(key, value) {
    return value;
  };
  var args = minified ? [replacer,2] : [];
  args.unshift(obj);
  return JSON.stringify.apply(JSON, args);
}

if (argv.h) {
  yargs.showHelp();
  process.exit();
}

if (argv.V) {
  var pkg = require('../package.json');
  console.log('Modernizr v' + pkg.version);
  process.exit();
}

if (argv.d) {
  dest = path.normalize(argv.d);
  var exists = fs.existsSync(dest);
  var isDir = exists && fs.statSync(dest).isDirectory();
  var fileRequested = _.endsWith(dest, '.js');

  if ((exists && isDir) || (!exists && !fileRequested)) {
    dest = path.join(dest, 'modernizr.js');
  }

  mkdirp.sync(path.dirname(dest));
}

if (argv.m) {
  // path.normalize is used instead of normalize in order to support ~
  // we get an absolute path on the fallback from cwd, and any user supplied
  // argument will be relative to their current directory.
  var metaDest = path.normalize(argv.m === true ? cwd + '/metadata.json' : argv.m);
  Modernizr.metadata(function(metadata) {
    mkdirp.sync(path.dirname(metaDest));
    fs.writeFileSync(metaDest, stringify(metadata, !argv.u));
    log('metadata saved to ' + metaDest);
  });
  if (!argv.d) {
    // return early unless we explicitly request Modernizr to be built
    return;
  }
}

if (argv.o || argv.f) {
  var metadata = Modernizr.metadata();
  var options = Modernizr.options();

  var find = function(config, source) {
    if (!config) {
      return;
    }

    return config
      .replace(/-/g, ',')
      .split(',')
      .map(function(prop) {
        var obj = _.find(source, function(o) {
          if (o.property instanceof Array) {
            return o.property.includes(prop);
          } else {
            return o.property === prop;
          }
        });

        // setClasses is technically a flag, not an option. But it is passed
        // in as an option. Since it doesn't exist as an option we have to
        // special case around it :[
        if (prop === 'setClasses') {
          return 'setClasses';
        } else if (_.isUndefined(obj)) {
          throw new Error('invalid key value name - ' + prop);
        } else {
          return obj.amdPath || obj.property;
        }
      });
  };

  config = {
    'feature-detects': find(argv.f, metadata),
    'options': find(argv.o, options)
  };
}

if (argv.c) {
  try {
    configPath = fs.realpathSync(argv.c);
  } catch (e) {
    console.error(argv.c + ' does not exist.');
    process.exit(1);
  }
  if (!configPath) {
    configPath = path.resolve(__dirname, '../lib/config-all.json');
  }
}

try {
  if (!config && !configPath) {
    console.error('config file, inline features, or options required.');
    yargs.showHelp();
    process.exit(1);
  } else {
    config = config || {};
    if (configPath) {
      config = _.extend(config, require(configPath));
    }
    if (config && config.dest) {
      dest = path.join(cwd, config.dest, 'modernizr.js');
    }
  }
} catch (e) {
  console.error(configPath + ' is not valid JSON.');
  console.error(e);
  process.exit(1);
}

if (argv.u) {
  config.minify = true;
}

if (argv.scriptGlobalName) {
  config.scriptGlobalName = argv.scriptGlobalName;
}

Modernizr.build(config, function(output) {
  fs.writeFileSync(dest, output);
  log('Modernizr build saved to ' + dest);
});