=i.length-1?u(t,r,e):u(t,r,e)||n(t,r,e+1)}),t.slice().sort(n)};var M=function(t,r){var e=O.apply(this,arguments);return e.splice(1),e};var P=function(t,r,e,n){var i,o,u,a,c=this&&this.currency?this.currency:{};r=b.exist(r)?r:c.symbol,e=b.exist(e)?e:c.decimalDigits,n=n||c;var l=/(\d{3})(?=\d)/g;if(t=parseFloat(t),!isFinite(t)||!t&&0!==t)return"";r=void 0!==r?r:"$",e=void 0!==e?e:2,i=null!=n.thousandsSeparator?n.thousandsSeparator:",",o=null==n.symbolOnLeft||n.symbolOnLeft,u=null!=n.spaceBetweenAmountAndSymbol&&n.spaceBetweenAmountAndSymbol,a=null!=n.showPlusSign&&n.showPlusSign;var s=function(t,r){return(+(Math.round(+(t+"e"+r))+"e"+-r)).toFixed(r)}(Math.abs(t),e);s=n.decimalSeparator?s.replace(".",n.decimalSeparator):s;var f=e?s.slice(0,-1-e):s,p=f.length%3,y=0=Math.pow(1024,4)?"".concat((t/Math.pow(1024,4)).toFixed(r)," TB"):t>=Math.pow(1024,3)?"".concat((t/Math.pow(1024,3)).toFixed(r)," GB"):t>=Math.pow(1024,2)?"".concat((t/Math.pow(1024,2)).toFixed(r)," MB"):1024<=t?"".concat((t/1024).toFixed(r)," kB"):"".concat(t,1===t?" byte":" bytes")};var N=function(t,r,e){var n=this&&this.pluralize?this.pluralize:{},i="";return!0===(null!=(e=e||n).includeNumber&&e.includeNumber)&&(i+=t+" "),!t&&0!==t||!r||(Array.isArray(r)?i+=r[t-1]||r[r.length-1]:i+=r+(1===t?"":"s")),i};var F=function(t,r){var e=this&&this.ordinal?this.ordinal:{},n="";!0===(null!=(r=r||e).includeNumber&&r.includeNumber)&&(n+=t);var i=t%10,o=t%100;return n+=1==i&&11!=o?"st":2==i&&12!=o?"nd":3==i&&13!=o?"rd":"th"};function k(t,r){return(+(Math.round(+(t+"e"+r))+"e"+-r)).toFixed(r)}Math.sign=function(t){return 0===(t=+t)||isNaN(t)?t:0=n[e].value);e--);return(t=(t/n[e].value).toFixed(r.decimals).replace(/\.0+$|(\.[0-9]*[1-9])0+$/,"$1"))+r.unit.replace("a",n[e].symbol)}(o.float,i);return i.sign+c}var l=function(t,r,e,n){var i=/(\d+)(\d{3})/,o=t.toString().split("."),u=o[0],a=1 -1
65 | }
66 | }
67 |
68 | export default filterBy
--------------------------------------------------------------------------------
/src/array/find.js:
--------------------------------------------------------------------------------
1 | import filterBy from './filterBy'
2 |
3 | /**
4 | * Get first matching element from a filtered array
5 | *
6 | * @param {Array} arr
7 | * @param {String|Number} search
8 | * @returns {mixed}
9 | */
10 | function find(arr, search)
11 | {
12 | var array = filterBy.apply(this, arguments);
13 | array.splice(1);
14 | return array;
15 | }
16 |
17 | export default find;
18 |
--------------------------------------------------------------------------------
/src/array/index.js:
--------------------------------------------------------------------------------
1 | import limitBy from "./limitBy";
2 | import filterBy from "./filterBy";
3 | import orderBy from "./orderBy";
4 | import find from "./find";
5 |
6 | export { limitBy, filterBy, orderBy, find };
7 |
--------------------------------------------------------------------------------
/src/array/limitBy.js:
--------------------------------------------------------------------------------
1 | import util from '../util/index'
2 |
3 | /**
4 | * Limit filter for arrays
5 | *
6 | * @param {Number|Array} arr (If Number, decimal expected)
7 | * @param {Number} n
8 | * @param {Number} offset (Decimal expected)
9 | */
10 |
11 | function limitBy (arr, n, offset) {
12 | arr = (util.isArray(arr)) ? arr : util.convertRangeToArray(arr)
13 |
14 | offset = offset ? parseInt(offset, 10) : 0
15 | n = util.toNumber(n)
16 | return typeof n === 'number'
17 | ? arr.slice(offset, offset + n)
18 | : arr
19 | }
20 |
21 | export default limitBy
--------------------------------------------------------------------------------
/src/array/orderBy.js:
--------------------------------------------------------------------------------
1 | import util from '../util/index'
2 |
3 | /**
4 | * Filter filter for arrays
5 | *
6 | * @param {String|Array|Function} ...sortKeys
7 | * @param {Number} [order]
8 | */
9 |
10 | function orderBy (arr) {
11 | var comparator = null
12 | var sortKeys
13 | arr = util.convertArray(arr)
14 |
15 | // determine order (last argument)
16 | var args = util.toArray(arguments, 1)
17 | var order = args[args.length - 1]
18 | if (typeof order === 'number') {
19 | order = order < 0 ? -1 : 1
20 | args = args.length > 1 ? args.slice(0, -1) : args
21 | } else {
22 | order = 1
23 | }
24 |
25 | // determine sortKeys & comparator
26 | var firstArg = args[0]
27 | if (!firstArg) {
28 | return arr
29 | } else if (typeof firstArg === 'function') {
30 | // custom comparator
31 | comparator = function (a, b) {
32 | return firstArg(a, b) * order
33 | }
34 | } else {
35 | // string keys. flatten first
36 | sortKeys = Array.prototype.concat.apply([], args)
37 | comparator = function (a, b, i) {
38 | i = i || 0
39 | return i >= sortKeys.length - 1
40 | ? baseCompare(a, b, i)
41 | : baseCompare(a, b, i) || comparator(a, b, i + 1)
42 | }
43 | }
44 |
45 | function baseCompare (a, b, sortKeyIndex) {
46 | var sortKey = sortKeys[sortKeyIndex]
47 | if (sortKey) {
48 | if (sortKey !== '$key') {
49 | if (util.isObject(a) && '$value' in a) a = a.$value
50 | if (util.isObject(b) && '$value' in b) b = b.$value
51 | }
52 | a = util.isObject(a) ? util.getPath(a, sortKey) : a
53 | b = util.isObject(b) ? util.getPath(b, sortKey) : b
54 | a = (typeof a === 'string') ? a.toLowerCase() : a
55 | b = (typeof b === 'string') ? b.toLowerCase() : b
56 | }
57 | return a === b ? 0 : a > b ? order : -order
58 | }
59 |
60 | // sort on a copy to avoid mutating original array
61 | return arr.slice().sort(comparator)
62 | }
63 |
64 | export default orderBy
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import util from './util/index'
2 | import * as stringFilters from './string/index'
3 | import * as arrayFilters from './array/index'
4 | import * as otherFilters from './other/index'
5 |
6 | var Vue2Filters = {
7 | install: function(Vue, options) {
8 | util.each(stringFilters, function(value, key) {
9 | Vue.filter(key, value.bind(options))
10 | })
11 |
12 | util.each(otherFilters, function(value, key) {
13 | Vue.filter(key, value.bind(options))
14 | })
15 | },
16 | mixin: {
17 | methods: { ...arrayFilters }
18 | }
19 | }
20 |
21 | export default Vue2Filters;
22 |
23 | if (typeof window !== 'undefined' && window.Vue) {
24 | window.Vue.use(Vue2Filters);
25 | window.Vue2Filters = Vue2Filters;
26 | }
27 |
--------------------------------------------------------------------------------
/src/other/bytes.js:
--------------------------------------------------------------------------------
1 | import util from '../util/index'
2 |
3 | /**
4 | * 1 => '8 byte'
5 | * 8 => '8 bytes'
6 | * 1024 => '1.00 kB'
7 | * 2000000 => '1.90 MB'
8 | * 2000000000 => '1.86 GB'
9 | * 2000000000000 => '1.82 TB'
10 | *
11 | * @param {Number} value
12 | * @param {Number} decimals Decimal places (default: 2)
13 | */
14 | function bytes(value, decimals) {
15 | const globalOptions = (this && this.bytes) ? this.bytes : {}
16 | decimals = util.exist(decimals) ? decimals : globalOptions.decimalDigits
17 | decimals = (typeof decimals !== 'undefined') ? decimals : 2
18 | value = value === null || isNaN(value) ? 0 : value
19 |
20 | if (value >= Math.pow(1024, 4)) {
21 | // TB
22 | return `${(value / Math.pow(1024, 4)).toFixed(decimals)} TB`
23 | } else if (value >= Math.pow(1024, 3)) {
24 | // GB
25 | return `${(value / Math.pow(1024, 3)).toFixed(decimals)} GB`
26 | } else if (value >= Math.pow(1024, 2)) {
27 | // MB
28 | return `${(value / Math.pow(1024, 2)).toFixed(decimals)} MB`
29 | } else if (value >= 1024) {
30 | // kb
31 | return `${(value / 1024).toFixed(decimals)} kB`
32 | }
33 | // byte
34 | return value === 1 ? `${value} byte` : `${value} bytes`
35 | }
36 |
37 | export default bytes
--------------------------------------------------------------------------------
/src/other/currency.js:
--------------------------------------------------------------------------------
1 | import util from '../util/index'
2 |
3 | /**
4 | *
5 | * 12345 => $12,345.00
6 | *
7 | * @param {String} symbol
8 | * @param {Number} decimals Decimal places
9 | * @param {Object} options
10 | */
11 |
12 | function currency (value, symbol, decimals, options) {
13 | const globalOptions = (this && this.currency) ? this.currency : {}
14 | symbol = util.exist(symbol) ? symbol : globalOptions.symbol
15 | decimals = util.exist(decimals) ? decimals : globalOptions.decimalDigits
16 | options = options || globalOptions
17 | var thousandsSeparator, symbolOnLeft, spaceBetweenAmountAndSymbol, showPlusSign
18 | var digitsRE = /(\d{3})(?=\d)/g
19 | value = parseFloat(value)
20 | if (!isFinite(value) || (!value && value !== 0)) return ''
21 | symbol = (typeof symbol !== 'undefined') ? symbol : '$'
22 | decimals = (typeof decimals !== 'undefined') ? decimals : 2
23 | thousandsSeparator = options.thousandsSeparator != null ? options.thousandsSeparator : ','
24 | symbolOnLeft = options.symbolOnLeft != null ? options.symbolOnLeft : true
25 | spaceBetweenAmountAndSymbol = options.spaceBetweenAmountAndSymbol != null ? options.spaceBetweenAmountAndSymbol : false
26 | showPlusSign = options.showPlusSign != null ? options.showPlusSign : false
27 | var number = Math.abs(value)
28 | var stringified = toFixed(number, decimals)
29 | stringified = options.decimalSeparator
30 | ? stringified.replace('.', options.decimalSeparator)
31 | : stringified
32 | var _int = decimals
33 | ? stringified.slice(0, -1 - decimals)
34 | : stringified
35 | var i = _int.length % 3
36 | var head = i > 0
37 | ? (_int.slice(0, i) + (_int.length > 3 ? thousandsSeparator : ''))
38 | : ''
39 | var _float = decimals
40 | ? stringified.slice(-1 - decimals)
41 | : ''
42 | symbol = spaceBetweenAmountAndSymbol
43 | ? (symbolOnLeft ? symbol + ' ' : ' ' + symbol)
44 | : symbol
45 | symbol = symbolOnLeft
46 | ? symbol + head +
47 | _int.slice(i).replace(digitsRE, '$1' + thousandsSeparator) + _float
48 | : head +
49 | _int.slice(i).replace(digitsRE, '$1' + thousandsSeparator) + _float + symbol
50 | var sign = value < 0 ? '-' : ''
51 | var plusSign = (value > 0 && showPlusSign) ? '+' : ''
52 | return plusSign + sign + symbol
53 | }
54 |
55 | function toFixed(num, precision) {
56 | return (+(Math.round(+(num + 'e' + precision)) + 'e' + -precision)).toFixed(precision);
57 | }
58 |
59 | export default currency
--------------------------------------------------------------------------------
/src/other/index.js:
--------------------------------------------------------------------------------
1 | import currency from './currency'
2 | import bytes from './bytes'
3 | import pluralize from './pluralize'
4 | import ordinal from './ordinal'
5 | import number from './number'
6 | import percent from './percent'
7 |
8 | export {
9 | currency,
10 | bytes,
11 | pluralize,
12 | ordinal,
13 | number,
14 | percent
15 | }
16 |
--------------------------------------------------------------------------------
/src/other/number.js:
--------------------------------------------------------------------------------
1 | import util from '../util/index'
2 |
3 | /**
4 | * 123456 => '123,456'
5 | *
6 | * @params {Object} options
7 | *
8 | */
9 |
10 | function number(value, format, options) {
11 | const globalOptions = this && this.number ? this.number : {}
12 | format = util.exist(format) ? format : globalOptions.format
13 | options = options || globalOptions
14 | const config = parseFormat(format)
15 | const number = parseNumber(value)
16 | const thousandsSeparator = options.thousandsSeparator != null ? options.thousandsSeparator : ','
17 | const decimalSeparator = options.decimalSeparator != null ? options.decimalSeparator : '.'
18 |
19 | config.sign = config.sign || number.sign
20 |
21 | if (config.unit) {
22 | const numberWithUnit = addUnit(number.float, config)
23 | return config.sign + numberWithUnit
24 | }
25 |
26 | const rounded = toFixed(number.float, config.decimals)
27 |
28 | const output = addSeparators(rounded, config.base, thousandsSeparator, decimalSeparator)
29 |
30 | return config.sign + output
31 | }
32 |
33 | Math.sign = function (x) {
34 | x = +x
35 | if (x === 0 || isNaN(x)) {
36 | return x
37 | }
38 | return x > 0 ? 1 : -1
39 | }
40 |
41 | function parseNumber(num) {
42 | return {
43 | float: Math.abs(parseFloat(num)),
44 | int: Math.abs(parseInt(num)),
45 | sign: Math.sign(num) < 0 ? '-' : ''
46 | }
47 | }
48 |
49 | function parseFormat(string = '0') {
50 | const regex = /([\+\-])?([0-9\,]+)?([\.0-9]+)?([a\s]+)?/
51 | const matches = string ? string.match(regex) : ['', '', '', '', '']
52 | const float = matches[3]
53 | const decimals = float ? float.match(/0/g).length : 0
54 |
55 | return {
56 | sign: matches[1] || '',
57 | base: matches[2] || '',
58 | decimals,
59 | unit: matches[4] || ''
60 | }
61 | }
62 |
63 | function addUnit(num, config) {
64 | const rx = /\.0+$|(\.[0-9]*[1-9])0+$/
65 | const si = [
66 | { value: 1, symbol: '' },
67 | { value: 1e3, symbol: 'K' },
68 | { value: 1e6, symbol: 'M' },
69 | { value: 1e9, symbol: 'B' },
70 | { value: 1e12, symbol: 'T' }
71 | ]
72 |
73 | let i
74 | for (i = si.length - 1; i > 0; i--) {
75 | if (num >= si[i].value) {
76 | break
77 | }
78 | }
79 |
80 | num = (num / si[i].value).toFixed(config.decimals).replace(rx, '$1')
81 |
82 | return num + config.unit.replace('a', si[i].symbol)
83 | }
84 |
85 | function addSeparators(num, base, thousandsSeparator, decimalSeparator) {
86 | const regex = /(\d+)(\d{3})/
87 | const string = num.toString()
88 | const x = string.split('.')
89 | let x1 = x[0]
90 | let x2 = x.length > 1 ? decimalSeparator + x[1] : ''
91 |
92 | switch (base) {
93 | case '':
94 | x1 = ''
95 | break
96 | case '0,0':
97 | while (regex.test(x1)) {
98 | x1 = x1.replace(regex, '$1' + thousandsSeparator + '$2')
99 | }
100 | break
101 | }
102 |
103 | return x1 + x2
104 | }
105 |
106 | function getFraction(num, decimals, separator) {
107 | const fraction = toFixed(num, decimals).toString().split('.')[1]
108 |
109 | return fraction ? separator + fraction : ''
110 | }
111 |
112 | function toFixed(num, precision) {
113 | return (+(Math.round(+(num + 'e' + precision)) + 'e' + -precision)).toFixed(precision)
114 | }
115 |
116 | export default number
117 |
--------------------------------------------------------------------------------
/src/other/ordinal.js:
--------------------------------------------------------------------------------
1 | import util from '../util/index'
2 |
3 | /**
4 | * 42 => 'nd'
5 | *
6 | * @params {Object} options
7 | *
8 | */
9 |
10 | function ordinal (value, options) {
11 | const globalOptions = (this && this.ordinal) ? this.ordinal : {}
12 | options = options || globalOptions
13 | var output = ''
14 | var includeNumber = options.includeNumber != null ? options.includeNumber : false
15 | if(includeNumber === true) output += value
16 | var j = value % 10,
17 | k = value % 100
18 |
19 | if (j == 1 && k != 11) output += 'st'
20 | else if (j == 2 && k != 12) output += 'nd'
21 | else if (j == 3 && k != 13) output += 'rd'
22 | else output += 'th'
23 |
24 | return output
25 | }
26 |
27 | export default ordinal
--------------------------------------------------------------------------------
/src/other/percent.js:
--------------------------------------------------------------------------------
1 | import util from '../util/index'
2 |
3 | /**
4 | * 1.2 => '120%'
5 | * -0.2 => '-20%'
6 | * 100 => '10000%'
7 | * 1 => '100%'
8 | * 0.97 => '97%'
9 | *
10 | * @param {Number} value
11 | * @param {Number} decimals Decimal places (default: 2)
12 | * @param {Number} multiplier (default: 100)
13 | * @params {Object} options
14 | */
15 | function percent(value, decimals, multiplier, options) {
16 | const globalOptions = this && this.percent ? this.percent : {}
17 | options = options || globalOptions
18 | multiplier = util.exist(multiplier) ? multiplier : globalOptions.multiplier
19 | multiplier = typeof multiplier !== 'undefined' ? multiplier : 100
20 | decimals = util.exist(decimals) ? decimals : globalOptions.decimalDigits
21 | decimals = typeof decimals !== 'undefined' ? decimals : 0
22 |
23 | const decimalSeparator = options.decimalSeparator != null ? options.decimalSeparator : '.'
24 |
25 | value = value === null || isNaN(value) ? 0 : value
26 |
27 | return `${(value * multiplier).toFixed(decimals).replace('.', decimalSeparator)}%`
28 | }
29 |
30 | export default percent
31 |
--------------------------------------------------------------------------------
/src/other/pluralize.js:
--------------------------------------------------------------------------------
1 | import util from '../util/index'
2 |
3 | /**
4 | * 'item' => 'items'
5 | *
6 | * @param {String|Array} word
7 | * @param {Object} options
8 | *
9 | */
10 |
11 | function pluralize (value, word, options) {
12 | const globalOptions = (this && this.pluralize) ? this.pluralize : {}
13 | options = options || globalOptions
14 | var output = ''
15 | var includeNumber = options.includeNumber != null ? options.includeNumber : false
16 | if(includeNumber === true) output += value + ' '
17 | if(!value && value !== 0 || !word) return output
18 | if(Array.isArray(word)) {
19 | output += word[value - 1] || word[word.length - 1]
20 | } else {
21 | output += word + (value === 1 ? '' : 's')
22 | }
23 |
24 | return output
25 | }
26 |
27 | export default pluralize
--------------------------------------------------------------------------------
/src/string/capitalize.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Converts a string into Capitalize
3 | *
4 | * 'abc' => 'Abc'
5 | *
6 | * @param {Object} options
7 | */
8 |
9 | function capitalize (value, options) {
10 | const globalOptions = (this && this.capitalize) ? this.capitalize : {}
11 | options = options || globalOptions
12 | var onlyFirstLetter = options.onlyFirstLetter != null ? options.onlyFirstLetter : false
13 | if (!value && value !== 0) return ''
14 | if(onlyFirstLetter === true) {
15 | return value.toString().charAt(0).toUpperCase() + value.toString().slice(1)
16 | } else {
17 | value = value.toString().toLowerCase().split(' ')
18 | return value.map(function(item) {
19 | return item.charAt(0).toUpperCase() + item.slice(1)
20 | }).join(' ')
21 | }
22 | }
23 |
24 | export default capitalize
25 |
--------------------------------------------------------------------------------
/src/string/index.js:
--------------------------------------------------------------------------------
1 | import capitalize from "./capitalize";
2 | import uppercase from "./uppercase";
3 | import lowercase from "./lowercase";
4 | import placeholder from "./placeholder";
5 | import truncate from "./truncate";
6 | import repeat from "./repeat";
7 | import wrap from "./wrap";
8 | import reverse from "./reverse";
9 |
10 | export {
11 | capitalize,
12 | uppercase,
13 | lowercase,
14 | placeholder,
15 | truncate,
16 | repeat,
17 | wrap,
18 | reverse,
19 | };
20 |
--------------------------------------------------------------------------------
/src/string/lowercase.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Converts a string to lowercase
3 | *
4 | * 'AbC' => 'abc'
5 | */
6 |
7 | function lowercase (value) {
8 | return (value || value === 0)
9 | ? value.toString().toLowerCase()
10 | : ''
11 | }
12 |
13 | export default lowercase
--------------------------------------------------------------------------------
/src/string/placeholder.js:
--------------------------------------------------------------------------------
1 | /**
2 | * If the value is missing outputs the placeholder text
3 | *
4 | * '' => {placeholder}
5 | * 'foo' => 'foo'
6 | */
7 |
8 | function placeholder (input, property) {
9 | return ( input === undefined || input === '' || input === null ) ? property : input;
10 | }
11 |
12 | export default placeholder
13 |
--------------------------------------------------------------------------------
/src/string/repeat.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Repeats a given value an x amount of times
3 | *
4 | * @author Bastiaan Jansen
5 | * @param {string | number} value to repeat
6 | * @param {number} amount
7 | * @returns repeated string
8 | */
9 | const repeat = (value, amount = 1) => {
10 | return amount ? value.toString().repeat(amount) : '';
11 | };
12 |
13 | export default repeat;
14 |
--------------------------------------------------------------------------------
/src/string/reverse.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Reverses a string
3 | *
4 | * @author Bastiaan Jansen
5 | * @param {string} value
6 | * @returns reversed string
7 | */
8 | const reverse = (value) => {
9 | return Array.from(value).reverse().join("");
10 | };
11 |
12 | export default reverse;
13 |
--------------------------------------------------------------------------------
/src/string/truncate.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Truncate at the given || default length
3 | *
4 | * 'lorem ipsum dolor' => 'lorem ipsum dol...'
5 | */
6 |
7 | function truncate (value, length) {
8 | length = length || 15
9 | if( !value || typeof value !== 'string' ) return ''
10 | if( value.length <= length) return value
11 | return value.substring(0, length) + '...'
12 | }
13 |
14 | export default truncate
15 |
--------------------------------------------------------------------------------
/src/string/uppercase.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Converts a string to UPPERCASE
3 | *
4 | * 'abc' => 'ABC'
5 | */
6 |
7 | function uppercase (value) {
8 | return (value || value === 0)
9 | ? value.toString().toUpperCase()
10 | : ''
11 | }
12 |
13 | export default uppercase
--------------------------------------------------------------------------------
/src/string/wrap.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Wraps a string or number with a string
3 | *
4 | * @author Bastiaan Jansen
5 | * @param {string | number} value to wrap
6 | * @param {string | number} wrap wrap string
7 | * @returns wrapped string
8 | */
9 | const wrap = (value, wrap) => {
10 | return [wrap, value, wrap].join("");
11 | };
12 |
13 | export default wrap;
14 |
--------------------------------------------------------------------------------
/src/util/index.js:
--------------------------------------------------------------------------------
1 | var
2 | ArrayProto = Array.prototype,
3 | ObjProto = Object.prototype;
4 |
5 | var
6 | slice = ArrayProto.slice,
7 | toString = ObjProto.toString;
8 |
9 | var util = {};
10 |
11 | util.isArray = function(obj) {
12 | return Array.isArray(obj);
13 | };
14 |
15 | var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
16 | util.isArrayLike = function(obj) {
17 | if(typeof obj !== 'object' || !obj){
18 | return false;
19 | }
20 | var length = obj.length;
21 | return typeof length === 'number'
22 | && length % 1 === 0 && length >= 0 && length <= MAX_ARRAY_INDEX;
23 | };
24 |
25 | util.isObject = function(obj) {
26 | var type = typeof obj;
27 | return type === 'function' || type === 'object' && !!obj;
28 | };
29 |
30 |
31 | util.each = function(obj, callback) {
32 | var i,
33 | len;
34 | if (util.isArray(obj)) {
35 | for (i = 0, len = obj.length; i < len; i++) {
36 | if (callback(obj[i], i, obj) === false) {
37 | break;
38 | }
39 | }
40 | } else {
41 | for (i in obj) {
42 | if (callback(obj[i], i, obj) === false) {
43 | break;
44 | }
45 | }
46 | }
47 | return obj;
48 | };
49 |
50 | util.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
51 | util['is' + name] = function(obj) {
52 | return toString.call(obj) === '[object ' + name + ']';
53 | };
54 | });
55 |
56 | util.toArray = function(list, start) {
57 | start = start || 0
58 | var i = list.length - start
59 | var ret = new Array(i)
60 | while (i--) {
61 | ret[i] = list[i + start]
62 | }
63 | return ret
64 | }
65 |
66 | util.toNumber = function(value) {
67 | if (typeof value !== 'string') {
68 | return value
69 | } else {
70 | var parsed = Number(value)
71 | return isNaN(parsed)
72 | ? value
73 | : parsed
74 | }
75 | };
76 |
77 | util.convertRangeToArray = function (range) {
78 | return [...Array(range + 1).keys()].slice(1)
79 | };
80 |
81 | util.convertArray = function (value) {
82 | if (util.isArray(value)) {
83 | return value
84 | } else if (util.isPlainObject(value)) {
85 | // convert plain object to array.
86 | var keys = Object.keys(value)
87 | var i = keys.length
88 | var res = new Array(i)
89 | var key
90 | while (i--) {
91 | key = keys[i]
92 | res[i] = {
93 | $key: key,
94 | $value: value[key]
95 | }
96 | }
97 | return res
98 | } else {
99 | return value || []
100 | }
101 | }
102 |
103 | function multiIndex(obj,is) { // obj,['1','2','3'] -> ((obj['1'])['2'])['3']
104 | return is.length ? multiIndex(obj[is[0]],is.slice(1)) : obj
105 | }
106 |
107 | util.getPath = function(obj,is) { // obj,'1.2.3' -> multiIndex(obj,['1','2','3'])
108 | return multiIndex(obj,is.split('.'))
109 | }
110 |
111 | /**
112 | * Strict object type check. Only returns true
113 | * for plain JavaScript objects.
114 | *
115 | * @param {*} obj
116 | * @return {Boolean}
117 | */
118 |
119 | var toString = Object.prototype.toString
120 | var OBJECT_STRING = '[object Object]'
121 | util.isPlainObject = function (obj) {
122 | return toString.call(obj) === OBJECT_STRING
123 | }
124 |
125 | util.exist = function(value) {
126 | return value !== null && typeof value !== 'undefined'
127 | }
128 |
129 | export default util;
--------------------------------------------------------------------------------
/test/filters.spec.js:
--------------------------------------------------------------------------------
1 | var stringFilters = require('../src/string/index')
2 | var arrayFilters = require('../src/array/index')
3 | var otherFilters = require('../src/other/index')
4 |
5 | describe('Filters', function () {
6 | it('number', function () {
7 | var filter = otherFilters.number
8 | expect(filter(123456)).toBe('123456')
9 | expect(filter('123456')).toBe('123456')
10 | expect(filter(-123456)).toBe('-123456')
11 | expect(filter(123456, '+0,0')).toBe('+123,456')
12 | expect(filter(123456, '-0,0')).toBe('-123,456')
13 | expect(filter(-123456, '+0,0')).toBe('+123,456')
14 | expect(filter(123456, '+0')).toBe('+123456')
15 | expect(filter(123456, '-0')).toBe('-123456')
16 | expect(filter(12345.67, '0,0')).toBe('12,346')
17 | expect(filter(12345.67, '0.0000')).toBe('12345.6700')
18 | expect(filter(12345.67, '0,0.0000')).toBe('12,345.6700')
19 | expect(filter(12345.6789, '0,0.0000')).toBe('12,345.6789')
20 | expect(filter(12345, '0,0.0')).toBe('12,345.0')
21 | expect(filter(-12345, '0,0.0')).toBe('-12,345.0')
22 | expect(filter(12345.6789, '0.000')).toBe('12345.679')
23 | expect(filter(1024, '0a')).toBe('1K')
24 | expect(filter(1224, '0.0a')).toBe('1.2K')
25 | expect(filter(10245, '0 a')).toBe('10 K')
26 | expect(filter(10245678, '0.0a')).toBe('10.2M')
27 | expect(filter(-10245678, '.0a')).toBe('-10.2M')
28 | expect(filter(10737418240, '0.0a')).toBe('10.7B')
29 | expect(filter(-10737418240, '.0a')).toBe('-10.7B')
30 | expect(filter(2317370418240, '0.00a')).toBe('2.32T')
31 | expect(filter(-2317370418240, '.00a')).toBe('-2.32T')
32 | expect(filter(-123456.093, '0.00 a')).toBe('-123.46 K')
33 | expect(filter(-0.23, '.00')).toBe('-.23')
34 | // options
35 | expect(filter(123456, '0,0', { thousandsSeparator: '|' })).toBe('123|456')
36 | expect(filter(123456.789, '0.00', { decimalSeparator: '|' })).toBe('123456|79')
37 | expect(filter(10000.998, '0,0.00', { thousandsSeparator: '.', decimalSeparator: '|' })).toBe(
38 | '10.001|00'
39 | )
40 | })
41 |
42 | it('number with global options', function () {
43 | var filter = otherFilters.number.bind({
44 | number: {
45 | thousandsSeparator: '@',
46 | decimalSeparator: '|',
47 | format: '0,0.000'
48 | }
49 | })
50 |
51 | expect(filter(123456.789)).toBe('123@456|789')
52 | expect(filter(123456.789, '0,0.0')).toBe('123@456|8')
53 | })
54 |
55 | it('capitalize', function () {
56 | var filter = stringFilters.capitalize
57 | var res = filter('fsefsfsef zxcvxzsaxz')
58 | var words = res.split(' ')
59 | expect(words[0].charAt(0)).toBe('F')
60 | expect(words[0].slice(1)).toBe('sefsfsef')
61 | expect(words[1].charAt(0)).toBe('Z')
62 | expect(words[1].slice(1)).toBe('xcvxzsaxz')
63 | assertNumberAndFalsy(filter)
64 | })
65 |
66 | it('capitalize only first letter of sentence', function () {
67 | var filter = stringFilters.capitalize
68 | var res = filter('fsefsfsef zxcvxzsaxz', { onlyFirstLetter: true })
69 | var words = res.split(' ')
70 | expect(words[0].charAt(0)).toBe('F')
71 | expect(words[0].slice(1)).toBe('sefsfsef')
72 | expect(words[1].charAt(0)).toBe('z')
73 | expect(words[1].slice(1)).toBe('xcvxzsaxz')
74 | assertNumberAndFalsy(filter)
75 | })
76 |
77 | it('capitalize with global options', function () {
78 | var filter = stringFilters.capitalize.bind({ capitalize: { onlyFirstLetter: true } })
79 | var res = filter('fsefsfsef zxcvxzsaxz')
80 | var words = res.split(' ')
81 | expect(words[0].charAt(0)).toBe('F')
82 | expect(words[0].slice(1)).toBe('sefsfsef')
83 | expect(words[1].charAt(0)).toBe('z')
84 | expect(words[1].slice(1)).toBe('xcvxzsaxz')
85 | assertNumberAndFalsy(filter)
86 | })
87 |
88 | it('uppercase', function () {
89 | var filter = stringFilters.uppercase
90 | expect(filter('fsefef')).toBe('FSEFEF')
91 | assertNumberAndFalsy(filter)
92 | })
93 |
94 | it('lowercase', function () {
95 | var filter = stringFilters.lowercase
96 | expect(filter('AWEsoME')).toBe('awesome')
97 | assertNumberAndFalsy(filter)
98 | })
99 |
100 | it('placeholder', function () {
101 | var filter = stringFilters.placeholder
102 | expect(filter('sometext', 'placeholder text')).toBe('sometext')
103 | expect(filter(1234, 'placeholder text')).toBe(1234)
104 | expect(filter('', 'placeholder text')).toBe('placeholder text')
105 | expect(filter(undefined, 'placeholder text')).toBe('placeholder text')
106 | expect(filter(null, 'placeholder text')).toBe('placeholder text')
107 | })
108 |
109 | it('truncate', function () {
110 | var filter = stringFilters.truncate
111 | expect(filter('lorem ipsum dolor')).toBe('lorem ipsum dol...')
112 | expect(filter('lorem ipsum dolor', 5)).toBe('lorem...')
113 | expect(filter('lorem ipsum dolor', 20)).toBe('lorem ipsum dolor')
114 | expect(filter(1234, 5)).toBe('')
115 | expect(filter('', 5)).toBe('')
116 | expect(filter(undefined, 5)).toBe('')
117 | expect(filter(null, 5)).toBe('')
118 | })
119 |
120 | it('currency', function () {
121 | var filter = otherFilters.currency
122 | expect(filter(1234)).toBe('$1,234.00')
123 | expect(filter(1234.45)).toBe('$1,234.45')
124 | expect(filter(123443434.4343434)).toBe('$123,443,434.43')
125 | expect(filter(0.99)).toBe('$0.99')
126 | expect(filter(0.99999)).toBe('$1.00')
127 | expect(filter(0.76)).toBe('$0.76')
128 | // sign arg
129 | expect(filter(2134, '@')).toBe('@2,134.00')
130 | // no symbol
131 | expect(filter(2134, '')).toBe('2,134.00')
132 | // decimal places
133 | expect(filter(1234, '$', 0)).toBe('$1,234')
134 | // if decimal places are present, currency is required
135 | expect(filter(1234, '', 2)).toBe('1,234.00')
136 | expect(filter(123.4, '$', 3)).toBe('$123.400')
137 | expect(filter(-12345, 'VND', 0)).toBe('-VND12,345')
138 | // falsy, infinity and 0
139 | expect(filter(0)).toBe('$0.00')
140 | expect(filter(false)).toBe('')
141 | expect(filter(null)).toBe('')
142 | expect(filter(undefined)).toBe('')
143 | expect(filter(Infinity)).toBe('')
144 | // negative numbers
145 | expect(filter(-50)).toBe('-$50.00')
146 | expect(filter(-150.43)).toBe('-$150.43')
147 | expect(filter(-1500.4343434)).toBe('-$1,500.43')
148 | // options
149 | expect(filter(1234, '@', 0, { thousandsSeparator: ',' })).toBe('@1,234')
150 | expect(filter(1234, '', 2, { decimalSeparator: '|' })).toBe('1,234|00')
151 | expect(filter(1234, '$', 2, { symbolOnLeft: false })).toBe('1,234.00$')
152 | expect(filter(1234, '$', 0, { spaceBetweenAmountAndSymbol: true })).toBe('$ 1,234')
153 | expect(filter(1234, '$', 0, { symbolOnLeft: false, spaceBetweenAmountAndSymbol: true })).toBe(
154 | '1,234 $'
155 | )
156 | expect(filter(-12345, 'VND', 0, { symbolOnLeft: true })).toBe('-VND12,345')
157 | expect(filter(12345, 'VND', 0, { showPlusSign: true })).toBe('+VND12,345')
158 | expect(filter(-12345, 'VND', 0, { showPlusSign: true })).toBe('-VND12,345')
159 | expect(filter(0, 'VND', 0, { showPlusSign: true })).toBe('VND0')
160 | // round up
161 | expect(filter(4514.275)).toBe('$4,514.28')
162 | expect(filter(9446.975)).toBe('$9,446.98')
163 | })
164 |
165 | it('currency with global options', function () {
166 | var filter = otherFilters.currency.bind({
167 | currency: {
168 | symbol: '@',
169 | decimalDigits: 3,
170 | thousandsSeparator: ',',
171 | decimalSeparator: '|',
172 | symbolOnLeft: false,
173 | spaceBetweenAmountAndSymbol: true,
174 | showPlusSign: true
175 | }
176 | })
177 |
178 | expect(filter(1234)).toBe('+1,234|000 @')
179 | })
180 |
181 | it('pluralize', function () {
182 | var filter = otherFilters.pluralize
183 | // single word
184 | var word = 'item'
185 | expect(filter(0, word)).toBe('items')
186 | expect(filter(1, word)).toBe('item')
187 | expect(filter(2, word)).toBe('items')
188 | expect(filter(21, word)).toBe('items')
189 |
190 | // multi words
191 | expect(filter(0, ['fry', 'fries'])).toBe('fries')
192 | expect(filter(1, ['fry', 'fries'])).toBe('fry')
193 | expect(filter(2, ['fry', 'fries'])).toBe('fries')
194 |
195 | expect(filter(0, ['first', 'second', 'third', 'nth'])).toBe('nth')
196 | expect(filter(1, ['first', 'second', 'third', 'nth'])).toBe('first')
197 | expect(filter(2, ['first', 'second', 'third', 'nth'])).toBe('second')
198 | expect(filter(3, ['first', 'second', 'third', 'nth'])).toBe('third')
199 | expect(filter(4, ['first', 'second', 'third', 'nth'])).toBe('nth')
200 | expect(filter(50, ['first', 'second', 'third', 'nth'])).toBe('nth')
201 |
202 | // include number
203 | expect(filter(1, word, { includeNumber: false })).toBe('item')
204 | expect(filter(1, word, { includeNumber: true })).toBe('1 item')
205 | expect(filter(1, ['fry', 'fries'], { includeNumber: true })).toBe('1 fry')
206 | })
207 |
208 | it('pluralize with global options', function () {
209 | var filter = otherFilters.pluralize.bind({
210 | pluralize: { includeNumber: false }
211 | })
212 | var word = 'item'
213 |
214 | expect(filter(1, word)).toBe('item')
215 | })
216 |
217 | it('ordinal', function () {
218 | var filter = otherFilters.ordinal
219 |
220 | expect(filter(0)).toBe('th')
221 | expect(filter(1)).toBe('st')
222 | expect(filter(2)).toBe('nd')
223 | expect(filter(3)).toBe('rd')
224 | expect(filter(4)).toBe('th')
225 |
226 | expect(filter(230)).toBe('th')
227 | expect(filter(231)).toBe('st')
228 | expect(filter(232)).toBe('nd')
229 | expect(filter(233)).toBe('rd')
230 | expect(filter(234)).toBe('th')
231 |
232 | expect(filter(4, { includeNumber: false })).toBe('th')
233 | expect(filter(0, { includeNumber: true })).toBe('0th')
234 | expect(filter(1, { includeNumber: true })).toBe('1st')
235 | })
236 |
237 | it('ordinal with global options', function () {
238 | var filter = otherFilters.ordinal.bind({
239 | ordinal: { includeNumber: false }
240 | })
241 |
242 | expect(filter(4)).toBe('th')
243 | })
244 |
245 | it('bytes', function () {
246 | var filter = otherFilters.bytes
247 |
248 | expect(filter(1)).toBe('1 byte')
249 | expect(filter(12)).toBe('12 bytes')
250 | expect(filter(2000, 0)).toBe('2 kB')
251 | expect(filter(2000, 1)).toBe('2.0 kB')
252 | expect(filter(2000)).toBe('1.95 kB')
253 | expect(filter(2000, 3)).toBe('1.953 kB')
254 | expect(filter(2000, 4)).toBe('1.9531 kB')
255 | expect(filter(2000000)).toBe('1.91 MB')
256 | expect(filter(2000000, 4)).toBe('1.9073 MB')
257 | expect(filter(2000000000)).toBe('1.86 GB')
258 | expect(filter(2000000000, 4)).toBe('1.8626 GB')
259 | expect(filter(2000000000000)).toBe('1.82 TB')
260 | expect(filter(2000000000000, 4)).toBe('1.8190 TB')
261 |
262 | // edge cases
263 | expect(filter(undefined)).toBe('0 bytes')
264 | expect(filter(null)).toBe('0 bytes')
265 | expect(filter('a random string')).toBe('0 bytes')
266 | })
267 |
268 | it('bytes with global options', function () {
269 | var filter = otherFilters.bytes.bind({
270 | bytes: { decimalDigits: 1 }
271 | })
272 |
273 | expect(filter(2000)).toBe('2.0 kB')
274 | })
275 |
276 | it('percent', function () {
277 | var filter = otherFilters.percent
278 |
279 | expect(filter(1.2)).toBe('120%')
280 | expect(filter(-0.2)).toBe('-20%')
281 | expect(filter(12)).toBe('1200%')
282 | expect(filter(100, 0)).toBe('10000%')
283 | expect(filter(1, 1)).toBe('100.0%')
284 | expect(filter(0.974878234, 3)).toBe('97.488%')
285 | expect(filter(0.0003, 1)).toBe('0.0%')
286 |
287 | // different multiplier
288 | expect(filter(0.1, 0, 150)).toBe('15%')
289 | expect(filter(0.2, 1, 150)).toBe('30.0%')
290 | expect(filter(1.2, 0, 300)).toBe('360%')
291 | expect(filter(0.974878234, 3, 150)).toBe('146.232%')
292 |
293 | // different decimalSeparator
294 | expect(filter(0.02, 2, 100, { decimalSeparator: '|' })).toBe('2|00%')
295 | expect(filter(0.974878234, 3, 150, { decimalSeparator: '|' })).toBe(
296 | '146|232%'
297 | )
298 | expect(filter(0.2, 0, 100, { decimalSeparator: '|' })).toBe('20%')
299 |
300 | // edge cases
301 | expect(filter(undefined)).toBe('0%')
302 | expect(filter(null)).toBe('0%')
303 | expect(filter('a random string')).toBe('0%')
304 | })
305 |
306 | it('percent with global options', function () {
307 | var filter = otherFilters.percent.bind({
308 | percent: { decimalDigits: 1, multiplier: 150, decimalSeparator: '|' },
309 | })
310 |
311 | expect(filter(100)).toBe('15000|0%')
312 | })
313 |
314 | it('limitByArray', function () {
315 | var filter = arrayFilters.limitBy
316 | var arr = [1, 2, 3]
317 | var res = filter(arr, false)
318 | expect(res).toBe(arr)
319 | res = filter(arr, 1)
320 | assertArray(res, [1])
321 | res = filter(arr, 10)
322 | assertArray(res, [1, 2, 3])
323 | res = filter(arr, -1)
324 | assertArray(res, [1, 2])
325 | // with offsets, note offsets are 0 bound (as expected)
326 | res = filter(arr, 1, 1)
327 | assertArray(res, [2])
328 | res = filter(arr, 2, 1)
329 | assertArray(res, [2, 3])
330 | res = filter(arr, 1, 2)
331 | assertArray(res, [3])
332 | })
333 |
334 | it('limitByRange', function () {
335 | var filter = arrayFilters.limitBy
336 | var range = 3
337 | var res = filter(range, false)
338 | expect(res).toEqual([1, 2, 3])
339 | res = filter(range, 1)
340 | assertArray(res, [1])
341 | res = filter(range, 10)
342 | assertArray(res, [1, 2, 3])
343 | res = filter(range, -1)
344 | assertArray(res, [1, 2])
345 | // with offsets, note offsets are 0 bound (as expected)
346 | res = filter(range, 1, 1)
347 | assertArray(res, [2])
348 | res = filter(range, 2, 1)
349 | assertArray(res, [2, 3])
350 | res = filter(range, 1, 2)
351 | assertArray(res, [3])
352 | })
353 |
354 | it('filterBy', function () {
355 | var filter = arrayFilters.filterBy
356 | var arr = [
357 | { a: 1, b: { c: 'hello' } },
358 | { a: 2, b: 'hello' },
359 | { a: 3, b: ['yoyo'] }
360 | ]
361 | var res
362 | // normal
363 | res = filter(arr, 'hello')
364 | assertArray(res, [arr[0], arr[1]])
365 | // data key
366 | res = filter(arr, 'hello', 'b.c')
367 | assertArray(res, [arr[0]])
368 | // no search key
369 | res = filter(arr, null)
370 | expect(res).toBe(arr)
371 | // number search key
372 | res = filter(arr, 2)
373 | assertArray(res, [arr[1]])
374 | // search in sub array
375 | res = filter(arr, 'yoyo')
376 | assertArray(res, [arr[2]])
377 | // filter by false (#928)
378 | arr = [{ a: false }, { b: true }]
379 | res = filter(arr, false)
380 | assertArray(res, [arr[0]])
381 | // filter by a function
382 | res = filter(arr, function (val) {
383 | return val.b === true
384 | })
385 | assertArray(res, [arr[1]])
386 | })
387 |
388 | it('filterBy multiple keys', function () {
389 | var filter = arrayFilters.filterBy
390 | var arr = [
391 | { firstname: 'A', lastname: 'B' },
392 | { firstname: 'C', lastname: 'B' },
393 | { firstname: 'A', lastname: 'D' }
394 | ]
395 | // multiple string keys
396 | var res
397 | // array of keys
398 | res = filter(arr, 'B', ['firstname', 'lastname'])
399 | assertArray(res, [arr[0], arr[1]])
400 | // multiple arrays of keys
401 | res = filter(arr, 'A', ['firstname', 'lastname'], [])
402 | assertArray(res, [arr[0], arr[2]])
403 | })
404 |
405 | it('find', function () {
406 | var find = arrayFilters.find
407 | var arr = [
408 | { a: 1, b: { c: 'hello' } },
409 | { a: 2, b: 'hello' },
410 | { a: 3, b: ['yoyo'] }
411 | ]
412 | var res = find(arr, 'hello')
413 | assertArray(res, [arr[0]])
414 | })
415 |
416 | it('orderBy', function () {
417 | var filter = arrayFilters.orderBy
418 | var arr = [
419 | { a: { b: 0 }, c: 'B' },
420 | { a: { b: 2 }, c: 'c' },
421 | { a: { b: 1 }, c: 'a' }
422 | ]
423 | var res
424 | // sort key
425 | res = filter(arr, 'a.b')
426 | assertArray(res, [arr[0], arr[2], arr[1]])
427 | // reverse key
428 | res = filter(arr, 'a.b', -1)
429 | assertArray(res, [arr[1], arr[2], arr[0]])
430 | // literal asc
431 | res = filter(arr, 'c', 1)
432 | assertArray(res, [arr[2], arr[0], arr[1]])
433 | // no sort key
434 | res = filter(arr, null)
435 | expect(res).toBe(arr)
436 | res = filter(arr)
437 | expect(res).toBe(arr)
438 | })
439 |
440 | it('orderBy on Object-converted array', function () {
441 | // object converted
442 | var filter = arrayFilters.orderBy
443 | var arr = [
444 | { $key: 'a', $value: 3 },
445 | { $key: 'c', $value: 1 },
446 | { $key: 'b', $value: 2 }
447 | ]
448 | var res = filter(arr, '$key')
449 | assertArray(res, [arr[0], arr[2], arr[1]])
450 | res = filter(arr, '$value')
451 | assertArray(res, [arr[1], arr[2], arr[0]])
452 | // normal keys
453 | arr = [
454 | { $key: 'a', $value: { v: 3 } },
455 | { $key: 'c', $value: { v: 1 } },
456 | { $key: 'b', $value: { v: 2 } }
457 | ]
458 | res = filter(arr, 'v')
459 | assertArray(res, [arr[1], arr[2], arr[0]])
460 | })
461 |
462 | it('orderBy primitive values', function () {
463 | var filter = arrayFilters.orderBy
464 | var arr = [9, 11, 1, 2]
465 | var res = filter(arr, true)
466 | assertArray(res, [arr[2], arr[3], arr[0], arr[1]])
467 | })
468 |
469 | it('orderBy array of strings', function () {
470 | var filter = arrayFilters.orderBy
471 | var arr = ['C', 'a', 'B', 'b']
472 | var res = filter(arr, true)
473 | assertArray(res, [arr[1], arr[2], arr[3], arr[0]])
474 | })
475 |
476 | it('orderBy multiple fields', function () {
477 | var filter = arrayFilters.orderBy
478 | var arr = [
479 | { a: 1, b: 1, c: 1 }, // 0
480 | { a: 0, b: 1, c: 1 }, // 1
481 | { a: 1, b: 2, c: 0 }, // 2
482 | { a: 1, b: 0, c: 0 }, // 3
483 | { a: 0, b: 0, c: 0 }, // 4
484 | { a: 0, b: 1, c: 0 } // 5
485 | ]
486 | var res
487 | // sort two keys
488 | res = filter(arr, ['a', 'b'])
489 | assertArray(res, [arr[4], arr[1], arr[5], arr[3], arr[0], arr[2]])
490 | res = filter(arr, 'a', 'b')
491 | assertArray(res, [arr[4], arr[1], arr[5], arr[3], arr[0], arr[2]])
492 |
493 | // sort two keys with order
494 | res = filter(arr, ['a', 'b'], 1)
495 | assertArray(res, [arr[4], arr[1], arr[5], arr[3], arr[0], arr[2]])
496 | res = filter(arr, 'a', 'b', 1)
497 | assertArray(res, [arr[4], arr[1], arr[5], arr[3], arr[0], arr[2]])
498 |
499 | // sort three keys
500 | res = filter(arr, ['a', 'b', 'c'])
501 | assertArray(res, [arr[4], arr[5], arr[1], arr[3], arr[0], arr[2]])
502 | res = filter(arr, 'a', 'b', 'c')
503 | assertArray(res, [arr[4], arr[5], arr[1], arr[3], arr[0], arr[2]])
504 |
505 | // reverse two key. Preserves order when equal: 1 then 5
506 | res = filter(arr, ['a', 'b'], -1)
507 | assertArray(res, [arr[2], arr[0], arr[3], arr[1], arr[5], arr[4]])
508 | res = filter(arr, 'a', 'b', -1)
509 | assertArray(res, [arr[2], arr[0], arr[3], arr[1], arr[5], arr[4]])
510 | })
511 |
512 | it('orderBy using a compare function', function () {
513 | var filter = arrayFilters.orderBy
514 | var arr = [9, 11, 1, 2]
515 | var res = filter(arr, evenBeforeOdd)
516 | assertArray(res, [arr[3], arr[2], arr[0], arr[1]])
517 | res = filter(arr, evenBeforeOdd, 1)
518 | assertArray(res, [arr[3], arr[2], arr[0], arr[1]])
519 | res = filter(arr, evenBeforeOdd, -1)
520 | assertArray(res, [arr[1], arr[0], arr[2], arr[3]])
521 | })
522 |
523 | it("repeat", () => {
524 | const filter = stringFilters.repeat;
525 | expect(filter("a")).toBe("a");
526 | expect(filter("a", 1)).toBe("a");
527 | expect(filter("a", 2)).toBe("aa");
528 | expect(filter("a", 5)).toBe("aaaaa");
529 | expect(filter("2", 2)).toBe("22");
530 | expect(filter(2, 2)).toBe("22");
531 | });
532 |
533 | it("reverse", () => {
534 | const filter = stringFilters.reverse;
535 | const value = "abcd";
536 | expect(filter(value)).toBe("dcba");
537 | });
538 |
539 | it("wrap", () => {
540 | const filter = stringFilters.wrap;
541 | const value = "value";
542 | expect(filter(value)).toBe("value");
543 | expect(filter(value, "/")).toBe("/value/");
544 | });
545 | })
546 |
547 | function evenBeforeOdd(a, b) {
548 | if (a % 2 === 0) {
549 | if (b % 2 === 0) {
550 | return a - b
551 | } else {
552 | return -1
553 | }
554 | } else if (b % 2 === 0) {
555 | return 1
556 | } else {
557 | return a - b
558 | }
559 | }
560 |
561 | function assertArray(res, expectations) {
562 | expect(res.length).toBe(expectations.length)
563 | expectations.forEach(function (exp, i) {
564 | expect(exp).toBe(res[i])
565 | })
566 | }
567 |
568 | function assertNumberAndFalsy(filter) {
569 | // should stringify numbers
570 | expect(filter(12345)).toBe('12345')
571 | expect(filter(0)).toBe('0')
572 | expect(filter(undefined)).toBe('')
573 | expect(filter(null)).toBe('')
574 | expect(filter(false)).toBe('')
575 | }
576 |
--------------------------------------------------------------------------------
/test/karma.conf.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer')
2 | process.env.CHROME_BIN = puppeteer.executablePath()
3 |
4 | module.exports = function(config) {
5 | config.set({
6 |
7 | frameworks: ['jasmine'],
8 |
9 | files: [
10 | '../test/**/*.spec.js'
11 | ],
12 |
13 | preprocessors: {
14 | '../test/**/*.spec.js': ['webpack']
15 | },
16 |
17 | browsers: ['ChromeHeadless'],
18 |
19 | plugins: [
20 | 'karma-chrome-launcher',
21 | 'karma-jasmine',
22 | 'karma-webpack'
23 | ],
24 |
25 | webpack: {
26 | entry: './src/index.js',
27 | mode: 'development'
28 | }
29 |
30 | })
31 | }
32 |
--------------------------------------------------------------------------------
/types/index.d.ts:
--------------------------------------------------------------------------------
1 | import Vue, { PluginFunction, PluginObject } from "vue";
2 |
3 | declare const Vue2Filters: Vue2Filters;
4 | export default Vue2Filters;
5 | export interface Vue2Filters extends PluginObject {
6 | install: PluginFunction;
7 | mixin: {
8 | methods: {
9 | limitBy: (arr: any, n: number, offset: number) => any;
10 | filterBy: (arr: any[], search: string | number, ...args: any[]) => any[];
11 | orderBy: (arr: any, ...args: any[]) => any;
12 | find: (arr: any[], search: string | number, ...args: any[]) => any;
13 | };
14 | };
15 | }
16 |
17 | export interface Vue2FiltersUseOptions {}
18 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var UglifyJsPlugin = require('uglifyjs-webpack-plugin');
3 |
4 | module.exports = {
5 | entry: {
6 | 'vue2-filters': './src/index.js',
7 | 'vue2-filters.min': './src/index.js'
8 | },
9 | output: {
10 | path: path.resolve(__dirname, 'dist'),
11 | filename: '[name].js',
12 | libraryTarget: "umd",
13 | globalObject: 'typeof self !== \'undefined\' ? self : this'
14 | },
15 | optimization: {
16 | minimize: true,
17 | minimizer: [new UglifyJsPlugin({
18 | include: /\.min\.js$/
19 | })]
20 | },
21 | module: {
22 | rules: [
23 | {
24 | test: /\.js$/,
25 | exclude: /node_modules/,
26 | use: {
27 | loader: 'babel-loader'
28 | }
29 | }
30 | ]
31 | }
32 | };
--------------------------------------------------------------------------------