judge 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
- // Underscore.js 1.2.1
2
- // (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
1
+ // Underscore.js 1.3.1
2
+ // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
3
3
  // Underscore is freely distributable under the MIT license.
4
4
  // Portions of Underscore are inspired or borrowed from Prototype,
5
5
  // Oliver Steele's Functional, and John Resig's Micro-Templating.
@@ -48,26 +48,21 @@
48
48
  // Create a safe reference to the Underscore object for use below.
49
49
  var _ = function(obj) { return new wrapper(obj); };
50
50
 
51
- // Export the Underscore object for **Node.js** and **"CommonJS"**, with
52
- // backwards-compatibility for the old `require()` API. If we're not in
53
- // CommonJS, add `_` to the global object.
51
+ // Export the Underscore object for **Node.js**, with
52
+ // backwards-compatibility for the old `require()` API. If we're in
53
+ // the browser, add `_` as a global object via a string identifier,
54
+ // for Closure Compiler "advanced" mode.
54
55
  if (typeof exports !== 'undefined') {
55
56
  if (typeof module !== 'undefined' && module.exports) {
56
57
  exports = module.exports = _;
57
58
  }
58
59
  exports._ = _;
59
- } else if (typeof define === 'function' && define.amd) {
60
- // Register as a named module with AMD.
61
- define('underscore', function() {
62
- return _;
63
- });
64
60
  } else {
65
- // Exported as a string, for Closure Compiler "advanced" mode.
66
61
  root['_'] = _;
67
62
  }
68
63
 
69
64
  // Current version.
70
- _.VERSION = '1.2.1';
65
+ _.VERSION = '1.3.1';
71
66
 
72
67
  // Collection Functions
73
68
  // --------------------
@@ -85,7 +80,7 @@
85
80
  }
86
81
  } else {
87
82
  for (var key in obj) {
88
- if (hasOwnProperty.call(obj, key)) {
83
+ if (_.has(obj, key)) {
89
84
  if (iterator.call(context, obj[key], key, obj) === breaker) return;
90
85
  }
91
86
  }
@@ -94,20 +89,21 @@
94
89
 
95
90
  // Return the results of applying the iterator to each element.
96
91
  // Delegates to **ECMAScript 5**'s native `map` if available.
97
- _.map = function(obj, iterator, context) {
92
+ _.map = _.collect = function(obj, iterator, context) {
98
93
  var results = [];
99
94
  if (obj == null) return results;
100
95
  if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
101
96
  each(obj, function(value, index, list) {
102
97
  results[results.length] = iterator.call(context, value, index, list);
103
98
  });
99
+ if (obj.length === +obj.length) results.length = obj.length;
104
100
  return results;
105
101
  };
106
102
 
107
103
  // **Reduce** builds up a single result from a list of values, aka `inject`,
108
104
  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
109
105
  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
110
- var initial = memo !== void 0;
106
+ var initial = arguments.length > 2;
111
107
  if (obj == null) obj = [];
112
108
  if (nativeReduce && obj.reduce === nativeReduce) {
113
109
  if (context) iterator = _.bind(iterator, context);
@@ -121,20 +117,22 @@
121
117
  memo = iterator.call(context, memo, value, index, list);
122
118
  }
123
119
  });
124
- if (!initial) throw new TypeError("Reduce of empty array with no initial value");
120
+ if (!initial) throw new TypeError('Reduce of empty array with no initial value');
125
121
  return memo;
126
122
  };
127
123
 
128
124
  // The right-associative version of reduce, also known as `foldr`.
129
125
  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
130
126
  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
127
+ var initial = arguments.length > 2;
131
128
  if (obj == null) obj = [];
132
129
  if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
133
130
  if (context) iterator = _.bind(iterator, context);
134
- return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
131
+ return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
135
132
  }
136
- var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
137
- return _.reduce(reversed, iterator, memo, context);
133
+ var reversed = _.toArray(obj).reverse();
134
+ if (context && !initial) iterator = _.bind(iterator, context);
135
+ return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
138
136
  };
139
137
 
140
138
  // Return the first value which passes a truth test. Aliased as `detect`.
