<commit_before>'use strict';

const path = require('path');
const fs = require('fs');
const child = require('child_process');
const Conf = require('conf');
const inquirer = require('inquirer');
const env = require('yeoman-environment').createEnv();
const chalk = require('chalk');
const figures = require('figures');
const minimist = require('minimist');
const updateNotifier = require('update-notifier');
const asciiLogo = require('@ngx-rocket/ascii-logo');
const pkg = require('./package.json');

const isWin = /^win/.test(process.platform);
const addonKey = 'ngx-rocket-addon';
const disabledAddons = 'disabled-addons';
const appName = path.basename(process.argv[1]);
const help = `${chalk.bold(`Usage:`)} ${appName} ${chalk.blue(`[new|update|config|list|<script>]`)} [options]\n`;
const detailedHelp = `
${chalk.blue('n, new')} [name]
  Creates a new app.
  -a, --addon                 Creates an add-on instead.
  --packageManager <yarn|npm> Uses specified package manager.
  --automate <json_file>      Automate prompt answers using JSON file.

${chalk.blue('u, update')}
  Updates an existing app or add-on.

${chalk.blue('c, config')}
  Configures add-ons to use for new apps.
  All available add-ons are used by default.

${chalk.blue('l, list')}
  Lists available add-ons.
  -n, --npm    Show installable add-ons on NPM

${chalk.blue('<script>')}
  Runs specified script from your ${chalk.bold(`package.json`)}.
  Works just like ${chalk.bold(`npm run <script>`)}
`;

class NgxCli {
  constructor(args) {
    this._args = args;
    this._options = minimist(args, {
      boolean: ['help', 'npm', 'addon', 'packageManager'],
      alias: {
        n: 'npm',
        a: 'addon'
      }
    });
    this._config = new Conf({
      defaults: {
        disabledAddons: {}
      }
    });

    env.register(require.resolve('generator-ngx-rocket'), 'ngx-rocket');
    env.register(require.resolve('generator-ngx-rocket-addon'), 'ngx-rocket-addon');
  }

  run() {
    updateNotifier({pkg}).notify();

    if (this._options.help) {
      return this._help(true);
    }
    switch (this._args[0]) {
      case 'n':
      case 'new':
        return this.generate(false, this._args.slice(1), this._options.addon);
      case 'u':
      case 'update':
        return this.generate(true, this._args.slice(1), this._options.addon);
      case 'c':
      case 'config':
        return this.configure();
      case 'l':
      case 'list':
        return this.list(this._options.npm);
      default:
        this.runScript(this._args);
    }
  }

  runScript(args) {
    const name = args[0];
    const packageFile = this._findPackageJson(process.cwd());
    const packageManager = this._packageManager();
    const projectPackage = packageFile ? require(packageFile) : null;
    if (!projectPackage) {
      this._help();
    }

    let scriptName = name;
    if (!projectPackage.scripts[name]) {
      const matches = this._findMatches(name, Object.keys(projectPackage.scripts));
      if (!matches) {
        this._help();
      }
      scriptName = matches[0];
      if (matches.length > 1) {
        console.warn(chalk.yellow(`Warning, multiple matching scripts. Try to be more specific.`));
      }
    }

    child.spawnSync(
      packageManager,
      ['run', scriptName].concat(packageManager === 'npm' ? ['--'] : [], args.splice(1)),
      {
        stdio: 'inherit',
        shell: isWin
      }
    );
  }

  generate(update, args, addon) {
    if (!update) {
      console.log(asciiLogo(pkg.version));
    } else if (fs.existsSync('.yo-rc.json')) {
      const rc = JSON.parse(fs.readFileSync('.yo-rc.json'));
      addon = Boolean(rc['generator-ngx-rocket-addon']);
    } else {
      this._exit(`No existing app found, use ${chalk.blue('ngx new')} instead`);
    }
    if (addon) {
      args = args.filter(arg => arg !== '--addon' && arg !== '-a');
      env.lookup(() => env.run(['ngx-rocket-addon'].concat(args), {
        update,
        packageManager: this._packageManager(),
        'skip-welcome': true,
      }));
    } else {
      const disabled = this._config.get(disabledAddons);
      return this._findAddons()
        .then(addons => addons.filter(addon => !disabled[addon]))
        .then(addons => {
          return new Promise(resolve => env.lookup(() => env.run(['ngx-rocket'].concat(args), {
            update,
            packageManager: this._packageManager(),
            addons: addons.join(' '),
            'skip-welcome': true
          }, resolve)));
        })
        .then(() => console.log());
    }
  }

  configure() {
    this._findAddons().then(addons => {
      const disabled = this._config.get(disabledAddons);
      inquirer
        .prompt({
          type: 'checkbox',
          name: 'addons',
          message: 'Choose add-ons to use for new apps',
          choices: addons.map(addon => ({
            name: addon,
            checked: !disabled[addon]
          }))
        })
        .then(answers => {
          this._config.set(disabledAddons, addons
            .filter(addon => !answers.addons.includes(addon))
            .reduce((r, addon) => {
              r[addon] = true;
              return r;
            }, {}));
          console.log('Configuration saved.');
        });
    });
  }

  list(npm) {
    let promise;
    if (npm) {
      promise = Promise
        .resolve(child.execSync(`npm search ${addonKey} --json`, {stdio: [0, null, 2]}))
        .then(addons => addons ? JSON.parse(addons) : [])
        .then(addons => addons.filter(addon => addon.name !== 'generator-ngx-rocket-addon'));
    } else {
      promise = this._findAddons();
    }
    promise.then(addons => {
      const disabled = this._config.get(disabledAddons);
      console.log(chalk.blue(`Available add-ons${npm ? ' on NPM' : ''}:`));

      if (!addons.length) {
        console.log('  No add-ons found.');
      } else if (npm) {
        addons.forEach(addon => console.log(`  ${addon.name}@${addon.version} - ${addon.description}`));
      } else {
        addons.forEach(addon => console.log(`${chalk.green(disabled[addon] ? ' ' : figures.tick)} ${addon}`));
      }
    });
  }

  _findAddons() {
    return new Promise(resolve => {
      env.lookup(() => {
        const generators = env.getGeneratorsMeta();
        const addons = Object.keys(generators)
          .map(alias => generators[alias])
          .filter(generator => {
            const packagePath = this._findPackageJson(generator.resolved);
            const keywords = require(packagePath).keywords || [];
            return keywords.includes(addonKey);
          })
          .map(generator => generator.namespace.replace(/(.*?):app$/, '$1'));
        resolve(addons);
      });
    });
  }

  _findPackageJson(basePath) {
    const find = components => {
      if (!components.length) {
        return null;
      }
      const dir = path.join.apply(path, components);
      const packageFile = path.join(dir, 'package.json');
      return fs.existsSync(packageFile) ? packageFile : find(components.slice(0, -1));
    };

    const components = basePath.split(/[/\\]/);
    if (components.length && !components[0].length) {
      // When path starts with a slash, the first path component is empty string
      components[0] = path.sep;
    }
    return find(components);
  }

  _packageManager() {
    if (this._options.packageManager) {
      return this._options.packageManager === 'yarn' ? 'yarn' : 'npm';
    }
    let pm = null;
    try {
      const rc = require(path.join(process.cwd(), '.yo-rc.json'));
      pm = rc[generator].props.packageManager;
    } catch (err) {
      // Do nothing
    }
    return pm || process.env.NGX_PACKAGE_MANAGER || 'npm';
  }

  _help(details) {
    console.log(asciiLogo(pkg.version));
    this._exit(help + (details ? detailedHelp : `Use ${chalk.white(`--help`)} for more info.\n`));
  }

  _findMatches(search, strings) {
    const matches = [];
    for (const s of strings) {
      if (s.startsWith(search)) {
        matches.push(s);
      }
    }
    return matches.length > 0 ? matches : null;
  }

  _exit(error, code = 1) {
    console.error(error);
    process.exit(code);
  }
}

module.exports = NgxCli;
<commit_msg>Fixed lint errors<commit_after>'use strict';

const path = require('path');
const fs = require('fs');
const child = require('child_process');
const Conf = require('conf');
const inquirer = require('inquirer');
const env = require('yeoman-environment').createEnv();
const chalk = require('chalk');
const figures = require('figures');
const minimist = require('minimist');
const updateNotifier = require('update-notifier');
const asciiLogo = require('@ngx-rocket/ascii-logo');
const pkg = require('./package.json');

const isWin = /^win/.test(process.platform);
const addonKey = 'ngx-rocket-addon';
const disabledAddons = 'disabled-addons';
const appName = path.basename(process.argv[1]);
const help = `${chalk.bold(`Usage:`)} ${appName} ${chalk.blue(`[new|update|config|list|<script>]`)} [options]\n`;
const detailedHelp = `
${chalk.blue('n, new')} [name]
  Creates a new app.
  -a, --addon                 Creates an add-on instead.
  --packageManager <yarn|npm> Uses specified package manager.
  --automate <json_file>      Automate prompt answers using JSON file.

${chalk.blue('u, update')}
  Updates an existing app or add-on.

${chalk.blue('c, config')}
  Configures add-ons to use for new apps.
  All available add-ons are used by default.

${chalk.blue('l, list')}
  Lists available add-ons.
  -n, --npm    Show installable add-ons on NPM

${chalk.blue('<script>')}
  Runs specified script from your ${chalk.bold(`package.json`)}.
  Works just like ${chalk.bold(`npm run <script>`)}
`;

class NgxCli {
  constructor(args) {
    this._args = args;
    this._options = minimist(args, {
      boolean: ['help', 'npm', 'addon', 'packageManager'],
      alias: {
        n: 'npm',
        a: 'addon'
      }
    });
    this._config = new Conf({
      defaults: {
        disabledAddons: {}
      }
    });

    env.register(require.resolve('generator-ngx-rocket'), 'ngx-rocket');
    env.register(require.resolve('generator-ngx-rocket-addon'), 'ngx-rocket-addon');
  }

  run() {
    updateNotifier({pkg}).notify();

    if (this._options.help) {
      return this._help(true);
    }
    switch (this._args[0]) {
      case 'n':
      case 'new':
        return this.generate(false, this._args.slice(1), this._options.addon);
      case 'u':
      case 'update':
        return this.generate(true, this._args.slice(1), this._options.addon);
      case 'c':
      case 'config':
        return this.configure();
      case 'l':
      case 'list':
        return this.list(this._options.npm);
      default:
        this.runScript(this._args);
    }
  }

