<commit_before>const webpackConfig = require('./webpack.config.js');

module.exports = function(config) {
  config.set({
    frameworks: ['mocha', 'sinon-chai'],

    files: [
      { pattern: 'src/**/*.spec.js', watched: false },
    ],

    exclude: [],

    preprocessors: {
      'src/**/*.spec.js': ['webpack'],
    },

    webpack: {
      module: webpackConfig.module,
    },
    webpackMiddleWare: {
      stats: 'minimal',
    },

    mochaReporter: {
      showDiff: true,
    },

    reporters: ['progress', 'mocha'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['PhantomJS'],
    singleRun: true,
    concurrency: Infinity,
  })
};
<commit_msg>remove karma.conf<commit_after><|endoftext|>


<commit_before>var utilities = require('./utilities');

// argv[2] (required): the name of the active file
// argv[3] (required): the ipv4 address of the server to contact first

var activeFileName = process.argv[2];

var fileContents;

var otherServerUri = "http://" + process.argv[3] + ':' +
  utilities.SERVER_HTTP_PORT;

var p = new utilities.p2p.peer(otherServerUri, utilities.SERVER_HTTP_PORT);

// TODO: make proxy solution for network with firewall which blocks all ports

utilities.fs.writeFile(activeFileName, "", function(error) {
  if (error) {
    console.log(error);
  }
  openFileInEmacs(activeFileName);
  p.start(
    // client init function
    function() {
      console.log("speaking on " + utilities.os.hostname() + ':' +
        utilities.SERVER_HTTP_PORT);
    },
    // client socket function
    function(socket) {
      // get user id, filename, and file contents; write to file
      socket.on('connection_info', function(sentFileName) {
        activeFileName = sentFileName;
      });
      socket.on('file_send', function(sentFileContents) {
        // if not self socket
        if ("http://127.0.0.1:" + utilities.SERVER_HTTP_PORT !=
          utilities.p2p.client.getUriOfSocket(socket)) {
          utilities.fs.writeFile(
            activeFileName,
            sentFileContents,
            function(error) {
              if (error) {
                console.log(error);
              }
              updateBufferInEmacs(activeFileName);
            });
        }
      });
      socket.on('file_diff', function(sentFilePatch) {
        // if not self socket
        if ("http://127.0.0.1:" + utilities.SERVER_HTTP_PORT !=
          utilities.p2p.client.getUriOfSocket(socket)) {
          utilities.fs.readFile(
            activeFileName,
            function(error,
              readFileContents) {
              if (error) {
                console.log(error);
              }
              utilities.fs.writeFile(
                activeFileName,
                patch_apply(sentFilePatch, readFileContents)[0], // get patched text
                function(error) {
                  if (error) {
                    console.log(error);
                  }
                  updateBufferInEmacs(activeFileName);
                });
            });
        }
      });
    },
    // server init function
    function() {
      console.log("listening on " + utilities.os.hostname() + ':' +
        utilities.SERVER_HTTP_PORT);
      if ("127.0.0.1" == process.argv[3]) { // if initial server
        setInterval(broadcastBuffer, utilities.FILE_SYNC_TIME);
        setInterval(broadcastDiff, utilities.DIFF_SYNC_TIME);
      }
    },
    // server socket function
    function(socket) {
      socket.emit('connection_info', activeFileName);
    });
});

// requires emacs to be open and server to be on
function openFileInEmacs(filename) {
  var emacsOpenFile = utilities.spawn('emacsclient', ['-n', filename]);
  emacsOpenFile.stdout.on('data', function(data) {
    console.log("emacs stdout: " + data);
  });
  emacsOpenFile.stderr.on('data', function(data) {
    console.log("emacs stderr: " + data);
  });
  emacsOpenFile.on('exit', function(return_code, signal) {
    if (return_code != 0) {
      console.log("error: file could not be opened.");
    } else {
      console.log("FILE OPENED :DDDDDDDDDDDDDDDDDD");
    }
  });
}

function broadcastBuffer() {
  var emacsWriteFile = spawnEmacsCommand(
    "send-buffer-to-file", "\"" + activeFileName + "\"",
    "\"" + utilities.TMP_FILENAME_SUFFIX + "\"");
  emacsWriteFile.stdout.on('data', function(data) {
    console.log("emacs stdout: " + data);
  });
  emacsWriteFile.stderr.on('data', function(data) {
    console.log("emacs stderr: " + data);
  });
  emacsWriteFile.on('exit', function(
    return_code, signal) {
    if (return_code != 0) {
      console.log("error: file could not be saved.");
    } else {
      console.log("file broadcasted");
      utilities.fs.readFile(
        activeFileName + utilities.TMP_FILENAME_SUFFIX,
        function(error, fileContents) {
          if (error) {
            console.log(error);
          }
          p.emit('file_send', fileContents.toString());
        });
    }
  });
}

function broadcastDiff(){
  utilities.fs.readFile();
}

function updateBufferInEmacs(filename) {
  var emacsReadFile = spawnEmacsCommand(
    "read-buffer-from-file", "\"" + filename + "\"");
  emacsReadFile.stdout.on('data', function(data) {
    console.log("emacs stdout: " + data);
  });
  emacsReadFile.stderr.on('data', function(data) {
    console.log("emacs stderr: " + data);
  });
  emacsReadFile.on('exit', function(return_code, signal) {
    if (return_code != 0) {
      console.log("error: file could not be read.");
    }
    console.log("file read");
  });
}

// takes variable number of arguments
// returns spawn object
function spawnEmacsCommand() {
  var evalArg = "(";
  for (var i = 0; i < arguments.length; ++i) {
    evalArg += arguments[i] + " ";
  }
  evalArg += ")";
  return utilities.spawn('emacsclient', ['-e', evalArg]);
}
<commit_msg>added diffs<commit_after>var utilities = require('./utilities');

// argv[2] (required): the name of the active file
// argv[3] (required): the ipv4 address of the server to contact first

var activeFileName = process.argv[2];

var fileContents;

var otherServerUri = "http://" + process.argv[3] + ':' +
  utilities.SERVER_HTTP_PORT;

var p = new utilities.p2p.peer(otherServerUri, utilities.SERVER_HTTP_PORT);

// TODO: make proxy solution for network with firewall which blocks all ports

utilities.fs.writeFile(activeFileName, "", function(error) {
  if (error) {
    console.log(error);
  }
  openFileInEmacs(activeFileName);
  p.start(
    // client init function
    function() {
      console.log("speaking on " + utilities.os.hostname() + ':' +
        utilities.SERVER_HTTP_PORT);
    },
    // client socket function
    function(socket) {
      // get user id, filename, and file contents; write to file
      socket.on('connection_info', function(sentFileName) {
        activeFileName = sentFileName;
      });
      socket.on('file_send', function(sentFileContents) {
        // if not self socket
        if ("http://127.0.0.1:" + utilities.SERVER_HTTP_PORT !=
          utilities.p2p.client.getUriOfSocket(socket)) {
          utilities.fs.writeFile(
            activeFileName + utilities.CLIENT_COPY_FILE_SUFFIX,
            sentFileContents,
            function(error) {
              if (error) {
                console.log(error);
              }
              updateBufferInEmacs(activeFileName);
            });
        }
      });
      socket.on('file_diff', function(sentFilePatch) {
        // if not self socket
        if ("http://127.0.0.1:" + utilities.SERVER_HTTP_PORT !=
          utilities.p2p.client.getUriOfSocket(socket)) {
          utilities.fs.readFile(
            activeFileName + utilities.CLIENT_COPY_FILE_SUFFIX,
            function(error,
              readFileContents) {
              if (error) {
                console.log(error);
              }
              utilities.fs.writeFile(
                activeFileName + utilities.CLIENT_COPY_FILE_SUFFIX,
                utilities.diff_match_patch.patch_apply(
                  sentFilePatch,
                  readFileContents)[0],
                function(error) {
                  if (error) {
                    console.log(error);
                  }
                  updateBufferInEmacs(activeFileName);
                });
            });
        }
      });
    },
    // server init function
    function() {
      console.log("listening on " + utilities.os.hostname() + ':' +
        utilities.SERVER_HTTP_PORT);
      if ("127.0.0.1" == process.argv[3]) { // if initial server
        setInterval(broadcastBuffer, utilities.FILE_SYNC_TIME);
        setInterval(broadcastDiff, utilities.DIFF_SYNC_TIME);
      }
    },
    // server socket function
    function(socket) {
      socket.emit('connection_info', activeFileName);
    });
});

// requires emacs to be open and server to be on
function openFileInEmacs(filename) {
  var emacsOpenFile = utilities.spawn('emacsclient', ['-n', filename]);
  emacsOpenFile.stdout.on('data', function(data) {
    console.log("emacs stdout: " + data);
  });
  emacsOpenFile.stderr.on('data', function(data) {
    console.log("emacs stderr: " + data);
  });
  emacsOpenFile.on('exit', function(return_code, signal) {
    if (return_code != 0) {
      console.log("error: file could not be opened.");
    } else {
      console.log("FILE OPENED :DDDDDDDDDDDDDDDDDD");
    }
  });
}

function broadcastBuffer() {
  var emacsWriteFile = spawnEmacsCommand(
    "send-buffer-to-file", "\"" + activeFileName + "\"",
    "\"" + utilities.TMP_FILENAME_SUFFIX + "\"");
  emacsWriteFile.stdout.on('data', function(data) {
    console.log("emacs stdout: " + data);
  });
  emacsWriteFile.stderr.on('data', function(data) {
    console.log("emacs stderr: " + data);
  });
  emacsWriteFile.on('exit', function(
    return_code, signal) {
    if (0 != return_code) {
      console.log("error: buffer could not be saved.");
    } else {
      utilities.fs.readFile(
        activeFileName + utilities.TMP_FILENAME_SUFFIX,
        function(error, fileContents) {
          if (error) {
            console.log(error);
          }
          p.emit('file_send', fileContents.toString());
        });
      console.log("file broadcasted");
    }
  });
}

function broadcastDiff() {
  var emacsWriteFile = spawnEmacsCommand(
    "send-buffer-to-file", "\"" + activeFileName + "\"",
    "\"" + utilities.TMP_FILENAME_SUFFIX + "\"");
  emacsWriteFile.stdout.on('data', function(data) {
    console.log("emacs stdout: " + data)
  });
  emacsWriteFile.stderr.on('data', function(data) {
    console.log("emacs stderr: " + data);
  });
  emacsWriteFile.on('exit', function(return_code, signal) {
    if (0 != return_code) {
      console.log("error: buffer could not be saved.");
    } else {
      utilities.fs.readFile(
        activeFileName + utilities.TMP_FILENAME_SUFFIX,
        function(tmpError, tmpFileContents) {
          if (tmpError) {
            console.log(error);
          }
          utilities.fs.readFile(
            activeFileName,
            function(curError, curFileContents) {
              if (curError) {
                console.log(error);
              }
              utilities.fs.writeFile(
                activeFileName,
                tmpFileContents,
                function(error) {
                  console.log(error);
                  p.emit('file_diff',
                    utilities.diff_match_patch.patch_make(
                      curFileContents, tmpFileContents));
                }
              )
            });
        });
    }
  });
}

function updateBufferInEmacs(filename) {
  var emacsReadFile = spawnEmacsCommand(
    "read-buffer-from-file", "\"" + filename + "\"");
  emacsReadFile.stdout.on('data', function(data) {
    console.log("emacs stdout: " + data);
  });
  emacsReadFile.stderr.on('data', function(data) {
    console.log("emacs stderr: " + data);
  });
  emacsReadFile.on('exit', function(return_code, signal) {
    if (return_code != 0) {
      console.log("error: file could not be read.");
    }
    console.log("file read");
  });
}

// takes variable number of arguments
// returns spawn object
function spawnEmacsCommand() {
  var evalArg = "(";
  for (var i = 0; i < arguments.length; ++i) {
    evalArg += arguments[i] + " ";
  }
  evalArg += ")";
  return utilities.spawn('emacsclient', ['-e', evalArg]);
}
<|endoftext|>


<commit_before>'use strict';

var operators = require('./operators')
  , custom = ['ALL'];

/**
 * Strip MongoDB operators from user provided objects.
 *
 * @Constructor
 * @param {Object} options
 * @api public
 */
function Filter(options) {
  this.options = options || {};

  for (var group in operators) {
    var prop = group.toLowerCase();
    this[prop] = this.mask(group, this.options[prop]);
  }
}

/**
 * Filter the provided query object, removing keys that are not
 * allowed to exists on the query object.
 *
 * @param {Object} query Query object.
 * @param {String} restrict Operator group to further restrict allowed operators.
 * @return {Object} Filtered query object.
 * @api public
 */
Filter.prototype.filter = function filter(query, restrict) {
  if ('object' !== typeof query) return query;

  var groups = this.groups(restrict)
    , filter = this;

  for (var key in query) {
    if ('$' !== key[0]) continue;
    if ('object' === typeof query[key]) {
      this.parse(query[key]);
      continue;
    }

    groups.forEach(function each(group) {
      if (!~filter[group].indexOf(key)) delete query[key];
    });
  }

  return query;
};

/**
 * Enable certain operators by providing a bitmask against the group.
 *
 * @param {String} group Group of operators to check the bitmask against.
 * @param {Number} bitmask Binary mask.
 * @returns {Array} set of allowed operators.
 * @api public
 */
Filter.prototype.mask = function mask(group, bitmask) {
  if (!group || !bitmask) return [];
  var stack = '';

  for (var key in operators[group]) {
    if (~custom.indexOf(key)) continue;
    if (Filter[group][key] & bitmask) {
      stack += operators[group][key];
    }
  }

  return stack.split(',');
};

/**
 * Return the operator groups that have allowed operators,
 * optionally filtered by a group name.
 *
 * @param {String} restrict Optional group name to only return that group.
 * @return {Array} Set of group names.
 * @api public
 */
Filter.prototype.groups = function groups(restrict) {
  var filter = this;

  return Object.keys(operators).map(function lowercase(group) {
    group = group.toLowerCase();
    if (filter[group].length) return group;
  }).filter(function filter(group) {
    return restrict ? group === restrict : group;
  });
};

/**
 * Check if the operator is allowed for the group.
 *
 * @param {String} group Group the operator belongs to.
 * @param {String} key Operator name
 * @return {Boolean}
 * @api public
 */
Filter.prototype.allowed = function allowed(group, key) {
  key += key[0] !== '$' ? '$' : '';
  return !!~this[group].indexOf(key);
};

//
// Define bitmaps for all operators on the constructor.
//
for (var group in operators) {
  var i = 0;

  if ('object' !== typeof operators[group]) Filter[group] = 1 << i++;
  else for (var key in operators[group]) {
    Filter[group] = Filter[group] || Object.create(null);
    Filter[group][key] = 1 << i++;
  }

  Filter[group].ALL = (1 << i) - 1;
}

//
// Expose the module.
//
module.exports = Filter;<commit_msg>[fix] jslint<commit_after>'use strict';

var operators = require('./operators')
  , custom = ['ALL'];

/**
 * Strip MongoDB operators from user provided objects.
 *
 * @Constructor
 * @param {Object} options
 * @api public
 */
function Filter(options) {
  this.options = options || {};

  for (var group in operators) {
    var prop = group.toLowerCase();
    this[prop] = this.mask(group, this.options[prop]);
  }
}

/**
 * Filter the provided query object, removing keys that are not
 * allowed to exists on the query object.
 *
 * @param {Object} query Query object.
 * @param {String} restrict Operator group to further restrict allowed operators.
 * @return {Object} Filtered query object.
 * @api public
 */
Filter.prototype.filter = function filter(query, restrict) {
  if ('object' !== typeof query) return query;

  var groups = this.groups(restrict);

  /**
   * Create iterater.
   *
   * @param {String} key Operator.
   * @return {Function} Iterater against the key.
   * @api private
   */
  function iterate(context, key) {
    return function each(group) {
      if (!~context[group].indexOf(key)) delete query[key];
    }
  }

  for (var key in query) {
    if ('$' !== key[0]) continue;
    if ('object' === typeof query[key]) {
      this.filter(query[key]);
      continue;
    }

    groups.forEach(iterate(this, key));
  }

  return query;
};

/**
 * Enable certain operators by providing a bitmask against the group.
 *
 * @param {String} group Group of operators to check the bitmask against.
 * @param {Number} bitmask Binary mask.
 * @returns {Array} set of allowed operators.
 * @api public
 */
Filter.prototype.mask = function mask(group, bitmask) {
  if (!group || !bitmask) return [];
  var stack = '';

  for (var key in operators[group]) {
    if (~custom.indexOf(key)) continue;
    if (Filter[group][key] & bitmask) {
      stack += operators[group][key];
    }
  }

  return stack.split(',');
};

/**
 * Return the operator groups that have allowed operators,
 * optionally filtered by a group name.
 *
 * @param {String} restrict Optional group name to only return that group.
 * @return {Array} Set of group names.
 * @api public
 */
Filter.prototype.groups = function groups(restrict) {
  var filter = this;

  return Object.keys(operators).map(function lowercase(group) {
    group = group.toLowerCase();
    if (filter[group].length) return group;
  }).filter(function filter(group) {
    return restrict ? group === restrict : group;
  });
};

/**
 * Check if the operator is allowed for the group.
 *
 * @param {String} group Group the operator belongs to.
 * @param {String} key Operator name
 * @return {Boolean}
 * @api public
 */
Filter.prototype.allowed = function allowed(group, key) {
  key += key[0] !== '$' ? '$' : '';
  return !!~this[group].indexOf(key);
};

//
// Define bitmaps for all operators on the constructor.
//
for (var group in operators) {
  var i = 0;

  if ('object' !== typeof operators[group]) Filter[group] = 1 << i++;
  else for (var key in operators[group]) {
    Filter[group] = Filter[group] || Object.create(null);
    Filter[group][key] = 1 << i++;
  }

  Filter[group].ALL = (1 << i) - 1;
}

//
// Expose the module.
//
module.exports = Filter;<|endoftext|>


<commit_before>import React, {Component} from 'react'
import ReactNative, {StyleSheet, Text, View, ScrollView, Dimensions, TouchableOpacity, ViewPagerAndroid, Platform} from 'react-native'

class CardsView extends Component {
  constructor(props) {
    super(props);
    this.scrollView = null;
    this.state = {
      width: 0,
      height: 0,
      childDimensions: []
    }
  }

  onScroll (options) {
    if(this.props.onScroll) this.props.onScroll(options);
  }

  onSelectedCard (index) {
    if(this.props.onSelectedCard) this.props.onSelectedCard(index);
  }

  getCardIndex(offset, velocity) {
    const VELOCITY_SCALE  = 0.6;
    const velocityOffset = {x:0, y:0};

    const CUTOFF_MIN = 0.5;
    const CUTOFF_MAX = 1.7;

    if(velocity.x <= -CUTOFF_MAX) velocityOffset.x = -this.state.width;
    else if(velocity.x < -CUTOFF_MIN) velocityOffset.x = this.state.width * 0.5 * (velocity.x/CUTOFF_MAX);
    else if(velocity.x <= CUTOFF_MIN) velocityOffset.x = 0;
    else if(velocity.x < CUTOFF_MAX) velocityOffset.x = this.state.width * 0.5 * (velocity.x/CUTOFF_MAX);
    else velocityOffset.x = this.state.width;

    if(velocity.y <= -CUTOFF_MAX) velocityOffset.y = -this.state.height;
    else if(velocity.y < -CUTOFF_MIN) velocityOffset.y = -this.state.height * 0.5 * (velocity.y/CUTOFF_MAX);
    else if(velocity.y <= CUTOFF_MIN) velocityOffset.y = 0;
    else if(velocity.y < CUTOFF_MAX) velocityOffset.y = this.state.height * 0.5 * (velocity.y/CUTOFF_MAX);
    else velocityOffset.y = this.state.height;

    const center = {x:this.state.width * 0.5 + offset.x + velocityOffset.x, y: this.state.height * 0.5 + offset.y + velocityOffset.y};

    if(this.state.childDimensions) {
      if(this.props.horizontal && center.x < 0) return 0;
      else if(!this.props.horizontal && center.y < 0) return 0;

      for(var i = 0; i < this.state.childDimensions.length; i++) {
        const dimension = this.state.childDimensions[i];
        if(this.props.horizontal && center.x >= dimension.x && center.x < dimension.x + dimension.width) return i;
        if(!this.props.horizontal && center.y >= dimension.y && center.y < dimension.y + dimension.height) return i;
      }

      return this.state.childDimensions.length - 1;
    }
  }

  onScrollEndDrag(e) {
    const index = this.getCardIndex(e.nativeEvent.contentOffset, e.nativeEvent.velocity) ;

    const firstItemDim = this.state.childDimensions[0];
    const dimension = this.state.childDimensions[index];
    const x = dimension.x + (dimension.width - firstItemDim.width)/2;
    const y = dimension.y + (dimension.height - firstItemDim.height)/2;

    if(this.props.horizontal) this.scrollView.scrollTo({x});
    else this.scrollView.scrollTo({y});

    this.onSelectedCard(index);
  }

  getCardWidth(child, layoutWidth, layoutHeight) {
    if(child == null) return layoutWidth;
    if(child.props.cardWidth == null) return layoutWidth;
    if(child.props.cardWidth instanceof Function) {
      return parseFloat(child.props.cardWidth({width: layoutWidth, height: layoutHeight}));
    } else {
      return parseFloat(child.props.cardWidth)
    }
  }

  getCardHeight(child, layoutWidth, layoutHeight) {
    if(child == null) return layoutHeight;
    if(child.props.cardHeight == null) return layoutHeight;
    if(child.props.cardHeight instanceof Function) {
      return parseFloat(child.props.cardHeight({width: layoutWidth, height: layoutHeight}));
    } else {
      return parseFloat(child.props.cardHeight)
    }
  }

  onLayout(e) {
    const layoutWidth = e.nativeEvent.layout.width || 0;
    const layoutHeight = e.nativeEvent.layout.height || 0;

    let dimAcc = {x:0, y:0};
    const childDimensions = this.props.children && this.props.children.map( (child, i) => {
      const width = this.getCardWidth(child, layoutWidth, layoutHeight);
      const height = this.getCardHeight(child, layoutWidth, layoutHeight);
      const x = dimAcc.x;
      const y = dimAcc.y;
      dimAcc.x += width;
      dimAcc.y += height;
      return {width, height, x, y}
    });

    this.setState({ width: layoutWidth, height: layoutHeight, childDimensions })
  }

  render() {
    const children = this.props.children.map( (child, i) => {
      const dimensions = this.state.childDimensions[i];
      var st = {};
      if(dimensions && dimensions.width) st.width = dimensions.width;
      if(dimensions && dimensions.height) st.height = dimensions.height;
      return <View style={st} key={i}>{child}</View>
    })
    const paddingLeft = this.state.childDimensions && this.state.childDimensions[0] && this.state.childDimensions[0].width? (this.state.width - this.state.childDimensions[0].width)/2: 0
    const paddingRight = this.state.childDimensions && this.state.childDimensions[this.state.childDimensions.length - 1] && this.state.childDimensions[this.state.childDimensions.length - 1].width? (this.state.width - this.state.childDimensions[this.state.childDimensions.length - 1].width)/2 :0

    const paddingTop = this.state.childDimensions && this.state.childDimensions[0] && this.state.childDimensions[0].height? (this.state.height - this.state.childDimensions[0].height)/2: 0
    const paddingBottom = this.state.childDimensions && this.state.childDimensions[this.state.childDimensions.length - 1] && this.state.childDimensions[this.state.childDimensions.length - 1].height? (this.state.height - this.state.childDimensions[this.state.childDimensions.length - 1].height)/2 :0

    return <ScrollView
      ref={(scrollView) => { this.scrollView = scrollView; }}
      onScrollEndDrag={this.onScrollEndDrag.bind(this)}
      onScroll={this.onScroll.bind(this)}
      scrollEventThrottle={this.props.scrollEventThrottle}
      horizontal={this.props.horizontal}
      onLayout={this.onLayout.bind(this)}
      contentContainerStyle={{paddingLeft, paddingRight, paddingTop, paddingBottom}}
      {...this.props}>
      {children}
  </ScrollView>
  }
}

CardsView.defaultProps = {
  horizontal : true,
  scrollEventThrottle: 100,
  showsHorizontalScrollIndicator: false,
  showsVerticalScrollIndicator: false,
}

CardsView.propTypes = {
  horizontal : React.PropTypes.bool,
  scrollEventThrottle: React.PropTypes.number,
  cardWidth: React.PropTypes.oneOfType([React.PropTypes.func, React.PropTypes.number]),
  cardHeight: React.PropTypes.oneOfType([React.PropTypes.func, React.PropTypes.number]),
  onSelectedCard: React.PropTypes.func,
  showsHorizontalScrollIndicator: React.PropTypes.bool,
  showsVerticalScrollIndicator: React.PropTypes.bool,
}

export default CardsView;
<commit_msg>added stuff<commit_after>import React, {Component} from 'react'
import ReactNative, {StyleSheet, Text, View, ScrollView, Dimensions, TouchableOpacity, ViewPagerAndroid, Platform} from 'react-native'

class CardsView extends Component {
  constructor(props) {
    super(props);
    this.scrollView = null;
    this.state = {
      width: 0,
      height: 0,
      childDimensions: []
    }
  }

  onScroll (options) {
    if(this.props.onScroll) this.props.onScroll(options);
  }

  onSelectedCard (index) {
    if(this.props.onSelectedCard) this.props.onSelectedCard(index);
  }

  getCardIndex(offset, velocity) {
    const VELOCITY_SCALE  = 0.6;
    const velocityOffset = {x:0, y:0};

    const CUTOFF_MIN = 0.5;
    const CUTOFF_MAX = 1.7;

    if(velocity.x <= -CUTOFF_MAX) velocityOffset.x = -this.state.width;
    else if(velocity.x < -CUTOFF_MIN) velocityOffset.x = this.state.width * 0.5 * (velocity.x/CUTOFF_MAX);
    else if(velocity.x <= CUTOFF_MIN) velocityOffset.x = 0;
    else if(velocity.x < CUTOFF_MAX) velocityOffset.x = this.state.width * 0.5 * (velocity.x/CUTOFF_MAX);
    else velocityOffset.x = this.state.width;

    if(velocity.y <= -CUTOFF_MAX) velocityOffset.y = -this.state.height;
    else if(velocity.y < -CUTOFF_MIN) velocityOffset.y = -this.state.height * 0.5 * (velocity.y/CUTOFF_MAX);
    else if(velocity.y <= CUTOFF_MIN) velocityOffset.y = 0;
    else if(velocity.y < CUTOFF_MAX) velocityOffset.y = this.state.height * 0.5 * (velocity.y/CUTOFF_MAX);
    else velocityOffset.y = this.state.height;

    const center = {x:this.state.width * 0.5 + offset.x + velocityOffset.x, y: this.state.height * 0.5 + offset.y + velocityOffset.y};

    if(this.state.childDimensions) {
      if(this.props.horizontal && center.x < 0) return 0;
      else if(!this.props.horizontal && center.y < 0) return 0;

      for(var i = 0; i < this.state.childDimensions.length; i++) {
        const dimension = this.state.childDimensions[i];
        if(this.props.horizontal && center.x >= dimension.x && center.x < dimension.x + dimension.width) return i;
        if(!this.props.horizontal && center.y >= dimension.y && center.y < dimension.y + dimension.height) return i;
      }

      return this.state.childDimensions.length - 1;
    }
  }

  onScrollEndDrag(e) {
    const index = this.getCardIndex(e.nativeEvent.contentOffset, e.nativeEvent.velocity) ;

    const firstItemDim = this.state.childDimensions[0];
    const dimension = this.state.childDimensions[index];
    const x = dimension.x + (dimension.width - firstItemDim.width)/2;
    const y = dimension.y + (dimension.height - firstItemDim.height)/2;

    if(this.props.horizontal) this.scrollView.scrollTo({x});
    else this.scrollView.scrollTo({y});

    this.onSelectedCard(index);
  }

  getCardWidth(child, layoutWidth, layoutHeight) {
    if(child == null) return layoutWidth;
    if(child.props.cardWidth == null) return layoutWidth;
    if(child.props.cardWidth instanceof Function) {
      return parseFloat(child.props.cardWidth({width: layoutWidth, height: layoutHeight}));
    } else {
      return parseFloat(child.props.cardWidth)
    }
  }

  getCardHeight(child, layoutWidth, layoutHeight) {
    if(child == null) return layoutHeight;
    if(child.props.cardHeight == null) return layoutHeight;
    if(child.props.cardHeight instanceof Function) {
      return parseFloat(child.props.cardHeight({width: layoutWidth, height: layoutHeight}));
    } else {
      return parseFloat(child.props.cardHeight)
    }
  }

  onLayout(e) {
    const layoutWidth = e.nativeEvent.layout.width || 0;
    const layoutHeight = e.nativeEvent.layout.height || 0;

    let dimAcc = {x:0, y:0};
    const childDimensions = this.props.children && this.props.children.map( (child, i) => {
      const width = this.getCardWidth(child, layoutWidth, layoutHeight);
      const height = this.getCardHeight(child, layoutWidth, layoutHeight);
      const x = dimAcc.x;
      const y = dimAcc.y;
      dimAcc.x += width;
      dimAcc.y += height;
      return {width, height, x, y}
    });

    this.setState({ width: layoutWidth, height: layoutHeight, childDimensions })
  }

  render() {
    const children = this.props.children.map( (child, i) => {
      const dimensions = this.state.childDimensions[i];
      var st = {};
      if(dimensions && dimensions.width) st.width = dimensions.width;
      if(dimensions && dimensions.height) st.height = dimensions.height;
      return <View style={st} key={i}>{child}</View>
    })
    const paddingLeft = this.state.childDimensions && this.state.childDimensions[0] && this.state.childDimensions[0].width? (this.state.width - this.state.childDimensions[0].width)/2: 0
    const paddingRight = this.state.childDimensions && this.state.childDimensions[this.state.childDimensions.length - 1] && this.state.childDimensions[this.state.childDimensions.length - 1].width? (this.state.width - this.state.childDimensions[this.state.childDimensions.length - 1].width)/2 :0

    const paddingTop = this.state.childDimensions && this.state.childDimensions[0] && this.state.childDimensions[0].height? (this.state.height - this.state.childDimensions[0].height)/2: 0
    const paddingBottom = this.state.childDimensions && this.state.childDimensions[this.state.childDimensions.length - 1] && this.state.childDimensions[this.state.childDimensions.length - 1].height? (this.state.height - this.state.childDimensions[this.state.childDimensions.length - 1].height)/2 :0

    return <ScrollView
      {...this.props}
      ref={(scrollView) => { this.scrollView = scrollView; }}
      onScrollEndDrag={this.onScrollEndDrag.bind(this)}
      onScroll={this.onScroll.bind(this)}
      scrollEventThrottle={this.props.scrollEventThrottle}
      horizontal={this.props.horizontal}
      onLayout={this.onLayout.bind(this)}
      contentContainerStyle={[{paddingLeft, paddingRight, paddingTop, paddingBottom}, this.props.contentContainerStyle]}>
      {children}
  </ScrollView>
  }
}

CardsView.defaultProps = {
  horizontal : true,
  scrollEventThrottle: 100,
  showsHorizontalScrollIndicator: false,
  showsVerticalScrollIndicator: false,
}

CardsView.propTypes = {
  horizontal : React.PropTypes.bool,
  scrollEventThrottle: React.PropTypes.number,
  cardWidth: React.PropTypes.oneOfType([React.PropTypes.func, React.PropTypes.number]),
  cardHeight: React.PropTypes.oneOfType([React.PropTypes.func, React.PropTypes.number]),
  onSelectedCard: React.PropTypes.func,
  showsHorizontalScrollIndicator: React.PropTypes.bool,
  showsVerticalScrollIndicator: React.PropTypes.bool,
}

export default CardsView;
<|endoftext|>


<commit_before>// Karma configuration
// Generated on Fri May 29 2015 22:58:29 GMT-0700 (PDT)
'use strict';
module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
        'dist/src/vendor.js',
        'vendor/angular-mocks/angular-mocks.js',
        'dist/src/constellation-app.js',
        'client/app/**/*.spec.js'
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['PhantomJS'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false
  });
};
<commit_msg>(fix) Delete file<commit_after><|endoftext|>


