<commit_before>'use strict';

/**
 * Require 'em all!
 */
var glob    = require('glob');
var map     = require('vinyl-map');
var colors  = require('colors');

var path    = require('path');

/**
 * Output a message, e.g. errors, warnings,...
 * @param  {Object} options Title, message
 */
var message = function (options) {
  options = options || {};
  options.title = options.title || 'Error!';
  options.message = options.message || '';

  console.log('gulp-jade-globbing'.bold.red + ': '.red + options.title);
  console.log(options.message);
};

/**
 * Remove new lines (you never know!)
 * @param  {String} string Input string
 * @return {String}        Output string without new lines
 */
var removeNewLines = function (string) {
  return string.replace(/(\r\n|\n|\r)/gm, '');
};

/**
 * Check if given string has indentation or not
 * @param  {String} string Input string
 * @return {Boolean}
 */
var hasIndent = function (string) {
  return /[\s](\binclude\b|\bextends\b)/g.test(removeNewLines(string));
};

/**
 * Return indentation of a string
 * @param  {String} string Input string
 * @return {String}        Indentation
 */
var getIndentation = function (string) {
  return /(\s*)?(?:\binclude\b|\bextends\b)/g.exec(removeNewLines(string))[1] || '';
};

/**
 * Return if string is an "include" or "extends"
 * @param  {String} string Input string
 * @return {String}        "include" or "extends"
 */
var getType = function (string) {
  return /[\s]?extends\s/g.test(removeNewLines(string)) ? 'extends' : 'include';
};

/**
 * Check if given object is empty or not.
 * @param  {Object}  obj The object to check
 * @return {Boolean}
 */
var isEmptyObject = function (obj) {
  return Object.keys(obj).length === 0;
};

/**
 * Regex tests to check which type of globbing is used
 * @return {Object} Tests
 */
var regexTests = {
  folder: /\/\*\*\/\*.jade/,
  direct: /[^*]\.jade/,
  file: /[^*]\/\*\.jade/,
  all: /\*\/\*[^\.]?/,
};

/**
 * Get type of globbing used via path string
 * @param  {String} path Path which includes globbing stuff
 * @return {String}      Globbing type used
 */
var getGlobType = function (path) {
  var globType;

  Object.keys(regexTests).forEach(function (type) {
    if (regexTests[type].test(path)) {
      globType = type;
      return false;
    }
  });

  return globType;
};

