<commit_before>/*
Language: Ruby
Author: Anton Kovalyov <anton@kovalyov.net>
Contributors: Peter Leonov <gojpeg@yandex.ru>, Vasily Polovnyov <vast@whiteants.net>
*/

hljs.LANGUAGES.ruby = function(){
  var RUBY_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_]*(\\!|\\?)?';
  var RUBY_DEFAULT_CONTAINS = ['comment', 'string', 'char', 'class', 'function', 'constant', 'symbol', 'number', 'variable', 'regexp_container']
  var RUBY_KEYWORDS = {
    'keyword': {'and': 1, 'false': 1, 'then': 1, 'defined': 1, 'module': 1, 'in': 1, 'return': 1, 'redo': 1, 'if': 1, 'BEGIN': 1, 'retry': 1, 'end': 1, 'for': 1, 'true': 1, 'self': 1, 'when': 1, 'next': 1, 'until': 1, 'do': 1, 'begin': 1, 'unless': 1, 'END': 1, 'rescue': 1, 'nil': 1, 'else': 1, 'break': 1, 'undef': 1, 'not': 1, 'super': 1, 'class': 1, 'case': 1, 'require': 1, 'yield': 1, 'alias': 1, 'while': 1, 'ensure': 1, 'elsif': 1, 'or': 1, 'def': 1},
    'keymethods': {'__id__': 1, '__send__': 1, 'abort': 1, 'abs': 1, 'all?': 1, 'allocate': 1, 'ancestors': 1, 'any?': 1, 'arity': 1, 'assoc': 1, 'at': 1, 'at_exit': 1, 'autoload': 1, 'autoload?': 1, 'between?': 1, 'binding': 1, 'binmode': 1, 'block_given?': 1, 'call': 1, 'callcc': 1, 'caller': 1, 'capitalize': 1, 'capitalize!': 1, 'casecmp': 1, 'catch': 1, 'ceil': 1, 'center': 1, 'chomp': 1, 'chomp!': 1, 'chop': 1, 'chop!': 1, 'chr': 1, 'class': 1, 'class_eval': 1, 'class_variable_defined?': 1, 'class_variables': 1, 'clear': 1, 'clone': 1, 'close': 1, 'close_read': 1, 'close_write': 1, 'closed?': 1, 'coerce': 1, 'collect': 1, 'collect!': 1, 'compact': 1, 'compact!': 1, 'concat': 1, 'const_defined?': 1, 'const_get': 1, 'const_missing': 1, 'const_set': 1, 'constants': 1, 'count': 1, 'crypt': 1, 'default': 1, 'default_proc': 1, 'delete': 1, 'delete!': 1, 'delete_at': 1, 'delete_if': 1, 'detect': 1, 'display': 1, 'div': 1, 'divmod': 1, 'downcase': 1, 'downcase!': 1, 'downto': 1, 'dump': 1, 'dup': 1, 'each': 1, 'each_byte': 1, 'each_index': 1, 'each_key': 1, 'each_line': 1, 'each_pair': 1, 'each_value': 1, 'each_with_index': 1, 'empty?': 1, 'entries': 1, 'eof': 1, 'eof?': 1, 'eql?': 1, 'equal?': 1, 'eval': 1, 'exec': 1, 'exit': 1, 'exit!': 1, 'extend': 1, 'fail': 1, 'fcntl': 1, 'fetch': 1, 'fileno': 1, 'fill': 1, 'find': 1, 'find_all': 1, 'first': 1, 'flatten': 1, 'flatten!': 1, 'floor': 1, 'flush': 1, 'for_fd': 1, 'foreach': 1, 'fork': 1, 'format': 1, 'freeze': 1, 'frozen?': 1, 'fsync': 1, 'getc': 1, 'gets': 1, 'global_variables': 1, 'grep': 1, 'gsub': 1, 'gsub!': 1, 'has_key?': 1, 'has_value?': 1, 'hash': 1, 'hex': 1, 'id': 1, 'include?': 1, 'included_modules': 1, 'index': 1, 'indexes': 1, 'indices': 1, 'induced_from': 1, 'inject': 1, 'insert': 1, 'inspect': 1, 'instance_eval': 1, 'instance_method': 1, 'instance_methods': 1, 'instance_of?': 1, 'instance_variable_defined?': 1, 'instance_variable_get': 1, 'instance_variable_set': 1, 'instance_variables': 1, 'integer?': 1, 'intern': 1, 'invert': 1, 'ioctl': 1, 'is_a?': 1, 'isatty': 1, 'iterator?': 1, 'join': 1, 'key?': 1, 'keys': 1, 'kind_of?': 1, 'lambda': 1, 'last': 1, 'length': 1, 'lineno': 1, 'ljust': 1, 'load': 1, 'local_variables': 1, 'loop': 1, 'lstrip': 1, 'lstrip!': 1, 'map': 1, 'map!': 1, 'match': 1, 'max': 1, 'member?': 1, 'merge': 1, 'merge!': 1, 'method': 1, 'method_defined?': 1, 'method_missing': 1, 'methods': 1, 'min': 1, 'module_eval': 1, 'modulo': 1, 'name': 1, 'nesting': 1, 'new': 1, 'next': 1, 'next!': 1, 'nil?': 1, 'nitems': 1, 'nonzero?': 1, 'object_id': 1, 'oct': 1, 'open': 1, 'pack': 1, 'partition': 1, 'pid': 1, 'pipe': 1, 'pop': 1, 'popen': 1, 'pos': 1, 'prec': 1, 'prec_f': 1, 'prec_i': 1, 'print': 1, 'printf': 1, 'private_class_method': 1, 'private_instance_methods': 1, 'private_method_defined?': 1, 'private_methods': 1, 'proc': 1, 'protected_instance_methods': 1, 'protected_method_defined?': 1, 'protected_methods': 1, 'public_class_method': 1, 'public_instance_methods': 1, 'public_method_defined?': 1, 'public_methods': 1, 'push': 1, 'putc': 1, 'puts': 1, 'quo': 1, 'raise': 1, 'rand': 1, 'rassoc': 1, 'read': 1, 'read_nonblock': 1, 'readchar': 1, 'readline': 1, 'readlines': 1, 'readpartial': 1, 'rehash': 1, 'reject': 1, 'reject!': 1, 'remainder': 1, 'reopen': 1, 'replace': 1, 'require': 1, 'respond_to?': 1, 'reverse': 1, 'reverse!': 1, 'reverse_each': 1, 'rewind': 1, 'rindex': 1, 'rjust': 1, 'round': 1, 'rstrip': 1, 'rstrip!': 1, 'scan': 1, 'seek': 1, 'select': 1, 'send': 1, 'set_trace_func': 1, 'shift': 1, 'singleton_method_added': 1, 'singleton_methods': 1, 'size': 1, 'sleep': 1, 'slice': 1, 'slice!': 1, 'sort': 1, 'sort!': 1, 'sort_by': 1, 'split': 1, 'sprintf': 1, 'squeeze': 1, 'squeeze!': 1, 'srand': 1, 'stat': 1, 'step': 1, 'store': 1, 'strip': 1, 'strip!': 1, 'sub': 1, 'sub!': 1, 'succ': 1, 'succ!': 1, 'sum': 1, 'superclass': 1, 'swapcase': 1, 'swapcase!': 1, 'sync': 1, 'syscall': 1, 'sysopen': 1, 'sysread': 1, 'sysseek': 1, 'system': 1, 'syswrite': 1, 'taint': 1, 'tainted?': 1, 'tell': 1, 'test': 1, 'throw': 1, 'times': 1, 'to_a': 1, 'to_ary': 1, 'to_f': 1, 'to_hash': 1, 'to_i': 1, 'to_int': 1, 'to_io': 1, 'to_proc': 1, 'to_s': 1, 'to_str': 1, 'to_sym': 1, 'tr': 1, 'tr!': 1, 'tr_s': 1, 'tr_s!': 1, 'trace_var': 1, 'transpose': 1, 'trap': 1, 'truncate': 1, 'tty?': 1, 'type': 1, 'ungetc': 1, 'uniq': 1, 'uniq!': 1, 'unpack': 1, 'unshift': 1, 'untaint': 1, 'untrace_var': 1, 'upcase': 1, 'upcase!': 1, 'update': 1, 'upto': 1, 'value?': 1, 'values': 1, 'values_at': 1, 'warn': 1, 'write': 1, 'write_nonblock': 1, 'zero?': 1, 'zip': 1}
  }
  return {
    defaultMode: {
      lexems: [RUBY_IDENT_RE],
      contains: RUBY_DEFAULT_CONTAINS,
      keywords: RUBY_KEYWORDS
    },
    modes: [
      {
        className: 'comment',
        begin: '#', end: '$',
        contains: ['yardoctag'],
        relevance: 10
      },
      {
        className: 'yardoctag',
        begin: '@[A-Za-z]+', end: '^'
      },
      {
        className: 'comment',
        begin: '^\\=begin', end: '^\\=end',
        contains: ['yardoctag'],
        relevance: 10
      },
      {
        className: 'comment',
        begin: '^__END__', end: '\\n$'
      },
      {
        className: 'params',
        begin: '\\(', end: '\\)',
        lexems: [RUBY_IDENT_RE],
        keywords: RUBY_KEYWORDS,
        contains: RUBY_DEFAULT_CONTAINS
      },
      {
        className: 'function',
        begin: '\\bdef\\b', end: '$|;',
        lexems: [RUBY_IDENT_RE],
        keywords: RUBY_KEYWORDS,
        contains: ['title', 'params', 'comment']
      },
      {
        className: 'class',
        begin: '\\b(class|module)\\b', end: '$|;',
        lexems: [hljs.UNDERSCORE_IDENT_RE],
        keywords: RUBY_KEYWORDS,
        contains: ['title', 'inheritance', 'comment'],
        keywords: {'class': 1, 'module': 1}
      },
      {
        className: 'title',
        begin: '[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?', end: '^',
        relevance: 0
      },
      {
        className: 'inheritance',
        begin: '<\\s*', end: '^',
        contains: ['parent']
      },
      {
        className: 'parent',
        begin: '(' + hljs.IDENT_RE + '::)?' + hljs.IDENT_RE, end: '^'
      },
      {
        className: 'number',
        begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b', end: '^',
        relevance: 0
      },
      {
        className: 'number',
        begin: '\\?\\w', end: '^'
      },
      {
        className: 'string',
        begin: '\'', end: '\'',
        contains: ['escape', 'subst'],
        relevance: 0
      },
      {
        className: 'string',
        begin: '"', end: '"',
        contains: ['escape', 'subst'],
        relevance: 0
      },
      {
        className: 'string',
        begin: '%[qw]?\\(', end: '\\)',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?\\[', end: '\\]',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?{', end: '}',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?<', end: '>',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?/', end: '/',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?%', end: '%',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?-', end: '-',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?\\|', end: '\\|',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'constant',
        begin: '(::)?([A-Z]\\w*(::)?)+', end: '^',
      },
      {
        className: 'symbol',
        begin: ':' + RUBY_IDENT_RE, end: '^'
      },
      {
        className: 'symbol',
        begin: ':', end: '^',
        contains: ['string']
      },
      hljs.BACKSLASH_ESCAPE,
      {
        className: 'subst',
        begin: '#\\{', end: '}',
        lexems: [RUBY_IDENT_RE],
        keywords: RUBY_KEYWORDS,
        contains: RUBY_DEFAULT_CONTAINS
      },
      {
        className: 'regexp_container',
        begin: '(' + hljs.RE_STARTERS_RE + ')\\s*', end: '^', noMarkup: true,
        contains: ['comment', 'regexp'],
        relevance: 0
      },
      {
        className: 'regexp',
        begin: '/', end: '/[a-z]*',
        illegal: '\\n',
        contains: ['escape']
      },
      {
        className: 'variable',
        begin: '(\\$\\W)|((\\$|\\@\\@?)(\\w+))', end: '^'
      }
    ]
  };
}();
<commit_msg>Ruby comments should not prioritize language auto-detection<commit_after>/*
Language: Ruby
Author: Anton Kovalyov <anton@kovalyov.net>
Contributors: Peter Leonov <gojpeg@yandex.ru>, Vasily Polovnyov <vast@whiteants.net>
*/