<commit_before>'use strict';

module.exports = {
	parserOptions: {
		ecmaVersion: 2020,
		sourceType: 'module',
		ecmaFeatures: {
			jsx: true
		}
	},
	env: {
		node: true,
		es6: true
	},
	reportUnusedDisableDirectives: true,
	rules: {
		'comma-dangle': [
			'error',
			'never'
		],
		'for-direction': 'error',
		'getter-return': 'error',
		'no-async-promise-executor': 'error',
		'no-await-in-loop': 'error',
		'no-compare-neg-zero': 'error',
		'no-cond-assign': 'error',
		'no-constant-condition': 'error',
		'no-control-regex': 'error',
		'no-debugger': 'error',
		'no-dupe-args': 'error',
		'no-dupe-keys': 'error',
		'no-duplicate-case': 'error',
		'no-empty-character-class': 'error',
		'no-empty': [
			'error',
			{
				allowEmptyCatch: true
			}
		],
		'no-ex-assign': 'error',
		'no-extra-boolean-cast': 'error',
		// Disabled because of https://github.com/eslint/eslint/issues/6028
		// 'no-extra-parens': [
		// 	'error',
		// 	'all',
		// 	{
		// 		conditionalAssign: false,
		// 		nestedBinaryExpressions: false,
		// 		ignoreJSX: 'multi-line'
		// 	}
		// ],
		'no-extra-semi': 'error',
		'no-func-assign': 'error',
		'no-import-assign': 'error',
		'no-inner-declarations': 'error',
		'no-invalid-regexp': 'error',
		'no-irregular-whitespace': 'error',
		'no-misleading-character-class': 'error',
		'no-obj-calls': 'error',
		'no-prototype-builtins': 'error',
		'no-regex-spaces': 'error',
		'no-sparse-arrays': 'error',
		'no-template-curly-in-string': 'error',
		'no-unreachable': 'error',
		'no-unsafe-finally': 'error',
		'no-unsafe-negation': 'error',
		'require-atomic-updates': 'error',
		'use-isnan': 'error',
		'valid-typeof': [
			'error',
			{
				requireStringLiterals: false
			}
		],
		'no-unexpected-multiline': 'error',
		'accessor-pairs': 'error',
		'array-callback-return': 'error',
		'block-scoped-var': 'error',
		complexity: 'warn',
		curly: 'error',
		'default-case': 'error',
		'dot-notation': 'error',
		'dot-location': [
			'error',
			'property'
		],
		eqeqeq: 'error',
		'guard-for-in': 'error',
		'no-alert': 'error',
		'no-caller': 'error',
		'no-case-declarations': 'error',
		'no-else-return': [
			'error',
			{
				allowElseIf: false
			}
		],
		'no-empty-pattern': 'error',
		'no-eq-null': 'error',
		'no-eval': 'error',
		'no-extend-native': 'error',
		'no-extra-bind': 'error',
		'no-extra-label': 'error',
		'no-fallthrough': 'error',
		'no-floating-decimal': 'error',
		'no-global-assign': 'error',
		'no-implicit-coercion': 'error',
		'no-implicit-globals': 'error',
		'no-implied-eval': 'error',
		'no-iterator': 'error',
		'no-labels': 'error',
		'no-lone-blocks': 'error',
		'no-multi-spaces': 'error',
		'no-multi-str': 'error',
		'no-new-func': 'error',
		'no-new-wrappers': 'error',
		'no-new': 'error',
		'no-octal-escape': 'error',
		'no-octal': 'error',
		'no-proto': 'error',
		'no-redeclare': 'error',
		'no-return-assign': [
			'error',
			'always'
		],
		'no-return-await': 'error',
		'no-script-url': 'error',
		'no-self-assign': [
			'error',
			{
				props: true
			}
		],
		'no-self-compare': 'error',
		'no-sequences': 'error',
		'no-throw-literal': 'error',
		'no-unmodified-loop-condition': 'error',
		'no-unused-expressions': 'error',
		'no-unused-labels': 'error',
		'no-useless-call': 'error',
		'no-useless-concat': 'error',
		'no-useless-escape': 'error',
		'no-useless-return': 'error',
		'no-void': 'error',
		'no-warning-comments': 'warn',
		'no-with': 'error',
		'prefer-promise-reject-errors': [
			'error',
			{
				allowEmptyReject: true
			}
		],
		'prefer-regex-literals': 'error',
		radix: 'error',

		// Disabled for now as it causes too much churn
		// TODO: Enable it in the future when I have time to deal with
		// the churn and the rule is stable and has an autofixer
		// 'require-unicode-regexp': 'error',

		'wrap-iife': [
			'error',
			'inside',
			{
				functionPrototypeMethods: true
			}
		],
		yoda: 'error',
		'no-delete-var': 'error',
		'no-label-var': 'error',
		'no-restricted-globals': [
			'error',
			'event'
		],
		'no-shadow-restricted-names': 'error',
		'no-undef-init': 'error',
		'no-undef': [
			'error',
			{
				typeof: true
			}
		],
		'no-unused-vars': [
			'error',
			{
				vars: 'all',
				args: 'after-used',
				ignoreRestSiblings: true,
				argsIgnorePattern: '^_$',
				caughtErrors: 'all',
				caughtErrorsIgnorePattern: '^_$'
			}
		],
		'handle-callback-err': 'warn',
		'no-buffer-constructor': 'error',
		'no-mixed-requires': [
			'error',
			{
				grouping: true,
				allowCall: true
			}
		],
		'no-new-require': 'error',
		'no-path-concat': 'error',
		'no-restricted-imports': [
			'error',
			'domain',
			'freelist',
			'smalloc',
			'sys',
			'colors'
		],
		'no-restricted-modules': [
			'error',
			'domain',
			'freelist',
			'smalloc',
			'sys',
			'colors'
		],
		'array-bracket-newline': [
			'error',
			'consistent'
		],
		'array-bracket-spacing': [
			'error',
			'never'
		],
		'array-element-newline': [
			'error',
			'consistent'
		],
		'brace-style': [
			'error',
			'1tbs',
			{
				allowSingleLine: false
			}
		],
		camelcase: [
			'error',
			{
				properties: 'always'
			}
		],
		'capitalized-comments': [
			'error',
			'always',
			{
				// You can also ignore this rule by wrapping the first word in quotes
				ignorePattern: 'pragma|ignore|prettier-ignore',
				ignoreInlineComments: true,
				ignoreConsecutiveComments: true
			}
		],
		'comma-spacing': [
			'error',
			{
				before: false,
				after: true
			}
		],
		'comma-style': [
			'error',
			'last'
		],
		'computed-property-spacing': [
			'error',
			'never'
		],
		'eol-last': 'error',
		'func-call-spacing': [
			'error',
			'never'
		],
		'func-name-matching': [
			'error',
			{
				considerPropertyDescriptor: true
			}
		],
		'func-names': [
			'error',
			'never'
		],
		'function-call-argument-newline': [
			'error',
			'consistent'
		],
		indent: [
			'error',
			'tab',
			{
				SwitchCase: 1
			}
		],
		'jsx-quotes': 'error',
		'key-spacing': [
			'error',
			{
				beforeColon: false,
				afterColon: true
			}
		],
		'keyword-spacing': 'error',
		'linebreak-style': [
			process.platform === 'win32' ? 'off' : 'error',
			'unix'
		],
		'lines-between-class-members': [
			'error',
			'always'
		],
		'max-depth': 'warn',
		'max-nested-callbacks': [
			'warn',
			4
		],
		'max-params': [
			'warn',
			{
				max: 4
			}
		],
		'max-statements-per-line': 'error',
		'new-cap': [
			'error',
			{
				newIsCap: true,
				capIsNew: true
			}
		],
		'new-parens': 'error',
		'no-array-constructor': 'error',
		'no-lonely-if': 'error',
		'no-mixed-operators': 'error',
		'no-mixed-spaces-and-tabs': 'error',
		'no-multi-assign': 'error',
		'no-multiple-empty-lines': [
			'error',
			{
				max: 1
			}
		],
		'no-negated-condition': 'error',
		'no-new-object': 'error',
		'no-restricted-syntax': [
			'error',
			'WithStatement'
		],
		'no-whitespace-before-property': 'error',
		'no-trailing-spaces': 'error',
		'no-unneeded-ternary': 'error',
		'object-curly-spacing': [
			'error',
			'never'
		],
		// Disabled because of https://github.com/xojs/eslint-config-xo/issues/27
		// 'object-property-newline': 'error',
		'one-var': [
			'error',
			'never'
		],
		'one-var-declaration-per-line': 'error',
		'operator-assignment': [
			'error',
			'always'
		],
		'operator-linebreak': [
			'error',
			'after'
		],
		'padded-blocks': [
			'error',
			'never',
			{
				allowSingleLineBlocks: false
			}
		],
		'padding-line-between-statements': [
			'error',
			{
				blankLine: 'always',
				prev: 'multiline-block-like',
				next: '*'
			}
		],
		'quote-props': [
			'error',
			'as-needed'
		],
		quotes: [
			'error',
			'single'
		],
		'semi-spacing': [
			'error',
			{
				before: false,
				after: true
			}
		],
		'semi-style': [
			'error',
			'last'
		],
		semi: [
			'error',
			'always'
		],
		'space-before-blocks': [
			'error',
			'always'
		],
		'space-before-function-paren': [
			'error',
			{
				anonymous: 'always',
				named: 'never',
				asyncArrow: 'always'
			}
		],
		'space-in-parens': [
			'error',
			'never'
		],
		'space-infix-ops': 'error',
		'space-unary-ops': 'error',
		'spaced-comment': [
			'error',
			'always',
			{
				line: {
					exceptions: [
						'-',
						'+',
						'*'
					],
					markers: [
						'!',
						'/',
						'=>'
					]
				},
				block: {
					exceptions: [
						'-',
						'+',
						'*'
					],
					markers: [
						'!',
						'*'
					],
					balanced: true
				}
			}
		],
		'switch-colon-spacing': [
			'error',
			{
				after: true,
				before: false
			}
		],
		'template-tag-spacing': [
			'error',
			'never'
		],
		'unicode-bom': [
			'error',
			'never'
		],
		'arrow-parens': [
			'error',
			'as-needed'
		],
		'arrow-spacing': [
			'error',
			{
				before: true,
				after: true
			}
		],
		'constructor-super': 'error',
		'generator-star-spacing': [
			'error',
			'both'
		],
		'no-class-assign': 'error',
		'no-const-assign': 'error',
		'no-dupe-class-members': 'error',
		'no-new-symbol': 'error',
		'no-this-before-super': 'error',
		'no-useless-computed-key': 'error',
		'no-useless-constructor': 'error',
		'no-useless-rename': 'error',
		'require-yield': 'error',
		'rest-spread-spacing': [
			'error',
			'never'
		],
		'symbol-description': 'error',
		'template-curly-spacing': 'error',
		'yield-star-spacing': [
			'error',
			'both'
		]
	}
};
<commit_msg>Add `default-param-last` rule<commit_after>'use strict';