  runScript(args) {
    const name = args[0];
    const packageFile = this._findPackageJson(process.cwd());
    const packageManager = this._packageManager();
    const projectPackage = packageFile ? require(packageFile) : null;
    if (!projectPackage) {
      this._help();
    }

    let scriptName = name;
    if (!projectPackage.scripts[name]) {
      const matches = this._findMatches(name, Object.keys(projectPackage.scripts));
      if (!matches) {
        this._help();
      }
      scriptName = matches[0];
      if (matches.length > 1) {
        console.warn(chalk.yellow(`Warning, multiple matching scripts. Try to be more specific.`));
      }
    }

    child.spawnSync(
      packageManager,
      ['run', scriptName].concat(packageManager === 'npm' ? ['--'] : [], args.splice(1)),
      {
        stdio: 'inherit',
        shell: isWin
      }
    );
  }

  generate(update, args, addon) {
    if (!update) {
      console.log(asciiLogo(pkg.version));
    } else if (fs.existsSync('.yo-rc.json')) {
      const rc = JSON.parse(fs.readFileSync('.yo-rc.json'));
      addon = Boolean(rc['generator-ngx-rocket-addon']);
    } else {
      this._exit(`No existing app found, use ${chalk.blue('ngx new')} instead`);
    }
    if (addon) {
      args = args.filter(arg => arg !== '--addon' && arg !== '-a');
      env.lookup(() => env.run(['ngx-rocket-addon'].concat(args), {
        update,
        packageManager: this._packageManager(),
        'skip-welcome': true
      }));
    } else {
      const disabled = this._config.get(disabledAddons);
      return this._findAddons()
        .then(addons => addons.filter(addon => !disabled[addon]))
        .then(addons => {
          return new Promise(resolve => env.lookup(() => env.run(['ngx-rocket'].concat(args), {
            update,
            packageManager: this._packageManager(),
            addons: addons.join(' '),
            'skip-welcome': true
          }, resolve)));
        })
        .then(() => console.log());
    }
  }

  configure() {
    this._findAddons().then(addons => {
      const disabled = this._config.get(disabledAddons);
      inquirer
        .prompt({
          type: 'checkbox',
          name: 'addons',
          message: 'Choose add-ons to use for new apps',
          choices: addons.map(addon => ({
            name: addon,
            checked: !disabled[addon]
          }))
        })
        .then(answers => {
          this._config.set(disabledAddons, addons
            .filter(addon => !answers.addons.includes(addon))
            .reduce((r, addon) => {
              r[addon] = true;
              return r;
            }, {}));
          console.log('Configuration saved.');
        });
    });
  }

  list(npm) {
    let promise;
    if (npm) {
      promise = Promise
        .resolve(child.execSync(`npm search ${addonKey} --json`, {stdio: [0, null, 2]}))
        .then(addons => addons ? JSON.parse(addons) : [])
        .then(addons => addons.filter(addon => addon.name !== 'generator-ngx-rocket-addon'));
    } else {
      promise = this._findAddons();
    }
    promise.then(addons => {
      const disabled = this._config.get(disabledAddons);
      console.log(chalk.blue(`Available add-ons${npm ? ' on NPM' : ''}:`));

      if (!addons.length) {
        console.log('  No add-ons found.');
      } else if (npm) {
        addons.forEach(addon => console.log(`  ${addon.name}@${addon.version} - ${addon.description}`));
      } else {
        addons.forEach(addon => console.log(`${chalk.green(disabled[addon] ? ' ' : figures.tick)} ${addon}`));
      }
    });
  }

  _findAddons() {
    return new Promise(resolve => {
      env.lookup(() => {
        const generators = env.getGeneratorsMeta();
        const addons = Object.keys(generators)
          .map(alias => generators[alias])
          .filter(generator => {
            const packagePath = this._findPackageJson(generator.resolved);
            const keywords = require(packagePath).keywords || [];
            return keywords.includes(addonKey);
          })
          .map(generator => generator.namespace.replace(/(.*?):app$/, '$1'));
        resolve(addons);
      });
    });
  }

  _findPackageJson(basePath) {
    const find = components => {
      if (!components.length) {
        return null;
      }
      const dir = path.join.apply(path, components);
      const packageFile = path.join(dir, 'package.json');
      return fs.existsSync(packageFile) ? packageFile : find(components.slice(0, -1));
    };

    const components = basePath.split(/[/\\]/);
    if (components.length && !components[0].length) {
      // When path starts with a slash, the first path component is empty string
      components[0] = path.sep;
    }
    return find(components);
  }

  _packageManager() {
    if (this._options.packageManager) {
      return this._options.packageManager === 'yarn' ? 'yarn' : 'npm';
    }
    let pm = null;
    try {
      const rc = require(path.join(process.cwd(), '.yo-rc.json'));
      pm = rc['generator-ngx-rocket'].props.packageManager;
    } catch (err) {
      // Do nothing
    }
    return pm || process.env.NGX_PACKAGE_MANAGER || 'npm';
  }

  _help(details) {
    console.log(asciiLogo(pkg.version));
    this._exit(help + (details ? detailedHelp : `Use ${chalk.white(`--help`)} for more info.\n`));
  }

  _findMatches(search, strings) {
    const matches = [];
    for (const s of strings) {
      if (s.startsWith(search)) {
        matches.push(s);
      }
    }
    return matches.length > 0 ? matches : null;
  }

  _exit(error, code = 1) {
    console.error(error);
    process.exit(code);
  }
}

module.exports = NgxCli;
<|endoftext|>


<commit_before>'use strict';

var React = require('react');
var colorParser = require('csscolorparser').parseCSSColor;
var extend = require('xtend');

var XYControl = require('./src/xy');

var { rgbaColor, rgb2hsv, rgb2hex, hsv2hex,
    hsv2rgb, colorCoords, colorCoordValue } = require('./src/colorfunc');

var isRGBMode = (c) => (c === 'r' || c === 'g' || c === 'b');
var isHSVMode = (c) => (c === 'h' || c === 's' || c === 'v');