module.exports = function (options) {
  /**
   * Default options object
   * @type {Object}
   */
  var opt = options || {};

  /**
   * Ignore specific paths which shouldn't be included
   * @type {Array}
   */
  opt.ignore = opt.ignore || [];
  if (typeof opt.ignore == 'string') opt.ignore = [opt.ignore];

  /**
   * Check if given path should be ignored or not
   * @param  {String} path Path to check
   * @return {Boolean}     Yep/Nope
   */
  var ignorePath = function (path) {
    var ignore = false;

    if (opt.ignore.length > 0) {
      opt.ignore.forEach(function (ignoreFolder) {
        if ((new RegExp(ignoreFolder)).test(path)) {
          ignore = true;
        }
      });
    }

    return ignore;
  };

  /**
   * Turn on/off placeholder replacement
   * @type {Object}
   */
  opt.placeholder = opt.placeholder || {};

  return map(function (buffer, filepath) {
    var content             = buffer.toString();
    var contentRegex        = /^((?:\s+)?(?:\binclude\b|\bextends\b)\s.+)$/gm;
    var globRegEx           = /\/\*/;
    var placeholderRegEx    = /\{/;
    var dirName             = path.dirname(filepath);

    /**
     * Check file for "include"'s and "extends" and replace
     * those with relative paths to given files.
     */
    content = content.replace(contentRegex, function (result, includeGlob) {
      /**
       * This holds all paths found by one glob pattern
       * @type {Array}
       */
      var files = [];

      /**
       * "include" or "extends"?
       * @type {String}
       */
      var lineType = getType(result);

      /**
       * Check if it's a placeholder...
       */
      var isPlaceholder = !isEmptyObject(opt.placeholder) && placeholderRegEx.exec(includeGlob) ? true : false;

      if (isPlaceholder) {
        /**
         * Plain placeholder name
         */
        var placeholder = /\{(.+)\}/.exec(includeGlob)[1];

        /**
         * Iterate over all placeholders defined...
         */
        Object.keys(opt.placeholder).forEach(function (name) {
          /**
           * ... and if we have a match...
           */
          if (placeholder === name) {
            var placeholderPath = includeGlob.replace(
              /^(?:\s+)?(?:\binclude\b|\bextends\b)\s({.+})$/,
              opt.placeholder[name]
            );

            var placeholderPathArr = placeholderPath.split(path.sep);
            var rootDir = placeholderPathArr[0] === '.' ? placeholderPathArr[1] : placeholderPathArr[0];
            var relativeFilepath = rootDir + dirName.split(rootDir)[1];
            var relativePath = path.relative(relativeFilepath, placeholderPath);

            includeGlob = includeGlob.replace(
              '{' + name + '}',
              relativePath
            );
          }
        });
      }

      /**
       * Check if we have a glob pattern...
       */
      var hasGlobPattern = includeGlob.match(globRegEx);

      /**
       * Include Path containing the glob
       */
      var includeGlobPath = includeGlob.replace(/^\s\s*/, '');
          includeGlobPath = includeGlobPath.replace(/^(\binclude\b|\bextends\b)\s+/, '');

      /**
       * If we have a glob pattern in the current line...
       */
      if (hasGlobPattern || isPlaceholder) {
        glob.sync(includeGlobPath, { cwd: dirName }).forEach(function (includePath) {
          /**
           * ... push only ".jade" filepaths into the files array...
           */
          if (path.extname(includePath) === '.jade') {
            /**
             * ... if they are not set to be ignored.
             */
            if (!ignorePath(path.resolve(dirName, includePath))) {
              files.push(includePath);
            } else if (isPlaceholder && !hasGlobPattern) {
              files.push(includePath);
            }
          }
        });

        /**
         * If we managed to push filepaths into the files array...
         */
        if (files.length > 0) {
          /**
           * ... and, if it's an "extends" statement, contains
           * no globs or placeholders...
           */
          if (lineType === 'extends' && /\s?(?:\bextends\b)\s(?:[^*{]+)$/.test(includeGlob) === false) {
            var errorMessage = '  statement:    ' + includeGlobPath.cyan + '\n';

            if (isPlaceholder) {
              errorMessage  += '  placeholder:  {' + placeholder + '}\n';
            }

            message({
              title: 'Error!\n  glob patterns are not allowed on extend statements.'.red,
              message: errorMessage
            });
          } else {
            /**
             * ... we can now replace the line containing the glob...
             */
            result = '';

            /**
             * ... with the found file paths.
             */
            files.forEach(function (includePath) {
              result += getIndentation(includeGlob) + lineType + ' ' + includePath + '\n';
            });
          }
        /**
         * Otherwise show a warning about the glob pattern not matching.
         */
        } else {
          var warningMessage = '  pattern:      ' + includeGlobPath.cyan + '\n';

          if (isPlaceholder) {
            warningMessage  += '  placeholder:  {' + placeholder + '}\n';
          }

          message({
            title: 'Warning!\n  glob pattern did not match any files.'.red,
            message: warningMessage
          });

          result = '//- No file(s) found in ' + includeGlobPath + '\n';
        }
      }

      return result;
    });

    return content;
  });
};
<commit_msg>Parsing extended files to avoid forget some "hidden" globbing<commit_after>'use strict';

/**
 * Require 'em all!
 */
var glob    = require('glob');
var map     = require('vinyl-map');
var colors  = require('colors');

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

/**
 * Output a message, e.g. errors, warnings,...
 * @param  {Object} options Title, message
 */
var message = function (options) {
  options = options || {};
  options.title = options.title || 'Error!';
  options.message = options.message || '';

  console.log('gulp-jade-globbing'.bold.red + ': '.red + options.title);
  console.log(options.message);
};

/**
 * Remove new lines (you never know!)
 * @param  {String} string Input string
 * @return {String}        Output string without new lines
 */
var removeNewLines = function (string) {
  return string.replace(/(\r\n|\n|\r)/gm, '');
};

/**
 * Check if given string has indentation or not
 * @param  {String} string Input string
 * @return {Boolean}
 */
var hasIndent = function (string) {
  return /[\s](\binclude\b|\bextends\b)/g.test(removeNewLines(string));
};

/**
 * Return indentation of a string
 * @param  {String} string Input string
 * @return {String}        Indentation
 */
var getIndentation = function (string) {
  return /(\s*)?(?:\binclude\b|\bextends\b)/g.exec(removeNewLines(string))[1] || '';
};

/**
 * Return if string is an "include" or "extends"
 * @param  {String} string Input string
 * @return {String}        "include" or "extends"
 */
var getType = function (string) {
  return /[\s]?extends\s/g.test(removeNewLines(string)) ? 'extends' : 'include';
};

/**
 * Check if given object is empty or not.
 * @param  {Object}  obj The object to check
 * @return {Boolean}
 */
var isEmptyObject = function (obj) {
  return Object.keys(obj).length === 0;
};

/**
 * Regex tests to check which type of globbing is used
 * @return {Object} Tests
 */
var regexTests = {
  folder: /\/\*\*\/\*.jade/,
  direct: /[^*]\.jade/,
  file: /[^*]\/\*\.jade/,
  all: /\*\/\*[^\.]?/,
};

/**
 * Get type of globbing used via path string
 * @param  {String} path Path which includes globbing stuff
 * @return {String}      Globbing type used
 */
var getGlobType = function (path) {
  var globType;

  Object.keys(regexTests).forEach(function (type) {
    if (regexTests[type].test(path)) {
      globType = type;
      return false;
    }
  });

  return globType;
};

/**
 * Parse the files that will be extended
 * @param  {String} path     Path of the requested file
 * @param  {String} filename Name of the file
 * @return {String}          File content
 */
var parseExtends = function(path, fileName) {
  var data = fs.readFileSync(path + fileName).toString();
  return data;
}

module.exports = function (options) {
  /**
   * Default options object
   * @type {Object}
   */
  var opt = options || {};

  /**
   * Ignore specific paths which shouldn't be included
   * @type {Array}
   */
  opt.ignore = opt.ignore || [];
  if (typeof opt.ignore == 'string') opt.ignore = [opt.ignore];

  /**
   * Check if given path should be ignored or not
   * @param  {String} path Path to check
   * @return {Boolean}     Yep/Nope
   */
  var ignorePath = function (path) {
    var ignore = false;

    if (opt.ignore.length > 0) {
      opt.ignore.forEach(function (ignoreFolder) {
        if ((new RegExp(ignoreFolder)).test(path)) {
          ignore = true;
        }
      });
    }

    return ignore;
  };

  /**
   * Turn on/off placeholder replacement
   * @type {Object}
   */
  opt.placeholder = opt.placeholder || {};

  return map(function (buffer, filepath) {
    var content             = buffer.toString();
    var contentRegex        = /^((?:\s+)?(?:\binclude\b|\bextends\b)\s.+)$/gm;
    var globRegEx           = /\/\*/;
    var placeholderRegEx    = /\{/;
    var dirName             = path.dirname(filepath);

    /**
     * Parse all extended files
     */
    content = parseExtends(
      filepath.replace(/\/$/, '').match(/.*\//g)[0],
      content.match(/extends.*/g)[0].replace(/.*\s+/g, '')
    );

    /**
     * Check file for "include"'s and "extends" and replace
     * those with relative paths to given files.
     */
    content = content.replace(contentRegex, function (result, includeGlob) {
      /**
       * This holds all paths found by one glob pattern
       * @type {Array}
       */
      var files = [];

      /**
       * "include" or "extends"?
       * @type {String}
       */
      var lineType = getType(result);

      /**
       * Check if it's a placeholder...
       */
      var isPlaceholder = !isEmptyObject(opt.placeholder) && placeholderRegEx.exec(includeGlob) ? true : false;

      if (isPlaceholder) {
        /**
         * Plain placeholder name
         */
        var placeholder = /\{(.+)\}/.exec(includeGlob)[1];

        /**
         * Iterate over all placeholders defined...
         */
        Object.keys(opt.placeholder).forEach(function (name) {
          /**
           * ... and if we have a match...
           */
          if (placeholder === name) {
            var placeholderPath = includeGlob.replace(
              /^(?:\s+)?(?:\binclude\b|\bextends\b)\s({.+})$/,
              opt.placeholder[name]
            );

            var placeholderPathArr = placeholderPath.split(path.sep);
            var rootDir = placeholderPathArr[0] === '.' ? placeholderPathArr[1] : placeholderPathArr[0];
            var relativeFilepath = rootDir + dirName.split(rootDir)[1];
            var relativePath = path.relative(relativeFilepath, placeholderPath);

            includeGlob = includeGlob.replace(
              '{' + name + '}',
              relativePath
            );
          }
        });
      }

      /**
       * Check if we have a glob pattern...
       */
      var hasGlobPattern = includeGlob.match(globRegEx);

      /**
       * Include Path containing the glob
       */
      var includeGlobPath = includeGlob.replace(/^\s\s*/, '');
          includeGlobPath = includeGlobPath.replace(/^(\binclude\b|\bextends\b)\s+/, '');

      /**
       * If we have a glob pattern in the current line...
       */
      if (hasGlobPattern || isPlaceholder) {
        glob.sync(includeGlobPath, { cwd: dirName }).forEach(function (includePath) {
          /**
           * ... push only ".jade" filepaths into the files array...
           */
          if (path.extname(includePath) === '.jade') {
            /**
             * ... if they are not set to be ignored.
             */
            if (!ignorePath(path.resolve(dirName, includePath))) {
              files.push(includePath);
            } else if (isPlaceholder && !hasGlobPattern) {
              files.push(includePath);
            }
          }
        });

        /**
         * If we managed to push filepaths into the files array...
         */
        if (files.length > 0) {
          /**
           * ... and, if it's an "extends" statement, contains
           * no globs or placeholders...
           */
          if (lineType === 'extends' && /\s?(?:\bextends\b)\s(?:[^*{]+)$/.test(includeGlob) === false) {
            var errorMessage = '  statement:    ' + includeGlobPath.cyan + '\n';

            if (isPlaceholder) {
              errorMessage  += '  placeholder:  {' + placeholder + '}\n';
            }

            message({
              title: 'Error!\n  glob patterns are not allowed on extend statements.'.red,
              message: errorMessage
            });
          } else {
            /**
             * ... we can now replace the line containing the glob...
             */
            result = '';

            /**
             * ... with the found file paths.
             */
            files.forEach(function (includePath) {
              result += getIndentation(includeGlob) + lineType + ' ' + includePath + '\n';
            });
          }
        /**
         * Otherwise show a warning about the glob pattern not matching.
         */
        } else {
          var warningMessage = '  pattern:      ' + includeGlobPath.cyan + '\n';

          if (isPlaceholder) {
            warningMessage  += '  placeholder:  {' + placeholder + '}\n';
          }

          message({
            title: 'Warning!\n  glob pattern did not match any files.'.red,
            message: warningMessage
          });

          result = '//- No file(s) found in ' + includeGlobPath + '\n';
        }
      }

      return result;
    });

    return content;
  });
};
<|endoftext|>


<commit_before>'use strict';

module.exports = ignore;
ignore.Ignore = Ignore;

var EE = require('events').EventEmitter;
var node_util = require('util');

function ignore (options){
    return new Ignore(options);
}

// @param {Object} options
// - ignore: {Array}
// - twoGlobstars: {boolean=false} enable pattern '`**`' (two consecutive asterisks), default to `false`.
//      If false, ignore patterns with two globstars will be omitted
// - noCase: {boolean=true} case sensitive.
//      By default, git is case-insensitive
function Ignore (options){
    options = options || {};
    options.noCase = 'noCase' in options ? options.noCase : true;

    this.options = options;
    this._patterns = [];
    this._rules = [];

    this.add(options.ignore);
}

// Events:
// 'warn': ,
//      will warn when encounter '`**`' (two consecutive asterisks)
//      which is not compatible with all platforms (not works on Mac OS for example)
node_util.inherits(Ignore, EE);

function makeArray (subject) {
    return Array.isArray(subject) ?
        subject :
        subject === undefined || subject === null ?
            [] :
            [subject];
}

// @param {Array.<string>|string} pattern
Ignore.prototype.add = function(pattern) {
    makeArray(pattern).forEach(this._add, this);
    return this;
};

Ignore.prototype.filter = function(paths) {
    return paths.filter(this._filter, this);
};

Ignore.prototype._add = function(pattern) {
    if(this._simpleTest(pattern)){
        var rule = this._createRule(pattern);
        this._rules.push(rule);
    }
};

Ignore.prototype._simpleTest = function(pattern) {
    var pass =
        // Whitespace dirs are allowed, so only filter blank pattern.
        pattern &&
        // And not start with a '#'
        pattern.indexOf('#') !== 0 &&

        ! ~ this._patterns.indexOf(pattern);

    this._patterns.push(pattern);

    if( ~ pattern.indexOf('**') ){
        this.emit('warn', {
            pattern: origin,
            reason: '`**` found, which is not compatible cross all platforms.'
        });

        if(!this.options.twoGlobstars){
            return false;
        }
    }

    return pass;
};

var REGEX_LEADING_EXCLAMATION = /^\\\!/;
var REGEX_LEADING_HASH = /^\\#/;

Ignore.prototype._createRule = function(pattern) {
    var rule_object = {
        origin: pattern
    };

    var match_start;

    if(pattern.indexOf('!') === 0){
        rule_object.negative = true;
        pattern = pattern.substr(1);
    }

    pattern = pattern
        .replace(REGEX_LEADING_EXCLAMATION, '!')
        .replace(REGEX_LEADING_HASH, '#');

    rule_object.pattern = pattern;

    rule_object.regex = this.makeRegex(pattern);

    return rule_object;
};

// > If the pattern ends with a slash, it is removed for the purpose of the following description, but it would only find a match with a directory. In other words, foo/ will match a directory foo and paths underneath it, but will not match a regular file or a symbolic link foo (this is consistent with the way how pathspec works in general in Git).
// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'
// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call
//      you could use option `mark: true` with `glob`

// '`foo/`' should not continue with the '`..`'
var REPLACERS = [
    // leading slash
    [

        // > A leading slash matches the beginning of the pathname. For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".
        // A leading slash matches the beginning of the pathname
        /^\//,
        '^'
    ],

    [
        // > A leading "**" followed by a slash means match in all directories. For example, "**/foo" matches file or directory "foo" anywhere, the same as pattern "foo". "**/foo/bar" matches file or directory "bar" anywhere that is directly under directory "foo".
        /\*\*\//,

        // '**/foo' <-> 'foo'
        // just remove it
        ''
    ],

    // 'f'
    // matches
    // - /f(end)
    // - /f/
    // - (start)f(end)
    // - (start)f/
    // doesn't match
    // - oof
    // - foo
    // pseudo:
    // -> (^|/)f(/|$)

    // ending
    [
        // 'js' will not match 'js.'
        /(?:[^*\/])$/,
        function (match1) {
            return match1 + '(?=$|\\/)';
        }
    ],

    // starting
    [
        // there will be no leading '/' (which has been replaced by the first replacer)
        // If starts with '**', adding a '^' to the regular expression also works
        /^(?=[^\^])/,
        '(?:^|\\/)'
    ],

    // two globstars
    [
        // > A slash followed by two consecutive asterisks then a slash matches zero or more directories. For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on.
        // '/**/'
        /\/\*\*\//g,

        // Zero, one or several directories
        // should not use '*', or it will be replaced by the next replacer
        '(?:\\/[^\\/]+){0,}\\/'
    ],

    // wildcard
    [
        /\*+/g,

        // 'abc/*.js' matches 'abc/...js'
        '[^\\/]*'
    ]
];

// @param {pattern}
Ignore.prototype.makeRegex = function(pattern) {
    var source = REPLACERS.reduce(function (prev, current) {
        return prev.replace( current[0], current[1] );

    }, pattern);

    return new RegExp(source, this.options.noCase ? 'i' : '');
};

Ignore.prototype._filter = function(path) {
    var rules = this._rules;
    var i = 0;
    var length = rules.length;
    var matched;
    var rule;

    for(; i < length; i ++){
        rule = rules[i];

        // if matched = true, then we only test negative rules
        // if matched = false, then we test non-negative rules
        if( !( matched ^ rule.negative ) ){
            matched = rule.negative ^ rule.regex.test(path);

        }else{
            continue;
        }
    }

    return !matched;
};

<commit_msg>add a new method .createFilter()<commit_after>'use strict';

module.exports = ignore;
ignore.Ignore = Ignore;

var EE = require('events').EventEmitter;
var node_util = require('util');

function ignore (options){
    return new Ignore(options);
}

// @param {Object} options
// - ignore: {Array}
// - twoGlobstars: {boolean=false} enable pattern '`**`' (two consecutive asterisks), default to `false`.
//      If false, ignore patterns with two globstars will be omitted
// - noCase: {boolean=true} case sensitive.
//      By default, git is case-insensitive
function Ignore (options){
    options = options || {};
    options.noCase = 'noCase' in options ? options.noCase : true;

    this.options = options;
    this._patterns = [];
    this._rules = [];

    this.add(options.ignore);
}

// Events:
// 'warn': ,
//      will warn when encounter '`**`' (two consecutive asterisks)
//      which is not compatible with all platforms (not works on Mac OS for example)
node_util.inherits(Ignore, EE);

function makeArray (subject) {
    return Array.isArray(subject) ?
        subject :
        subject === undefined || subject === null ?
            [] :
            [subject];
}

// @param {Array.<string>|string} pattern
Ignore.prototype.add = function(pattern) {
    makeArray(pattern).forEach(this._add, this);
    return this;
};

Ignore.prototype.filter = function(paths) {
    return paths.filter(this._filter, this);
};

Ignore.prototype._add = function(pattern) {
    if(this._simpleTest(pattern)){
        var rule = this._createRule(pattern);
        this._rules.push(rule);
    }
};

Ignore.prototype._simpleTest = function(pattern) {
    var pass =
        // Whitespace dirs are allowed, so only filter blank pattern.
        pattern &&
        // And not start with a '#'
        pattern.indexOf('#') !== 0 &&

        ! ~ this._patterns.indexOf(pattern);

    this._patterns.push(pattern);

    if( ~ pattern.indexOf('**') ){
        this.emit('warn', {
            code: 'WGLOBSTARS',
            data: {
                pattern: origin
            },
            message: '`**` found, which is not compatible cross all platforms.'
        });

        if(!this.options.twoGlobstars){
            return false;
        }
    }

    return pass;
};

var REGEX_LEADING_EXCLAMATION = /^\\\!/;
var REGEX_LEADING_HASH = /^\\#/;

Ignore.prototype._createRule = function(pattern) {
    var rule_object = {
        origin: pattern
    };

    var match_start;

    if(pattern.indexOf('!') === 0){
        rule_object.negative = true;
        pattern = pattern.substr(1);
    }

    pattern = pattern
        .replace(REGEX_LEADING_EXCLAMATION, '!')
        .replace(REGEX_LEADING_HASH, '#');

    rule_object.pattern = pattern;

    rule_object.regex = this.makeRegex(pattern);

    return rule_object;
};

// > If the pattern ends with a slash, it is removed for the purpose of the following description, but it would only find a match with a directory. In other words, foo/ will match a directory foo and paths underneath it, but will not match a regular file or a symbolic link foo (this is consistent with the way how pathspec works in general in Git).
// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'
// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call
//      you could use option `mark: true` with `glob`

// '`foo/`' should not continue with the '`..`'
var REPLACERS = [
    // leading slash
    [

        // > A leading slash matches the beginning of the pathname. For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".
        // A leading slash matches the beginning of the pathname
        /^\//,
        '^'
    ],

    [
        // > A leading "**" followed by a slash means match in all directories. For example, "**/foo" matches file or directory "foo" anywhere, the same as pattern "foo". "**/foo/bar" matches file or directory "bar" anywhere that is directly under directory "foo".
        /\*\*\//,

        // '**/foo' <-> 'foo'
        // just remove it
        ''
    ],

    // 'f'
    // matches
    // - /f(end)
    // - /f/
    // - (start)f(end)
    // - (start)f/
    // doesn't match
    // - oof
    // - foo
    // pseudo:
    // -> (^|/)f(/|$)

    // ending
    [
        // 'js' will not match 'js.'
        /(?:[^*\/])$/,
        function (match1) {
            return match1 + '(?=$|\\/)';
        }
    ],

    // starting
    [
        // there will be no leading '/' (which has been replaced by the first replacer)
        // If starts with '**', adding a '^' to the regular expression also works
        /^(?=[^\^])/,
        '(?:^|\\/)'
    ],

    // two globstars
    [
        // > A slash followed by two consecutive asterisks then a slash matches zero or more directories. For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on.
        // '/**/'
        /\/\*\*\//g,

        // Zero, one or several directories
        // should not use '*', or it will be replaced by the next replacer
        '(?:\\/[^\\/]+){0,}\\/'
    ],

    // wildcard
    [
        /\*+/g,

        // 'abc/*.js' matches 'abc/...js'
        '[^\\/]*'
    ]
];

// @param {pattern}
Ignore.prototype.makeRegex = function(pattern) {
    var source = REPLACERS.reduce(function (prev, current) {
        return prev.replace( current[0], current[1] );

    }, pattern);

    return new RegExp(source, this.options.noCase ? 'i' : '');
};

Ignore.prototype._filter = function(path) {
    var rules = this._rules;
    var i = 0;
    var length = rules.length;
    var matched;
    var rule;

    for(; i < length; i ++){
        rule = rules[i];

        // if matched = true, then we only test negative rules
        // if matched = false, then we test non-negative rules
        if( !( matched ^ rule.negative ) ){
            matched = rule.negative ^ rule.regex.test(path);

        }else{
            continue;
        }
    }

    return !matched;
};

Ignore.prototype.createFilter = function() {
    var self = this;

    return function (path) {
        return self._filter(path);
    };
};

<|endoftext|>


<commit_before>'use strict';

const TimerMixin = require('react-timer-mixin');

import React from 'react';
import {
  StyleSheet,
  Text,
  ScrollView,
  View
} from 'react-native';

const PAGE_CHANGE_DELAY = 4000;

/**
 * Animates pages in cycle
 * (loop possible if children count > 1)
*/
var Carousel = React.createClass({
  propTypes:{
    children: React.PropTypes.node.isRequired,
    delay: React.PropTypes.number,
    style: View.propTypes.style,
    pageStyle: View.propTypes.style,
    contentContainerStyle: View.propTypes.style,
    autoplay: React.PropTypes.bool,
    pageInfo: React.PropTypes.bool,
    pageInfoBackgroundColor: React.PropTypes.string,
    pageInfoTextStyle: Text.propTypes.style,
    pageInfoTextSeparator: React.PropTypes.string,
    onAnimateNextPage: React.PropTypes.func
  },
  mixins: [TimerMixin],
  getDefaultProps() {
    return {
      delay: PAGE_CHANGE_DELAY,
      autoplay: true,
      pageInfo: false,
      pageInfoBackgroundColor: 'rgba(0, 0, 0, 0.25)',
      pageInfoTextSeparator: ' / ',
    };
  },
  getInitialState() {
    if (!!this.props.children) {
      var childrenCount = this.props.children.length;
      return {
        contentOffset: {x: 0, y: 0},
        currentPage: childrenCount > 1 ? 1 : 0,
        hasChildren: true,
        size: { width: 0, height: 0 }
      };
    } else {
      return {
        hasChildren: false,
        size: { width: 0, height: 0 }
      }
    }
  },
  componentDidMount(){
    if (this.state.hasChildren) {
      this._setUpTimer();
    }
  },
  _onScrollBegin(event) {
    this.clearTimeout(this.timer);
  },
  _onScrollEnd(event) {
    this._setUpTimer();

    var offset = Object.assign({}, event.nativeEvent.contentOffset);

    var childrenCount = this.props.children.length,
      size = this.state.size;
    if (offset.x === 0) {
      offset.x = childrenCount * size.width;
    } else if (offset.x == (childrenCount+1)*size.width) {
      offset.x = size.width;
    }

    this._calculateCurrentPage(offset.x);
    this.setState({contentOffset: offset});
  },
  _onLayout() {
    let self = this;
    this.refs.container.measure(function(x, y, w, h, px, py) {
      self.setState({
        contentOffset: { x: w },
        size: { width: w, height: h}
      });
    });
  },
  _setUpTimer() {
    //only for cycling
    if (this.props.autoplay && this.props.children.length > 1) {
      this.clearTimeout(this.timer);
      this.timer = this.setTimeout(this._animateNextPage, this.props.delay);
    }
  },
  _animateNextPage() {
    var k = this.state.currentPage;
    var size = this.state.size;
    k++;

    this.setState({currentPage: k});
    this.refs.scrollView.scrollTo({ y: 0, x: k*size.width });
    this._setUpTimer();
  },
  _calculateCurrentPage(offset) {
    var size = this.state.size;
    var page = Math.floor((offset - size.width/2) / size.width) + 1;
    this.setState({currentPage: page}, () => {
      if (this.props.onAnimateNextPage) {
        this.props.onAnimateNextPage(this.state.currentPage)
      }
    });
  },
  _renderPageInfo(pageLength) {
    return (
      <View style={styles.pageInfoBottomContainer} pointerEvents="none">
        <View style={styles.pageInfoContainer}>
          <View style={[styles.pageInfoPill, { backgroundColor: this.props.pageInfoBackgroundColor }]}>
            <Text style={[styles.pageInfoText, this.props.pageInfoTextStyle]}>{`${this.state.currentPage}${this.props.pageInfoTextSeparator}${pageLength}`}</Text>
          </View>
        </View>
      </View>
    );
  },
  //TODO: add optional `dots` for displaying current page (like pageControl)
  render() {
    var pages = [],
      contents,
      containerProps;

    var size = this.state.size;

    containerProps = {
      ref: 'container',
      onLayout: this._onLayout,
      style: [this.props.style]
    };

    if (!this.state.hasChildren) {
      contents = (
        <Text style={{backgroundColor: 'white'}}>
          You are supposed to add children inside Carousel
        </Text>
      );
    }

    var children = this.props.children;

    //to make infinite pages structure like this is needed: 3-1-2-3-1
    //add last one at the 1st place
    if (children.length >= 1) {
      pages.push(children[children.length-1]);
    }

    //add all pages
    for (var i=0; i<children.length; i++) {
      pages.push(children[i]);
    }

    //add first one at the last place
    if (children.length >= 1) {
      pages.push(children[0]);
    }

    pages = pages.map((page, i) =>
        <View style={[{width: size.width, height: size.height}, this.props.pageStyle]} key={"page"+i}>
          {page}
        </View>
    );

    contents = (
      <ScrollView
        ref='scrollView'
        onScrollBeginDrag={this._onScrollBegin}
        onMomentumScrollEnd={this._onScrollEnd}
        alwaysBounceHorizontal={false}
        alwaysBounceVertical={false}
        contentInset={{top:0}}
        automaticallyAdjustContentInsets={false}
        showsHorizontalScrollIndicator={false}
        horizontal={true}
        pagingEnabled={true}
        bounces={false}
        contentOffset={this.state.contentOffset}
        contentContainerStyle={[
          styles.horizontalScroll,
          this.props.contentContainerStyle,
          {
            width: size.width*(this.props.children.length+(this.props.children.length>1?2:0)),
            height: size.height
          }
        ]}
      >
        {pages}
      </ScrollView>);
      return (
        <View {...containerProps}>
          {contents}
          {this.props.pageInfo && this._renderPageInfo(children.length)}
        </View>
      );
  },
});

var styles = StyleSheet.create({
  horizontalScroll: {
    position:'absolute',
  },
  pageInfoBottomContainer: {
    position: 'absolute',
    bottom: 20,
    left: 0,
    right: 0,
    backgroundColor: 'transparent',
  },
  pageInfoContainer: {
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'transparent'
  },
  pageInfoPill: {
    width: 80,
    height: 20,
    borderRadius: 10,
    alignItems: 'center',
    justifyContent: 'center',
  },
  pageInfoText: {
    textAlign: 'center',
  }
});

module.exports = Carousel;
<commit_msg>addint bullet point to control your image. And you can pass a chosen argument to the Carousel tag to choose from which image to start the Carousel<commit_after>'use strict';

const TimerMixin = require('react-timer-mixin');

import React from 'react';
import {
  StyleSheet,
  Text,
  ScrollView,
  View,
  TouchableWithoutFeedback
} from 'react-native';

const PAGE_CHANGE_DELAY = 4000;

/**
 * Animates pages in cycle
 * (loop possible if children count > 1)
*/
var Carousel = React.createClass({
  propTypes:{
    children: React.PropTypes.node.isRequired,
    delay: React.PropTypes.number,
    style: View.propTypes.style,
    pageStyle: View.propTypes.style,
    contentContainerStyle: View.propTypes.style,
    autoplay: React.PropTypes.bool,
    pageInfo: React.PropTypes.bool,
    pageInfoBackgroundColor: React.PropTypes.string,
    pageInfoTextStyle: Text.propTypes.style,
    pageInfoTextSeparator: React.PropTypes.string,
    onAnimateNextPage: React.PropTypes.func,
    chosen: React.PropTypes.number
  },
  mixins: [TimerMixin],
  getDefaultProps() {
    return {
      delay: PAGE_CHANGE_DELAY,
      autoplay: true,
      pageInfo: false,
      pageInfoBackgroundColor: 'rgba(0, 0, 0, 0.25)',
      pageInfoTextSeparator: ' / ',
    };
  },
  getInitialState() {
    if (!!this.props.children) {
      var childrenCount = this.props.children.length;
      return {
        contentOffset: {x: 0, y: 0},
        currentPage: childrenCount > 1 ? 1 : 0,
        chosen: this.props.chosen == undefined ? 0 : this.props.chosen,
        hasChildren: true,
        size: { width: 0, height: 0 }
      };
    } else {
      return {
        hasChildren: false,
        size: { width: 0, height: 0 }
      }
    }
  },
  componentDidMount(){
    if (this.state.hasChildren) {
      this._setUpTimer();
    }
  },
  _onScrollBegin(event) {
    this.clearTimeout(this.timer);
  },
  _onScrollEnd(event) {
    this._setUpTimer();

    var offset = Object.assign({}, event.nativeEvent.contentOffset);

    var childrenCount = this.props.children.length,
      size = this.state.size;
    if (offset.x === 0) {
      offset.x = childrenCount * size.width;
    } else if (offset.x == (childrenCount+1)*size.width) {
      offset.x = size.width;
    }

    this._calculateCurrentPage(offset.x);
    this.setState({contentOffset: offset});
  },
  _onLayout() {
    let self = this;
    this.refs.container.measure(function(x, y, w, h, px, py) {
      self.setState({
        contentOffset: { x: w },
        size: { width: w, height: h}
      });
    });
  },
  _setUpTimer() {
    //only for cycling
    if (this.props.autoplay && this.props.children.length > 1) {
      this.clearTimeout(this.timer);
      this.timer = this.setTimeout(this._animateNextPage, this.props.delay);
    }
  },
  _animateNextPage() {
    var k = this.state.currentPage;
    var size = this.state.size;
    k++;

    this.setState({currentPage: k});
    this.refs.scrollView.scrollTo({ y: 0, x: k*size.width });
    this._setUpTimer();
  },
  _animateToPage(p){
    this.clearTimeout(this.timer);
    let size = this.state.size;

    this.setState({currentPage: p});
    this.refs.scrollView.scrollTo({y: 0, x:p*size.width});
    this._setUpTimer();
  },
  _calculateCurrentPage(offset) {
    var size = this.state.size;
    var page = Math.floor((offset - size.width/2) / size.width) + 1;
    this.setState({currentPage: page}, () => {
      if (this.props.onAnimateNextPage) {
        this.props.onAnimateNextPage(this.state.currentPage)
      }
    });
  },
  _renderPageInfo(pageLength) {
    return (
      <View style={styles.pageInfoBottomContainer} pointerEvents="none">
        <View style={styles.pageInfoContainer}>
          <View style={[styles.pageInfoPill, { backgroundColor: this.props.pageInfoBackgroundColor }]}>
            <Text style={[styles.pageInfoText, this.props.pageInfoTextStyle]}>{`${this.state.currentPage}${this.props.pageInfoTextSeparator}${pageLength}`}</Text>
          </View>
        </View>
      </View>
    );
  },
  render() {
    var pages = [],
      contents,
      bullets,
      containerProps;

    var size = this.state.size;

    containerProps = {
      ref: 'container',
      onLayout: this._onLayout,
      style: [this.props.style]
    };

    if (!this.state.hasChildren) {
      contents = (
        <Text style={{backgroundColor: 'white'}}>
          You are supposed to add children inside Carousel
        </Text>
      );
    }

    var children = this.props.children;
    //to make infinite pages structure like this is needed: 3-1-2-3-1
    //add last one at the 1st place
    if (children.length >= 1) {
      pages.push(children[this.props.chosen == 0 ? children.length-1 : this.props.chosen-1]);
    }

    //add all pages
    if (this.props.chosen == 0){
      for (let i=0; i<children.length; i++) {
        pages.push(children[i]);
      }
    } else {
      for (let i = this.props.chosen; i < children.length; i++ ){
        pages.push(children[i]);
      }
      for (let i = 0; i < this.props.chosen; i++) {
        pages.push(children[i]);
      }
    }

    //add first one at the last place
    if (children.length >= 1) {
      pages.push(children[this.props.chosen]);
    }

    bullets = children.map((child, i) =>{
      let currentPage = this.state.currentPage == children.length ? 0 : this.state.currentPage;
      return (
        <TouchableWithoutFeedback onPress={() => this._animateToPage(i)} key={"bullet"+i}>
          <View style={i == currentPage ? styles.chosenBullet : styles.bullet} />
        </TouchableWithoutFeedback>)
    });

    pages = pages.map((page, i) =>
        <View style={[{width: size.width, height: size.height}, this.props.pageStyle]} key={"page"+i}>
          {page}
        </View>
    );

    contents = (
      <ScrollView
        ref='scrollView'
        onScrollBeginDrag={this._onScrollBegin}
        onMomentumScrollEnd={this._onScrollEnd}
        alwaysBounceHorizontal={false}
        alwaysBounceVertical={false}
        contentInset={{top:0}}
        automaticallyAdjustContentInsets={false}
        showsHorizontalScrollIndicator={false}
        horizontal={true}
        pagingEnabled={true}
        bounces={false}
        contentOffset={this.state.contentOffset}
        contentContainerStyle={[
          styles.horizontalScroll,
          this.props.contentContainerStyle,
          {
            width: size.width*(this.props.children.length+(this.props.children.length>1?2:0)),
            height: size.height
          }
        ]}
      >
        {pages}
      </ScrollView>);
      return (
        <View {...containerProps}>
          {contents}
          <View style={styles.container}>
            {bullets}
          </View>
          {this.props.pageInfo && this._renderPageInfo(children.length)}
        </View>
      );
  },
});

var styles = StyleSheet.create({
  horizontalScroll: {
    position:'absolute',
  },
  pageInfoBottomContainer: {
    position: 'absolute',
    bottom: 20,
    left: 0,
    right: 0,
    backgroundColor: 'transparent',
  },
  pageInfoContainer: {
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'transparent'
  },
  pageInfoPill: {
    width: 80,
    height: 20,
    borderRadius: 10,
    alignItems: 'center',
    justifyContent: 'center',
  },
  pageInfoText: {
    textAlign: 'center',
  },
  container: {
    position:'absolute',
    left:0,
    right:0,
    bottom:10,
    height:30,
    backgroundColor: 'transparent',
    alignItems: 'center',
    justifyContent: 'center',
    flexDirection: 'row'
  },
  chosenBullet: {
    marginLeft: 20,
    width: 10,
    height: 10,
    borderRadius: 20,
    backgroundColor: 'white'
  },
  bullet: {
    marginLeft: 20,
    width: 10,
    height: 10,
    borderRadius: 20,
    backgroundColor: 'transparent',
    borderColor: 'white',
    borderWidth: 1
  }
});

module.exports = Carousel;
<|endoftext|>


<commit_before>var request = require('request')

var perform_request = function(url, resolve, reject){

  var options = {
    url: url,
    headers: {
      'Accept': 'application/json',
      'X-Mashape-Key': process.env.mashapeKey || global.mashapeKey || ''
    }
  };

  return request(options, function(error, response, body) {

    if(!error){
      error = (response.statusCode != 200 ? response.statusCode + " - " + options.url : null);
    }

    if (error) {
      if(reject){
        return reject(error);
      }else{
        throw error;
      }
    }

    if (response.statusCode == 200 && resolve) {
      return resolve({
        url: options.url,
        body: JSON.parse(body),
        head: response.headers,
        scroll_url: response.headers['X-Next-Page'],
        scroll_count: response.headers['X-Count']
      });
    }
  });
}

var get = function(url, fields, opts, resolve, reject) {
  url = "https://igdbcom-internet-game-database-v1.p.mashape.com/" + url + "/";
  if (opts) {
    var optUrl = [], filter, param;
    for (param in opts) {
      var paramValue = opts[param];
      if (param == "filters") {
        for (filter in paramValue) {
          filter_split = filter.split('-')
          optUrl.push("filter[" + filter_split.join("][") + "]=" + paramValue[filter]);
        }
      } else if(param == "ids") {
        url += paramValue.join(',')
      } else {
        optUrl.push(param + "=" + paramValue);
      }
    }

    if(fields){
      optUrl.push("fields=" + fields.join(','));
    }

    url += "?" + optUrl.join('&');
  }

  return perform_request(url, resolve, reject);
};

var endpoint = function(e){
  return function(opts, fields) {
    return new Promise(function(resolve, reject){
      get(e, fields, opts, resolve, reject);
    });
  }
}

var endpoints = ["games", "companies", "people", "genres", "keywords", "platforms", "player_perspectives", "pulses", "themes", "franchises", "collections"],
endpoints_obj = {
  image: function(image_object, size, filetype){
    if(image_object){
      return "https://images.igdb.com/igdb/image/upload/t_" + (size || "thumb") + "/" + image_object.cloudinary_id + "." + (filetype || "jpg");
    }
  },
  scroll: function(url){
    return new Promise(function(resolve, reject){
      return perform_request(url, resolve, reject);
    });
  }
};

for(i = 0; i < endpoints.length; i++){
  endpoints_obj[endpoints[i]] = endpoint(endpoints[i]);
}

module.exports = endpoints_obj
<commit_msg>support new endpoints<commit_after>var request = require('request')

var perform_request = function(url, resolve, reject){

  var options = {
    url: url,
    headers: {
      'Accept': 'application/json',
      'X-Mashape-Key': process.env.mashapeKey || global.mashapeKey || ''
    }
  };

  return request(options, function(error, response, body) {

    if(!error){
      error = (response.statusCode != 200 ? response.statusCode + " - " + options.url : null);
    }

    if (error) {
      if(reject){
        return reject(error);
      }else{
        throw error;
      }
    }

    if (response.statusCode == 200 && resolve) {
      return resolve({
        url: options.url,
        body: JSON.parse(body),
        head: response.headers,
        scroll_url: response.headers['X-Next-Page'],
        scroll_count: response.headers['X-Count']
      });
    }
  });
}

var get = function(url, fields, opts, resolve, reject) {
  url = "https://igdbcom-internet-game-database-v1.p.mashape.com/" + url + "/";
  if (opts) {
    var optUrl = [], filter, param;
    for (param in opts) {
      var paramValue = opts[param];
      if (param == "filters") {
        for (filter in paramValue) {
          filter_split = filter.split('-')
          optUrl.push("filter[" + filter_split.join("][") + "]=" + paramValue[filter]);
        }
      } else if(param == "ids") {
        url += paramValue.join(',')
      } else {
        optUrl.push(param + "=" + paramValue);
      }
    }

    if(fields){
      optUrl.push("fields=" + fields.join(','));
    }

    url += "?" + optUrl.join('&');
  }

  return perform_request(url, resolve, reject);
};

var endpoint = function(e){
  return function(opts, fields) {
    return new Promise(function(resolve, reject){
      get(e, fields, opts, resolve, reject);
    });
  }
}

var endpoints = [
  "characters",
  "games",
  "feed",
  "companies",
  "people",
  "genres",
  "keywords",
  "platforms",
  "player_perspectives",
  "pulses",
  "themes",
  "release_dates",
  "franchises",
  "collections",
  "game_modes",
  "pages",
  "pulse_sources"
],
endpoints_obj = {
  image: function(image_object, size, filetype){
    if(image_object){
      return "https://images.igdb.com/igdb/image/upload/t_" + (size || "thumb") + "/" + image_object.cloudinary_id + "." + (filetype || "jpg");
    }
  },
  scroll: function(url){
    return new Promise(function(resolve, reject){
      return perform_request(url, resolve, reject);
    });
  }
};

for(i = 0; i < endpoints.length; i++){
  endpoints_obj[endpoints[i]] = endpoint(endpoints[i]);
}

module.exports = endpoints_obj
<|endoftext|>


<commit_before>var isBrowser = this.window ? true : false,
	objectId = isBrowser ? require("object-id") : require("./object-id"),
	inherits = isBrowser ? require("inherit") : require("util").inherits,
	EventEmitter = isBrowser ? require("emitter") : require("events").EventEmitter;

module.exports = Node;

function Node(){
	EventEmitter.call(this);
    this._id = objectId();
	this._childs = {};
	this._childIdsList = [];
	this._parent = null;
	this._data = {};
}

if(isBrowser){
	EventEmitter(o);
}else{
	inherits(Node,EventEmitter);
}

var o = Node.prototype;

o.getChild = function(childId){
	var child = this._childs[childId];
	if(child){
		return child;
	}else{
		for(var cid in this._childIdsList){
            child = this._childs[cid];
			if(child && child.getChild(childId)){
				return child;
			}
		}
		return null;
	}
}

/**
* @member Node#createChild
* @return {Node} , return new child node.
*/
o.createChild = function(){
	var child = new Node();
	child._parent = this;
	this._childs[child.id] = child;
	this._childIdsList.push(child.id);
	return child;
}

/**
* @member Node#appendChild
* @param {Node} child , child can't contain root.
* @return {Node} , self.
*/
o.appendChild = function(child){
	if(this.root.getChild(child.id) || child._childIdsList.length !== 0){
		return this;
	}else if(child.parent){
		child.parent.removeChild(child.id);
	}
	child._parent = this;
	this._childs[child.id] = child;
	this._childIdsList.push(child.id);
	return this;
}

o.removeChild = function(childId){

	child = this.getChild(childId);

	var parent;

	if(child && (parent = child._parent)){
		delete parent._childs[childId];
		child._parent = null;
		var index = parent._childIdsList.indexOf(childId);
		parent._childIdsList.splice(index,1);
	}

	return this;

}

o.replaceNode = function(child,targetId){

	var target = this.getChild(targetId);

	if( !child || !target || target.getChild(this.id) || child.getChild(this.id) || target.getChild(child.id) ){
		return this;
	}

	var parent = child.parent;
	if(parent){
		parent.removeChild(child.id);
	}

	var index = target.position();

	target.parent._childIdsList.splice(index,1,child);
    child._parent = target.parent;
    delete target.parent._childs[target.id];
	target._parent = null;

	return this;

}

o.position = function(childId){

	var child = this._getNode(childId);

	if(child){
		var parent = child.parent;
		return parent ? parent._childIdsList.indexOf(child.id) : null;
	}else{
		return null;
	}

}

o.layer = function(childId){
	var child = this._getNode(childId),layer = 0;

	if(child){
		var parent = child.parent;
		while(parent){
			layer += 1;
			parent = parent.parent;
		}
		return layer;
	}else{
		return 0;
	}
}

o._getNode = function(childId){

	var child;

	if(childId){
		if(childId === this.id){
			child = this;
		}else{
			child = this.getChild(childId);
		}
	}else{
		child = this;
	}

	return child;

}

o.top = function(childId){
	var child = this._getNode(childId),parent;
	if(child && (parent = child.parent)){
		var index = parent._childIdsList.indexOf(childId);
		parent._childIdsList.splice(index,1);
		parent._childIdsList.unshift(childId);
	}

	return this;
}

o.up = function(childId){
	var child = this._getNode(childId),parent;
	if(child && (parent = child.parent)){
		var index = parent._childIdsList.indexOf(child.id);
		parent._childIdsList.splice(index,1);
		if(index !== 0){
			parent._childIdsList.splice(index-1,0,child.id);
		}
	}
	return this;
}

o.down = function(childId){
	var child = this._getNode(childId),parent;
	if(child && (parent = child.parent)){
		var nextNode = child.nextNode();
        if(nextNode){
            nextNode.up();
        }
	}
	return this;
}

o.nextNode = function(childId){
    var child = this._getNode(childId);
    if(child){
        var parent = child.parent,
            index = child.position(),
            nextChildId = parent._childIdsList[index+1];

        if(nextChildId){
            return parent.getChild(nextChildId);
        }
    }
}

o.prevNode = function(childId){
    var child = this._getNode(childId);
    if(child){
        var parent = child.parent,
            index = child.position(),
            prevChildId = parent._childIdsList[index-1];

        if(prevChildId){
            return parent.getChild(prevChildId);
        }
    }
}

// move childId node to  parentId node.
o.move = function(childId,parentId){

	var child = this.getChild(childId),
		parent = parentId === this.parent ? this : this.getChild(parentId);

	if( child && parent && !child.getChild(parentId) ){
		var childParent = child.parent;
		childParent.removeChild(child.id);
		parent.appendChild(child);
	}

	return this;

}

o.isRoot = function(){
	return this.parent ? false : true ;
}

o.data = function(){

	var obj = {}

	if(arguments.length === 2){
		obj[arguments[0]] = arguments[1];
	}else if(arguments.length === 1){
        if(typeof arguments[0] === "string"){
            return this._data[arguments[0]];
        }else{
            obj = arguments[0];
        }
	}else{
        return this._data;
    }

	for(var k in obj){
		this._data[k] = obj[k];
	}

}

o.reborn = function(jsonObj){

    if(this._childIdsList.length === 0 && this.isRoot()){
        var self = this;
        this._id = jsonObj.id;
        this._childs = {};
        this._childIdsList = [];
        this._parent = jsonObj.parent;
        this._data = jsonObj.data;

        jsonObj.childIdsList.forEach(function(cid){
            var child = new Node();
            child.reborn(jsonObj.childs[cid]);
            self._childs[cid] = child;
        });
	}
	return this;

}

Object.defineProperties(o,{

	parent : {
		get : function(){
			return this._parent;
		}
	},

	id: {
		get : function(){
			return this._id;
		}
	},

	route:{
		get : function(){
			var route = [this.id],
				parent = this.parent;
			while(parent){
				route.unshift(parent.id);
				parent = parent.parent;
			}
			return route;
		}
	},

    root:{
        get:function(){
            var root = this.parent;
			while(root){
				root = root.parent;
			}
			return root || this;
        }
    },

	json:{
		get : function(){

			var jsonObj = {
				id : this._id,
				childs : {},
				childIdsList : this._childIdsList,
				parent : this._parent ? this._parent.id : null,
				data : this._data
			}, self  =  this;

			this._childIdsList.forEach(function(cid){
				jsonObj.childs[cid] = self._childs[cid].json;
			})

			return JSON.parse(JSON.stringify(jsonObj));

		}
	}

});

<commit_msg>format code.<commit_after>var isBrowser = this.window ? true : false,
objectId = isBrowser ? require("object-id") : require("./object-id"),
inherits = isBrowser ? require("inherit") : require("util").inherits,
EventEmitter = isBrowser ? require("emitter") : require("events").EventEmitter;

module.exports = Node;

function Node() {
	EventEmitter.call(this);
	this._id = objectId();
	this._childs = {};
	this._childIdsList = [];
	this._parent = null;
	this._data = {};
}

if (isBrowser) {
	EventEmitter(o);
} else {
	inherits(Node, EventEmitter);
}

var o = Node.prototype;

o.getChild = function (childId) {
	var child = this._childs[childId];
	if (child) {
		return child;
	} else {
		for (var cid in this._childIdsList) {
			child = this._childs[cid];
			if (child && child.getChild(childId)) {
				return child;
			}
		}
		return null;
	}
}

/**
 * @member Node#createChild
 * @return {Node} , return new child node.
 */
o.createChild = function () {
	var child = new Node();
	child._parent = this;
	this._childs[child.id] = child;
	this._childIdsList.push(child.id);
	return child;
}

/**
 * @member Node#appendChild
 * @param {Node} child , child can't contain root.
 * @return {Node} , self.
 */
o.appendChild = function (child) {
	if (this.root.getChild(child.id) || child._childIdsList.length !== 0) {
		return this;
	} else if (child.parent) {
		child.parent.removeChild(child.id);
	}
	child._parent = this;
	this._childs[child.id] = child;
	this._childIdsList.push(child.id);
	return this;
}

o.removeChild = function (childId) {

	child = this.getChild(childId);

	var parent;

	if (child && (parent = child._parent)) {
		delete parent._childs[childId];
		child._parent = null;
		var index = parent._childIdsList.indexOf(childId);
		parent._childIdsList.splice(index, 1);
	}

	return this;

}

o.replaceNode = function (child, targetId) {

	var target = this.getChild(targetId);

	if (!child || !target || target.getChild(this.id) || child.getChild(this.id) || target.getChild(child.id)) {
		return this;
	}

	var parent = child.parent;
	if (parent) {
		parent.removeChild(child.id);
	}

	var index = target.position();

	target.parent._childIdsList.splice(index, 1, child);
	child._parent = target.parent;
	delete target.parent._childs[target.id];
	target._parent = null;

	return this;

}

o.position = function (childId) {

	var child = this._getNode(childId);

	if (child) {
		var parent = child.parent;
		return parent ? parent._childIdsList.indexOf(child.id) : null;
	} else {
		return null;
	}

}

o.layer = function (childId) {
	var child = this._getNode(childId),
	layer = 0;

	if (child) {
		var parent = child.parent;
		while (parent) {
			layer += 1;
			parent = parent.parent;
		}
		return layer;
	} else {
		return 0;
	}
}

o._getNode = function (childId) {

	var child;

	if (childId) {
		if (childId === this.id) {
			child = this;
		} else {
			child = this.getChild(childId);
		}
	} else {
		child = this;
	}

	return child;

}

o.top = function (childId) {
	var child = this._getNode(childId),
	parent;
	if (child && (parent = child.parent)) {
		var index = parent._childIdsList.indexOf(childId);
		parent._childIdsList.splice(index, 1);
		parent._childIdsList.unshift(childId);
	}

	return this;
}

o.up = function (childId) {
	var child = this._getNode(childId),
	parent;
	if (child && (parent = child.parent)) {
		var index = parent._childIdsList.indexOf(child.id);
		parent._childIdsList.splice(index, 1);
		if (index !== 0) {
			parent._childIdsList.splice(index - 1, 0, child.id);
		}
	}
	return this;
}

o.down = function (childId) {
	var child = this._getNode(childId),
	parent;
	if (child && (parent = child.parent)) {
		var nextNode = child.nextNode();
		if (nextNode) {
			nextNode.up();
		}
	}
	return this;
}

o.nextNode = function (childId) {
	var child = this._getNode(childId);
	if (child) {
		var parent = child.parent,
		index = child.position(),
		nextChildId = parent._childIdsList[index + 1];

		if (nextChildId) {
			return parent.getChild(nextChildId);
		}
	}
}

o.prevNode = function (childId) {
	var child = this._getNode(childId);
	if (child) {
		var parent = child.parent,
		index = child.position(),
		prevChildId = parent._childIdsList[index - 1];

		if (prevChildId) {
			return parent.getChild(prevChildId);
		}
	}
}

// move childId node to  parentId node.
o.move = function (childId, parentId) {

	var child = this.getChild(childId),
	parent = parentId === this.parent ? this : this.getChild(parentId);

	if (child && parent && !child.getChild(parentId)) {
		var childParent = child.parent;
		childParent.removeChild(child.id);
		parent.appendChild(child);
	}

	return this;

}

o.isRoot = function () {
	return this.parent ? false : true;
}

o.data = function () {

	var obj = {}

	if (arguments.length === 2) {
		obj[arguments[0]] = arguments[1];
	} else if (arguments.length === 1) {
		if (typeof arguments[0] === "string") {
			return this._data[arguments[0]];
		} else {
			obj = arguments[0];
		}
	} else {
		return this._data;
	}

	for (var k in obj) {
		this._data[k] = obj[k];
	}

}

o.reborn = function (jsonObj) {

	if (this._childIdsList.length === 0 && this.isRoot()) {
		var self = this;
		this._id = jsonObj.id;
		this._childs = {};
		this._childIdsList = [];
		this._parent = jsonObj.parent;
		this._data = jsonObj.data;

		jsonObj.childIdsList.forEach(function (cid) {
			var child = new Node();
			child.reborn(jsonObj.childs[cid]);
			self._childs[cid] = child;
		});
	}
	return this;

}

Object.defineProperties(o, {

	parent : {
		get : function () {
			return this._parent;
		}
	},

	id : {
		get : function () {
			return this._id;
		}
	},

	route : {
		get : function () {
			var route = [this.id],
			parent = this.parent;
			while (parent) {
				route.unshift(parent.id);
				parent = parent.parent;
			}
			return route;
		}
	},

	root : {
		get : function () {
			var root = this.parent;
			while (root) {
				root = root.parent;
			}
			return root || this;
		}
	},

	json : {
		get : function () {

			var jsonObj = {
				id : this._id,
				childs : {},
				childIdsList : this._childIdsList,
				parent : this._parent ? this._parent.id : null,
				data : this._data
			},
			self = this;

			this._childIdsList.forEach(function (cid) {
				jsonObj.childs[cid] = self._childs[cid].json;
			})

			return JSON.parse(JSON.stringify(jsonObj));

		}
	}

});
<|endoftext|>


<commit_before>'use strict'

var MongoClient = require('mongodb').MongoClient,
	assert = require('assert'),
	gameCode = require('./gameCode'),
	chess = require('./chess');
const express = require('express'),
	bodyParser = require('body-parser'),
	request = require('request'),
	app = express(),
	token = process.env.PAGE_ACCESS_TOKEN,
	mongoURI = process.env.MONGODB_URI;

MongoClient.connect(mongoURI , function(err, db) {
  assert.equal(null, err);
  console.log("Connected successfully to Mongo server");

  db.close();
});

app.set('port', (process.env.PORT || 5000))

// Spin up the server
app.listen(app.get('port'), function() {
	console.log('running on port', app.get('port'))
})

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

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

// Index route
app.get('/', function(req, res) {
	res.send('App Online!')
})

// for Facebook verification
app.get('/webhook/', function(req, res) {
	if (req.query['hub.mode'] && req.query['hub.verify_token'] === process.env.VERIFY_TOKEN) {
		res.status(200).send(req.query['hub.challenge'])
	} else {
		res.send('Error, wrong token')
	}
})

app.post('/webhook/', function(req, res) {
	let messaging_events = req.body.entry[0].messaging
	for (let i = 0; i < messaging_events.length; i++) {
		let event = req.body.entry[0].messaging[i];
		let sender = event.sender.id;
		let timestamp = event.timestamp;
 		if (event.message && event.message.text) {
			let text = event.message.text;
			messageHandler(sender, text);
			// logMessage(sender, text, timestamp);
			// repeatLastMessages(sender);
		}
	}
	res.sendStatus(200)
})

function logMessage(sender, text, timestamp){
	MongoClient.connect(mongoURI , function(err, db) {
		assert.equal(null, err);
		var message = { "sender": sender, "text":text, "timestamp":time};
		db.collection("datamine").insertOne(message, function(err, res) {
			if (err) throw err;
			console.log("MESSAGE WAS LOGGED");
			db.close();
		})
	});
}

function repeatLastMessages(sender){
	MongoClient.connect(mongoURI , function(err, db) {
		assert.equal(null, err);
		//Find latest 3 message from this user
		var cursor = db.collection("datamine").find({"sender":sender}).sort({"timestamp":-1}).limit(3);

		cursor.toArray(function(err, results) {
			if (err) throw err;
			var message = "";
			//Compress messages to one message and send it
			for(var i = 0; i < results.length; i++){
				message += results[i].text + "\n";
			}
			sendTextMessage(sender, message);
			db.close();
		})
	});
}

function messageHandler(sender, text){
	//array of split terms from the command

	let textSplit = text.toLowerCase().split(" ");
	//if the message does not call out the chat bot, it is not a command
	if(textSplit[0] !== "@chess-bot" && textSplit[0] !== "@chess"){
		return null;
	}

	switch(textSplit[1]){
		case "hey":
			sendTextMessage(sender, "Hey!" + sender.toString());
			break;
		case "create":
			initGame(sender);
			sendTextMessage(sender, chess.initBoard().toString());
			gameCode.genCode("./dict.json", mongoURI).then(function (fulfilled){
				sendTextMessage(sender, fulfilled);
			});
			break;
		case "accept": //accept should have bulletproofing that game with same p1 and p2 already exists
			break;
		case "move":
			break;
		case "resign":
			break;
		case "draw":
			break;
		case "help":
			sendHelp(sender);
			break;
		default:
			sendTextMessage(sender, "That's no command");
			sendHelp(sender);
			break;
	}
}

function initGame(sender){
	MongoClient.connect(mongoURI , function(err, db) {
		assert.equal(null, err);
		var senderID = sender.toString();
		var game = {"white": senderID,
					"board": chess.initBoard(),
					//"groupChatID": getChatID(); //WIP
					"turnNum": 0,
					"isCheck": false,
					"drawOffered": false,
					"movePiece": 0,
					"moveLocationX": 0,
					"moveLocationY": 0}
		db.collection("games").insertOne(game, function(err, res) {
			if (err) throw err;
			console.log("NEW GAME ADDED! CHALLENGER:" + sender.toString);
			db.close();
		})
	});
}

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)
		}
	})
}