module.exports = {
	parserOptions: {
		ecmaVersion: 2020,
		sourceType: 'module',
		ecmaFeatures: {
			jsx: true
		}
	},
	env: {
		node: true,
		es6: true
	},
	reportUnusedDisableDirectives: true,
	rules: {
		'comma-dangle': [
			'error',
			'never'
		],
		'for-direction': 'error',
		'getter-return': 'error',
		'no-async-promise-executor': 'error',
		'no-await-in-loop': 'error',
		'no-compare-neg-zero': 'error',
		'no-cond-assign': 'error',
		'no-constant-condition': 'error',
		'no-control-regex': 'error',
		'no-debugger': 'error',
		'no-dupe-args': 'error',
		'no-dupe-keys': 'error',
		'no-duplicate-case': 'error',
		'no-empty-character-class': 'error',
		'no-empty': [
			'error',
			{
				allowEmptyCatch: true
			}
		],
		'no-ex-assign': 'error',
		'no-extra-boolean-cast': 'error',
		// Disabled because of https://github.com/eslint/eslint/issues/6028
		// 'no-extra-parens': [
		// 	'error',
		// 	'all',
		// 	{
		// 		conditionalAssign: false,
		// 		nestedBinaryExpressions: false,
		// 		ignoreJSX: 'multi-line'
		// 	}
		// ],
		'no-extra-semi': 'error',
		'no-func-assign': 'error',
		'no-import-assign': 'error',
		'no-inner-declarations': 'error',
		'no-invalid-regexp': 'error',
		'no-irregular-whitespace': 'error',
		'no-misleading-character-class': 'error',
		'no-obj-calls': 'error',
		'no-prototype-builtins': 'error',
		'no-regex-spaces': 'error',
		'no-sparse-arrays': 'error',
		'no-template-curly-in-string': 'error',
		'no-unreachable': 'error',
		'no-unsafe-finally': 'error',
		'no-unsafe-negation': 'error',
		'require-atomic-updates': 'error',
		'use-isnan': 'error',
		'valid-typeof': [
			'error',
			{
				requireStringLiterals: false
			}
		],
		'no-unexpected-multiline': 'error',
		'accessor-pairs': 'error',
		'array-callback-return': 'error',
		'block-scoped-var': 'error',
		complexity: 'warn',
		curly: 'error',
		'default-case': 'error',
		'default-param-last': 'error',
		'dot-notation': 'error',
		'dot-location': [
			'error',
			'property'
		],
		eqeqeq: 'error',
		'guard-for-in': 'error',
		'no-alert': 'error',
		'no-caller': 'error',
		'no-case-declarations': 'error',
		'no-else-return': [
			'error',
			{
				allowElseIf: false
			}
		],
		'no-empty-pattern': 'error',
		'no-eq-null': 'error',
		'no-eval': 'error',
		'no-extend-native': 'error',
		'no-extra-bind': 'error',
		'no-extra-label': 'error',
		'no-fallthrough': 'error',
		'no-floating-decimal': 'error',
		'no-global-assign': 'error',
		'no-implicit-coercion': 'error',
		'no-implicit-globals': 'error',
		'no-implied-eval': 'error',
		'no-iterator': 'error',
		'no-labels': 'error',
		'no-lone-blocks': 'error',
		'no-multi-spaces': 'error',
		'no-multi-str': 'error',
		'no-new-func': 'error',
		'no-new-wrappers': 'error',
		'no-new': 'error',
		'no-octal-escape': 'error',
		'no-octal': 'error',
		'no-proto': 'error',
		'no-redeclare': 'error',
		'no-return-assign': [
			'error',
			'always'
		],
		'no-return-await': 'error',
		'no-script-url': 'error',
		'no-self-assign': [
			'error',
			{
				props: true
			}
		],
		'no-self-compare': 'error',
		'no-sequences': 'error',
		'no-throw-literal': 'error',
		'no-unmodified-loop-condition': 'error',
		'no-unused-expressions': 'error',
		'no-unused-labels': 'error',
		'no-useless-call': 'error',
		'no-useless-concat': 'error',
		'no-useless-escape': 'error',
		'no-useless-return': 'error',
		'no-void': 'error',
		'no-warning-comments': 'warn',
		'no-with': 'error',
		'prefer-promise-reject-errors': [
			'error',
			{
				allowEmptyReject: true
			}
		],
		'prefer-regex-literals': 'error',
		radix: 'error',

		// Disabled for now as it causes too much churn
		// TODO: Enable it in the future when I have time to deal with
		// the churn and the rule is stable and has an autofixer
		// 'require-unicode-regexp': 'error',

		'wrap-iife': [
			'error',
			'inside',
			{
				functionPrototypeMethods: true
			}
		],
		yoda: 'error',
		'no-delete-var': 'error',
		'no-label-var': 'error',
		'no-restricted-globals': [
			'error',
			'event'
		],
		'no-shadow-restricted-names': 'error',
		'no-undef-init': 'error',
		'no-undef': [
			'error',
			{
				typeof: true
			}
		],
		'no-unused-vars': [
			'error',
			{
				vars: 'all',
				args: 'after-used',
				ignoreRestSiblings: true,
				argsIgnorePattern: '^_$',
				caughtErrors: 'all',
				caughtErrorsIgnorePattern: '^_$'
			}
		],
		'handle-callback-err': 'warn',
		'no-buffer-constructor': 'error',
		'no-mixed-requires': [
			'error',
			{
				grouping: true,
				allowCall: true
			}
		],
		'no-new-require': 'error',
		'no-path-concat': 'error',
		'no-restricted-imports': [
			'error',
			'domain',
			'freelist',
			'smalloc',
			'sys',
			'colors'
		],
		'no-restricted-modules': [
			'error',
			'domain',
			'freelist',
			'smalloc',
			'sys',
			'colors'
		],
		'array-bracket-newline': [
			'error',
			'consistent'
		],
		'array-bracket-spacing': [
			'error',
			'never'
		],
		'array-element-newline': [
			'error',
			'consistent'
		],
		'brace-style': [
			'error',
			'1tbs',
			{
				allowSingleLine: false
			}
		],
		camelcase: [
			'error',
			{
				properties: 'always'
			}
		],
		'capitalized-comments': [
			'error',
			'always',
			{
				// You can also ignore this rule by wrapping the first word in quotes
				ignorePattern: 'pragma|ignore|prettier-ignore',
				ignoreInlineComments: true,
				ignoreConsecutiveComments: true
			}
		],
		'comma-spacing': [
			'error',
			{
				before: false,
				after: true
			}
		],
		'comma-style': [
			'error',
			'last'
		],
		'computed-property-spacing': [
			'error',
			'never'
		],
		'eol-last': 'error',
		'func-call-spacing': [
			'error',
			'never'
		],
		'func-name-matching': [
			'error',
			{
				considerPropertyDescriptor: true
			}
		],
		'func-names': [
			'error',
			'never'
		],
		'function-call-argument-newline': [
			'error',
			'consistent'
		],
		indent: [
			'error',
			'tab',
			{
				SwitchCase: 1
			}
		],
		'jsx-quotes': 'error',
		'key-spacing': [
			'error',
			{
				beforeColon: false,
				afterColon: true
			}
		],
		'keyword-spacing': 'error',
		'linebreak-style': [
			process.platform === 'win32' ? 'off' : 'error',
			'unix'
		],
		'lines-between-class-members': [
			'error',
			'always'
		],
		'max-depth': 'warn',
		'max-nested-callbacks': [
			'warn',
			4
		],
		'max-params': [
			'warn',
			{
				max: 4
			}
		],
		'max-statements-per-line': 'error',
		'new-cap': [
			'error',
			{
				newIsCap: true,
				capIsNew: true
			}
		],
		'new-parens': 'error',
		'no-array-constructor': 'error',
		'no-lonely-if': 'error',
		'no-mixed-operators': 'error',
		'no-mixed-spaces-and-tabs': 'error',
		'no-multi-assign': 'error',
		'no-multiple-empty-lines': [
			'error',
			{
				max: 1
			}
		],
		'no-negated-condition': 'error',
		'no-new-object': 'error',
		'no-restricted-syntax': [
			'error',
			'WithStatement'
		],
		'no-whitespace-before-property': 'error',
		'no-trailing-spaces': 'error',
		'no-unneeded-ternary': 'error',
		'object-curly-spacing': [
			'error',
			'never'
		],
		// Disabled because of https://github.com/xojs/eslint-config-xo/issues/27
		// 'object-property-newline': 'error',
		'one-var': [
			'error',
			'never'
		],
		'one-var-declaration-per-line': 'error',
		'operator-assignment': [
			'error',
			'always'
		],
		'operator-linebreak': [
			'error',
			'after'
		],
		'padded-blocks': [
			'error',
			'never',
			{
				allowSingleLineBlocks: false
			}
		],
		'padding-line-between-statements': [
			'error',
			{
				blankLine: 'always',
				prev: 'multiline-block-like',
				next: '*'
			}
		],
		'quote-props': [
			'error',
			'as-needed'
		],
		quotes: [
			'error',
			'single'
		],
		'semi-spacing': [
			'error',
			{
				before: false,
				after: true
			}
		],
		'semi-style': [
			'error',
			'last'
		],
		semi: [
			'error',
			'always'
		],
		'space-before-blocks': [
			'error',
			'always'
		],
		'space-before-function-paren': [
			'error',
			{
				anonymous: 'always',
				named: 'never',
				asyncArrow: 'always'
			}
		],
		'space-in-parens': [
			'error',
			'never'
		],
		'space-infix-ops': 'error',
		'space-unary-ops': 'error',
		'spaced-comment': [
			'error',
			'always',
			{
				line: {
					exceptions: [
						'-',
						'+',
						'*'
					],
					markers: [
						'!',
						'/',
						'=>'
					]
				},
				block: {
					exceptions: [
						'-',
						'+',
						'*'
					],
					markers: [
						'!',
						'*'
					],
					balanced: true
				}
			}
		],
		'switch-colon-spacing': [
			'error',
			{
				after: true,
				before: false
			}
		],
		'template-tag-spacing': [
			'error',
			'never'
		],
		'unicode-bom': [
			'error',
			'never'
		],
		'arrow-parens': [
			'error',
			'as-needed'
		],
		'arrow-spacing': [
			'error',
			{
				before: true,
				after: true
			}
		],
		'constructor-super': 'error',
		'generator-star-spacing': [
			'error',
			'both'
		],
		'no-class-assign': 'error',
		'no-const-assign': 'error',
		'no-dupe-class-members': 'error',
		'no-new-symbol': 'error',
		'no-this-before-super': 'error',
		'no-useless-computed-key': 'error',
		'no-useless-constructor': 'error',
		'no-useless-rename': 'error',
		'require-yield': 'error',
		'rest-spread-spacing': [
			'error',
			'never'
		],
		'symbol-description': 'error',
		'template-curly-spacing': 'error',
		'yield-star-spacing': [
			'error',
			'both'
		]
	}
};
<|endoftext|>


