@jaredwray/fumanchu 2.0.0 → 3.0.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.
package/lib/array.js DELETED
@@ -1,822 +0,0 @@
1
- 'use strict';
2
-
3
- var util = require('handlebars-utils');
4
- var utils = require('./utils');
5
- var helpers = module.exports;
6
-
7
- /**
8
- * Returns all of the items in an array after the specified index.
9
- * Opposite of [before](#before).
10
- *
11
- * ```handlebars
12
- * <!-- array: ['a', 'b', 'c'] -->
13
- * {{after array 1}}
14
- * <!-- results in: '["c"]' -->
15
- * ```
16
- * @param {Array} `array` Collection
17
- * @param {Number} `n` Starting index (number of items to exclude)
18
- * @return {Array} Array exluding `n` items.
19
- * @api public
20
- */
21
-
22
- helpers.after = function(array, n) {
23
- if (util.isUndefined(array)) return '';
24
- return array.slice(n);
25
- };
26
-
27
- /**
28
- * Cast the given `value` to an array.
29
- *
30
- * ```handlebars
31
- * {{arrayify "foo"}}
32
- * <!-- results in: [ "foo" ] -->
33
- * ```
34
- * @param {any} `value`
35
- * @return {Array}
36
- * @api public
37
- */
38
-
39
- helpers.arrayify = function(value) {
40
- return value ? (Array.isArray(value) ? value : [value]) : [];
41
- };
42
-
43
- /**
44
- * Return all of the items in the collection before the specified
45
- * count. Opposite of [after](#after).
46
- *
47
- * ```handlebars
48
- * <!-- array: ['a', 'b', 'c'] -->
49
- * {{before array 2}}
50
- * <!-- results in: '["a", "b"]' -->
51
- * ```
52
- * @param {Array} `array`
53
- * @param {Number} `n`
54
- * @return {Array} Array excluding items after the given number.
55
- * @api public
56
- */
57
-
58
- helpers.before = function(array, n) {
59
- if (util.isUndefined(array)) return '';
60
- return array.slice(0, -n);
61
- };
62
-
63
- /**
64
- * ```handlebars
65
- * <!-- array: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] -->
66
- * {{#eachIndex array}}
67
- * {{item}} is {{index}}
68
- * {{/eachIndex}}
69
- * ```
70
- * @param {Array} `array`
71
- * @param {Object} `options`
72
- * @return {String}
73
- * @block
74
- * @api public
75
- */
76
-
77
- helpers.eachIndex = function(array, options) {
78
- var result = '';
79
- for (var i = 0; i < array.length; i++) {
80
- result += options.fn({item: array[i], index: i});
81
- }
82
- return result;
83
- };
84
-
85
- /**
86
- * Block helper that filters the given array and renders the block for values that
87
- * evaluate to `true`, otherwise the inverse block is returned.
88
- *
89
- * ```handlebars
90
- * <!-- array: ['a', 'b', 'c'] -->
91
- * {{#filter array "foo"}}AAA{{else}}BBB{{/filter}}
92
- * <!-- results in: 'BBB' -->
93
- * ```
94
- * @param {Array} `array`
95
- * @param {any} `value`
96
- * @param {Object} `options`
97
- * @return {String}
98
- * @block
99
- * @api public
100
- */
101
-
102
- helpers.filter = function(array, value, options) {
103
- var content = '';
104
- var results = [];
105
-
106
- // filter on a specific property
107
- var prop = options.hash && (options.hash.property || options.hash.prop);
108
- if (prop) {
109
- results = array.filter(function(val) {
110
- return value === utils.get(val, prop);
111
- });
112
- } else {
113
-
114
- // filter on a string value
115
- results = array.filter(function(v) {
116
- return value === v;
117
- });
118
- }
119
-
120
- if (results && results.length > 0) {
121
- for (var i = 0; i < results.length; i++) {
122
- content += options.fn(results[i]);
123
- }
124
- return content;
125
- }
126
- return options.inverse(this);
127
- };
128
-
129
- /**
130
- * Returns the first item, or first `n` items of an array.
131
- *
132
- * ```handlebars
133
- * {{first "['a', 'b', 'c', 'd', 'e']" 2}}
134
- * <!-- results in: '["a", "b"]' -->
135
- * ```
136
- * @param {Array} `array`
137
- * @param {Number} `n` Number of items to return, starting at `0`.
138
- * @return {Array}
139
- * @api public
140
- */
141
-
142
- helpers.first = function(array, n) {
143
- if (util.isUndefined(array)) return '';
144
- if (!utils.isNumber(n)) {
145
- return array[0];
146
- }
147
- return array.slice(0, n);
148
- };
149
-
150
- /**
151
- * Iterates over each item in an array and exposes the current item
152
- * in the array as context to the inner block. In addition to
153
- * the current array item, the helper exposes the following variables
154
- * to the inner block:
155
- *
156
- * - `index`
157
- * - `total`
158
- * - `isFirst`
159
- * - `isLast`
160
- *
161
- * Also, `@index` is exposed as a private variable, and additional
162
- * private variables may be defined as hash arguments.
163
- *
164
- * ```handlebars
165
- * <!-- accounts = [
166
- * {'name': 'John', 'email': 'john@example.com'},
167
- * {'name': 'Malcolm', 'email': 'malcolm@example.com'},
168
- * {'name': 'David', 'email': 'david@example.com'}
169
- * ] -->
170
- *
171
- * {{#forEach accounts}}
172
- * <a href="mailto:{{ email }}" title="Send an email to {{ name }}">
173
- * {{ name }}
174
- * </a>{{#unless isLast}}, {{/unless}}
175
- * {{/forEach}}
176
- * ```
177
- * @source <http://stackoverflow.com/questions/13861007>
178
- * @param {Array} `array`
179
- * @return {String}
180
- * @block
181
- * @api public
182
- */
183
-
184
- helpers.forEach = function(array, options) {
185
- var data = utils.createFrame(options, options.hash);
186
- var len = array.length;
187
- var buffer = '';
188
- var i = -1;
189
-
190
- while (++i < len) {
191
- var item = array[i];
192
- data.index = i;
193
- item.index = i + 1;
194
- item.total = len;
195
- item.isFirst = i === 0;
196
- item.isLast = i === (len - 1);
197
- buffer += options.fn(item, {data: data});
198
- }
199
- return buffer;
200
- };
201
-
202
- /**
203
- * Block helper that renders the block if an array has the
204
- * given `value`. Optionally specify an inverse block to render
205
- * when the array does not have the given value.
206
- *
207
- * ```handlebars
208
- * <!-- array: ['a', 'b', 'c'] -->
209
- * {{#inArray array "d"}}
210
- * foo
211
- * {{else}}
212
- * bar
213
- * {{/inArray}}
214
- * <!-- results in: 'bar' -->
215
- * ```
216
- * @param {Array} `array`
217
- * @param {any} `value`
218
- * @param {Object} `options`
219
- * @return {String}
220
- * @block
221
- * @api public
222
- */
223
-
224
- helpers.inArray = function(array, value, options) {
225
- return util.value(util.indexOf(array, value) > -1, this, options);
226
- };
227
-
228
- /**
229
- * Returns true if `value` is an es5 array.
230
- *
231
- * ```handlebars
232
- * {{isArray "abc"}}
233
- * <!-- results in: false -->
234
- *
235
- * <!-- array: [1, 2, 3] -->
236
- * {{isArray array}}
237
- * <!-- results in: true -->
238
- * ```
239
- * @param {any} `value` The value to test.
240
- * @return {Boolean}
241
- * @api public
242
- */
243
-
244
- helpers.isArray = function(value) {
245
- return Array.isArray(value);
246
- };
247
-
248
- /**
249
- * Returns the item from `array` at index `idx`.
250
- *
251
- * ```handlebars
252
- * <!-- array: ['a', 'b', 'c'] -->
253
- * {{itemAt array 1}}
254
- * <!-- results in: 'b' -->
255
- * ```
256
- * @param {Array} `array`
257
- * @param {Number} `idx`
258
- * @return {any} `value`
259
- * @block
260
- * @api public
261
- */
262
-
263
- helpers.itemAt = function(array, idx) {
264
- array = util.result(array);
265
- if (Array.isArray(array)) {
266
- idx = utils.isNumber(idx) ? +idx : 0;
267
- if (idx < 0) {
268
- return array[array.length + idx];
269
- }
270
- if (idx < array.length) {
271
- return array[idx];
272
- }
273
- }
274
- };
275
-
276
- /**
277
- * Join all elements of array into a string, optionally using a
278
- * given separator.
279
- *
280
- * ```handlebars
281
- * <!-- array: ['a', 'b', 'c'] -->
282
- * {{join array}}
283
- * <!-- results in: 'a, b, c' -->
284
- *
285
- * {{join array '-'}}
286
- * <!-- results in: 'a-b-c' -->
287
- * ```
288
- * @param {Array} `array`
289
- * @param {String} `separator` The separator to use. Defaults to `, `.
290
- * @return {String}
291
- * @api public
292
- */
293
-
294
- helpers.join = function(array, separator) {
295
- if (typeof array === 'string') return array;
296
- if (!Array.isArray(array)) return '';
297
- separator = util.isString(separator) ? separator : ', ';
298
- return array.join(separator);
299
- };
300
-
301
- /**
302
- * Returns true if the the length of the given `value` is equal
303
- * to the given `length`. Can be used as a block or inline helper.
304
- *
305
- * @param {Array|String} `value`
306
- * @param {Number} `length`
307
- * @param {Object} `options`
308
- * @return {String}
309
- * @block
310
- * @api public
311
- */
312
-
313
- helpers.equalsLength = function(value, length, options) {
314
- if (util.isOptions(length)) {
315
- options = length;
316
- length = 0;
317
- }
318
-
319
- var len = 0;
320
- if (typeof value === 'string' || Array.isArray(value)) {
321
- len = value.length;
322
- }
323
-
324
- return util.value(len === length, this, options);
325
- };
326
-
327
- /**
328
- * Returns the last item, or last `n` items of an array or string.
329
- * Opposite of [first](#first).
330
- *
331
- * ```handlebars
332
- * <!-- var value = ['a', 'b', 'c', 'd', 'e'] -->
333
- *
334
- * {{last value}}
335
- * <!-- results in: ['e'] -->
336
- *
337
- * {{last value 2}}
338
- * <!-- results in: ['d', 'e'] -->
339
- *
340
- * {{last value 3}}
341
- * <!-- results in: ['c', 'd', 'e'] -->
342
- * ```
343
- * @param {Array|String} `value` Array or string.
344
- * @param {Number} `n` Number of items to return from the end of the array.
345
- * @return {Array}
346
- * @api public
347
- */
348
-
349
- helpers.last = function(value, n) {
350
- if (!Array.isArray(value) && typeof value !== 'string') {
351
- return '';
352
- }
353
- if (!utils.isNumber(n)) {
354
- return value[value.length - 1];
355
- }
356
- return value.slice(-Math.abs(n));
357
- };
358
-
359
- /**
360
- * Returns the length of the given string or array.
361
- *
362
- * ```handlebars
363
- * {{length '["a", "b", "c"]'}}
364
- * <!-- results in: 3 -->
365
- *
366
- * <!-- results in: myArray = ['a', 'b', 'c', 'd', 'e']; -->
367
- * {{length myArray}}
368
- * <!-- results in: 5 -->
369
- *
370
- * <!-- results in: myObject = {'a': 'a', 'b': 'b'}; -->
371
- * {{length myObject}}
372
- * <!-- results in: 2 -->
373
- * ```
374
- * @param {Array|Object|String} `value`
375
- * @return {Number} The length of the value.
376
- * @api public
377
- */
378
-
379
- helpers.length = function(value) {
380
- if (util.isObject(value) && !util.isOptions(value)) {
381
- value = Object.keys(value);
382
- }
383
- if (typeof value === 'string' || Array.isArray(value)) {
384
- return value.length;
385
- }
386
- return 0;
387
- };
388
-
389
- /**
390
- * Alias for [equalsLength](#equalsLength)
391
- *
392
- * @api public
393
- */
394
-
395
- helpers.lengthEqual = helpers.equalsLength;
396
-
397
- /**
398
- * Returns a new array, created by calling `function` on each
399
- * element of the given `array`. For example,
400
- *
401
- * ```handlebars
402
- * <!-- array: ['a', 'b', 'c'], and "double" is a
403
- * fictitious function that duplicates letters -->
404
- * {{map array double}}
405
- * <!-- results in: '["aa", "bb", "cc"]' -->
406
- * ```
407
- *
408
- * @param {Array} `array`
409
- * @param {Function} `fn`
410
- * @return {String}
411
- * @api public
412
- */
413
-
414
- helpers.map = function(array, iter) {
415
- if (!Array.isArray(array)) return '';
416
- var len = array.length;
417
- var res = new Array(len);
418
- var i = -1;
419
-
420
- if (typeof iter !== 'function') {
421
- return array;
422
- }
423
-
424
- while (++i < len) {
425
- res[i] = iter(array[i], i, array);
426
- }
427
- return res;
428
- };
429
-
430
- /**
431
- * Map over the given object or array or objects and create an array of values
432
- * from the given `prop`. Dot-notation may be used (as a string) to get
433
- * nested properties.
434
- *
435
- * ```handlebars
436
- * // {{pluck items "data.title"}}
437
- * <!-- results in: '["aa", "bb", "cc"]' -->
438
- * ```
439
- * @param {Array|Object} `collection`
440
- * @param {Function} `prop`
441
- * @return {String}
442
- * @api public
443
- */
444
-
445
- helpers.pluck = function(arr, prop) {
446
- if (util.isUndefined(arr)) return '';
447
- var res = [];
448
- for (var i = 0; i < arr.length; i++) {
449
- var val = utils.get(arr[i], prop);
450
- if (typeof val !== 'undefined') {
451
- res.push(val);
452
- }
453
- }
454
- return res;
455
- };
456
-
457
- /**
458
- * Reverse the elements in an array, or the characters in a string.
459
- *
460
- * ```handlebars
461
- * <!-- value: 'abcd' -->
462
- * {{reverse value}}
463
- * <!-- results in: 'dcba' -->
464
- * <!-- value: ['a', 'b', 'c', 'd'] -->
465
- * {{reverse value}}
466
- * <!-- results in: ['d', 'c', 'b', 'a'] -->
467
- * ```
468
- * @param {Array|String} `value`
469
- * @return {Array|String} Returns the reversed string or array.
470
- * @api public
471
- */
472
-
473
- helpers.reverse = function(val) {
474
- if (Array.isArray(val)) {
475
- val.reverse();
476
- return val;
477
- }
478
- if (val && typeof val === 'string') {
479
- return val.split('').reverse().join('');
480
- }
481
- };
482
-
483
- /**
484
- * Block helper that returns the block if the callback returns true
485
- * for some value in the given array.
486
- *
487
- * ```handlebars
488
- * <!-- array: [1, 'b', 3] -->
489
- * {{#some array isString}}
490
- * Render me if the array has a string.
491
- * {{else}}
492
- * Render me if it doesn't.
493
- * {{/some}}
494
- * <!-- results in: 'Render me if the array has a string.' -->
495
- * ```
496
- * @param {Array} `array`
497
- * @param {Function} `iter` Iteratee
498
- * @param {Options} Handlebars provided options object
499
- * @return {String}
500
- * @block
501
- * @api public
502
- */
503
-
504
- helpers.some = function(array, iter, options) {
505
- if (Array.isArray(array)) {
506
- for (var i = 0; i < array.length; i++) {
507
- if (iter(array[i], i, array)) {
508
- return options.fn(this);
509
- }
510
- }
511
- }
512
- return options.inverse(this);
513
- };
514
-
515
- /**
516
- * Sort the given `array`. If an array of objects is passed,
517
- * you may optionally pass a `key` to sort on as the second
518
- * argument. You may alternatively pass a sorting function as
519
- * the second argument.
520
- *
521
- * ```handlebars
522
- * <!-- array: ['b', 'a', 'c'] -->
523
- * {{sort array}}
524
- * <!-- results in: '["a", "b", "c"]' -->
525
- * ```
526
- *
527
- * @param {Array} `array` the array to sort.
528
- * @param {String|Function} `key` The object key to sort by, or sorting function.
529
- * @api public
530
- */
531
-
532
- helpers.sort = function(array, options) {
533
- if (!Array.isArray(array)) return '';
534
- if (utils.get(options, 'hash.reverse')) {
535
- return array.sort().reverse();
536
- }
537
- return array.sort();
538
- };
539
-
540
- /**
541
- * Sort an `array`. If an array of objects is passed,
542
- * you may optionally pass a `key` to sort on as the second
543
- * argument. You may alternatively pass a sorting function as
544
- * the second argument.
545
- *
546
- * ```handlebars
547
- * <!-- array: [{a: 'zzz'}, {a: 'aaa'}] -->
548
- * {{sortBy array "a"}}
549
- * <!-- results in: '[{"a":"aaa"}, {"a":"zzz"}]' -->
550
- * ```
551
- *
552
- * @param {Array} `array` the array to sort.
553
- * @param {String|Function} `props` One or more properties to sort by, or sorting functions to use.
554
- * @api public
555
- */
556
-
557
- helpers.sortBy = function(array, prop, options) {
558
- if (!Array.isArray(array)) return '';
559
- var args = [].slice.call(arguments);
560
- // remove handlebars options
561
- args.pop();
562
-
563
- if (!util.isString(prop) && typeof prop !== 'function') {
564
- return array.sort();
565
- }
566
- return utils.sortBy.apply(null, args);
567
- };
568
-
569
- /**
570
- * Use the items in the array _after_ the specified index
571
- * as context inside a block. Opposite of [withBefore](#withBefore).
572
- *
573
- * ```handlebars
574
- * <!-- array: ['a', 'b', 'c', 'd', 'e'] -->
575
- * {{#withAfter array 3}}
576
- * {{this}}
577
- * {{/withAfter}}
578
- * <!-- results in: "de" -->
579
- * ```
580
- * @param {Array} `array`
581
- * @param {Number} `idx`
582
- * @param {Object} `options`
583
- * @return {Array}
584
- * @block
585
- * @api public
586
- */
587
-
588
- helpers.withAfter = function(array, idx, options) {
589
- if (!Array.isArray(array)) return '';
590
- array = array.slice(idx);
591
- var result = '';
592
-
593
- for (var i = 0; i < array.length; i++) {
594
- result += options.fn(array[i]);
595
- }
596
- return result;
597
- };
598
-
599
- /**
600
- * Use the items in the array _before_ the specified index
601
- * as context inside a block. Opposite of [withAfter](#withAfter).
602
- *
603
- * ```handlebars
604
- * <!-- array: ['a', 'b', 'c', 'd', 'e'] -->
605
- * {{#withBefore array 3}}
606
- * {{this}}
607
- * {{/withBefore}}
608
- * <!-- results in: 'ab' -->
609
- * ```
610
- * @param {Array} `array`
611
- * @param {Number} `idx`
612
- * @param {Object} `options`
613
- * @return {Array}
614
- * @block
615
- * @api public
616
- */
617
-
618
- helpers.withBefore = function(array, idx, options) {
619
- if (!Array.isArray(array)) return '';
620
- array = array.slice(0, -idx);
621
- var result = '';
622
-
623
- for (var i = 0; i < array.length; i++) {
624
- result += options.fn(array[i]);
625
- }
626
- return result;
627
- };
628
-
629
- /**
630
- * Use the first item in a collection inside a handlebars
631
- * block expression. Opposite of [withLast](#withLast).
632
- *
633
- * ```handlebars
634
- * <!-- array: ['a', 'b', 'c'] -->
635
- * {{#withFirst array}}
636
- * {{this}}
637
- * {{/withFirst}}
638
- * <!-- results in: 'a' -->
639
- * ```
640
- * @param {Array} `array`
641
- * @param {Number} `idx`
642
- * @param {Object} `options`
643
- * @return {String}
644
- * @block
645
- * @api public
646
- */
647
-
648
- helpers.withFirst = function(array, idx, options) {
649
- if (util.isUndefined(array)) return '';
650
- array = util.result(array);
651
-
652
- if (!util.isUndefined(idx)) {
653
- idx = parseFloat(util.result(idx));
654
- }
655
-
656
- if (util.isUndefined(idx)) {
657
- options = idx;
658
- return options.fn(array[0]);
659
- }
660
-
661
- array = array.slice(0, idx);
662
- var result = '';
663
- for (var i = 0; i < array.length; i++) {
664
- result += options.fn(array[i]);
665
- }
666
- return result;
667
- };
668
-
669
- /**
670
- * Block helper that groups array elements by given group `size`.
671
- *
672
- * ```handlebars
673
- * <!-- array: ['a','b','c','d','e','f','g','h'] -->
674
- * {{#withGroup array 4}}
675
- * {{#each this}}
676
- * {{.}}
677
- * {{each}}
678
- * <br>
679
- * {{/withGroup}}
680
- * <!-- results in: -->
681
- * <!-- 'a','b','c','d'<br> -->
682
- * <!-- 'e','f','g','h'<br> -->
683
- * ```
684
- * @param {Array} `array` The array to iterate over
685
- * @param {Number} `size` The desired length of each array "group"
686
- * @param {Object} `options` Handlebars options
687
- * @return {String}
688
- * @block
689
- * @api public
690
- */
691
-
692
- helpers.withGroup = function(array, size, options) {
693
- var result = '';
694
- if (Array.isArray(array) && array.length > 0) {
695
- var subcontext = [];
696
- for (var i = 0; i < array.length; i++) {
697
- if (i > 0 && (i % size) === 0) {
698
- result += options.fn(subcontext);
699
- subcontext = [];
700
- }
701
- subcontext.push(array[i]);
702
- }
703
- result += options.fn(subcontext);
704
- }
705
- return result;
706
- };
707
-
708
- /**
709
- * Use the last item or `n` items in an array as context inside a block.
710
- * Opposite of [withFirst](#withFirst).
711
- *
712
- * ```handlebars
713
- * <!-- array: ['a', 'b', 'c'] -->
714
- * {{#withLast array}}
715
- * {{this}}
716
- * {{/withLast}}
717
- * <!-- results in: 'c' -->
718
- * ```
719
- * @param {Array} `array`
720
- * @param {Number} `idx` The starting index.
721
- * @param {Object} `options`
722
- * @return {String}
723
- * @block
724
- * @api public
725
- */
726
-
727
- helpers.withLast = function(array, idx, options) {
728
- if (util.isUndefined(array)) return '';
729
- array = util.result(array);
730
-
731
- if (!util.isUndefined(idx)) {
732
- idx = parseFloat(util.result(idx));
733
- }
734
-
735
- if (util.isUndefined(idx)) {
736
- options = idx;
737
- return options.fn(array[array.length - 1]);
738
- }
739
-
740
- array = array.slice(-idx);
741
- var len = array.length, i = -1;
742
- var result = '';
743
- while (++i < len) {
744
- result += options.fn(array[i]);
745
- }
746
- return result;
747
- };
748
-
749
- /**
750
- * Block helper that sorts a collection and exposes the sorted
751
- * collection as context inside the block.
752
- *
753
- * ```handlebars
754
- * <!-- array: ['b', 'a', 'c'] -->
755
- * {{#withSort array}}{{this}}{{/withSort}}
756
- * <!-- results in: 'abc' -->
757
- * ```
758
- * @param {Array} `array`
759
- * @param {String} `prop`
760
- * @param {Object} `options` Specify `reverse="true"` to reverse the array.
761
- * @return {String}
762
- * @block
763
- * @api public
764
- */
765
-
766
- helpers.withSort = function(array, prop, options) {
767
- if (util.isUndefined(array)) return '';
768
- var result = '';
769
-
770
- if (util.isUndefined(prop)) {
771
- options = prop;
772
-
773
- array = array.sort();
774
- if (utils.get(options, 'hash.reverse')) {
775
- array = array.reverse();
776
- }
777
-
778
- for (var i = 0, len = array.length; i < len; i++) {
779
- result += options.fn(array[i]);
780
- }
781
- return result;
782
- }
783
-
784
- array.sort(function(a, b) {
785
- a = utils.get(a, prop);
786
- b = utils.get(b, prop);
787
- return a > b ? 1 : (a < b ? -1 : 0);
788
- });
789
-
790
- if (utils.get(options, 'hash.reverse')) {
791
- array = array.reverse();
792
- }
793
-
794
- var alen = array.length, j = -1;
795
- while (++j < alen) {
796
- result += options.fn(array[j]);
797
- }
798
- return result;
799
- };
800
-
801
- /**
802
- * Block helper that return an array with all duplicate
803
- * values removed. Best used along with a [each](#each) helper.
804
- *
805
- * ```handlebars
806
- * <!-- array: ['a', 'a', 'c', 'b', 'e', 'e'] -->
807
- * {{#each (unique array)}}{{.}}{{/each}}
808
- * <!-- results in: 'acbe' -->
809
- * ```
810
- * @param {Array} `array`
811
- * @param {Object} `options`
812
- * @return {Array}
813
- * @api public
814
- */
815
-
816
- helpers.unique = function(array, options) {
817
- if (util.isUndefined(array)) return '';
818
-
819
- return array.filter(function(item, index, arr) {
820
- return arr.indexOf(item) === index;
821
- });
822
- };