function sendHelp(sender){
	sendTextMessage(sender, "HELP: I'M TRYING DAMNIT!")
}<commit_msg>Fixed Danny's code<commit_after>'use strict'

var MongoClient = require('mongodb').MongoClient,
	assert = require('assert'),
	gameCode = require('./gameCode'),
	chess = require('./chess');
const express = require('express'),
	bodyParser = require('body-parser'),
	request = require('request'),
	app = express(),
	token = process.env.PAGE_ACCESS_TOKEN,
	mongoURI = process.env.MONGODB_URI;

MongoClient.connect(mongoURI , function(err, db) {
  assert.equal(null, err);
  console.log("Connected successfully to Mongo server");

  db.close();
});

app.set('port', (process.env.PORT || 5000))

// Spin up the server
app.listen(app.get('port'), function() {
	console.log('running on port', app.get('port'))
})

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

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

// Index route
app.get('/', function(req, res) {
	res.send('App Online!')
})

// for Facebook verification
app.get('/webhook/', function(req, res) {
	if (req.query['hub.mode'] && req.query['hub.verify_token'] === process.env.VERIFY_TOKEN) {
		res.status(200).send(req.query['hub.challenge'])
	} else {
		res.send('Error, wrong token')
	}
})

app.post('/webhook/', function(req, res) {
	let messaging_events = req.body.entry[0].messaging
	for (let i = 0; i < messaging_events.length; i++) {
		let event = req.body.entry[0].messaging[i];
		let sender = event.sender.id;
		let timestamp = event.timestamp;
 		if (event.message && event.message.text) {
			let text = event.message.text;
			messageHandler(sender, text);
			// logMessage(sender, text, timestamp);
			// repeatLastMessages(sender);
		}
	}
	res.sendStatus(200)
})