hljs.LANGUAGES.ruby = function(){
  var RUBY_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_]*(\\!|\\?)?';
  var RUBY_DEFAULT_CONTAINS = ['comment', 'string', 'char', 'class', 'function', 'constant', 'symbol', 'number', 'variable', 'regexp_container']
  var RUBY_KEYWORDS = {
    'keyword': {'and': 1, 'false': 1, 'then': 1, 'defined': 1, 'module': 1, 'in': 1, 'return': 1, 'redo': 1, 'if': 1, 'BEGIN': 1, 'retry': 1, 'end': 1, 'for': 1, 'true': 1, 'self': 1, 'when': 1, 'next': 1, 'until': 1, 'do': 1, 'begin': 1, 'unless': 1, 'END': 1, 'rescue': 1, 'nil': 1, 'else': 1, 'break': 1, 'undef': 1, 'not': 1, 'super': 1, 'class': 1, 'case': 1, 'require': 1, 'yield': 1, 'alias': 1, 'while': 1, 'ensure': 1, 'elsif': 1, 'or': 1, 'def': 1},
    'keymethods': {'__id__': 1, '__send__': 1, 'abort': 1, 'abs': 1, 'all?': 1, 'allocate': 1, 'ancestors': 1, 'any?': 1, 'arity': 1, 'assoc': 1, 'at': 1, 'at_exit': 1, 'autoload': 1, 'autoload?': 1, 'between?': 1, 'binding': 1, 'binmode': 1, 'block_given?': 1, 'call': 1, 'callcc': 1, 'caller': 1, 'capitalize': 1, 'capitalize!': 1, 'casecmp': 1, 'catch': 1, 'ceil': 1, 'center': 1, 'chomp': 1, 'chomp!': 1, 'chop': 1, 'chop!': 1, 'chr': 1, 'class': 1, 'class_eval': 1, 'class_variable_defined?': 1, 'class_variables': 1, 'clear': 1, 'clone': 1, 'close': 1, 'close_read': 1, 'close_write': 1, 'closed?': 1, 'coerce': 1, 'collect': 1, 'collect!': 1, 'compact': 1, 'compact!': 1, 'concat': 1, 'const_defined?': 1, 'const_get': 1, 'const_missing': 1, 'const_set': 1, 'constants': 1, 'count': 1, 'crypt': 1, 'default': 1, 'default_proc': 1, 'delete': 1, 'delete!': 1, 'delete_at': 1, 'delete_if': 1, 'detect': 1, 'display': 1, 'div': 1, 'divmod': 1, 'downcase': 1, 'downcase!': 1, 'downto': 1, 'dump': 1, 'dup': 1, 'each': 1, 'each_byte': 1, 'each_index': 1, 'each_key': 1, 'each_line': 1, 'each_pair': 1, 'each_value': 1, 'each_with_index': 1, 'empty?': 1, 'entries': 1, 'eof': 1, 'eof?': 1, 'eql?': 1, 'equal?': 1, 'eval': 1, 'exec': 1, 'exit': 1, 'exit!': 1, 'extend': 1, 'fail': 1, 'fcntl': 1, 'fetch': 1, 'fileno': 1, 'fill': 1, 'find': 1, 'find_all': 1, 'first': 1, 'flatten': 1, 'flatten!': 1, 'floor': 1, 'flush': 1, 'for_fd': 1, 'foreach': 1, 'fork': 1, 'format': 1, 'freeze': 1, 'frozen?': 1, 'fsync': 1, 'getc': 1, 'gets': 1, 'global_variables': 1, 'grep': 1, 'gsub': 1, 'gsub!': 1, 'has_key?': 1, 'has_value?': 1, 'hash': 1, 'hex': 1, 'id': 1, 'include?': 1, 'included_modules': 1, 'index': 1, 'indexes': 1, 'indices': 1, 'induced_from': 1, 'inject': 1, 'insert': 1, 'inspect': 1, 'instance_eval': 1, 'instance_method': 1, 'instance_methods': 1, 'instance_of?': 1, 'instance_variable_defined?': 1, 'instance_variable_get': 1, 'instance_variable_set': 1, 'instance_variables': 1, 'integer?': 1, 'intern': 1, 'invert': 1, 'ioctl': 1, 'is_a?': 1, 'isatty': 1, 'iterator?': 1, 'join': 1, 'key?': 1, 'keys': 1, 'kind_of?': 1, 'lambda': 1, 'last': 1, 'length': 1, 'lineno': 1, 'ljust': 1, 'load': 1, 'local_variables': 1, 'loop': 1, 'lstrip': 1, 'lstrip!': 1, 'map': 1, 'map!': 1, 'match': 1, 'max': 1, 'member?': 1, 'merge': 1, 'merge!': 1, 'method': 1, 'method_defined?': 1, 'method_missing': 1, 'methods': 1, 'min': 1, 'module_eval': 1, 'modulo': 1, 'name': 1, 'nesting': 1, 'new': 1, 'next': 1, 'next!': 1, 'nil?': 1, 'nitems': 1, 'nonzero?': 1, 'object_id': 1, 'oct': 1, 'open': 1, 'pack': 1, 'partition': 1, 'pid': 1, 'pipe': 1, 'pop': 1, 'popen': 1, 'pos': 1, 'prec': 1, 'prec_f': 1, 'prec_i': 1, 'print': 1, 'printf': 1, 'private_class_method': 1, 'private_instance_methods': 1, 'private_method_defined?': 1, 'private_methods': 1, 'proc': 1, 'protected_instance_methods': 1, 'protected_method_defined?': 1, 'protected_methods': 1, 'public_class_method': 1, 'public_instance_methods': 1, 'public_method_defined?': 1, 'public_methods': 1, 'push': 1, 'putc': 1, 'puts': 1, 'quo': 1, 'raise': 1, 'rand': 1, 'rassoc': 1, 'read': 1, 'read_nonblock': 1, 'readchar': 1, 'readline': 1, 'readlines': 1, 'readpartial': 1, 'rehash': 1, 'reject': 1, 'reject!': 1, 'remainder': 1, 'reopen': 1, 'replace': 1, 'require': 1, 'respond_to?': 1, 'reverse': 1, 'reverse!': 1, 'reverse_each': 1, 'rewind': 1, 'rindex': 1, 'rjust': 1, 'round': 1, 'rstrip': 1, 'rstrip!': 1, 'scan': 1, 'seek': 1, 'select': 1, 'send': 1, 'set_trace_func': 1, 'shift': 1, 'singleton_method_added': 1, 'singleton_methods': 1, 'size': 1, 'sleep': 1, 'slice': 1, 'slice!': 1, 'sort': 1, 'sort!': 1, 'sort_by': 1, 'split': 1, 'sprintf': 1, 'squeeze': 1, 'squeeze!': 1, 'srand': 1, 'stat': 1, 'step': 1, 'store': 1, 'strip': 1, 'strip!': 1, 'sub': 1, 'sub!': 1, 'succ': 1, 'succ!': 1, 'sum': 1, 'superclass': 1, 'swapcase': 1, 'swapcase!': 1, 'sync': 1, 'syscall': 1, 'sysopen': 1, 'sysread': 1, 'sysseek': 1, 'system': 1, 'syswrite': 1, 'taint': 1, 'tainted?': 1, 'tell': 1, 'test': 1, 'throw': 1, 'times': 1, 'to_a': 1, 'to_ary': 1, 'to_f': 1, 'to_hash': 1, 'to_i': 1, 'to_int': 1, 'to_io': 1, 'to_proc': 1, 'to_s': 1, 'to_str': 1, 'to_sym': 1, 'tr': 1, 'tr!': 1, 'tr_s': 1, 'tr_s!': 1, 'trace_var': 1, 'transpose': 1, 'trap': 1, 'truncate': 1, 'tty?': 1, 'type': 1, 'ungetc': 1, 'uniq': 1, 'uniq!': 1, 'unpack': 1, 'unshift': 1, 'untaint': 1, 'untrace_var': 1, 'upcase': 1, 'upcase!': 1, 'update': 1, 'upto': 1, 'value?': 1, 'values': 1, 'values_at': 1, 'warn': 1, 'write': 1, 'write_nonblock': 1, 'zero?': 1, 'zip': 1}
  }
  return {
    defaultMode: {
      lexems: [RUBY_IDENT_RE],
      contains: RUBY_DEFAULT_CONTAINS,
      keywords: RUBY_KEYWORDS
    },
    modes: [
      {
        className: 'comment',
        begin: '#', end: '$',
        contains: ['yardoctag']
      },
      {
        className: 'yardoctag',
        begin: '@[A-Za-z]+', end: '^'
      },
      {
        className: 'comment',
        begin: '^\\=begin', end: '^\\=end',
        contains: ['yardoctag'],
        relevance: 10
      },
      {
        className: 'comment',
        begin: '^__END__', end: '\\n$'
      },
      {
        className: 'params',
        begin: '\\(', end: '\\)',
        lexems: [RUBY_IDENT_RE],
        keywords: RUBY_KEYWORDS,
        contains: RUBY_DEFAULT_CONTAINS
      },
      {
        className: 'function',
        begin: '\\bdef\\b', end: '$|;',
        lexems: [RUBY_IDENT_RE],
        keywords: RUBY_KEYWORDS,
        contains: ['title', 'params', 'comment']
      },
      {
        className: 'class',
        begin: '\\b(class|module)\\b', end: '$|;',
        lexems: [hljs.UNDERSCORE_IDENT_RE],
        keywords: RUBY_KEYWORDS,
        contains: ['title', 'inheritance', 'comment'],
        keywords: {'class': 1, 'module': 1}
      },
      {
        className: 'title',
        begin: '[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?', end: '^',
        relevance: 0
      },
      {
        className: 'inheritance',
        begin: '<\\s*', end: '^',
        contains: ['parent']
      },
      {
        className: 'parent',
        begin: '(' + hljs.IDENT_RE + '::)?' + hljs.IDENT_RE, end: '^'
      },
      {
        className: 'number',
        begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b', end: '^',
        relevance: 0
      },
      {
        className: 'number',
        begin: '\\?\\w', end: '^'
      },
      {
        className: 'string',
        begin: '\'', end: '\'',
        contains: ['escape', 'subst'],
        relevance: 0
      },
      {
        className: 'string',
        begin: '"', end: '"',
        contains: ['escape', 'subst'],
        relevance: 0
      },
      {
        className: 'string',
        begin: '%[qw]?\\(', end: '\\)',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?\\[', end: '\\]',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?{', end: '}',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?<', end: '>',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?/', end: '/',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?%', end: '%',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?-', end: '-',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'string',
        begin: '%[qw]?\\|', end: '\\|',
        contains: ['escape', 'subst'],
        relevance: 10
      },
      {
        className: 'constant',
        begin: '(::)?([A-Z]\\w*(::)?)+', end: '^',
      },
      {
        className: 'symbol',
        begin: ':' + RUBY_IDENT_RE, end: '^'
      },
      {
        className: 'symbol',
        begin: ':', end: '^',
        contains: ['string']
      },
      hljs.BACKSLASH_ESCAPE,
      {
        className: 'subst',
        begin: '#\\{', end: '}',
        lexems: [RUBY_IDENT_RE],
        keywords: RUBY_KEYWORDS,
        contains: RUBY_DEFAULT_CONTAINS
      },
      {
        className: 'regexp_container',
        begin: '(' + hljs.RE_STARTERS_RE + ')\\s*', end: '^', noMarkup: true,
        contains: ['comment', 'regexp'],
        relevance: 0
      },
      {
        className: 'regexp',
        begin: '/', end: '/[a-z]*',
        illegal: '\\n',
        contains: ['escape']
      },
      {
        className: 'variable',
        begin: '(\\$\\W)|((\\$|\\@\\@?)(\\w+))', end: '^'
      }
    ]
  };
}();
<|endoftext|>


