index.js 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310
  1. /**
  2. * @fileOverview
  3. * is2 derived from is by Enrico Marino, adapted for Node.js.
  4. * Slightly modified by Edmond Meinfelder
  5. *
  6. * is
  7. * the definitive JavaScript type testing library
  8. * Copyright(c) 2013,2014 Edmond Meinfelder <edmond@stdarg.com>
  9. * Copyright(c) 2011 Enrico Marino <enrico.marino@email.com>
  10. * MIT license
  11. */
  12. 'use strict';
  13. const owns = {}.hasOwnProperty;
  14. const toString = {}.toString;
  15. const is = exports;
  16. const deepIs = require('deep-is');
  17. const ipRegEx = require('ip-regex');
  18. is.version = require('./package.json').version;
  19. ////////////////////////////////////////////////////////////////////////////////
  20. // Environment
  21. /**
  22. * Tests if is is running under a browser.
  23. * @return {Boolean} true if the environment has process, process.version and process.versions.
  24. */
  25. is.browser = function() {
  26. return (!is.node() && typeof window !== 'undefined' && toString.call(window) === '[object global]');
  27. };
  28. /**
  29. * Test if 'value' is defined.
  30. * Alias: def
  31. * @param {Any} value The value to test.
  32. * @return {Boolean} true if 'value' is defined, false otherwise.
  33. */
  34. is.defined = function(value) {
  35. return typeof value !== 'undefined';
  36. };
  37. is.def = is.defined;
  38. /**
  39. * Tests if is is running under node.js
  40. * @return {Boolean} true if the environment has process, process.version and process.versions.
  41. */
  42. is.nodejs = function() {
  43. return (process && process.hasOwnProperty('version') &&
  44. process.hasOwnProperty('versions'));
  45. };
  46. is.node = is.nodejs;
  47. /**
  48. * Test if 'value' is undefined.
  49. * Aliases: undef, udef
  50. * @param {Any} value value to test.
  51. * @return {Boolean} true if 'value' is undefined, false otherwise.
  52. */
  53. is.undefined = function(value) {
  54. return value === undefined;
  55. };
  56. is.udef = is.undef = is.undefined;
  57. ////////////////////////////////////////////////////////////////////////////////
  58. // Types
  59. /**
  60. * Test if 'value' is an array.
  61. * Alias: ary, arry
  62. * @param {Any} value value to test.
  63. * @return {Boolean} true if 'value' is an array, false otherwise.
  64. */
  65. is.array = function(value) {
  66. return '[object Array]' === toString.call(value);
  67. };
  68. is.arr = is.ary = is.arry = is.array;
  69. /**
  70. * Test if 'value' is an arraylike object (i.e. it has a length property with a valid value)
  71. * Aliases: arraylike, arryLike, aryLike
  72. * @param {Any} value value to test.
  73. * @return {Boolean} true if 'value' is an arguments object, false otherwise.
  74. */
  75. is.arrayLike = function(value) {
  76. if (is.nullOrUndef(value))
  77. return false;
  78. return value !== undefined &&
  79. owns.call(value, 'length') &&
  80. isFinite(value.length);
  81. };
  82. is.arrLike = is.arryLike = is.aryLike = is.arraylike = is.arrayLike;
  83. /**
  84. * Test if 'value' is an arguments object.
  85. * Alias: args
  86. * @param {Any} value value to test
  87. * @return {Boolean} true if 'value' is an arguments object, false otherwise
  88. */
  89. is.arguments = function(value) {
  90. return '[object Arguments]' === toString.call(value);
  91. };
  92. is.args = is.arguments;
  93. /**
  94. * Test if 'value' is a boolean.
  95. * Alias: bool
  96. * @param {Any} value value to test.
  97. * @return {Boolean} true if 'value' is a boolean, false otherwise.
  98. */
  99. is.boolean = function(value) {
  100. return '[object Boolean]' === toString.call(value);
  101. };
  102. is.bool = is.boolean;
  103. /**
  104. * Test if 'value' is an instance of Buffer.
  105. * Aliases: instOf, instanceof
  106. * @param {Any} value value to test.
  107. * @return {Boolean} true if 'value' is an instance of 'constructor'.
  108. */
  109. is.buffer = function(value) {
  110. return is.nodejs() && Buffer && Buffer.hasOwnProperty('isBuffer') && Buffer.isBuffer(value);
  111. };
  112. is.buff = is.buf = is.buffer;
  113. /**
  114. * Test if 'value' is a date.
  115. * @param {Any} value value to test.
  116. * @return {Boolean} true if 'value' is a date, false otherwise.
  117. */
  118. is.date = function(value) {
  119. return '[object Date]' === toString.call(value);
  120. };
  121. /**
  122. * Test if 'value' is an error object.
  123. * Alias: err
  124. * @param value value to test.
  125. * @return {Boolean} true if 'value' is an error object, false otherwise.
  126. */
  127. is.error = function(value) {
  128. return '[object Error]' === toString.call(value);
  129. };
  130. is.err = is.error;
  131. /**
  132. * Test if 'value' is false.
  133. * @param {Any} value value to test.
  134. * @return {Boolean} true if 'value' is false, false otherwise
  135. */
  136. is.false = function(value) {
  137. return value === false;
  138. };
  139. /**
  140. * Test if 'value' is a function or async function.
  141. * Alias: func
  142. * @param {Any} value value to test.
  143. * @return {Boolean} true if 'value' is a function, false otherwise.
  144. */
  145. is.function = function(value) {
  146. return is.syncFunction(value) || is.asyncFunction(value)
  147. };
  148. is.fun = is.func = is.function;
  149. /**
  150. * Test if 'value' is an async function using `async () => {}` or `async function () {}`.
  151. * Alias: func
  152. * @param {Any} value value to test.
  153. * @return {Boolean} true if 'value' is a function, false otherwise.
  154. */
  155. is.asyncFunction = function(value) {
  156. return '[object AsyncFunction]' === toString.call(value);
  157. }
  158. is.asyncFun = is.asyncFunc = is.asyncFunction;
  159. /**
  160. * Test if 'value' is a synchronous function.
  161. * Alias: syncFunc
  162. * @param {Any} value value to test.
  163. * @return {Boolean} true if 'value' is a function, false otherwise.
  164. */
  165. is.syncFunction = function (value) {
  166. return '[object Function]' === toString.call(value);
  167. }
  168. is.syncFun = is.syncFunc = is.syncFunction
  169. /**
  170. * Test if 'value' is null.
  171. * @param {Any} value to test.
  172. * @return {Boolean} true if 'value' is null, false otherwise.
  173. */
  174. is.null = function(value) {
  175. return value === null;
  176. };
  177. /**
  178. * Test is 'value' is either null or undefined.
  179. * Alias: nullOrUndef
  180. * @param {Any} value value to test.
  181. * @return {Boolean} True if value is null or undefined, false otherwise.
  182. */
  183. is.nullOrUndefined = function(value) {
  184. return value === null || typeof value === 'undefined';
  185. };
  186. is.nullOrUndef = is.nullOrUndefined;
  187. /**
  188. * Test if 'value' is a number.
  189. * Alias: num
  190. * @param {Any} value to test.
  191. * @return {Boolean} true if 'value' is a number, false otherwise.
  192. */
  193. is.number = function(value) {
  194. return '[object Number]' === toString.call(value);
  195. };
  196. is.num = is.number;
  197. /**
  198. * Test if 'value' is an object. Note: Arrays, RegExps, Date, Error, etc all return false.
  199. * Alias: obj
  200. * @param {Any} value to test.
  201. * @return {Boolean} true if 'value' is an object, false otherwise.
  202. */
  203. is.object = function(value) {
  204. return '[object Object]' === toString.call(value);
  205. };
  206. is.obj = is.object;
  207. /**
  208. * Test if 'value' is a regular expression.
  209. * Alias: regexp
  210. * @param {Any} value to test.
  211. * @return {Boolean} true if 'value' is a regexp, false otherwise.
  212. */
  213. is.regExp = function(value) {
  214. return '[object RegExp]' === toString.call(value);
  215. };
  216. is.re = is.regexp = is.regExp;
  217. /**
  218. * Test if 'value' is a string.
  219. * Alias: str
  220. * @param {Any} value to test.
  221. * @return {Boolean} true if 'value' is a string, false otherwise.
  222. */
  223. is.string = function(value) {
  224. return '[object String]' === toString.call(value);
  225. };
  226. is.str = is.string;
  227. /**
  228. * Test if 'value' is true.
  229. * @param {Any} value to test.
  230. * @return {Boolean} true if 'value' is true, false otherwise.
  231. */
  232. is.true = function(value) {
  233. return value === true;
  234. };
  235. /**
  236. * Test if 'value' is a uuid (v1-v5)
  237. * @param {Any} value to test.
  238. * @return {Boolean} true if 'value is a valid RFC4122 UUID. Case non-specific.
  239. */
  240. var uuidRegExp = new RegExp('[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab]'+
  241. '[0-9a-f]{3}-[0-9a-f]{12}', 'i');
  242. is.uuid = function(value) {
  243. return uuidRegExp.test(value);
  244. };
  245. ////////////////////////////////////////////////////////////////////////////////
  246. // Object Relationships
  247. /**
  248. * Test if 'value' is equal to 'other'. Works for objects and arrays and will do deep comparisions,
  249. * using recursion.
  250. * Alias: eq
  251. * @param {Any} value value.
  252. * @param {Any} other value to compare with.
  253. * @return {Boolean} true if 'value' is equal to 'other', false otherwise
  254. */
  255. is.equal = function(value, other) {
  256. var type = toString.call(value);
  257. if (typeof value !== typeof other) {
  258. return false;
  259. }
  260. if (type !== toString.call(other)) {
  261. return false;
  262. }
  263. if ('[object Object]' === type || '[object Array]' === type) {
  264. return deepIs(value, other);
  265. } else if ('[object Function]' === type) {
  266. return value.prototype === other.prototype;
  267. } else if ('[object Date]' === type) {
  268. return value.getTime() === other.getTime();
  269. }
  270. return value === other;
  271. };
  272. is.objEquals = is.eq = is.equal;
  273. /**
  274. * JS Type definitions which cannot host values.
  275. * @api private
  276. */
  277. var NON_HOST_TYPES = {
  278. 'boolean': 1,
  279. 'number': 1,
  280. 'string': 1,
  281. 'undefined': 1
  282. };
  283. /**
  284. * Test if 'key' in host is an object. To be hosted means host[value] is an object.
  285. * @param {Any} value The value to test.
  286. * @param {Any} host Host that may contain value.
  287. * @return {Boolean} true if 'value' is hosted by 'host', false otherwise.
  288. */
  289. is.hosted = function(value, host) {
  290. if (is.nullOrUndef(value))
  291. return false;
  292. var type = typeof host[value];
  293. return type === 'object' ? !!host[value] : !NON_HOST_TYPES[type];
  294. };
  295. /**
  296. * Test if 'value' is an instance of 'constructor'.
  297. * Aliases: instOf, instanceof
  298. * @param {Any} value value to test.
  299. * @return {Boolean} true if 'value' is an instance of 'constructor'.
  300. */
  301. is.instanceOf = function(value, constructor) {
  302. if (is.nullOrUndef(value) || is.nullOrUndef(constructor))
  303. return false;
  304. return (value instanceof constructor);
  305. };
  306. is.instOf = is.instanceof = is.instanceOf;
  307. /**
  308. * Test if 'value' is an instance type objType.
  309. * Aliases: objInstOf, objectinstanceof, instOf, instanceOf
  310. * @param {object} objInst an object to testfor type.
  311. * @param {object} objType an object type to compare.
  312. * @return {Boolean} true if 'value' is an object, false otherwise.
  313. */
  314. is.objectInstanceOf = function(objInst, objType) {
  315. try {
  316. return '[object Object]' === toString.call(objInst) && (objInst instanceof objType);
  317. } catch(err) {
  318. return false;
  319. }
  320. };
  321. is.instOf = is.instanceOf = is.objInstOf = is.objectInstanceOf;
  322. /**
  323. * Test if 'value' is a type of 'type'.
  324. * Alias: a
  325. * @param value value to test.
  326. * @param {String} type The name of the type.
  327. * @return {Boolean} true if 'value' is an arguments object, false otherwise.
  328. */
  329. is.type = function(value, type) {
  330. return typeof value === type;
  331. };
  332. is.a = is.type;
  333. ////////////////////////////////////////////////////////////////////////////////
  334. // Object State
  335. /**
  336. * Test if 'value' is empty. To be empty means to be an array, object or string with nothing contained.
  337. * @param {Any} value value to test.
  338. * @return {Boolean} true if 'value' is empty, false otherwise.
  339. */
  340. is.empty = function(value) {
  341. var type = toString.call(value);
  342. if ('[object Array]' === type || '[object Arguments]' === type) {
  343. return value.length === 0;
  344. }
  345. if ('[object Object]' === type) {
  346. for (var key in value) if (owns.call(value, key)) return false;
  347. return true;
  348. }
  349. if ('[object String]' === type) {
  350. return value === '';
  351. }
  352. return false;
  353. };
  354. /**
  355. * Test if 'value' is an arguments object that is empty.
  356. * Alias: args
  357. * @param {Any} value value to test
  358. * @return {Boolean} true if 'value' is an arguments object with no args, false otherwise
  359. */
  360. is.emptyArguments = function(value) {
  361. return '[object Arguments]' === toString.call(value) && value.length === 0;
  362. };
  363. is.noArgs = is.emptyArgs = is.emptyArguments;
  364. /**
  365. * Test if 'value' is an array containing no entries.
  366. * Aliases: emptyArry, emptyAry
  367. * @param {Any} value The value to test.
  368. * @return {Boolean} true if 'value' is an array with no elemnets.
  369. */
  370. is.emptyArray = function(value) {
  371. return '[object Array]' === toString.call(value) && value.length === 0;
  372. };
  373. is.emptyArry = is.emptyAry = is.emptyArray;
  374. /**
  375. * Test if 'value' is an empty array(like) object.
  376. * Aliases: arguents.empty, args.empty, ary.empty, arry.empty
  377. * @param {Any} value value to test.
  378. * @return {Boolean} true if 'value' is an empty array(like), false otherwise.
  379. */
  380. is.emptyArrayLike = function(value) {
  381. return value.length === 0;
  382. };
  383. is.emptyArrLike = is.emptyArrayLike;
  384. /**
  385. * Test if 'value' is an empty string.
  386. * Alias: emptyStr
  387. * @param {Any} value to test.
  388. * @return {Boolean} true if 'value' is am empty string, false otherwise.
  389. */
  390. is.emptyString = function(value) {
  391. return is.string(value) && value.length === 0;
  392. };
  393. is.emptyStr = is.emptyString;
  394. /**
  395. * Test if 'value' is an array containing at least 1 entry.
  396. * Aliases: nonEmptyArry, nonEmptyAry
  397. * @param {Any} value The value to test.
  398. * @return {Boolean} true if 'value' is an array with at least 1 value, false otherwise.
  399. */
  400. is.nonEmptyArray = function(value) {
  401. return '[object Array]' === toString.call(value) && value.length > 0;
  402. };
  403. is.nonEmptyArr = is.nonEmptyArry = is.nonEmptyAry = is.nonEmptyArray;
  404. /**
  405. * Test if 'value' is an object with properties. Note: Arrays are objects.
  406. * Alias: nonEmptyObj
  407. * @param {Any} value to test.
  408. * @return {Boolean} true if 'value' is an object, false otherwise.
  409. */
  410. is.nonEmptyObject = function(value) {
  411. return '[object Object]' === toString.call(value) && Object.keys(value).length > 0;
  412. };
  413. is.nonEmptyObj = is.nonEmptyObject;
  414. /**
  415. * Test if 'value' is an object with no properties. Note: Arrays are objects.
  416. * Alias: nonEmptyObj
  417. * @param {Any} value to test.
  418. * @return {Boolean} true if 'value' is an object, false otherwise.
  419. */
  420. is.emptyObject = function(value) {
  421. return '[object Object]' === toString.call(value) && Object.keys(value).length === 0;
  422. };
  423. is.emptyObj = is.emptyObject;
  424. /**
  425. * Test if 'value' is a non-empty string.
  426. * Alias: nonEmptyStr
  427. * @param {Any} value to test.
  428. * @return {Boolean} true if 'value' is a non-empty string, false otherwise.
  429. */
  430. is.nonEmptyString = function(value) {
  431. return is.string(value) && value.length > 0;
  432. };
  433. is.nonEmptyStr = is.nonEmptyString;
  434. ////////////////////////////////////////////////////////////////////////////////
  435. // Numeric Types within Number
  436. /**
  437. * Test if 'value' is an even number.
  438. * @param {Number} value to test.
  439. * @return {Boolean} true if 'value' is an even number, false otherwise.
  440. */
  441. is.even = function(value) {
  442. return '[object Number]' === toString.call(value) && value % 2 === 0;
  443. };
  444. /**
  445. * Test if 'value' is a decimal number.
  446. * Aliases: decimalNumber, decNum
  447. * @param {Any} value value to test.
  448. * @return {Boolean} true if 'value' is a decimal number, false otherwise.
  449. */
  450. is.decimal = function(value) {
  451. return '[object Number]' === toString.call(value) && value % 1 !== 0;
  452. };
  453. is.dec = is.decNum = is.decimal;
  454. /**
  455. * Test if 'value' is an integer.
  456. * Alias: integer
  457. * @param {Any} value to test.
  458. * @return {Boolean} true if 'value' is an integer, false otherwise.
  459. */
  460. is.integer = function(value) {
  461. return '[object Number]' === toString.call(value) && value % 1 === 0;
  462. };
  463. is.int = is.integer;
  464. /**
  465. * is.nan
  466. * Test if `value` is not a number.
  467. *
  468. * @param {Mixed} value value to test
  469. * @return {Boolean} true if `value` is not a number, false otherwise
  470. * @api public
  471. */
  472. is.notANumber = function(value) {
  473. return !is.num(value) || value !== value;
  474. };
  475. is.nan = is.notANum = is.notANumber;
  476. /**
  477. * Test if 'value' is an odd number.
  478. * @param {Number} value to test.
  479. * @return {Boolean} true if 'value' is an odd number, false otherwise.
  480. */
  481. is.odd = function(value) {
  482. return !is.decimal(value) && '[object Number]' === toString.call(value) && value % 2 !== 0;
  483. };
  484. is.oddNumber = is.oddNum = is.odd;
  485. ////////////////////////////////////////////////////////////////////////////////
  486. // Numeric Type & State
  487. /**
  488. * Test if 'value' is a positive number.
  489. * Alias: positiveNum, posNum
  490. * @param {Any} value to test.
  491. * @return {Boolean} true if 'value' is a number, false otherwise.
  492. */
  493. is.positiveNumber = function(value) {
  494. return '[object Number]' === toString.call(value) && value > 0;
  495. };
  496. is.pos = is.positive = is.posNum = is.positiveNum = is.positiveNumber;
  497. /**
  498. * Test if 'value' is a negative number.
  499. * Aliases: negNum, negativeNum
  500. * @param {Any} value to test.
  501. * @return {Boolean} true if 'value' is a number, false otherwise.
  502. */
  503. is.negativeNumber = function(value) {
  504. return '[object Number]' === toString.call(value) && value < 0;
  505. };
  506. is.neg = is.negNum = is.negativeNum = is.negativeNumber;
  507. /**
  508. * Test if 'value' is a negative integer.
  509. * Aliases: negInt, negativeInteger
  510. * @param {Any} value to test.
  511. * @return {Boolean} true if 'value' is a negative integer, false otherwise.
  512. */
  513. is.negativeInteger = function(value) {
  514. return '[object Number]' === toString.call(value) && value % 1 === 0 && value < 0;
  515. };
  516. is.negativeInt = is.negInt = is.negativeInteger;
  517. /**
  518. * Test if 'value' is a positive integer.
  519. * Alias: posInt
  520. * @param {Any} value to test.
  521. * @return {Boolean} true if 'value' is a positive integer, false otherwise.
  522. */
  523. is.positiveInteger = function(value) {
  524. return '[object Number]' === toString.call(value) && value % 1 === 0 && value > 0;
  525. };
  526. is.posInt = is.positiveInt = is.positiveInteger;
  527. ////////////////////////////////////////////////////////////////////////////////
  528. // Numeric Relationships
  529. /**
  530. * Test if 'value' is divisible by 'n'.
  531. * Alias: divisBy
  532. * @param {Number} value value to test.
  533. * @param {Number} n dividend.
  534. * @return {Boolean} true if 'value' is divisible by 'n', false otherwise.
  535. */
  536. is.divisibleBy = function(value, n) {
  537. if (value === 0)
  538. return false;
  539. return '[object Number]' === toString.call(value) &&
  540. n !== 0 &&
  541. value % n === 0;
  542. };
  543. is.divBy = is.divisBy = is.divisibleBy;
  544. /**
  545. * Test if 'value' is greater than or equal to 'other'.
  546. * Aliases: greaterOrEq, greaterOrEqual
  547. * @param {Number} value value to test.
  548. * @param {Number} other value to compare with.
  549. * @return {Boolean} true, if value is greater than or equal to other, false otherwise.
  550. */
  551. is.greaterOrEqualTo = function(value, other) {
  552. return value >= other;
  553. };
  554. is.greaterOrEqual = is.ge = is.greaterOrEqualTo;
  555. /**
  556. * Test if 'value' is greater than 'other'.
  557. * Aliases: greaterThan
  558. * @param {Number} value value to test.
  559. * @param {Number} other value to compare with.
  560. * @return {Boolean} true, if value is greater than other, false otherwise.
  561. */
  562. is.greaterThan = function(value, other) {
  563. return value > other;
  564. };
  565. is.gt = is.greaterThan;
  566. /**
  567. * Test if 'value' is less than or equal to 'other'.
  568. * Alias: lessThanOrEq, lessThanOrEqual
  569. * @param {Number} value value to test
  570. * @param {Number} other value to compare with
  571. * @return {Boolean} true, if 'value' is less than or equal to 'other', false otherwise.
  572. */
  573. is.lessThanOrEqualTo = function(value, other) {
  574. return value <= other;
  575. };
  576. is.lessThanOrEq = is.lessThanOrEqual = is.le = is.lessThanOrEqualTo;
  577. /**
  578. * Test if 'value' is less than 'other'.
  579. * Alias: lessThan
  580. * @param {Number} value value to test
  581. * @param {Number} other value to compare with
  582. * @return {Boolean} true, if 'value' is less than 'other', false otherwise.
  583. */
  584. is.lessThan = function(value, other) {
  585. return value < other;
  586. };
  587. is.lt = is.lessThan;
  588. /**
  589. * Test if 'value' is greater than 'others' values.
  590. * Alias: max
  591. * @param {Number} value value to test.
  592. * @param {Array} others values to compare with.
  593. * @return {Boolean} true if 'value' is greater than 'others' values.
  594. */
  595. is.maximum = function(value, others) {
  596. if (!is.arrayLike(others) || !is.number(value))
  597. return false;
  598. var len = others.length;
  599. while (--len > -1) {
  600. if (value < others[len]) {
  601. return false;
  602. }
  603. }
  604. return true;
  605. };
  606. is.max = is.maximum;
  607. /**
  608. * Test if 'value' is less than 'others' values.
  609. * Alias: min
  610. * @param {Number} value value to test.
  611. * @param {Array} others values to compare with.
  612. * @return {Boolean} true if 'value' is less than 'others' values.
  613. */
  614. is.minimum = function(value, others) {
  615. if (!is.arrayLike(others) || !is.number(value))
  616. return false;
  617. var len = others.length;
  618. while (--len > -1) {
  619. if (value > others[len]) {
  620. return false;
  621. }
  622. }
  623. return true;
  624. };
  625. is.min = is.minimum;
  626. /**
  627. * Test if 'value' is within 'start' and 'finish'.
  628. * Alias: withIn
  629. * @param {Number} value value to test.
  630. * @param {Number} start lower bound.
  631. * @param {Number} finish upper bound.
  632. * @return {Boolean} true if 'value' is is within 'start' and 'finish', false otherwise.
  633. */
  634. is.within = function(value, start, finish) {
  635. return value >= start && value <= finish;
  636. };
  637. is.withIn = is.within;
  638. /**
  639. * Test if 'value' is within 'precision' decimal places from 'comparitor'.
  640. * Alias: closish, near.
  641. * @param {Number} value value to test
  642. * @param {Number} comparitor value to test 'value' against
  643. * @param {Number} precision number of decimals to compare floating points, defaults to 2
  644. * @return {Boolean} true if 'value' is within 'precision' decimal places from 'comparitor', false otherwise.
  645. */
  646. is.prettyClose = function(value, comparitor, precision) {
  647. if (!is.number(value) || !is.number(comparitor)) return false;
  648. if (is.defined(precision) && !is.posInt(precision)) return false;
  649. if (is.undefined(precision)) precision = 2;
  650. return value.toFixed(precision) === comparitor.toFixed(precision);
  651. };
  652. is.closish = is.near = is.prettyClose;
  653. ////////////////////////////////////////////////////////////////////////////////
  654. // Networking
  655. /**
  656. * Test if a value is a valid DNS address. eg www.stdarg.com is true while
  657. * 127.0.0.1 is false.
  658. * @param {Any} value to test if a DNS address.
  659. * @return {Boolean} true if a DNS address, false otherwise.
  660. * DNS Address is made up of labels separated by '.'
  661. * Each label must be between 1 and 63 characters long
  662. * The entire hostname (including the delimiting dots) has a maximum of 255 characters.
  663. * Hostname may not contain other characters, such as the underscore character (_)
  664. * other DNS names may contain the underscore.
  665. */
  666. is.dnsAddress = function(value) {
  667. if (!is.nonEmptyStr(value)) return false;
  668. if (value.length > 255) return false;
  669. if (numbersLabel.test(value)) return false;
  670. if (!dnsLabel.test(value)) return false;
  671. return true;
  672. //var names = value.split('.');
  673. //if (!is.array(names) || !names.length) return false;
  674. //if (names[0].indexOf('_') > -1) return false;
  675. //for (var i=0; i<names.length; i++) {
  676. //if (!dnsLabel.test(names[i])) return false;
  677. //}
  678. //return true;
  679. };
  680. is.dnsAddr = is.dns = is.dnsAddress;
  681. var dnsLabel = /^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$/;
  682. var numbersLabel = /^([0-9]|[0-9][0-9\-]{0,61}[0-9])(\.([0-9]|[0-9][0-9\-]{0,61}[0-9]))*$/;
  683. /**
  684. * Test if value is a valid email address.
  685. * @param {Any} value to test if an email address.
  686. * @return {Boolean} true if an email address, false otherwise.
  687. */
  688. is.emailAddress = function(value) {
  689. if (!is.nonEmptyStr(value))
  690. return false;
  691. return emailRegexp.test(value);
  692. };
  693. is.email = is.emailAddr = is.emailAddress;
  694. var emailRegexp = /^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*$/;
  695. /**
  696. * Test if a value is either an IPv4 numeric IP address.
  697. * The rules are:
  698. * must be a string
  699. * length must be 15 characters or less
  700. * There must be four octets separated by a '.'
  701. * No octet can be less than 0 or greater than 255.
  702. * @param {Any} value to test if an ip address.
  703. * @return {Boolean} true if an ip address, false otherwise.
  704. */
  705. is.ipv4Address = function(value) {
  706. if (!is.nonEmptyStr(value)) return false;
  707. if (value.length > 15) return false;
  708. var octets = value.split('.');
  709. if (!is.array(octets) || octets.length !== 4) return false;
  710. for (var i=0; i<octets.length; i++) {
  711. var val = parseInt(octets[i], 10);
  712. if (isNaN(val)) return false;
  713. if (val < 0 || val > 255) return false;
  714. }
  715. return true;
  716. };
  717. is.ipv4 = is.ipv4Addr = is.ipv4Address;
  718. /**
  719. * Test if a value is either an IPv6 numeric IP address.
  720. * @param {Any} value to test if an ip address.
  721. * @return {Boolean} true if an ip address, false otherwise.
  722. */
  723. is.ipv6Address = function(value) {
  724. if (!is.nonEmptyStr(value)) return false;
  725. return ipRegEx.v6({extract: true}).test(value);
  726. };
  727. is.ipv6 = is.ipv6Addr = is.ipv6Address;
  728. /**
  729. * Test if a value is either an IPv4 or IPv6 numeric IP address.
  730. * @param {Any} value to test if an ip address.
  731. * @return {Boolean} true if an ip address, false otherwise.
  732. */
  733. is.ipAddress = function(value) {
  734. if (!is.nonEmptyStr(value)) return false;
  735. return is.ipv4Address(value) || is.ipv6Address(value)
  736. };
  737. is.ip = is.ipAddr = is.ipAddress;
  738. /**
  739. * Test is a value is a valid ipv4, ipv6 or DNS name.
  740. * Aliases: host, hostAddr, hostAddress.
  741. * @param {Any} value to test if a host address.
  742. * @return {Boolean} true if a host address, false otherwise.
  743. */
  744. is.hostAddress = function(value) {
  745. if (!is.nonEmptyStr(value)) return false;
  746. return is.dns(value) || is.ipv4(value) || is.ipv6(value);
  747. };
  748. is.host = is.hostIp = is.hostAddr = is.hostAddress;
  749. /**
  750. * Test if a number is a valid TCP port
  751. * @param {Any} value to test if its a valid TCP port
  752. */
  753. is.port = function(value) {
  754. if (!is.num(value) || is.negativeInt(value) || value > 65535)
  755. return false;
  756. return true;
  757. };
  758. /**
  759. * Test if a number is a valid TCP port in the range 0-1023.
  760. * Alias: is.sysPort.
  761. * @param {Any} value to test if its a valid TCP port
  762. */
  763. is.systemPort = function(value) {
  764. if (is.port(value) && value < 1024)
  765. return true;
  766. return false;
  767. };
  768. is.sysPort = is.systemPort;
  769. /**
  770. * Test if a number is a valid TCP port in the range 1024-65535.
  771. * @param {Any} value to test if its a valid TCP port
  772. */
  773. is.userPort = function(value) {
  774. if (is.port(value) && value > 1023)
  775. return true;
  776. return false;
  777. };
  778. /*
  779. function sumDigits(num) {
  780. var str = num.toString();
  781. var sum = 0;
  782. for (var i = 0; i < str.length; i++)
  783. sum += (str[i]-0);
  784. return sum;
  785. }
  786. */
  787. /**
  788. * Test if a string is a credit card.
  789. * From http://en.wikipedia.org/wiki/Luhn_algorithm
  790. * @param {String} value to test if a credit card.
  791. * @return true if the string is the correct format, false otherwise
  792. */
  793. is.creditCardNumber = function(str) {
  794. if (!is.str(str))
  795. return false;
  796. var ary = str.split('');
  797. var i, cnt;
  798. // From the rightmost digit, which is the check digit, moving left, double
  799. // the value of every second digit;
  800. for (i=ary.length-1, cnt=1; i>-1; i--, cnt++) {
  801. if (cnt%2 === 0)
  802. ary[i] *= 2;
  803. }
  804. str = ary.join('');
  805. var sum = 0;
  806. // if the product of the previous doubling operation is greater than 9
  807. // (e.g., 7 * 2 = 14), then sum the digits of the products (e.g., 10: 1 + 0
  808. // = 1, 14: 1 + 4 = 5). We do the this by joining the array of numbers and
  809. // add adding the int value of all the characters in the string.
  810. for (i=0; i<str.length; i++)
  811. sum += Math.floor(str[i]);
  812. // If the total (sum) modulo 10 is equal to 0 (if the total ends in zero)
  813. // then the number is valid according to the Luhn formula; else it is not
  814. // valid.
  815. return sum % 10 === 0;
  816. };
  817. is.creditCard = is.creditCardNum = is.creditCardNumber;
  818. ////////////////////////////////////////////////////////////////////////////////
  819. // The following credit card info is from:
  820. // http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29
  821. /**
  822. * Test if card number is an American Express card.
  823. * @param {String} the credit card number string to test.
  824. * @return true if the string is the correct format, false otherwise
  825. */
  826. is.americanExpressCardNumber = function(str) {
  827. if (!is.str(str) || str.length !== 15)
  828. return false;
  829. var prefix = Math.floor(str.slice(0,2));
  830. if (prefix !== 34 && prefix !== 37)
  831. return false;
  832. if (!is.creditCardNumber(str))
  833. return false;
  834. return true;
  835. };
  836. is.amexCard = is.amexCardNum = is.americanExpressCardNumber;
  837. /**
  838. * Test if card number is a China UnionPay card.
  839. * @param {String} the credit card number string to test.
  840. * @return true if the string is the correct format, false otherwise
  841. */
  842. is.chinaUnionPayCardNumber = function(str) {
  843. if (!is.str(str) || (str.length < 16 && str.length > 19))
  844. return false;
  845. var prefix = Math.floor(str.slice(0,2));
  846. if (prefix !== 62 && prefix !== 88)
  847. return false;
  848. // no validation for this card
  849. return true;
  850. };
  851. is.chinaUnion = is.chinaUnionPayCard = is.chinaUnionPayCardNumber;
  852. /**
  853. * Test if card number is a Diner's Club Carte Blance card.
  854. * @param {String} the credit card number string to test.
  855. * @return true if the string is the correct format, false otherwise
  856. */
  857. is.dinersClubCarteBlancheCardNumber = function(str) {
  858. if (!is.str(str) || str.length !== 14)
  859. return false;
  860. var prefix = Math.floor(str.slice(0,3));
  861. if (prefix < 300 || prefix > 305)
  862. return false;
  863. if (!is.creditCardNumber(str))
  864. return false;
  865. return true;
  866. };
  867. is.dinersClubCB = is.dinersClubCarteBlancheCard =
  868. is.dinersClubCarteBlancheCardNumber;
  869. /**
  870. * Test if card number is a Diner's Club International card.
  871. * @param {String} the credit card number string to test.
  872. * @return true if the string is the correct format, false otherwise
  873. */
  874. is.dinersClubInternationalCardNumber = function(str) {
  875. if (!is.str(str) || str.length !== 14)
  876. return false;
  877. var prefix = Math.floor(str.slice(0,3));
  878. var prefix2 = Math.floor(str.slice(0,2));
  879. // 300-305, 309, 36, 38-39
  880. if ((prefix < 300 || prefix > 305) && prefix !== 309 && prefix2 !== 36 &&
  881. (prefix2 < 38 || prefix2 > 39)) {
  882. return false;
  883. }
  884. if (!is.creditCardNumber(str))
  885. return false;
  886. return true;
  887. };
  888. is.dinersClubInt = is.dinersClubInternationalCard =
  889. is.dinersClubInternationalCardNumber;
  890. /**
  891. * Test if card number is a Diner's Club USA & CA card.
  892. * @param {String} the credit card number string to test.
  893. * @return true if the string is the correct format, false otherwise
  894. */
  895. is.dinersClubUSACanadaCardNumber = function(str) {
  896. if (!is.str(str) || str.length !== 16)
  897. return false;
  898. var prefix = Math.floor(str.slice(0,2));
  899. if (prefix !== 54 && prefix !== 55)
  900. return false;
  901. if (!is.creditCardNumber(str))
  902. return false;
  903. return true;
  904. };
  905. is.dinersClub = is.dinersClubUSACanCard = is.dinersClubUSACanadaCardNumber;
  906. /**
  907. * Test if card number is a Diner's Club USA/CA card.
  908. * @param {String} the credit card number string to test.
  909. * @return true if the string is the correct format, false otherwise
  910. */
  911. is.discoverCardNumber = function(str) {
  912. if (!is.str(str) || str.length !== 16)
  913. return false;
  914. var prefix = Math.floor(str.slice(0,6));
  915. var prefix2 = Math.floor(str.slice(0,3));
  916. if (str.slice(0,4) !== '6011' && (prefix < 622126 || prefix > 622925) &&
  917. (prefix2 < 644 || prefix2 > 649) && str.slice(0,2) !== '65') {
  918. return false;
  919. }
  920. if (!is.creditCardNumber(str))
  921. return false;
  922. return true;
  923. };
  924. is.discover = is.discoverCard = is.discoverCardNumber;
  925. /**
  926. * Test if card number is an InstaPayment card number
  927. * @param {String} the credit card number string to test.
  928. * @return true if the string is the correct format, false otherwise
  929. */
  930. is.instaPaymentCardNumber = function(str) {
  931. if (!is.str(str) || str.length !== 16)
  932. return false;
  933. var prefix = Math.floor(str.slice(0,3));
  934. if (prefix < 637 || prefix > 639)
  935. return false;
  936. if (!is.creditCardNumber(str))
  937. return false;
  938. return true;
  939. };
  940. is.instaPayment = is.instaPaymentCardNumber;
  941. /**
  942. * Test if card number is a JCB card number
  943. * @param {String} the credit card number string to test.
  944. * @return true if the string is the correct format, false otherwise
  945. */
  946. is.jcbCardNumber = function(str) {
  947. if (!is.str(str) || str.length !== 16)
  948. return false;
  949. var prefix = Math.floor(str.slice(0,4));
  950. if (prefix < 3528 || prefix > 3589)
  951. return false;
  952. if (!is.creditCardNumber(str))
  953. return false;
  954. return true;
  955. };
  956. is.jcb = is.jcbCard = is.jcbCardNumber;
  957. /**
  958. * Test if card number is a Laser card number
  959. * @param {String} the credit card number string to test.
  960. * @return true if the string is the correct format, false otherwise
  961. */
  962. is.laserCardNumber = function(str) {
  963. if (!is.str(str) || (str.length < 16 && str.length > 19))
  964. return false;
  965. var prefix = Math.floor(str.slice(0,4));
  966. var valid = [ 6304, 6706, 6771, 6709 ];
  967. if (valid.indexOf(prefix) === -1)
  968. return false;
  969. if (!is.creditCardNumber(str))
  970. return false;
  971. return true;
  972. };
  973. is.laser = is.laserCard = is.laserCardNumber;
  974. /**
  975. * Test if card number is a Maestro card number
  976. * @param {String} the credit card number string to test.
  977. * @return true if the string is the correct format, false otherwise
  978. */
  979. is.maestroCardNumber = function(str) {
  980. if (!is.str(str) || str.length < 12 || str.length > 19)
  981. return false;
  982. var prefix = str.slice(0,4);
  983. var valid = [ '5018', '5020', '5038', '5612', '5893', '6304', '6759',
  984. '6761', '6762', '6763', '0604', '6390' ];
  985. if (valid.indexOf(prefix) === -1)
  986. return false;
  987. if (!is.creditCardNumber(str))
  988. return false;
  989. return true;
  990. };
  991. is.maestro = is.maestroCard = is.maestroCardNumber;
  992. /**
  993. * Test if card number is a Dankort card number
  994. * @param {String} the credit card number string to test.
  995. * @return true if the string is the correct format, false otherwise
  996. */
  997. is.dankortCardNumber = function(str) {
  998. if (!is.str(str) || str.length !== 16)
  999. return false;
  1000. if (str.slice(0,4) !== '5019')
  1001. return false;
  1002. if (!is.creditCardNumber(str))
  1003. return false;
  1004. return true;
  1005. };
  1006. is.dankort = is.dankortCard = is.dankortCardNumber;
  1007. /**
  1008. * Test if card number is a MasterCard card number
  1009. * @param {String} the credit card number string to test.
  1010. * @return true if the string is the correct format, false otherwise
  1011. */
  1012. is.masterCardCardNumber = function(str) {
  1013. if (!is.str(str) || str.length !== 16)
  1014. return false;
  1015. var prefix = Math.floor(str.slice(0,2));
  1016. if (prefix < 50 || prefix > 55)
  1017. return false;
  1018. if (!is.creditCardNumber(str))
  1019. return false;
  1020. return true;
  1021. };
  1022. is.masterCard = is.masterCardCard = is.masterCardCardNumber;
  1023. /**
  1024. * Test if card number is a Visa card number
  1025. * @param {String} the credit card number string to test.
  1026. * @return true if the string is the correct format, false otherwise
  1027. */
  1028. is.visaCardNumber = function(str) {
  1029. if (!is.str(str) || (str.length !== 13 && str.length !== 16))
  1030. return false;
  1031. if ('4' !== str.slice(0,1))
  1032. return false;
  1033. if (!is.creditCardNumber(str))
  1034. return false;
  1035. return true;
  1036. };
  1037. is.visa = is.visaCard = is.visaCardNumber;
  1038. /**
  1039. * Test if card number is a Visa card number
  1040. * @param {String} the credit card number string to test.
  1041. * @return true if the string is the correct format, false otherwise
  1042. */
  1043. is.visaElectronCardNumber = function(str) {
  1044. if (!is.str(str) || str.length !== 16)
  1045. return false;
  1046. var prefix = Math.floor(str.slice(0,4));
  1047. var valid = [ 4026, 4405, 4508, 4844, 4913, 4917 ];
  1048. if ('417500' !== str.slice(0,6) && valid.indexOf(prefix) === -1)
  1049. return false;
  1050. if (!is.creditCardNumber(str))
  1051. return false;
  1052. return false;
  1053. };
  1054. is.visaElectron = is.visaElectronCard = is.visaElectronCardNumber;
  1055. /**
  1056. * Test if the input is a valid MongoDB id.
  1057. * @param {String|Object} Either a mongodb object id or a string representation.
  1058. * @return true if the string is the correct format, false otherwise
  1059. * Thanks to Jason Denizac (https://github.com/jden) for pointing this out.
  1060. * https://github.com/jden/objectid/blob/master/index.js#L7-L10
  1061. */
  1062. var objIdPattern = /^[0-9a-fA-F]{24}$/;
  1063. is.mongoId = is.objectId = is.objId = function(id) {
  1064. return (Boolean(id) && !Array.isArray(id) && objIdPattern.test(String(id)));
  1065. };
  1066. /**
  1067. * Test is the first argument is structly equal to any of the subsequent args.
  1068. * @param Value to test against subsequent arguments.
  1069. * @return true if the first value matches any of subsequent values.
  1070. */
  1071. is.matching = is.match = is.inArgs = function(val) {
  1072. if (arguments.length < 2)
  1073. return false;
  1074. var result = false;
  1075. for (var i=1; i<arguments.length; i++) {
  1076. var eq = is.equal(val, arguments[i]);
  1077. result = result || eq;
  1078. }
  1079. return result;
  1080. };
  1081. // US Address components
  1082. /**********************************
  1083. ***Definitely a work in progress***
  1084. **********************************/
  1085. /**
  1086. * Test if a string contains a US street address
  1087. * @param {String} the string to search
  1088. * @return true if an address is present, false otherwise
  1089. */
  1090. is.streetAddress = function(str) {
  1091. if (!is.str(str))
  1092. return false;
  1093. var regex = /\b\d+[\s](?:[A-Za-z0-9.-]+[\s]+)+\b(ALLEY|ALY|AVENUE|AVE|BEND|BND|BLUFFS?|BLFS?|BOULEVARD|BLVD|BRANCH|BR|CENTERS?|CTRS?|CIRCLES?|CIRS?|CLIFFS?|CLFS?|COURTS?|CTS?|COVES?|CVS?|CREEK|CRK|CRESCENT|CRES|CREST|CRST|CROSSING|XING|DRIVES?|DRS?|EXPRESSWAY|EXPY|FREEWAY|FWY|HEIGHTS|HTS|HIGHWAY|HWY|HILLS?|HLS?|LANE|LN|LOOP|MANORS?|MNRS?|MOTORWAY|MTWY|MOUNT|MT|PARKS?|PARKWAYS?|PKWY|PASS|PLACE|PL|PLAZA|PLZ|POINTS?|PTS?|RIDGES?|RDGS?|ROADS?|RDS?|ROUTE|RTE?|SHOALS?|SHLS?|SHORES?|SHRS?|SPRINGS?|SPGS?|SPURS?|STREETS?|STS?|SUMMIT|SMT|TERRACE|TER|THROUGHWAY|TRWY|TRAFFICWAY|TRFY|TRAIL|TRL|TURNPIKE|TPKE|VALLEYS?|VLYS?|WAYS?)+(?:[\.\-\s\,]?)*((APARTMENT|APT|APPT|#|NUMBER|NUM|FLOOR|FL|\s)?(\d)*)\b/ig;
  1094. return regex.test(str);
  1095. };
  1096. is.street = is.address = is.streetAddress;
  1097. /**
  1098. * Test if a string resembles a US Zip code,
  1099. * no regular expression will be perfect for this,
  1100. * as there are many numbers that aren't valid zip codes
  1101. * @param {String || Number} the string or number literal to test
  1102. * @return true if zipcode like, false otherwise
  1103. */
  1104. is.zipCode = function(str) {
  1105. if (is.undefined(str) || !(is.string(str) || is.number(str)))
  1106. return false;
  1107. var zip = /^\d{5}(?:-\d{4})?$/;
  1108. return zip.test(str);
  1109. };
  1110. is.zip = is.zipCode;
  1111. /**
  1112. * Test if a string contains a US phone number
  1113. * @param {String} the string to search
  1114. * @return true if str contains a phone number, false otherwise.
  1115. */
  1116. is.phoneNumber = function(str){
  1117. if (!is.string(str))
  1118. return false;
  1119. var nums = /(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:(\(?)(?:(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]‌​)\s*)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\)?)\s*(?:[.-]\s*)?)?([2-9]1[02-‌​9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})/g;
  1120. return nums.test(str);
  1121. };
  1122. is.phone = is.phoneNumber;
  1123. /**
  1124. * Test is a string is a valid URL
  1125. * @param {string} val - the possible url to check
  1126. * @return true if str contains a phone number, false otherwise.
  1127. */
  1128. var isUrl = require('is-url');
  1129. is.url = function(val) {
  1130. return isUrl(val);
  1131. };
  1132. is.uri = is.url;
  1133. is.enumerator = function(val, ary){
  1134. var value = false;
  1135. if (!is.defined(val) || !is.defined(ary) || !is.arrayLike(ary))
  1136. return value;
  1137. for (var i = 0, len = ary.length; i < len; i++) {
  1138. if (is.equal(val, ary[i])) {
  1139. value = true;
  1140. break;
  1141. }
  1142. }
  1143. return value;
  1144. };
  1145. is.enum = is.inArray = is.enumerator;