module.exports = React.createClass({
  propTypes: {
    onChange: React.PropTypes.func.isRequired,
    colorAttribute: React.PropTypes.string,
    mode: React.PropTypes.string,
    value: React.PropTypes.string,
    reset: React.PropTypes.bool
  },

  getInitialState: function() {
    var { value, reset, mode, colorAttribute } = this.props;
    var color = value ? value : '#3887be';
    this.original = color;

    return {
      color: this.getColor(color),
      reset: (typeof reset !== 'undefined') ? reset : true,
      mode: (typeof mode !== 'undefined') ? mode : 'rgb',
      colorAttribute: (typeof colorAttribute !== 'undefined') ? colorAttribute : 'h'
    };
  },

  emitOnChange: function(change) {
    var { color, mode, colorAttribute } = this.state;
    this.props.onChange(extend(
      color,
      { mode: mode },
      { colorAttribute: colorAttribute },
      change
    ));
  },

  changeHSV: function(p, val) {
    var { color } = this.state;
    var j = p;
    if (typeof j === 'string') {
      j = {};
      j[p] = Math.floor(parseInt(val.target.value || 0, 10));
    }
    var rgb = hsv2rgb(j.h || color.h, j.s || color.s, j.v || color.v);
    var hex = rgb2hex(rgb.r, rgb.g, rgb.b);

    color = extend(color, j, rgb, {hex: hex});

    this.setState({ color: color });
    this.emitOnChange(color);
  },

  changeRGB: function(p, val) {
    var { color } = this.state;
    var j = p;
    if (typeof j === 'string') {
      j = {};
      j[p] = Math.floor(parseInt(val.target.value || 0, 10));
    }

    var hsv = rgb2hsv(j.r || color.r, j.g || color.g, j.b || color.b);

    color = extend(color, j, hsv, {
      hex: rgb2hex(j.r || color.r, j.g || color.g, j.b || color.b)
    });

    this.setState({ color: color });
    this.emitOnChange(color);
  },

  changeAlpha: function(e) {
    var value = e.target.value || '0';
    if (value && typeof value === 'string') {
      var a = Math.floor(parseFloat(value));
      var color = extend(this.state.color, { a: a / 100 });
      this.setState({ color: color });
      this.emitOnChange(color);
    }
  },

  changeHEX: function(e) {
    var hex = '#' + e.target.value.trim();
    var rgba = colorParser(hex);

    var color = this.getColor(hex) || this.state.color;

    if (rgba) {
      this.setState({ color: color });
    } else {
      this.setState({ color: extend(color, {hex: e.target.value.trim()}) });
    }

    this.emitOnChange();
  },

  reset: function(e) {
    var obj = this.getColor(this.original);
    this.setState({ color: obj });
    this.emitOnChange(obj);
  },

  getColor: function(cssColor) {
    var rgba = colorParser(cssColor);
    if(rgba) {
      var r = rgba[0],
        g = rgba[1],
        b = rgba[2],
        a = rgba[3];

      var hsv = rgb2hsv(r, g, b);
      var hex = rgb2hex(r, g, b);

      // Convert to shorthand hex is applicable
      if (hex[0] === hex[1] &&
          hex[2] === hex[3] &&
          hex[4] === hex[5]) {
        hex = [hex[0], hex[2], hex[4]].join('');
      }

      return extend(hsv, {
        r: r,
        g: g,
        b: b,
        a: a,
        hex: hex
      });
    }
    else {
      return null;
    }
  },

  _onXYChange: function(mode, pos) {
    var color = colorCoordValue(mode, pos);
    if (isRGBMode(mode)) this.changeRGB(color);
    if (isHSVMode(mode)) this.changeHSV(color);
  },

  _onColorSliderChange: function(mode, e) {
    var color = {};
    color[mode] = parseFloat(e.target.value);
    if (isRGBMode(mode)) this.changeRGB(color);
    if (isHSVMode(mode)) this.changeHSV(color);
  },

  _onAlphaSliderChange: function(e) {
    this.changeHSV({
      a: Math.floor(parseFloat(e.target.value)) / 100
    });
  },

  setMode: function(e) {
    var obj = { mode: e.target.value };
    this.setState(obj);
    this.emitOnChange(obj);
  },

  setColorAttribute: function(attribute) {
    var obj = { colorAttribute: attribute };
    this.setState(obj);
    this.emitOnChange(obj);
  },

  render: function () {
    var { colorAttribute, color } = this.state;
    var { r, g, b, h, s, v, hex } = color;

    var a = Math.round(color.a * 100);

    var colorAttributeValue = color[colorAttribute];

    var colorAttributeMax;
    if (isRGBMode(colorAttribute)) {
      colorAttributeMax = 255;
    } else if (colorAttribute === 'h') {
      colorAttributeMax = 359;
    } else {
      colorAttributeMax = 100;
    }

    var rgbaBackground = rgbaColor(r, g, b, a);
    var opacityGradient = 'linear-gradient(to right, ' +
      rgbaColor(r, g, b, 0) + ', ' +
      rgbaColor(r, g, b, 100) + ')';

    var hueBackground = '#' + hsv2hex(h, 100, 100);
    var coords = colorCoords(colorAttribute, color);

    var opacity = Math.round((coords.y / coords.ymax) * 100);

    // Slider background color for saturation & value.
    var hueSlide = {};
    if (colorAttribute === 'v') {
      hueSlide.background = 'linear-gradient(to left, ' + hueBackground + ' 0%, #000 100%)';
    } else if (colorAttribute === 's') {
      hueSlide.background = 'linear-gradient(to left, ' + hueBackground + ' 0%, #bbb 100%)';
    }

    // Opacity between colorspaces in RGB & SV
    var opacityHigh = {}, opacityLow = {};
    if (['r', 'g', 'b'].indexOf(colorAttribute) >= 0) {
      opacityHigh.opacity = Math.round((color[colorAttribute] / 255) * 100) / 100;
      opacityLow.opacity = Math.round(100 - ((color[colorAttribute] / 255) * 100)) / 100;
    } else if (['s', 'v'].indexOf(colorAttribute) >= 0) {
      opacityHigh.opacity = Math.round((color[colorAttribute] / 100) * 100) / 100;
      opacityLow.opacity = Math.round(100 - ((color[colorAttribute] / 100) * 100)) / 100;
    }

    // Determines display color of the XY control handle.
    var isdark = ((r * 0.299) + (g * 0.587) + (b * 0.114) > 186 || a < 0.50) ? '' : 'dark';

    return (

              {colorAttribute === 'r' &&

              }
              {colorAttribute === 'g' &&

              }
              {colorAttribute === 'b' &&

              }
              {colorAttribute === 'h' &&

              }
              {colorAttribute === 's' &&

              }
              {colorAttribute === 'v' &&

              }

              <XYControl
                className='cp-slider-xy'
                x={coords.x}
                y={coords.y}
                xmax={coords.xmax}
                ymax={coords.ymax}
                handleClass={isdark}
                onChange={this._onXYChange.bind(null, colorAttribute)} />

            <div className={`cp-colormode-slider cp-colormode-attribute-slider ${colorAttribute}`}>
              <input
                value={colorAttributeValue}
                style={hueSlide}
                onChange={this._onColorSliderChange.bind(null, colorAttribute)}
                className='cp-colormode-slider-input'
                type='range'
                min={0}
                max={colorAttributeMax} />

              <button
                onClick={this.setMode}
                className={`cp-mode-rgb ${this.state.mode === 'rgb' ? 'cp-active' : ''}`}
                value='rgb'>RGB
              </button>
              <button
                className={`cp-mode-hsv ${this.state.mode === 'hsv' ? 'cp-active' : ''}`}
                onClick={this.setMode}
                value='hsv'>HSV
              </button>

              {this.state.mode === 'rgb' ? (

                <fieldset className={colorAttribute === 'r' ? 'cp-active' : ''}>
                  R
                  <input
                    value={r}
                    onFocus={this.setColorAttribute.bind(null, 'r')}
                    onChange={this.changeRGB.bind(null, 'r')}
                    className='rgb-attribute-r'
                    type='number'
                    min={0}
                    max={255}
                    step={1} />
                </fieldset>
                <fieldset className={colorAttribute === 'g' ? 'cp-active' : ''}>
                  G
                  <input
                    value={g}
                    onFocus={this.setColorAttribute.bind(null, 'g')}
                    onChange={this.changeRGB.bind(null, 'g')}
                    className='rgb-attribute-g'
                    type='number'
                    min={0}
                    max={255}
                    step={1} />
                </fieldset>
                <fieldset className={colorAttribute === 'b' ? 'cp-active' : ''}>
                  B
                  <input
                    value={b}
                    onFocus={this.setColorAttribute.bind(null, 'b')}
                    onChange={this.changeRGB.bind(null, 'b')}
                    className='rgb-attribute-b'
                    type='number'
                    min={0}
                    max={255}
                    step={1} />
                </fieldset>

              ) : (

                <fieldset className={colorAttribute === 'h' ? 'cp-active' : ''}>
                  H
                  <input
                    value={h}
                    onFocus={this.setColorAttribute.bind(null, 'h')}
                    onChange={this.changeHSV.bind(null, 'h')}
                    className='hsv-attribute-h'
                    type='number'
                    min={0}
                    max={359}
                    step={1} />
                </fieldset>
                <fieldset className={colorAttribute === 's' ? 'cp-active' : ''}>
                  S
                  <input
                    value={s}
                    onFocus={this.setColorAttribute.bind(null, 's')}
                    onChange={this.changeHSV.bind(null, 's')}
                    className='hsv-attribute-s'
                    type='number'
                    min={0}
                    max={100}
                    step={1} />
                </fieldset>
                <fieldset className={colorAttribute === 'v' ? 'cp-active' : ''}>
                  V
                  <input
                    value={v}
                    onFocus={this.setColorAttribute.bind(null, 'v')}
                    onChange={this.changeHSV.bind(null, 'v')}
                    className='hsv-attribute-v'
                    type='number'
                    min={0}
                    max={100}
                    step={1} />
                </fieldset>

              )}

              <fieldset>
                {String.fromCharCode(945)}
                <input
                  value={a}
                  onChange={this.changeAlpha}
                  type='number'
                  min={0}
                  max={100}
                  step={1} />
              </fieldset>

            <fieldset className='cp-fill-tile'>
              <input
                className='cp-alpha-slider-input'
                value={a}
                onChange={this._onAlphaSliderChange}
                style={{background: opacityGradient}}
                type='range'
                min={0}
                max={100} />
            </fieldset>

            {this.state.reset &&
              <button
                className='cp-swatch cp-swatch-reset'
                title='Reset color'
                style={{backgroundColor: this.original}}
                onClick={this.reset}>
              </button>
            }

            <fieldset className='cp-hex cp-fr'>
              #
              <input
                value={hex}
                className='cp-hex-input'
                onChange={this.changeHEX}
                type='text' />
            </fieldset>

    );
  }
});
<commit_msg>Use consistent import style, simpler undefined test<commit_after>'use strict';

var React = require('react');
var { parseCSSColor } = require('csscolorparser');
var extend = require('xtend');

var XYControl = require('./src/xy');

var { rgbaColor, rgb2hsv, rgb2hex, hsv2hex,
    hsv2rgb, colorCoords, colorCoordValue } = require('./src/colorfunc');

var isRGBMode = (c) => (c === 'r' || c === 'g' || c === 'b');
var isHSVMode = (c) => (c === 'h' || c === 's' || c === 'v');