<commit_before><commit_msg>Add basic karma.conf.js<commit_after>module.exports = function(config) {
  config.set({

    // frameworks to use
    frameworks: ['jasmine'],

    files: [
      'bower_components/angular/angular.js',
      'bower_components/angular-mocks/angular-mocks.js',
      'bower_components/angular-sanitize/angular-sanitize.js',

      'bower_components/i18next/i18next.js',

      'test/bind-polyfill.js', // For Jasmine

      'i18ng.js',
      'test/i18ng-test.js',
    ],

    reporters: ['progress', 'coverage'],

    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    browsers: ['Chrome', 'Firefox', 'PhantomJS'],

    // If browser does not capture in given timeout [ms], kill it
    captureTimeout: 60000,

    singleRun: false // Continuous Integration mode
  });
};
<|endoftext|>


<commit_before>'use strict';

var template = require('./template.marko');

function buildModel(input) {
    input = input || {};
    input.score = input.score || 0;
    var score = (Math.round(input.score * 4) / 4).toFixed(2); // round to quarter
    var scoreString = score + '';
    var stars = ['', '', '', '', ''];
    var starClass;
    var starType;

    stars.forEach(function (val, i) {
        starClass = 'star-rating-marko__icon';
        if (score >= i + 1) {
            starType = 'full';
        } else if (score - i < 1 && score - i > 0) {
            starType = 'quarter';
            if (scoreString.includes('.75')) {
                starType = 'three-quarters';
            } else if (scoreString.includes('.50')) {
                starType = 'half';
            }
        }
        if (starType) {
            starClass += ' star-rating-marko__icon--' + starType;
            starClass += ' star-rating-marko__icon--active';
        }
        stars[i] = starClass;
    });

    return {
        stars: stars
    };
}

