<commit_before>#!/usr/bin/env node

'use strict';

const async = require('async');
const colors = require('colors/safe');
const request = require('minimal-request');
const semver = require('semver');
const _ = require('lodash');

var pkg = require('./package');

const getLatestVersion = (module, cb) => {
  request({
    url: `https://skimdb.npmjs.com/registry/_design/app/_view/byField?key=%22${module}%22`,
    json: true
  }, (err, response) => {
    if(err){ return cb(`Unable to connect to NPM: ${err}`); }
    cb(null, response.rows[0].value.version);
  });
};

const getParams = (cb) => {
  if(process.argv.length < 3){
    return cb('Usage: oc-migrate https://your-registry-url.domain.com');
  }

  cb(null, process.argv[2]);
};

const getRegistryVersion = (registryUrl, cb) => {
  request({
    url: registryUrl,
    json: true
  }, (err, response) => err ? cb(`Unable to connect to registry: ${err}`) : cb(err, response.ocVersion));
};

const getHandlebars3Components = (registryUrl, cb) => {
  request({
    url: registryUrl,
    json: true
  }, (err, response) => {
    let h3components = [];

    if(response.components.length === 0){
      return cb(null, h3components);
    }

    async.each(response.components, (component, next) => {
      request({
        url: `${component}/~info`,
        json: true
      }, (err, componentInfo) => {

        if(err){ return next(err); }

        const isHandlebars = componentInfo.oc.files.template.type === 'handlebars',
              isHandlebars3 = isHandlebars && (!componentInfo.oc.version || semver.lt(componentInfo.oc.version, '0.32.0')),
              isDeprecated = componentInfo.oc.state === 'deprecated';

        if(isHandlebars3 && !isDeprecated){
          h3components.push(componentInfo);
        }

        next();
      });
    }, err => cb(err, h3components));
  });
};

const log = (msg, type) => {
  const colour = { 'error' : 'red', 'warn': 'yellow', 'ok': 'green' }[type];

  if(!!colour){
    msg = colors[colour](msg);
  }

  return console.log(msg);
};

const exit = (msg) => {
  if(msg){
    log(msg, 'error');
    process.exit(1);
  }

  process.exit(0);
};

const checkHandlebars3MigrationIssues = (registryUrl, cb) => {

  log(`Analysing components...`, 'warn');

  getHandlebars3Components(registryUrl, (err, components) => {

    if(err){ return exit(err); }

    if(components.length > 0){

      log(`Warning: OC v0.33.X removes support for Handlebars 3, and it looks like some of your components will break if you upgrade to >0.33.X.`, 'warn')
      log(`${registryUrl} will need to be upgraded to 0.32.X, which supports both Handlebars 3 and 4.`, 'warn');
      log(`Then, the following components will need to be re-published using Handlebars 4. After that, re-run this tool for upgrading ${registryUrl} to a more recent version.`, 'warn');
      log(`Note: given OC components immutability, after publishing a new version of each component, you will need to ensure no consumer is consuming previous versions`, 'warn');

      _.each(components, (component, i) => {
        const author = _.isObject(component.author) ? JSON.stringify(component.author) : component.author;
        const repository = _.isObject(component.repository) ? JSON.stringify(component.repository) : component.repository;
        log(`${i + 1})\t${component.name}@${component.version} - Maintained by ${author || 'unknown'} ${repository || ''}`, 'error');
      });
    } else {
      log('OK', 'ok');
    }

    cb();
  });
};

getParams((err, registryUrl) => {
  if(err){ return exit(err); }

  async.parallel({
    ocMigrateVersion: next => getLatestVersion('oc-migrate', next),
    ocVersion: next => getLatestVersion('oc', next),
    registryVersion: next => getRegistryVersion(registryUrl, next)
  }, (err, results) => {

    if(err){ return exit(err); }

    if(semver.lt(pkg.version, results.ocMigrateVersion)){
      exit(`oc-migrate is outdated. For upgrading run: ${colors.green('[sudo] npm i -g oc-migrate')}`);
    }

    log(`Latest OC version: ${colors.green(results.ocVersion)}`);
    log(`${registryUrl} version: ${colors.green(results.registryVersion)}`);

    const diff = semver.diff(results.ocVersion, results.registryVersion);
    const safeUpgrade = (diff === 'patch') || (semver.major(results.ocVersion) > 0 && diff === 'minor');

    if(!diff){
      log('${registryUrl} is already using latest version. Well done.', 'ok');
    } else if(safeUpgrade){
      log(`${registryUrl} can be safely upgraded from ${results.registryVersion} to ${results.ocVersion}.`, 'ok');
    } else {
      log(`${registryUrl} should be upgraded to the latest version, but be careful: breaking changes are listed here: https://github.com/opentable/oc/blob/master/CHANGELOG.md`, 'warn');
    }

    if(semver.lt(results.registryVersion, '0.33.0')){
      checkHandlebars3MigrationIssues(registryUrl, exit);
    } else {
      exit();
    }
  });
});
<commit_msg>Better wording<commit_after>#!/usr/bin/env node

'use strict';

const async = require('async');
const colors = require('colors/safe');
const request = require('minimal-request');
const semver = require('semver');
const _ = require('lodash');

var pkg = require('./package');

const getLatestVersion = (module, cb) => {
  request({
    url: `https://skimdb.npmjs.com/registry/_design/app/_view/byField?key=%22${module}%22`,
    json: true
  }, (err, response) => {
    if(err){ return cb(`Unable to connect to NPM: ${err}`); }
    cb(null, response.rows[0].value.version);
  });
};

const getParams = (cb) => {
  if(process.argv.length < 3){
    return cb('Usage: oc-migrate https://your-registry-url.domain.com');
  }

  cb(null, process.argv[2]);
};

const getRegistryVersion = (registryUrl, cb) => {
  request({
    url: registryUrl,
    json: true
  }, (err, response) => err ? cb(`Unable to connect to registry: ${err}`) : cb(err, response.ocVersion));
};

const getHandlebars3Components = (registryUrl, cb) => {
  request({
    url: registryUrl,
    json: true
  }, (err, response) => {
    let h3components = [];

    if(response.components.length === 0){
      return cb(null, h3components);
    }

    async.each(response.components, (component, next) => {
      request({
        url: `${component}/~info`,
        json: true
      }, (err, componentInfo) => {

        if(err){ return next(err); }

        const isHandlebars = componentInfo.oc.files.template.type === 'handlebars',
              isHandlebars3 = isHandlebars && (!componentInfo.oc.version || semver.lt(componentInfo.oc.version, '0.32.0')),
              isDeprecated = componentInfo.oc.state === 'deprecated';

        if(isHandlebars3 && !isDeprecated){
          h3components.push(componentInfo);
        }

        next();
      });
    }, err => cb(err, h3components));
  });
};

const log = (msg, type) => {
  const colour = { 'error' : 'red', 'warn': 'yellow', 'ok': 'green' }[type];

  if(!!colour){
    msg = colors[colour](msg);
  }

  return console.log(msg);
};

const exit = (msg) => {
  if(msg){
    log(msg, 'error');
    process.exit(1);
  }

  process.exit(0);
};

const checkHandlebars3MigrationIssues = (registryUrl, registryVersion, cb) => {

  if(!semver.lt(registryVersion, '0.33.0')){
    return cb();
  };

  log(`Analysing components...`, 'warn');

  getHandlebars3Components(registryUrl, (err, components) => {

    if(err){ return exit(err); }

    if(components.length > 0){

      log(`Warning: OC v0.33.X removes support for Handlebars 3, and it looks like some of your components will break if you upgrade to >0.33.X.`, 'warn')

      if(semver.gte(registryVersion, '0.32.0')){
        log(`Before upgrading ${registryUrl} to 0.33.X, the following components will need to be re-published using 0.32.X<CLI<0.33.X (which will pick Handlebars 4).`, 'warn');
      } else {
        log(`${registryUrl} will need to be upgraded to 0.32.X, which supports both Handlebars 3 and 4.`, 'warn');
        log(`Only then, the following components will need to be re-published using 0.32.X<CLI<0.33.X (which will pick Handlebars 4).`, 'warn');
      }

      log(`After that, re-run this tool for upgrading ${registryUrl} to a more recent version.`, 'warn');
      log(`Note: given OC components immutability, after publishing a new version of each component, you will need to ensure no consumer is consuming previous versions`, 'warn');

      _.each(components, (component, i) => {
        const author = _.isObject(component.author) ? JSON.stringify(component.author) : component.author;
        const repository = _.isObject(component.repository) ? JSON.stringify(component.repository) : component.repository;
        log(`${i + 1})\t${component.name}@${component.version} - Maintained by ${author || 'unknown'} ${repository || ''}`, 'error');
      });
    } else {
      log('OK', 'ok');
    }

    cb();
  });
};

getParams((err, registryUrl) => {
  if(err){ return exit(err); }

  async.parallel({
    ocMigrateVersion: next => getLatestVersion('oc-migrate', next),
    ocVersion: next => getLatestVersion('oc', next),
    registryVersion: next => getRegistryVersion(registryUrl, next)
  }, (err, results) => {

    if(err){ return exit(err); }

    if(semver.lt(pkg.version, results.ocMigrateVersion)){
      exit(`oc-migrate is outdated. For upgrading run: ${colors.green('[sudo] npm i -g oc-migrate')}`);
    }

    log(`Latest OC version: ${colors.green(results.ocVersion)}`);
    log(`${registryUrl} version: ${colors.green(results.registryVersion)}`);

    const diff = semver.diff(results.ocVersion, results.registryVersion);
    const safeUpgrade = (diff === 'patch') || (semver.major(results.ocVersion) > 0 && diff === 'minor');

    if(!diff){
      log('${registryUrl} is already using latest version. Well done.', 'ok');
    } else if(safeUpgrade){
      log(`${registryUrl} can be safely upgraded from ${results.registryVersion} to ${results.ocVersion}.`, 'ok');
    } else {
      log(`${registryUrl} should be upgraded to the latest version, but be careful: breaking changes are listed here: https://github.com/opentable/oc/blob/master/CHANGELOG.md`, 'warn');
    }

    checkHandlebars3MigrationIssues(registryUrl, results.registryVersion, exit);
  });
});
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

var csv = require('to-csv');
var input = process.argv.slice(2);
var pkg = require('./package.json');
var stdin = require('get-stdin');
var viewport = require('./');

/**
 * Help screen
 */

function help() {
    console.log(pkg.description);
    console.log('');
    console.log('Usage');
    console.log('  $ viewport [device]');
    console.log('  $ cat <file> | viewport [device]');
    console.log('');
    console.log('Example');
    console.log('  $ viewport');
    console.log('  $ viewport iphone4 iphone5');
    console.log('  $ cat devices.txt | viewport');
}

/**
 * Show help
 */

if (input.indexOf('-h') !== -1 || input.indexOf('--help') !== -1) {
    help();
    return;
}

/**
 * Show package version
 */

if (input.indexOf('-v') !== -1 || input.indexOf('--version') !== -1) {
    console.log(pkg.version);
    return;
}

/**
 * Run
 */

function run(input) {
    viewport(input, function (err, devices) {
        if (err) {
            throw err;
        }

        console.log(csv(devices));
    });
}

/**
 * Apply arguments
 */

if (process.stdin.isTTY) {
    run(input);
} else {
    stdin(function (data) {
        [].push.apply(input, data.trim().split('\n'));
        run(input);
    });
}
<commit_msg>Tweak CLI<commit_after>#!/usr/bin/env node
'use strict';

var csv = require('to-csv');
var input = process.argv.slice(2);
var pkg = require('./package.json');
var stdin = require('get-stdin');
var viewport = require('./');

/**
 * Help screen
 */

function help() {
    console.log(pkg.description);
    console.log('');
    console.log('Usage');
    console.log('  $ viewport [device]');
    console.log('  $ cat <file> | viewport [device]');
    console.log('');
    console.log('Example');
    console.log('  $ viewport');
    console.log('  $ viewport iphone4 iphone5');
    console.log('  $ cat devices.txt | viewport');
}

/**
 * Show help
 */