function logMessage(sender, text, timestamp){
	MongoClient.connect(mongoURI , function(err, db) {
		assert.equal(null, err);
		var message = { "sender": sender, "text":text, "timestamp":time};
		db.collection("datamine").insertOne(message, function(err, res) {
			if (err) throw err;
			console.log("MESSAGE WAS LOGGED");
			db.close();
		})
	});
}

function repeatLastMessages(sender){
	MongoClient.connect(mongoURI , function(err, db) {
		assert.equal(null, err);
		//Find latest 3 message from this user
		var cursor = db.collection("datamine").find({"sender":sender}).sort({"timestamp":-1}).limit(3);

		cursor.toArray(function(err, results) {
			if (err) throw err;
			var message = "";
			//Compress messages to one message and send it
			for(var i = 0; i < results.length; i++){
				message += results[i].text + "\n";
			}
			sendTextMessage(sender, message);
			db.close();
		})
	});
}

function messageHandler(sender, text){
	//array of split terms from the command

	let textSplit = text.toLowerCase().split(" ");
	//if the message does not call out the chat bot, it is not a command
	if(textSplit[0] !== "@chess-bot" && textSplit[0] !== "@chess"){
		return null;
	}

	switch(textSplit[1]){
		case "hey":
			sendTextMessage(sender, "Hey!" + sender.toString());
			break;
		case "create":
			initGame(sender);
			sendTextMessage(sender, chess.initBoard().toString());
			gameCode.genCode("./dict.json", mongoURI).then(function (fulfilled){
				console.log(fulfilled);
				sendTextMessage(sender, fulfilled);
			});
			break;
		case "accept": //accept should have bulletproofing that game with same p1 and p2 already exists
			break;
		case "move":
			break;
		case "resign":
			break;
		case "draw":
			break;
		case "help":
			sendHelp(sender);
			break;
		default:
			sendTextMessage(sender, "That's no command");
			sendHelp(sender);
			break;
	}
}