module.exports = function render(input, out) {
    template.render(buildModel(input), out);
};
<commit_msg>reset starType per star<commit_after>'use strict';

var template = require('./template.marko');

function buildModel(input) {
    input = input || {};
    input.score = input.score || 0;
    var score = (Math.round(input.score * 4) / 4).toFixed(2); // round to quarter
    var scoreString = score + '';
    var stars = ['', '', '', '', ''];
    var starClass;
    var starType;

    stars.forEach(function (val, i) {
        starClass = 'star-rating-marko__icon';
        starType = '';

        if (score >= i + 1) {
            starType = 'full';
        }

        if (score - i < 1 && score - i > 0) {
            starType = 'quarter';
            if (scoreString.includes('.75')) {
                starType = 'three-quarters';
            } else if (scoreString.includes('.50')) {
                starType = 'half';
            }
        }

        if (starType) {
            starClass += ' star-rating-marko__icon--' + starType;
            starClass += ' star-rating-marko__icon--active';
        }

        stars[i] = starClass;
    });

    return {
        stars: stars
    };
}

module.exports = function render(input, out) {
    template.render(buildModel(input), out);
};
<|endoftext|>


<commit_before>var PLAYGROUND_WIDTH = 600;
var NUMBER_OF_SQUARE = 17;
var NUMBER_OF_PLAYGROUND_LINE = PLAYGROUND_WIDTH / NUMBER_OF_SQUARE;

var CHARACTER_PARAMETER = [
  {
    "name": "daisyo",
    "cost": 1,
    "hitPoint": 3,
    "attack": 1,
    "attacableRange": 2,
    "move": 1
  },
  {
    "name": "pupepon",
    "cost": 3,
    "hitPoint": 7,
    "attack": 3,
    "attacableRange": 2,
    "move": 3
  },
  {
    "name": "haseaki",
    "cost": 2,
    "hitPoint": 3,
    "attack": 2,
    "attacableRange": 2,
    "move": 2
  },
  {
    "name": "miho",
    "cost": 5,
    "hitPoint": 8,
    "attack": 3,
    "attacableRange": 2,
    "move": 2
  }
]

// Declarations
var selectX = -1;
var selectY = -1;

$(function(){
  /* canvas */
  playGround = $("#play-ground").get(0);
  ctxCanvas  = playGround.getContext("2d");

  // クリック処理
  var canvasPosition = $('#play-ground').position();

  $('#play-ground').click(function(e) {
    /*
    (selectY, selectX)
    */
    selectX = e.pageX - canvasPosition.left;
    selectY = e.pageY - canvasPosition.top;

    console.log(Math.floor(selectY / NUMBER_OF_PLAYGROUND_LINE) + "," + Math.floor(selectX / NUMBER_OF_PLAYGROUND_LINE));

  });

  console.log(CHARACTER_PARAMETER[3].name);

  /* Load function */
  drawField();

});

