validator.js 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. /*!
  2. * Copyright (c) 2016 Chris O'Hara <cohara87@gmail.com>
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to
  9. * permit persons to whom the Software is furnished to do so, subject to
  10. * the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  19. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  20. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  21. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. (function (global, factory) {
  24. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  25. typeof define === 'function' && define.amd ? define(factory) :
  26. (global.validator = factory());
  27. }(this, function () { 'use strict';
  28. function assertString(input) {
  29. if (typeof input !== 'string') {
  30. throw new TypeError('This library (validator.js) validates strings only');
  31. }
  32. }
  33. function toDate(date) {
  34. assertString(date);
  35. date = Date.parse(date);
  36. return !isNaN(date) ? new Date(date) : null;
  37. }
  38. function toFloat(str) {
  39. assertString(str);
  40. return parseFloat(str);
  41. }
  42. function toInt(str, radix) {
  43. assertString(str);
  44. return parseInt(str, radix || 10);
  45. }
  46. function toBoolean(str, strict) {
  47. assertString(str);
  48. if (strict) {
  49. return str === '1' || str === 'true';
  50. }
  51. return str !== '0' && str !== 'false' && str !== '';
  52. }
  53. function equals(str, comparison) {
  54. assertString(str);
  55. return str === comparison;
  56. }
  57. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  58. return typeof obj;
  59. } : function (obj) {
  60. return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;
  61. };
  62. function toString(input) {
  63. if ((typeof input === 'undefined' ? 'undefined' : _typeof(input)) === 'object' && input !== null) {
  64. if (typeof input.toString === 'function') {
  65. input = input.toString();
  66. } else {
  67. input = '[object Object]';
  68. }
  69. } else if (input === null || typeof input === 'undefined' || isNaN(input) && !input.length) {
  70. input = '';
  71. }
  72. return String(input);
  73. }
  74. function contains(str, elem) {
  75. assertString(str);
  76. return str.indexOf(toString(elem)) >= 0;
  77. }
  78. function matches(str, pattern, modifiers) {
  79. assertString(str);
  80. if (Object.prototype.toString.call(pattern) !== '[object RegExp]') {
  81. pattern = new RegExp(pattern, modifiers);
  82. }
  83. return pattern.test(str);
  84. }
  85. function merge() {
  86. var obj = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  87. var defaults = arguments[1];
  88. for (var key in defaults) {
  89. if (typeof obj[key] === 'undefined') {
  90. obj[key] = defaults[key];
  91. }
  92. }
  93. return obj;
  94. }
  95. /* eslint-disable prefer-rest-params */
  96. function isByteLength(str, options) {
  97. assertString(str);
  98. var min = void 0;
  99. var max = void 0;
  100. if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') {
  101. min = options.min || 0;
  102. max = options.max;
  103. } else {
  104. // backwards compatibility: isByteLength(str, min [, max])
  105. min = arguments[1];
  106. max = arguments[2];
  107. }
  108. var len = encodeURI(str).split(/%..|./).length - 1;
  109. return len >= min && (typeof max === 'undefined' || len <= max);
  110. }
  111. var default_fqdn_options = {
  112. require_tld: true,
  113. allow_underscores: false,
  114. allow_trailing_dot: false
  115. };
  116. function isFDQN(str, options) {
  117. assertString(str);
  118. options = merge(options, default_fqdn_options);
  119. /* Remove the optional trailing dot before checking validity */
  120. if (options.allow_trailing_dot && str[str.length - 1] === '.') {
  121. str = str.substring(0, str.length - 1);
  122. }
  123. var parts = str.split('.');
  124. if (options.require_tld) {
  125. var tld = parts.pop();
  126. if (!parts.length || !/^([a-z\u00a1-\uffff]{2,}|xn[a-z0-9-]{2,})$/i.test(tld)) {
  127. return false;
  128. }
  129. }
  130. for (var part, i = 0; i < parts.length; i++) {
  131. part = parts[i];
  132. if (options.allow_underscores) {
  133. part = part.replace(/_/g, '');
  134. }
  135. if (!/^[a-z\u00a1-\uffff0-9-]+$/i.test(part)) {
  136. return false;
  137. }
  138. if (/[\uff01-\uff5e]/.test(part)) {
  139. // disallow full-width chars
  140. return false;
  141. }
  142. if (part[0] === '-' || part[part.length - 1] === '-') {
  143. return false;
  144. }
  145. }
  146. return true;
  147. }
  148. var default_email_options = {
  149. allow_display_name: false,
  150. allow_utf8_local_part: true,
  151. require_tld: true
  152. };
  153. /* eslint-disable max-len */
  154. /* eslint-disable no-control-regex */
  155. var displayName = /^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\.\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\.\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF\s]*<(.+)>$/i;
  156. var emailUserPart = /^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~]+$/i;
  157. var quotedEmailUser = /^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f]))*$/i;
  158. var emailUserUtf8Part = /^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+$/i;
  159. var quotedEmailUserUtf8 = /^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*$/i;
  160. /* eslint-enable max-len */
  161. /* eslint-enable no-control-regex */
  162. function isEmail(str, options) {
  163. assertString(str);
  164. options = merge(options, default_email_options);
  165. if (options.allow_display_name) {
  166. var display_email = str.match(displayName);
  167. if (display_email) {
  168. str = display_email[1];
  169. }
  170. }
  171. var parts = str.split('@');
  172. var domain = parts.pop();
  173. var user = parts.join('@');
  174. var lower_domain = domain.toLowerCase();
  175. if (lower_domain === 'gmail.com' || lower_domain === 'googlemail.com') {
  176. user = user.replace(/\./g, '').toLowerCase();
  177. }
  178. if (!isByteLength(user, { max: 64 }) || !isByteLength(domain, { max: 256 })) {
  179. return false;
  180. }
  181. if (!isFDQN(domain, { require_tld: options.require_tld })) {
  182. return false;
  183. }
  184. if (user[0] === '"') {
  185. user = user.slice(1, user.length - 1);
  186. return options.allow_utf8_local_part ? quotedEmailUserUtf8.test(user) : quotedEmailUser.test(user);
  187. }
  188. var pattern = options.allow_utf8_local_part ? emailUserUtf8Part : emailUserPart;
  189. var user_parts = user.split('.');
  190. for (var i = 0; i < user_parts.length; i++) {
  191. if (!pattern.test(user_parts[i])) {
  192. return false;
  193. }
  194. }
  195. return true;
  196. }
  197. var ipv4Maybe = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
  198. var ipv6Block = /^[0-9A-F]{1,4}$/i;
  199. function isIP(str) {
  200. var version = arguments.length <= 1 || arguments[1] === undefined ? '' : arguments[1];
  201. assertString(str);
  202. version = String(version);
  203. if (!version) {
  204. return isIP(str, 4) || isIP(str, 6);
  205. } else if (version === '4') {
  206. if (!ipv4Maybe.test(str)) {
  207. return false;
  208. }
  209. var parts = str.split('.').sort(function (a, b) {
  210. return a - b;
  211. });
  212. return parts[3] <= 255;
  213. } else if (version === '6') {
  214. var blocks = str.split(':');
  215. var foundOmissionBlock = false; // marker to indicate ::
  216. // At least some OS accept the last 32 bits of an IPv6 address
  217. // (i.e. 2 of the blocks) in IPv4 notation, and RFC 3493 says
  218. // that '::ffff:a.b.c.d' is valid for IPv4-mapped IPv6 addresses,
  219. // and '::a.b.c.d' is deprecated, but also valid.
  220. var foundIPv4TransitionBlock = isIP(blocks[blocks.length - 1], 4);
  221. var expectedNumberOfBlocks = foundIPv4TransitionBlock ? 7 : 8;
  222. if (blocks.length > expectedNumberOfBlocks) {
  223. return false;
  224. }
  225. // initial or final ::
  226. if (str === '::') {
  227. return true;
  228. } else if (str.substr(0, 2) === '::') {
  229. blocks.shift();
  230. blocks.shift();
  231. foundOmissionBlock = true;
  232. } else if (str.substr(str.length - 2) === '::') {
  233. blocks.pop();
  234. blocks.pop();
  235. foundOmissionBlock = true;
  236. }
  237. for (var i = 0; i < blocks.length; ++i) {
  238. // test for a :: which can not be at the string start/end
  239. // since those cases have been handled above
  240. if (blocks[i] === '' && i > 0 && i < blocks.length - 1) {
  241. if (foundOmissionBlock) {
  242. return false; // multiple :: in address
  243. }
  244. foundOmissionBlock = true;
  245. } else if (foundIPv4TransitionBlock && i === blocks.length - 1) {
  246. // it has been checked before that the last
  247. // block is a valid IPv4 address
  248. } else if (!ipv6Block.test(blocks[i])) {
  249. return false;
  250. }
  251. }
  252. if (foundOmissionBlock) {
  253. return blocks.length >= 1;
  254. }
  255. return blocks.length === expectedNumberOfBlocks;
  256. }
  257. return false;
  258. }
  259. var default_url_options = {
  260. protocols: ['http', 'https', 'ftp'],
  261. require_tld: true,
  262. require_protocol: false,
  263. require_host: true,
  264. require_valid_protocol: true,
  265. allow_underscores: false,
  266. allow_trailing_dot: false,
  267. allow_protocol_relative_urls: false
  268. };
  269. var wrapped_ipv6 = /^\[([^\]]+)\](?::([0-9]+))?$/;
  270. function isRegExp(obj) {
  271. return Object.prototype.toString.call(obj) === '[object RegExp]';
  272. }
  273. function checkHost(host, matches) {
  274. for (var i = 0; i < matches.length; i++) {
  275. var match = matches[i];
  276. if (host === match || isRegExp(match) && match.test(host)) {
  277. return true;
  278. }
  279. }
  280. return false;
  281. }
  282. function isURL(url, options) {
  283. assertString(url);
  284. if (!url || url.length >= 2083 || /\s/.test(url)) {
  285. return false;
  286. }
  287. if (url.indexOf('mailto:') === 0) {
  288. return false;
  289. }
  290. options = merge(options, default_url_options);
  291. var protocol = void 0,
  292. auth = void 0,
  293. host = void 0,
  294. hostname = void 0,
  295. port = void 0,
  296. port_str = void 0,
  297. split = void 0,
  298. ipv6 = void 0;
  299. split = url.split('#');
  300. url = split.shift();
  301. split = url.split('?');
  302. url = split.shift();
  303. split = url.split('://');
  304. if (split.length > 1) {
  305. protocol = split.shift();
  306. if (options.require_valid_protocol && options.protocols.indexOf(protocol) === -1) {
  307. return false;
  308. }
  309. } else if (options.require_protocol) {
  310. return false;
  311. } else if (options.allow_protocol_relative_urls && url.substr(0, 2) === '//') {
  312. split[0] = url.substr(2);
  313. }
  314. url = split.join('://');
  315. split = url.split('/');
  316. url = split.shift();
  317. if (url === '' && !options.require_host) {
  318. return true;
  319. }
  320. split = url.split('@');
  321. if (split.length > 1) {
  322. auth = split.shift();
  323. if (auth.indexOf(':') >= 0 && auth.split(':').length > 2) {
  324. return false;
  325. }
  326. }
  327. hostname = split.join('@');
  328. port_str = ipv6 = null;
  329. var ipv6_match = hostname.match(wrapped_ipv6);
  330. if (ipv6_match) {
  331. host = '';
  332. ipv6 = ipv6_match[1];
  333. port_str = ipv6_match[2] || null;
  334. } else {
  335. split = hostname.split(':');
  336. host = split.shift();
  337. if (split.length) {
  338. port_str = split.join(':');
  339. }
  340. }
  341. if (port_str !== null) {
  342. port = parseInt(port_str, 10);
  343. if (!/^[0-9]+$/.test(port_str) || port <= 0 || port > 65535) {
  344. return false;
  345. }
  346. }
  347. if (!isIP(host) && !isFDQN(host, options) && (!ipv6 || !isIP(ipv6, 6)) && host !== 'localhost') {
  348. return false;
  349. }
  350. host = host || ipv6;
  351. if (options.host_whitelist && !checkHost(host, options.host_whitelist)) {
  352. return false;
  353. }
  354. if (options.host_blacklist && checkHost(host, options.host_blacklist)) {
  355. return false;
  356. }
  357. return true;
  358. }
  359. var macAddress = /^([0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])$/;
  360. function isMACAddress(str) {
  361. assertString(str);
  362. return macAddress.test(str);
  363. }
  364. function isBoolean(str) {
  365. assertString(str);
  366. return ['true', 'false', '1', '0'].indexOf(str) >= 0;
  367. }
  368. var alpha = {
  369. 'en-US': /^[A-Z]+$/i,
  370. 'cs-CZ': /^[A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]+$/i,
  371. 'de-DE': /^[A-ZÄÖÜß]+$/i,
  372. 'es-ES': /^[A-ZÁÉÍÑÓÚÜ]+$/i,
  373. 'fr-FR': /^[A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ]+$/i,
  374. 'nl-NL': /^[A-ZÉËÏÓÖÜ]+$/i,
  375. 'hu-HU': /^[A-ZÁÉÍÓÖŐÚÜŰ]+$/i,
  376. 'pl-PL': /^[A-ZĄĆĘŚŁŃÓŻŹ]+$/i,
  377. 'pt-PT': /^[A-ZÃÁÀÂÇÉÊÍÕÓÔÚÜ]+$/i,
  378. 'ru-RU': /^[А-ЯЁ]+$/i,
  379. 'sr-RS@latin': /^[A-ZČĆŽŠĐ]+$/i,
  380. 'sr-RS': /^[А-ЯЂЈЉЊЋЏ]+$/i,
  381. 'tr-TR': /^[A-ZÇĞİıÖŞÜ]+$/i,
  382. ar: /^[ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]+$/
  383. };
  384. var alphanumeric = {
  385. 'en-US': /^[0-9A-Z]+$/i,
  386. 'cs-CZ': /^[0-9A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]+$/i,
  387. 'de-DE': /^[0-9A-ZÄÖÜß]+$/i,
  388. 'es-ES': /^[0-9A-ZÁÉÍÑÓÚÜ]+$/i,
  389. 'fr-FR': /^[0-9A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ]+$/i,
  390. 'hu-HU': /^[0-9A-ZÁÉÍÓÖŐÚÜŰ]+$/i,
  391. 'nl-NL': /^[0-9A-ZÉËÏÓÖÜ]+$/i,
  392. 'pl-PL': /^[0-9A-ZĄĆĘŚŁŃÓŻŹ]+$/i,
  393. 'pt-PT': /^[0-9A-ZÃÁÀÂÇÉÊÍÕÓÔÚÜ]+$/i,
  394. 'ru-RU': /^[0-9А-ЯЁ]+$/i,
  395. 'sr-RS@latin': /^[0-9A-ZČĆŽŠĐ]+$/i,
  396. 'sr-RS': /^[0-9А-ЯЂЈЉЊЋЏ]+$/i,
  397. 'tr-TR': /^[0-9A-ZÇĞİıÖŞÜ]+$/i,
  398. ar: /^[٠١٢٣٤٥٦٧٨٩0-9ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]+$/
  399. };
  400. var englishLocales = ['AU', 'GB', 'HK', 'IN', 'NZ', 'ZA', 'ZM'];
  401. for (var locale, i = 0; i < englishLocales.length; i++) {
  402. locale = 'en-' + englishLocales[i];
  403. alpha[locale] = alpha['en-US'];
  404. alphanumeric[locale] = alphanumeric['en-US'];
  405. }
  406. alpha['pt-BR'] = alpha['pt-PT'];
  407. alphanumeric['pt-BR'] = alphanumeric['pt-PT'];
  408. // Source: http://www.localeplanet.com/java/
  409. var arabicLocales = ['AE', 'BH', 'DZ', 'EG', 'IQ', 'JO', 'KW', 'LB', 'LY', 'MA', 'QM', 'QA', 'SA', 'SD', 'SY', 'TN', 'YE'];
  410. for (var _locale, _i = 0; _i < arabicLocales.length; _i++) {
  411. _locale = 'ar-' + arabicLocales[_i];
  412. alpha[_locale] = alpha.ar;
  413. alphanumeric[_locale] = alphanumeric.ar;
  414. }
  415. function isAlpha(str) {
  416. var locale = arguments.length <= 1 || arguments[1] === undefined ? 'en-US' : arguments[1];
  417. assertString(str);
  418. if (locale in alpha) {
  419. return alpha[locale].test(str);
  420. }
  421. throw new Error('Invalid locale \'' + locale + '\'');
  422. }
  423. function isAlphanumeric(str) {
  424. var locale = arguments.length <= 1 || arguments[1] === undefined ? 'en-US' : arguments[1];
  425. assertString(str);
  426. if (locale in alphanumeric) {
  427. return alphanumeric[locale].test(str);
  428. }
  429. throw new Error('Invalid locale \'' + locale + '\'');
  430. }
  431. var numeric = /^[-+]?[0-9]+$/;
  432. function isNumeric(str) {
  433. assertString(str);
  434. return numeric.test(str);
  435. }
  436. function isLowercase(str) {
  437. assertString(str);
  438. return str === str.toLowerCase();
  439. }
  440. function isUppercase(str) {
  441. assertString(str);
  442. return str === str.toUpperCase();
  443. }
  444. /* eslint-disable no-control-regex */
  445. var ascii = /^[\x00-\x7F]+$/;
  446. /* eslint-enable no-control-regex */
  447. function isAscii(str) {
  448. assertString(str);
  449. return ascii.test(str);
  450. }
  451. var fullWidth = /[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;
  452. function isFullWidth(str) {
  453. assertString(str);
  454. return fullWidth.test(str);
  455. }
  456. var halfWidth = /[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;
  457. function isHalfWidth(str) {
  458. assertString(str);
  459. return halfWidth.test(str);
  460. }
  461. function isVariableWidth(str) {
  462. assertString(str);
  463. return fullWidth.test(str) && halfWidth.test(str);
  464. }
  465. /* eslint-disable no-control-regex */
  466. var multibyte = /[^\x00-\x7F]/;
  467. /* eslint-enable no-control-regex */
  468. function isMultibyte(str) {
  469. assertString(str);
  470. return multibyte.test(str);
  471. }
  472. var surrogatePair = /[\uD800-\uDBFF][\uDC00-\uDFFF]/;
  473. function isSurrogatePair(str) {
  474. assertString(str);
  475. return surrogatePair.test(str);
  476. }
  477. var int = /^(?:[-+]?(?:0|[1-9][0-9]*))$/;
  478. var intLeadingZeroes = /^[-+]?[0-9]+$/;
  479. function isInt(str, options) {
  480. assertString(str);
  481. options = options || {};
  482. // Get the regex to use for testing, based on whether
  483. // leading zeroes are allowed or not.
  484. var regex = options.hasOwnProperty('allow_leading_zeroes') && options.allow_leading_zeroes ? intLeadingZeroes : int;
  485. // Check min/max
  486. var minCheckPassed = !options.hasOwnProperty('min') || str >= options.min;
  487. var maxCheckPassed = !options.hasOwnProperty('max') || str <= options.max;
  488. return regex.test(str) && minCheckPassed && maxCheckPassed;
  489. }
  490. var float = /^(?:[-+]?(?:[0-9]+))?(?:\.[0-9]*)?(?:[eE][\+\-]?(?:[0-9]+))?$/;
  491. function isFloat(str, options) {
  492. assertString(str);
  493. options = options || {};
  494. if (str === '' || str === '.') {
  495. return false;
  496. }
  497. return float.test(str) && (!options.hasOwnProperty('min') || str >= options.min) && (!options.hasOwnProperty('max') || str <= options.max);
  498. }
  499. var decimal = /^[-+]?([0-9]+|\.[0-9]+|[0-9]+\.[0-9]+)$/;
  500. function isDecimal(str) {
  501. assertString(str);
  502. return str !== '' && decimal.test(str);
  503. }
  504. var hexadecimal = /^[0-9A-F]+$/i;
  505. function isHexadecimal(str) {
  506. assertString(str);
  507. return hexadecimal.test(str);
  508. }
  509. function isDivisibleBy(str, num) {
  510. assertString(str);
  511. return toFloat(str) % parseInt(num, 10) === 0;
  512. }
  513. var hexcolor = /^#?([0-9A-F]{3}|[0-9A-F]{6})$/i;
  514. function isHexColor(str) {
  515. assertString(str);
  516. return hexcolor.test(str);
  517. }
  518. var md5 = /^[a-f0-9]{32}$/;
  519. function isMD5(str) {
  520. assertString(str);
  521. return md5.test(str);
  522. }
  523. function isJSON(str) {
  524. assertString(str);
  525. try {
  526. var obj = JSON.parse(str);
  527. return !!obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object';
  528. } catch (e) {/* ignore */}
  529. return false;
  530. }
  531. function isNull(str) {
  532. assertString(str);
  533. return str.length === 0;
  534. }
  535. /* eslint-disable prefer-rest-params */
  536. function isLength(str, options) {
  537. assertString(str);
  538. var min = void 0;
  539. var max = void 0;
  540. if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') {
  541. min = options.min || 0;
  542. max = options.max;
  543. } else {
  544. // backwards compatibility: isLength(str, min [, max])
  545. min = arguments[1];
  546. max = arguments[2];
  547. }
  548. var surrogatePairs = str.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g) || [];
  549. var len = str.length - surrogatePairs.length;
  550. return len >= min && (typeof max === 'undefined' || len <= max);
  551. }
  552. var uuid = {
  553. 3: /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
  554. 4: /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
  555. 5: /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
  556. all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i
  557. };
  558. function isUUID(str) {
  559. var version = arguments.length <= 1 || arguments[1] === undefined ? 'all' : arguments[1];
  560. assertString(str);
  561. var pattern = uuid[version];
  562. return pattern && pattern.test(str);
  563. }
  564. function isMongoId(str) {
  565. assertString(str);
  566. return isHexadecimal(str) && str.length === 24;
  567. }
  568. /* eslint-disable max-len */
  569. // from http://goo.gl/0ejHHW
  570. var iso8601 = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
  571. /* eslint-enable max-len */
  572. function isISO8601 (str) {
  573. assertString(str);
  574. return iso8601.test(str);
  575. }
  576. function getTimezoneOffset(str) {
  577. var iso8601Parts = str.match(iso8601);
  578. var timezone = void 0,
  579. sign = void 0,
  580. hours = void 0,
  581. minutes = void 0;
  582. if (!iso8601Parts) {
  583. str = str.toLowerCase();
  584. timezone = str.match(/(?:\s|gmt\s*)(-|\+)(\d{1,4})(\s|$)/);
  585. if (!timezone) {
  586. return str.indexOf('gmt') !== -1 ? 0 : null;
  587. }
  588. sign = timezone[1];
  589. var offset = timezone[2];
  590. if (offset.length === 3) {
  591. offset = '0' + offset;
  592. }
  593. if (offset.length <= 2) {
  594. hours = 0;
  595. minutes = parseInt(offset, 10);
  596. } else {
  597. hours = parseInt(offset.slice(0, 2), 10);
  598. minutes = parseInt(offset.slice(2, 4), 10);
  599. }
  600. } else {
  601. timezone = iso8601Parts[21];
  602. if (!timezone) {
  603. // if no hour/minute was provided, the date is GMT
  604. return !iso8601Parts[12] ? 0 : null;
  605. }
  606. if (timezone === 'z' || timezone === 'Z') {
  607. return 0;
  608. }
  609. sign = iso8601Parts[22];
  610. if (timezone.indexOf(':') !== -1) {
  611. hours = parseInt(iso8601Parts[23], 10);
  612. minutes = parseInt(iso8601Parts[24], 10);
  613. } else {
  614. hours = 0;
  615. minutes = parseInt(iso8601Parts[23], 10);
  616. }
  617. }
  618. return (hours * 60 + minutes) * (sign === '-' ? 1 : -1);
  619. }
  620. function isDate(str) {
  621. assertString(str);
  622. var normalizedDate = new Date(Date.parse(str));
  623. if (isNaN(normalizedDate)) {
  624. return false;
  625. }
  626. // normalizedDate is in the user's timezone. Apply the input
  627. // timezone offset to the date so that the year and day match
  628. // the input
  629. var timezoneOffset = getTimezoneOffset(str);
  630. if (timezoneOffset !== null) {
  631. var timezoneDifference = normalizedDate.getTimezoneOffset() - timezoneOffset;
  632. normalizedDate = new Date(normalizedDate.getTime() + 60000 * timezoneDifference);
  633. }
  634. var day = String(normalizedDate.getDate());
  635. var dayOrYear = void 0,
  636. dayOrYearMatches = void 0,
  637. year = void 0;
  638. // check for valid double digits that could be late days
  639. // check for all matches since a string like '12/23' is a valid date
  640. // ignore everything with nearby colons
  641. dayOrYearMatches = str.match(/(^|[^:\d])[23]\d([^T:\d]|$)/g);
  642. if (!dayOrYearMatches) {
  643. return true;
  644. }
  645. dayOrYear = dayOrYearMatches.map(function (digitString) {
  646. return digitString.match(/\d+/g)[0];
  647. }).join('/');
  648. year = String(normalizedDate.getFullYear()).slice(-2);
  649. if (dayOrYear === day || dayOrYear === year) {
  650. return true;
  651. } else if (dayOrYear === '' + day / year || dayOrYear === '' + year / day) {
  652. return true;
  653. }
  654. return false;
  655. }
  656. function isAfter(str) {
  657. var date = arguments.length <= 1 || arguments[1] === undefined ? String(new Date()) : arguments[1];
  658. assertString(str);
  659. var comparison = toDate(date);
  660. var original = toDate(str);
  661. return !!(original && comparison && original > comparison);
  662. }
  663. function isBefore(str) {
  664. var date = arguments.length <= 1 || arguments[1] === undefined ? String(new Date()) : arguments[1];
  665. assertString(str);
  666. var comparison = toDate(date);
  667. var original = toDate(str);
  668. return !!(original && comparison && original < comparison);
  669. }
  670. function isIn(str, options) {
  671. assertString(str);
  672. var i = void 0;
  673. if (Object.prototype.toString.call(options) === '[object Array]') {
  674. var array = [];
  675. for (i in options) {
  676. if ({}.hasOwnProperty.call(options, i)) {
  677. array[i] = toString(options[i]);
  678. }
  679. }
  680. return array.indexOf(str) >= 0;
  681. } else if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') {
  682. return options.hasOwnProperty(str);
  683. } else if (options && typeof options.indexOf === 'function') {
  684. return options.indexOf(str) >= 0;
  685. }
  686. return false;
  687. }
  688. /* eslint-disable max-len */
  689. var creditCard = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})|62[0-9]{14}$/;
  690. /* eslint-enable max-len */
  691. function isCreditCard(str) {
  692. assertString(str);
  693. var sanitized = str.replace(/[^0-9]+/g, '');
  694. if (!creditCard.test(sanitized)) {
  695. return false;
  696. }
  697. var sum = 0;
  698. var digit = void 0;
  699. var tmpNum = void 0;
  700. var shouldDouble = void 0;
  701. for (var i = sanitized.length - 1; i >= 0; i--) {
  702. digit = sanitized.substring(i, i + 1);
  703. tmpNum = parseInt(digit, 10);
  704. if (shouldDouble) {
  705. tmpNum *= 2;
  706. if (tmpNum >= 10) {
  707. sum += tmpNum % 10 + 1;
  708. } else {
  709. sum += tmpNum;
  710. }
  711. } else {
  712. sum += tmpNum;
  713. }
  714. shouldDouble = !shouldDouble;
  715. }
  716. return !!(sum % 10 === 0 ? sanitized : false);
  717. }
  718. var isin = /^[A-Z]{2}[0-9A-Z]{9}[0-9]$/;
  719. function isISIN(str) {
  720. assertString(str);
  721. if (!isin.test(str)) {
  722. return false;
  723. }
  724. var checksumStr = str.replace(/[A-Z]/g, function (character) {
  725. return parseInt(character, 36);
  726. });
  727. var sum = 0;
  728. var digit = void 0;
  729. var tmpNum = void 0;
  730. var shouldDouble = true;
  731. for (var i = checksumStr.length - 2; i >= 0; i--) {
  732. digit = checksumStr.substring(i, i + 1);
  733. tmpNum = parseInt(digit, 10);
  734. if (shouldDouble) {
  735. tmpNum *= 2;
  736. if (tmpNum >= 10) {
  737. sum += tmpNum + 1;
  738. } else {
  739. sum += tmpNum;
  740. }
  741. } else {
  742. sum += tmpNum;
  743. }
  744. shouldDouble = !shouldDouble;
  745. }
  746. return parseInt(str.substr(str.length - 1), 10) === (10000 - sum) % 10;
  747. }
  748. var isbn10Maybe = /^(?:[0-9]{9}X|[0-9]{10})$/;
  749. var isbn13Maybe = /^(?:[0-9]{13})$/;
  750. var factor = [1, 3];
  751. function isISBN(str) {
  752. var version = arguments.length <= 1 || arguments[1] === undefined ? '' : arguments[1];
  753. assertString(str);
  754. version = String(version);
  755. if (!version) {
  756. return isISBN(str, 10) || isISBN(str, 13);
  757. }
  758. var sanitized = str.replace(/[\s-]+/g, '');
  759. var checksum = 0;
  760. var i = void 0;
  761. if (version === '10') {
  762. if (!isbn10Maybe.test(sanitized)) {
  763. return false;
  764. }
  765. for (i = 0; i < 9; i++) {
  766. checksum += (i + 1) * sanitized.charAt(i);
  767. }
  768. if (sanitized.charAt(9) === 'X') {
  769. checksum += 10 * 10;
  770. } else {
  771. checksum += 10 * sanitized.charAt(9);
  772. }
  773. if (checksum % 11 === 0) {
  774. return !!sanitized;
  775. }
  776. } else if (version === '13') {
  777. if (!isbn13Maybe.test(sanitized)) {
  778. return false;
  779. }
  780. for (i = 0; i < 12; i++) {
  781. checksum += factor[i % 2] * sanitized.charAt(i);
  782. }
  783. if (sanitized.charAt(12) - (10 - checksum % 10) % 10 === 0) {
  784. return !!sanitized;
  785. }
  786. }
  787. return false;
  788. }
  789. /* eslint-disable max-len */
  790. var phones = {
  791. 'ar-DZ': /^(\+?213|0)(5|6|7)\d{8}$/,
  792. 'ar-SY': /^(!?(\+?963)|0)?9\d{8}$/,
  793. 'ar-SA': /^(!?(\+?966)|0)?5\d{8}$/,
  794. 'en-US': /^(\+?1)?[2-9]\d{2}[2-9](?!11)\d{6}$/,
  795. 'cs-CZ': /^(\+?420)? ?[1-9][0-9]{2} ?[0-9]{3} ?[0-9]{3}$/,
  796. 'de-DE': /^(\+?49[ \.\-])?([\(]{1}[0-9]{1,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/,
  797. 'da-DK': /^(\+?45)?(\d{8})$/,
  798. 'el-GR': /^(\+?30)?(69\d{8})$/,
  799. 'en-AU': /^(\+?61|0)4\d{8}$/,
  800. 'en-GB': /^(\+?44|0)7\d{9}$/,
  801. 'en-HK': /^(\+?852\-?)?[569]\d{3}\-?\d{4}$/,
  802. 'en-IN': /^(\+?91|0)?[789]\d{9}$/,
  803. 'en-NZ': /^(\+?64|0)2\d{7,9}$/,
  804. 'en-ZA': /^(\+?27|0)\d{9}$/,
  805. 'en-ZM': /^(\+?26)?09[567]\d{7}$/,
  806. 'es-ES': /^(\+?34)?(6\d{1}|7[1234])\d{7}$/,
  807. 'fi-FI': /^(\+?358|0)\s?(4(0|1|2|4|5)?|50)\s?(\d\s?){4,8}\d$/,
  808. 'fr-FR': /^(\+?33|0)[67]\d{8}$/,
  809. 'hu-HU': /^(\+?36)(20|30|70)\d{7}$/,
  810. 'it-IT': /^(\+?39)?\s?3\d{2} ?\d{6,7}$/,
  811. 'ja-JP': /^(\+?81|0)\d{1,4}[ \-]?\d{1,4}[ \-]?\d{4}$/,
  812. 'ms-MY': /^(\+?6?01){1}(([145]{1}(\-|\s)?\d{7,8})|([236789]{1}(\s|\-)?\d{7}))$/,
  813. 'nb-NO': /^(\+?47)?[49]\d{7}$/,
  814. 'nl-BE': /^(\+?32|0)4?\d{8}$/,
  815. 'nn-NO': /^(\+?47)?[49]\d{7}$/,
  816. 'pl-PL': /^(\+?48)? ?[5-8]\d ?\d{3} ?\d{2} ?\d{2}$/,
  817. 'pt-BR': /^(\+?55|0)\-?[1-9]{2}\-?[2-9]{1}\d{3,4}\-?\d{4}$/,
  818. 'pt-PT': /^(\+?351)?9[1236]\d{7}$/,
  819. 'ru-RU': /^(\+?7|8)?9\d{9}$/,
  820. 'sr-RS': /^(\+3816|06)[- \d]{5,9}$/,
  821. 'tr-TR': /^(\+?90|0)?5\d{9}$/,
  822. 'vi-VN': /^(\+?84|0)?((1(2([0-9])|6([2-9])|88|99))|(9((?!5)[0-9])))([0-9]{7})$/,
  823. 'zh-CN': /^(\+?0?86\-?)?1[345789]\d{9}$/,
  824. 'zh-TW': /^(\+?886\-?|0)?9\d{8}$/
  825. };
  826. /* eslint-enable max-len */
  827. // aliases
  828. phones['en-CA'] = phones['en-US'];
  829. phones['fr-BE'] = phones['nl-BE'];
  830. function isMobilePhone(str, locale) {
  831. assertString(str);
  832. if (locale in phones) {
  833. return phones[locale].test(str);
  834. }
  835. return false;
  836. }
  837. function currencyRegex(options) {
  838. var symbol = '(\\' + options.symbol.replace(/\./g, '\\.') + ')' + (options.require_symbol ? '' : '?'),
  839. negative = '-?',
  840. whole_dollar_amount_without_sep = '[1-9]\\d*',
  841. whole_dollar_amount_with_sep = '[1-9]\\d{0,2}(\\' + options.thousands_separator + '\\d{3})*',
  842. valid_whole_dollar_amounts = ['0', whole_dollar_amount_without_sep, whole_dollar_amount_with_sep],
  843. whole_dollar_amount = '(' + valid_whole_dollar_amounts.join('|') + ')?',
  844. decimal_amount = '(\\' + options.decimal_separator + '\\d{2})?';
  845. var pattern = whole_dollar_amount + decimal_amount;
  846. // default is negative sign before symbol, but there are two other options (besides parens)
  847. if (options.allow_negatives && !options.parens_for_negatives) {
  848. if (options.negative_sign_after_digits) {
  849. pattern += negative;
  850. } else if (options.negative_sign_before_digits) {
  851. pattern = negative + pattern;
  852. }
  853. }
  854. // South African Rand, for example, uses R 123 (space) and R-123 (no space)
  855. if (options.allow_negative_sign_placeholder) {
  856. pattern = '( (?!\\-))?' + pattern;
  857. } else if (options.allow_space_after_symbol) {
  858. pattern = ' ?' + pattern;
  859. } else if (options.allow_space_after_digits) {
  860. pattern += '( (?!$))?';
  861. }
  862. if (options.symbol_after_digits) {
  863. pattern += symbol;
  864. } else {
  865. pattern = symbol + pattern;
  866. }
  867. if (options.allow_negatives) {
  868. if (options.parens_for_negatives) {
  869. pattern = '(\\(' + pattern + '\\)|' + pattern + ')';
  870. } else if (!(options.negative_sign_before_digits || options.negative_sign_after_digits)) {
  871. pattern = negative + pattern;
  872. }
  873. }
  874. /* eslint-disable prefer-template */
  875. return new RegExp('^' +
  876. // ensure there's a dollar and/or decimal amount, and that
  877. // it doesn't start with a space or a negative sign followed by a space
  878. '(?!-? )(?=.*\\d)' + pattern + '$');
  879. /* eslint-enable prefer-template */
  880. }
  881. var default_currency_options = {
  882. symbol: '$',
  883. require_symbol: false,
  884. allow_space_after_symbol: false,
  885. symbol_after_digits: false,
  886. allow_negatives: true,
  887. parens_for_negatives: false,
  888. negative_sign_before_digits: false,
  889. negative_sign_after_digits: false,
  890. allow_negative_sign_placeholder: false,
  891. thousands_separator: ',',
  892. decimal_separator: '.',
  893. allow_space_after_digits: false
  894. };
  895. function isCurrency(str, options) {
  896. assertString(str);
  897. options = merge(options, default_currency_options);
  898. return currencyRegex(options).test(str);
  899. }
  900. var notBase64 = /[^A-Z0-9+\/=]/i;
  901. function isBase64(str) {
  902. assertString(str);
  903. var len = str.length;
  904. if (!len || len % 4 !== 0 || notBase64.test(str)) {
  905. return false;
  906. }
  907. var firstPaddingChar = str.indexOf('=');
  908. return firstPaddingChar === -1 || firstPaddingChar === len - 1 || firstPaddingChar === len - 2 && str[len - 1] === '=';
  909. }
  910. var dataURI = /^\s*data:([a-z]+\/[a-z0-9\-\+]+(;[a-z\-]+=[a-z0-9\-]+)?)?(;base64)?,[a-z0-9!\$&',\(\)\*\+,;=\-\._~:@\/\?%\s]*\s*$/i; // eslint-disable-line max-len
  911. function isDataURI(str) {
  912. assertString(str);
  913. return dataURI.test(str);
  914. }
  915. function ltrim(str, chars) {
  916. assertString(str);
  917. var pattern = chars ? new RegExp('^[' + chars + ']+', 'g') : /^\s+/g;
  918. return str.replace(pattern, '');
  919. }
  920. function rtrim(str, chars) {
  921. assertString(str);
  922. var pattern = chars ? new RegExp('[' + chars + ']') : /\s/;
  923. var idx = str.length - 1;
  924. while (idx >= 0 && pattern.test(str[idx])) {
  925. idx--;
  926. }
  927. return idx < str.length ? str.substr(0, idx + 1) : str;
  928. }
  929. function trim(str, chars) {
  930. return rtrim(ltrim(str, chars), chars);
  931. }
  932. function escape(str) {
  933. assertString(str);
  934. return str.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\//g, '&#x2F;').replace(/`/g, '&#96;');
  935. }
  936. function unescape(str) {
  937. assertString(str);
  938. return str.replace(/&amp;/g, '&').replace(/&quot;/g, '"').replace(/&#x27;/g, "'").replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&#x2F;/g, '/').replace(/&#96;/g, '`');
  939. }
  940. function blacklist(str, chars) {
  941. assertString(str);
  942. return str.replace(new RegExp('[' + chars + ']+', 'g'), '');
  943. }
  944. function stripLow(str, keep_new_lines) {
  945. assertString(str);
  946. var chars = keep_new_lines ? '\\x00-\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F' : '\\x00-\\x1F\\x7F';
  947. return blacklist(str, chars);
  948. }
  949. function whitelist(str, chars) {
  950. assertString(str);
  951. return str.replace(new RegExp('[^' + chars + ']+', 'g'), '');
  952. }
  953. function isWhitelisted(str, chars) {
  954. assertString(str);
  955. for (var i = str.length - 1; i >= 0; i--) {
  956. if (chars.indexOf(str[i]) === -1) {
  957. return false;
  958. }
  959. }
  960. return true;
  961. }
  962. var default_normalize_email_options = {
  963. lowercase: true,
  964. remove_dots: true,
  965. remove_extension: true
  966. };
  967. function normalizeEmail(email, options) {
  968. options = merge(options, default_normalize_email_options);
  969. if (!isEmail(email)) {
  970. return false;
  971. }
  972. var parts = email.split('@', 2);
  973. parts[1] = parts[1].toLowerCase();
  974. if (parts[1] === 'gmail.com' || parts[1] === 'googlemail.com') {
  975. if (options.remove_extension) {
  976. parts[0] = parts[0].split('+')[0];
  977. }
  978. if (options.remove_dots) {
  979. parts[0] = parts[0].replace(/\./g, '');
  980. }
  981. if (!parts[0].length) {
  982. return false;
  983. }
  984. parts[0] = parts[0].toLowerCase();
  985. parts[1] = 'gmail.com';
  986. } else if (options.lowercase) {
  987. parts[0] = parts[0].toLowerCase();
  988. }
  989. return parts.join('@');
  990. }
  991. var version = '5.7.0';
  992. var validator = {
  993. version: version,
  994. toDate: toDate,
  995. toFloat: toFloat, toInt: toInt,
  996. toBoolean: toBoolean,
  997. equals: equals, contains: contains, matches: matches,
  998. isEmail: isEmail, isURL: isURL, isMACAddress: isMACAddress, isIP: isIP, isFQDN: isFDQN,
  999. isBoolean: isBoolean,
  1000. isAlpha: isAlpha, isAlphanumeric: isAlphanumeric, isNumeric: isNumeric, isLowercase: isLowercase, isUppercase: isUppercase,
  1001. isAscii: isAscii, isFullWidth: isFullWidth, isHalfWidth: isHalfWidth, isVariableWidth: isVariableWidth,
  1002. isMultibyte: isMultibyte, isSurrogatePair: isSurrogatePair,
  1003. isInt: isInt, isFloat: isFloat, isDecimal: isDecimal, isHexadecimal: isHexadecimal, isDivisibleBy: isDivisibleBy,
  1004. isHexColor: isHexColor,
  1005. isMD5: isMD5,
  1006. isJSON: isJSON,
  1007. isNull: isNull,
  1008. isLength: isLength, isByteLength: isByteLength,
  1009. isUUID: isUUID, isMongoId: isMongoId,
  1010. isDate: isDate, isAfter: isAfter, isBefore: isBefore,
  1011. isIn: isIn,
  1012. isCreditCard: isCreditCard,
  1013. isISIN: isISIN, isISBN: isISBN,
  1014. isMobilePhone: isMobilePhone,
  1015. isCurrency: isCurrency,
  1016. isISO8601: isISO8601,
  1017. isBase64: isBase64, isDataURI: isDataURI,
  1018. ltrim: ltrim, rtrim: rtrim, trim: trim,
  1019. escape: escape, unescape: unescape, stripLow: stripLow,
  1020. whitelist: whitelist, blacklist: blacklist,
  1021. isWhitelisted: isWhitelisted,
  1022. normalizeEmail: normalizeEmail,
  1023. toString: toString
  1024. };
  1025. return validator;
  1026. }));