function initGame(sender){
	MongoClient.connect(mongoURI , function(err, db) {
		assert.equal(null, err);
		var senderID = sender.toString();
		var game = {"white": senderID,
					"board": chess.initBoard(),
					//"groupChatID": getChatID(); //WIP
					"turnNum": 0,
					"isCheck": false,
					"drawOffered": false,
					"movePiece": 0,
					"moveLocationX": 0,
					"moveLocationY": 0}
		db.collection("games").insertOne(game, function(err, res) {
			if (err) throw err;
			console.log("NEW GAME ADDED! CHALLENGER:" + sender.toString);
			db.close();
		})
	});
}

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)
		}
	})
}

function sendHelp(sender){
	sendTextMessage(sender, "HELP: I'M TRYING DAMNIT!")
}<|endoftext|>


<commit_before>'use strict';

module.exports = shrinked;

var jf = require('jsonfile');

// @param {path} file
// @param {Object} options
//   - dependencyKeys {Array}
// @param {function(err, tree)} callback
function shrinked (file, options, callback) {
  if (typeof options === 'function') {
    callback = options;
    options = {};
  }

  jf.readFile(file, function (err, json) {
    if (err) {
      return callback(err);
    }

    var tree = shrinked.parse(json, options);
    return callback(null, tree);
  });
}