module.exports = React.createClass({
  propTypes: {
    onChange: React.PropTypes.func.isRequired,
    colorAttribute: React.PropTypes.string,
    mode: React.PropTypes.string,
    value: React.PropTypes.string,
    reset: React.PropTypes.bool
  },

  getInitialState: function() {
    var { value, reset, mode, colorAttribute } = this.props;
    var color = value ? value : '#3887be';
    this.original = color;

    return {
      color: this.getColor(color),
      reset: reset !== undefined ? reset : true,
      mode: mode !== undefined ? mode : 'rgb',
      colorAttribute: colorAttribute !== undefined ? colorAttribute : 'h'
    };
  },

  emitOnChange: function(change) {
    var { color, mode, colorAttribute } = this.state;
    this.props.onChange(extend(
      color,
      { mode: mode },
      { colorAttribute: colorAttribute },
      change
    ));
  },

  changeHSV: function(p, val) {
    var { color } = this.state;
    var j = p;
    if (typeof j === 'string') {
      j = {};
      j[p] = Math.floor(parseInt(val.target.value || 0, 10));
    }
    var rgb = hsv2rgb(j.h || color.h, j.s || color.s, j.v || color.v);
    var hex = rgb2hex(rgb.r, rgb.g, rgb.b);

    color = extend(color, j, rgb, {hex: hex});

    this.setState({ color: color });
    this.emitOnChange(color);
  },

  changeRGB: function(p, val) {
    var { color } = this.state;
    var j = p;
    if (typeof j === 'string') {
      j = {};
      j[p] = Math.floor(parseInt(val.target.value || 0, 10));
    }

    var hsv = rgb2hsv(j.r || color.r, j.g || color.g, j.b || color.b);

    color = extend(color, j, hsv, {
      hex: rgb2hex(j.r || color.r, j.g || color.g, j.b || color.b)
    });

    this.setState({ color: color });
    this.emitOnChange(color);
  },

  changeAlpha: function(e) {
    var value = e.target.value || '0';
    if (value && typeof value === 'string') {
      var a = Math.floor(parseFloat(value));
      var color = extend(this.state.color, { a: a / 100 });
      this.setState({ color: color });
      this.emitOnChange(color);
    }
  },

  changeHEX: function(e) {
    var hex = '#' + e.target.value.trim();
    var rgba = parseCSSColor(hex);

    var color = this.getColor(hex) || this.state.color;

    if (rgba) {
      this.setState({ color: color });
    } else {
      this.setState({ color: extend(color, {hex: e.target.value.trim()}) });
    }

    this.emitOnChange();
  },

  reset: function(e) {
    var obj = this.getColor(this.original);
    this.setState({ color: obj });
    this.emitOnChange(obj);
  },

  getColor: function(cssColor) {
    var rgba = parseCSSColor(cssColor);
    if(rgba) {
      var r = rgba[0],
        g = rgba[1],
        b = rgba[2],
        a = rgba[3];

      var hsv = rgb2hsv(r, g, b);
      var hex = rgb2hex(r, g, b);

      // Convert to shorthand hex is applicable
      if (hex[0] === hex[1] &&
          hex[2] === hex[3] &&
          hex[4] === hex[5]) {
        hex = [hex[0], hex[2], hex[4]].join('');
      }

      return extend(hsv, {
        r: r,
        g: g,
        b: b,
        a: a,
        hex: hex
      });
    }
    else {
      return null;
    }
  },

  _onXYChange: function(mode, pos) {
    var color = colorCoordValue(mode, pos);
    if (isRGBMode(mode)) this.changeRGB(color);
    if (isHSVMode(mode)) this.changeHSV(color);
  },

  _onColorSliderChange: function(mode, e) {
    var color = {};
    color[mode] = parseFloat(e.target.value);
    if (isRGBMode(mode)) this.changeRGB(color);
    if (isHSVMode(mode)) this.changeHSV(color);
  },

  _onAlphaSliderChange: function(e) {
    this.changeHSV({
      a: Math.floor(parseFloat(e.target.value)) / 100
    });
  },

  setMode: function(e) {
    var obj = { mode: e.target.value };
    this.setState(obj);
    this.emitOnChange(obj);
  },

  setColorAttribute: function(attribute) {
    var obj = { colorAttribute: attribute };
    this.setState(obj);
    this.emitOnChange(obj);
  },

  render: function () {
    var { colorAttribute, color } = this.state;
    var { r, g, b, h, s, v, hex } = color;

    var a = Math.round(color.a * 100);

    var colorAttributeValue = color[colorAttribute];

    var colorAttributeMax;
    if (isRGBMode(colorAttribute)) {
      colorAttributeMax = 255;
    } else if (colorAttribute === 'h') {
      colorAttributeMax = 359;
    } else {
      colorAttributeMax = 100;
    }

    var rgbaBackground = rgbaColor(r, g, b, a);
    var opacityGradient = 'linear-gradient(to right, ' +
      rgbaColor(r, g, b, 0) + ', ' +
      rgbaColor(r, g, b, 100) + ')';

    var hueBackground = '#' + hsv2hex(h, 100, 100);
    var coords = colorCoords(colorAttribute, color);

    var opacity = Math.round((coords.y / coords.ymax) * 100);

    // Slider background color for saturation & value.
    var hueSlide = {};
    if (colorAttribute === 'v') {
      hueSlide.background = 'linear-gradient(to left, ' + hueBackground + ' 0%, #000 100%)';
    } else if (colorAttribute === 's') {
      hueSlide.background = 'linear-gradient(to left, ' + hueBackground + ' 0%, #bbb 100%)';
    }

    // Opacity between colorspaces in RGB & SV
    var opacityHigh = {}, opacityLow = {};
    if (['r', 'g', 'b'].indexOf(colorAttribute) >= 0) {
      opacityHigh.opacity = Math.round((color[colorAttribute] / 255) * 100) / 100;
      opacityLow.opacity = Math.round(100 - ((color[colorAttribute] / 255) * 100)) / 100;
    } else if (['s', 'v'].indexOf(colorAttribute) >= 0) {
      opacityHigh.opacity = Math.round((color[colorAttribute] / 100) * 100) / 100;
      opacityLow.opacity = Math.round(100 - ((color[colorAttribute] / 100) * 100)) / 100;
    }

    // Determines display color of the XY control handle.
    var isdark = ((r * 0.299) + (g * 0.587) + (b * 0.114) > 186 || a < 0.50) ? '' : 'dark';

    return (

              {colorAttribute === 'r' &&

              }
              {colorAttribute === 'g' &&

              }
              {colorAttribute === 'b' &&

              }
              {colorAttribute === 'h' &&

              }
              {colorAttribute === 's' &&

              }
              {colorAttribute === 'v' &&

              }

              <XYControl
                className='cp-slider-xy'
                x={coords.x}
                y={coords.y}
                xmax={coords.xmax}
                ymax={coords.ymax}
                handleClass={isdark}
                onChange={this._onXYChange.bind(null, colorAttribute)} />

            <div className={`cp-colormode-slider cp-colormode-attribute-slider ${colorAttribute}`}>
              <input
                value={colorAttributeValue}
                style={hueSlide}
                onChange={this._onColorSliderChange.bind(null, colorAttribute)}
                className='cp-colormode-slider-input'
                type='range'
                min={0}
                max={colorAttributeMax} />

              <button
                onClick={this.setMode}
                className={`cp-mode-rgb ${this.state.mode === 'rgb' ? 'cp-active' : ''}`}
                value='rgb'>RGB
              </button>
              <button
                className={`cp-mode-hsv ${this.state.mode === 'hsv' ? 'cp-active' : ''}`}
                onClick={this.setMode}
                value='hsv'>HSV
              </button>

              {this.state.mode === 'rgb' ? (

                <fieldset className={colorAttribute === 'r' ? 'cp-active' : ''}>
                  R
                  <input
                    value={r}
                    onFocus={this.setColorAttribute.bind(null, 'r')}
                    onChange={this.changeRGB.bind(null, 'r')}
                    className='rgb-attribute-r'
                    type='number'
                    min={0}
                    max={255}
                    step={1} />
                </fieldset>
                <fieldset className={colorAttribute === 'g' ? 'cp-active' : ''}>
                  G
                  <input
                    value={g}
                    onFocus={this.setColorAttribute.bind(null, 'g')}
                    onChange={this.changeRGB.bind(null, 'g')}
                    className='rgb-attribute-g'
                    type='number'
                    min={0}
                    max={255}
                    step={1} />
                </fieldset>
                <fieldset className={colorAttribute === 'b' ? 'cp-active' : ''}>
                  B
                  <input
                    value={b}
                    onFocus={this.setColorAttribute.bind(null, 'b')}
                    onChange={this.changeRGB.bind(null, 'b')}
                    className='rgb-attribute-b'
                    type='number'
                    min={0}
                    max={255}
                    step={1} />
                </fieldset>

              ) : (

                <fieldset className={colorAttribute === 'h' ? 'cp-active' : ''}>
                  H
                  <input
                    value={h}
                    onFocus={this.setColorAttribute.bind(null, 'h')}
                    onChange={this.changeHSV.bind(null, 'h')}
                    className='hsv-attribute-h'
                    type='number'
                    min={0}
                    max={359}
                    step={1} />
                </fieldset>
                <fieldset className={colorAttribute === 's' ? 'cp-active' : ''}>
                  S
                  <input
                    value={s}
                    onFocus={this.setColorAttribute.bind(null, 's')}
                    onChange={this.changeHSV.bind(null, 's')}
                    className='hsv-attribute-s'
                    type='number'
                    min={0}
                    max={100}
                    step={1} />
                </fieldset>
                <fieldset className={colorAttribute === 'v' ? 'cp-active' : ''}>
                  V
                  <input
                    value={v}
                    onFocus={this.setColorAttribute.bind(null, 'v')}
                    onChange={this.changeHSV.bind(null, 'v')}
                    className='hsv-attribute-v'
                    type='number'
                    min={0}
                    max={100}
                    step={1} />
                </fieldset>

              )}

              <fieldset>
                {String.fromCharCode(945)}
                <input
                  value={a}
                  onChange={this.changeAlpha}
                  type='number'
                  min={0}
                  max={100}
                  step={1} />
              </fieldset>

            <fieldset className='cp-fill-tile'>
              <input
                className='cp-alpha-slider-input'
                value={a}
                onChange={this._onAlphaSliderChange}
                style={{background: opacityGradient}}
                type='range'
                min={0}
                max={100} />
            </fieldset>

            {this.state.reset &&
              <button
                className='cp-swatch cp-swatch-reset'
                title='Reset color'
                style={{backgroundColor: this.original}}
                onClick={this.reset}>
              </button>
            }

            <fieldset className='cp-hex cp-fr'>
              #
              <input
                value={hex}
                className='cp-hex-input'
                onChange={this.changeHEX}
                type='text' />
            </fieldset>

    );
  }
});
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013 Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the MIT License.
 * See the accompanying LICENSE file for terms.
 */
/*jshint node:true*/
'use strict';

    NAME_RE = /:(\w+)/g;
var SYMBOLS = /([\/.+(){}\[\]])/g, //escape /.+(){}[] before :name conversions

function Byway(routes) {
    this.routes = compile(routes);
}

Byway.prototype.of = function(str) {
    var found = false;

    function checkRoute(route) {
        if(route.regex.test(str)) {
            found = route;
            return true;
        }
    }

    this.routes.some(checkRoute);
    return found;
};

function compile(routes) {
    var out = [];

    function perRoute(route) {
        var pattern;
        route.names = []; //todo

        if(!route.param) {
            route.param = [];
        }

        function partnames(ignored, name) {
            route.names.push(name);
            return '(\\w+)';
        }

        pattern = route.isregex ? route.pattern :
            route.pattern.replace(SYMBOLS, '\\$1').replace(NAME_RE, partnames);

        route.regex = new RegExp(pattern);
        out.push(route);
    }

    routes.forEach(perRoute);
    return out;
}

module.exports = Byway;
<commit_msg>make route.regex case-insensitive<commit_after>/**
 * Copyright (c) 2013 Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the MIT License.
 * See the accompanying LICENSE file for terms.
 */
/*jshint node:true*/
'use strict';

var SYMBOLS = /([\/.+(){}\[\]])/g, //escape /.+(){}[] before :name conversions
    NAME_RE = /:(\w+)/g;           //valid :names

function Byway(routes) {
    this.routes = compile(routes);
}

Byway.prototype.of = function(str) {
    var found = false;

    function checkRoute(route) {
        if(route.regex.test(str)) {
            found = route;
            return true;
        }
    }

    this.routes.some(checkRoute);
    return found;
};

function compile(routes) {
    var out = [];

    function perRoute(route) {
        var pattern;
        route.names = []; //todo

        if(!route.param) {
            route.param = [];
        }

        function partnames(ignored, name) {
            route.names.push(name);
            return '(\\w+)';
        }

        pattern = route.isregex ? route.pattern :
            route.pattern.replace(SYMBOLS, '\\$1').replace(NAME_RE, partnames);

        route.regex = new RegExp(pattern, 'i');
        out.push(route);
    }

    routes.forEach(perRoute);
    return out;
}

module.exports = Byway;
<|endoftext|>


<commit_before>var Q = require('q');
var spawn = require('child_process').spawn;
var iedriver = require('./lib/iedriver');
var nwin = require('node-windows');

module.exports = {
    port: 5555,
    host: 'localhost',
    path: '/',
    spawned: null,
    launch: function () {
        var deferred = Q.defer();
        var stream = '';
        this.spawned = spawn(iedriver.path, ['--port=5555']);

        this.spawned.stdout.on('data', function (data) {
            var dataStr = new String(data);
            stream += dataStr;
            if (stream.search('Listening on port') !== -1) {
                deferred.resolve();
            }
        });
        return deferred.promise;
    },
    kill: function () {

        nwin.list(function(svc){
          svc.forEach(function (item, idx) {
            Object.keys(item).forEach(function (key) {
               if(svc[idx][key] === 'iexplore.exe') {
                   nwin.kill(svc[idx].PID);
               }
            });
          });
        },true);
        this.spawned.kill('SIGTERM');
    }
};
<commit_msg>Comments & small code improvements<commit_after>/*!
 *
 * Copyright (c) 2013 Sebastian Golasch
 *
 * 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.
 *
 */

// ext. libs
var Q = require('q');
var spawn = require('child_process').spawn;
var nwin = require('node-windows');

// int. libs
var iedriver = require('./lib/iedriver');

/**
 * @module
 */

