underscore-source 1.1.7 → 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
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