shrinked._walk = function (node, keys, host) {
  var name = node.name;
  var version = node.version;

  var pkg = host[name] || (host[name] = {});

  if (pkg[version]) {
    return;
  }

  var current = pkg[version] = {};
  keys.forEach(function (key) {
    var deps = node[key] || {};
    var parsed_deps = current[key] = {};

    var dep_name;
    var dep_info;
    var dep_range;
    var is_empty = true;

    for(dep_name in deps) {
      is_empty = false;

      dep_info = deps[dep_name];
      dep_info.name = dep_name;
      dep_range = shrinked._parseFrom(dep_info.from).range;
      parsed_deps[dep_name] = {};
      parsed_deps[dep_name][dep_range] = dep_info.version;
      shrinked._walk(dep_info, keys, host);
    }

    if (is_empty) {
      delete current[key];
    }
  });
};

// 'a@~0.2.3'
// ->
// {
//   name: 'a',
//   range: '~0.2.3'
// }
shrinked._parseFrom = function(pkg) {
  var split = pkg.split('@');

  return {
    name: split[0],
    range: split[1]
  };
};

shrinked.parse = function (json, options) {
  var tree = {};
  options || (options = {});
  var keys = options.dependencyKeys || ['dependencies'];
  shrinked._walk(json, keys, tree);
  return tree;
};
<commit_msg>check node to improve stability; #1<commit_after>'use strict';

module.exports = shrinked;

var jf = require('jsonfile');

// @param {path} file
// @param {Object} options
//   - dependencyKeys {Array}
// @param {function(err, tree)} callback
function shrinked (file, options, callback) {
  if (typeof options === 'function') {
    callback = options;
    options = {};
  }

  jf.readFile(file, function (err, json) {
    if (err) {
      return callback(err);
    }

    var tree = shrinked.parse(json, options);
    return callback(null, tree);
  });
}

shrinked._walk = function (node, keys, host) {
  var name = node.name;
  var version = node.version;

  var pkg = host[name] || (host[name] = {});

  if (pkg[version]) {
    return;
  }

  var current = pkg[version] = {};
  keys.forEach(function (key) {
    var deps = node[key] || {};
    var parsed_deps = current[key] = {};

    var dep_name;
    var dep_info;
    var dep_range;
    var is_empty = true;

    for(dep_name in deps) {
      is_empty = false;

      dep_info = deps[dep_name];

      // At the toplevel of shrinkwrap.json,
      // there is a `name` field but not for sub level of the object
      // so, we add it.
      dep_info.name = dep_name;

      // `dep_info` must be an object
      if (!shrinked._invalid(dep_info)) {
        continue;
      }

      dep_range = shrinked._parseFrom(dep_info.from).range;
      parsed_deps[dep_name] = {};
      parsed_deps[dep_name][dep_range] = dep_info.version;
      shrinked._walk(dep_info, keys, host);
    }

    if (is_empty) {
      delete current[key];
    }
  });
};

// 'a@~0.2.3'
// ->
// {
//   name: 'a',
//   range: '~0.2.3'
// }
shrinked._parseFrom = function(pkg) {
  var split = pkg.split('@');

  return {
    name: split[0],
    range: split[1]
  };
};