@@ -189,12 +187,12 @@
189
187
  // Delegates to **ECMAScript 5**'s native `some` if available.
190
188
  // Aliased as `any`.
191
189
  var any = _.some = _.any = function(obj, iterator, context) {
192
- iterator = iterator || _.identity;
190
+ iterator || (iterator = _.identity);
193
191
  var result = false;
194
192
  if (obj == null) return result;
195
193
  if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
196
194
  each(obj, function(value, index, list) {
197
- if (result |= iterator.call(context, value, index, list)) return breaker;
195
+ if (result || (result = iterator.call(context, value, index, list))) return breaker;
198
196
  });
199
197
  return !!result;
200
198
  };
@@ -215,7 +213,7 @@
215
213
  _.invoke = function(obj, method) {
216
214
  var args = slice.call(arguments, 2);
217
215
  return _.map(obj, function(value) {
218
- return (method.call ? method || value : value[method]).apply(value, args);
216
+ return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
219
217
  });
220
218
  };
221
219
 
@@ -335,7 +333,11 @@
335
333
  // Get the last element of an array. Passing **n** will return the last N
336
334
  // values in the array. The **guard** check allows it to work with `_.map`.
337
335
  _.last = function(array, n, guard) {
338
- return (n != null) && !guard ? slice.call(array, array.length - n) : array[array.length - 1];
336
+ if ((n != null) && !guard) {
337
+ return slice.call(array, Math.max(array.length - n, 0));
338
+ } else {
339
+ return array[array.length - 1];
340
+ }
339
341
  };
340
342
 
341
343
  // Returns everything but the first entry of the array. Aliased as `tail`.
@@ -398,10 +400,11 @@
398
400
  });
399
401
  };
400
402
 
401
- // Take the difference between one array and another.
403
+ // Take the difference between one array and a number of other arrays.
402
404
  // Only the elements present in just the first array will remain.
403
- _.difference = function(array, other) {
404
- return _.filter(array, function(value){ return !_.include(other, value); });
405
+ _.difference = function(array) {
406
+ var rest = _.flatten(slice.call(arguments, 1));
407
+ return _.filter(array, function(value){ return !_.include(rest, value); });
405
408
  };
406
409
 
407
410
  // Zip together multiple lists into a single array -- elements that share
@@ -428,7 +431,7 @@
428
431
  return array[i] === item ? i : -1;
429
432
  }
430
433
  if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
431
- for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
434
+ for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
432
435
  return -1;
433
436
  };
434
437
 
@@ -437,7 +440,7 @@
437
440
  if (array == null) return -1;
438
441
  if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
439
442
  var i = array.length;
440
- while (i--) if (array[i] === item) return i;
443
+ while (i--) if (i in array && array[i] === item) return i;
441
444
  return -1;
442
445
  };
443
446
 
@@ -503,7 +506,7 @@
503
506
  hasher || (hasher = _.identity);
504
507
  return function() {
505
508
  var key = hasher.apply(this, arguments);
506
- return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
509
+ return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
507
510
  };
508
511
  };
509
512
 
@@ -575,7 +578,7 @@
575
578
  // conditionally execute the original function.
576
579
  _.wrap = function(func, wrapper) {
577
580
  return function() {
578
- var args = [func].concat(slice.call(arguments));
581
+ var args = [func].concat(slice.call(arguments, 0));
579
582
  return wrapper.apply(this, args);
580
583
  };
581
584
  };
@@ -583,9 +586,9 @@
583
586
  // Returns a function that is the composition of a list of functions, each
584
587
  // consuming the return value of the function that follows.
