@lvchengbin/is
Advanced tools
Comparing version 0.0.10 to 0.0.12
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global.IS = factory()); | ||
(global.is = factory()); | ||
}(this, (function () { 'use strict'; | ||
var isArguments = (function (obj) { | ||
return {}.toString.call(obj) === '[object Arguments]'; | ||
}); | ||
function isArguments (obj) { return ({}).toString.call( obj ) === '[object Arguments]'; } | ||
var isArray = (function (obj) { | ||
return Array.isArray(obj); | ||
}); | ||
function isArray (obj) { return Array.isArray( obj ); } | ||
var isAsyncFunction = (function (fn) { | ||
return {}.toString.call(fn) === '[object AsyncFunction]'; | ||
}); | ||
/** | ||
* async function | ||
* | ||
* @syntax: | ||
* async function() {} | ||
* async () => {} | ||
* async x() => {} | ||
* | ||
* @compatibility | ||
* IE: no | ||
* Edge: >= 15 | ||
* Android: >= 5.0 | ||
* | ||
*/ | ||
var isFunction = (function (fn) { | ||
return {}.toString.call(fn) === '[object Function]' || isAsyncFunction(fn); | ||
}); | ||
function isAsyncFunction (fn) { return ( {} ).toString.call( fn ) === '[object AsyncFunction]'; } | ||
var arrowFunction = (function (fn) { | ||
if (!isFunction(fn)) return false; | ||
return (/^(?:function)?\s*\(?[\w\s,]*\)?\s*=>/.test(fn.toString()) | ||
); | ||
}); | ||
function isFunction (fn) { return ({}).toString.call( fn ) === '[object Function]' || isAsyncFunction( fn ); } | ||
var isBoolean = (function (s) { | ||
return typeof s === 'boolean'; | ||
}); | ||
/** | ||
* arrow function | ||
* | ||
* Syntax: () => {} | ||
* | ||
* IE : no | ||
* Android : >= 5.0 | ||
*/ | ||
var date = (function (date) { | ||
return {}.toString.call(date) === '[object Date]'; | ||
}); | ||
function arrowFunction (fn) { | ||
if( !isFunction( fn ) ) { return false; } | ||
return /^(?:function)?\s*\(?[\w\s,]*\)?\s*=>/.test( fn.toString() ); | ||
} | ||
var email = (function (str) { | ||
return (/^(([^#$%&*!+-/=?^`{|}~<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/i.test(str) | ||
); | ||
}); | ||
function isBoolean (s) { return typeof s === 'boolean'; } | ||
var isString = (function (str) { | ||
return typeof str === 'string' || str instanceof String; | ||
}); | ||
function date (date) { return ({}).toString.call( date ) === '[object Date]'; } | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
return typeof obj; | ||
} : function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; | ||
}; | ||
function email (str) { return /^(([^#$%&*!+-/=?^`{|}~<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/i.test( str ); } | ||
var isObject = (function (obj) { | ||
return obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && !Array.isArray(obj); | ||
}); | ||
function isString (str) { return typeof str === 'string' || str instanceof String; } | ||
var empty = (function (obj) { | ||
if (isArray(obj) || isString(obj)) { | ||
function isObject (obj) { return obj && typeof obj === 'object' && !Array.isArray( obj ); } | ||
function empty (obj) { | ||
if( isArray( obj ) || isString( obj ) ) { | ||
return !obj.length; | ||
} | ||
if (isObject(obj)) { | ||
return !Object.keys(obj).length; | ||
if( isObject( obj ) ) { | ||
return !Object.keys( obj ).length; | ||
} | ||
return !obj; | ||
}); | ||
} | ||
var error = (function (e) { | ||
return {}.toString.call(e) === '[object Error]'; | ||
}); | ||
function error (e) { return ({}).toString.call( e ) === '[object Error]'; } | ||
var isFalse = (function (obj) { | ||
var generalized = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; | ||
function isFalse ( obj, generalized ) { | ||
if ( generalized === void 0 ) generalized = true; | ||
if (isBoolean(obj) || !generalized) return !obj; | ||
if (isString(obj)) { | ||
return ['false', 'no', '0', '', 'nay', 'n', 'disagree'].indexOf(obj.toLowerCase()) > -1; | ||
if( isBoolean( obj ) || !generalized ) { return !obj; } | ||
if( isString( obj ) ) { | ||
return [ 'false', 'no', '0', '', 'nay', 'n', 'disagree' ].indexOf( obj.toLowerCase() ) > -1; | ||
} | ||
return !obj; | ||
}); | ||
} | ||
var isNumber = (function (n) { | ||
var strict = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
function isNumber ( n, strict ) { | ||
if ( strict === void 0 ) strict = false; | ||
if ({}.toString.call(n).toLowerCase() === '[object number]') { | ||
if( ({}).toString.call( n ).toLowerCase() === '[object number]' ) { | ||
return true; | ||
} | ||
if (strict) return false; | ||
return !isNaN(parseFloat(n)) && isFinite(n) && !/\.$/.test(n); | ||
}); | ||
if( strict ) { return false; } | ||
return !isNaN( parseFloat( n ) ) && isFinite( n ) && !/\.$/.test( n ); | ||
} | ||
var integer = (function (n) { | ||
var strict = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
function isInteger ( n, strict ) { | ||
if ( strict === void 0 ) strict = false; | ||
if (isNumber(n, true)) return n % 1 === 0; | ||
if( isNumber( n, true ) ) { return n % 1 === 0; } | ||
if (strict) return false; | ||
if( strict ) { return false; } | ||
if (isString(n)) { | ||
if (n === '-0') return true; | ||
return n.indexOf('.') < 0 && String(parseInt(n)) === n; | ||
if( isString( n ) ) { | ||
if( n === '-0' ) { return true; } | ||
return n.indexOf( '.' ) < 0 && String( parseInt( n ) ) === n; | ||
} | ||
return false; | ||
}); | ||
} | ||
var iterable = (function (obj) { | ||
/** | ||
* iterable | ||
* | ||
* @compatibility | ||
* | ||
* IE: no | ||
* Edge: >= 13 | ||
* Android: >= 5.0 | ||
* | ||
*/ | ||
function iterable (obj) { | ||
try { | ||
return isFunction(obj[Symbol.iterator]); | ||
} catch (e) { | ||
return isFunction( obj[ Symbol.iterator ] ); | ||
} catch( e ) { | ||
return false; | ||
} | ||
}); | ||
} | ||
// https://github.com/jquery/jquery/blob/2d4f53416e5f74fa98e0c1d66b6f3c285a12f0ce/test/data/jquery-1.9.1.js#L480 | ||
var plainObject = (function (obj) { | ||
if (!isObject(obj)) { | ||
function plainObject (obj) { | ||
if( !isObject( obj ) ) { | ||
return false; | ||
@@ -122,72 +129,89 @@ } | ||
try { | ||
if (obj.constructor && !{}.hasOwnProperty.call(obj, 'constructor') && !{}.hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf')) { | ||
if( obj.constructor && !({}).hasOwnProperty.call( obj, 'constructor' ) && !({}).hasOwnProperty.call( obj.constructor.prototype, 'isPrototypeOf' ) ) { | ||
return false; | ||
} | ||
} catch (e) { | ||
} catch( e ) { | ||
return false; | ||
} | ||
var key = void 0; | ||
for (key in obj) {} // eslint-disable-line | ||
var key; | ||
for( key in obj ) {} // eslint-disable-line | ||
return key === undefined || {}.hasOwnProperty.call(obj, key); | ||
}); | ||
return key === undefined || ({}).hasOwnProperty.call( obj, key ); | ||
} | ||
var promise = (function (p) { | ||
return p && isFunction(p.then); | ||
}); | ||
function promise (p) { return p && isFunction( p.then ); } | ||
var regexp = (function (reg) { | ||
return {}.toString.call(reg) === '[object RegExp]'; | ||
}); | ||
function regexp (reg) { return ({}).toString.call( reg ) === '[object RegExp]'; } | ||
var isTrue = (function (obj) { | ||
var generalized = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; | ||
function isTrue ( obj, generalized ) { | ||
if ( generalized === void 0 ) generalized = true; | ||
if (isBoolean(obj) || !generalized) return !!obj; | ||
if (isString(obj)) { | ||
return ['true', 'yes', 'ok', '1', 'yea', 'yep', 'y', 'agree'].indexOf(obj.toLowerCase()) > -1; | ||
if( isBoolean( obj ) || !generalized ) { return !!obj; } | ||
if( isString( obj ) ) { | ||
return [ 'true', 'yes', 'ok', '1', 'yea', 'yep', 'y', 'agree' ].indexOf( obj.toLowerCase() ) > -1; | ||
} | ||
return !!obj; | ||
}); | ||
} | ||
function isUndefined () { | ||
return arguments.length > 0 && typeof arguments[0] === 'undefined'; | ||
function isUndefined() { | ||
return arguments.length > 0 && typeof arguments[ 0 ] === 'undefined'; | ||
} | ||
var url = (function (url) { | ||
if (!isString(url)) return false; | ||
if (!/^(https?|ftp):\/\//i.test(url)) return false; | ||
var a = document.createElement('a'); | ||
function isIPv4 (ip) { | ||
if( !isString( ip ) ) { return false; } | ||
var pieces = ip.split( '.' ); | ||
if( pieces.length !== 4 ) { return false; } | ||
for( var i$1 = 0, list = pieces; i$1 < list.length; i$1 += 1 ) { | ||
var i = list[i$1]; | ||
if( !isInteger( i ) ) { return false; } | ||
if( i < 0 || i > 255 ) { return false; } | ||
} | ||
return true; | ||
} | ||
function url (url) { | ||
if( !isString( url ) ) { return false; } | ||
if( !/^(https?|ftp):\/\//i.test( url ) ) { return false; } | ||
var a = document.createElement( 'a' ); | ||
a.href = url; | ||
return (/^(https?|ftp):/i.test(a.protocol) | ||
); | ||
}); | ||
var isNode = (function (s) { | ||
return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ? s instanceof Node : s && (typeof s === 'undefined' ? 'undefined' : _typeof(s)) === 'object' && typeof s.nodeType === 'number' && typeof s.nodeName === 'string'; | ||
}); | ||
/** | ||
* In IE, sometimes a.protocol would be an unknown type | ||
* Getting a.protocol will throw Error: Invalid argument in IE | ||
*/ | ||
try { | ||
if( !isString( a.protocol ) ) { return false; } | ||
} catch( e ) { | ||
return false; | ||
} | ||
var textNode = (function (node) { | ||
return isNode(node) && node.nodeType === 3; | ||
}); | ||
if( !/^(https?|ftp):/i.test( a.protocol ) ) { return false; } | ||
var elementNode = (function (node) { | ||
return isNode(node) && node.nodeType === 1; | ||
}); | ||
/** | ||
* In IE, invalid IP address could be a valid hostname | ||
*/ | ||
if( /^(\d+\.){3}\d+$/.test( a.hostname ) && !isIPv4( a.hostname ) ) { return false; } | ||
var isWindow = (function (obj) { | ||
return obj && obj === obj.window; | ||
}); | ||
return true; | ||
} | ||
var isClass = (function (obj) { | ||
return isFunction(obj) && /^\s*class\s+/.test(obj.toString()); | ||
}); | ||
function isNode (s) { return ( typeof Node === 'object' ? s instanceof Node : s && typeof s === 'object' && typeof s.nodeType === 'number' && typeof s.nodeName === 'string' ); } | ||
var is = { | ||
arguments: isArguments, | ||
function textNode (node) { return isNode( node ) && node.nodeType === 3; } | ||
function elementNode (node) { return isNode( node ) && node.nodeType === 1; } | ||
function isWindow (obj) { return obj && obj === obj.window; } | ||
function isClass (obj) { return isFunction( obj ) && /^\s*class\s+/.test( obj.toString() ); } | ||
var is_bc = { | ||
arguments : isArguments, | ||
array: isArray, | ||
arrowFunction: arrowFunction, | ||
asyncFunction: isAsyncFunction, | ||
boolean: isBoolean, | ||
boolean : isBoolean, | ||
date: date, | ||
@@ -197,5 +221,5 @@ email: email, | ||
error: error, | ||
false: isFalse, | ||
function: isFunction, | ||
integer: integer, | ||
false : isFalse, | ||
function : isFunction, | ||
integer: isInteger, | ||
iterable: iterable, | ||
@@ -208,4 +232,4 @@ number: isNumber, | ||
string: isString, | ||
true: isTrue, | ||
undefined: isUndefined, | ||
true : isTrue, | ||
undefined : isUndefined, | ||
url: url, | ||
@@ -215,8 +239,9 @@ node: isNode, | ||
elementNode: elementNode, | ||
window: isWindow, | ||
class: isClass | ||
window : isWindow, | ||
class : isClass, | ||
ipv4 : isIPv4 | ||
}; | ||
return is; | ||
return is_bc; | ||
}))); |
@@ -7,2 +7,17 @@ 'use strict'; | ||
/** | ||
* async function | ||
* | ||
* @syntax: | ||
* async function() {} | ||
* async () => {} | ||
* async x() => {} | ||
* | ||
* @compatibility | ||
* IE: no | ||
* Edge: >= 15 | ||
* Android: >= 5.0 | ||
* | ||
*/ | ||
var isAsyncFunction = fn => ( {} ).toString.call( fn ) === '[object AsyncFunction]'; | ||
@@ -12,2 +27,11 @@ | ||
/** | ||
* arrow function | ||
* | ||
* Syntax: () => {} | ||
* | ||
* IE : no | ||
* Android : >= 5.0 | ||
*/ | ||
var arrowFunction = fn => { | ||
@@ -56,3 +80,3 @@ if( !isFunction( fn ) ) return false; | ||
var integer = ( n, strict = false ) => { | ||
var isInteger = ( n, strict = false ) => { | ||
@@ -71,2 +95,13 @@ if( isNumber( n, true ) ) return n % 1 === 0; | ||
/** | ||
* iterable | ||
* | ||
* @compatibility | ||
* | ||
* IE: no | ||
* Edge: >= 13 | ||
* Android: >= 5.0 | ||
* | ||
*/ | ||
var iterable = obj => { | ||
@@ -117,2 +152,14 @@ try { | ||
var isIPv4 = ip => { | ||
if( !isString( ip ) ) return false; | ||
const pieces = ip.split( '.' ); | ||
if( pieces.length !== 4 ) return false; | ||
for( const i of pieces ) { | ||
if( !isInteger( i ) ) return false; | ||
if( i < 0 || i > 255 ) return false; | ||
} | ||
return true; | ||
}; | ||
var url = url => { | ||
@@ -123,3 +170,21 @@ if( !isString( url ) ) return false; | ||
a.href = url; | ||
return /^(https?|ftp):/i.test( a.protocol ); | ||
/** | ||
* In IE, sometimes a.protocol would be an unknown type | ||
* Getting a.protocol will throw Error: Invalid argument in IE | ||
*/ | ||
try { | ||
if( !isString( a.protocol ) ) return false; | ||
} catch( e ) { | ||
return false; | ||
} | ||
if( !/^(https?|ftp):/i.test( a.protocol ) ) return false; | ||
/** | ||
* In IE, invalid IP address could be a valid hostname | ||
*/ | ||
if( /^(\d+\.){3}\d+$/.test( a.hostname ) && !isIPv4( a.hostname ) ) return false; | ||
return true; | ||
}; | ||
@@ -137,2 +202,4 @@ | ||
var generator = fn => fn.constructor === (function*(){}).constructor; | ||
var is = { | ||
@@ -150,3 +217,3 @@ arguments : isArguments, | ||
function : isFunction, | ||
integer, | ||
integer: isInteger, | ||
iterable, | ||
@@ -166,5 +233,7 @@ number: isNumber, | ||
window : isWindow, | ||
class : isClass | ||
class : isClass, | ||
ipv4 : isIPv4, | ||
generator | ||
}; | ||
module.exports = is; |
@@ -11,2 +11,17 @@ (function (global, factory) { | ||
/** | ||
* async function | ||
* | ||
* @syntax: | ||
* async function() {} | ||
* async () => {} | ||
* async x() => {} | ||
* | ||
* @compatibility | ||
* IE: no | ||
* Edge: >= 15 | ||
* Android: >= 5.0 | ||
* | ||
*/ | ||
var isAsyncFunction = fn => ( {} ).toString.call( fn ) === '[object AsyncFunction]'; | ||
@@ -16,2 +31,11 @@ | ||
/** | ||
* arrow function | ||
* | ||
* Syntax: () => {} | ||
* | ||
* IE : no | ||
* Android : >= 5.0 | ||
*/ | ||
var arrowFunction = fn => { | ||
@@ -60,3 +84,3 @@ if( !isFunction( fn ) ) return false; | ||
var integer = ( n, strict = false ) => { | ||
var isInteger = ( n, strict = false ) => { | ||
@@ -75,2 +99,13 @@ if( isNumber( n, true ) ) return n % 1 === 0; | ||
/** | ||
* iterable | ||
* | ||
* @compatibility | ||
* | ||
* IE: no | ||
* Edge: >= 13 | ||
* Android: >= 5.0 | ||
* | ||
*/ | ||
var iterable = obj => { | ||
@@ -121,2 +156,14 @@ try { | ||
var isIPv4 = ip => { | ||
if( !isString( ip ) ) return false; | ||
const pieces = ip.split( '.' ); | ||
if( pieces.length !== 4 ) return false; | ||
for( const i of pieces ) { | ||
if( !isInteger( i ) ) return false; | ||
if( i < 0 || i > 255 ) return false; | ||
} | ||
return true; | ||
}; | ||
var url = url => { | ||
@@ -127,3 +174,21 @@ if( !isString( url ) ) return false; | ||
a.href = url; | ||
return /^(https?|ftp):/i.test( a.protocol ); | ||
/** | ||
* In IE, sometimes a.protocol would be an unknown type | ||
* Getting a.protocol will throw Error: Invalid argument in IE | ||
*/ | ||
try { | ||
if( !isString( a.protocol ) ) return false; | ||
} catch( e ) { | ||
return false; | ||
} | ||
if( !/^(https?|ftp):/i.test( a.protocol ) ) return false; | ||
/** | ||
* In IE, invalid IP address could be a valid hostname | ||
*/ | ||
if( /^(\d+\.){3}\d+$/.test( a.hostname ) && !isIPv4( a.hostname ) ) return false; | ||
return true; | ||
}; | ||
@@ -141,2 +206,4 @@ | ||
var generator = fn => fn.constructor === (function*(){}).constructor; | ||
var is = { | ||
@@ -154,3 +221,3 @@ arguments : isArguments, | ||
function : isFunction, | ||
integer, | ||
integer: isInteger, | ||
iterable, | ||
@@ -170,3 +237,5 @@ number: isNumber, | ||
window : isWindow, | ||
class : isClass | ||
class : isClass, | ||
ipv4 : isIPv4, | ||
generator | ||
}; | ||
@@ -173,0 +242,0 @@ |
{ | ||
"name": "@lvchengbin/is", | ||
"version": "0.0.10", | ||
"version": "0.0.12", | ||
"description": "A library, which is possible to be imported as ES6 module separately, for checking the type of a value.", | ||
@@ -11,2 +11,3 @@ "keywords": "is check types es6", | ||
"devDependencies": { | ||
"@lvchengbin/promise": "^1.1.4", | ||
"babel-cli": "^6.26.0", | ||
@@ -16,2 +17,3 @@ "babel-core": "^6.26.0", | ||
"babel-preset-es2015": "^6.24.1", | ||
"buble": "^0.19.3", | ||
"eslint": "^4.14.0", | ||
@@ -30,2 +32,3 @@ "jasmine-core": "^2.8.0", | ||
"rollup-plugin-babel": "^3.0.3", | ||
"rollup-plugin-buble": "^0.19.2", | ||
"rollup-plugin-node-resolve": "^3.0.2", | ||
@@ -32,0 +35,0 @@ "run-sequence": "^2.2.0" |
@@ -1,3 +0,3 @@ | ||
import babel from 'rollup-plugin-babel'; | ||
import resolve from 'rollup-plugin-node-resolve'; | ||
import buble from 'rollup-plugin-buble'; | ||
@@ -17,3 +17,3 @@ export default [ { | ||
}, { | ||
input : 'src/is.js', | ||
input : 'src/is.bc.js', | ||
plugins : [ | ||
@@ -24,7 +24,12 @@ resolve( { | ||
} ), | ||
babel() | ||
buble( { | ||
transforms : { | ||
arrow : true, | ||
dangerousForOf : true | ||
} | ||
} ) | ||
], | ||
output : [ | ||
{ file : 'dist/is.bc.js', format : 'umd', name : 'IS' } | ||
{ file : 'dist/is.bc.js', format : 'umd', name : 'is' } | ||
] | ||
} ]; |
@@ -0,1 +1,10 @@ | ||
/** | ||
* arrow function | ||
* | ||
* Syntax: () => {} | ||
* | ||
* IE : no | ||
* Android : >= 5.0 | ||
*/ | ||
import isFunction from './function'; | ||
@@ -2,0 +11,0 @@ |
@@ -0,1 +1,16 @@ | ||
/** | ||
* async function | ||
* | ||
* @syntax: | ||
* async function() {} | ||
* async () => {} | ||
* async x() => {} | ||
* | ||
* @compatibility | ||
* IE: no | ||
* Edge: >= 15 | ||
* Android: >= 5.0 | ||
* | ||
*/ | ||
export default fn => ( {} ).toString.call( fn ) === '[object AsyncFunction]'; |
@@ -28,2 +28,4 @@ import isArguments from './arguments'; | ||
import isClass from './class'; | ||
import isIPv4 from './ipv4'; | ||
import generator from './generator'; | ||
@@ -57,3 +59,5 @@ export default { | ||
window : isWindow, | ||
class : isClass | ||
class : isClass, | ||
ipv4 : isIPv4, | ||
generator | ||
}; |
@@ -0,1 +1,12 @@ | ||
/** | ||
* iterable | ||
* | ||
* @compatibility | ||
* | ||
* IE: no | ||
* Edge: >= 13 | ||
* Android: >= 5.0 | ||
* | ||
*/ | ||
import isFunction from './function'; | ||
@@ -2,0 +13,0 @@ |
import isString from './string'; | ||
import isIPv4 from './ipv4'; | ||
@@ -8,3 +9,21 @@ export default url => { | ||
a.href = url; | ||
return /^(https?|ftp):/i.test( a.protocol ); | ||
/** | ||
* In IE, sometimes a.protocol would be an unknown type | ||
* Getting a.protocol will throw Error: Invalid argument in IE | ||
*/ | ||
try { | ||
if( !isString( a.protocol ) ) return false; | ||
} catch( e ) { | ||
return false; | ||
} | ||
if( !/^(https?|ftp):/i.test( a.protocol ) ) return false; | ||
/** | ||
* In IE, invalid IP address could be a valid hostname | ||
*/ | ||
if( /^(\d+\.){3}\d+$/.test( a.hostname ) && !isIPv4( a.hostname ) ) return false; | ||
return true; | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
35021
43
904
22