// @param {Object} node
// @returns if a node is invalid
shrinked._invalid = function (node) {
  if (!node || Object(node) !== node) {
    return false;
  }

  return [node.name, node.version, node.from].every(function (str) {
    return str && typeof str === 'string';
  });
};

shrinked.parse = function (json, options) {
  var tree = {};
  options || (options = {});
  var keys = options.dependencyKeys || ['dependencies'];
  shrinked._walk(json, keys, tree);
  return tree;
};
<|endoftext|>


<commit_before>var WebSocketServer = require('websocket').server;
var http = require('http');

var events = {};

var httpServer = http.createServer(function(request,response){
    response.writeHead(404);
    response.end();
});

httpServer.listen(8282);

var server = new WebSocketServer({
    httpServer: httpServer,
    autoAcceptConnections: true
});

server.on('connect', function(conn){
    var eventID;

    console.log("Connection from " + conn.remoteAddress);
    conn.on('message', function(msg){
        try {
            var incoming = JSON.parse(msg.utf8Data);
            eventID = incoming["eventID"];

            if(events.hasOwnProperty(eventID)){
                var connections = events[eventID];

                // Check if this connection is already known
                if(connections.indexOf(conn) === -1)
                    connections.push(conn);

                connections.forEach(function(elem){
                    if (elem !== conn)
                        elem.sendUTF(msg);
                });
            } else {
                // Nobody in this event yet, create new array with
                // this connection as its first element
                var newArray = [];
                newArray.push(conn);
                events[eventID] = newArray;
            }
        } catch (e){
            console.log('Received invalid JSON: ' + e);
        }
    });

    conn.on('close', function(){
        // Remove this connection from the event's connection list
        console.log("Disconnected: " + conn.remoteAddress);
        if(eventID &&
           events.hasOwnProperty(eventID) &&
           events[eventID].indexOf(conn) !== -1)
            events[eventID].splice(events[eventID].indexOf(conn), 1);
    });
});
<commit_msg>Fix bug<commit_after>var WebSocketServer = require('websocket').server;
var http = require('http');

var events = {};

var httpServer = http.createServer(function(request,response){
    response.writeHead(404);
    response.end();
});

httpServer.listen(8282);

var server = new WebSocketServer({
    httpServer: httpServer,
    autoAcceptConnections: true
});

server.on('connect', function(conn){
    var eventID;

    console.log("Connection from " + conn.remoteAddress);
    conn.on('message', function(msg){
        try {
            var incoming = JSON.parse(msg.utf8Data);
            eventID = incoming["eventID"];

            if(events.hasOwnProperty(eventID)){
                var connections = events[eventID];

                // Check if this connection is already known
                if(connections.indexOf(conn) === -1)
                    connections.push(conn);

                connections.forEach(function(elem){
                    if (elem !== conn)
                        elem.sendUTF(msg.utf8Data);
                });
            } else {
                // Nobody in this event yet, create new array with
                // this connection as its first element
                var newArray = [];
                newArray.push(conn);
                events[eventID] = newArray;
            }
        } catch (e){
            console.log('Received invalid JSON: ' + e);
        }
    });

    conn.on('close', function(){
        // Remove this connection from the event's connection list
        console.log("Disconnected: " + conn.remoteAddress);
        if(eventID &&
           events.hasOwnProperty(eventID) &&
           events[eventID].indexOf(conn) !== -1)
            events[eventID].splice(events[eventID].indexOf(conn), 1);
    });
});
<|endoftext|>


<commit_before>var TelegramBot = require('node-telegram-bot-api');
var CREDENTIALS = require('./private/telegram_credentials.json');
var chalk = require('chalk');

var locator = require('./public/api/locator')

var bot = new TelegramBot(CREDENTIALS.token, {
    polling: true
});

console.log(chalk.blue("============================"));
console.log(chalk.blue("                            "));
console.log(chalk.blue("     MusollahBot Started    "));
console.log(chalk.blue("                            "));
console.log(chalk.blue("============================"));
console.log(chalk.blue("                            "));

bot.on('message', function(msg) {
    try {
        console.log(msg);
        if (!msg.hasOwnProperty('text') && !msg.hasOwnProperty('location')) {
            return false;
        }
        if (msg.hasOwnProperty('location')) {
            return locator.processLocation(msg);
        }
        var chatId = msg.chat.id;
        var body = msg.text;
        var command = body;
        var args = body;
        if (body.charAt(0) === '/') {
            command = body.split(' ')[0].substr(1);
            args = body.split(' ')[1];
        }

        switch (command.toLowerCase()) {
            case "start":
                return help(chatId);
            case "musollah":
                return locator.musollahLocator(chatId);
        }
        switch (body.toLowerCase()) {
            default:
                var musollahSession = musollahSessions[chatId] || new musollahSession(chatId);
                if (musollahSession.onGoing) {
                    return locator.musollahLocator(chatId, body.toLowerCase(), msg.location);
                }
        }
        return default_msg(chatId);
    } catch (e) {
        bot.sendMessage(msg.chat.id, "MusollahBot has encountered an Error, please try again later");
        bot.sendMessage('49892469', e.toString());
    }
});

function default_msg(chatId) {
    bot.sendMessage(chatId, "Sorry, I don't understand you! Try another command instead", {
        reply_markup: JSON.stringify({
            hide_keyboard: true
        })
    });
}

<commit_msg>fixed locator error<commit_after>var TelegramBot = require('node-telegram-bot-api');
var CREDENTIALS = require('./private/telegram_credentials.json');
var chalk = require('chalk');

var locator = require('./public/api/locator');

var bot = new TelegramBot(CREDENTIALS.token, {
    polling: true
});

console.log(chalk.blue("============================"));
console.log(chalk.blue("                            "));
console.log(chalk.blue("     MusollahBot Started    "));
console.log(chalk.blue("                            "));
console.log(chalk.blue("============================"));
console.log(chalk.blue("                            "));

bot.on('message', function(msg) {
    try {
        console.log(msg);
        if (!msg.hasOwnProperty('text') && !msg.hasOwnProperty('location')) {
            return false;
        }
        if (msg.hasOwnProperty('location')) {
            return locator.processLocation(msg);
        }
        var chatId = msg.chat.id;
        var body = msg.text;
        var command = body;
        var args = body;
        if (body.charAt(0) === '/') {
            command = body.split(' ')[0].substr(1);
            args = body.split(' ')[1];
        }

        switch (command.toLowerCase()) {
            case "start":
                return help(chatId);
            case "musollah":
                return locator.musollahLocator(chatId);
        }
        switch (body.toLowerCase()) {
            default:
                var musollahSession = musollahSessions[chatId] || new musollahSession(chatId);
                if (musollahSession.onGoing) {
                    return locator.musollahLocator(chatId, body.toLowerCase(), msg.location);
                }
        }
        return default_msg(chatId);
    } catch (e) {
        bot.sendMessage(msg.chat.id, "MusollahBot has encountered an Error, please try again later");
        bot.sendMessage('49892469', e.toString());
    }
});

function default_msg(chatId) {
    bot.sendMessage(chatId, "Sorry, I don't understand you! Try another command instead", {
        reply_markup: JSON.stringify({
            hide_keyboard: true
        })
    });
}

<|endoftext|>


<commit_before>var express    = require('express');
var bodyParser = require('body-parser');
var crypto     = require('crypto');

function smartTrim(str, length, delim, appendix) {
    if (str.length <= length) {
        return str;
    }

    var trimmedStr     = str.substr(0, length+delim.length);
    var lastDelimIndex = trimmedStr.lastIndexOf(delim);

    if (lastDelimIndex >= 0) {
        trimmedStr = trimmedStr.substr(0, lastDelimIndex);
    }

    if (trimmedStr) {
        trimmedStr += appendix;
    }

    return trimmedStr;
}

var app = express();

app.use(bodyParser.json());

app.post('/', function (req, res) {
    var body      = JSON.stringify(req.body);

    var hmac      = crypto.createHmac('sha1', process.env.GITHUBTOKEN);
    var payload   = hmac.update(body);
    var signature = new Buffer(hmac.digest('hex')).toString();

    // Signatures are matching..
    if (req.headers['x-hub-signature'] === 'sha1=' + signature) {
        // Any time a Commit is commented on.
        if (req.headers['x-github-event'] === 'commit_comment') {
            console.log('[' + req.body['repository']['full_name'] + '] ' + req.body['comment']['user']['login'] + ' commented on commit #' + req.body['comment']['commit_id'].substring(0, 7) + ': ' + smartTrim(req.body['comment']['body'], 50, ' ', '...') + ' - ' + req.body['comment']['html_url']);
        }
        // Any time a Branch or Tag is created.
        else if (req.headers['x-github-event'] === 'create') {

        }
        // Any time a Branch or Tag is deleted.
        else if (req.headers['x-github-event'] === 'delete') {

        }
        // Any time a Repository has a new deployment created from the API.
        else if (req.headers['x-github-event'] === 'deployment') {

        }
        // Any time a deployment for a Repository has a status update from the API.
        else if (req.headers['x-github-event'] === 'deployment_status') {
            console.log('[' + req.body['repository']['full_name'] + '] ' + req.body['comment']['user']['login'] + ' commented on issue #' + req.body['issue']['number'] + ': ' + smartTrim(req.body['comment']['body'], 50, ' ', '...') + ' - ' + req.body['comment']['html_url']);
        }
        // Any time a Repository is forked.
        else if (req.headers['x-github-event'] === 'fork') {
            console.log('[' + req.body['repository']['full_name'] + '] ' + req.body['issue']['user']['login'] + ' ' + req.body['action'] + ' issue #' + req.body['issue']['number'] + ': ' + req.body['issue']['title'] + ' - ' + req.body['issue']['html_url']);
        }
        // Any time a Wiki page is updated.
        else if (req.headers['x-github-event'] === 'gollum') {

        }
        // Any time an Issue is commented on.
        else if (req.headers['x-github-event'] === 'issue_comment') {

        }
        // Any time an Issue is assigned, unassigned, labeled, unlabeled, opened, closed, or reopened.
        else if (req.headers['x-github-event'] === 'issues') {

        }
        // Any time a User is added as a collaborator to a non-Organization Repository.
        else if (req.headers['x-github-event'] === 'member') {

        }
        // Any time a User is added or removed from a team. Organization hooks only.
        else if (req.headers['x-github-event'] === 'membership') {

        }
        // Any time a Pages site is built or results in a failed build.
        else if (req.headers['x-github-event'] === 'page_build') {

        }
        // Any time a Repository changes from private to public.
        else if (req.headers['x-github-event'] === 'public') {

        }
        // Any time a Commit is commented on while inside a Pull Request review (the Files Changed tab).
        else if (req.headers['x-github-event'] === 'pull_request_review_comment') {
            console.log('[' + req.body['repository']['full_name'] + '] ' + req.body['comment']['user']['login'] + ' commented on pull request #' + req.body['pull_request']['number'] + ': ' + smartTrim(req.body['comment']['body'], 50, ' ', '...') + ' (' + req.body['pull_request']['base']['sha'].substring(0, 7) + ') - ' + req.body['comment']['html_url']);
        }
        // Any time a Pull Request is assigned, unassigned, labeled, unlabeled, opened, closed,
        // reopened, or synchronized (updated due to a new push in the branch that the pull request is tracking).
        else if (req.headers['x-github-event'] === 'pull_request') {
            console.log('[' + req.body['repository']['full_name'] + '] ' + req.body['pull_request']['user']['login'] + ' ' + req.body['action'] + ' pull request #' + req.body['pull_request']['number'] + ': ' + req.body['pull_request']['title'] + ' [' + req.body['pull_request']['base']['ref'] + '/' + req.body['pull_request']['head']['ref'] + '] - ' + req.body['pull_request']['html_url']);
        }
        // Any Git push to a Repository, including editing tags or branches. Commits via API actions that
        // update references are also counted. This is the default event.
        else if (req.headers['x-github-event'] === 'push') {
            var message = [];

            message.push('[' + req.body['repository']['full_name'] + '] ' + req.body['pusher']['name']);

            if (req.body['created']) {
                if (req.body['ref'].indexOf('refs/tags') >= 0) {
                    message.push('tagged ' + req.body['ref'].split('/')[2] + ' at ' + req.body['after'].substring(0, 7) + ' - ' + req.body['repository']['html_url'] + '/tags');
                }
                else {
                    message.push('created ' + req.body['ref'].split('/')[2]);

                    if (req.body['base_ref']) {
                        message.push('from ' + req.body['base_ref'].split('/')[2]);
                    }
                    else if (req.body['head_commit']['distinct']) {
                        message.push('at ' + req.body['after'].substring(0, 7));
                    }

                    if (req.body['commits'].length >= 1) {
                        message.push(req.body['commits'].length + ' new commit(s) - ' + req.body['head_commit']['url']);
                    }
                }
            }
            else if (req.body['deleted']) {
                message.push('deleted ' + req.body['ref'].split('/')[2] + ' at ' + req.body['before'].substring(0, 7));
            }
            else if (req.body['forced']) {
                message.push('deleted ' + req.body['ref'].split('/')[2] + ' from ' + req.body['before'].substring(0, 7) + ' to ' + req.body['after'].substring(0, 7));
            }
            else if (req.body['commits'].length >= 1 && !req.body['head_commit']['distinct']) {
                if (req.body['base_ref']) {
                    message.push('merged ' + req.body['base_ref'].split('/')[2] + ' into ' + req.body['ref'].split('/')[2]);
                }
                else {
                    message.push('fast-forwarded ' + req.body['ref'].split('/')[2] + ' from ' + req.body['before'].substring(0, 7) + ' to ' + req.body['after'].substring(0, 7));
                }
            }
            else {
                message.push('pushed ' + req.body['commits'].length + ' new commit(s) to ' + req.body['ref'].split('/')[2] + ' - ' + req.body['head_commit']['url']);
            }

            console.log(message.join(' '));
        }
        // Any time a Repository is created. Organization hooks only.
        else if (req.headers['x-github-event'] === 'repository') {

        }
        // Any time a Release is published in a Repository.
        else if (req.headers['x-github-event'] === 'release') {

        }
        // Any time a Repository has a status update from the API
        else if (req.headers['x-github-event'] === 'status') {

        }
        // Any time a team is added or modified on a Repository.
        else if (req.headers['x-github-event'] === 'team_add') {

        }
        // Any time a User watches a Repository.
        else if (req.headers['x-github-event'] === 'watch') {

        }
    }

    res.send({});
});