<commit_before>function _dubug(msg){
    DEBUG && console.log(msg);
}

function callBotAPI(newmsg,callback) {
   //YQL for cross region json ajax
    var yql_url = 'https://query.yahooapis.com/v1/public/yql';
    var url = 'http://www.tuling123.com/openapi/api?key=abab9d3783d6e367e71e56c721e3165a&info='+encodeURIComponent(newmsg);
    $.ajax({
        'url': yql_url,
        'data': {
              'q': 'SELECT * FROM json WHERE url="'+url+'"',
                   'format': 'json',
                   'jsonCompat': 'new',
        },
        'dataType': 'jsonp',
        'success': function(response) {
            ans = response.query.results.json.text;
            callback(ans);
        },
        'error': function() {
            _dubug("ajax error occured");
        }
    });
}

function sendmsg(ans) {
    _dubug("bot resp with: " + ans);
    $('#textInput')[0].value=ans;
    $('.chatSend')[0].click();
    _dubug("msg sent to: " + name);
    $('#conv_filehelper').click();
}

function installbot(chats){
    //add bot notes
    for (i=0;i<chats.length;i++) {
        var bot = document.createElement('div');
        bot.className='bot';
        chats[i].appendChild(bot);
    }

    //listen on bot click event
    $(chats).children('.bot').click(function(e){
        e.stopPropagation();
        $(this).toggleClass('active');
    });

    //add drag drop event to bot div
    jQuery.event.props.push('dataTransfer');
    $(chats).on({
        dragenter: function(e) {
            $(this).addClass('over');
        },
        dragover: function(e) {
            e.preventDefault();
        },
        dragleave: function(e) {
            $(this).removeClass('over');
        },
        drop: function() {
            $(this).find('.bot').toggleClass('active');
        },
    });

    _dubug("installed "+chats.length.toString()+" bots");
}