module.exports = {

    /**
     * Verbose version of the browser name
     *
     * @property
     * @type string
     * @default Internet Explorer
     */

    longName: 'Internet Explorer',

    /**
     * Default port of the IEDriverServer
     * The port may change, cause the port conflict resultion
     * tool might pick another one, if the default one is blocked
     *
     * @property
     * @type integer
     * @default 5555
     */

    port: 5555,

    /**
     * Default host of the IEDriverServer
     * The host may be overriden with
     * a user configured value
     *
     * @property
     * @type string
     * @default localhost
     */

    host: 'localhost',

    /**
     * Path to the IEDriverServer.exe file
     *
     * @property
     * @type string
     * @default /
     */

    path: '/',

    /**
     * Child process instance of the IEDriverServer
     *
     * @property
     * @type null|Object
     */

    spawned: null,

    /**
     * Resolves the driver port
     *
     * @method getPort
     * @return integer
     */

    getPort: function () {
        return this.port;
    },

    /**
     * Returns the driver host
     *
     * @method getHost
     * @type string
     */

    getHost: function () {
        return this.host;
    },

    /**
     * Launches the driver
     * (the driver takes care of launching the browser)
     *
     * @method launch
     * @return Q.promise
     */

    launch: function (options) {
        var deferred = Q.defer();
        var stream = '';
        this.spawned = spawn(iedriver.path, ['--port=' + this.getPort(), '--host=' + this.getHost()]);

        this.spawned.stdout.on('data', function (data) {
            var dataStr = new String(data);
            stream += dataStr;
            if (stream.search('Listening on port') !== -1) {
                deferred.resolve();
            }
        });
        return deferred.promise;
    },

    /**
     * Kills the driver & browser processes
     *
     * @method kill
     * @chainable
     */

    kill: function () {
        // get a list of all running processes
        nwin.list(function(svc){
          // filter out the browser process
          svc.forEach(function (item, idx) {
            Object.keys(item).forEach(function (key) {
              if(svc[idx][key] === 'iexplore.exe') {
                // kill the browser process
                nwin.kill(svc[idx].PID);
              }
            });
          });
        },true);

        // kill the driver process
        this.spawned.kill('SIGTERM');
        return this;
    }
};
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var _ = require('lodash');
var util = require('util');