function drawField(){
  var i;

  for (i=0; i<=17;i++) {
    if (i === 0 || i === NUMBER_OF_SQUARE) {
      ctxCanvas.beginPath();
      ctxCanvas.lineWidth = 10.0;
    } else {
      ctxCanvas.beginPath();
      ctxCanvas.lineWidth = 1.0;
    }
    ctxCanvas.moveTo(i * NUMBER_OF_PLAYGROUND_LINE, 0);
    ctxCanvas.lineTo(i * NUMBER_OF_PLAYGROUND_LINE, PLAYGROUND_WIDTH);
    ctxCanvas.stroke();
    ctxCanvas.moveTo(0, i * NUMBER_OF_PLAYGROUND_LINE);
    ctxCanvas.lineTo(PLAYGROUND_WIDTH, i * NUMBER_OF_PLAYGROUND_LINE);
    ctxCanvas.stroke();
  }

}<commit_msg>add characterClass<commit_after>var PLAYGROUND_WIDTH = 600;
var NUMBER_OF_SQUARE = 17;
var NUMBER_OF_PLAYGROUND_LINE = PLAYGROUND_WIDTH / NUMBER_OF_SQUARE;

var CHARACTER_PARAMETER = [
  {
    "name": "daisyo",
    "cost": 1,
    "hitPoint": 3,
    "attack": 1,
    "attacableRange": 2,
    "move": 1
  },
  {
    "name": "pupepon",
    "cost": 3,
    "hitPoint": 7,
    "attack": 3,
    "attacableRange": 2,
    "move": 3
  },
  {
    "name": "haseaki",
    "cost": 2,
    "hitPoint": 3,
    "attack": 2,
    "attacableRange": 2,
    "move": 2
  },
  {
    "name": "miho",
    "cost": 5,
    "hitPoint": 8,
    "attack": 3,
    "attacableRange": 2,
    "move": 2
  }
]

character = function(posx, posy,charaId) {
  this.posx = posx;
  this.posy = posy;
  this.charaId = charaId;
  this.name = CHARACTER_PARAMETER[charaId].name;
  this.cost = CHARACTER_PARAMETER[charaId].cost;
  this.hitPoint = CHARACTER_PARAMETER[charaId].hitPoint;
  this.attack = CHARACTER_PARAMETER[charaId].attack;
  this.attacableRange = CHARACTER_PARAMETER[charaId].attacableRange;
  this.move = CHARACTER_PARAMETER[charaId].move;
}

// Declarations
var selectX = -1;
var selectY = -1;

$(function(){
  /* canvas */
  playGround = $("#play-ground").get(0);
  ctxCanvas  = playGround.getContext("2d");

  // クリック処理
  var canvasPosition = $('#play-ground').position();

  $('#play-ground').click(function(e) {
    /*
    (selectY, selectX)
    */
    selectX = e.pageX - canvasPosition.left;
    selectY = e.pageY - canvasPosition.top;

    console.log(Math.floor(selectY / NUMBER_OF_PLAYGROUND_LINE) + "," + Math.floor(selectX / NUMBER_OF_PLAYGROUND_LINE));

  });

  console.log(CHARACTER_PARAMETER[3].name);

  /* Load function */
  drawField();

});

function drawField(){
  var i;

  for (i=0; i<=17;i++) {
    if (i === 0 || i === NUMBER_OF_SQUARE) {
      ctxCanvas.beginPath();
      ctxCanvas.lineWidth = 10.0;
    } else {
      ctxCanvas.beginPath();
      ctxCanvas.lineWidth = 1.0;
    }
    ctxCanvas.moveTo(i * NUMBER_OF_PLAYGROUND_LINE, 0);
    ctxCanvas.lineTo(i * NUMBER_OF_PLAYGROUND_LINE, PLAYGROUND_WIDTH);
    ctxCanvas.stroke();
    ctxCanvas.moveTo(0, i * NUMBER_OF_PLAYGROUND_LINE);
    ctxCanvas.lineTo(PLAYGROUND_WIDTH, i * NUMBER_OF_PLAYGROUND_LINE);
    ctxCanvas.stroke();
  }

}<|endoftext|>


<commit_before>'use strict'

const express = require('express')
const bodyParser = require('body-parser')
const request = require('request')
const app = express()
const config = require('config')

const hubVerifyToken = process.env.HUB_VERIFY_TOKEN || config.hubVerifyToken
const token = process.env.PAGE_ACCESS_TOKEN || config.pageToken

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}))

// parse application/json
app.use(bodyParser.json())

// index
app.get('/', (req, res) => {
  res.send('hello world i am mawhai bot')
})

app.post('/webhook/', function (req, res) {
  let messagingEvents = req.body.entry[0].messaging
  for (let i = 0; i < messagingEvents.length; i++) {
    let event = req.body.entry[0].messaging[i]
    let sender = event.sender.id
    if (event.message && event.message.text) {
      let text = event.message.text
      sendTextMessage(sender, 'Text received, echo: ' + text.substring(0, 200))
    }
  }
  res.sendStatus(200)
})

function sendTextMessage (sender, text) {
  let messageData = { text: text }

  request({
    url: 'https://graph.facebook.com/v2.6/me/messages',
    qs: {access_token: token},
    method: 'POST',
    json: {
      recipient: {id: sender},
      message: messageData
    }
  }, function (error, response, body) {
    if (error) {
      console.log('Error sending messages: ', error)
    } else if (response.body.error) {
      console.log('Error: ', response.body.error)
    } else {
      console.log('success sending to', sender)
    }
  })
}

function sendGenericMessage(sender) {
  let messageData = {
    'attachment': {
      'type': 'template',
      'payload': {
        'template_type': 'generic',
        'elements': [{
          'title': 'First card',
          'subtitle': 'Element #1 of an hscroll',
          'image_url': 'http://messengerdemo.parseapp.com/img/rift.png',
          'buttons': [{
            'type': 'web_url',
            'url': 'https://www.messenger.com',
            'title': 'web url'
          }, {
            'type': 'postback',
            'title': 'Postback',
            'payload': 'Payload for first element in a generic bubble'
          }]
        }, {
          'title': 'Second card',
          'subtitle': 'Element #2 of an hscroll',
          'image_url': 'http://messengerdemo.parseapp.com/img/gearvr.png',
          'buttons': [{
            'type': 'postback',
            'title': 'Postback',
            'payload': 'Payload for second element in a generic bubble'
          }]
        }]
      }
    }
  }
  request({
    url: 'https://graph.facebook.com/v2.6/me/messages',
    qs: {access_token: token},
    method: 'POST',
    json: {
      recipient: {id: sender},
      message: messageData
    }
  }, function (error, response, body) {
    if (error) {
      console.log('Error sending messages: ', error)
    } else if (response.body.error) {
      console.log('Error: ', response.body.error)
    }
  })
}

// spin spin sugar
const port = process.env.PORT || 5000
app.listen(port, function () {
  console.log('running on port', port)
})

<commit_msg>add more text<commit_after>'use strict'

const express = require('express')
const bodyParser = require('body-parser')
const request = require('request')
const app = express()
const config = require('config')

const hubVerifyToken = process.env.HUB_VERIFY_TOKEN || config.hubVerifyToken
const token = process.env.PAGE_ACCESS_TOKEN || config.pageToken

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}))

// parse application/json
app.use(bodyParser.json())

// index
app.get('/', (req, res) => {
  res.send('hello world i am mawhai bot')
})

app.post('/webhook/', function (req, res) {
  let messagingEvents = req.body.entry[0].messaging
  for (let i = 0; i < messagingEvents.length; i++) {
    let event = req.body.entry[0].messaging[i]
    let sender = event.sender.id
    if (event.message && event.message.text) {
      let text = event.message.text
      sendTextMessage(sender, 'Text received, echo: ' + text.substring(0, 200))
      sendTextMessage(sender, 'meow meow~*')
    }
  }
  res.sendStatus(200)
})

function sendTextMessage (sender, text) {
  let messageData = { text: text }

  request({
    url: 'https://graph.facebook.com/v2.6/me/messages',
    qs: {access_token: token},
    method: 'POST',
    json: {
      recipient: {id: sender},
      message: messageData
    }
  }, function (error, response, body) {
    if (error) {
      console.log('Error sending messages: ', error)
    } else if (response.body.error) {
      console.log('Error: ', response.body.error)
    } else {
      console.log('success sending to', sender)
    }
  })
}

function sendGenericMessage(sender) {
  let messageData = {
    'attachment': {
      'type': 'template',
      'payload': {
        'template_type': 'generic',
        'elements': [{
          'title': 'First card',
          'subtitle': 'Element #1 of an hscroll',
          'image_url': 'http://messengerdemo.parseapp.com/img/rift.png',
          'buttons': [{
            'type': 'web_url',
            'url': 'https://www.messenger.com',
            'title': 'web url'
          }, {
            'type': 'postback',
            'title': 'Postback',
            'payload': 'Payload for first element in a generic bubble'
          }]
        }, {
          'title': 'Second card',
          'subtitle': 'Element #2 of an hscroll',
          'image_url': 'http://messengerdemo.parseapp.com/img/gearvr.png',
          'buttons': [{
            'type': 'postback',
            'title': 'Postback',
            'payload': 'Payload for second element in a generic bubble'
          }]
        }]
      }
    }
  }
  request({
    url: 'https://graph.facebook.com/v2.6/me/messages',
    qs: {access_token: token},
    method: 'POST',
    json: {
      recipient: {id: sender},
      message: messageData
    }
  }, function (error, response, body) {
    if (error) {
      console.log('Error sending messages: ', error)
    } else if (response.body.error) {
      console.log('Error: ', response.body.error)
    }
  })
}

// spin spin sugar
const port = process.env.PORT || 5000
app.listen(port, function () {
  console.log('running on port', port)
})

<|endoftext|>


<commit_before>// Karma configuration
module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha', 'phantomjs-shim'],

    // list of files / patterns to load in the browser
    files: [
      'src/**/*.spec.js',
      'src/**/*.spec.jsx'
    ],

    // list of files to exclude
    exclude: [
      '**/flycheck_*' // syntax checking for GNU Emacs
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'src/**/*.spec.js*': [ 'webpack' ]
    },

    webpack: {
      devtool: 'inline-source-map',
      module: {
        loaders: [
          { test: /\.js$/,   exclude: /node_modules/, loader: 'babel' },
          { test: /\.json$/, loader: 'json-loader' }
        ]
      },
      resolve: {
        extensions: ['', '.json', '.js', '.jsx']
      }
    },

    // ? webpackServer: {
    // ?   noInfo: true
    // ? },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['mocha'],

    mochaReporter: {
      output: 'autowatch'
    },

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_ERROR,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['PhantomJS'],
    // browsers: ['Chrome'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false
  })
}
<commit_msg>suppress verbose transpiler output in our unit test code<commit_after>// Karma configuration
module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha', 'phantomjs-shim'],

    // list of files / patterns to load in the browser
    files: [
      'src/**/*.spec.js',
      'src/**/*.spec.jsx'
    ],

    // list of files to exclude
    exclude: [
      '**/flycheck_*' // syntax checking for GNU Emacs
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'src/**/*.spec.js*': [ 'webpack' ]
    },

    webpack: {
      devtool: 'inline-source-map',
      module: {
        loaders: [
          { test: /\.js$/,   exclude: /node_modules/, loader: 'babel' },
          { test: /\.json$/, loader: 'json-loader' }
        ]
      },
      resolve: {
        extensions: ['', '.json', '.js', '.jsx']
      }
    },

    webpackServer: {
      noInfo: true
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['mocha'],

    mochaReporter: {
      output: 'autowatch'
    },

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_ERROR,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['PhantomJS'],
    // browsers: ['Chrome'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false
  })
}
<|endoftext|>