function buildbothome() {
    //add bot home
    $('#profile').append([
    '
',
        '',
        '',
            '
快把我拖到聊天列表上
',
            '
点击我可以 暂停/恢复
',
        '',
        '',
    '
'].join(''));

    //show tooltip for 10s
    setTimeout(function{
        $('img.botico').on('load',function(){
            $('#bot-wrapper span').show();
            setTimeout(function(){
                $('#bot-wrapper span').hide();
            },10*1000);
        });
    },500);

    //clear tooltip on mousedown
    $('.bot-home').mousedown(function(){
        $('#bot-wrapper span').hide();
    });

    //listen on bot-home click event
    $('.bot-home').click(function(){
        $('.bot-home').toggleClass('paused');
    });

    //listen drag event
    jQuery.event.props.push('dataTransfer');
    $('.bot-home').on({
        dragstart: function() {
            $(this).css('opacity', '0.5');
            $('.chatListColumn *').css('pointer-events','none');
        },
        dragend: function() {
            $(this).css('opacity', '1');
            $('.chatListColumn *').css('pointer-events','');
            $('.chatListColumn').removeClass('over');
        },
    });
    _dubug("bot home constructed");
}

function botinit(){
    $(document).ready(function(){
        //init bot-home
        buildbothome();
        //init bot divs
        var bots = $(['.chatListColumn',
            ':not([un="newsapp"])',
            ':not([un="filehelper"])',
            ':not([un="fmessage"])',
            ':not(".loadMoreConv")'].join(''))
        installbot(bots);
        _dubug(bots.length.toString()+" bots initiated");
    });
}

function botstart(interval){
    setInterval(chatbot,interval*1000);
    _dubug("started with interval: "+interval.toString()+"s");
}

function botupdate(){
    uninstalled = $(['.chatListColumn',
            ':not([un="newsapp"])',
            ':not([un="filehelper"])',
            ':not([un="fmessage"])',
            ':not(".loadMoreConv")',
            ':not(:has(".bot"))'].join(''));
    uninstalled.length && installbot(uninstalled);
    _dubug(uninstalled.length.toString()+" nodes to update");
}

function chatbot() {
    botupdate();
    //if paused
    if ( $('.bot-home').hasClass('paused') ) return;
    //if no bot-took-overed
    if ( $('.bot.active').length == 0 )  return;

    $('#conv_filehelper').click();
    $('.unreadDot:visible,.unreadDotS:visible').each(function()
    {
        is_active = $(this).parent().find(".bot").hasClass("active");
        if (!is_active) return;
        name = $(this).parent().find(".left.name").text();
        _dubug("msg from: " + name);
        $(this).click();
        //Wait till chat box loaded
        setTimeout(function(){
            newmsg = $("#chat_chatmsglist").children(".chatItem.you").last().find("pre").text();
            if (newmsg) {
                _dubug("msg content: " + newmsg);
                callBotAPI(newmsg,sendmsg);
            } else {
                _dubug("no msg found")
            }
        },500);
    });
}

DEBUG = true;
botinit();
botstart(30);
botupdate();
<commit_msg>syntax error<commit_after>function _dubug(msg){
    DEBUG && console.log(msg);
}

function callBotAPI(newmsg,callback) {
   //YQL for cross region json ajax
    var yql_url = 'https://query.yahooapis.com/v1/public/yql';
    var url = 'http://www.tuling123.com/openapi/api?key=abab9d3783d6e367e71e56c721e3165a&info='+encodeURIComponent(newmsg);
    $.ajax({
        'url': yql_url,
        'data': {
              'q': 'SELECT * FROM json WHERE url="'+url+'"',
                   'format': 'json',
                   'jsonCompat': 'new',
        },
        'dataType': 'jsonp',
        'success': function(response) {
            ans = response.query.results.json.text;
            callback(ans);
        },
        'error': function() {
            _dubug("ajax error occured");
        }
    });
}

function sendmsg(ans) {
    _dubug("bot resp with: " + ans);
    $('#textInput')[0].value=ans;
    $('.chatSend')[0].click();
    _dubug("msg sent to: " + name);
    $('#conv_filehelper').click();
}

function installbot(chats){
    //add bot notes
    for (i=0;i<chats.length;i++) {
        var bot = document.createElement('div');
        bot.className='bot';
        chats[i].appendChild(bot);
    }

    //listen on bot click event
    $(chats).children('.bot').click(function(e){
        e.stopPropagation();
        $(this).toggleClass('active');
    });

    //add drag drop event to bot div
    jQuery.event.props.push('dataTransfer');
    $(chats).on({
        dragenter: function(e) {
            $(this).addClass('over');
        },
        dragover: function(e) {
            e.preventDefault();
        },
        dragleave: function(e) {
            $(this).removeClass('over');
        },
        drop: function() {
            $(this).find('.bot').toggleClass('active');
        },
    });

    _dubug("installed "+chats.length.toString()+" bots");
}

function buildbothome() {
    //add bot home
    $('#profile').append([
    '
',
        '',
        '',
            '
快把我拖到聊天列表上
',
            '
点击我可以 暂停/恢复
',
        '',
        '',
    '
'].join(''));

    //show tooltip for 10s
    setTimeout(function(){
        $('img.botico').on('load',function(){
            $('#bot-wrapper span').show();
            setTimeout(function(){
                $('#bot-wrapper span').hide();
            },10*1000);
        });
    },500);

    //clear tooltip on mousedown
    $('.bot-home').mousedown(function(){
        $('#bot-wrapper span').hide();
    });

    //listen on bot-home click event
    $('.bot-home').click(function(){
        $('.bot-home').toggleClass('paused');
    });

    //listen drag event
    jQuery.event.props.push('dataTransfer');
    $('.bot-home').on({
        dragstart: function() {
            $(this).css('opacity', '0.5');
            $('.chatListColumn *').css('pointer-events','none');
        },
        dragend: function() {
            $(this).css('opacity', '1');
            $('.chatListColumn *').css('pointer-events','');
            $('.chatListColumn').removeClass('over');
        },
    });
    _dubug("bot home constructed");
}

function botinit(){
    $(document).ready(function(){
        //init bot-home
        buildbothome();
        //init bot divs
        var bots = $(['.chatListColumn',
            ':not([un="newsapp"])',
            ':not([un="filehelper"])',
            ':not([un="fmessage"])',
            ':not(".loadMoreConv")'].join(''))
        installbot(bots);
        _dubug(bots.length.toString()+" bots initiated");
    });
}

function botstart(interval){
    setInterval(chatbot,interval*1000);
    _dubug("started with interval: "+interval.toString()+"s");
}

function botupdate(){
    uninstalled = $(['.chatListColumn',
            ':not([un="newsapp"])',
            ':not([un="filehelper"])',
            ':not([un="fmessage"])',
            ':not(".loadMoreConv")',
            ':not(:has(".bot"))'].join(''));
    uninstalled.length && installbot(uninstalled);
    _dubug(uninstalled.length.toString()+" nodes to update");
}

function chatbot() {
    botupdate();
    //if paused
    if ( $('.bot-home').hasClass('paused') ) return;
    //if no bot-took-overed
    if ( $('.bot.active').length == 0 )  return;

    $('#conv_filehelper').click();
    $('.unreadDot:visible,.unreadDotS:visible').each(function()
    {
        is_active = $(this).parent().find(".bot").hasClass("active");
        if (!is_active) return;
        name = $(this).parent().find(".left.name").text();
        _dubug("msg from: " + name);
        $(this).click();
        //Wait till chat box loaded
        setTimeout(function(){
            newmsg = $("#chat_chatmsglist").children(".chatItem.you").last().find("pre").text();
            if (newmsg) {
                _dubug("msg content: " + newmsg);
                callBotAPI(newmsg,sendmsg);
            } else {
                _dubug("no msg found")
            }
        },500);
    });
}

DEBUG = true;
botinit();
botstart(30);
botupdate();
<|endoftext|>


<commit_before>'use strict';

var logger = require('log4js').getLogger('cloudify.blueprints');
/**
 * @typedef {object} Blueprint
 *
 * @property {string} id The identifier of the blueprint
 * @property {number} created_at timestamp of blueprint creation
 * @property {object} the contents of the blueprint. plan Gets the plan the blueprints represents: nodes, relationships etc..
 */

/**
 * @description
 * collection of API calls for blueprints
 * @class BlueprintsClient
 * @param {ClientConfig} config
 * @constructor
 */
function BlueprintsClient( config ){
    this.config = config;
}

/**
 * @param {IncludeParam} [_include] list of fields to include in response
 * @param {ApiCallback} callback body gets a list of blueprints
 */
BlueprintsClient.prototype.list = function( _include, callback ){
    logger.trace('listing blueprints');
    var qs = {};
    if ( !!_include ){
        qs._include = _include;
    }
    return this.config.request( {
        'method' : 'GET',
        'url' : this.config.endpoint + '/blueprints',
        'qs' : qs
    }, callback );
};

/**
 * @description
 * Gets  a bluprint by its id.
 * @param {string} blueprint_id Blueprint's id to get
 * @param {IncludeParam} [_include] List of fields to include in response
 * @param {ApiCallback} callback body gets the blueprint
 */
BlueprintsClient.prototype.get = function (blueprint_id, _include, callback) {
    logger.trace('getting blueprint by id');
    var qs = {};
    if (!!_include) {
        qs._include = _include;
    }

    return this.config.request({
            'method': 'GET',
            'url': String.format(this.config.endpoint + '/blueprints/{0}', blueprint_id ),
            'qs': qs
        }, callback );
};

/**
 * @description
 * Gets  a bluprint by its id.
 * @param {string} blueprint_id Blueprint's id to validate
 * @param {IncludeParam} [_include] List of fields to include in response
 * @param {ApiCallback} callback body gets the blueprint validation result
 */
BlueprintsClient.prototype.validate = function (blueprint_id, _include, callback) {
    logger.trace('validating blueprint by id');
    var qs = {};
    if (!!_include) {
        qs._include = _include;
    }

    return this.config.request({
        'method': 'GET',
        'url': String.format(this.config.endpoint + '/blueprints/{0}/validate', blueprint_id ),
        'qs': qs
    }, callback );
};

/**
 * @description Deltes the blueprint whose id matches the provided blueprint id.
 * @param {string} blueprint_id the id of the blueprint to be deleted
 * @param {ApiCallback} callback body gets the deleted blueprint
 */
BlueprintsClient.prototype.delete = function(blueprint_id, callback ){
    logger.trace('deleting blueprint');
    return this.config.request({
        'method' : 'DELETE',
        'url' : String.format(this.config.endpoint + '/blueprints/{0}', blueprint_id )
    }, callback );
};

///// ONLY ADD FUNCTION THAT MIGHT NOT BE IMPLEMENTED FROM THIS POINT ON..

// ignore undefined variables.
/* jshint unused: false */
/**
 *
 * @description
 * uploads a blueprint to cloudify's manager.
 *
 * @exception error if function is not implemented. not all clients implement this function.
 *
 * @param {string} [blueprint_path] main blueprint yaml file path.
 * @param {string} blueprint_id id of the uploaded blueprint
 * @param {ApiCallback} callback body gets the uploaded blueprint
 */
BlueprintsClient.prototype.upload = function( blueprint_path , blueprint_id, callback ){
    logger.trace('uploading blueprint');
    throw new Error('this function is not implemented');
};

/**
 *
 * @description
 * downloads aa previously uploaded blueprint from cloudify's manager.
 *
 * @param {string} blueprint_id
 * @param {string} output_file
 * @param {ApiCallback} callback body gets the path of downloaded  blueprint
 */
BlueprintsClient.prototype.download = function( blueprint_id, output_file, callback  ){
    logger.trace('downloading blueprint');
    throw new Error('this function is not implemented');
};

module.exports = BlueprintsClient;<commit_msg>Added blueprint browse call (not implemented)<commit_after>'use strict';

var logger = require('log4js').getLogger('cloudify.blueprints');
/**
 * @typedef {object} Blueprint
 *
 * @property {string} id The identifier of the blueprint
 * @property {number} created_at timestamp of blueprint creation
 * @property {object} the contents of the blueprint. plan Gets the plan the blueprints represents: nodes, relationships etc..
 */

/**
 * @description
 * collection of API calls for blueprints
 * @class BlueprintsClient
 * @param {ClientConfig} config
 * @constructor
 */
function BlueprintsClient( config ){
    this.config = config;
}

/**
 * @param {IncludeParam} [_include] list of fields to include in response
 * @param {ApiCallback} callback body gets a list of blueprints
 */
BlueprintsClient.prototype.list = function( _include, callback ){
    logger.trace('listing blueprints');
    var qs = {};
    if ( !!_include ){
        qs._include = _include;
    }
    return this.config.request( {
        'method' : 'GET',
        'url' : this.config.endpoint + '/blueprints',
        'qs' : qs
    }, callback );
};

/**
 * @description
 * Gets  a bluprint by its id.
 * @param {string} blueprint_id Blueprint's id to get
 * @param {IncludeParam} [_include] List of fields to include in response
 * @param {ApiCallback} callback body gets the blueprint
 */
BlueprintsClient.prototype.get = function (blueprint_id, _include, callback) {
    logger.trace('getting blueprint by id');
    var qs = {};
    if (!!_include) {
        qs._include = _include;
    }

    return this.config.request({
            'method': 'GET',
            'url': String.format(this.config.endpoint + '/blueprints/{0}', blueprint_id ),
            'qs': qs
        }, callback );
};

/**
 * @description
 * Gets  a bluprint by its id.
 * @param {string} blueprint_id Blueprint's id to validate
 * @param {IncludeParam} [_include] List of fields to include in response
 * @param {ApiCallback} callback body gets the blueprint validation result
 */
BlueprintsClient.prototype.validate = function (blueprint_id, _include, callback) {
    logger.trace('validating blueprint by id');
    var qs = {};
    if (!!_include) {
        qs._include = _include;
    }

    return this.config.request({
        'method': 'GET',
        'url': String.format(this.config.endpoint + '/blueprints/{0}/validate', blueprint_id ),
        'qs': qs
    }, callback );
};

/**
 * @description Deltes the blueprint whose id matches the provided blueprint id.
 * @param {string} blueprint_id the id of the blueprint to be deleted
 * @param {ApiCallback} callback body gets the deleted blueprint
 */
BlueprintsClient.prototype.delete = function(blueprint_id, callback ){
    logger.trace('deleting blueprint');
    return this.config.request({
        'method' : 'DELETE',
        'url' : String.format(this.config.endpoint + '/blueprints/{0}', blueprint_id )
    }, callback );
};

///// ONLY ADD FUNCTION THAT MIGHT NOT BE IMPLEMENTED FROM THIS POINT ON..

// ignore undefined variables.
/* jshint unused: false */
/**
 *
 * @description
 * uploads a blueprint to cloudify's manager.
 *
 * @exception error if function is not implemented. not all clients implement this function.
 *
 * @param {string} [blueprint_path] main blueprint yaml file path.
 * @param {string} blueprint_id id of the uploaded blueprint
 * @param {ApiCallback} callback body gets the uploaded blueprint
 */
BlueprintsClient.prototype.upload = function( blueprint_path , blueprint_id, callback ){
    logger.trace('uploading blueprint');
    throw new Error('this function is not implemented');
};

/**
 *
 * @description
 * downloads aa previously uploaded blueprint from cloudify's manager.
 *
 * @param {string} blueprint_id
 * @param {string} output_file
 * @param {ApiCallback} callback body gets the path of downloaded  blueprint
 */
BlueprintsClient.prototype.download = function( blueprint_id, output_file, callback  ){
    logger.trace('downloading blueprint');
    throw new Error('this function is not implemented');
};

/**
 *
 * @description
 * browse a previously downloaded blueprint.
 *
 * @param {string} blueprint_id
 * @param {number} last_update
 * @param {ApiCallback} callback body gets the content of blueprint files tree
 */
BlueprintsClient.prototype.browse = function (blueprint_id, last_update, _include, callback) {
    logger.trace('browse blueprint');
    throw new Error('this function is not implemented');
};

module.exports = BlueprintsClient;<|endoftext|>


<commit_before>import _ from 'lodash';

// Declare the private dataset.
const privData = new WeakMap();
function priv(ctx) { return privData.get(ctx); }

export default class Manifest {
    constructor(name, props, options) {
        privData.set(this, {});

        for (var propKey in props) {
            this[propKey] = props[propKey];
        }

        if (!this.options) { this.options = {}; }
        _.assign(this.options, options);

        priv(this).name = name;
    }

    get name() { return priv(this).name; }

    resolveContext(context) {
        return _.defaults({ name: this.name, context: context }, this);
    }
}<commit_msg>Added support for contracts.  Refactored definition structure.<commit_after>import _ from 'lodash';

// Declare the private dataset.
const privData = new WeakMap();
function priv(ctx) { return privData.get(ctx); }

export default class Definition {
    constructor(name, props, options = {}) {
        privData.set(this, {
            name: name
        });

        this.namespace = props.namespace;
        this.options = props.options ? _.cloneDeep(props.options) : {};
        this.enums = _.map(props.enums || [], props => new Enum(this, props));
        this.contracts = _.map(props.contracts || [], props => new Contract(this, props));
        this.models = _.map(props.models || [], props => new Model(this, props));
        this.services = _.map(props.services || [], props => new Service(this, props));
        this.extensions = props.extensions ? _.cloneDeep(props.extensions) : {};

        _.assign(this.options, options);
    }

    get name() { return priv(this).name; }

    resolveContext(context) {
        return _.defaults({ name: this.name, context: context }, this);
    }
}

class Enum {
    constructor(manifest, props) {
        this.manifest = manifest;

        this.name = props.name;
        this.values = props.values ? _.clone(props.values) : {};
        this.extensions = props.extensions ? _.cloneDeep(props.extensions) : {};
    }
}
class Contract {
    constructor(manifest, props) {
        this.manifest = manifest;

        this.name = props.name;
        this.properties = _.map(props.properties || [], props => new Property(this, props));
        this.extensions = props.extensions ? _.cloneDeep(props.extensions) : {};
    }
}
class Model {
    constructor(manifest, props) {
        this.manifest = manifest;

        this.name = props.name;
        this.properties = _.map(props.properties || [], props => new Property(this, props));
        this.extensions = props.extensions ? _.cloneDeep(props.extensions) : {};
        this.contracts = props.contracts ? _.clone(props.contracts) : {};

        let manifestContracts = this.getContracts();
        for (let contract of manifestContracts) {
            for (let prop of contract.properties) {
                let existingProp = _.find(this.properties, existingProp => existingProp.name === prop.name);
                if (!existingProp) {
                    this.properties.push(new Property(manifest, prop));
                }
                else {
                    if (existingProp.type !== prop.type) {
                        throw new Error(`Conflicting data types for contract property "${prop.name}"`);
                    }
                }
            }
        }
    }

    getContracts() {
        return _.map(this.contracts || [], (contractName) => {
            let contract = _.find(this.manifest.contracts, contract => contract.name === contractName);
            if (!contract) { throw new Error(`Contract "${contractName}" not defined`); }

            return contract;
        });
    }
}
class Service {
    constructor(manifest, props) {
        this.manifest = manifest;

        this.name = props.name;
        this.methods = _.map(props.methods || [], props => new Method(this, props));
        this.extensions = props.extensions ? _.cloneDeep(props.extensions) : {};
    }
}

class Property {
    constructor(manifest, props) {
        this.manifest = manifest;

        this.name = props.name;
        this.type = props.type;
        this.extensions = props.extensions ? _.cloneDeep(props.extensions) : {};
    }
}
class Method {
    constructor(manifest, props) {
        this.manifest = manifest;

        this.name = props.name;
        this.returnType = props.returnType;
        this.params = _.map(props.params || [], props => new MethodParam(this, props));
        this.extensions = props.extensions ? _.cloneDeep(props.extensions) : {};
    }
}
class MethodParam {
    constructor(manifest, props) {
        this.manifest = manifest;

        this.name = props.name;
        this.type = props.type;
    }
}<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Panel, Col, Row, Button, FormGroup, ControlLabel, FormControl, FormControlsSelect, FieldGroup, InputGroup } from 'react-bootstrap';
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom';

export default class ReportMatchPage extends Component {
	constructor(props) {
		super(props)
		this.state = {
			p1Name: null,
			p1Email: null,
			p1Score: null,
			p2Name: null,
			p2Email: null,
			p2Score: null,
			roomName: props.match.params.roomName
		}
	}

	handleSubmit = (event) => {
		event.preventDefault();
		console.log("asdf");

		const match = {
			p1_name: this.state.p1Name,
			p1_email: this.state.p1Email,
			p1_score: this.state.p1Score,
			p2_name: this.state.p2Name,
			p2_email: this.state.p2Email,
			p2_score: this.state.p2Score,
			room_name: this.state.roomName
		}

		fetch('/api/matches', {
	      method: 'post',
	      body: JSON.stringify(match),
	      headers: {
	                "Content-Type": "application/json"
	            }
	    }).then(res => {
	      return res.json();
	      this.setState({
	      	p1Name: null,
			p1Email: null,
			p1Score: null,
			p2Name: null,
			p2Email: null,
			p2Score: null,
	      })
	    }).then(json => {
	      console.log(json);
	    })
		}

	onValueChanged = (event) => {
		console.log(event.target.name)
		this.setState({
			[event.target.name]: event.target.value
		})
	}

	onRoomChanged = (event) => {
		console.log(event.target.value);
		this.setState({
			roomName: event.target.value
		});
	}

	render() {
		return (

Report Match in room <Link to={`/rooms/${this.props.match.params.roomName}`}>{this.props.match.params.roomName}</Link>

				<Row>
					<Col md={4}>

Player 1

					</Col>
					<Col md={4}>
					</Col>
					<Col md={4}>

Player 2

					</Col>
				</Row>
				<Row>
					<Col md={4}>
						<FormGroup>
							<FormControl type="text" placeholder="Name" name="p1Name" value={this.state.p1Name} onChange={this.onValueChanged} />
						</FormGroup>
					</Col>
					<Col md={4}>
					</Col>
					<Col md={4}>
						<FormGroup>
							<FormControl type="text" placeholder="Name" name="p2Name" value={this.state.p2Name} onChange={this.onValueChanged} />
						</FormGroup>
					</Col>
				</Row>

				<Row>
				<Col md={4}>
					</Col>
					<Col md={2}>
						<FormGroup>
							<FormControl type="text" placeholder="Score" name="p1Score" value={this.state.p1Score} onChange={this.onValueChanged} />
						</FormGroup>
					</Col>
					<Col md={2}>
						<FormGroup>
							<FormControl type="text" placeholder="Score" name="p2Score" value={this.state.p2Score} onChange={this.onValueChanged} />
						</FormGroup>
					</Col>
					<Col md={4}>
					</Col>
				</Row>

				<Row>
					<Col md={4}>
						<FormGroup>
							<FormControl type="text" placeholder="Email" name="p1Email" value={this.state.p1Email} onChange={this.onValueChanged} />
						</FormGroup>
					</Col>
					<Col md={4}>
					</Col>
					<Col md={4}>
						<FormGroup>
							<FormControl type="text" placeholder="Email" name="p2Email" value={this.state.p2Email} onChange={this.onValueChanged} />
						</FormGroup>
					</Col>
				</Row>
				<Button onClick={this.handleSubmit}>Submit</Button>

		)
	}
}<commit_msg>Bug fixes<commit_after>import React, { Component } from 'react';
import { Panel, Col, Row, Button, FormGroup, ControlLabel, FormControl, FormControlsSelect, FieldGroup, InputGroup } from 'react-bootstrap';
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom';

export default class ReportMatchPage extends Component {
	constructor(props) {
		super(props)
		this.state = {
			p1Name: null,
			p1Email: null,
			p1Score: null,
			p2Name: null,
			p2Email: null,
			p2Score: null,
			roomName: props.match.params.roomName
		}
	}

	handleSubmit = (event) => {
		event.preventDefault();
		console.log("asdf");

		const match = {
			p1_name: this.state.p1Name,
			p1_email: this.state.p1Email,
			p1_score: this.state.p1Score,
			p2_name: this.state.p2Name,
			p2_email: this.state.p2Email,
			p2_score: this.state.p2Score,
			room_name: this.state.roomName
		}

		fetch('/api/matches', {
	      method: 'post',
	      body: JSON.stringify(match),
	      headers: {
	                "Content-Type": "application/json"
	            }
	    }).then(res => {
	      return res.json();
	    }).then(json => {
		    this.setState({
		      	p1Name: null,
				p1Email: null,
				p1Score: null,
				p2Name: null,
				p2Email: null,
				p2Score: null,
		      })
	      console.log(json);
	    })
		}

	onValueChanged = (event) => {
		console.log(event.target.name)
		this.setState({
			[event.target.name]: event.target.value
		})
	}

	onRoomChanged = (event) => {
		console.log(event.target.value);
		this.setState({
			roomName: event.target.value
		});
	}

	render() {
		return (

Report Match in room <Link to={`/rooms/${this.props.match.params.roomName}`}>{this.props.match.params.roomName}</Link>

				<Row>
					<Col md={4}>

Player 1

					</Col>
					<Col md={4}>
					</Col>
					<Col md={4}>

Player 2

					</Col>
				</Row>
				<Row>
					<Col md={4}>
						<FormGroup>
							<FormControl type="text" placeholder="Name" name="p1Name" value={this.state.p1Name} onChange={this.onValueChanged} />
						</FormGroup>
					</Col>
					<Col md={4}>
					</Col>
					<Col md={4}>
						<FormGroup>
							<FormControl type="text" placeholder="Name" name="p2Name" value={this.state.p2Name} onChange={this.onValueChanged} />
						</FormGroup>
					</Col>
				</Row>

				<Row>
				<Col md={4}>
					</Col>
					<Col md={2}>
						<FormGroup>
							<FormControl type="text" placeholder="Score" name="p1Score" value={this.state.p1Score} onChange={this.onValueChanged} />
						</FormGroup>
					</Col>
					<Col md={2}>
						<FormGroup>
							<FormControl type="text" placeholder="Score" name="p2Score" value={this.state.p2Score} onChange={this.onValueChanged} />
						</FormGroup>
					</Col>
					<Col md={4}>
					</Col>
				</Row>

				<Row>
					<Col md={4}>
						<FormGroup>
							<FormControl type="text" placeholder="Email" name="p1Email" value={this.state.p1Email} onChange={this.onValueChanged} />
						</FormGroup>
					</Col>
					<Col md={4}>
					</Col>
					<Col md={4}>
						<FormGroup>
							<FormControl type="text" placeholder="Email" name="p2Email" value={this.state.p2Email} onChange={this.onValueChanged} />
						</FormGroup>
					</Col>
				</Row>
				<Button onClick={this.handleSubmit}>Submit</Button>

		)
	}
}<|endoftext|>


<commit_before>import React from "react";
import ReactDOM from "react-dom";

//
// Messy smorgasbord of React components
//

// Stateful class component
export class App extends React.Component {

  constructor() {
    super();

    // State belongs to the component
    // This parent contains the root state. It passes
    //  it down to children as props
    this.state = {
      subtitle: "Subtitle",
      messages: ["First!", "Second!"],
      color: {
        r: 0,
        g: 0,
        b: 0
      },
      counterIds: []
    };
  }

  //
  // Child event handlers
  //

  // called when any widget changes its text value
  updateWidget(e, childId) {
    const newState = Object.assign({}, this.state, {
      subtitle: `${e.target.value} (edited by widget ${childId})`
    });

    this.setState(newState);
  }

  // Called when any slider updates its value
  updateSlider(e) {
    const color = {
      r: +this.refs.redSlider.refs.input.value,
      g: +this.refs.greenSlider.refs.input.value,
      b: +this.refs.blueSlider.refs.input.value,
    }

    const newState = Object.assign({}, this.state, { color });
    this.setState(newState);
  }

  addCounter() {
    const nextId = this.state.counterIds.length + 1;
    const counterIds = [...this.state.counterIds, nextId];
    const newState = Object.assign({}, this.state, { counterIds });
    this.setState(newState);
  }

  popCounter() {
    const counterIds = this.state.counterIds.slice(0, -1);
    const newState = Object.assign({}, this.state, { counterIds });
    this.setState(newState);
  }

  //
  // rendering methods
  //

  render() {
    // Without JSX:
    // return React.createElement("h1", { className: "title" }, "Hi no JSX!")

    // Props are passed by the parent component
    const { message } = this.props;
    const { r, g, b } = this.state.color;
    const rgba = [r, g, b, 1].join(", ");

    return (

        <h1 style={{ color: `rgba(${rgba})` }} >
          {this.props.title}

{this.state.subtitle}

        {/* mapping array state to child components */}
        {this.state.messages.map((message, i) =>
          <Widget
            key={i}
            message={message}
            title={`Widget ${i}`}
            update={(e) => this.updateWidget(e, i)}
          />
        )}

        {/* refs */}

Change the title colour:

        R
        <Slider ref="redSlider" value={r} update={this.updateSlider.bind(this)} />
        <span style={{ color: `rgba(${r}, 0, 0, 1)` }}>({r})

        G
        <Slider ref="greenSlider" value={g} update={this.updateSlider.bind(this)} />
        <span style={{ color: `rgba(0, ${g}, 0, 1)` }}>({g})

        B
        <Slider ref="blueSlider" value={b} update={this.updateSlider.bind(this)} />
        <span style={{ color: `rgba(0, 0, ${b}, 1)` }}>({b})

        {/* components and other elements can be nested with child properties  */}

Child properties

        <Button>child properties!</Button>
        <Button>
          Grr!
          <TableFlip />
        </Button>

        {/* lifecycle example */}

Lifecyle

        <Button onclick={this.addCounter.bind(this)}>Add counter</Button>
        <Button onclick={this.popCounter.bind(this)}>Pop counter</Button>

        {this.state.counterIds.map((id) =>
          <Counter key={id} id={id}/>
        )}

    );
  }
}

// Prop type hints
App.propTypes = {
  title: React.PropTypes.string.isRequired
};

App.defaultProps = {
  title: "Default title!"
};

const Widget = ({ title, message, update }) =>

{title}

{message}

    Change the subtitle:
    <input id="title-input" type="text" onChange={update} />

// A component that will be assigned to a ref.
// Although it's stateless, functional components cannot be refs
//  so we need to use a class.
class Slider extends React.Component {
  render() {
    const { value, update } = this.props;
    return (
      <input ref="input" type="range"
        value={value} min="0" max="255"
        onChange={this.props.update}
      />
    );
  }
}

// A component with child properties (transcluded content)
const Button = ({ children, onclick }) =>
  <button onClick={onclick}>{children}</button>;

const TableFlip = () => "(╯°□°）╯︵ ┻━┻";

// Lifecycle methods kitchen sink
class Counter extends React.Component {
  constructor() {
    super();
    this.state = {
      value: 0
    };
  }

  // Mounting
  componentWillMount() {
    console.log(`Counter ${this.props.id} will mount`);
  }

  componentDidMount() {
    console.log(`Counter ${this.props.id} mounted`);
  }

  componentWillUnmount() {
    console.log(`Counter ${this.props.id} will unmount`);
  }

  // Updating

  // The component's updates have been flushed to the DOM
  componentDidUpdate(oldProps, oldState) {
    console.log(`Counter ${this.props.id} flushed to the DOM`, oldProps, oldState);
  }

  // New props!
  componentWillReceiveProps(nextProps) {
    console.log(`Counter ${this.props.id} will receive props`, nextProps);
  }

  // Return true if the component should have updates flushed to the DOM.
  // For avoiding redundant re-renders.
  shouldComponentUpdate(nextProps, nextState) {
    // Only render every third increment
    return nextState.value % 3 == 0;
  }

  // Event handlers
  increment() {
    this.setState({ value: this.state.value + 1 });
  }

  render() {
    return (
      <Button onclick={this.increment.bind(this)}>
        { this.state.value }
      </Button>
    );
  }

}
<commit_msg>React: Higher-order components<commit_after>import React from "react";
import ReactDOM from "react-dom";

//
// Messy smorgasbord of React components
//

// Stateful class component
export class App extends React.Component {

  constructor() {
    super();

    // State belongs to the component
    // This parent contains the root state. It passes
    //  it down to children as props
    this.state = {
      subtitle: "Subtitle",
      messages: ["First!", "Second!"],
      color: {
        r: 0,
        g: 0,
        b: 0
      },
      counterIds: []
    };
  }

  //
  // Child event handlers
  //

  // called when any widget changes its text value
  updateWidget(e, childId) {
    const newState = Object.assign({}, this.state, {
      subtitle: `${e.target.value} (edited by widget ${childId})`
    });

    this.setState(newState);
  }

  // Called when any slider updates its value
  updateSlider(e) {
    const color = {
      r: +this.refs.redSlider.refs.input.value,
      g: +this.refs.greenSlider.refs.input.value,
      b: +this.refs.blueSlider.refs.input.value,
    }

    const newState = Object.assign({}, this.state, { color });
    this.setState(newState);
  }

  addCounter() {
    const nextId = this.state.counterIds.length + 1;
    const counterIds = [...this.state.counterIds, nextId];
    const newState = Object.assign({}, this.state, { counterIds });
    this.setState(newState);
  }

  popCounter() {
    const counterIds = this.state.counterIds.slice(0, -1);
    const newState = Object.assign({}, this.state, { counterIds });
    this.setState(newState);
  }

  //
  // rendering methods
  //

  render() {
    // Without JSX:
    // return React.createElement("h1", { className: "title" }, "Hi no JSX!")

    // Props are passed by the parent component
    const { message } = this.props;
    const { r, g, b } = this.state.color;
    const rgba = [r, g, b, 1].join(", ");

    return (

        <h1 style={{ color: `rgba(${rgba})` }} >
          {this.props.title}

{this.state.subtitle}

        {/* mapping array state to child components */}
        {this.state.messages.map((message, i) =>
          <Widget
            key={i}
            message={message}
            title={`Widget ${i}`}
            update={(e) => this.updateWidget(e, i)}
          />
        )}

        {/* refs */}

Change the title colour:

        R
        <Slider ref="redSlider" value={r} update={this.updateSlider.bind(this)} />
        <span style={{ color: `rgba(${r}, 0, 0, 1)` }}>({r})

        G
        <Slider ref="greenSlider" value={g} update={this.updateSlider.bind(this)} />
        <span style={{ color: `rgba(0, ${g}, 0, 1)` }}>({g})

        B
        <Slider ref="blueSlider" value={b} update={this.updateSlider.bind(this)} />
        <span style={{ color: `rgba(0, 0, ${b}, 1)` }}>({b})

        {/* components and other elements can be nested with child properties  */}

Child properties

        <Button>child properties!</Button>
        <Button>
          Grr!
          <TableFlip />
        </Button>

        {/* lifecycle example */}

Lifecyle

        <Button onclick={this.addCounter.bind(this)}>Add counter</Button>
        <Button onclick={this.popCounter.bind(this)}>Pop counter</Button>

        {this.state.counterIds.map((id) =>
          <Counter key={id} id={id}/>
        )}

Higher-order components

        <MixedButton text="Click me!" />
        <MixedLabel text="Mouse over me!" />

    );
  }
}

// Prop type hints
App.propTypes = {
  title: React.PropTypes.string.isRequired
};

App.defaultProps = {
  title: "Default title!"
};

const Widget = ({ title, message, update }) =>

{title}

{message}

    Change the subtitle:
    <input id="title-input" type="text" onChange={update} />

// A component that will be assigned to a ref.
// Although it's stateless, functional components cannot be refs
//  so we need to use a class.
class Slider extends React.Component {
  render() {
    const { value, update } = this.props;
    return (
      <input ref="input" type="range"
        value={value} min="0" max="255"
        onChange={this.props.update}
      />
    );
  }
}

// A component with child properties (transcluded content)
const Button = ({ children, onclick }) =>
  <button onClick={onclick}>{children}</button>;

const TableFlip = () => "(╯°□°）╯︵ ┻━┻";

// Lifecycle methods kitchen sink
class Counter extends React.Component {
  constructor() {
    super();
    this.state = {
      value: 0
    };
  }

  // Mounting
  componentWillMount() {
    console.log(`Counter ${this.props.id} will mount`);
  }

  componentDidMount() {
    console.log(`Counter ${this.props.id} mounted`);
  }

  componentWillUnmount() {
    console.log(`Counter ${this.props.id} will unmount`);
  }

  // Updating

  // The component's updates have been flushed to the DOM
  componentDidUpdate(oldProps, oldState) {
    console.log(`Counter ${this.props.id} flushed to the DOM`, oldProps, oldState);
  }

  // New props!
  componentWillReceiveProps(nextProps) {
    console.log(`Counter ${this.props.id} will receive props`, nextProps);
  }

  // Return true if the component should have updates flushed to the DOM.
  // For avoiding redundant re-renders.
  shouldComponentUpdate(nextProps, nextState) {
    // Only render every third increment
    return nextState.value % 3 == 0;
  }

  // Event handlers
  increment() {
    this.setState({ value: this.state.value + 1 });
  }

  render() {
    return (
      <Button onclick={this.increment.bind(this)}>
        { this.state.value }
      </Button>
    );
  }
}

// Higher-order component
// A function that takes an original component and returns a decorated form
// Higher-order components are like mixins, but using composition instead
//  of inheritance.
const CountMixin = (Component) => class extends React.Component {
  constructor() {
    super();
    this.update = this.update.bind(this);
    this.state = { value: 0 };
  }

  update() {
    this.setState({ value: this.state.value + 1 })
  }

  componentWillMount() {
    console.log("CountMixin-ed component will mount");
  }

  render() {
    //* pass through the rest of the properties - the higher-order component doesn't need to know what to expect.
    return (
      <Component
        update={this.update}
        { ...this.state }
        { ...this.props }
      />
    );
  }
}

// A couple of stateless components that use the update mixin
const MixedButton = CountMixin(({ update, text, value }) =>
  <button onClick={update}>{text}: {value}</button>
)

const MixedLabel = CountMixin(({ update, text, value }) =>
  {text}: {value}
)
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 TechnologyAdvice
 */
import output from './output';
import dgram from 'dgram';
import net from 'net';
import Promise from 'bluebird';

const forwarders = {
  /**
   * Enables TCP connection and UDP packet forwarding to a remote host.
   * @param {string} host The hostname or IP address of the remote server
   * @param {number} localPort The port on which to listen for local connections
   * @param {number} [remotePort=localPort] The port to which traffic should be forwarded on the host. If omitted,
   *    localPort is used.
   * @return {Promise} Resolves when the given localPort is successfully listening for both TCP and UDP.
   */
  startForwarder: (host, localPort, remotePort = localPort) => {
    return Promise.all([
      forwarders.startTcpForwarder(host, localPort, remotePort),
      forwarders.startUdpForwarder(host, localPort, remotePort)
    ]);
  },

  /**
   * Starts a forwarder for each given port on the local machine to the same ports on the remote machine.
   * @param {string} host The hostname of the machine to which the ports should be forwarded.
   * @param {Array<number>} ports An array of port numbers to forward
   * @return {Promise} Resolves when all given ports are listening locally.
   */
  startForwarders: (host, ports) => {
    const promises = ports.map((port) => forwarders.startForwarder(host, port));
    return Promise.all(promises);
  },

  /**
   * Opens a TCP server socket on the given port, proxying it to the specified port at the given host
   * when a connection is established.
   * @param {string} host The hostname or IP address of the remote server
   * @param {number} localPort The port on which to listen for local connections
   * @param {number} [remotePort=localPort] The port to which traffic should be forwarded on the host.
   *    If omitted, localPort is used.
   * @return {Promise} Resolves when the given localPort is successfully listening.
   */
  startTcpForwarder: (host, localPort, remotePort = localPort) => {
    const server = net.createServer((localConn) => {
      const remoteConn = net.connect(remotePort, host);
      remoteConn.on('connect', () => {
        localConn.pipe(remoteConn);
        remoteConn.pipe(localConn);
      });
      remoteConn.on('error', (err) => {
        output.error(err.message);
        localConn.end();
      });
    });
    output.success(`Forwarding {{localhost:${localPort}}} to {{${host}:${remotePort}}} over TCP`);
    forwarders._servers.push(server);
    return new Promise((resolve, reject) => {
      server.on('error', (err) => reject(err));
      server.listen(localPort, resolve);
    });
  },

  /**
   * Opens a UDP listening socket on the given port, proxying any messages it receives to the specified
   * port at the given host.
   * @param {string} host The hostname or IP address of the remote server
   * @param {number} localPort The port on which to listen for local connections
   * @param {number} [remotePort=localPort] The port to which traffic should be forwarded on the host.
   *    If omitted, localPort is used.
   * @param {string} [type='udp4'] The UDP message type to support
   * @return {Promise} Resolves when the given localPort is successfully listening.
   */
  startUdpForwarder: (host, localPort, remotePort = localPort, type = 'udp4') => {
    const socket = dgram.createSocket(type);
    socket.on('message', (msg) => {
      socket.send(msg, 0, msg.length, remotePort, host);
    });
    forwarders._servers.push(socket);
    output.success(`Forwarding {{localhost:${localPort}}} to {{${host}:${remotePort}}} over UDP`);
    return new Promise((resolve, reject) => {
      try {
        socket.bind(localPort);
      } catch (e) {
        reject(e);
      }
      resolve();
    });
  },

  /**
   * Stops any active forwarders. If no forwarders are active, this does nothing.
   */
  stopForwarders: () => {
    if (forwarders._servers.length) {
      output.success('Halting all port forwarding');
      forwarders._servers.forEach((server) => {
        server.unref();
        server.close();
      });
      forwarders._servers = [];
    }
  },

  /**
   * An array of server sockets
   */
  _servers: []
};

export default forwarders;
<commit_msg>Refactor: forwarders.js<commit_after>/*
 * Copyright (c) 2015 TechnologyAdvice
 */
import output from './output';
import dgram from 'dgram';
import net from 'net';
import Promise from 'bluebird';

/**
 * An array of server sockets
 */
let _servers = [];

const forwarders = {
  /**
   * Enables TCP connection and UDP packet forwarding to a remote host.
   * @param {string} host The hostname or IP address of the remote server
   * @param {number} localPort The port on which to listen for local connections
   * @param {number} [remotePort=localPort] The port to which traffic should be forwarded on the host. If omitted,
   *    localPort is used.
   * @return {Promise} Resolves when the given localPort is successfully listening for both TCP and UDP.
   */
  startForwarder: (host, localPort, remotePort = localPort) => {
    return Promise.all([
      forwarders.startTcpForwarder(host, localPort, remotePort),
      forwarders.startUdpForwarder(host, localPort, remotePort)
    ]);
  },

  /**
   * Starts a forwarder for each given port on the local machine to the same ports on the remote machine.
   * @param {string} host The hostname of the machine to which the ports should be forwarded.
   * @param {Array<number>} ports An array of port numbers to forward
   * @return {Promise} Resolves when all given ports are listening locally.
   */
  startForwarders: (host, ports) => {
    return Promise.all(
      ports.map(port => forwarders.startForwarder(host, port))
    );
  },

  /**
   * Opens a TCP server socket on the given port, proxying it to the specified port at the given host
   * when a connection is established.
   * @param {string} host The hostname or IP address of the remote server
   * @param {number} localPort The port on which to listen for local connections
   * @param {number} [remotePort=localPort] The port to which traffic should be forwarded on the host.
   *    If omitted, localPort is used.
   * @return {Promise} Resolves when the given localPort is successfully listening.
   */
  startTcpForwarder: (host, localPort, remotePort = localPort) => {
    const server = net.createServer(localConn => {
      const remoteConn = net.connect(remotePort, host);
      remoteConn.on('connect', () => {
        localConn.pipe(remoteConn);
        remoteConn.pipe(localConn);
      });
      remoteConn.on('error', err => {
        output.error(err.message);
        localConn.end();
      });
    });
    output.success(`Forwarding {{localhost:${localPort}}} to {{${host}:${remotePort}}} over TCP`);
    _servers.push(server);
    return new Promise((resolve, reject) => {
      server.on('error', err => reject(err));
      server.listen(localPort, resolve);
    });
  },

  /**
   * Opens a UDP listening socket on the given port, proxying any messages it receives to the specified
   * port at the given host.
   * @param {string} host The hostname or IP address of the remote server
   * @param {number} localPort The port on which to listen for local connections
   * @param {number} [remotePort=localPort] The port to which traffic should be forwarded on the host.
   *    If omitted, localPort is used.
   * @param {string} [type='udp4'] The UDP message type to support
   * @return {Promise} Resolves when the given localPort is successfully listening.
   */
  startUdpForwarder: (host, localPort, remotePort = localPort, type = 'udp4') => {
    const socket = dgram.createSocket(type);
    socket.on('message', msg => socket.send(msg, 0, msg.length, remotePort, host));
    _servers.push(socket);
    output.success(`Forwarding {{localhost:${localPort}}} to {{${host}:${remotePort}}} over UDP`);
    return new Promise((resolve, reject) => {
      try {
        socket.bind(localPort);
      } catch (e) {
        reject(e);
      }
      resolve();
    });
  },

  /**
   * Stops any active forwarders. If no forwarders are active, this does nothing.
   */
  stopForwarders: () => {
    if (!_servers.length) return Promise.resolve();
    output.success('Halting all port forwarding');
    return Promise.each(_servers, server => {
      return new Promise(resolve => {
        server.unref();
        try {
          server.close(resolve);
        } catch (e) {
          resolve();
        }
      });
    })
    .then(() => _servers = []);
  }

};

export default forwarders;
<|endoftext|>


<commit_before>/**
 * Takes an old map and a new map, and returns a map of changes needed to get
 * from the old to the new. This may include nulls for deletions.
 */

import {Immutable} from '@trip/util';

export default function getChanges(oldMap, newMap) {
  const changes = {};

  for (const file of new Set([...oldMap.keys(), ...newMap.keys()])) {
    const newContents = newMap.get(file);

    if (!newContents) changes[file] = null;
    else if (newContents !== oldMap.get(file)) changes[file] = newContents;
  }

  return Immutable.Map(changes);
}
<commit_msg>use immutable directly<commit_after>/**
 * Takes an old map and a new map, and returns a map of changes needed to get
 * from the old to the new. This may include nulls for deletions.
 */

import Immutable from 'immutable';

export default function getChanges(oldMap, newMap) {
  const changes = {};

  for (const file of new Set([...oldMap.keys(), ...newMap.keys()])) {
    const newContents = newMap.get(file);

    if (!newContents) changes[file] = null;
    else if (newContents !== oldMap.get(file)) changes[file] = newContents;
  }

  return Immutable.Map(changes);
}
<|endoftext|>


<commit_before>/*
Mag.JS AddOns v0.21.7
(c) Michael Glazer 2016
https://github.com/magnumjs/mag.js
Requires: MagJS (core) Addons: Ajax , Router
*/

;
(function(mag, window, document, undefined) {

  'use strict';

  // helper
  mag.noop = function() {}

  //UTILITY
  // mag.utils.copy - now in core
  // mag.utils.merge - now in core

  mag.copy = mag.utils.copy
  mag.merge = mag.utils.merge

  /*
  controller:function(props)
    // if props has a property 'isVisible' when true will display entire module on before updates
    mag.show(this,'isVisible')
  }
  http://jsbin.com/fegizubime/edit?html,js,output
  */

  // show hide

  mag.show = function(context, conditionName) {
    var ctype = typeof context;
    if (ctype !== 'object') {
      var obj = {
        _config: function(node) {
          node.style.display = context ? 'block' : 'none'
        }
      }
      if (typeof conditionName == 'object') {
        mag.merge(conditionName, obj)
      }
      return obj
    } else if (ctype == 'object') {
      context.willload = function(event, node, inprops) {
        node.style.display = 'block'
      }
    } else {
      context.willupdate = function(event, node, inprops) {
        node.style.display = inprops[conditionName] ? 'block' : 'none'
      }
    }
  }

  // promises

  /*
  var d = mag.deferred()

  d.promise.then(function() {
    console.log('success', arguments)
  }, function() {
    console.log('failure', arguments)
  })
  d.reject({
    things: false
  })
  d.resolve({
    things: []
  })
  */

mag.deferred = function() {
  var Deferred = {}
  Deferred.promise = new Promise(function(resolve, reject) {
    Deferred.resolve = resolve
    Deferred.reject = reject
  })
  return Deferred
}

mag.when = function(arrayOfPromises, callback) {
  return Promise.all(arrayOfPromises).then(callback)
}

//TODO: add jsonp support

mag.request = function(options) {
  var deferred = mag.deferred();
  if (options.initialValue) {
    deferred.promise.initialValue = options.initialValue
  }
  //Uid:
  var key = JSON.stringify(options)
    //Cache:
  if (options.cache) {
    var cache = mag.cache(key)
    if (cache) {
      deferred.resolve(cache)
      return deferred.promise
    }
  }

  //In queue:
  if (mag.request.queue[key]) {
    return mag.request.queue[key]
  }
  //Add to queue
  mag.request.queue[key] = deferred.promise;

  var client = new XMLHttpRequest();
  var method = (options.method || 'GET').toUpperCase();
  var data = method === "GET" || !options.data ? "" : options.data

  client.onload = function(e) {
    var ct = client.getResponseHeader("content-type") || "";
    var data = e.target.responseText;
    if (ct.indexOf('json') > -1) {
      data = JSON.parse(data)
    }
    if (options.cache) {
      mag.cache(key, data, options.cacheTime, options.cacheType)
    }
    delete mag.request.queue[key];
    var headers = client.getAllResponseHeaders();
    deferred.resolve(data, headers);
  }

  client.onerror = function(e) {
    deferred.reject(e)
  };

  client.open(method, options.url);
    //Headers:
  if(options.headers){
    for(var i=0;i<options.headers.length;i++){
    	var header = options.headers[i]
      for(var k in header){
    	  client.setRequestHeader(k, header[k]);
      }
    }
  }
  client.send(data);

  return deferred.promise
}
mag.request.queue = {}

mag.cache = function(key, data, cacheTime, storageType) {
   var stype = window[storageType || 'sessionStorage']

  if (arguments.length == 1) {

    if (mag.cache.data[key]) {
      return mag.cache.data[key].data;
    } else {
      // check storage
      var item = stype.getItem(key)
      if (item) {
        mag.cache.data[key] = JSON.parse(item)
        return mag.cache.data[key].data
      }
      else return 0;
    }
  }

  if (mag.cache.data[key] && mag.cache.data[key].id) clearTimeout(mag.cache.data[key].id)

  var intervalID = setTimeout(function(key) {
    stype.removeItem(key);
    delete mag.cache.data[key]
  }.bind({}, key), cacheTime || 1000 * 60 * 10); //10 minutes

  mag.cache.data[key] = {
    id: intervalID,
    data: data
  }

  stype.setItem(key, JSON.stringify(mag.cache.data[key]))
}
mag.cache.data = {}

  // goes with mag.request for json ajax requests
  /*
  will show and hide all ''.loader' elements in transition
  */
  mag.requestWithFeedback = function(args) {
    var key = JSON.stringify(args)
    if (!mag.requestWithFeedback.cache[key]) {

      var loaders = document.querySelectorAll(".loader")

      //show icons
      for (var i = 0, loader; loader = loaders[i]; i++) loader.style.display = "block"

      var expire = function(data) {
        delete mag.requestWithFeedback.cache[key]

        if (Object.keys(mag.requestWithFeedback.cache).length == 0) {
          //hide icons
          for (var i = 0, loader; loader = loaders[i]; i++) loader.style.display = "none"
        }
        return data
      }
      mag.requestWithFeedback.cache[key] = mag.request(args)
      mag.requestWithFeedback.cache[key].then(expire, function(error) {
        expire(error)
        throw error
      })
    }
    return mag.requestWithFeedback.cache[key]
  }
  mag.requestWithFeedback.cache = {}

  // disable add to config
  // http://jsbin.com/zepacabile/edit?js,output
  // define condition func
  // this.show = mag.prop(false);

  //define context
  //   this.input = mag.disable(this.show)
  // OR mag.disable(this.show, this.input={})
  //TODO: change to mag.ui.disable
 mag.disable = function(condition, obj) {

  // add or merge to config if not exists
  var orig = obj && obj._config ? obj._config : function() {};

  var tmp = {
    _config: function(n) {
      orig.apply(this, arguments);
      if (condition()) n.setAttribute('disabled', 'disabled');
      else n.removeAttribute('disabled');
    }
  }
  if (obj) {
    mag.merge(obj, tmp);
  }
  return tmp;

}

  // TODO: change to mag.find
  // find a MagJS element Matcher
  mag.find = function(parentRootId, selector) {
    var parent = document.getElementById(parentRootId);
    return mag.fill.find(parent, selector)
  }

  // mag.addons.toMenu(['one', 'two', 'three'], state.selected())
  // http://jsbin.com/mapuwojumu/3/edit?js,output
  //TODO change to mag.ui.menu
  mag.toMenu = function(maps, selected) {
    return maps.map(function(v, k) {
      return {
        _text: v,
        _value: k,
        _selected: selected === k || selected === v ? true : null
      }
    })
  }

  /*
  module library creation with single global namespace / package names
  (function(namespace) {

    var mod = {
      view: function(state, props) {
      }
    }

    namespace.CommentBox = mod;

  })(mag.namespace('mglazer.mods.comments'));
  */
  mag.namespace = function(ns, obj) {
    var levels = ns.split('.'),
      first = levels.shift();
    obj = obj || this; //if no object argument supplied declare a global property
    obj[first] = obj[first] || {}; // initialize the "level"
    if (levels.length) { // recursion condition
      return mag.namespace(levels.join('.'), obj[first]);
    }
    return obj[first]; // return a reference to the top level object
  }

  //ROUTER:

  mag.route = (function(window) {

    'use strict';

    var routes = [];

    function addRoute(route, handler) {

      routes.push({
        parts: route.split('/'),
        handler: handler
      });
    }

    function load(route) {
      window.location.hash = route;
    }

    function start() {

      var path = window.location.hash.substr(1),
        parts = path.split('/'),
        partsLength = parts.length;

      for (var i = 0; i < routes.length; i++) {
        var route = routes[i];
        if (route.parts.length === partsLength) {
          var params = [];
          for (var j = 0; j < partsLength; j++) {
            if (route.parts[j].substr(0, 1) === ':') {
              params.push(parts[j]);
            } else if (route.parts[j] !== parts[j]) {
              break;
            }
          }
          if (j === partsLength) {
            route.handler.apply(undefined, params);
            return;
          }
        }
      }
    }

    window.onhashchange = start;

    return {
      addRoute: addRoute,
      load: load,
      start: start
    };

  }(window));

  //PLUGINS!
  // hookins

function forEach(obj, fn) {
  var keys = Object.keys(obj);
  for (var i = 0, l = keys.length; i < l; ++i) {
    var key = keys[i];
    fn(key, obj[key]);
  }
}

mag.hookin('attributes', 'key', function(data) {
  // remove system key from being added to attributes in html
  data.value = null
});

mag.hookin('attributes', 'style', function(data) {

  //convert from object
  if (typeof data.value === 'object') {
    // get current styles not overwrite existing?
    var style = data.node.getAttribute('style') || '';
    forEach(data.value, function(key, value) {
      style += key + ':' + (!isNaN(value) ? (value + "px") : value) + ';';
    });
    data.value = style;
  }
});

  // _className plugin example
  mag.hookin('attributes', 'className', function(data) {
    data.key = 'class'
    var newClass = data.value

    if (typeof data.value == 'string') {
      newClass = data.value.split(' ')
    } else if (typeof data.value == 'object') {
      for (var k in newClass) {
        data.node.classList.toggle(k, newClass[k])
      }
      data.value = data.node.classList + ''
      return
    }

    data.value = data.node.classList + ''

    for (var k in newClass) {
      var cls = newClass[k]
      if (cls.trim() && data.node.classList.length > 0 && !data.node.classList.contains(cls.trim())) {
        data.value = data.node.classList + ' ' + cls

      } else if (cls.trim() && data.node.classList.length == 0) {
        data.value += cls + ' '
      }
    }

    data.value = data.value.trim()
  })

  //Values hookin:
mag.hookin('values', '*', function(data) {
  var dtype = typeof data.value

  if (data.value == null) {

  } else
  // allow function to return values
  if (dtype === 'function' && data.value.toJSON) {
    data.change = 1
    data.value = data.value()
  } else
  // Allow for promises to be resolved
  if (dtype == 'object' && typeof data.value.then == 'function') {
    var mid = mag.utils.items.getItem(mag.fill.id);

    data.value.then(function(newData) {
      mag.mod.getState(mid)[data.key] = newData;
    })

    if (data.value.initialValue) {
      data.change = 1
      data.value = data.value.initialValue
    }
  }
})

//GetId helper method
mag.getId =function(instanceId){
  return mag.utils.items.getItemVal(instanceId);
};

  /** DEPRECATED - avoid use **/

  mag.prop = function(store) {
    var prop = function() {
      if (arguments.length) store = arguments[0];
      return store;
    };

    prop.toJSON = function() {
      return store;
    };
    prop.type = 'fun'
    return prop;
  };

  mag.withProp = function(prop, withAttrCallback) {
    return function(e) {
      e = e || event;
      var currentTarget = e.currentTarget || this;
      withAttrCallback(prop in currentTarget ? currentTarget[prop] : currentTarget.getAttribute(prop))
    }
  }

})(mag, window, document);
<commit_msg>Update mag.addons.0.2.js<commit_after>/*
Mag.JS AddOns v0.21.8
(c) Michael Glazer 2016
https://github.com/magnumjs/mag.js
Requires: MagJS (core) Addons: Ajax , Router
*/

;
(function(mag, window, document, undefined) {

  'use strict';

  // helper
  mag.noop = function() {}

  //UTILITY
  // mag.utils.copy - now in core
  // mag.utils.merge - now in core

  mag.copy = mag.utils.copy
  mag.merge = mag.utils.merge

  /*
  controller:function(props)
    // if props has a property 'isVisible' when true will display entire module on before updates
    mag.show(this,'isVisible')
  }
  http://jsbin.com/fegizubime/edit?html,js,output
  */

  // show hide

  mag.show = function(context, conditionName) {
    var ctype = typeof context;
    if (ctype !== 'object') {
      var obj = {
        _config: function(node) {
          node.style.display = context ? 'block' : 'none'
        }
      }
      if (typeof conditionName == 'object') {
        mag.merge(conditionName, obj)
      }
      return obj
    } else if (ctype == 'object') {
      context.willload = function(event, node, inprops) {
        node.style.display = 'block'
      }
    } else {
      context.willupdate = function(event, node, inprops) {
        node.style.display = inprops[conditionName] ? 'block' : 'none'
      }
    }
  }

  // promises

  /*
  var d = mag.deferred()

  d.promise.then(function() {
    console.log('success', arguments)
  }, function() {
    console.log('failure', arguments)
  })
  d.reject({
    things: false
  })
  d.resolve({
    things: []
  })
  */

mag.deferred = function() {
  var Deferred = {}
  Deferred.promise = new Promise(function(resolve, reject) {
    Deferred.resolve = resolve
    Deferred.reject = reject
  })
  return Deferred
}

mag.when = function(arrayOfPromises, callback) {
  return Promise.all(arrayOfPromises).then(callback)
}

//TODO: add jsonp support

mag.request = function(options) {
  var deferred = mag.deferred();
  if (options.initialValue) {
    deferred.promise.initialValue = options.initialValue
  }
  //Uid:
  var key = JSON.stringify(options)
    //Cache:
  if (options.cache) {
    var cache = mag.cache(key)
    if (cache) {
      deferred.resolve(cache)
      return deferred.promise
    }
  }

  //In queue:
  if (mag.request.queue[key]) {
    return mag.request.queue[key]
  }
  //Add to queue
  mag.request.queue[key] = deferred.promise;

  var client = new XMLHttpRequest();
  var method = (options.method || 'GET').toUpperCase();
  var data = method === "GET" || !options.data ? "" : options.data

  client.onload = function(e) {
    var ct = client.getResponseHeader("content-type") || "";
    var data = e.target.responseText;
    if (ct.indexOf('json') > -1) {
      data = JSON.parse(data)
    }
    if (options.cache) {
      mag.cache(key, data, options.cacheTime, options.cacheType)
    }
    delete mag.request.queue[key];
    var headers = client.getAllResponseHeaders();
    deferred.resolve(data, headers);
  }

  client.onerror = function(e) {
    deferred.reject(e)
  };

  client.open(method, options.url);
    //Headers:
  if(options.headers){
    for(var i=0;i<options.headers.length;i++){
    	var header = options.headers[i]
      for(var k in header){
    	  client.setRequestHeader(k, header[k]);
      }
    }
  }
  client.send(data);

  return deferred.promise
}
mag.request.queue = {}

mag.cache = function(key, data, cacheTime, storageType) {
   var stype = window[storageType || 'sessionStorage']

  if (arguments.length == 1) {

    if (mag.cache.data[key]) {
      return mag.cache.data[key].data;
    } else {
      // check storage
      var item = stype.getItem(key)
      if (item) {
        mag.cache.data[key] = JSON.parse(item)
        return mag.cache.data[key].data
      }
      else return 0;
    }
  }

  if (mag.cache.data[key] && mag.cache.data[key].id) clearTimeout(mag.cache.data[key].id)

  var intervalID = setTimeout(function(key) {
    stype.removeItem(key);
    delete mag.cache.data[key]
  }.bind({}, key), cacheTime || 1000 * 60 * 10); //10 minutes

  mag.cache.data[key] = {
    id: intervalID,
    data: data
  }

  stype.setItem(key, JSON.stringify(mag.cache.data[key]))
}
mag.cache.data = {}

  // goes with mag.request for json ajax requests
  /*
  will show and hide all ''.loader' elements in transition
  */
  mag.requestWithFeedback = function(args) {
    var key = JSON.stringify(args)
    if (!mag.requestWithFeedback.cache[key]) {

      var loaders = document.querySelectorAll(".loader")

      //show icons
      for (var i = 0, loader; loader = loaders[i]; i++) loader.style.display = "block"

      var expire = function(data) {
        delete mag.requestWithFeedback.cache[key]

        if (Object.keys(mag.requestWithFeedback.cache).length == 0) {
          //hide icons
          for (var i = 0, loader; loader = loaders[i]; i++) loader.style.display = "none"
        }
        return data
      }
      mag.requestWithFeedback.cache[key] = mag.request(args)
      mag.requestWithFeedback.cache[key].then(expire, function(error) {
        expire(error)
        throw error
      })
    }
    return mag.requestWithFeedback.cache[key]
  }
  mag.requestWithFeedback.cache = {}

  // disable add to config
  // http://jsbin.com/zepacabile/edit?js,output
  // define condition func
  // this.show = mag.prop(false);

  //define context
  //   this.input = mag.disable(this.show)
  // OR mag.disable(this.show, this.input={})
  //TODO: change to mag.ui.disable
 mag.disable = function(condition, obj) {

  // add or merge to config if not exists
  var orig = obj && obj._config ? obj._config : function() {};

  var tmp = {
    _config: function(n) {
      orig.apply(this, arguments);
      if (condition()) n.setAttribute('disabled', 'disabled');
      else n.removeAttribute('disabled');
    }
  }
  if (obj) {
    mag.merge(obj, tmp);
  }
  return tmp;

}

  // TODO: change to mag.find
  // find a MagJS element Matcher
  mag.find = function(parentRootId, selector) {
    var parent = document.getElementById(parentRootId);
    return mag.fill.find(parent, selector)
  }

  // mag.addons.toMenu(['one', 'two', 'three'], state.selected())
  // http://jsbin.com/mapuwojumu/3/edit?js,output
  //TODO change to mag.ui.menu
  mag.toMenu = function(maps, selected) {
    return maps.map(function(v, k) {
      return {
        _text: v,
        _value: k,
        _selected: selected === k || selected === v ? true : null
      }
    })
  }

  /*
  module library creation with single global namespace / package names
  (function(namespace) {

    var mod = {
      view: function(state, props) {
      }
    }

    namespace.CommentBox = mod;

  })(mag.namespace('mglazer.mods.comments'));
  */
  mag.namespace = function(ns, obj) {
    var levels = ns.split('.'),
      first = levels.shift();
    obj = obj || this; //if no object argument supplied declare a global property
    obj[first] = obj[first] || {}; // initialize the "level"
    if (levels.length) { // recursion condition
      return mag.namespace(levels.join('.'), obj[first]);
    }
    return obj[first]; // return a reference to the top level object
  }

  //ROUTER:

  mag.route = (function(window) {

    'use strict';

    var routes = [];

    function addRoute(route, handler) {

      routes.push({
        parts: route.split('/'),
        handler: handler
      });
    }

    function load(route) {
      window.location.hash = route;
    }

    function start() {

      var path = window.location.hash.substr(1),
        parts = path.split('/'),
        partsLength = parts.length;

      for (var i = 0; i < routes.length; i++) {
        var route = routes[i];
        if (route.parts.length === partsLength) {
          var params = [];
          for (var j = 0; j < partsLength; j++) {
            if (route.parts[j].substr(0, 1) === ':') {
              params.push(parts[j]);
            } else if (route.parts[j] !== parts[j]) {
              break;
            }
          }
          if (j === partsLength) {
            route.handler.apply(undefined, params);
            return;
          }
        }
      }
    }

    window.onhashchange = start;

    return {
      addRoute: addRoute,
      load: load,
      start: start
    };

  }(window));

  //PLUGINS!
  // hookins

function forEach(obj, fn) {
  var keys = Object.keys(obj);
  for (var i = 0, l = keys.length; i < l; ++i) {
    var key = keys[i];
    fn(key, obj[key]);
  }
}

mag.hookin('attributes', 'key', function(data) {
  // remove system key from being added to attributes in html
  data.value = null
});

mag.hookin('attributes', 'style', function(data) {

  //convert from object
  if (typeof data.value === 'object') {
    // get current styles not overwrite existing?

    var ostyle = data.node.getAttribute('style') || '';

    // make sure not already in styles
    var nstyle = ''
    forEach(data.value, function(key, value) {
     nstyle += key + ':' + (!isNaN(value) ? (value + "px") : value) + ';';
    });

    if(ostyle && ~ostyle.indexOf(nstyle)) data.value=ostyle;
    else data.value = ostyle+nstyle;

  }
});

  // _className plugin example
  mag.hookin('attributes', 'className', function(data) {
    data.key = 'class'
    var newClass = data.value

    if (typeof data.value == 'string') {
      newClass = data.value.split(' ')
    } else if (typeof data.value == 'object') {
      for (var k in newClass) {
        data.node.classList.toggle(k, newClass[k])
      }
      data.value = data.node.classList + ''
      return
    }

    data.value = data.node.classList + ''

    for (var k in newClass) {
      var cls = newClass[k]
      if (cls.trim() && data.node.classList.length > 0 && !data.node.classList.contains(cls.trim())) {
        data.value = data.node.classList + ' ' + cls

      } else if (cls.trim() && data.node.classList.length == 0) {
        data.value += cls + ' '
      }
    }

    data.value = data.value.trim()
  })

  //Values hookin:
mag.hookin('values', '*', function(data) {
  var dtype = typeof data.value

  if (data.value == null) {

  } else
  // allow function to return values
  if (dtype === 'function' && data.value.toJSON) {
    data.change = 1
    data.value = data.value()
  } else
  // Allow for promises to be resolved
  if (dtype == 'object' && typeof data.value.then == 'function') {
    var mid = mag.utils.items.getItem(mag.fill.id);

    data.value.then(function(newData) {
      mag.mod.getState(mid)[data.key] = newData;
    })

    if (data.value.initialValue) {
      data.change = 1
      data.value = data.value.initialValue
    }
  }
})

//GetId helper method
mag.getId =function(instanceId){
  return mag.utils.items.getItemVal(instanceId);
};

mag.prop = function(store) {
  var prop = function() {
    if (arguments.length) store = arguments[0];
    return store;
  };

  prop.toJSON = function() {
    return store;
  };
  prop.type = 'fun'
  return prop;
};

mag.withProp = function(prop, withAttrCallback) {
  return function(e) {
    e = e || event;
    var currentTarget = e.currentTarget || this;
    withAttrCallback(prop in currentTarget ? currentTarget[prop] : currentTarget.getAttribute(prop))
  }
}

})(mag, window || global || this, document);
<|endoftext|>