underscore-source 1.1.7 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  module Underscore
2
2
  module Source
3
- VERSION = "1.1.7"
3
+ VERSION = "1.2.0"
4
4
  end
5
5
  end
@@ -1,4 +1,4 @@
1
- // Underscore.js 1.1.7
1
+ // Underscore.js 1.2.0
2
2
  // (c) 2011 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,
@@ -60,7 +60,7 @@
60
60
  }
61
61
 
62
62
  // Current version.
63
- _.VERSION = '1.1.7';
63
+ _.VERSION = '1.2.0';
64
64
 
65
65
  // Collection Functions
66
66
  // --------------------
@@ -220,6 +220,7 @@
220
220
  // Return the maximum element or (element-based computation).
221
221
  _.max = function(obj, iterator, context) {
222
222
  if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
223
+ if (!iterator && _.isEmpty(obj)) return -Infinity;
223
224
  var result = {computed : -Infinity};
224
225
  each(obj, function(value, index, list) {
225
226
  var computed = iterator ? iterator.call(context, value, index, list) : value;
@@ -231,6 +232,7 @@
231
232
  // Return the minimum element (or element-based computation).
232
233
  _.min = function(obj, iterator, context) {
233
234
  if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
235
+ if (!iterator && _.isEmpty(obj)) return Infinity;
234
236
  var result = {computed : Infinity};
235
237
  each(obj, function(value, index, list) {
236
238
  var computed = iterator ? iterator.call(context, value, index, list) : value;
@@ -239,6 +241,21 @@
239
241
  return result.value;
240
242
  };
241
243
 
244
+ // Shuffle an array.
245
+ _.shuffle = function(obj) {
246
+ var shuffled = [], rand;
247
+ each(obj, function(value, index, list) {
248
+ if (index == 0) {
249
+ shuffled[0] = value;
250
+ } else {
251
+ rand = Math.floor(Math.random() * (index + 1));
252
+ shuffled[index] = shuffled[rand];
253
+ shuffled[rand] = value;
254
+ }
255
+ });
256
+ return shuffled;
257
+ };
258
+
242
259
  // Sort the object's values by a criterion produced by an iterator.
243
260
  _.sortBy = function(obj, iterator, context) {
244
261
  return _.pluck(_.map(obj, function(value, index, list) {
@@ -298,6 +315,20 @@
298
315
  return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
299
316
  };
300
317
 
318
+ // Returns everything but the last entry of the array. Especcialy useful on
319
+ // the arguments object. Passing **n** will return all the values in
320
+ // the array, excluding the last N. The **guard** check allows it to work with
321
+ // `_.map`.
322
+ _.initial = function(array, n, guard) {
323
+ return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
324
+ };
325
+
326
+ // Get the last element of an array. Passing **n** will return the last N
327
+ // values in the array. The **guard** check allows it to work with `_.map`.
328
+ _.last = function(array, n, guard) {
329
+ return (n != null) && !guard ? slice.call(array, array.length - n) : array[array.length - 1];
330
+ };
331
+
301
332
  // Returns everything but the first entry of the array. Aliased as `tail`.
302
333
  // Especially useful on the arguments object. Passing an **index** will return
303
334
  // the rest of the values in the array from that index onward. The **guard**
@@ -306,11 +337,6 @@
306
337
  return slice.call(array, (index == null) || guard ? 1 : index);
307
338
  };
308
339
 
309
- // Get the last element of an array.
310
- _.last = function(array) {
311
- return array[array.length - 1];
312
- };
313
-
314
340
  // Trim out all falsy values from an array.
315
341
  _.compact = function(array) {
316
342
  return _.filter(array, function(value){ return !!value; });
@@ -333,11 +359,17 @@
333
359
  // Produce a duplicate-free version of the array. If the array has already
334
360
  // been sorted, you have the option of using a faster algorithm.
335
361
  // Aliased as `unique`.
336
- _.uniq = _.unique = function(array, isSorted) {
337
- return _.reduce(array, function(memo, el, i) {
338
- if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo[memo.length] = el;
362
+ _.uniq = _.unique = function(array, isSorted, iterator) {
363
+ var initial = iterator ? _.map(array, iterator) : array;
364
+ var result = [];
365
+ _.reduce(initial, function(memo, el, i) {
366
+ if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
367
+ memo[memo.length] = el;
368
+ result[result.length] = array[i];
369
+ }
339
370
  return memo;
340
371
  }, []);
372
+ return result;
341
373
  };
342
374
 
343
375
  // Produce an array that contains the union: each distinct element from all of
@@ -391,7 +423,6 @@
391
423
  return -1;
392
424
  };
393
425
 
394
-
395
426
  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
396
427
  _.lastIndexOf = function(array, item) {
397
428
  if (array == null) return -1;
@@ -538,7 +569,6 @@
538
569
  };
539
570
  };
540
571
 
541
-
542
572
  // Object Functions
543
573
  // ----------------
544
574
 
@@ -599,44 +629,97 @@
599
629
  return obj;
600
630
  };
601
631
 
602
- // Perform a deep comparison to check if two objects are equal.
603
- _.isEqual = function(a, b) {
604
- // Check object identity.
605
- if (a === b) return true;
606
- // Different types?
607
- var atype = typeof(a), btype = typeof(b);
608
- if (atype != btype) return false;
609
- // Basic equality test (watch out for coercions).
610
- if (a == b) return true;
611
- // One is falsy and the other truthy.
612
- if ((!a && b) || (a && !b)) return false;
632
+ // Internal recursive comparison function.
633
+ function eq(a, b, stack) {
634
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
635
+ // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
636
+ if (a === b) return a !== 0 || 1 / a == 1 / b;
637
+ // A strict comparison is necessary because `null == undefined`.
638
+ if (a == null) return a === b;
639
+ // Compare object types.
640
+ var typeA = typeof a;
641
+ if (typeA != typeof b) return false;
642
+ // Optimization; ensure that both values are truthy or falsy.
643
+ if (!a != !b) return false;
644
+ // `NaN` values are equal.
645
+ if (_.isNaN(a)) return _.isNaN(b);
646
+ // Compare string objects by value.
647
+ var isStringA = _.isString(a), isStringB = _.isString(b);
648
+ if (isStringA || isStringB) return isStringA && isStringB && String(a) == String(b);
649
+ // Compare number objects by value.
650
+ var isNumberA = _.isNumber(a), isNumberB = _.isNumber(b);
651
+ if (isNumberA || isNumberB) return isNumberA && isNumberB && +a == +b;
652
+ // Compare boolean objects by value. The value of `true` is 1; the value of `false` is 0.
653
+ var isBooleanA = _.isBoolean(a), isBooleanB = _.isBoolean(b);
654
+ if (isBooleanA || isBooleanB) return isBooleanA && isBooleanB && +a == +b;
655
+ // Compare dates by their millisecond values.
656
+ var isDateA = _.isDate(a), isDateB = _.isDate(b);
657
+ if (isDateA || isDateB) return isDateA && isDateB && a.getTime() == b.getTime();
658
+ // Compare RegExps by their source patterns and flags.
659
+ var isRegExpA = _.isRegExp(a), isRegExpB = _.isRegExp(b);
660
+ if (isRegExpA || isRegExpB) {
661
+ // Ensure commutative equality for RegExps.
662
+ return isRegExpA && isRegExpB &&
663
+ a.source == b.source &&
664
+ a.global == b.global &&
665
+ a.multiline == b.multiline &&
666
+ a.ignoreCase == b.ignoreCase;
667
+ }
668
+ // Ensure that both values are objects.
669
+ if (typeA != 'object') return false;
613
670
  // Unwrap any wrapped objects.
614
671
  if (a._chain) a = a._wrapped;
615
672
  if (b._chain) b = b._wrapped;
616
- // One of them implements an isEqual()?
617
- if (a.isEqual) return a.isEqual(b);
618
- if (b.isEqual) return b.isEqual(a);
619
- // Check dates' integer values.
620
- if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
621
- // Both are NaN?
622
- if (_.isNaN(a) && _.isNaN(b)) return false;
623
- // Compare regular expressions.
624
- if (_.isRegExp(a) && _.isRegExp(b))
625
- return a.source === b.source &&
626
- a.global === b.global &&
627
- a.ignoreCase === b.ignoreCase &&
628
- a.multiline === b.multiline;
629
- // If a is not an object by this point, we can't handle it.
630
- if (atype !== 'object') return false;
631
- // Check for different array lengths before comparing contents.
632
- if (a.length && (a.length !== b.length)) return false;
633
- // Nothing else worked, deep compare the contents.
634
- var aKeys = _.keys(a), bKeys = _.keys(b);
635
- // Different object sizes?
636
- if (aKeys.length != bKeys.length) return false;
637
- // Recursive comparison of contents.
638
- for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
639
- return true;
673
+ // Invoke a custom `isEqual` method if one is provided.
674
+ if (_.isFunction(a.isEqual)) return a.isEqual(b);
675
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic structures is
676
+ // adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
677
+ var length = stack.length;
678
+ while (length--) {
679
+ // Linear search. Performance is inversely proportional to the number of unique nested
680
+ // structures.
681
+ if (stack[length] == a) return true;
682
+ }
683
+ // Add the first object to the stack of traversed objects.
684
+ stack.push(a);
685
+ var size = 0, result = true;
686
+ if (a.length === +a.length || b.length === +b.length) {
687
+ // Compare object lengths to determine if a deep comparison is necessary.
688
+ size = a.length;
689
+ result = size == b.length;
690
+ if (result) {
691
+ // Deep compare array-like object contents, ignoring non-numeric properties.
692
+ while (size--) {
693
+ // Ensure commutative equality for sparse arrays.
694
+ if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
695
+ }
696
+ }
697
+ } else {
698
+ // Deep compare objects.
699
+ for (var key in a) {
700
+ if (hasOwnProperty.call(a, key)) {
701
+ // Count the expected number of properties.
702
+ size++;
703
+ // Deep compare each member.
704
+ if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break;
705
+ }
706
+ }
707
+ // Ensure that both objects contain the same number of properties.
708
+ if (result) {
709
+ for (key in b) {
710
+ if (hasOwnProperty.call(b, key) && !size--) break;
711
+ }
712
+ result = !size;
713
+ }
714
+ }
715
+ // Remove the first object from the stack of traversed objects.
716
+ stack.pop();
717
+ return result;
718
+ }
719
+
720
+ // Perform a deep comparison to check if two objects are equal.
721
+ _.isEqual = function(a, b) {
722
+ return eq(a, b, []);
640
723
  };
641
724
 
642
725
  // Is a given array or object empty?
@@ -690,7 +773,7 @@
690
773
 
691
774
  // Is a given value a boolean?
692
775
  _.isBoolean = function(obj) {
693
- return obj === true || obj === false;
776
+ return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
694
777
  };
695
778
 
696
779
  // Is a given value a date?
@@ -733,6 +816,11 @@
733
816
  for (var i = 0; i < n; i++) iterator.call(context, i);
734
817
  };
735
818
 
819
+ // Escape a string for HTML interpolation.
820
+ _.escape = function(string) {
821
+ return (''+string).replace(/&(?!\w+;|#\d+;|#x[\da-f]+;)/gi, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
822
+ };
823
+
736
824
  // Add your own custom functions to the Underscore object, ensuring that
737
825
  // they're correctly added to the OOP wrapper as well.
738
826
  _.mixin = function(obj) {
@@ -753,7 +841,8 @@
753
841
  // following template settings to use alternative delimiters.
754
842
  _.templateSettings = {
755
843
  evaluate : /<%([\s\S]+?)%>/g,
756
- interpolate : /<%=([\s\S]+?)%>/g
844
+ interpolate : /<%=([\s\S]+?)%>/g,
845
+ escape : /<%-([\s\S]+?)%>/g
757
846
  };
758
847
 
759
848
  // JavaScript micro-templating, similar to John Resig's implementation.
@@ -765,6 +854,9 @@
765
854
  'with(obj||{}){__p.push(\'' +
766
855
  str.replace(/\\/g, '\\\\')
767
856
  .replace(/'/g, "\\'")
857
+ .replace(c.escape, function(match, code) {
858
+ return "',_.escape(" + code.replace(/\\'/g, "'") + "),'";
859
+ })
768
860
  .replace(c.interpolate, function(match, code) {
769
861
  return "'," + code.replace(/\\'/g, "'") + ",'";
770
862
  })
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: underscore-source
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.1.7
5
+ version: 1.2.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Daniel X. Moore