<commit_before>'use strict';

var async    = require ('async');
var inquirer = require ('inquirer');

var Command  = require ('./lib/command.js');

/**
 * Prompt constructor.
 */
function Prompt () {
  return [{
    type    : 'input',
    name    : 'command',
    message : '>'
  }];
}

/**
 * ShellCraft constructor.
 */
function ShellCraft () {
  var self = this;

  var ArgumentsList = require ('./lib/argumentslist.js');

  self._exit = false;
  self._shell = true; /* open the shell be default */

  self.arguments = new ArgumentsList ();
  self.arguments._add ('exit', new Command (function (callback) {
    self._exit = true;
    if (callback) {
      callback ();
    }
  }, {builtIn: true}, 'exit the shell'));
  self.arguments._add ('help', new Command (function (callback) {
    Object.keys (Object.getPrototypeOf (self.arguments)).forEach (function (fct) {
      if (!self.arguments.hasOwnProperty (fct) &&
          !/^_/.test(fct) &&
          self.arguments[fct].type () === 'command') {
        console.log (self.arguments[fct].help ());
      }
    });
    if (callback) {
      callback ();
    }
  }, {builtIn: true}, 'list of commands'));

  self.options = {
    version: '0.0.1'
  };
  self.prompt = new Prompt ();
  self.extensions = [];
}

/**
 * Check if we must exit the shell.
 *
 * @api private
 * @returns {boolean} Exit status.
 */
ShellCraft.prototype.isExit = function () {
  return this._exit;
};

/**
 * Start the Shell interface.
 *
 * @api private
 * @param {function(err, results)} callback
 */
ShellCraft.prototype.shell = function (callback) {
  var self = this;

  var AutoComplete = require ('./lib/autocomplete.js');

  if (self.options.prompt) {
    self.prompt[0].message = self.options.prompt;
  }

  var history = [];
  var iterator = 0;

  process.stdin.setRawMode (true);
  self.uiPrompt     = {};
  self.autocomplete = new AutoComplete (self);

  process.stdin.on ('keypress', function (chunk, key) {
    if (!key) {
      return;
    }

    switch (key.name) {
    /* Command history */
    case 'up': {
      if (iterator > 0) {
        --iterator;
      }
      self.uiPrompt.rl.write (null, {ctrl: true, name: 'u'});
      self.uiPrompt.rl.write (history[iterator]);
      break;
    }
    case 'down': {
      self.uiPrompt.rl.write (null, {ctrl: true, name: 'u'});
      if (iterator < history.length - 1) {
        ++iterator;
        self.uiPrompt.rl.write (history[iterator]);
      } else {
        iterator = history.length;
      }
      break;
    }
    /* Command auto-completion */
    case 'tab': {
      self.autocomplete.begin ();
      break;
    }
    }
  });

  var inquirerCallback = null;
  var inquirerPrompt   = self.prompt;

  async.forever (function (next) {
    self.uiPrompt = inquirer.prompt (inquirerPrompt, function (answers) {
      /*
       * Special handling when the command returns an Inquirer definition. In
       * this case we must return the answers to the caller.
       */
      if (inquirerCallback) {
        var returnToPrompt = inquirerCallback (answers);
        if (returnToPrompt) {
          inquirerCallback = null;
          inquirerPrompt   = self.prompt;
          next (null);
        }
        return;
      }

      /*
       * Normal shell handling for the commands.
       */
      var cmdArgs = answers.command.split (' ');
      var cmd = cmdArgs[0];
      cmdArgs.shift ();

      if (cmd.length && answers.command !== history[history.length - 1]) {
        history.push (answers.command);
      }
      iterator = history.length;

      try {
        if (self.arguments[cmd].type () === 'option') {
          throw new Error ();
        }

        self.arguments[cmd].call (function (data, wizardCallback) {
          /* The next prompt we must start the wizard provided by the client. */
          if (data) {
            if (self.arguments[cmd].isWizard ()) {
              inquirerPrompt = data;
              inquirerCallback = wizardCallback;
            }
          } else {
            inquirerPrompt   = self.prompt;
            inquirerCallback = null;
          }
          next (self.isExit () ? 'good bye' : null);
        }, cmdArgs);
      } catch (ex) {
        if (answers.command.length) {
          console.log ('command ' + cmd + ' unknown');
        }

        next (null);
      }
    });
  }, function (results) {
    if (callback) {
      callback (null, results);
    }
  });
};

/**
 * Start the Command Line Interface (CLI).
 *
 * @api private
 * @param {function(results)} callback
 */
ShellCraft.prototype.cli = function (callback) {
  var self = this;
  var program = require ('commander');

  program.version (self.options.version);

  Object.keys (Object.getPrototypeOf (self.arguments)).forEach (function (fct) {
    if (self.arguments.hasOwnProperty (fct) || /^_/.test (fct) || self.arguments[fct].isBuiltIn ()) {
      return;
    }

    var params = self.arguments[fct].params ();

    switch (self.arguments[fct].type ()) {
    case 'option': {
      program
        .option (fct + params,
                 self.arguments[fct].help (true),
                 function () {
                   var args = arguments;

                   /* We force to only one argument with the options. */
                   if (args.length > 1) {
                     args = [args[0]];
                   }
                   self.arguments[fct].call (function () {}, args);
                 });
      return;
    }
    case 'command': {
      program
        .command (fct + params)
        .description (self.arguments[fct].help (true))
        .action (function (first, next) {
          self._shell = false;

          var values = [];

          if (Array.isArray (first)) {
            values = values.concat (first);
          } else if (first && typeof first !== 'object') {
            values.push (first);
          }
          if (Array.isArray (next)) {
            values = values.concat (next);
          } else if (next && typeof next !== 'object') {
            values.push (next);
          }

          self.arguments[fct].call (function (data, wizardCallback) {
            if (data) {
              if (!self.arguments[fct].isWizard ()) {
                return;
              }
            } else {
              return;
            }

            /* Start the wizard. */
            inquirer.prompt (data, function (answers) {
              wizardCallback (answers);
            });
          }, values);
        });
      return;
    }
    default: {
      callback ('item ' + fct + ' is ' + self.arguments[fct].type () +
                ' but a command or an option was expected');
      return;
    }
    }
  });

  program.parse (process.argv);

  if (callback) {
    callback ();
  }
};

/**
 * Close the Command Line Interface (CLI) or the shell.
 *
 * @api private
 * @param {function(err)} callback
 */
ShellCraft.prototype.shutdown = function (callback) {
  async.each (this.extensions, function (ext, callback) {
    ext.unregister (callback);
  }, function (err) {
    callback (err);
  });
};

/**
 * Register external commands.
 *
 * @param {string} shellExt - Path on the shell extension file.
 * @param {function(err)} callback
 */
ShellCraft.prototype.registerExtension = function (shellExt, callback) {
  var self = this;
  var ext = require (shellExt);

  var Extension = require ('./lib/extension.js');
  var extension = new Extension (self);

  ext.register (extension, function (err) {
    if (!err) {
      self.extensions.push (ext);
      if (self.autocomplete) {
        self.autocomplete.reload ();
      }
    }

    if (callback) {
      callback (err);
    }
  });
};

/**
 * Begins the Shell or the CLI accordingly to the provided arguments.
 *
 * @param {Object} options
 * @param {function(err, results)} callback
 */
ShellCraft.prototype.begin = function (options, callback) {
  var self = this;
  self.options = options;

  /* Run in command line. */
  self.cli (function () {
    if (self._shell) {
      /* Run the Shell. */
      self.shell (function () {
        self.shutdown (callback);
      });
    } else {
      self.shutdown (callback);
    }
  });
};

exports = module.exports = new ShellCraft ();
<commit_msg>Simplify conditions.<commit_after>'use strict';

var async    = require ('async');
var inquirer = require ('inquirer');

var Command  = require ('./lib/command.js');

/**
 * Prompt constructor.
 */
function Prompt () {
  return [{
    type    : 'input',
    name    : 'command',
    message : '>'
  }];
}

/**
 * ShellCraft constructor.
 */
function ShellCraft () {
  var self = this;

  var ArgumentsList = require ('./lib/argumentslist.js');

  self._exit = false;
  self._shell = true; /* open the shell be default */

  self.arguments = new ArgumentsList ();
  self.arguments._add ('exit', new Command (function (callback) {
    self._exit = true;
    if (callback) {
      callback ();
    }
  }, {builtIn: true}, 'exit the shell'));
  self.arguments._add ('help', new Command (function (callback) {
    Object.keys (Object.getPrototypeOf (self.arguments)).forEach (function (fct) {
      if (!self.arguments.hasOwnProperty (fct) &&
          !/^_/.test(fct) &&
          self.arguments[fct].type () === 'command') {
        console.log (self.arguments[fct].help ());
      }
    });
    if (callback) {
      callback ();
    }
  }, {builtIn: true}, 'list of commands'));

  self.options = {
    version: '0.0.1'
  };
  self.prompt = new Prompt ();
  self.extensions = [];
}

/**
 * Check if we must exit the shell.
 *
 * @api private
 * @returns {boolean} Exit status.
 */
ShellCraft.prototype.isExit = function () {
  return this._exit;
};

/**
 * Start the Shell interface.
 *
 * @api private
 * @param {function(err, results)} callback
 */
ShellCraft.prototype.shell = function (callback) {
  var self = this;

  var AutoComplete = require ('./lib/autocomplete.js');

  if (self.options.prompt) {
    self.prompt[0].message = self.options.prompt;
  }

  var history = [];
  var iterator = 0;

  process.stdin.setRawMode (true);
  self.uiPrompt     = {};
  self.autocomplete = new AutoComplete (self);

  process.stdin.on ('keypress', function (chunk, key) {
    if (!key) {
      return;
    }

    switch (key.name) {
    /* Command history */
    case 'up': {
      if (iterator > 0) {
        --iterator;
      }
      self.uiPrompt.rl.write (null, {ctrl: true, name: 'u'});
      self.uiPrompt.rl.write (history[iterator]);
      break;
    }
    case 'down': {
      self.uiPrompt.rl.write (null, {ctrl: true, name: 'u'});
      if (iterator < history.length - 1) {
        ++iterator;
        self.uiPrompt.rl.write (history[iterator]);
      } else {
        iterator = history.length;
      }
      break;
    }
    /* Command auto-completion */
    case 'tab': {
      self.autocomplete.begin ();
      break;
    }
    }
  });

  var inquirerCallback = null;
  var inquirerPrompt   = self.prompt;

  async.forever (function (next) {
    self.uiPrompt = inquirer.prompt (inquirerPrompt, function (answers) {
      /*
       * Special handling when the command returns an Inquirer definition. In
       * this case we must return the answers to the caller.
       */
      if (inquirerCallback) {
        var returnToPrompt = inquirerCallback (answers);
        if (returnToPrompt) {
          inquirerCallback = null;
          inquirerPrompt   = self.prompt;
          next (null);
        }
        return;
      }

      /*
       * Normal shell handling for the commands.
       */
      var cmdArgs = answers.command.split (' ');
      var cmd = cmdArgs[0];
      cmdArgs.shift ();

      if (cmd.length && answers.command !== history[history.length - 1]) {
        history.push (answers.command);
      }
      iterator = history.length;

      try {
        if (self.arguments[cmd].type () === 'option') {
          throw new Error ();
        }

        self.arguments[cmd].call (function (data, wizardCallback) {
          /* The next prompt we must start the wizard provided by the client. */
          if (data) {
            if (self.arguments[cmd].isWizard ()) {
              inquirerPrompt = data;
              inquirerCallback = wizardCallback;
            }
          } else {
            inquirerPrompt   = self.prompt;
            inquirerCallback = null;
          }
          next (self.isExit () ? 'good bye' : null);
        }, cmdArgs);
      } catch (ex) {
        if (answers.command.length) {
          console.log ('command ' + cmd + ' unknown');
        }

        next (null);
      }
    });
  }, function (results) {
    if (callback) {
      callback (null, results);
    }
  });
};