var cmdLineRegex = /(?:(--?)([\w_][\w_-]*))|((:?["'].*?["']|[^"',=\s]+)(?:,(?:["'].*?["']|[^'',\s]+))*)/ig;

/**
 * Trims quotes off the passed string.
 * @param  {string} str
 * @return {string}
 */
function trimQuotes(str) {
	return str.replace(/^'(.*?)'$/, '$1');
}

/**
 * @constructor
 * @param {string} description The program description to be displayed when using help.
 * @param {Object} config      The command line config parameters, please refer to the examles and/or the readme
 */
function ArgumentParser(description, config) {
	this.config = config;
	this.description = description || '';

	config.help = {
		type:			'boolean',
		description:	'Show the help'
	};

	var flagRegex = /^[\w_][\w_-]*$/i;
	var shortRegex = /^\w$/i;
	var validTypes = ['number', 'integer', 'string', 'array', 'file', 'boolean'];
	var validSubTypes = ['number', 'integer', 'string', 'file'];
	_.forEach(this.config, function(v, switchName, o) {
		if (!flagRegex.test(switchName)) {
			throw new Error('Invalid switch ' + switchName + ', long switches must match /^[\\w_][\\w_-]*$/');
		}

		if (v.required && v.default) {
			throw new Error('Flag value cannot be required and have a default');
		}

		if (v.enum && (v.type || v.subType || v.regex || v.min || v.max || v.validator || v.short)) {
			throw new Error('Flag must not have any validation attributes if it is an enum');
		}

		v.type = v.type || 'string';//default to string
		if (validTypes.indexOf(v.type) === -1) {
			throw new Error('Invalid argument to \'type\', \'' + v.type + '\' specified must be [' + validTypes.join(',') + ']');
		}

		v.subType = v.subType || 'boolean';//default to string
		if (v.type === 'array') {
			if (validSubTypes.indexOf(v.subType) === -1) {
				throw new Error('Invalid argument to \'type\', \'' + v.subType + '\' specified must be [' + validSubTypes.join(',') + ']');
			}
		}

		if (v.regex) {
			if (v.type === 'number' || v.type === 'integer') {
				throw new Error('Cannot use \'regex\' when type is \'' + v.type + '\'');
			}
			if (typeof v.regex === 'string') {
				v.regex = new RegExp(v.regex);//Error is propagated
			}
			else if (!(v.regex instanceof RegExp)) {
				throw new Error('Invalid argument to \'regex\', must be either a RegExp or compilable string');
			}
		}

		if (v.min && typeof v.min !== 'number') {
			throw new Error('Invalid argument to \'min\', must be a number');
		}

		if (v.max && typeof v.max !== 'number') {
			throw new Error('Invalid argument to \'max\', must be a number');
		}

		if (v.filter && typeof v.filter !== 'function') {
			throw new Error('Invalid argument to \'filter\', must be a function');
		}

		if (v.validator && typeof v.validator !== 'function') {
			throw new Error('Invalid argument to \'validator\', must be a function');
		}

		if (v.short) {
			if (typeof v.short !== 'string') {
				throw new Error('Invalid argument to \'short\', must be a string');
			}

			if (!shortRegex.test(v.short)) {
				throw new Error('Invalid argument to \'short\', string must match /^\\w$/');
			}

			this.config[v.short] = v;
		}
	}, this);
	this.values = {};
}

var p = ArgumentParser.prototype;

/**
 * Attempts to split given command line input into usable pieces.
 * @private
 * @param  {string} line The command line string
 * @return {Array.<Object>}
 */
p.splitArgs = function(line) {
	var matches;
	var ret = [];
	line.replace(cmdLineRegex, function(match, shortDash, shortFlags, value) {
		if (shortDash === '-') {
			shortFlags.split('').forEach(function(shortFlag) {
				ret.push({
					isFlag: true,
					value: shortFlag,
					isShort: true
				});
			});
		} else {
			ret.push({
				isFlag: !!shortDash,
				value: shortDash ? shortFlags : matches[3],
				isShort: false
			});
		}
	});
	return ret;
};

/**
 * Handles the parsing and validation of a value
 * @private
 * @param  {Object} entry The corresponding switch config object for the switch.
 * @param  {string} value The raw string value associated with the switch
 * @param  {string} flag  The name of the flag
 * @return {*}
 */
p.handleValue = function(entry, value, flag) {
	if (!value && entry.default && entry.type !== 'file') {
		value = entry.default;
	}

	if (value) {
		value = trimQuotes(value);
	}

	if (entry.enum && entry.enum.indexOf(value) === -1) {
		throw new Error('Invalid enum value for \'' + flag + '\' must be in [' + entry.enum.join(',') + ']');
	}

	switch (entry.type) {
		case 'boolean':
			value = true;
			break;
		case 'number':
		case 'integer':
			value = (entry.type === 'number' ? parseFloat : parseInt)(value);
			if (!isFinite(value)) {
				throw new Error('Could not parse number from argument for \'' + flag + '\'');
			}
			if (entry.min && value < entry.min) {
				throw new Error('Argument for \'' + flag + '\' must be greater or equal to ' + entry.min);
			}

			if (entry.max && value > entry.max) {
				throw new Error('Argument for \'' + flag + '\' must be less or equal to ' + entry.min);
			}
			break;
		case 'string'://heh
			if (entry.regex && !entry.regex.test(value)) {
				throw new Error('Argument for \'' + flag + '\' did not match the regular expression ' + entry.regex.source);
			}
			break;
		case 'array'://we are assuming all arguments in the array should be of a uniform type
			value = value.split(',').map(function(value, index, arr) {
				value = trimQuotes(value);
				if (entry.regex && !entry.regex.test(value)) {
					throw new Error(
						util.format(
							'Member \'%s\' of argument for \'%s\' did not match the regular expression %s',
							value,
							flag,
							entry.regex.source
						)
					);
				}
				switch (entry.subType) {
					case 'integer':
						value = (entry.subType === 'number' ? parseFloat : parseInt)(value);
						if (!isFinite(value)) {
							throw new Error('Could not parse number from member \'' + value + '\' of argument for \'' + flag + '\'');
						}

						if (entry.min && value < entry.min) {
							throw new Error(
								util.format(
									'Member \'%s\' of argument for \'%s\' must be greater or equal than %s',
									value,
									flag,
									entry.min
								)
							);
						}

						if (entry.max && value > entry.max) {
							throw new Error(
								util.format(
									'Member \'%s\' of argument for \'%s\' must be less or equal than %s',
									value,
									flag,
									entry.max
								)
							);
						}
				}
			});
			break;
		case 'file':
			var path = entry.path || entry.default;
			if (entry.json) {
				var data = fs.readFileSync(path, entry.json ? 'utf8' : entry.encoding);
				try {
					return JSON.parse(data);
				} catch (error) {
					throw new Error('Could not parse json from file ' + path);
				}
			}
			if (entry.stream) {
				try {
					value = fs.createReadStream(path)
					.on('error', function(error) {
						if (error.errno === 34) {
							throw new Error('Could not open file ' + path);
						}
						throw error;
					});
					return value;
				} catch (e) {
					throw new Error('Could not open file ' + path);
				}
			}
	}
	var validatorResult;
	if (
		entry.validator &&
		(validatorResult = entry.validator(value)) &&
		((typeof validatorResult === 'object' && validatorResult.error) || validatorResult === false)
	) {
		throw new Error('Validator failed for argument for \'' + flag + '\', \'' + validatorResult.error + '\'');
	}
	return value;
};

/**
 * Processes the individual flags and pre-filters non-existant ones.
 * Also handles flag-value associations.
 * @private
 * @param  {Object}   curr The parsed flag/value info
 * @param  {Object} next The next parse flag/value info
 * @return {*}
 */
p.handleFlag = function(curr, next) {
	var entry = this.config[curr.value];
	if (!entry) {
		throw new Error('Unknown flag \'' + curr.value + '\'');
	}
	if (this.values[curr.value]) {
		throw new Error('Dublicate flag \'' + curr.value + '\'');
	}
	if (!curr.isShort) {
		if (entry.required && next.isFlag) {
			throw new Error('Flag \'' + curr.value + '\' requires a value');
		}
		return this.handleValue(entry, next && next.value, curr.value);
	}
};

/**
 * Generates the help string for the specified flag name.
 * @public
 * @param  {string} flagName
 * @return {string}
 */
p.getFlagHelpString = function(flagName) {
	var conf = this.config[flagName];
	var baseString = (conf.short || '') + '--' + flagName;
	var defaultString = conf.default ? '(' + conf.default + ')' : '';
	var requiredString = conf.required ? '!' : '';
	var descriptionString = conf.description || '';
	var middleString = '';
	if (conf.enum) {
		middleString = '=[' + conf.enum.join(',') + ']';
	} else {
		switch (conf.type) {
			case 'number':
			case 'integer':
				middleString = '=<' + (conf.min ? (conf.min + '<=') : '') + conf.type + (conf.max ? ('<=' + conf.max) : '') + '>';
				break;
			case 'string':
				middleString = '=<string' + (conf.regex ? ' matching ' + conf.regex.source : '') + '>';
				break;
			case 'array':
				middleString = '=<' + 'array of ' + conf.subType + '>';
				break;
			case 'file':
				middleString = '=<file>';
		}
	}

	return baseString + middleString + defaultString + requiredString + ' ' + descriptionString;

};

/**
 * @public
 * Builds the complete help info.
 * @return {string}
 */
p.getHelpString = function() {
	var ret = [];
	ret.push('Description: ' + this.description);
	ret.push('--FLAGNAME[=<TYPE>(DEFAULT)[!REQUIRED]');
	ret.push('\n');
	_.forEach(this.config, function(value, flagName, conf) {
		ret.push(this.getFlagHelpString(flagName));
	}, this);
	return ret.join('\n');
};

/**
 * Main function that initiates the parsing, validation and refinement of the data
 * @public
 * @param  {string} str
 * @return {Object.<string, *>}
 */
p.parse = function(str) {
	var split = this.splitArgs(str);
	var stopParse = false;
	split.forEach(function(flag) {
		if (flag.isFlag && flag.value === 'help') {
			console.log(this.getHelpString());
			stopParse = true;
		}
	}, this);
	if (stopParse) {
		return false;
	}

	var self = this;

	var skipNext = false;

	_.forEach(split, function(curr, index) {
		if (skipNext) {
			skipNext = false;
			return;
		}
		var next = split[index + 1];
		if (!curr.isFlag) {
			throw new Error('Unhandled value ' + curr.value);
		}
		var val = self.handleFlag(curr, next);
		self.values[curr.value] = val;

		if (next && !next.isFlag) {
			skipNext = true;
		}
	});

	_.forEach(self.config, function(v, k, o) {
		if (!self.values[k]) {
			if (v.required) {
				throw new Error('Flag \'' + k + '\' is required but was not set');
			}
			else if (v.default) {
				self.values[k] = v.default;
			}
		}
	}, this);
};

/**
 * Utility function that directory passes the fixed command line args to the parse function.
 * @return {Object.<string, *>}
 */
p.run = function() {
	return this.parse(process.argv.slice(2).join(' '));
};

module.exports = ArgumentParser;
<commit_msg>Added missing return<commit_after>'use strict';

var fs = require('fs');
var _ = require('lodash');
var util = require('util');

var cmdLineRegex = /(?:(--?)([\w_][\w_-]*))|((:?["'].*?["']|[^"',=\s]+)(?:,(?:["'].*?["']|[^'',\s]+))*)/ig;

/**
 * Trims quotes off the passed string.
 * @param  {string} str
 * @return {string}
 */
function trimQuotes(str) {
	return str.replace(/^'(.*?)'$/, '$1');
}

/**
 * @constructor
 * @param {string} description The program description to be displayed when using help.
 * @param {Object} config      The command line config parameters, please refer to the examles and/or the readme
 */
function ArgumentParser(description, config) {
	this.config = config;
	this.description = description || '';

	config.help = {
		type:			'boolean',
		description:	'Show the help'
	};

	var flagRegex = /^[\w_][\w_-]*$/i;
	var shortRegex = /^\w$/i;
	var validTypes = ['number', 'integer', 'string', 'array', 'file', 'boolean'];
	var validSubTypes = ['number', 'integer', 'string', 'file'];
	_.forEach(this.config, function(v, switchName, o) {
		if (!flagRegex.test(switchName)) {
			throw new Error('Invalid switch ' + switchName + ', long switches must match /^[\\w_][\\w_-]*$/');
		}

		if (v.required && v.default) {
			throw new Error('Flag value cannot be required and have a default');
		}

		if (v.enum && (v.type || v.subType || v.regex || v.min || v.max || v.validator || v.short)) {
			throw new Error('Flag must not have any validation attributes if it is an enum');
		}

		v.type = v.type || 'string';//default to string
		if (validTypes.indexOf(v.type) === -1) {
			throw new Error('Invalid argument to \'type\', \'' + v.type + '\' specified must be [' + validTypes.join(',') + ']');
		}

		v.subType = v.subType || 'boolean';//default to string
		if (v.type === 'array') {
			if (validSubTypes.indexOf(v.subType) === -1) {
				throw new Error('Invalid argument to \'type\', \'' + v.subType + '\' specified must be [' + validSubTypes.join(',') + ']');
			}
		}

		if (v.regex) {
			if (v.type === 'number' || v.type === 'integer') {
				throw new Error('Cannot use \'regex\' when type is \'' + v.type + '\'');
			}
			if (typeof v.regex === 'string') {
				v.regex = new RegExp(v.regex);//Error is propagated
			}
			else if (!(v.regex instanceof RegExp)) {
				throw new Error('Invalid argument to \'regex\', must be either a RegExp or compilable string');
			}
		}

		if (v.min && typeof v.min !== 'number') {
			throw new Error('Invalid argument to \'min\', must be a number');
		}

		if (v.max && typeof v.max !== 'number') {
			throw new Error('Invalid argument to \'max\', must be a number');
		}

		if (v.filter && typeof v.filter !== 'function') {
			throw new Error('Invalid argument to \'filter\', must be a function');
		}

		if (v.validator && typeof v.validator !== 'function') {
			throw new Error('Invalid argument to \'validator\', must be a function');
		}

		if (v.short) {
			if (typeof v.short !== 'string') {
				throw new Error('Invalid argument to \'short\', must be a string');
			}

			if (!shortRegex.test(v.short)) {
				throw new Error('Invalid argument to \'short\', string must match /^\\w$/');
			}

			this.config[v.short] = v;
		}
	}, this);
	this.values = {};
}

var p = ArgumentParser.prototype;

/**
 * Attempts to split given command line input into usable pieces.
 * @private
 * @param  {string} line The command line string
 * @return {Array.<Object>}
 */
p.splitArgs = function(line) {
	var matches;
	var ret = [];
	line.replace(cmdLineRegex, function(match, shortDash, shortFlags, value) {
		if (shortDash === '-') {
			shortFlags.split('').forEach(function(shortFlag) {
				ret.push({
					isFlag: true,
					value: shortFlag,
					isShort: true
				});
			});
		} else {
			ret.push({
				isFlag: !!shortDash,
				value: shortDash ? shortFlags : matches[3],
				isShort: false
			});
		}
	});
	return ret;
};

/**
 * Handles the parsing and validation of a value
 * @private
 * @param  {Object} entry The corresponding switch config object for the switch.
 * @param  {string} value The raw string value associated with the switch
 * @param  {string} flag  The name of the flag
 * @return {*}
 */
p.handleValue = function(entry, value, flag) {
	if (!value && entry.default && entry.type !== 'file') {
		value = entry.default;
	}

	if (value) {
		value = trimQuotes(value);
	}

	if (entry.enum && entry.enum.indexOf(value) === -1) {
		throw new Error('Invalid enum value for \'' + flag + '\' must be in [' + entry.enum.join(',') + ']');
	}

	switch (entry.type) {
		case 'boolean':
			value = true;
			break;
		case 'number':
		case 'integer':
			value = (entry.type === 'number' ? parseFloat : parseInt)(value);
			if (!isFinite(value)) {
				throw new Error('Could not parse number from argument for \'' + flag + '\'');
			}
			if (entry.min && value < entry.min) {
				throw new Error('Argument for \'' + flag + '\' must be greater or equal to ' + entry.min);
			}

			if (entry.max && value > entry.max) {
				throw new Error('Argument for \'' + flag + '\' must be less or equal to ' + entry.min);
			}
			break;
		case 'string'://heh
			if (entry.regex && !entry.regex.test(value)) {
				throw new Error('Argument for \'' + flag + '\' did not match the regular expression ' + entry.regex.source);
			}
			break;
		case 'array'://we are assuming all arguments in the array should be of a uniform type
			value = value.split(',').map(function(value, index, arr) {
				value = trimQuotes(value);
				if (entry.regex && !entry.regex.test(value)) {
					throw new Error(
						util.format(
							'Member \'%s\' of argument for \'%s\' did not match the regular expression %s',
							value,
							flag,
							entry.regex.source
						)
					);
				}
				switch (entry.subType) {
					case 'integer':
						value = (entry.subType === 'number' ? parseFloat : parseInt)(value);
						if (!isFinite(value)) {
							throw new Error('Could not parse number from member \'' + value + '\' of argument for \'' + flag + '\'');
						}

						if (entry.min && value < entry.min) {
							throw new Error(
								util.format(
									'Member \'%s\' of argument for \'%s\' must be greater or equal than %s',
									value,
									flag,
									entry.min
								)
							);
						}

						if (entry.max && value > entry.max) {
							throw new Error(
								util.format(
									'Member \'%s\' of argument for \'%s\' must be less or equal than %s',
									value,
									flag,
									entry.max
								)
							);
						}
				}
			});
			break;
		case 'file':
			var path = entry.path || entry.default;
			if (entry.json) {
				var data = fs.readFileSync(path, entry.json ? 'utf8' : entry.encoding);
				try {
					return JSON.parse(data);
				} catch (error) {
					throw new Error('Could not parse json from file ' + path);
				}
			}
			if (entry.stream) {
				try {
					value = fs.createReadStream(path)
					.on('error', function(error) {
						if (error.errno === 34) {
							throw new Error('Could not open file ' + path);
						}
						throw error;
					});
					return value;
				} catch (e) {
					throw new Error('Could not open file ' + path);
				}
			}
	}
	var validatorResult;
	if (
		entry.validator &&
		(validatorResult = entry.validator(value)) &&
		((typeof validatorResult === 'object' && validatorResult.error) || validatorResult === false)
	) {
		throw new Error('Validator failed for argument for \'' + flag + '\', \'' + validatorResult.error + '\'');
	}
	return value;
};

/**
 * Processes the individual flags and pre-filters non-existant ones.
 * Also handles flag-value associations.
 * @private
 * @param  {Object}   curr The parsed flag/value info
 * @param  {Object} next The next parse flag/value info
 * @return {*}
 */
p.handleFlag = function(curr, next) {
	var entry = this.config[curr.value];
	if (!entry) {
		throw new Error('Unknown flag \'' + curr.value + '\'');
	}
	if (this.values[curr.value]) {
		throw new Error('Dublicate flag \'' + curr.value + '\'');
	}
	if (!curr.isShort) {
		if (entry.required && next.isFlag) {
			throw new Error('Flag \'' + curr.value + '\' requires a value');
		}
		return this.handleValue(entry, next && next.value, curr.value);
	}
};

/**
 * Generates the help string for the specified flag name.
 * @public
 * @param  {string} flagName
 * @return {string}
 */
p.getFlagHelpString = function(flagName) {
	var conf = this.config[flagName];
	var baseString = (conf.short || '') + '--' + flagName;
	var defaultString = conf.default ? '(' + conf.default + ')' : '';
	var requiredString = conf.required ? '!' : '';
	var descriptionString = conf.description || '';
	var middleString = '';
	if (conf.enum) {
		middleString = '=[' + conf.enum.join(',') + ']';
	} else {
		switch (conf.type) {
			case 'number':
			case 'integer':
				middleString = '=<' + (conf.min ? (conf.min + '<=') : '') + conf.type + (conf.max ? ('<=' + conf.max) : '') + '>';
				break;
			case 'string':
				middleString = '=<string' + (conf.regex ? ' matching ' + conf.regex.source : '') + '>';
				break;
			case 'array':
				middleString = '=<' + 'array of ' + conf.subType + '>';
				break;
			case 'file':
				middleString = '=<file>';
		}
	}

	return baseString + middleString + defaultString + requiredString + ' ' + descriptionString;

};

/**
 * @public
 * Builds the complete help info.
 * @return {string}
 */
p.getHelpString = function() {
	var ret = [];
	ret.push('Description: ' + this.description);
	ret.push('--FLAGNAME[=<TYPE>(DEFAULT)[!REQUIRED]');
	ret.push('\n');
	_.forEach(this.config, function(value, flagName, conf) {
		ret.push(this.getFlagHelpString(flagName));
	}, this);
	return ret.join('\n');
};

/**
 * Main function that initiates the parsing, validation and refinement of the data
 * @public
 * @param  {string} str
 * @return {Object.<string, *>}
 */
p.parse = function(str) {
	var split = this.splitArgs(str);
	var stopParse = false;
	split.forEach(function(flag) {
		if (flag.isFlag && flag.value === 'help') {
			console.log(this.getHelpString());
			stopParse = true;
		}
	}, this);
	if (stopParse) {
		return false;
	}

	var self = this;

	var skipNext = false;

	_.forEach(split, function(curr, index) {
		if (skipNext) {
			skipNext = false;
			return;
		}
		var next = split[index + 1];
		if (!curr.isFlag) {
			throw new Error('Unhandled value ' + curr.value);
		}
		var val = self.handleFlag(curr, next);
		self.values[curr.value] = val;

		if (next && !next.isFlag) {
			skipNext = true;
		}
	});

	_.forEach(self.config, function(v, k, o) {
		if (!self.values[k]) {
			if (v.required) {
				throw new Error('Flag \'' + k + '\' is required but was not set');
			}
			else if (v.default) {
				self.values[k] = v.default;
			}
		}
	}, this);
	return self.values;
};

/**
 * Utility function that directory passes the fixed command line args to the parse function.
 * @return {Object.<string, *>}
 */
p.run = function() {
	return this.parse(process.argv.slice(2).join(' '));
};

module.exports = ArgumentParser;
<|endoftext|>


<commit_before>(function(){
    var Twitter = require('twitter');
    var express = require('express');
    var app = express();
    var method = 'search/tweets';

    var client = new Twitter({
        consumer_key: process.env.TWITTER_CONSUMER_KEY,
        consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
        access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY,
        access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET
    });

    var methods = [
        'statuses/mentions_timeline',
        'statuses/home_timeline',
        'statuses/retweets_of_me',
        'search/tweets',
        'lists/statuses',
        'statuses/retweets/:id',
    ];

    var twitterAPICall = function(method) {
        return function(req, res) {
            var params = req.query;

            if (Object.keys(req.params).length === 1) {
                method = method.replace(/:id/, req.params.id);
            }

            client.get(method, params, function(error, tweets, response) {
                console.log(response);
                res.sendStatus(response.toString());
                /*res.writeHead({'Content-type': 'application/json'});*/
                var json = {};
                if (error) {
                    json = JSON.stringify(error);
                } else {
                    json = JSON.stringify(tweets);
                }
                res.write(json);
                res.end();
            });
        }
    }

    for (var i in methods) {
        app.get('/' + methods[i], twitterAPICall(methods[i]));
    }

    var server = app.listen(process.env.PORT || 8081, function() {
        var host = server.address().address,
            port = server.address().port;

            console.log("Twitter API app listening at http://%s:%s", host, port);
    });
})();<commit_msg>Updated HTTP response<commit_after>(function(){
    var Twitter = require('twitter');
    var express = require('express');
    var app = express();
    var method = 'search/tweets';

    var client = new Twitter({
        consumer_key: process.env.TWITTER_CONSUMER_KEY,
        consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
        access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY,
        access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET
    });

    var methods = [
        'statuses/mentions_timeline',
        'statuses/home_timeline',
        'statuses/retweets_of_me',
        'search/tweets',
        'lists/statuses',
        'statuses/retweets/:id',
    ];

    var twitterAPICall = function(method) {
        return function(req, res) {
            var params = req.query;

            if (Object.keys(req.params).length === 1) {
                method = method.replace(/:id/, req.params.id);
            }

            client.get(method, params, function(error, tweets, response) {
                var json = {};
                if (error) {
                    json = error;
                } else {
                    json = tweets;
                }

                res.json(json);
            });
        }
    }

    for (var i in methods) {
        app.get('/' + methods[i], twitterAPICall(methods[i]));
    }

    var server = app.listen(process.env.PORT || 8081, function() {
        var host = server.address().address,
            port = server.address().port;

            console.log("Twitter API app listening at http://%s:%s", host, port);
    });
})();<|endoftext|>


<commit_before>
var defaults = require('lodash.defaults');

var props = [
  'name',
  'message',
  'stack',
  'type',
]

var DEFAULTS = {
  format: function(err) {
    var obj = {}

    // set all enumerable properties of error onto the object
    Object.keys(err).forEach(function (key) {
      obj[key] = err[key]
    })
    props.forEach(function (key) {
      var value = err[key]
      if (value) obj[key] = value
    })

    obj.status = err.status || err.statusCode || 500

    return obj
  }
}

module.exports = function (options) {
  options = defaults({}, options, DEFAULTS);

  return function* jsonErrorHandler(next) {
    var status
    try {
      yield* next

      status = this.response.status
      // future proof status
      if (!status || (status === 404 && this.response.body == null)) this.throw(404)
    } catch (err) {
      // set body
      this.response.body = options.format(err) || {};

      // set status
      status =
      this.response.status =
      err.status || err.statusCode || 500

      // emit the error if we really care
      if (!err.expose && status >= 500) this.app.emit('error', err, this)
    }
  }
}
<commit_msg>Make use of Object.assign<commit_after>
var defaults = require('lodash.defaults');

var props = [
  'name',
  'message',
  'stack',
  'type',
]

var DEFAULTS = {
  format: function(err) {
    // set all enumerable properties of error onto the object
    var obj =  Object.assign({}, err)

    props.forEach(function (key) {
      var value = err[key]
      if (value) obj[key] = value
    })

    obj.status = err.status || err.statusCode || 500

    return obj
  }
}

module.exports = function (options) {
  options = defaults({}, options, DEFAULTS);

  return function* jsonErrorHandler(next) {
    var status
    try {
      yield* next

      status = this.response.status
      // future proof status
      if (!status || (status === 404 && this.response.body == null)) this.throw(404)
    } catch (err) {
      // set body
      this.response.body = options.format(err) || {};

      // set status
      status =
      this.response.status =
      err.status || err.statusCode || 500

      // emit the error if we really care
      if (!err.expose && status >= 500) this.app.emit('error', err, this)
    }
  }
}
<|endoftext|>


<commit_before>'use strict';

function um(numero) {
    var numeros = {
        '0': 'zero',
        '1': 'um',
        '2': 'dois',
        '3': 'três',
        '4': 'quatro',
        '5': 'cinco',
        '6': 'seis',
        '7': 'sete',
        '8': 'oito',
        '9': 'nove'
    };

    return numeros[numero];
}

function dez(numero) {
    if (numero < 10) {
        return um(numero);
    }

    var numeros = {
        '10': 'dez',
        '11': 'onze',
        '12': 'doze',
        '13': 'treze',
        '14': 'quatorze',
        '15': 'quinze',
        '16': 'dezesseis',
        '17': 'dezessete',
        '18': 'dezoito',
        '19': 'dezenove',
        '20': 'vinte',
        '30': 'trinta',
        '40': 'quarenta',
        '50': 'cinquenta',
        '60': 'sessenta',
        '70': 'setenta',
        '80': 'oitenta',
        '90': 'noventa'
    };

    var inicio = numero - numero % 10,
        fim = numero % 10;

    if (numero < 20) {
        return numeros[numero];
    } else {
        if (numero % 10 === 0) {
            return numeros[numero];
        } else {
            return numeros[inicio] + ' e ' + um(fim);
        }
    }
}

function cem(numero) {
    if (numero < 100) {
        return dez(numero);
    } else if (numero === 100) {
        return 'cem';
    } else {
        var numeros = {
            '100': 'cento',
            '200': 'duzentos',
            '300': 'trezentos',
            '400': 'quatrocentos',
            '500': 'quinhentos',
            '600': 'seissentos',
            '700': 'setecentos',
            '800': 'oitocentos',
            '900': 'novecentos'
        };

        var inicio = numero - numero % 100,
            fim = numero % 100;

        if (numero % 100 === 0) {
            return numeros[numero];
        } else {
            return numeros[inicio] + ' e ' + dez(fim);
        }
    }
}

function separar(numero) {
    function reverse(str) {
        str = str.toString();
        return str.split('').reverse().join('');
    }

    var rev = reverse(numero).match(/.?.?.?/g);
    rev = rev.slice(0, rev.length - 1).reverse();

    var a = [];

    rev.forEach(function (i) {
        a.push(reverse(i));
    });

    return a.join('.');
}

function extenso(numero) {
    var separado;

    if (/\./.test(numero)) {
        if (/^\d?\d?\d?(\.\d{3})+$/.test(numero)) {
            separado = numero;
            numero = numero.replace(/\./g, '');
        } else {
            return undefined;
        }
    }

    if (isNaN(numero)) {
        return NaN;
    }

    var positivo = numero,
        negativo = false;

    if (numero < 0) {
        positivo = -numero;
        negativo = true;
    }

    if (numero % 1 || numero > 1e+42 || numero < -1e+42) {
        return undefined;
    } else if (positivo < 1e+3) {
        if (negativo) {
            return 'menos ' + cem(parseInt(positivo));
        } else {
            return cem(parseInt(numero));
        }
    } else if (parseInt(numero) === 1e+3) {
        return 'mil';
    } else {
        var str = typeof numero !== 'string';

        if ((numero > 1e+15 || numero < -1e+15) && str) {
            return undefined;
        }

        var numeros = [
            'mil',
            'milhões',
            'bilhões',
            'trilhões',
            'quatrilhões',
            'quintilhões',
            'sextilhões',
            'septilhões',
            'octilhões',
            'nonilhões',
            'decilhões',
            'undecilhões',
            'duodecilhões'
        ];

        var ext;

        if (separado) {
            ext = separado;
        } else {
            ext = separar(numero.toString());
        }

        if (negativo) {
            ext = ext.substring(1, ext.length);
        }

        var num = numeros.slice(0, ext.match(/\./g).length)
            .reverse();

        num.forEach(function (i) {
            ext = ext.replace(/\./, ' ' + i + ' ');
        });

        ext = ext.replace(/(\b(0+)?1\s.[^\s]*)ões/g, '$1ão')
            .replace(/000\s.[^\s]*|\b0+|\s000$/g, '')
            .replace(/\s\s+/g, ' ')
            .replace(/\s$/, '')
            .replace(/\b(\d(00|\d?))$/g, 'e $1')
            .replace(/\s(\d+\s[\wõã]+)$/g, ' e $1')
            .replace(/\b1\smil\b/g, 'mil');

        var lista = [];

        ext.match(/\d+/g).forEach(function (i) {
            if (/^0+$/.test(i)) {
                lista.push(undefined);
            } else {
                lista.push(i);
            }
        });

        lista.forEach(function (i) {
            if (i) {
                ext = ext.replace(i, cem(parseInt(i)));
            } else {
                ext = ext.replace(/0+/, '');
            }
        });

        if (negativo) {
            return 'menos ' + ext;
        } else {
            return ext;
        }
    }
}

function decimal(numero) {
    var numeros = {
        '3': 'milésimo',
        '6': 'milionésimo',
        '9': 'bilionésimo',
        '12': 'trilionésimo',
        '15': 'quatrilionésimo',
        '18': 'quintilionésimo',
        '21': 'sextilionésimo',
        '24': 'septilionésimo',
        '27': 'octilionésimo',
        '30': 'nonilionésimo',
        '33': 'decilionésimo',
        '36': 'undecilionésimo',
        '39': 'duodecilionésimo'
    };

    var inteiro = parseInt(numero),
        len,
        n;

    if (numero.length < 4) {
        len = numero.length;

        if (len === 1) {
            n = cem(inteiro) + ' décimo';
        } else if (len === 2) {
            n = cem(inteiro) + ' centésimo';
        } else {
            n = cem(inteiro) + ' milésimo';
        }

        if (inteiro === 1) {
            return n;
        } else {
            return n + 's';
        }
    } else {
        len = numero.length;

        var tipo = len % 3,
            ext = extenso(inteiro);

        if (tipo === 0) {
            n = numeros[len];

            if (inteiro === 1) {
                return ext + ' ' + n;
            } else {
                return ext + ' ' + n + 's';
            }
        } else if (tipo === 1) {
            n = numeros[len - 1];

            if (inteiro === 1) {
                return ext + ' décimo de ' + n;
            } else {
                return ext + ' décimos de ' + n + 's';
            }
        } else {
            n = numeros[len - 2];

            if (inteiro === 1) {
                return ext + ' centésimo de ' + n;
            } else {
                return ext + ' centésimos de ' + n + 's';
            }
        }
    }
}

module.exports = function (numero) {
    if (typeof numero === 'string' && !isNaN(numero)) {
        numero = numero.trim();

        if (/^\d+(\.\d+)?e(\-|\+)?\d+$/i.test(numero)) {
            if (numero % 1 === 0) {
                numero = parseFloat(numero);
            } else {
                numero = parseFloat(numero);
            }
        }
    }

    if (/^[\d\.]+,\d+$/.test(numero)) {
        var s = numero.toString()
            .split(',');

        var inte = extenso(s[0]),
            nint = decimal(s[1]);

        if (/^0+$/.test(s[1])) {
            return inte;
        } else if (inte === 'zero') {
            return nint;
        } else {
            if (inte === 'um') {
                return 'um inteiro e ' + nint;
            } else {
                return inte + ' inteiros e ' + nint;
            }
        }
    } else {
        return extenso(numero);
    }
};
<commit_msg>Corrige erro com hexadecimal<commit_after>'use strict';

function um(numero) {
    var numeros = {
        '0': 'zero',
        '1': 'um',
        '2': 'dois',
        '3': 'três',
        '4': 'quatro',
        '5': 'cinco',
        '6': 'seis',
        '7': 'sete',
        '8': 'oito',
        '9': 'nove'
    };

    return numeros[numero];
}

function dez(numero) {
    if (numero < 10) {
        return um(numero);
    }

    var numeros = {
        '10': 'dez',
        '11': 'onze',
        '12': 'doze',
        '13': 'treze',
        '14': 'quatorze',
        '15': 'quinze',
        '16': 'dezesseis',
        '17': 'dezessete',
        '18': 'dezoito',
        '19': 'dezenove',
        '20': 'vinte',
        '30': 'trinta',
        '40': 'quarenta',
        '50': 'cinquenta',
        '60': 'sessenta',
        '70': 'setenta',
        '80': 'oitenta',
        '90': 'noventa'
    };

    var inicio = numero - numero % 10,
        fim = numero % 10;

    if (numero < 20) {
        return numeros[numero];
    } else {
        if (numero % 10 === 0) {
            return numeros[numero];
        } else {
            return numeros[inicio] + ' e ' + um(fim);
        }
    }
}

function cem(numero) {
    if (numero < 100) {
        return dez(numero);
    } else if (numero === 100) {
        return 'cem';
    } else {
        var numeros = {
            '100': 'cento',
            '200': 'duzentos',
            '300': 'trezentos',
            '400': 'quatrocentos',
            '500': 'quinhentos',
            '600': 'seissentos',
            '700': 'setecentos',
            '800': 'oitocentos',
            '900': 'novecentos'
        };

        var inicio = numero - numero % 100,
            fim = numero % 100;

        if (numero % 100 === 0) {
            return numeros[numero];
        } else {
            return numeros[inicio] + ' e ' + dez(fim);
        }
    }
}

function separar(numero) {
    function reverse(str) {
        str = str.toString();
        return str.split('').reverse().join('');
    }

    var rev = reverse(numero).match(/.?.?.?/g);
    rev = rev.slice(0, rev.length - 1).reverse();

    var a = [];

    rev.forEach(function (i) {
        a.push(reverse(i));
    });

    return a.join('.');
}

function extenso(numero) {
    var separado;

    if (/\./.test(numero)) {
        if (/^\d?\d?\d?(\.\d{3})+$/.test(numero)) {
            separado = numero;
            numero = numero.replace(/\./g, '');
        } else {
            return undefined;
        }
    }

    if (isNaN(numero)) {
        return NaN;
    }

    var positivo = numero,
        negativo = false;

    if (numero < 0) {
        positivo = -numero;
        negativo = true;
    }

    if (numero % 1 || numero > 1e+42 || numero < -1e+42) {
        return undefined;
    } else if (positivo < 1e+3) {
        if (negativo) {
            return 'menos ' + cem(parseInt(positivo));
        } else {
            return cem(parseInt(numero));
        }
    } else if (parseInt(numero) === 1e+3) {
        return 'mil';
    } else {
        var str = typeof numero !== 'string';

        if ((numero > 1e+15 || numero < -1e+15) && str) {
            return undefined;
        }

        var numeros = [
            'mil',
            'milhões',
            'bilhões',
            'trilhões',
            'quatrilhões',
            'quintilhões',
            'sextilhões',
            'septilhões',
            'octilhões',
            'nonilhões',
            'decilhões',
            'undecilhões',
            'duodecilhões'
        ];

        var ext;

        if (separado) {
            ext = separado;
        } else {
            ext = separar(numero.toString());
        }

        if (negativo) {
            ext = ext.substring(1, ext.length);
        }

        var num = numeros.slice(0, ext.match(/\./g).length)
            .reverse();

        num.forEach(function (i) {
            ext = ext.replace(/\./, ' ' + i + ' ');
        });

        ext = ext.replace(/(\b(0+)?1\s.[^\s]*)ões/g, '$1ão')
            .replace(/000\s.[^\s]*|\b0+|\s000$/g, '')
            .replace(/\s\s+/g, ' ')
            .replace(/\s$/, '')
            .replace(/\b(\d(00|\d?))$/g, 'e $1')
            .replace(/\s(\d+\s[\wõã]+)$/g, ' e $1')
            .replace(/\b1\smil\b/g, 'mil');

        var lista = [];

        ext.match(/\d+/g).forEach(function (i) {
            if (/^0+$/.test(i)) {
                lista.push(undefined);
            } else {
                lista.push(i);
            }
        });

        lista.forEach(function (i) {
            if (i) {
                ext = ext.replace(i, cem(parseInt(i)));
            } else {
                ext = ext.replace(/0+/, '');
            }
        });

        if (negativo) {
            return 'menos ' + ext;
        } else {
            return ext;
        }
    }
}

function decimal(numero) {
    var numeros = {
        '3': 'milésimo',
        '6': 'milionésimo',
        '9': 'bilionésimo',
        '12': 'trilionésimo',
        '15': 'quatrilionésimo',
        '18': 'quintilionésimo',
        '21': 'sextilionésimo',
        '24': 'septilionésimo',
        '27': 'octilionésimo',
        '30': 'nonilionésimo',
        '33': 'decilionésimo',
        '36': 'undecilionésimo',
        '39': 'duodecilionésimo'
    };

    var inteiro = parseInt(numero),
        len,
        n;

    if (numero.length < 4) {
        len = numero.length;

        if (len === 1) {
            n = cem(inteiro) + ' décimo';
        } else if (len === 2) {
            n = cem(inteiro) + ' centésimo';
        } else {
            n = cem(inteiro) + ' milésimo';
        }

        if (inteiro === 1) {
            return n;
        } else {
            return n + 's';
        }
    } else {
        len = numero.length;

        var tipo = len % 3,
            ext = extenso(inteiro);

        if (tipo === 0) {
            n = numeros[len];

            if (inteiro === 1) {
                return ext + ' ' + n;
            } else {
                return ext + ' ' + n + 's';
            }
        } else if (tipo === 1) {
            n = numeros[len - 1];

            if (inteiro === 1) {
                return ext + ' décimo de ' + n;
            } else {
                return ext + ' décimos de ' + n + 's';
            }
        } else {
            n = numeros[len - 2];

            if (inteiro === 1) {
                return ext + ' centésimo de ' + n;
            } else {
                return ext + ' centésimos de ' + n + 's';
            }
        }
    }
}

module.exports = function (numero) {
    if (typeof numero === 'string' && !isNaN(numero)) {
        numero = numero.trim();

        if (/^\d+(\.\d+)?e(\-|\+)?\d+$/i.test(numero)) {
            if (numero % 1 === 0) {
                numero = parseFloat(numero);
            } else {
                numero = parseFloat(numero);
            }
        }

        if (/^0x[\dA-F]+$/i.test(numero)) {
            numero = parseInt(numero);
        }
    }

    if (/^[\d\.]+,\d+$/.test(numero)) {
        var s = numero.toString()
            .split(',');

        var inte = extenso(s[0]),
            nint = decimal(s[1]);

        if (/^0+$/.test(s[1])) {
            return inte;
        } else if (inte === 'zero') {
            return nint;
        } else {
            if (inte === 'um') {
                return 'um inteiro e ' + nint;
            } else {
                return inte + ' inteiros e ' + nint;
            }
        }
    } else {
        return extenso(numero);
    }
};
<|endoftext|>