if (input.indexOf('-h') !== -1 || input.indexOf('--help') !== -1) {
    return help();
}

/**
 * Show package version
 */

if (input.indexOf('-v') !== -1 || input.indexOf('--version') !== -1) {
    return console.log(pkg.version);
}

/**
 * Run
 */

function run(input) {
    viewport(input, function (err, devices) {
        if (err) {
            console.error(err);
            process.exit(1);
        }

        console.log(csv(devices));
    });
}

/**
 * Apply arguments
 */

if (process.stdin.isTTY) {
    run(input);
} else {
    stdin(function (data) {
        [].push.apply(input, data.trim().split('\n'));
        run(input);
    });
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

var minimist = require('minimist');
var osenv = require('osenv');
var filesize = require('file-size');
var mime = require('mime');
var ini = require('ini');
var fs = require('fs');
var path = require('path');
var s3 = require('s3');
var url = require('url');
var http = require('http');
var https = require('https');
var args = minimist(process.argv.slice(2), {
  'default': {
    'config': path.join(osenv.home(), '.s3cfg'),
    'delete-removed': false,
    'max-sockets': 20,
    'insecure': false,
    'region': 'us-east-1',
    'acl-public': false,
    'acl-private': false,
    'no-guess-mime-type': false,
  },
  'boolean': [
    'recursive',
    'delete-removed',
    'insecure',
    'acl-public',
    'acl-private',
    'no-guess-mime-type',
  ],
  'alias': {
    'P': 'acl-public',
  },
});

var fns = {
  'sync': cmdSync,
  'ls': cmdList,
  'help': cmdHelp,
  'del': cmdDelete,
  'put': cmdPut,
  'get': cmdGet,
  'cp': cmdCp,
  'mv': cmdMv,
};

var s3UrlRe = /^[sS]3:\/\/(.*?)\/(.*)/;

var client;
fs.readFile(args.config, {encoding: 'utf8'}, function(err, contents) {
  if (err) {
    console.error("This utility needs a config file formatted the same as for s3cmd");
    process.exit(1);
    return;
  }
  var config = ini.parse(contents);
  var accessKeyId, secretAccessKey;
  if (config && config.default) {
    accessKeyId = config.default.access_key;
    secretAccessKey = config.default.secret_key;
  }
  if (!secretAccessKey || !accessKeyId) {
    console.error("Config file missing access_key or secret_key");
    process.exit(1);
    return;
  }
  var maxSockets = parseInt(args['max-sockets'], 10);
  http.globalAgent.maxSockets = maxSockets;
  https.globalAgent.maxSockets = maxSockets;
  client = s3.createClient({
    s3Options: {
      accessKeyId: accessKeyId,
      secretAccessKey: secretAccessKey,
      sslEnabled: !args.insecure,
      region: args.region,
    },
  });
  var cmd = args._.shift();
  var fn = fns[cmd];
  if (!fn) fn = cmdHelp;
  fn();
});

function cmdSync() {
  var source = args._[0];
  var dest = args._[1];

  var sourceS3 = isS3Url(source);
  var destS3 = isS3Url(dest);

  var localDir, s3Url, method;
  var getS3Params;
  var s3Params = {};
  if (sourceS3 && !destS3) {
    localDir = dest;
    s3Url = source;
    method = client.downloadDir;
    getS3Params = downloadGetS3Params;
  } else if (!sourceS3 && destS3) {
    localDir = source;
    s3Url = dest;
    method = client.uploadDir;
    s3Params.ACL = getAcl();
    getS3Params = uploadGetS3Params;
  } else {
    console.error("one target must be from S3, the other must be from local file system.");
    process.exit(1);
  }
  var parts = parseS3Url(s3Url);
  s3Params.Prefix = parts.key;
  s3Params.Bucket = parts.bucket;

  parseAddHeaders(s3Params);

  var params = {
    deleteRemoved: args['delete-removed'],
    getS3Params: getS3Params,
    localDir: localDir,
    s3Params: s3Params,
  };
  var syncer = method.call(client, params);
  setUpProgress(syncer);
}

function uploadGetS3Params(filePath, stat, callback) {
  //console.error("Uploading", filePath);
  callback(null, {
    ContentType: getContentType(filePath),
  });
}

function downloadGetS3Params(filePath, s3Object, callback) {
  //console.error("Downloading", filePath);
  callback(null, {});
}

function cmdList() {
  var recursive = args.recursive;
  var s3Url = args._[0];
  var parts = parseS3Url(s3Url);
  var params = {
    recursive: recursive,
    s3Params: {
      Bucket: parts.bucket,
      Prefix: parts.key,
      Delimiter: recursive ? null : '/',
    },
  };
  var finder = client.listObjects(params);
  finder.on('data', function(data) {
    data.CommonPrefixes.forEach(function(dirObject) {
      console.log("DIR " + dirObject.Prefix);
    });
    data.Contents.forEach(function(object) {
      console.log(object.LastModified + " " + object.Size + " " + object.Key);
    });
  });
}

function cmdDelete() {
  var parts = parseS3Url(args._[0]);
  if (args.recursive) {
    doDeleteDir();
  } else {
    doDeleteObject();
  }

  function doDeleteDir() {
    var params = {
      Bucket: parts.bucket,
      Prefix: parts.key,
    };
    var deleter = client.deleteDir(params);
    setUpProgress(deleter, true);
  }

  function doDeleteObject() {
    var params = {
      Bucket: parts.bucket,
      Delete: {
        Objects: [
          {
            Key: parts.key,
          },
        ],
      }
    };
    client.deleteObjects(params);
  }
}

function cmdPut() {
  var source = args._[0];
  var dest = args._[1];
  var parts = parseS3Url(dest);
  if (/\/$/.test(parts.key)) {
    parts.key += path.basename(source);
  }
  var acl = getAcl();
  var s3Params = {
    Bucket: parts.bucket,
    Key: parts.key,
    ACL: acl,
    ContentType: getContentType(source),
  };
  parseAddHeaders(s3Params);
  var params = {
    localFile: source,
    s3Params: s3Params,
  };
  var uploader = client.uploadFile(params);
  var doneText;
  if (acl === 'public-read') {
    var publicUrl = args.insecure ?
      s3.getPublicUrlHttp(parts.bucket, parts.key) :
      s3.getPublicUrl(parts.bucket, parts.key, args.region);
    doneText = "Public URL: " + publicUrl;
  } else {
    doneText = "done";
  }
  setUpProgress(uploader, false, doneText);
}

function cmdGet() {
  var source = args._[0];
  var dest = args._[1];
  var parts = parseS3Url(source);
  if (!dest) {
    dest = path.basename(source);
  }
  var params = {
    localFile: dest,
    s3Params: {
      Bucket: parts.bucket,
      Key: parts.key,
    },
  };
  var downloader = client.downloadFile(params);
  setUpProgress(downloader);
}

function cmdCp() {
  var source = args._[0];
  var dest = args._[1];
  var sourceParts = parseS3Url(source);
  var destParts = parseS3Url(dest);

  var s3Params = {
    CopySource: sourceParts.bucket + '/' + sourceParts.key,
    Bucket: destParts.bucket,
    Key: destParts.key,
  };

  client.copyObject(s3Params);
}

function cmdMv() {
  var source = args._[0];
  var dest = args._[1];
  var sourceParts = parseS3Url(source);
  var destParts = parseS3Url(dest);

  var s3Params = {
    CopySource: sourceParts.bucket + '/' + sourceParts.key,
    Bucket: destParts.bucket,
    Key: destParts.key,
  };

  client.moveObject(s3Params);
}

function cmdHelp() {
  console.log("Usage: s3-cli (command) (command arguments)");
  console.log("Commands:", Object.keys(fns).join(" "));
}

function parseS3Url(s3Url) {
  if (!s3Url) {
    console.error("Expected S3 URL argument");
    process.exit(1);
  }
  var match = s3Url.match(s3UrlRe);
  if (!match) {
    console.error("Not a valid S3 URL:", s3Url);
    process.exit(1);
  }
  return {
    bucket: match[1],
    key: match[2],
  };
}

function isS3Url(str) {
  return s3UrlRe.test(str);
}

function getContentType(filename) {
  if (args['default-mime-type']) {
    mime.default_type = args['default-mime-type'];
  }
  if (args['no-guess-mime-type']) {
    return mime.default_type;
  } else {
    return mime.lookup(filename);
  }
}

function getAcl() {
  var acl = null;
  if (args['acl-public']) {
    acl = 'public-read';
  } else if (args['acl-private']) {
    acl = 'private';
  }
  return acl;
}

function setUpProgress(o, notBytes, doneText) {
  var start = null;
  doneText = doneText || "done";
  var printFn = process.stderr.isTTY ? printProgress : noop;
  printFn();
  var progressInterval = setInterval(printFn, 100);
  o.on('end', function() {
    clearInterval(progressInterval);
    process.stderr.write("\n" + doneText + "\n");
  });

  function printProgress() {
    var percent = Math.floor(o.progressAmount / o.progressTotal * 100);
    var amt = notBytes ? String(o.progressAmount) : fmtBytes(o.progressAmount);
    var total = notBytes ? String(o.progressTotal) : fmtBytes(o.progressTotal);
    var parts = [];
    if (o.filesFound > 0 && !o.doneFindingFiles) {
      parts.push(o.filesFound + " files");
    }
    if (o.objectsFound > 0 && !o.doneFindingObjects) {
      parts.push(o.objectsFound + " objects");
    }
    if (o.deleteTotal > 0) {
      parts.push(o.deleteAmount + "/" + o.deleteTotal + " deleted");
    }
    if (o.progressMd5Amount > 0 && !o.doneMd5) {
      parts.push(fmtBytes(o.progressMd5Amount) + "/" + fmtBytes(o.progressMd5Total) + " MD5");
    }
    if (o.progressTotal > 0) {
      if (!start) start = new Date();
      var part = amt + "/" + total;
      if (!isNaN(percent)) part += " " + percent + "% done";
      parts.push(part);
      if (!notBytes) {
        var now = new Date();
        var seconds = (now - start) / 1000;
        var bytesPerSec = o.progressAmount / seconds;
        var humanSpeed = fmtBytes(bytesPerSec) + '/s';
        parts.push(humanSpeed);
      }
    }
    var line = parts.join(", ");
    process.stderr.clearLine();
    process.stderr.cursorTo(0);
    process.stderr.write(line);
  }
}

function parseAddHeaders(s3Params) {
  var addHeaders = args['add-header'];
  if (addHeaders) {
    if (Array.isArray(addHeaders)) {
      addHeaders.forEach(handleAddHeader);
    } else {
      handleAddHeader(addHeaders);
    }
  }
  function handleAddHeader(header) {
    var match = header.match(/^(.*):\s*(.*)$/);
    if (!match) {
      console.error("Improperly formatted header:", header);
      process.exit(1);
    }
    var headerName = match[1];
    var paramName = headerName.replace(/-/g, '');
    var paramValue = match[2];
    s3Params[paramName] = paramValue;
  }
}

function fmtBytes(byteCount) {
  if (byteCount <= 0) {
    return "0B";
  } else {
    return filesize(byteCount).human({jedec: true});
  }
}

function noop() {}
<commit_msg>barf on unexpected command line parameters. closes #2<commit_after>#!/usr/bin/env node

var minimist = require('minimist');
var osenv = require('osenv');
var filesize = require('file-size');
var mime = require('mime');
var ini = require('ini');
var fs = require('fs');
var path = require('path');
var s3 = require('s3');
var url = require('url');
var http = require('http');
var https = require('https');
var argOptions = {
  'default': {
    'config': path.join(osenv.home(), '.s3cfg'),
    'delete-removed': false,
    'max-sockets': 20,
    'region': 'us-east-1',
    'default-mime-type': null,
    'add-header': null,
  },
  'boolean': [
    'recursive',
    'delete-removed',
    'insecure',
    'acl-public',
    'acl-private',
    'no-guess-mime-type',
  ],
  'alias': {
    'P': 'acl-public',
  },
};
var args = minimist(process.argv.slice(2), argOptions);

var fns = {
  'sync': cmdSync,
  'ls': cmdList,
  'help': cmdHelp,
  'del': cmdDelete,
  'put': cmdPut,
  'get': cmdGet,
  'cp': cmdCp,
  'mv': cmdMv,
};
var USAGE_TEXT =
  "Usage: s3-cli (command) (command arguments)\n" +
  "Commands: " + Object.keys(fns).join(" ");

var s3UrlRe = /^[sS]3:\/\/(.*?)\/(.*)/;
barfOnUnexpectedArgs();

var client;
fs.readFile(args.config, {encoding: 'utf8'}, function(err, contents) {
  if (err) {
    console.error("This utility needs a config file formatted the same as for s3cmd");
    process.exit(1);
    return;
  }
  var config = ini.parse(contents);
  var accessKeyId, secretAccessKey;
  if (config && config.default) {
    accessKeyId = config.default.access_key;
    secretAccessKey = config.default.secret_key;
  }
  if (!secretAccessKey || !accessKeyId) {
    console.error("Config file missing access_key or secret_key");
    process.exit(1);
    return;
  }
  var maxSockets = parseInt(args['max-sockets'], 10);
  http.globalAgent.maxSockets = maxSockets;
  https.globalAgent.maxSockets = maxSockets;
  client = s3.createClient({
    s3Options: {
      accessKeyId: accessKeyId,
      secretAccessKey: secretAccessKey,
      sslEnabled: !args.insecure,
      region: args.region,
    },
  });
  var cmd = args._.shift();
  var fn = fns[cmd];
  if (!fn) fn = cmdHelp;
  fn();
});

function cmdSync() {
  expectArgCount(2);
  var source = args._[0];
  var dest = args._[1];

  var sourceS3 = isS3Url(source);
  var destS3 = isS3Url(dest);

  var localDir, s3Url, method;
  var getS3Params;
  var s3Params = {};
  if (sourceS3 && !destS3) {
    localDir = dest;
    s3Url = source;
    method = client.downloadDir;
    getS3Params = downloadGetS3Params;
  } else if (!sourceS3 && destS3) {
    localDir = source;
    s3Url = dest;
    method = client.uploadDir;
    s3Params.ACL = getAcl();
    getS3Params = uploadGetS3Params;
  } else {
    console.error("one target must be from S3, the other must be from local file system.");
    process.exit(1);
  }
  var parts = parseS3Url(s3Url);
  s3Params.Prefix = parts.key;
  s3Params.Bucket = parts.bucket;

  parseAddHeaders(s3Params);

  var params = {
    deleteRemoved: args['delete-removed'],
    getS3Params: getS3Params,
    localDir: localDir,
    s3Params: s3Params,
  };
  var syncer = method.call(client, params);
  setUpProgress(syncer);
}

function uploadGetS3Params(filePath, stat, callback) {
  //console.error("Uploading", filePath);
  callback(null, {
    ContentType: getContentType(filePath),
  });
}

function downloadGetS3Params(filePath, s3Object, callback) {
  //console.error("Downloading", filePath);
  callback(null, {});
}

function cmdList() {
  expectArgCount(1);
  var recursive = args.recursive;
  var s3Url = args._[0];
  var parts = parseS3Url(s3Url);
  var params = {
    recursive: recursive,
    s3Params: {
      Bucket: parts.bucket,
      Prefix: parts.key,
      Delimiter: recursive ? null : '/',
    },
  };
  var finder = client.listObjects(params);
  finder.on('data', function(data) {
    data.CommonPrefixes.forEach(function(dirObject) {
      console.log("DIR " + dirObject.Prefix);
    });
    data.Contents.forEach(function(object) {
      console.log(object.LastModified + " " + object.Size + " " + object.Key);
    });
  });
}

function cmdDelete() {
  expectArgCount(1);
  var parts = parseS3Url(args._[0]);
  if (args.recursive) {
    doDeleteDir();
  } else {
    doDeleteObject();
  }

  function doDeleteDir() {
    var params = {
      Bucket: parts.bucket,
      Prefix: parts.key,
    };
    var deleter = client.deleteDir(params);
    setUpProgress(deleter, true);
  }

  function doDeleteObject() {
    var params = {
      Bucket: parts.bucket,
      Delete: {
        Objects: [
          {
            Key: parts.key,
          },
        ],
      }
    };
    client.deleteObjects(params);
  }
}

function cmdPut() {
  expectArgCount(2);
  var source = args._[0];
  var dest = args._[1];
  var parts = parseS3Url(dest);
  if (/\/$/.test(parts.key)) {
    parts.key += path.basename(source);
  }
  var acl = getAcl();
  var s3Params = {
    Bucket: parts.bucket,
    Key: parts.key,
    ACL: acl,
    ContentType: getContentType(source),
  };
  parseAddHeaders(s3Params);
  var params = {
    localFile: source,
    s3Params: s3Params,
  };
  var uploader = client.uploadFile(params);
  var doneText;
  if (acl === 'public-read') {
    var publicUrl = args.insecure ?
      s3.getPublicUrlHttp(parts.bucket, parts.key) :
      s3.getPublicUrl(parts.bucket, parts.key, args.region);
    doneText = "Public URL: " + publicUrl;
  } else {
    doneText = "done";
  }
  setUpProgress(uploader, false, doneText);
}

function cmdGet() {
  expectArgCount(2);
  var source = args._[0];
  var dest = args._[1];
  var parts = parseS3Url(source);
  if (!dest) {
    dest = path.basename(source);
  }
  var params = {
    localFile: dest,
    s3Params: {
      Bucket: parts.bucket,
      Key: parts.key,
    },
  };
  var downloader = client.downloadFile(params);
  setUpProgress(downloader);
}

function cmdCp() {
  expectArgCount(2);
  var source = args._[0];
  var dest = args._[1];
  var sourceParts = parseS3Url(source);
  var destParts = parseS3Url(dest);

  var s3Params = {
    CopySource: sourceParts.bucket + '/' + sourceParts.key,
    Bucket: destParts.bucket,
    Key: destParts.key,
  };

  client.copyObject(s3Params);
}

function cmdMv() {
  expectArgCount(2);
  var source = args._[0];
  var dest = args._[1];
  var sourceParts = parseS3Url(source);
  var destParts = parseS3Url(dest);

  var s3Params = {
    CopySource: sourceParts.bucket + '/' + sourceParts.key,
    Bucket: destParts.bucket,
    Key: destParts.key,
  };

  client.moveObject(s3Params);
}

function cmdHelp() {
  console.log(USAGE_TEXT);
}

function parseS3Url(s3Url) {
  if (!s3Url) {
    console.error("Expected S3 URL argument");
    process.exit(1);
  }
  var match = s3Url.match(s3UrlRe);
  if (!match) {
    console.error("Not a valid S3 URL:", s3Url);
    process.exit(1);
  }
  return {
    bucket: match[1],
    key: match[2],
  };
}

function isS3Url(str) {
  return s3UrlRe.test(str);
}

function getContentType(filename) {
  if (args['default-mime-type']) {
    mime.default_type = args['default-mime-type'];
  }
  if (args['no-guess-mime-type']) {
    return mime.default_type;
  } else {
    return mime.lookup(filename);
  }
}

function getAcl() {
  var acl = null;
  if (args['acl-public']) {
    acl = 'public-read';
  } else if (args['acl-private']) {
    acl = 'private';
  }
  return acl;
}

function setUpProgress(o, notBytes, doneText) {
  var start = null;
  doneText = doneText || "done";
  var printFn = process.stderr.isTTY ? printProgress : noop;
  printFn();
  var progressInterval = setInterval(printFn, 100);
  o.on('end', function() {
    clearInterval(progressInterval);
    process.stderr.write("\n" + doneText + "\n");
  });

  function printProgress() {
    var percent = Math.floor(o.progressAmount / o.progressTotal * 100);
    var amt = notBytes ? String(o.progressAmount) : fmtBytes(o.progressAmount);
    var total = notBytes ? String(o.progressTotal) : fmtBytes(o.progressTotal);
    var parts = [];
    if (o.filesFound > 0 && !o.doneFindingFiles) {
      parts.push(o.filesFound + " files");
    }
    if (o.objectsFound > 0 && !o.doneFindingObjects) {
      parts.push(o.objectsFound + " objects");
    }
    if (o.deleteTotal > 0) {
      parts.push(o.deleteAmount + "/" + o.deleteTotal + " deleted");
    }
    if (o.progressMd5Amount > 0 && !o.doneMd5) {
      parts.push(fmtBytes(o.progressMd5Amount) + "/" + fmtBytes(o.progressMd5Total) + " MD5");
    }
    if (o.progressTotal > 0) {
      if (!start) start = new Date();
      var part = amt + "/" + total;
      if (!isNaN(percent)) part += " " + percent + "% done";
      parts.push(part);
      if (!notBytes) {
        var now = new Date();
        var seconds = (now - start) / 1000;
        var bytesPerSec = o.progressAmount / seconds;
        var humanSpeed = fmtBytes(bytesPerSec) + '/s';
        parts.push(humanSpeed);
      }
    }
    var line = parts.join(", ");
    process.stderr.clearLine();
    process.stderr.cursorTo(0);
    process.stderr.write(line);
  }
}

function parseAddHeaders(s3Params) {
  var addHeaders = args['add-header'];
  if (addHeaders) {
    if (Array.isArray(addHeaders)) {
      addHeaders.forEach(handleAddHeader);
    } else {
      handleAddHeader(addHeaders);
    }
  }
  function handleAddHeader(header) {
    var match = header.match(/^(.*):\s*(.*)$/);
    if (!match) {
      console.error("Improperly formatted header:", header);
      process.exit(1);
    }
    var headerName = match[1];
    var paramName = headerName.replace(/-/g, '');
    var paramValue = match[2];
    s3Params[paramName] = paramValue;
  }
}

function fmtBytes(byteCount) {
  if (byteCount <= 0) {
    return "0B";
  } else {
    return filesize(byteCount).human({jedec: true});
  }
}

function noop() {}

function barfOnUnexpectedArgs() {
  var validArgs = {'_': true};
  addValid(Object.keys(argOptions.default));
  addValid(Object.keys(argOptions.alias));
  addValid(argOptions.boolean);

  var invalidArgs = [];
  for (var argName in args) {
    if (!validArgs[argName]) {
      invalidArgs.push(argName);
    }
  }

  if (invalidArgs.length) {
    console.error(USAGE_TEXT);
    console.error("Unrecognized option(s): " + invalidArgs.join(", "));
    process.exit(1);
  }

  function addValid(array) {
    array.forEach(function(name) {
      validArgs[name] = true;
    });
  }
}

function expectArgCount(n) {
  if (args._.length === n) return;
  console.error("Expected " + n + " arguments, got " + args._.length);
  process.exit(1);
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

const fs = require('fs');
const url = require('url');
const http = require('follow-redirects').http;
const https = require('follow-redirects').https;
const colors = require('colors');

colors.setTheme({
    error: ['red', 'bold']
});

colors.setTheme({
    info: ['cyan', 'bold']
});

colors.setTheme({
    normal: ['green', 'bold']
});

const argv = require('yargs')
    .usage('\nUsage: $0 -u [/user.id] -n [file name]'.info)
    .demand(['u', 'n'])
    .describe('u', 'ID of facebook user')
    .describe('n', 'File name')
    .argv;

console.log("Please Wait")
var file = fs.createWriteStream(argv.n+".jpg");

var start_downlaod = http.get('http://graph.facebook.com/' + argv.u + '/picture?width=80', function(res) {
    res.pipe(file);
    console.log('Done');
}).on('error', function(err) {
    console.error(err);
});
<commit_msg>[extended string obj]<commit_after>#!/usr/bin/env node

'use strict';

const fs = require('fs');

const http = require('follow-redirects').http;

const colors = require('chalk');

const argv = require('yargs')
    .usage(colors.cyan('\nUsage: $0 -u [/user.id] -n [file name]'))
    .demand(['u', 'n'])
    .describe('u', 'ID of facebook user')
    .describe('n', 'File name')
    .argv;
console.log("Please Wait")
const file = fs.createWriteStream(argv.n+".jpg");

const start_downlaod = http.get('http://graph.facebook.com/' + argv.u + '/picture?width=80', function(res) {
    res.pipe(file);
    console.log('Done');
}).on('error', function(err) {
    console.error(err);
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

var seaport = require('seaport')
  , cc = require('config-chain')
  , path = require('path')
  , fs = require('fs')
  , log = require('npmlog')
  , optimist = require('optimist')

function extend(dest, src) {
  Object.keys(src).forEach(function (key) {
    dest[key] = src[key]
  })
}

var argv = optimist
  .describe('h', 'Seaport hostname')
  .alias('h', 'host')

  .describe('p', 'Seaport port (required)')
  .alias('p', 'port')

  .describe('q', 'Quiet mode')
  .alias('q', 'quiet')

  .describe('k', 'Seaport key file (see Seaport documentation)')
  .alias('k', 'key')

  .describe('help', 'Displays this help message')
  .argv

if (argv.help) {
  optimist.showHelp()
  return
}

log.heading = 'nodeport'

var file

var conf = cc( argv , cc.env('NODEPORT_') )

file = path.resolve('.nodeport')
if (fs.existsSync(file))
  conf.addFile(file, 'ini', 'local')

file = path.resolve(process.env.HOME, '.nodeport')
if (fs.existsSync(file))
  conf.addFile(file, 'ini', 'global')

// Defaults config
conf.root = {}
conf.root.host = '127.0.0.1'

if (conf.get('quiet')) {
  log.level = 'silent'
} else {
  log.level = conf.get('loglevel')
}

if (!conf.get('port')) {
  log.error('Missing seaport port')
  return
}

var main
  , role
  , meta = {}

file = path.resolve(argv._[0])

var pkgFile = path.basename(file) == 'package.json' ? file : path.join(file, 'package.json')
if (fs.existsSync( pkgFile )) {
  var pkg = require(pkgFile)

  if (pkg.nodeport) main = pkg.nodeport
  else if (pkg.main) main = pkg.main
  else if (pkg.scripts && pkg.scripts.start) main = pkg.scripts.start

  if (main) main = path.resolve(path.dirname(pkgFile), main)

  role = pkg.name + '@' + pkg.version
  if (pkg.seaport) extend(meta, pkg.seaport)
}

if (!main) {
  main = path.join(file, 'server.js')
  if (!fs.existsSync(main)) {
    main = file
  }
}

if (!role) {
  role = path.basename(file)
}

try {
  main = require(main)
} catch(err) {
  log.error(err)
  log.error('Failed to load main')
  return
}

if (!main.listen) {
  log.error('Main must have a listen method')
  return
}

var opts = conf.get('key') && JSON.parse(fs.readFileSync(path.resolve(conf.get('key')), 'utf8')) || {}

var ports = seaport.connect(conf.get('port'), conf.get('host'), opts)

var argMeta = conf.get('meta')
if (typeof argMeta === 'string') {
  argMeta = JSON.parse(fs.readFileSync(path.resolve(argMeta), 'utf8')) || {}
}
if (typeof argMeta === 'object') {
  extend(meta, argMeta)
}

var server = main.listen(ports.register(role, meta))

process.once('SIGINT', function () {
  log.info('Got SIGINT, closeing seaport connection')
  ports.close()
  if (typeof main.close === 'function') main.close()
  if (typeof server.close === 'function') server.close()
})
<commit_msg>defaults to process.cwd()<commit_after>#!/usr/bin/env node

var seaport = require('seaport')
  , cc = require('config-chain')
  , path = require('path')
  , fs = require('fs')
  , log = require('npmlog')
  , optimist = require('optimist')

function extend(dest, src) {
  Object.keys(src).forEach(function (key) {
    dest[key] = src[key]
  })
}

var argv = optimist
  .describe('h', 'Seaport hostname')
  .alias('h', 'host')

  .describe('p', 'Seaport port (required)')
  .alias('p', 'port')

  .describe('q', 'Quiet mode')
  .alias('q', 'quiet')

  .describe('k', 'Seaport key file (see Seaport documentation)')
  .alias('k', 'key')

  .describe('help', 'Displays this help message')
  .argv

if (argv.help) {
  optimist.showHelp()
  return
}

log.heading = 'nodeport'

var file

var conf = cc( argv , cc.env('NODEPORT_') )

file = path.resolve('.nodeport')
if (fs.existsSync(file))
  conf.addFile(file, 'ini', 'local')

file = path.resolve(process.env.HOME, '.nodeport')
if (fs.existsSync(file))
  conf.addFile(file, 'ini', 'global')

// Defaults config
conf.root = {}
conf.root.host = '127.0.0.1'

if (conf.get('quiet')) {
  log.level = 'silent'
} else {
  log.level = conf.get('loglevel')
}

if (!conf.get('port')) {
  log.error('Missing seaport port')
  return
}

var main
  , role
  , meta = {}

file = path.resolve(argv._[0] || '')

var pkgFile = path.basename(file) == 'package.json' ? file : path.join(file, 'package.json')
if (fs.existsSync( pkgFile )) {
  var pkg = require(pkgFile)

  if (pkg.nodeport) main = pkg.nodeport
  else if (pkg.main) main = pkg.main
  else if (pkg.scripts && pkg.scripts.start) main = pkg.scripts.start

  if (main) main = path.resolve(path.dirname(pkgFile), main)

  role = pkg.name + '@' + pkg.version
  if (pkg.seaport) extend(meta, pkg.seaport)
}

if (!main) {
  main = path.join(file, 'server.js')
  if (!fs.existsSync(main)) {
    main = file
  }
}

if (!role) {
  role = path.basename(file)
}

try {
  main = require(main)
} catch(err) {
  log.error(err)
  log.error('Failed to load main')
  return
}

if (!main.listen) {
  log.error('Main must have a listen method')
  return
}

var opts = conf.get('key') && JSON.parse(fs.readFileSync(path.resolve(conf.get('key')), 'utf8')) || {}

var ports = seaport.connect(conf.get('port'), conf.get('host'), opts)

var argMeta = conf.get('meta')
if (typeof argMeta === 'string') {
  argMeta = JSON.parse(fs.readFileSync(path.resolve(argMeta), 'utf8')) || {}
}
if (typeof argMeta === 'object') {
  extend(meta, argMeta)
}

var server = main.listen(ports.register(role, meta))

process.once('SIGINT', function () {
  log.info('Got SIGINT, closeing seaport connection')
  ports.close()
  if (typeof main.close === 'function') main.close()
  if (typeof server.close === 'function') server.close()
})
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

require('v8-compile-cache');

const importLocal = require('import-local');

// Prefer the local installation of webpack-cli
if (importLocal(__filename)) {
    return;
}
process.title = 'webpack';
process.cliLogger = require('webpack-log')({
    name: 'webpack',
});

const updateNotifier = require('update-notifier');
const packageJson = require('./package.json');

const notifier = updateNotifier({
    pkg,
    updateCheckInterval: 1000 * 60 * 60 * 24 * 7, // 1 week
});

if (notifier.update) {
    console.log(`Update available: ${notifier.update.latest}`);
}

const semver = require('semver');

const version = packageJson.engines.node;

if (!semver.satisfies(process.version, version)) {
    const rawVersion = version.replace(/[^\d\.]*/, '');
    process.cliLogger.error('webpack CLI requires at least Node v' + rawVersion + '. ' + 'You have ' + process.version + '.\n' + 'See https://webpack.js.org/ ' + 'for migration help and similar.');
    process.exit(1);
}

require('./lib/bootstrap');
<commit_msg>fix: tweak<commit_after>#!/usr/bin/env node

'use strict';

require('v8-compile-cache');

const importLocal = require('import-local');

// Prefer the local installation of webpack-cli
if (importLocal(__filename)) {
    return;
}
process.title = 'webpack';
process.cliLogger = require('webpack-log')({
    name: 'webpack',
});

const updateNotifier = require('update-notifier');
const packageJson = require('./package.json');

const notifier = updateNotifier({
    pkg: packageJson,
    updateCheckInterval: 1000 * 60 * 60 * 24 * 7, // 1 week
});

if (notifier.update) {
    console.log(`Update available: ${notifier.update.latest}`);
}

const semver = require('semver');

const version = packageJson.engines.node;

if (!semver.satisfies(process.version, version)) {
    const rawVersion = version.replace(/[^\d\.]*/, '');
    process.cliLogger.error('webpack CLI requires at least Node v' + rawVersion + '. ' + 'You have ' + process.version + '.\n' + 'See https://webpack.js.org/ ' + 'for migration help and similar.');
    process.exit(1);
}

require('./lib/bootstrap');
<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
 * html-minifier CLI tool
 *
 * The MIT License (MIT)
 *
 *  Copyright (c) 2014-2016 Zoltan Frombach
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
 *  this software and associated documentation files (the "Software"), to deal in
 *  the Software without restriction, including without limitation the rights to
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 *  the Software, and to permit persons to whom the Software is furnished to do so,
 *  subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

'use strict';

var cli = require('cli');
var concat = require('concat-stream');
var changeCase = require('change-case');
var path = require('path');
var fs = require('fs');
var appName = require('./package.json').name;
var appVersion = require('./package.json').version;
var minify = require('./dist/htmlminifier.min.js').minify;
var HTMLLint = require('./dist/htmlminifier.min.js').HTMLLint;
var minifyOptions = {};
var input = null;
var output = null;

cli.width = 100;
cli.option_width = 40;
cli.setApp(appName, appVersion);

var usage = appName + ' [OPTIONS] [FILE(s)]\n\n';
usage += '  If no input files are specified then STDIN will be used for input.\n';
usage += '  If more than one input file is specified then those will be concatenated and minified together.\n\n';
usage += '  When you specify a config file with the --config-file option (see sample-cli-config-file.conf for format)\n';
usage += '    you can still override some of its contents by providing individual command line options, too.\n\n';
usage += '  When you want to provide an array of strings for --ignore-custom-comments or --process-scripts options\n';
usage += '    on the command line you must escape those such as --ignore-custom-comments "[\\"string1\\",\\"string1\\"]"\n';

cli.setUsage(usage);

var mainOptions = {
  removeComments: [[false, 'Strip HTML comments']],
  removeCommentsFromCDATA: [[false, 'Strip HTML comments from scripts and styles']],
  removeCDATASectionsFromCDATA: [[false, 'Remove CDATA sections from script and style elements']],
  collapseWhitespace: [[false, 'Collapse white space that contributes to text nodes in a document tree.']],
  conservativeCollapse: [[false, 'Always collapse to 1 space (never remove it entirely)']],
  preserveLineBreaks: [[false, 'Always collapse to 1 line break (never remove it entirely) when whitespace between tags include a line break.']],
  collapseInlineTagWhitespace: [[false, 'Collapse white space around inline tag']],
  collapseBooleanAttributes: [[false, 'Omit attribute values from boolean attributes']],
  removeTagWhitespace: [[false, 'Remove space between attributes whenever possible.']],
  removeAttributeQuotes: [[false, 'Remove quotes around attributes when possible.']],
  removeRedundantAttributes: [[false, 'Remove attributes when value matches default.']],
  preventAttributesEscaping: [[false, 'Prevents the escaping of the values of attributes.']],
  useShortDoctype: [[false, 'Replaces the doctype with the short (HTML5) doctype']],
  removeEmptyAttributes: [[false, 'Remove all attributes with whitespace-only values']],
  removeScriptTypeAttributes: [[false, 'Remove type="text/javascript" from script tags. Other type attribute values are left intact.']],
  removeStyleLinkTypeAttributes: [[false, 'Remove type="text/css" from style and link tags. Other type attribute values are left intact.']],
  removeOptionalTags: [[false, 'Remove unrequired tags']],
  removeEmptyElements: [[false, 'Remove all elements with empty contents']],
  lint: [[false, 'Toggle linting']],
  keepClosingSlash: [[false, 'Keep the trailing slash on singleton elements']],
  caseSensitive: [[false, 'Treat attributes in case sensitive manner (useful for SVG; e.g. viewBox)']],
  minifyJS: [[false, 'Minify Javascript in script elements and on* attributes (uses UglifyJS)']],
  minifyCSS: [[false, 'Minify CSS in style elements and style attributes (uses clean-css)']],
  minifyURLs: [[false, 'Minify URLs in various attributes (uses relateurl)', 'string'], 'site-url'],
  ignoreCustomComments: [[false, 'Array of regex\'es that allow to ignore certain comments, when matched', 'string'], 'json-regex'],
  ignoreCustomFragments: [[false, 'Array of regex\'es that allow to ignore certain fragments, when matched (e.g. <?php ... ?>, {{ ... }})', 'string'], 'json-regex'],
  processScripts: [[false, 'Array of strings corresponding to types of script elements to process through minifier (e.g. "text/ng-template", "text/x-handlebars-template", etc.)', 'string'], 'json'],
  maxLineLength: [[false, 'Max line length', 'number'], true],
  customEventAttributes: [[false, 'Arrays of regex\'es that allow to support custom event attributes for minifyJS (e.g. ng-click)', 'string'], 'json-regex'],
  customAttrAssign: [[false, 'Arrays of regex\'es that allow to support custom attribute assign expressions (e.g. \'

\')', 'string'], 'json-regex'],
  customAttrSurround: [[false, 'Arrays of regex\'es that allow to support custom attribute surround expressions (e.g. <input {{#if value}}checked="checked"{{/if}}>)', 'string'], 'json-regex'],
  customAttrCollapse: [[false, 'Regex that specifies custom attribute to strip newlines from (e.g. /ng\-class/)', 'string'], 'string-regex']
};

var cliOptions = {
  version: ['v', 'Version information'],
  output: ['o', 'Specify output file (if not specified STDOUT will be used for output)', 'file'],
  'config-file': ['c', 'Use config file', 'file'],
  'input-dir': [false, 'Specify an input directory', 'dir'],
  'output-dir': [false, 'Specify an output directory', 'dir']
};

var mainOptionKeys = Object.keys(mainOptions);
mainOptionKeys.forEach(function(key) {
  cliOptions[changeCase.paramCase(key)] = mainOptions[key][0];
});

cli.parse(cliOptions);

cli.main(function(args, options) {

  function stringToRegExp(value) {
    // JSON does not support regexes, so, e.g., JSON.parse() will not create
    // a RegExp from the JSON value `[ "/matchString/" ]`, which is
    // technically just an array containing a string that begins and end with
    // a forward slash. To get a RegExp from a JSON string, it must be
    // constructed explicitly in JavaScript.
    //
    // The likelihood of actually wanting to match text that is enclosed in
    // forward slashes is probably quite rare, so if forward slashes were
    // included in an argument that requires a regex, the user most likely
    // thought they were part of the syntax for specifying a regex.
    //
    // In the unlikely case that forward slashes are indeed desired in the
    // search string, the user would need to enclose the expression in a
    // second set of slashes:
    //
    //    --customAttrSrround "[\"//matchString//\"]"
    //
    if (value) {
      var stripSlashes = /^\/(.*)\/$/.exec(value);
      if (stripSlashes) {
        value = stripSlashes[1];
      }
      return new RegExp(value);
    }
  }

  function parseJSONOption(value, options) {
    var opts = options || {};
    if (value !== null) {
      var jsonArray;
      try {
        jsonArray = JSON.parse(value);
        if (opts.regexArray) {
          jsonArray = jsonArray.map(function (regexString) {
            return stringToRegExp(regexString);
          });
        }
      }
      catch (e) {
        cli.fatal('Could not parse JSON value \'' + value + '\'');
      }
      if (jsonArray instanceof Array) {
        return jsonArray;
      }
      else {
        return [value];
      }
    }
  }

  function runMinify(original, output) {
    var status = 0;
    var minified = null;
    try {
      minified = minify(original, minifyOptions);
    }
    catch (e) {
      status = 3;
      cli.error('Minification error');
      process.stderr.write((e.stack || e).toString());
    }

    if (minifyOptions.lint) {
      minifyOptions.lint.populate();
    }

    if (minified !== null) {
      // Write the output
      try {
        if (output != null) {
          fs.writeFileSync(path.resolve(output), minified);
        }
        else {
          process.stdout.write(minified);
        }
      }
      catch (e) {
        status = 4;
        console.log(output);
        cli.error('Cannot write to output');
      }
    }

    return status;
  }

  function createDirectory(path) {
    try {
      fs.mkdirSync(path);
    }
    catch (e) {
      if (e.code !== 'EEXIST') {
        cli.fatal('Can not create directory ' + path);
        return 3;
      }
    }
    return 0;
  }

  function processDirectory(inputDir, outputDir) {
    var fileList = fs.readdirSync(inputDir);
    var status = createDirectory(outputDir);

    for (var i = 0; status === 0 && i < fileList.length; i++) {
      var fileName = fileList[i];
      var inputFilePath = inputDir + '/' + fileName;
      var outputFilePath = outputDir + '/' + fileName;

      var stat = fs.statSync(inputFilePath);
      if (stat.isDirectory()) {
        status = processDirectory(inputFilePath, outputFilePath);
      }
      else {
        var originalContent = fs.readFileSync(inputFilePath, 'utf8');
        status = runMinify(originalContent, outputFilePath);
      }
    }

    return status;
  }

  if (options.version) {
    cli.output(appName + ' v' + appVersion);
    cli.exit(0);
  }

  if (options['config-file']) {
    var fileOptions;
    var fileOptionsPath = path.resolve(options['config-file']);
    try {
      fileOptions = fs.readFileSync(fileOptionsPath, { encoding: 'utf8' });
    }
    catch (e) {
      cli.fatal('The specified config file doesn’t exist or is unreadable:\n' + fileOptionsPath);
    }
    try {
      fileOptions = JSON.parse(fileOptions);
    }
    catch (je) {
      try {
        fileOptions = require(fileOptionsPath);
      }
      catch (ne) {
        cli.fatal('Cannot read the specified config file. \nAs JSON: ' + je.message + '\nAs module: ' + ne.message);
      }
    }

    if (fileOptions && typeof fileOptions === 'object') {
      minifyOptions = fileOptions;
    }
  }
  mainOptionKeys.forEach(function(key) {
    var paramKey = changeCase.paramCase(key);
    var value = options[paramKey];
    if (options[paramKey] !== null) {
      switch (mainOptions[key][1]) {
        case 'json':
          minifyOptions[key] = parseJSONOption(value);
          break;
        case 'json-regex':
          minifyOptions[key] = parseJSONOption(value, { regexArray: true });
          break;
        case 'string-regex':
          minifyOptions[key] = stringToRegExp(value);
          break;
        case 'site-url':
          minifyOptions[key] = { site: value };
          break;
        case true:
          minifyOptions[key] = value;
          break;
        default:
          minifyOptions[key] = true;
      }
    }
  });

  if (minifyOptions.lint === true) {
    minifyOptions.lint = new HTMLLint();
  }

  if (args.length) {
    input = args;
  }

  if (options['input-dir'] || options['output-dir']) {
    var inputDir = options['input-dir'];
    var outputDir = options['output-dir'];

    if (!inputDir) {
      cli.error('The option output-dir needs to be used with the option input-dir. If you are working with a single file, use -o.');
      cli.exit(2);
    }

    try {
      fs.statSync(inputDir);
    }
    catch (e) {
      cli.error('The input directory does not exist');
      cli.exit(2);
    }

    if (!outputDir) {
      cli.error('You need to specify where to write the output files with the option --output-dir');
      cli.exit(2);
    }

    try {
      cli.exit(processDirectory(inputDir, outputDir));
    }
    catch (e) {
      cli.error('Error while processing input files');
      cli.error(e);
      cli.exit(3);
    }
  }

  if (options.output) {
    output = options.output;
  }

  if (input !== null) { // Minifying one or more files specified on the CMD line

    var original = '';

    input.forEach(function(afile) {
      try {
        original += fs.readFileSync(afile, 'utf8');
      }
      catch (e) {
        cli.error('Cannot read file ' + afile);
        cli.exit(2);
      }
    });

    cli.exit(runMinify(original, output));

  }
  else { // Minifying input coming from STDIN
    process.stdin.pipe(concat({ encoding: 'string' }, runMinify));
  }
});
<commit_msg>Allow -o from stdin<commit_after>#!/usr/bin/env node
/**
 * html-minifier CLI tool
 *
 * The MIT License (MIT)
 *
 *  Copyright (c) 2014-2016 Zoltan Frombach
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
 *  this software and associated documentation files (the "Software"), to deal in
 *  the Software without restriction, including without limitation the rights to
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 *  the Software, and to permit persons to whom the Software is furnished to do so,
 *  subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

'use strict';

var cli = require('cli');
var concat = require('concat-stream');
var changeCase = require('change-case');
var path = require('path');
var fs = require('fs');
var appName = require('./package.json').name;
var appVersion = require('./package.json').version;
var minify = require('./dist/htmlminifier.min.js').minify;
var HTMLLint = require('./dist/htmlminifier.min.js').HTMLLint;
var minifyOptions = {};
var input = null;
var output = null;

cli.width = 100;
cli.option_width = 40;
cli.setApp(appName, appVersion);

var usage = appName + ' [OPTIONS] [FILE(s)]\n\n';
usage += '  If no input files are specified then STDIN will be used for input.\n';
usage += '  If more than one input file is specified then those will be concatenated and minified together.\n\n';
usage += '  When you specify a config file with the --config-file option (see sample-cli-config-file.conf for format)\n';
usage += '    you can still override some of its contents by providing individual command line options, too.\n\n';
usage += '  When you want to provide an array of strings for --ignore-custom-comments or --process-scripts options\n';
usage += '    on the command line you must escape those such as --ignore-custom-comments "[\\"string1\\",\\"string1\\"]"\n';

cli.setUsage(usage);

var mainOptions = {
  removeComments: [[false, 'Strip HTML comments']],
  removeCommentsFromCDATA: [[false, 'Strip HTML comments from scripts and styles']],
  removeCDATASectionsFromCDATA: [[false, 'Remove CDATA sections from script and style elements']],
  collapseWhitespace: [[false, 'Collapse white space that contributes to text nodes in a document tree.']],
  conservativeCollapse: [[false, 'Always collapse to 1 space (never remove it entirely)']],
  preserveLineBreaks: [[false, 'Always collapse to 1 line break (never remove it entirely) when whitespace between tags include a line break.']],
  collapseInlineTagWhitespace: [[false, 'Collapse white space around inline tag']],
  collapseBooleanAttributes: [[false, 'Omit attribute values from boolean attributes']],
  removeTagWhitespace: [[false, 'Remove space between attributes whenever possible.']],
  removeAttributeQuotes: [[false, 'Remove quotes around attributes when possible.']],
  removeRedundantAttributes: [[false, 'Remove attributes when value matches default.']],
  preventAttributesEscaping: [[false, 'Prevents the escaping of the values of attributes.']],
  useShortDoctype: [[false, 'Replaces the doctype with the short (HTML5) doctype']],
  removeEmptyAttributes: [[false, 'Remove all attributes with whitespace-only values']],
  removeScriptTypeAttributes: [[false, 'Remove type="text/javascript" from script tags. Other type attribute values are left intact.']],
  removeStyleLinkTypeAttributes: [[false, 'Remove type="text/css" from style and link tags. Other type attribute values are left intact.']],
  removeOptionalTags: [[false, 'Remove unrequired tags']],
  removeEmptyElements: [[false, 'Remove all elements with empty contents']],
  lint: [[false, 'Toggle linting']],
  keepClosingSlash: [[false, 'Keep the trailing slash on singleton elements']],
  caseSensitive: [[false, 'Treat attributes in case sensitive manner (useful for SVG; e.g. viewBox)']],
  minifyJS: [[false, 'Minify Javascript in script elements and on* attributes (uses UglifyJS)']],
  minifyCSS: [[false, 'Minify CSS in style elements and style attributes (uses clean-css)']],
  minifyURLs: [[false, 'Minify URLs in various attributes (uses relateurl)', 'string'], 'site-url'],
  ignoreCustomComments: [[false, 'Array of regex\'es that allow to ignore certain comments, when matched', 'string'], 'json-regex'],
  ignoreCustomFragments: [[false, 'Array of regex\'es that allow to ignore certain fragments, when matched (e.g. <?php ... ?>, {{ ... }})', 'string'], 'json-regex'],
  processScripts: [[false, 'Array of strings corresponding to types of script elements to process through minifier (e.g. "text/ng-template", "text/x-handlebars-template", etc.)', 'string'], 'json'],
  maxLineLength: [[false, 'Max line length', 'number'], true],
  customEventAttributes: [[false, 'Arrays of regex\'es that allow to support custom event attributes for minifyJS (e.g. ng-click)', 'string'], 'json-regex'],
  customAttrAssign: [[false, 'Arrays of regex\'es that allow to support custom attribute assign expressions (e.g. \'

\')', 'string'], 'json-regex'],
  customAttrSurround: [[false, 'Arrays of regex\'es that allow to support custom attribute surround expressions (e.g. <input {{#if value}}checked="checked"{{/if}}>)', 'string'], 'json-regex'],
  customAttrCollapse: [[false, 'Regex that specifies custom attribute to strip newlines from (e.g. /ng\-class/)', 'string'], 'string-regex']
};

var cliOptions = {
  version: ['v', 'Version information'],
  output: ['o', 'Specify output file (if not specified STDOUT will be used for output)', 'file'],
  'config-file': ['c', 'Use config file', 'file'],
  'input-dir': [false, 'Specify an input directory', 'dir'],
  'output-dir': [false, 'Specify an output directory', 'dir']
};

var mainOptionKeys = Object.keys(mainOptions);
mainOptionKeys.forEach(function(key) {
  cliOptions[changeCase.paramCase(key)] = mainOptions[key][0];
});

cli.parse(cliOptions);

cli.main(function(args, options) {

  function stringToRegExp(value) {
    // JSON does not support regexes, so, e.g., JSON.parse() will not create
    // a RegExp from the JSON value `[ "/matchString/" ]`, which is
    // technically just an array containing a string that begins and end with
    // a forward slash. To get a RegExp from a JSON string, it must be
    // constructed explicitly in JavaScript.
    //
    // The likelihood of actually wanting to match text that is enclosed in
    // forward slashes is probably quite rare, so if forward slashes were
    // included in an argument that requires a regex, the user most likely
    // thought they were part of the syntax for specifying a regex.
    //
    // In the unlikely case that forward slashes are indeed desired in the
    // search string, the user would need to enclose the expression in a
    // second set of slashes:
    //
    //    --customAttrSrround "[\"//matchString//\"]"
    //
    if (value) {
      var stripSlashes = /^\/(.*)\/$/.exec(value);
      if (stripSlashes) {
        value = stripSlashes[1];
      }
      return new RegExp(value);
    }
  }

  function parseJSONOption(value, options) {
    var opts = options || {};
    if (value !== null) {
      var jsonArray;
      try {
        jsonArray = JSON.parse(value);
        if (opts.regexArray) {
          jsonArray = jsonArray.map(function (regexString) {
            return stringToRegExp(regexString);
          });
        }
      }
      catch (e) {
        cli.fatal('Could not parse JSON value \'' + value + '\'');
      }
      if (jsonArray instanceof Array) {
        return jsonArray;
      }
      else {
        return [value];
      }
    }
  }

  function runMinify(original, output) {
    var status = 0;
    var minified = null;
    try {
      minified = minify(original, minifyOptions);
    }
    catch (e) {
      status = 3;
      cli.error('Minification error');
      process.stderr.write((e.stack || e).toString());
    }

    if (minifyOptions.lint) {
      minifyOptions.lint.populate();
    }

    if (minified !== null) {
      // Write the output
      try {
        if (output != null) {
          fs.writeFileSync(path.resolve(output), minified);
        }
        else {
          process.stdout.write(minified);
        }
      }
      catch (e) {
        status = 4;
        console.log(output);
        cli.error('Cannot write to output');
      }
    }

    return status;
  }

  function createDirectory(path) {
    try {
      fs.mkdirSync(path);
    }
    catch (e) {
      if (e.code !== 'EEXIST') {
        cli.fatal('Can not create directory ' + path);
        return 3;
      }
    }
    return 0;
  }

  function processDirectory(inputDir, outputDir) {
    var fileList = fs.readdirSync(inputDir);
    var status = createDirectory(outputDir);

    for (var i = 0; status === 0 && i < fileList.length; i++) {
      var fileName = fileList[i];
      var inputFilePath = inputDir + '/' + fileName;
      var outputFilePath = outputDir + '/' + fileName;

      var stat = fs.statSync(inputFilePath);
      if (stat.isDirectory()) {
        status = processDirectory(inputFilePath, outputFilePath);
      }
      else {
        var originalContent = fs.readFileSync(inputFilePath, 'utf8');
        status = runMinify(originalContent, outputFilePath);
      }
    }

    return status;
  }

  if (options.version) {
    cli.output(appName + ' v' + appVersion);
    cli.exit(0);
  }

  if (options['config-file']) {
    var fileOptions;
    var fileOptionsPath = path.resolve(options['config-file']);
    try {
      fileOptions = fs.readFileSync(fileOptionsPath, { encoding: 'utf8' });
    }
    catch (e) {
      cli.fatal('The specified config file doesn’t exist or is unreadable:\n' + fileOptionsPath);
    }
    try {
      fileOptions = JSON.parse(fileOptions);
    }
    catch (je) {
      try {
        fileOptions = require(fileOptionsPath);
      }
      catch (ne) {
        cli.fatal('Cannot read the specified config file. \nAs JSON: ' + je.message + '\nAs module: ' + ne.message);
      }
    }

    if (fileOptions && typeof fileOptions === 'object') {
      minifyOptions = fileOptions;
    }
  }
  mainOptionKeys.forEach(function(key) {
    var paramKey = changeCase.paramCase(key);
    var value = options[paramKey];
    if (options[paramKey] !== null) {
      switch (mainOptions[key][1]) {
        case 'json':
          minifyOptions[key] = parseJSONOption(value);
          break;
        case 'json-regex':
          minifyOptions[key] = parseJSONOption(value, { regexArray: true });
          break;
        case 'string-regex':
          minifyOptions[key] = stringToRegExp(value);
          break;
        case 'site-url':
          minifyOptions[key] = { site: value };
          break;
        case true:
          minifyOptions[key] = value;
          break;
        default:
          minifyOptions[key] = true;
      }
    }
  });

  if (minifyOptions.lint === true) {
    minifyOptions.lint = new HTMLLint();
  }

  if (args.length) {
    input = args;
  }

  if (options['input-dir'] || options['output-dir']) {
    var inputDir = options['input-dir'];
    var outputDir = options['output-dir'];

    if (!inputDir) {
      cli.error('The option output-dir needs to be used with the option input-dir. If you are working with a single file, use -o.');
      cli.exit(2);
    }

    try {
      fs.statSync(inputDir);
    }
    catch (e) {
      cli.error('The input directory does not exist');
      cli.exit(2);
    }

    if (!outputDir) {
      cli.error('You need to specify where to write the output files with the option --output-dir');
      cli.exit(2);
    }

    try {
      cli.exit(processDirectory(inputDir, outputDir));
    }
    catch (e) {
      cli.error('Error while processing input files');
      cli.error(e);
      cli.exit(3);
    }
  }

  if (options.output) {
    output = options.output;
  }

  if (input !== null) { // Minifying one or more files specified on the CMD line

    var original = '';

    input.forEach(function(afile) {
      try {
        original += fs.readFileSync(afile, 'utf8');
      }
      catch (e) {
        cli.error('Cannot read file ' + afile);
        cli.exit(2);
      }
    });

    cli.exit(runMinify(original, output));

  }
  else { // Minifying input coming from STDIN
    process.stdin.pipe(concat({ encoding: 'string' }, function(content) {
      runMinify(content, output);
    }));
  }
});
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict'

var semver = require('semver')
var cliPackageJson = require('./package.json')

if (!semver.satisfies(process.versions.node, cliPackageJson.engines.node)) {
  console.error(
    'jsreport cli requires to have installed a nodejs version of at least ' +
    cliPackageJson.engines.node +
    ' but you have installed version ' + process.versions.node + '. please update your nodejs version and try again'
  )

  process.exit(1)
}

const path = require('path')
const Liftoff = require('liftoff')
const commander = require('./lib/commander')
const { printError } = require('./lib/errorUtils')
const help = require('./lib/commands/help')
const init = require('./lib/commands/init')
const repair = require('./lib/commands/repair')
const configure = require('./lib/commands/configure')
const render = require('./lib/commands/render')

const cli = new Liftoff({
  processTitle: 'jsreport',
  moduleName: 'jsreport-cli',
  configName: '.jsreport'
})

cli.launch({}, initCLI)

function initCLI (env) {
  const isCLIDev = process.env.JSREPORT_CLI_DEV === 'enabled'
  const args = process.argv.slice(2)
  const cwd = process.cwd()
  let localCommander

  if (!isCLIDev && !env.modulePath) {
    // if no local installation is found,
    // try to detect if some global command was specified
    const globalCliHandler = commander(cwd, {
      builtInCommands: [help, init, repair, configure, render]
    })

    globalCliHandler.on('started', (err, info) => {
      if (err) {
        printError(err, console)
        return process.exit(1)
      }

      if (!info.handled) {
        if (info.mainCommand != null) {
          console.error('"' + info.mainCommand + '" command not found')
          console.error('Local jsreport-cli not found in:', env.cwd)
          console.error('Try installing jsreport-cli or jsreport package to have more commands available')

          return process.exit(1)
        }

        console.error('Local jsreport-cli not found in:', env.cwd)
        console.error('Try installing jsreport-cli or jsreport package')

        return process.exit(1)
      }
    })

    globalCliHandler.start(args)
  } else {
    if (isCLIDev) {
      localCommander = require(path.join(cwd, 'lib/commander.js'))(cwd, { cliName: 'jsreport' })
    } else {
      // Check for semver difference between global cli and local installation
      if (semver.gt(cliPackageJson.version, env.modulePackage.version)) {
        console.log('Warning: jsreport-cli version mismatch:')
        console.log('Global jsreport-cli is', cliPackageJson.version)
        console.log('Local jsreport-cli is', env.modulePackage.version)
      }

      localCommander = require(path.join(path.dirname(env.modulePath), 'lib/commander.js'))(cwd)
    }

    // start processing
    localCommander.start(args)
  }
}
<commit_msg>ensure a correct cli name by default<commit_after>#!/usr/bin/env node
'use strict'

var semver = require('semver')
var cliPackageJson = require('./package.json')

if (!semver.satisfies(process.versions.node, cliPackageJson.engines.node)) {
  console.error(
    'jsreport cli requires to have installed a nodejs version of at least ' +
    cliPackageJson.engines.node +
    ' but you have installed version ' + process.versions.node + '. please update your nodejs version and try again'
  )

  process.exit(1)
}

const path = require('path')
const Liftoff = require('liftoff')
const commander = require('./lib/commander')
const { printError } = require('./lib/errorUtils')
const help = require('./lib/commands/help')
const init = require('./lib/commands/init')
const repair = require('./lib/commands/repair')
const configure = require('./lib/commands/configure')
const render = require('./lib/commands/render')

const cli = new Liftoff({
  processTitle: 'jsreport',
  moduleName: 'jsreport-cli',
  configName: '.jsreport'
})

cli.launch({}, initCLI)

function initCLI (env) {
  const isCLIDev = process.env.JSREPORT_CLI_DEV === 'enabled'
  const args = process.argv.slice(2)
  const cwd = process.cwd()
  let localCommander

  if (!isCLIDev && !env.modulePath) {
    // if no local installation is found,
    // try to detect if some global command was specified
    const globalCliHandler = commander(cwd, {
      cliName: 'jsreport',
      builtInCommands: [help, init, repair, configure, render]
    })

    globalCliHandler.on('started', (err, info) => {
      if (err) {
        printError(err, console)
        return process.exit(1)
      }

      if (!info.handled) {
        if (info.mainCommand != null) {
          console.error('"' + info.mainCommand + '" command not found')
          console.error('Local jsreport-cli not found in:', env.cwd)
          console.error('Try installing jsreport-cli or jsreport package to have more commands available')

          return process.exit(1)
        }

        console.error('Local jsreport-cli not found in:', env.cwd)
        console.error('Try installing jsreport-cli or jsreport package')

        return process.exit(1)
      }
    })

    globalCliHandler.start(args)
  } else {
    if (isCLIDev) {
      localCommander = require(path.join(cwd, 'lib/commander.js'))(cwd, { cliName: 'jsreport' })
    } else {
      // Check for semver difference between global cli and local installation
      if (semver.gt(cliPackageJson.version, env.modulePackage.version)) {
        console.log('Warning: jsreport-cli version mismatch:')
        console.log('Global jsreport-cli is', cliPackageJson.version)
        console.log('Local jsreport-cli is', env.modulePackage.version)
      }

      localCommander = require(path.join(path.dirname(env.modulePath), 'lib/commander.js'))(cwd, {
        cliName: 'jsreport'
      })
    }

    // start processing
    localCommander.start(args)
  }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

var concat = require('concat-stream'),
    argv = require('minimist')(process.argv.slice(2), {
        string: 'overpass-url',
        boolean: 'flat-properties',
        default: {
            'flat-properties': false
        }
    }),
    fs = require('fs'),
    overpass = require('./');

function openData(s) {
    var query = s.toString();
    overpass(query, function(err, geojson) {
        if (!err) {
            console.log(JSON.stringify(geojson));
        } else {
            console.error(err);
            process.exit(1);
        }
    }, {
        overpassUrl: argv['overpass-url'],
        flatProperties: argv['flat-properties']
    });
}

((argv._[0] && fs.createReadStream(argv._[0])) || process.stdin).pipe(concat(openData));
<commit_msg>add --version command line option<commit_after>#!/usr/bin/env node

var concat = require('concat-stream'),
    argv = require('minimist')(process.argv.slice(2), {
        string: 'overpass-url',
        boolean: 'flat-properties',
        boolean: 'version',
        default: {
            'flat-properties': false
        }
    }),
    fs = require('fs'),
    overpass = require('./');

if (argv['version'])
  return process.stdout.write(require('./package.json').version+'\n');

function openData(s) {
    var query = s.toString();
    overpass(query, function(err, geojson) {
        if (!err) {
            console.log(JSON.stringify(geojson));
        } else {
            console.error(err);
            process.exit(1);
        }
    }, {
        overpassUrl: argv['overpass-url'],
        flatProperties: argv['flat-properties']
    });
}

((argv._[0] && fs.createReadStream(argv._[0])) || process.stdin).pipe(concat(openData));
<|endoftext|>


<commit_before>#!/usr/bin/env node

var sesico = require('./lib');

// TODO: It would be nice if Cheerio could parse a stream directly,
// but it seems that it is not possible. In the meantime, we read the
// whole stream into a string.

function readStreamIntoString (stream, callback){
  var output = '';
  stream.on('data', function(data){ output += data; });
  stream.on('end', function(){ callback(null, output); });
  stream.on('error', callback);
}

readStreamIntoString(process.stdin, function(err, input){
  var $ = sesico(input);
  $.use('./sesico');
  process.stdout.write( $.html() );
  process.stdout.write('\n');
});
<commit_msg>command line tool loads sesico.js file from current directory<commit_after>#!/usr/bin/env node

var path = require('path');
var sesico = require('./lib');

// TODO: It would be nice if Cheerio could parse a stream directly,
// but it seems that it is not possible. In the meantime, we read the
// whole stream into a string.

function readStreamIntoString (stream, callback){
  var output = '';
  stream.on('data', function(data){ output += data; });
  stream.on('end', function(){ callback(null, output); });
  stream.on('error', callback);
}

readStreamIntoString(process.stdin, function(err, input){
  var $ = sesico(input);
  $.use(path.join(process.cwd(), 'sesico'));
  process.stdout.write( $.html() );
  process.stdout.write('\n');
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

var version = require('./package.json').version;

var path = require('path');
var fs = require('fs');
var lexParser = require('lex-parser');
var RegExpLexer = require('./regexp-lexer.js');

var opts = require('nomnom')
  .unknownOptionTreatment(false)              // do not accept unknown options!
  .script('jison-lex')
  .option('file', {
    flag: true,
    position: 0,
    help: 'file containing a lexical grammar'
  })
  .option('outfile', {
    abbr: 'o',
    metavar: 'FILE',
    help: 'Filename and base module name of the generated parser'
  })
  .option('module-type', {
    abbr: 't',
    default: 'commonjs',
    metavar: 'TYPE',
    choices: ['commonjs', 'amd', 'js', 'es'],
    help: 'The type of module to generate (commonjs, amd, es, js)'
  })
  .option('version', {
    abbr: 'V',
    flag: true,
    help: 'print version and exit',
    callback: function() {
       return version;
    }
  });

exports.main = function (opts) {
    if (opts.file) {
        var raw = fs.readFileSync(path.normalize(opts.file), 'utf8'),
            name = path.basename((opts.outfile||opts.file)).replace(/\..*$/g, '');

        fs.writeFileSync(opts.outfile||(name + '.js'), processGrammar(raw, name));
    } else {
        readin(function (raw) {
            console.log(processGrammar(raw));
        });
    }
};

function processGrammar(file, name) {
    var grammar;
    try {
        grammar = lexParser.parse(file);
    } catch (e) {
        try {
            grammar = JSON.parse(file);
        } catch (e2) {
            throw e;
        }
    }

    var settings = grammar.options || {};
    if (!settings.moduleType) {
        settings.moduleType = (opts['module-type'] || opts.moduleType);
    }
    if (!settings.moduleName && name) {
        settings.moduleName = name.replace(/-\w/g, function (match) {
            return match.charAt(1).toUpperCase();
        });
    }
    grammar.options = settings;

    return RegExpLexer.generate(grammar);
}

function readin (cb) {
    var stdin = process.openStdin(),
        data = '';

    stdin.setEncoding('utf8');
    stdin.addListener('data', function (chunk) {
        data += chunk;
    });
    stdin.addListener('end', function () {
        cb(data);
    });
}

if (require.main === module) {
    exports.main(opts.parse());
}

<commit_msg>refactor: synchronized the CLI code to ensure jison-lex and jison both share the same code structures and flow for handling the CLI and running their compilers from the command line.<commit_after>#!/usr/bin/env node

var lexParser = require('lex-parser');
var RegExpLexer = require('./regexp-lexer.js');

function getCommandlineOptions() {
    'use strict';

    var version = require('./package.json').version;
    var opts = require('nomnom')
        .script('jison-lex')
        .unknownOptionTreatment(false)              // do not accept unknown options!
        .options({
            file: {
                flag: true,
                position: 0,
                help: 'file containing a lexical grammar'
            },
            json: {
                abbr: 'j',
                flag: true,
                default: false,
                help: 'jison will expect a grammar in either JSON/JSON5 or JISON format: the precise format is autodetected'
            },
            outfile: {
                abbr: 'o',
                metavar: 'FILE',
                help : 'Filepath and base module name of the generated parser;\nwhen terminated with a / (dir separator) it is treated as the destination directory where the generated output will be stored'
            },
            debug: {
                abbr: 'd',
                flag: true,
                default: false,
                help: 'Debug mode'
            },
            reportStats: {
                full: 'info',
                abbr: 'I',
                flag: true,
                default: false,
                help: 'Report some statistics about the generated parser'
            },
            moduleType: {
                full: 'module-type',
                abbr: 't',
                default: 'commonjs',
                metavar: 'TYPE',
                choices: ['commonjs', 'amd', 'js', 'es'],
                help: 'The type of module to generate (commonjs, amd, es, js)'
            },
            moduleName: {
                full: 'module-name',
            	abbr: 'n',
            	metavar: 'NAME',
            	help: 'The name of the generated parser object, namespace supported'
            },
            main: {
                full: 'main',
            	abbr: 'x',
                flag: true,
                default: false,
                help: 'Include .main() entry point in generated commonjs module'
            },
            moduleMain: {
                full: 'module-main',
            	abbr: 'y',
            	metavar: 'NAME',
            	help: 'The main module function definition'
            },
            version: {
                abbr: 'V',
                flag: true,
                help: 'print version and exit',
                callback: function () {
                    return version;
                }
            }
        }).parse();

    return opts;
}

var cli = module.exports;

cli.main = function cliMain(opts) {
    'use strict';

    opts = RegExpLexer.mkStdOptions(opts);

    var fs = require('fs');
    var path = require('path');

    function isDirectory(fp) {
        try {
            return fs.lstatSync(fp).isDirectory();
        } catch (e) {
            return false;
        }
    }

    function mkdirp(fp) {
        if (!fp || fp === '.' || fp.length === 0) {
            return false;
        }
        try {
            fs.mkdirSync(fp);
            return true;
        } catch (e) {
            if (e.code === 'ENOENT') {
                var parent = path.dirname(fp);
                // Did we hit the root directory by now? If so, abort!
                // Else, create the parent; iff that fails, we fail too...
                if (parent !== fp && mkdirp(parent)) {
                    try {
                        // Retry creating the original directory: it should succeed now
                        fs.mkdirSync(fp);
                        return true;
                    } catch (e) {
                        return false;
                    }
                }
            }
        }
        return false;
    }

    function processInputFile() {
        // getting raw files
        var lex;
        var original_cwd = process.cwd();

        var raw = fs.readFileSync(path.normalize(opts.file), 'utf8');

        // making best guess at json mode
        opts.json = path.extname(opts.file) === '.json' || opts.json;

        // When only the directory part of the output path was specified, then we
        // do NOT have the target module name in there as well!
        var outpath = opts.outfile;
        if (/[\\\/]$/.test(outpath) || isDirectory(outpath)) {
            opts.outfile = null;
            outpath = outpath.replace(/[\\\/]$/, '');
        }
        if (outpath && outpath.length > 0) {
            outpath += '/';
        } else {
            outpath = '';
        }

        // setting output file name and module name based on input file name
        // if they aren't specified.
        var name = path.basename(opts.outfile || opts.file);

        // get the base name (i.e. the file name without extension)
        // i.e. strip off only the extension and keep any other dots in the filename
        name = path.basename(name, path.extname(name));

        opts.outfile = opts.outfile || (outpath + name + '.js');
        if (!opts.moduleName && name) {
            opts.moduleName = opts.defaultModuleName = name.replace(/-\w/g,
                function (match) {
                    return match.charAt(1).toUpperCase();
                });
        }

        // Change CWD to the directory where the source grammar resides: this helps us properly
        // %include any files mentioned in the grammar with relative paths:
        var new_cwd = path.dirname(path.normalize(opts.file));
        process.chdir(new_cwd);

        var lexer = cli.generateLexerString(raw, opts);

        // and change back to the CWD we started out with:
        process.chdir(original_cwd);

        mkdirp(path.dirname(opts.outfile));
        fs.writeFileSync(opts.outfile, lexer);
        console.log('JISON-LEX output for module [' + opts.moduleName + '] has been written to file:', opts.outfile);
    }

    function readin(cb) {
        var stdin = process.openStdin(),
        data = '';

        stdin.setEncoding('utf8');
        stdin.addListener('data', function (chunk) {
            data += chunk;
        });
        stdin.addListener('end', function () {
            cb(data);
        });
    }

    function processStdin() {
        readin(function processStdinReadInCallback(raw) {
            console.log(cli.generateLexerString(raw, opts));
        });
    }

    // if an input file wasn't given, assume input on stdin
    if (opts.file) {
        processInputFile();
    } else {
        processStdin();
    }
};

cli.generateLexerString = function generateLexerString(lexerSpec, opts) {
    'use strict';

    // var settings = RegExpLexer.mkStdOptions(opts);

    return RegExpLexer.generate(lexerSpec, null, opts);
};

if (require.main === module) {
    var opts = getCommandlineOptions();
    cli.main(opts);
}

<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';
const updateNotifier = require('update-notifier');
const meow = require('meow');
const moment = require('moment-timezone');
const devTime = require('dev-time');
const logSymbols = require('log-symbols');
const chalk = require('chalk');
const elegantSpinner = require('elegant-spinner');
const logUpdate = require('log-update');

const cli = meow(`
	Usage
	  $ dev-time <user> <user2> ...

	Options
	  -v, --verbose  Show UTC offset.
	  --format       The moment format of the output. [Default: HH:mm - D MMM. YYYY]
	  --token        The GitHub authentication token.

	Examples
	  $ dev-time SamVerschueren
	  19:47 - 8 Dec. 2015

	  $ dev-time SamVerschueren sindresorhus
	  SamVerschueren
	    19:47 - 8 Dec. 2015
	  sindresorhus
	    18:47 - 8 Dec. 2015

	  $ dev-time SamVerschueren -v
	  19:47 - 8 Dec. 2015 - UTC+1

	  $ dev-time SamVerschueren --format DD-MM-YYYY
	  07-12-2015
`, {
	string: ['_'],
	boolean: ['verbose'],
	alias: {
		v: 'verbose'
	},
	default: {
		format: 'HH:mm - D MMM. YYYY'
	}
});

updateNotifier({pkg: cli.pkg}).notify();

if (cli.input.length === 0) {
	console.error('Provide a GitHub user');
	process.exit(1);
}

const result = {};
const frames = {};

cli.input.forEach(user => frames[user] = elegantSpinner());

function parseError(err) {
	if (/no contributions/.test(err.message)) {
		return `  ${logSymbols.error} ${chalk.red('error')} ${err.message}`;
	}

	return err.stack;
}

function render() {
	const output = [];

	cli.input.forEach(user => {
		if (cli.input.length === 1) {
			output.push(result[user]);
			return;
		}

		output.push(user);

		if (result[user]) {
			if (result[user] instanceof Error) {
				output.push(parseError(result[user]));
			} else {
				output.push(`  ${result[user]}`);
			}
		} else {
			output.push(`  ${chalk.gray.dim(frames[user]())}`);
		}
	});

	logUpdate(output.join('\n'));
}

if (cli.input.length > 1) {
	setInterval(render, 50);
}

Promise.all(cli.input.map(user =>
	devTime(user, cli.flags)
		.then(time => {
			const date = moment.utc(time).utcOffset(time);
			result[user] = date.format(cli.flags.format);

			if (cli.flags.verbose) {
				const sign = date.utcOffset() >= 0 ? '+' : '';
				result[user] += ` - UTC${sign}${date.utcOffset() / 60}`;
			}
		})
		.catch(err => result[user] = err)
)).then(() => {
	render();
	process.exit();
});
<commit_msg>friendly message when exceeding rate limit - fixes #8<commit_after>#!/usr/bin/env node
'use strict';
const updateNotifier = require('update-notifier');
const meow = require('meow');
const moment = require('moment-timezone');
const devTime = require('dev-time');
const logSymbols = require('log-symbols');
const chalk = require('chalk');
const elegantSpinner = require('elegant-spinner');
const logUpdate = require('log-update');

const cli = meow(`
	Usage
	  $ dev-time <user> <user2> ...

	Options
	  -v, --verbose  Show UTC offset.
	  --format       The moment format of the output. [Default: HH:mm - D MMM. YYYY]
	  --token        The GitHub authentication token.

	Examples
	  $ dev-time SamVerschueren
	  19:47 - 8 Dec. 2015

	  $ dev-time SamVerschueren sindresorhus
	  SamVerschueren
	    19:47 - 8 Dec. 2015
	  sindresorhus
	    18:47 - 8 Dec. 2015

	  $ dev-time SamVerschueren -v
	  19:47 - 8 Dec. 2015 - UTC+1

	  $ dev-time SamVerschueren --format DD-MM-YYYY
	  07-12-2015
`, {
	string: ['_'],
	boolean: ['verbose'],
	alias: {
		v: 'verbose'
	},
	default: {
		format: 'HH:mm - D MMM. YYYY'
	}
});

updateNotifier({pkg: cli.pkg}).notify();

if (cli.input.length === 0) {
	console.error('Provide a GitHub user');
	process.exit(1);
}

const result = {};
const frames = {};

cli.input.forEach(user => frames[user] = elegantSpinner());

function parseError(err) {
	if (/no contributions/.test(err.message) || /Rate limit exceeded/.test(err.message)) {
		return `  ${logSymbols.error} ${chalk.red('error')} ${err.message.toLowerCase()}`;
	}

	return err.stack;
}

function render() {
	const output = [];

	cli.input.forEach(user => {
		if (cli.input.length === 1) {
			output.push(result[user].stack ? parseError(result[user]) : result[user]);
			return;
		}

		output.push(user);

		if (result[user]) {
			if (result[user] instanceof Error) {
				output.push(parseError(result[user]));
			} else {
				output.push(`  ${result[user]}`);
			}
		} else {
			output.push(`  ${chalk.gray.dim(frames[user]())}`);
		}
	});

	logUpdate(output.join('\n'));
}

if (cli.input.length > 1) {
	setInterval(render, 50);
}

Promise.all(cli.input.map(user =>
	devTime(user, cli.flags)
		.then(time => {
			const date = moment.utc(time).utcOffset(time);
			result[user] = date.format(cli.flags.format);

			if (cli.flags.verbose) {
				const sign = date.utcOffset() >= 0 ? '+' : '';
				result[user] += ` - UTC${sign}${date.utcOffset() / 60}`;
			}
		})
		.catch(err => result[user] = err)
)).then(() => {
	render();
	process.exit();
});
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

var fs = require('fs');
var nopt = require('nopt');
var stdin = require('get-stdin');
var pkg = require('./package.json');
var Imagemin = require('./');

/**
 * Options
 */

var opts = nopt({
	help: Boolean,
	interlaced: Boolean,
	optimizationLevel: Number,
	progressive: Boolean,
	version: Boolean
}, {
	h: '--help',
	i: '--interlaced',
	l: '--optimizationLevel',
	p: '--progressive',
	v: '--version'
});

/**
 * Help screen
 */

function help() {
	console.log([
		'',
		'  ' + pkg.description,
		'',
		'  Usage',
		'    imagemin <file> <directory>',
		'    imagemin <file> > <output>',
		'    cat <file> | imagemin > <output>',
		'',
		'  Example',
		'    imagemin images/* build',
		'    imagemin foo.png > foo-optimized.png',
		'    cat foo.png | imagemin > foo-optimized.png',
		'',
		'  Options',
		'    -i, --interlaced                    Interlace gif for progressive rendering',
		'    -o, --optimizationLevel <number>    Select an optimization level between 0 and 7',
		'    -p, --progressive                   Lossless conversion to progressive'
	].join('\n'));
}

/**
 * Show help
 */

if (opts.help) {
	help();
	return;
}

/**
 * Show package version
 */

if (opts.version) {
	console.log(pkg.version);
	return;
}

/**
 * Check if path is a file
 *
 * @param {String} path
 * @api private
 */

function isFile(path) {
	if (/^[^\s]+\.\w*$/g.test(path)) {
		return true;
	}

	try {
		return fs.statSync(path).isFile();
	} catch (e) {
		return false;
	}
}

/**
 * Run
 *
 * @param {Array|Buffer|String} src
 * @param {String} dest
 * @api private
 */

function run(src, dest) {
	var imagemin = new Imagemin()
		.src(src)
		.use(Imagemin.gifsicle(opts))
		.use(Imagemin.jpegtran(opts))
		.use(Imagemin.optipng(opts))
		.use(Imagemin.pngquant(opts))
		.use(Imagemin.svgo());

	if (process.stdout.isTTY) {
		imagemin.dest(dest ? dest : 'build');
	}

	imagemin.run(function (err, files) {
		if (err) {
			console.error(err);
			process.exit(1);
		}

		if (!process.stdout.isTTY) {
			files.forEach(function (file) {
				process.stdout.write(file.contents);
			});
		}
	});
}

/**
 * Apply arguments
 */

if (process.stdin.isTTY) {
	var src = opts.argv.remain;
	var dest;

	if (!src.length) {
		help();
		return;
	}

	if (!isFile(src[src.length - 1])) {
		dest = src[src.length - 1];
		src.pop();
	}

	run(src, dest);
} else {
	stdin.buffer(run);
}
<commit_msg>Fix `optimizationLevel` shorthand<commit_after>#!/usr/bin/env node
'use strict';

var fs = require('fs');
var nopt = require('nopt');
var stdin = require('get-stdin');
var pkg = require('./package.json');
var Imagemin = require('./');

/**
 * Options
 */

var opts = nopt({
	help: Boolean,
	interlaced: Boolean,
	optimizationLevel: Number,
	progressive: Boolean,
	version: Boolean
}, {
	h: '--help',
	i: '--interlaced',
	o: '--optimizationLevel',
	p: '--progressive',
	v: '--version'
});

/**
 * Help screen
 */

function help() {
	console.log([
		'',
		'  ' + pkg.description,
		'',
		'  Usage',
		'    imagemin <file> <directory>',
		'    imagemin <file> > <output>',
		'    cat <file> | imagemin > <output>',
		'',
		'  Example',
		'    imagemin images/* build',
		'    imagemin foo.png > foo-optimized.png',
		'    cat foo.png | imagemin > foo-optimized.png',
		'',
		'  Options',
		'    -i, --interlaced                    Interlace gif for progressive rendering',
		'    -o, --optimizationLevel <number>    Select an optimization level between 0 and 7',
		'    -p, --progressive                   Lossless conversion to progressive'
	].join('\n'));
}

/**
 * Show help
 */

if (opts.help) {
	help();
	return;
}

/**
 * Show package version
 */

if (opts.version) {
	console.log(pkg.version);
	return;
}

/**
 * Check if path is a file
 *
 * @param {String} path
 * @api private
 */

function isFile(path) {
	if (/^[^\s]+\.\w*$/g.test(path)) {
		return true;
	}

	try {
		return fs.statSync(path).isFile();
	} catch (e) {
		return false;
	}
}

/**
 * Run
 *
 * @param {Array|Buffer|String} src
 * @param {String} dest
 * @api private
 */

function run(src, dest) {
	var imagemin = new Imagemin()
		.src(src)
		.use(Imagemin.gifsicle(opts))
		.use(Imagemin.jpegtran(opts))
		.use(Imagemin.optipng(opts))
		.use(Imagemin.pngquant(opts))
		.use(Imagemin.svgo());

	if (process.stdout.isTTY) {
		imagemin.dest(dest ? dest : 'build');
	}

	imagemin.run(function (err, files) {
		if (err) {
			console.error(err);
			process.exit(1);
		}

		if (!process.stdout.isTTY) {
			files.forEach(function (file) {
				process.stdout.write(file.contents);
			});
		}
	});
}

/**
 * Apply arguments
 */

if (process.stdin.isTTY) {
	var src = opts.argv.remain;
	var dest;

	if (!src.length) {
		help();
		return;
	}

	if (!isFile(src[src.length - 1])) {
		dest = src[src.length - 1];
		src.pop();
	}

	run(src, dest);
} else {
	stdin.buffer(run);
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

var args = require('minimist')(process.argv.slice(2))
var pump = require('pump')
/*
  cat stacks.out | perf-sym <pid>

  --relative=[path] -r=[path] [false]
  --keep-addr -k [false]
 */

if (!args._[0]) {
  console.error('Provide PID of the process when the stacks were captured')
  process.exit(1)
}

var stream = require('./')(Object.assign(args, {
  pid: args._[0]
}))

console.log(stream)

pump(process.stdin, stream, process.stdout)<commit_msg>bug fix<commit_after>#!/usr/bin/env node

var args = require('minimist')(process.argv.slice(2))
var pump = require('pump')
/*
  cat stacks.out | perf-sym <pid>

  --relative=[path] -r=[path] [false]
  --keep-addr -k [false]
 */

if (!args._[0]) {
  console.error('Provide PID of the process when the stacks were captured')
  process.exit(1)
}

var stream = require('./')(Object.assign(args, {
  pid: args._[0]
}))

pump(process.stdin, stream, process.stdout)<|endoftext|>