/**
 * Start the Command Line Interface (CLI).
 *
 * @api private
 * @param {function(results)} callback
 */
ShellCraft.prototype.cli = function (callback) {
  var self = this;
  var program = require ('commander');

  program.version (self.options.version);

  Object.keys (Object.getPrototypeOf (self.arguments)).forEach (function (fct) {
    if (self.arguments.hasOwnProperty (fct) || /^_/.test (fct) || self.arguments[fct].isBuiltIn ()) {
      return;
    }

    var params = self.arguments[fct].params ();

    switch (self.arguments[fct].type ()) {
    case 'option': {
      program
        .option (fct + params,
                 self.arguments[fct].help (true),
                 function () {
                   var args = arguments;

                   /* We force to only one argument with the options. */
                   if (args.length > 1) {
                     args = [args[0]];
                   }
                   self.arguments[fct].call (function () {}, args);
                 });
      return;
    }
    case 'command': {
      program
        .command (fct + params)
        .description (self.arguments[fct].help (true))
        .action (function (first, next) {
          self._shell = false;

          var values = [];

          if (Array.isArray (first)) {
            values = values.concat (first);
          } else if (first && typeof first !== 'object') {
            values.push (first);
          }
          if (Array.isArray (next)) {
            values = values.concat (next);
          } else if (next && typeof next !== 'object') {
            values.push (next);
          }

          self.arguments[fct].call (function (data, wizardCallback) {
            if (!data || !self.arguments[fct].isWizard ()) {
              return;
            }

            /* Start the wizard. */
            inquirer.prompt (data, function (answers) {
              wizardCallback (answers);
            });
          }, values);
        });
      return;
    }
    default: {
      callback ('item ' + fct + ' is ' + self.arguments[fct].type () +
                ' but a command or an option was expected');
      return;
    }
    }
  });

  program.parse (process.argv);

  if (callback) {
    callback ();
  }
};

/**
 * Close the Command Line Interface (CLI) or the shell.
 *
 * @api private
 * @param {function(err)} callback
 */
ShellCraft.prototype.shutdown = function (callback) {
  async.each (this.extensions, function (ext, callback) {
    ext.unregister (callback);
  }, function (err) {
    callback (err);
  });
};

/**
 * Register external commands.
 *
 * @param {string} shellExt - Path on the shell extension file.
 * @param {function(err)} callback
 */
ShellCraft.prototype.registerExtension = function (shellExt, callback) {
  var self = this;
  var ext = require (shellExt);

  var Extension = require ('./lib/extension.js');
  var extension = new Extension (self);

  ext.register (extension, function (err) {
    if (!err) {
      self.extensions.push (ext);
      if (self.autocomplete) {
        self.autocomplete.reload ();
      }
    }

    if (callback) {
      callback (err);
    }
  });
};

/**
 * Begins the Shell or the CLI accordingly to the provided arguments.
 *
 * @param {Object} options
 * @param {function(err, results)} callback
 */
ShellCraft.prototype.begin = function (options, callback) {
  var self = this;
  self.options = options;

  /* Run in command line. */
  self.cli (function () {
    if (self._shell) {
      /* Run the Shell. */
      self.shell (function () {
        self.shutdown (callback);
      });
    } else {
      self.shutdown (callback);
    }
  });
};

exports = module.exports = new ShellCraft ();
<|endoftext|>


<commit_before>function isObject(whoAmI) {
    return (!!whoAmI) && (whoAmI.constructor === Object);
}

function isArray(whoAmI) {
    return (!!whoAmI) && (whoAmI.constructor === Array);
}

function isNumber(whoAmI) {
    return !isNaN(whoAmI);
}

function isSet(whoAmI) {
    return (!!whoAmI) && (whoAmI.constructor === Set);
}

function isMap(whoAmI) {
    return (!!whoAmI) && (whoAmI.constructor === Map);
}

function fourLoop(loopMe, callback) {
    var iterator = 0;
    if (isObject(loopMe)) {
        Object.keys(loopMe).forEach(function (k) {
            callback(loopMe[k], k, iterator);
            iterator++;
        });
    } else if (isArray(loopMe)) {
        loopMe.forEach(function (v, i) {
            callback(v, v, i);
        });
    } else if (isNumber(loopMe)) {
        for (var i = 0; i < loopMe; i++) {
            callback(i, i, i);
        }
    } else if (isSet(loopMe) || isMap(loopMe)) {
        loopMe.forEach(function (v, k) {
            callback(v, k, i);
            iterator++;
        });
    }
}

module.exports = fourLoop;
<commit_msg>RB: Patch set and map with iterator<commit_after>function isObject(whoAmI) {
    return (!!whoAmI) && (whoAmI.constructor === Object);
}

function isArray(whoAmI) {
    return (!!whoAmI) && (whoAmI.constructor === Array);
}

function isNumber(whoAmI) {
    return !isNaN(whoAmI);
}

function isSet(whoAmI) {
    return (!!whoAmI) && (whoAmI.constructor === Set);
}

function isMap(whoAmI) {
    return (!!whoAmI) && (whoAmI.constructor === Map);
}

function fourLoop(loopMe, callback) {
    var iterator = 0;
    if (isObject(loopMe)) {
        Object.keys(loopMe).forEach(function (k) {
            callback(loopMe[k], k, iterator);
            iterator++;
        });
    } else if (isArray(loopMe)) {
        loopMe.forEach(function (v, i) {
            callback(v, v, i);
        });
    } else if (isNumber(loopMe)) {
        for (var i = 0; i < loopMe; i++) {
            callback(i, i, i);
        }
    } else if (isSet(loopMe) || isMap(loopMe)) {
        loopMe.forEach(function (v, k) {
            callback(v, k, iterator);
            iterator++;
        });
    }
}

module.exports = fourLoop;
<|endoftext|>


<commit_before>// Karma configuration
// Generated on Tue Jan 03 2017 22:49:18 GMT-0800 (PST)

module.exports = function (config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '.',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha', 'chai', 'sinon'],

    // list of files / patterns to load in the browser
    files: [
      // Polyfills.
      'node_modules/core-js/client/shim.min.js',

      'node_modules/traceur/bin/traceur.js',

      // System.js for module loading
      'node_modules/systemjs/dist/system.src.js',

      // Zone.js dependencies
      'node_modules/zone.js/dist/zone.js',
      'node_modules/zone.js/dist/long-stack-trace-zone.js',
      'node_modules/zone.js/dist/async-test.js',
      'node_modules/zone.js/dist/fake-async-test.js',
      'node_modules/zone.js/dist/sync-test.js',
      'node_modules/zone.js/dist/proxy.js',
      'node_modules/zone.js/dist/mocha-patch.js',

      // RxJs.
      { pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
      { pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false },

      // paths loaded via module imports
      // Angular itself
      { pattern: 'node_modules/@angular/**/*.js', included: false, watched: true },
      { pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false },

      { pattern: 'dist/client/**/*.js', included: false, watched: true },
      { pattern: 'dist/test/client/**/*.js', included: false, watched: true },
      { pattern: 'dist/client/**/*.html', included: false, watched: true, served: true },
      { pattern: 'dist/client/**/*.css', included: false, watched: true, served: true },
      { pattern: 'node_modules/systemjs/dist/system-polyfills.js', included: false, watched: false }, // PhantomJS2 (and possibly others) might require it
      { pattern: 'node_modules/chai/**/*.js', included: false, watched: false },
      { pattern: 'node_modules/assertion-error/**/*.js', included: false, watched: false },
      { pattern: 'node_modules/sinon/**/*.js', included: false, watched: false },

      // suppress annoying 404 warnings for resources, images, etc.
      { pattern: 'dist/client/assets/**/*', watched: false, included: false, served: true },

      'tools/testconfig/test.config.js',
      'dist/client/app/systemjs.config.js',
      'tools/testconfig/test.main.js'
    ],

    // must go along with above, suppress annoying 404 warnings.
    proxies: {
      '/assets/': '/base/dist/client/assets/',
      '/npm/': '/base/node_modules/'
    },

    // list of files to exclude
    exclude: [
      'node_modules/**/*spec.js'
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {},

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['mocha'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    //browsers: ['PhantomJS'],
    browsers: ['Chrome'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  });

  if (process.env.TRAVIS || process.env.CIRCLECI) {
    config.browsers = ['Chrome_travis_ci'];
    config.browserNoActivityTimeout = 90000;
  }
};
<commit_msg>update karma conf for travis<commit_after>// Karma configuration
// Generated on Tue Jan 03 2017 22:49:18 GMT-0800 (PST)

module.exports = function (config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '.',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha', 'chai', 'sinon'],

    // list of files / patterns to load in the browser
    files: [
      // Polyfills.
      'node_modules/core-js/client/shim.min.js',

      'node_modules/traceur/bin/traceur.js',

      // System.js for module loading
      'node_modules/systemjs/dist/system.src.js',

      // Zone.js dependencies
      'node_modules/zone.js/dist/zone.js',
      'node_modules/zone.js/dist/long-stack-trace-zone.js',
      'node_modules/zone.js/dist/async-test.js',
      'node_modules/zone.js/dist/fake-async-test.js',
      'node_modules/zone.js/dist/sync-test.js',
      'node_modules/zone.js/dist/proxy.js',
      'node_modules/zone.js/dist/mocha-patch.js',

      // RxJs.
      {
        pattern: 'node_modules/rxjs/**/*.js',
        included: false,
        watched: false
      },
      {
        pattern: 'node_modules/rxjs/**/*.js.map',
        included: false,
        watched: false
      },

      // paths loaded via module imports
      // Angular itself
      {
        pattern: 'node_modules/@angular/**/*.js',
        included: false,
        watched: true
      },
      {
        pattern: 'node_modules/@angular/**/*.js.map',
        included: false,
        watched: false
      },

      {
        pattern: 'dist/client/**/*.js',
        included: false,
        watched: true
      },
      {
        pattern: 'dist/test/client/**/*.js',
        included: false,
        watched: true
      },
      {
        pattern: 'dist/client/**/*.html',
        included: false,
        watched: true,
        served: true
      },
      {
        pattern: 'dist/client/**/*.css',
        included: false,
        watched: true,
        served: true
      },
      {
        pattern: 'node_modules/systemjs/dist/system-polyfills.js',
        included: false,
        watched: false
      }, // PhantomJS2 (and possibly others) might require it
      {
        pattern: 'node_modules/chai/**/*.js',
        included: false,
        watched: false
      },
      {
        pattern: 'node_modules/assertion-error/**/*.js',
        included: false,
        watched: false
      },
      {
        pattern: 'node_modules/sinon/**/*.js',
        included: false,
        watched: false
      },

      // suppress annoying 404 warnings for resources, images, etc.
      {
        pattern: 'dist/client/assets/**/*',
        watched: false,
        included: false,
        served: true
      },

      'tools/testconfig/test.config.js',
      'dist/client/app/systemjs.config.js',
      'tools/testconfig/test.main.js'
    ],

    // must go along with above, suppress annoying 404 warnings.
    proxies: {
      '/assets/': '/base/dist/client/assets/',
      '/npm/': '/base/node_modules/'
    },

    // list of files to exclude
    exclude: [
      'node_modules/**/*spec.js'
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {},

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['mocha'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    //browsers: ['PhantomJS'],
    browsers: ['Chrome'],

    customLaunchers: {
      Chrome_travis_ci: {
        base: 'Chrome',
        flags: ['--no-sandbox']
      }
    },

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  });

  if (process.env.TRAVIS || process.env.CIRCLECI) {
    config.browsers = ['Chrome_travis_ci'];
    config.browserNoActivityTimeout = 90000;
  }
};
<|endoftext|>