var server = app.listen(3000, function () {

    var host = server.address().address;
    var port = server.address().port;

    console.log('App listening at http://%s:%s', host, port)

});<commit_msg>Added gollum.<commit_after>var express    = require('express');
var bodyParser = require('body-parser');
var crypto     = require('crypto');

function smartTrim(str, length, delim, appendix) {
    if (str.length <= length) {
        return str;
    }

    var trimmedStr     = str.substr(0, length+delim.length);
    var lastDelimIndex = trimmedStr.lastIndexOf(delim);

    if (lastDelimIndex >= 0) {
        trimmedStr = trimmedStr.substr(0, lastDelimIndex);
    }

    if (trimmedStr) {
        trimmedStr += appendix;
    }

    return trimmedStr;
}

var app = express();

app.use(bodyParser.json());

app.post('/', function (req, res) {
    var body      = JSON.stringify(req.body);

    var hmac      = crypto.createHmac('sha1', process.env.GITHUBTOKEN);
    var payload   = hmac.update(body);
    var signature = new Buffer(hmac.digest('hex')).toString();

    // Signatures are matching..
    if (req.headers['x-hub-signature'] === 'sha1=' + signature) {
        // Any time a Commit is commented on.
        if (req.headers['x-github-event'] === 'commit_comment') {
            console.log('[' + req.body['repository']['full_name'] + '] ' + req.body['comment']['user']['login'] + ' commented on commit #' + req.body['comment']['commit_id'].substring(0, 7) + ': ' + smartTrim(req.body['comment']['body'], 50, ' ', '...') + ' - ' + req.body['comment']['html_url']);
        }
        // Any time a Branch or Tag is created.
        else if (req.headers['x-github-event'] === 'create') {

        }
        // Any time a Branch or Tag is deleted.
        else if (req.headers['x-github-event'] === 'delete') {

        }
        // Any time a Repository has a new deployment created from the API.
        else if (req.headers['x-github-event'] === 'deployment') {
            console.log('[' + req.body['repository']['full_name'] + '] ' + req.body['sender']['login'] + ' updated the wiki page \'' + req.body['pages'][0]['page_name'] + '\' - ' + req.body['pages'][0]['html_url']);
        }
        // Any time a deployment for a Repository has a status update from the API.
        else if (req.headers['x-github-event'] === 'deployment_status') {
            console.log('[' + req.body['repository']['full_name'] + '] ' + req.body['comment']['user']['login'] + ' commented on issue #' + req.body['issue']['number'] + ': ' + smartTrim(req.body['comment']['body'], 50, ' ', '...') + ' - ' + req.body['comment']['html_url']);
        }
        // Any time a Repository is forked.
        else if (req.headers['x-github-event'] === 'fork') {
            console.log('[' + req.body['repository']['full_name'] + '] ' + req.body['issue']['user']['login'] + ' ' + req.body['action'] + ' issue #' + req.body['issue']['number'] + ': ' + req.body['issue']['title'] + ' - ' + req.body['issue']['html_url']);
        }
        // Any time a Wiki page is updated.
        else if (req.headers['x-github-event'] === 'gollum') {

        }
        // Any time an Issue is commented on.
        else if (req.headers['x-github-event'] === 'issue_comment') {

        }
        // Any time an Issue is assigned, unassigned, labeled, unlabeled, opened, closed, or reopened.
        else if (req.headers['x-github-event'] === 'issues') {

        }
        // Any time a User is added as a collaborator to a non-Organization Repository.
        else if (req.headers['x-github-event'] === 'member') {

        }
        // Any time a User is added or removed from a team. Organization hooks only.
        else if (req.headers['x-github-event'] === 'membership') {

        }
        // Any time a Pages site is built or results in a failed build.
        else if (req.headers['x-github-event'] === 'page_build') {

        }
        // Any time a Repository changes from private to public.
        else if (req.headers['x-github-event'] === 'public') {

        }
        // Any time a Commit is commented on while inside a Pull Request review (the Files Changed tab).
        else if (req.headers['x-github-event'] === 'pull_request_review_comment') {
            console.log('[' + req.body['repository']['full_name'] + '] ' + req.body['comment']['user']['login'] + ' commented on pull request #' + req.body['pull_request']['number'] + ': ' + smartTrim(req.body['comment']['body'], 50, ' ', '...') + ' (' + req.body['pull_request']['base']['sha'].substring(0, 7) + ') - ' + req.body['comment']['html_url']);
        }
        // Any time a Pull Request is assigned, unassigned, labeled, unlabeled, opened, closed,
        // reopened, or synchronized (updated due to a new push in the branch that the pull request is tracking).
        else if (req.headers['x-github-event'] === 'pull_request') {
            console.log('[' + req.body['repository']['full_name'] + '] ' + req.body['pull_request']['user']['login'] + ' ' + req.body['action'] + ' pull request #' + req.body['pull_request']['number'] + ': ' + req.body['pull_request']['title'] + ' [' + req.body['pull_request']['base']['ref'] + '/' + req.body['pull_request']['head']['ref'] + '] - ' + req.body['pull_request']['html_url']);
        }
        // Any Git push to a Repository, including editing tags or branches. Commits via API actions that
        // update references are also counted. This is the default event.
        else if (req.headers['x-github-event'] === 'push') {
            var message = [];

            message.push('[' + req.body['repository']['full_name'] + '] ' + req.body['pusher']['name']);

            if (req.body['created']) {
                if (req.body['ref'].indexOf('refs/tags') >= 0) {
                    message.push('tagged ' + req.body['ref'].split('/')[2] + ' at ' + req.body['after'].substring(0, 7) + ' - ' + req.body['repository']['html_url'] + '/tags');
                }
                else {
                    message.push('created ' + req.body['ref'].split('/')[2]);

                    if (req.body['base_ref']) {
                        message.push('from ' + req.body['base_ref'].split('/')[2]);
                    }
                    else if (req.body['head_commit']['distinct']) {
                        message.push('at ' + req.body['after'].substring(0, 7));
                    }

                    if (req.body['commits'].length >= 1) {
                        message.push(req.body['commits'].length + ' new commit(s) - ' + req.body['head_commit']['url']);
                    }
                }
            }
            else if (req.body['deleted']) {
                message.push('deleted ' + req.body['ref'].split('/')[2] + ' at ' + req.body['before'].substring(0, 7));
            }
            else if (req.body['forced']) {
                message.push('deleted ' + req.body['ref'].split('/')[2] + ' from ' + req.body['before'].substring(0, 7) + ' to ' + req.body['after'].substring(0, 7));
            }
            else if (req.body['commits'].length >= 1 && !req.body['head_commit']['distinct']) {
                if (req.body['base_ref']) {
                    message.push('merged ' + req.body['base_ref'].split('/')[2] + ' into ' + req.body['ref'].split('/')[2]);
                }
                else {
                    message.push('fast-forwarded ' + req.body['ref'].split('/')[2] + ' from ' + req.body['before'].substring(0, 7) + ' to ' + req.body['after'].substring(0, 7));
                }
            }
            else {
                message.push('pushed ' + req.body['commits'].length + ' new commit(s) to ' + req.body['ref'].split('/')[2] + ' - ' + req.body['head_commit']['url']);
            }

            console.log(message.join(' '));
        }
        // Any time a Repository is created. Organization hooks only.
        else if (req.headers['x-github-event'] === 'repository') {

        }
        // Any time a Release is published in a Repository.
        else if (req.headers['x-github-event'] === 'release') {

        }
        // Any time a Repository has a status update from the API
        else if (req.headers['x-github-event'] === 'status') {

        }
        // Any time a team is added or modified on a Repository.
        else if (req.headers['x-github-event'] === 'team_add') {

        }
        // Any time a User watches a Repository.
        else if (req.headers['x-github-event'] === 'watch') {

        }
    }

    res.send({});
});

var server = app.listen(3000, function () {

    var host = server.address().address;
    var port = server.address().port;

    console.log('App listening at http://%s:%s', host, port)

});<|endoftext|>


<commit_before>'use strict'
var fs = require('fs');
var CSSJSON = require('cssjson');

var source = process.argv.splice(2)[0];
var target = source.substring(0, source.lastIndexOf('.')) + '.css';

fs.readFile(source, 'utf-8', function(err, data){
  if (err){throw err;}

  var parser = function (input){
    var css = CSSJSON.toJSON(input);
    for (var key in css.children){
      var val = css.children[key].attributes;
      switch (val.somewhat){
        case '"blueish"':
          val.somewhat = '"blue"';
          break;
        case '"redish"':
          val.somewhat = '"red"';
          break;
        default:
      }
    }
    return CSSJSON.toCSS(css);
  };

  var output = parser(data);

  fs.writeFile(target, output, function(err) {
      if (err) {throw err;}
      console.log('Wrote ' + target + '!');
   });
});
<commit_msg>converts to postcss plugin style<commit_after>'use strict'
var fs = require('fs');dd
var postcss = require('postcss');

var source = process.argv.splice(2)[0];
var target = source.substring(0, source.lastIndexOf('.')) + '.css';

module.exports = postcss.plugin('closecss', function (opts){
  opts = opts || {};

  return function (css){
    css.eachDecl(function transformDecl(decl){
      console.log(decl.prop);
      console.log(decl.value);
    });
  };
});<|endoftext|>