585
588
  _.compose = function() {
586
- var funcs = slice.call(arguments);
589
+ var funcs = arguments;
587
590
  return function() {
588
- var args = slice.call(arguments);
591
+ var args = arguments;
589
592
  for (var i = funcs.length - 1; i >= 0; i--) {
590
593
  args = [funcs[i].apply(this, args)];
591
594
  }
@@ -595,6 +598,7 @@
595
598
 
596
599
  // Returns a function that will only be executed after being called N times.
597
600
  _.after = function(times, func) {
601
+ if (times <= 0) return func();
598
602
  return function() {
599
603
  if (--times < 1) { return func.apply(this, arguments); }
600
604
  };
@@ -608,7 +612,7 @@
608
612
  _.keys = nativeKeys || function(obj) {
609
613
  if (obj !== Object(obj)) throw new TypeError('Invalid object');
610
614
  var keys = [];
611
- for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
615
+ for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
612
616
  return keys;
613
617
  };
614
618
 
@@ -631,7 +635,7 @@
631
635
  _.extend = function(obj) {
632
636
  each(slice.call(arguments, 1), function(source) {
633
637
  for (var prop in source) {
634
- if (source[prop] !== void 0) obj[prop] = source[prop];
638
+ obj[prop] = source[prop];
635
639
  }
636
640
  });
637
641
  return obj;
@@ -667,48 +671,40 @@
667
671
  // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
668
672
  if (a === b) return a !== 0 || 1 / a == 1 / b;
669
673
  // A strict comparison is necessary because `null == undefined`.
670
- if ((a == null) || (b == null)) return a === b;
674
+ if (a == null || b == null) return a === b;
671
675
  // Unwrap any wrapped objects.
672
676
  if (a._chain) a = a._wrapped;
673
677
  if (b._chain) b = b._wrapped;
674
678
  // Invoke a custom `isEqual` method if one is provided.
675
- if (_.isFunction(a.isEqual)) return a.isEqual(b);
676
- if (_.isFunction(b.isEqual)) return b.isEqual(a);
677
- // Compare object types.
678
- var typeA = typeof a;
679
- if (typeA != typeof b) return false;
680
- // Optimization; ensure that both values are truthy or falsy.
681
- if (!a != !b) return false;
682
- // `NaN` values are equal.
683
- if (_.isNaN(a)) return _.isNaN(b);
684
- // Compare string objects by value.
685
- var isStringA = _.isString(a), isStringB = _.isString(b);
686
- if (isStringA || isStringB) return isStringA && isStringB && String(a) == String(b);
687
- // Compare number objects by value.
688
- var isNumberA = _.isNumber(a), isNumberB = _.isNumber(b);
689
- if (isNumberA || isNumberB) return isNumberA && isNumberB && +a == +b;
690
- // Compare boolean objects by value. The value of `true` is 1; the value of `false` is 0.
691
- var isBooleanA = _.isBoolean(a), isBooleanB = _.isBoolean(b);
692
- if (isBooleanA || isBooleanB) return isBooleanA && isBooleanB && +a == +b;
693
- // Compare dates by their millisecond values.
694
- var isDateA = _.isDate(a), isDateB = _.isDate(b);
695
- if (isDateA || isDateB) return isDateA && isDateB && a.getTime() == b.getTime();
696
- // Compare RegExps by their source patterns and flags.
697
- var isRegExpA = _.isRegExp(a), isRegExpB = _.isRegExp(b);
698
- if (isRegExpA || isRegExpB) {
699
- // Ensure commutative equality for RegExps.
700
- return isRegExpA && isRegExpB &&
701
- a.source == b.source &&
702
- a.global == b.global &&
703
- a.multiline == b.multiline &&
704
- a.ignoreCase == b.ignoreCase;
679
+ if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
680
+ if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
681
+ // Compare `[[Class]]` names.
682
+ var className = toString.call(a);
683
+ if (className != toString.call(b)) return false;
684
+ switch (className) {
685
+ // Strings, numbers, dates, and booleans are compared by value.
686
+ case '[object String]':
687
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
688
+ // equivalent to `new String("5")`.
689
+ return a == String(b);
690
+ case '[object Number]':
691
+ // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
692
+ // other numeric values.
693
+ return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
694
+ case '[object Date]':
695
+ case '[object Boolean]':
696
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
697
+ // millisecond representations. Note that invalid dates with millisecond representations
698
+ // of `NaN` are not equivalent.
699
+ return +a == +b;
700
+ // RegExps are compared by their source patterns and flags.
701
+ case '[object RegExp]':
702
+ return a.source == b.source &&
703
+ a.global == b.global &&
704
+ a.multiline == b.multiline &&
705
+ a.ignoreCase == b.ignoreCase;
705
706
  }
706
- // Ensure that both values are objects.
707
- if (typeA != 'object') return false;
708
- // Arrays or Arraylikes with different lengths are not equal.
709
- if (a.length !== b.length) return false;
710
- // Objects with different constructors are not equal.
711
- if (a.constructor !== b.constructor) return false;
707
+ if (typeof a != 'object' || typeof b != 'object') return false;
712
708
  // Assume equality for cyclic structures. The algorithm for detecting cyclic
713
709
  // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
714
710
  var length = stack.length;
@@ -720,21 +716,37 @@
720
716
  // Add the first object to the stack of traversed objects.
721
717
  stack.push(a);
722
718
  var size = 0, result = true;
723
- // Deep compare objects.
724
- for (var key in a) {
725
- if (hasOwnProperty.call(a, key)) {
726
- // Count the expected number of properties.
727
- size++;
728
- // Deep compare each member.
729
- if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break;
719
+ // Recursively compare objects and arrays.
720
+ if (className == '[object Array]') {
721
+ // Compare array lengths to determine if a deep comparison is necessary.
722
+ size = a.length;
723
+ result = size == b.length;
724
+ if (result) {
725
+ // Deep compare the contents, ignoring non-numeric properties.
726
+ while (size--) {
727
+ // Ensure commutative equality for sparse arrays.
728
+ if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
729
+ }
730
730
  }
731
- }
732
- // Ensure that both objects contain the same number of properties.
733
- if (result) {
734
- for (key in b) {
735
- if (hasOwnProperty.call(b, key) && !(size--)) break;
731
+ } else {
732
+ // Objects with different constructors are not equivalent.
733
+ if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
734
+ // Deep compare objects.
735
+ for (var key in a) {
736
+ if (_.has(a, key)) {
737
+ // Count the expected number of properties.
738
+ size++;
739
+ // Deep compare each member.
740
+ if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
741
+ }
742
+ }
743
+ // Ensure that both objects contain the same number of properties.
744
+ if (result) {
745
+ for (key in b) {
746
+ if (_.has(b, key) && !(size--)) break;
747
+ }
748
+ result = !size;
736
749
  }
737
- result = !size;
738
750
  }
739
751
  // Remove the first object from the stack of traversed objects.
740
752
  stack.pop();
@@ -750,7 +762,7 @@
750
762
  // An "empty" object has no enumerable own-properties.
751
763
  _.isEmpty = function(obj) {
752
764
  if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
753
- for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
765
+ for (var key in obj) if (_.has(obj, key)) return false;
754
766
  return true;
755
767
  };
756
768
 
@@ -771,13 +783,12 @@
771
783
  };
772
784
 
773
785
  // Is a given variable an arguments object?
774
- if (toString.call(arguments) == '[object Arguments]') {
775
- _.isArguments = function(obj) {
776
- return toString.call(obj) == '[object Arguments]';
777
- };
778
- } else {
786
+ _.isArguments = function(obj) {
787
+ return toString.call(obj) == '[object Arguments]';
788
+ };
789
+ if (!_.isArguments(arguments)) {
779
790
  _.isArguments = function(obj) {
780
- return !!(obj && hasOwnProperty.call(obj, 'callee'));
791
+ return !!(obj && _.has(obj, 'callee'));
781
792
  };
782
793
  }
783
794
 
@@ -827,6 +838,11 @@
827
838
  return obj === void 0;
828
839
  };
829
840
 
841
+ // Has own property?
842
+ _.has = function(obj, key) {
843
+ return hasOwnProperty.call(obj, key);
844
+ };
845
+
830
846
  // Utility Functions
831
847
  // -----------------
832
848
 
@@ -876,6 +892,17 @@
876
892
  escape : /<%-([\s\S]+?)%>/g
877
893
  };
878
894
 
895
+ // When customizing `templateSettings`, if you don't want to define an
896
+ // interpolation, evaluation or escaping regex, we need one that is
897
+ // guaranteed not to match.
898
+ var noMatch = /.^/;
899
+
900
+ // Within an interpolation, evaluation, or escaping, remove HTML escaping
901
+ // that had been previously added.
902
+ var unescape = function(code) {
903
+ return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
904
+ };
905
+
879
906
  // JavaScript micro-templating, similar to John Resig's implementation.
880
907
  // Underscore templating handles arbitrary delimiters, preserves whitespace,
881
908
  // and correctly escapes quotes within interpolated code.
@@ -885,22 +912,29 @@
885
912
  'with(obj||{}){__p.push(\'' +
886
913
  str.replace(/\\/g, '\\\\')
887
914
  .replace(/'/g, "\\'")
888
- .replace(c.escape, function(match, code) {
889
- return "',_.escape(" + code.replace(/\\'/g, "'") + "),'";
915
+ .replace(c.escape || noMatch, function(match, code) {
916
+ return "',_.escape(" + unescape(code) + "),'";
890
917
  })
891
- .replace(c.interpolate, function(match, code) {
892
- return "'," + code.replace(/\\'/g, "'") + ",'";
918
+ .replace(c.interpolate || noMatch, function(match, code) {
919
+ return "'," + unescape(code) + ",'";
893
920
  })
894
- .replace(c.evaluate || null, function(match, code) {
895
- return "');" + code.replace(/\\'/g, "'")
896
- .replace(/[\r\n\t]/g, ' ') + "__p.push('";
921
+ .replace(c.evaluate || noMatch, function(match, code) {
922
+ return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('";
897
923
  })
898
924
  .replace(/\r/g, '\\r')
899
925
  .replace(/\n/g, '\\n')
900
926
  .replace(/\t/g, '\\t')
901
927
  + "');}return __p.join('');";
902
928
  var func = new Function('obj', '_', tmpl);
903
- return data ? func(data, _) : function(data) { return func(data, _) };
929
+ if (data) return func(data, _);
930
+ return function(data) {
931
+ return func.call(this, data, _);
932
+ };
933
+ };
934
+
935
+ // Add a "chain" function, which will delegate to the wrapper.
936
+ _.chain = function(obj) {
937
+ return _(obj).chain();
904
938
  };
905
939
 
906
940
  // The OOP Wrapper
@@ -935,8 +969,11 @@
935
969
  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
936
970
  var method = ArrayProto[name];
937
971
  wrapper.prototype[name] = function() {
938
- method.apply(this._wrapped, arguments);
939
- return result(this._wrapped, this._chain);
972
+ var wrapped = this._wrapped;
973
+ method.apply(wrapped, arguments);
974
+ var length = wrapped.length;
975
+ if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
976
+ return result(wrapped, this._chain);
940
977
  };
941
978
  });
942
979
 
data/lib/judge/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Judge
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -58,7 +58,7 @@ describe('judge', function() {
58
58
  });
59
59
 
60
60
  it('has custom validation methods when defined by user', function() {
61
- judge.customValidators.phatness = function(options) { return { valid: true }; };
61
+ judge.customValidators.phatness = function() {};
62
62
  expect(_(j.validates()).keys()).toContain('phatness');
63
63
  });
64
64
 
@@ -649,13 +649,14 @@ describe('judge', function() {
649
649
  describe('convertFlags', function() {
650
650
 
651
651
  it('returns m if present in options string without negation', function() {
652
- expect(judge.utils.convertFlags('imx')).toEqual('m');
652
+ expect(judge.utils.convertFlags('mix')).toEqual('m');
653
+ expect(judge.utils.convertFlags('m-ix')).toEqual('m');
654
+ expect(judge.utils.convertFlags('mx-i')).toEqual('m');
653
655
  });
654
656
 
655
657
  it('returns empty string otherwise', function() {
656
- expect(judge.utils.convertFlags('-imx')).toEqual('');
657
- expect(judge.utils.convertFlags('ix')).toEqual('');
658
- expect(judge.utils.convertFlags('-m')).toEqual('');
658
+ expect(judge.utils.convertFlags('ix-m')).toEqual('');
659
+ expect(judge.utils.convertFlags('x-mi')).toEqual('');
659
660
  });
660
661
 
661
662
  });