diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 8311927d1..ef99b5358 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ $ bower install validator-js - **contains(str, seed)** - check if the string contains the seed. - **matches(str, pattern [, modifiers])** - check if string matches the pattern. Either `matches('foo', /foo/i)` or `matches('foo', 'foo', 'i')`. - **isEmail(str)** - check if the string is an email. -- **isURL(str [, options])** - check if the string is an URL. `options` is an object which defaults to `{ protocols: ['http','https','ftp'], require_tld: true, require_protocol: false, allow_underscores: false }`. +- **isURL(str [, options])** - check if the string is an URL. `options` is an object which defaults to `{ protocols: ['http','https','ftp'], require_tld: true, require_protocol: false, allow_underscores: false, include_domains: [], exclude_domains: [] }`. (`include_domains` and `exclude_domains` allow testing for domain names.) - **isFQDN(str [, options])** - check if the string is a fully qualified domain name (e.g. domain.com). `options` is an object which defaults to `{ require_tld: true, allow_underscores: false }`. - **isIP(str [, version])** - check if the string is an IP (version 4 or 6). - **isAlpha(str)** - check if the string contains only letters (a-zA-Z). diff --git a/test/validators.js b/test/validators.js index 367a452bb..d7e8e3b02 100644 --- a/test/validators.js +++ b/test/validators.js @@ -162,6 +162,48 @@ describe('Validators', function () { }); }); + it('should validate URLs including a domain', function () { + test({ + validator: 'isURL' + , args: [{ + include: 'foobar.com, rocketman.com, playcoders.org' + }] + , valid: [ + 'http://foobar.com/', + 'http://rocketman.com/', + 'https://playcoders.org' + ] + }); + }); + + it('should validate URLs excluding a domain', function () { + test({ + validator: 'isURL' + , args: [{ + exclude: 'google.com' + }] + , valid: [ + 'http://foobar.com/', + 'http://rocketman.com/', + 'https://playcoders.org' + ] + }); + }); + + it('should validate URLs including and excluding domains', function () { + test({ + validator: 'isURL' + , args: [{ + include: 'nodejs.org, rocketman.com', + exclude: 'google.com, bladerunners.org' + }] + , valid: [ + 'http://nodejs.org/', + 'http://rocketman.com/' + ] + }); + }); + it('should let users specify whether URLs require a protocol', function () { test({ validator: 'isURL' diff --git a/validator.js b/validator.js index ed09d7180..22d21aa6f 100644 --- a/validator.js +++ b/validator.js @@ -1,456 +1,483 @@ -/*! - * Copyright (c) 2014 Chris O'Hara - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -(function (name, definition) { - if (typeof exports !== 'undefined' && typeof module !== 'undefined') { - module.exports = definition(); - } else if (typeof define === 'function' && typeof define.amd === 'object') { - define(definition); - } else { - this[name] = definition(); - } -})('validator', function (validator) { - - 'use strict'; - - validator = { version: '3.18.1' }; - - var email = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\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]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; - - var creditCard = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|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})$/; - - var isbn10Maybe = /^(?:[0-9]{9}X|[0-9]{10})$/ - , isbn13Maybe = /^(?:[0-9]{13})$/; - - var ipv4Maybe = /^(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)$/ - , ipv6 = /^::|^::1|^([a-fA-F0-9]{1,4}::?){1,7}([a-fA-F0-9]{1,4})$/; - - var uuid = { - '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i - , '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i - , '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i - , all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i - }; - - var alpha = /^[a-zA-Z]+$/ - , alphanumeric = /^[a-zA-Z0-9]+$/ - , numeric = /^-?[0-9]+$/ - , int = /^(?:-?(?:0|[1-9][0-9]*))$/ - , float = /^(?:-?(?:[0-9]+))?(?:\.[0-9]*)?(?:[eE][\+\-]?(?:[0-9]+))?$/ - , hexadecimal = /^[0-9a-fA-F]+$/ - , hexcolor = /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/; - - var ascii = /^[\x00-\x7F]+$/ - , multibyte = /[^\x00-\x7F]/ - , fullWidth = /[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/ - , halfWidth = /[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/; - - var surrogatePair = /[\uD800-\uDBFF][\uDC00-\uDFFF]/; - - var base64 = /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/; - - validator.extend = function (name, fn) { - validator[name] = function () { - var args = Array.prototype.slice.call(arguments); - args[0] = validator.toString(args[0]); - return fn.apply(validator, args); - }; - }; - - //Right before exporting the validator object, pass each of the builtins - //through extend() so that their first argument is coerced to a string - validator.init = function () { - for (var name in validator) { - if (typeof validator[name] !== 'function' || name === 'toString' || - name === 'toDate' || name === 'extend' || name === 'init') { - continue; - } - validator.extend(name, validator[name]); - } - }; - - validator.toString = function (input) { - if (typeof input === 'object' && input !== null && input.toString) { - input = input.toString(); - } else if (input === null || typeof input === 'undefined' || (isNaN(input) && !input.length)) { - input = ''; - } else if (typeof input !== 'string') { - input += ''; - } - return input; - }; - - validator.toDate = function (date) { - if (Object.prototype.toString.call(date) === '[object Date]') { - return date; - } - date = Date.parse(date); - return !isNaN(date) ? new Date(date) : null; - }; - - validator.toFloat = function (str) { - return parseFloat(str); - }; - - validator.toInt = function (str, radix) { - return parseInt(str, radix || 10); - }; - - validator.toBoolean = function (str, strict) { - if (strict) { - return str === '1' || str === 'true'; - } - return str !== '0' && str !== 'false' && str !== ''; - }; - - validator.equals = function (str, comparison) { - return str === validator.toString(comparison); - }; - - validator.contains = function (str, elem) { - return str.indexOf(validator.toString(elem)) >= 0; - }; - - validator.matches = function (str, pattern, modifiers) { - if (Object.prototype.toString.call(pattern) !== '[object RegExp]') { - pattern = new RegExp(pattern, modifiers); - } - return pattern.test(str); - }; - - validator.isEmail = function (str) { - return email.test(str); - }; - - var default_url_options = { - protocols: [ 'http', 'https', 'ftp' ] - , require_tld: true - , require_protocol: false - , allow_underscores: false - }; - - validator.isURL = function (str, options) { - if (!str || str.length >= 2083) { - return false; - } - options = merge(options, default_url_options); - var ipv4_url_parts = [ - '(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])' - , '(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}', - , '(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))' - ]; - var protocol = '(?:(?:' + options.protocols.join('|') + ')://)' + (options.require_protocol ? '' : '?') - , auth = '(?:\\S+(?::\\S*)?@)?' - , ipv4 = '(?:' + ipv4_url_parts.join('') + ')' - , hostname = '(?:' + ipv4 + '|' + domain(options) + '|localhost)' - , port = '(\\d{1,5})' - , host = hostname + '(?::' + port + ')?' - , path_query_anchor = '(?:(?:/|\\?|#)[^\\s]*)?'; - var is_url = new RegExp('^(?!mailto:)' + protocol + auth + host + path_query_anchor + '$', 'i'); - var match = str.match(is_url) - , port_match = match ? match[1] : 0; - return !!(match && (!port_match || (port_match > 0 && port_match <= 65535))); - }; - - validator.isIP = function (str, version) { - version = validator.toString(version); - if (!version) { - return validator.isIP(str, 4) || validator.isIP(str, 6); - } else if (version === '4') { - if (!ipv4Maybe.test(str)) { - return false; - } - var parts = str.split('.').sort(function (a, b) { - return a - b; - }); - return parts[3] <= 255; - } - return version === '6' && ipv6.test(str); - }; - - var default_fqdn_options = { - require_tld: true - , allow_underscores: false - }; - - validator.isFQDN = function (str, options) { - options = merge(options, default_fqdn_options); - return new RegExp('^' + domain(options) + '$', 'i').test(str); - }; - - validator.isAlpha = function (str) { - return alpha.test(str); - }; - - validator.isAlphanumeric = function (str) { - return alphanumeric.test(str); - }; - - validator.isNumeric = function (str) { - return numeric.test(str); - }; - - validator.isHexadecimal = function (str) { - return hexadecimal.test(str); - }; - - validator.isHexColor = function (str) { - return hexcolor.test(str); - }; - - validator.isLowercase = function (str) { - return str === str.toLowerCase(); - }; - - validator.isUppercase = function (str) { - return str === str.toUpperCase(); - }; - - validator.isInt = function (str) { - return int.test(str); - }; - - validator.isFloat = function (str) { - return str !== '' && float.test(str); - }; - - validator.isDivisibleBy = function (str, num) { - return validator.toFloat(str) % validator.toInt(num) === 0; - }; - - validator.isNull = function (str) { - return str.length === 0; - }; - - validator.isLength = function (str, min, max) { - var surrogatePairs = str.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g) || []; - var len = str.length - surrogatePairs.length; - return len >= min && (typeof max === 'undefined' || len <= max); - }; - - validator.isByteLength = function (str, min, max) { - return str.length >= min && (typeof max === 'undefined' || str.length <= max); - }; - - validator.isUUID = function (str, version) { - var pattern = uuid[version ? version : 'all']; - return pattern && pattern.test(str); - }; - - validator.isDate = function (str) { - return !isNaN(Date.parse(str)); - }; - - validator.isAfter = function (str, date) { - var comparison = validator.toDate(date || new Date()) - , original = validator.toDate(str); - return !!(original && comparison && original > comparison); - }; - - validator.isBefore = function (str, date) { - var comparison = validator.toDate(date || new Date()) - , original = validator.toDate(str); - return original && comparison && original < comparison; - }; - - validator.isIn = function (str, options) { - if (!options || typeof options.indexOf !== 'function') { - return false; - } - if (Object.prototype.toString.call(options) === '[object Array]') { - var array = []; - for (var i = 0, len = options.length; i < len; i++) { - array[i] = validator.toString(options[i]); - } - options = array; - } - return options.indexOf(str) >= 0; - }; - - validator.isCreditCard = function (str) { - var sanitized = str.replace(/[^0-9]+/g, ''); - if (!creditCard.test(sanitized)) { - return false; - } - var sum = 0, digit, tmpNum, shouldDouble; - for (var i = sanitized.length - 1; i >= 0; i--) { - digit = sanitized.substring(i, (i + 1)); - tmpNum = parseInt(digit, 10); - if (shouldDouble) { - tmpNum *= 2; - if (tmpNum >= 10) { - sum += ((tmpNum % 10) + 1); - } else { - sum += tmpNum; - } - } else { - sum += tmpNum; - } - shouldDouble = !shouldDouble; - } - return !!((sum % 10) === 0 ? sanitized : false); - }; - - validator.isISBN = function (str, version) { - version = validator.toString(version); - if (!version) { - return validator.isISBN(str, 10) || validator.isISBN(str, 13); - } - var sanitized = str.replace(/[\s-]+/g, '') - , checksum = 0, i; - if (version === '10') { - if (!isbn10Maybe.test(sanitized)) { - return false; - } - for (i = 0; i < 9; i++) { - checksum += (i + 1) * sanitized.charAt(i); - } - if (sanitized.charAt(9) === 'X') { - checksum += 10 * 10; - } else { - checksum += 10 * sanitized.charAt(9); - } - if ((checksum % 11) === 0) { - return !!sanitized; - } - } else if (version === '13') { - if (!isbn13Maybe.test(sanitized)) { - return false; - } - var factor = [ 1, 3 ]; - for (i = 0; i < 12; i++) { - checksum += factor[i % 2] * sanitized.charAt(i); - } - if (sanitized.charAt(12) - ((10 - (checksum % 10)) % 10) === 0) { - return !!sanitized; - } - } - return false; - }; - - validator.isJSON = function (str) { - try { - JSON.parse(str); - } catch (e) { - return false; - } - return true; - }; - - validator.isMultibyte = function (str) { - return multibyte.test(str); - }; - - validator.isAscii = function (str) { - return ascii.test(str); - }; - - validator.isFullWidth = function (str) { - return fullWidth.test(str); - }; - - validator.isHalfWidth = function (str) { - return halfWidth.test(str); - }; - - validator.isVariableWidth = function (str) { - return fullWidth.test(str) && halfWidth.test(str); - }; - - validator.isSurrogatePair = function (str) { - return surrogatePair.test(str); - }; - - validator.isBase64 = function (str) { - return base64.test(str); - }; - - validator.ltrim = function (str, chars) { - var pattern = chars ? new RegExp('^[' + chars + ']+', 'g') : /^\s+/g; - return str.replace(pattern, ''); - }; - - validator.rtrim = function (str, chars) { - var pattern = chars ? new RegExp('[' + chars + ']+$', 'g') : /\s+$/g; - return str.replace(pattern, ''); - }; - - validator.trim = function (str, chars) { - var pattern = chars ? new RegExp('^[' + chars + ']+|[' + chars + ']+$', 'g') : /^\s+|\s+$/g; - return str.replace(pattern, ''); - }; - - validator.escape = function (str) { - return (str.replace(/&/g, '&') - .replace(/"/g, '"') - .replace(/'/g, ''') - .replace(//g, '>')); - }; - - validator.stripLow = function (str, keep_new_lines) { - var chars = keep_new_lines ? '\x00-\x09\x0B\x0C\x0E-\x1F\x7F' : '\x00-\x1F\x7F'; - return validator.blacklist(str, chars); - }; - - validator.whitelist = function (str, chars) { - return str.replace(new RegExp('[^' + chars + ']+', 'g'), ''); - }; - - validator.blacklist = function (str, chars) { - return str.replace(new RegExp('[' + chars + ']+', 'g'), ''); - }; - - validator.normalizeEmail = function (email) { - var parts = email.toLowerCase().split('@', 2); - if (parts[1] === 'gmail.com' || parts[1] === 'googlemail.com') { - parts[0] = parts[0].replace('.', '').split('+')[0]; - email = parts.join('@'); - } - return email; - }; - - function merge(obj, defaults) { - obj = obj || {}; - for (var key in defaults) { - if (typeof obj[key] === 'undefined') { - obj[key] = defaults[key]; - } - } - return obj; - } - - function domain(options) { - var sep = '-?-?' + (options.allow_underscores ? '_?' : '') - , alpha = 'a-z\\u00a1-\\uffff' - , alphanum = alpha + '0-9' - , subdomain = '(?:(?:[' + alphanum + ']+' + sep + ')*[' + alphanum + ']+)' - , tld = '(?:\\.(?:[' + alpha + ']{2,}))' + (options.require_tld ? '' : '?'); - return '(?:' + subdomain + '(?:\\.' + subdomain + ')*' + tld + ')'; - } - - validator.init(); - - return validator; - -}); + /*! + * Copyright (c) 2014 Chris O'Hara + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + (function (name, definition) { + if (typeof exports !== 'undefined' && typeof module !== 'undefined') { + module.exports = definition(); + } else if (typeof define === 'function' && typeof define.amd === 'object') { + define(definition); + } else { + this[name] = definition(); + } + })('validator', function (validator) { + + 'use strict'; + + validator = { version: '3.18.1' }; + + var email = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\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]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; + + var creditCard = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|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})$/; + + var isbn10Maybe = /^(?:[0-9]{9}X|[0-9]{10})$/ + , isbn13Maybe = /^(?:[0-9]{13})$/; + + var ipv4Maybe = /^(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)$/ + , ipv6 = /^::|^::1|^([a-fA-F0-9]{1,4}::?){1,7}([a-fA-F0-9]{1,4})$/; + + var uuid = { + '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i + , '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i + , '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i + , all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i + }; + + var alpha = /^[a-zA-Z]+$/ + , alphanumeric = /^[a-zA-Z0-9]+$/ + , numeric = /^-?[0-9]+$/ + , int = /^(?:-?(?:0|[1-9][0-9]*))$/ + , float = /^(?:-?(?:[0-9]+))?(?:\.[0-9]*)?(?:[eE][\+\-]?(?:[0-9]+))?$/ + , hexadecimal = /^[0-9a-fA-F]+$/ + , hexcolor = /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/; + + var ascii = /^[\x00-\x7F]+$/ + , multibyte = /[^\x00-\x7F]/ + , fullWidth = /[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/ + , halfWidth = /[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/; + + var surrogatePair = /[\uD800-\uDBFF][\uDC00-\uDFFF]/; + + var base64 = /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/; + + var default_url_options = { + protocols: [ 'http', 'https', 'ftp' ] + , require_tld: true + , require_protocol: false + , allow_underscores: false + , include_domains: [] + , exclude_domains: [] + }; + + validator.extend = function (name, fn) { + validator[name] = function () { + var args = Array.prototype.slice.call(arguments); + args[0] = validator.toString(args[0]); + return fn.apply(validator, args); + }; + }; + + //Right before exporting the validator object, pass each of the builtins + //through extend() so that their first argument is coerced to a string + validator.init = function () { + for (var name in validator) { + if (typeof validator[name] !== 'function' || name === 'toString' || + name === 'toDate' || name === 'extend' || name === 'init') { + continue; + } + validator.extend(name, validator[name]); + } + }; + + validator.toString = function (input) { + if (typeof input === 'object' && input !== null && input.toString) { + input = input.toString(); + } else if (input === null || typeof input === 'undefined' || (isNaN(input) && !input.length)) { + input = ''; + } else if (typeof input !== 'string') { + input += ''; + } + return input; + }; + + validator.toDate = function (date) { + if (Object.prototype.toString.call(date) === '[object Date]') { + return date; + } + date = Date.parse(date); + return !isNaN(date) ? new Date(date) : null; + }; + + validator.toFloat = function (str) { + return parseFloat(str); + }; + + validator.toInt = function (str, radix) { + return parseInt(str, radix || 10); + }; + + validator.toBoolean = function (str, strict) { + if (strict) { + return str === '1' || str === 'true'; + } + return str !== '0' && str !== 'false' && str !== ''; + }; + + validator.equals = function (str, comparison) { + return str === validator.toString(comparison); + }; + + validator.contains = function (str, elem) { + return str.indexOf(validator.toString(elem)) >= 0; + }; + + validator.matches = function (str, pattern, modifiers) { + if (Object.prototype.toString.call(pattern) !== '[object RegExp]') { + pattern = new RegExp(pattern, modifiers); + } + return pattern.test(str); + }; + + validator.isEmail = function (str) { + return email.test(str); + }; + + validator.isURL = function (str, options) { + if (!str || str.length >= 2083) { + return false; + } + options = merge(options, default_url_options); + var ipv4_url_parts = [ + '(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])' + , '(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}', + , '(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))' + ]; + var protocol = '(?:(?:' + options.protocols.join('|') + ')://)' + (options.require_protocol ? '' : '?') + , auth = '(?:\\S+(?::\\S*)?@)?' + , ipv4 = '(?:' + ipv4_url_parts.join('') + ')' + , hostname = '(?:' + ipv4 + '|' + domain(options) + '|localhost)' + , port = '(\\d{1,5})' + , host = hostname + '(?::' + port + ')?' + , path_query_anchor = '(?:(?:/|\\?|#)[^\\s]*)?' + , passInclude = (options.include_domains.length) ? options.include_domains.indexOf(str) !== -1 : true + , passExclude = (options.exclude_domains.length) ? options.exclude_domains.indexOf(str) === -1 : true + + var is_url = new RegExp('^(?!mailto:)' + protocol + auth + host + path_query_anchor + '$', 'i'); + var match = str.match(is_url) + , port_match = match ? match[1] : 0; + + return !!(match && (!port_match || (port_match > 0 && port_match <= 65535)) && passInclude && passExclude); + }; + + validator.isIP = function (str, version) { + version = validator.toString(version); + if (!version) { + return validator.isIP(str, 4) || validator.isIP(str, 6); + } else if (version === '4') { + if (!ipv4Maybe.test(str)) { + return false; + } + var parts = str.split('.').sort(function (a, b) { + return a - b; + }); + return parts[3] <= 255; + } + return version === '6' && ipv6.test(str); + }; + + var default_fqdn_options = { + require_tld: true + , allow_underscores: false + }; + + validator.isFQDN = function (str, options) { + options = merge(options, default_fqdn_options); + return new RegExp('^' + domain(options) + '$', 'i').test(str); + }; + + validator.isAlpha = function (str) { + return alpha.test(str); + }; + + validator.isAlphanumeric = function (str) { + return alphanumeric.test(str); + }; + + validator.isNumeric = function (str) { + return numeric.test(str); + }; + + validator.isHexadecimal = function (str) { + return hexadecimal.test(str); + }; + + validator.isHexColor = function (str) { + return hexcolor.test(str); + }; + + validator.isLowercase = function (str) { + return str === str.toLowerCase(); + }; + + validator.isUppercase = function (str) { + return str === str.toUpperCase(); + }; + + validator.isInt = function (str) { + return int.test(str); + }; + + validator.isFloat = function (str) { + return str !== '' && float.test(str); + }; + + validator.isDivisibleBy = function (str, num) { + return validator.toFloat(str) % validator.toInt(num) === 0; + }; + + validator.isNull = function (str) { + return str.length === 0; + }; + + validator.isLength = function (str, min, max) { + var surrogatePairs = str.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g) || []; + var len = str.length - surrogatePairs.length; + return len >= min && (typeof max === 'undefined' || len <= max); + }; + + validator.isByteLength = function (str, min, max) { + return str.length >= min && (typeof max === 'undefined' || str.length <= max); + }; + + validator.isUUID = function (str, version) { + var pattern = uuid[version ? version : 'all']; + return pattern && pattern.test(str); + }; + + validator.isDate = function (str) { + return !isNaN(Date.parse(str)); + }; + + validator.isAfter = function (str, date) { + var comparison = validator.toDate(date || new Date()) + , original = validator.toDate(str); + return !!(original && comparison && original > comparison); + }; + + validator.isBefore = function (str, date) { + var comparison = validator.toDate(date || new Date()) + , original = validator.toDate(str); + return original && comparison && original < comparison; + }; + + validator.isIn = function (str, options) { + if (!options || typeof options.indexOf !== 'function') { + return false; + } + if (Object.prototype.toString.call(options) === '[object Array]') { + var array = []; + for (var i = 0, len = options.length; i < len; i++) { + array[i] = validator.toString(options[i]); + } + options = array; + } + return options.indexOf(str) >= 0; + }; + + validator.isCreditCard = function (str) { + var sanitized = str.replace(/[^0-9]+/g, ''); + if (!creditCard.test(sanitized)) { + return false; + } + var sum = 0, digit, tmpNum, shouldDouble; + for (var i = sanitized.length - 1; i >= 0; i--) { + digit = sanitized.substring(i, (i + 1)); + tmpNum = parseInt(digit, 10); + if (shouldDouble) { + tmpNum *= 2; + if (tmpNum >= 10) { + sum += ((tmpNum % 10) + 1); + } else { + sum += tmpNum; + } + } else { + sum += tmpNum; + } + shouldDouble = !shouldDouble; + } + return !!((sum % 10) === 0 ? sanitized : false); + }; + + validator.isISBN = function (str, version) { + version = validator.toString(version); + if (!version) { + return validator.isISBN(str, 10) || validator.isISBN(str, 13); + } + var sanitized = str.replace(/[\s-]+/g, '') + , checksum = 0, i; + if (version === '10') { + if (!isbn10Maybe.test(sanitized)) { + return false; + } + for (i = 0; i < 9; i++) { + checksum += (i + 1) * sanitized.charAt(i); + } + if (sanitized.charAt(9) === 'X') { + checksum += 10 * 10; + } else { + checksum += 10 * sanitized.charAt(9); + } + if ((checksum % 11) === 0) { + return !!sanitized; + } + } else if (version === '13') { + if (!isbn13Maybe.test(sanitized)) { + return false; + } + var factor = [ 1, 3 ]; + for (i = 0; i < 12; i++) { + checksum += factor[i % 2] * sanitized.charAt(i); + } + if (sanitized.charAt(12) - ((10 - (checksum % 10)) % 10) === 0) { + return !!sanitized; + } + } + return false; + }; + + validator.isJSON = function (str) { + try { + JSON.parse(str); + } catch (e) { + return false; + } + return true; + }; + + validator.isMultibyte = function (str) { + return multibyte.test(str); + }; + + validator.isAscii = function (str) { + return ascii.test(str); + }; + + validator.isFullWidth = function (str) { + return fullWidth.test(str); + }; + + validator.isHalfWidth = function (str) { + return halfWidth.test(str); + }; + + validator.isVariableWidth = function (str) { + return fullWidth.test(str) && halfWidth.test(str); + }; + + validator.isSurrogatePair = function (str) { + return surrogatePair.test(str); + }; + + validator.isBase64 = function (str) { + return base64.test(str); + }; + + validator.ltrim = function (str, chars) { + var pattern = chars ? new RegExp('^[' + chars + ']+', 'g') : /^\s+/g; + return str.replace(pattern, ''); + }; + + validator.rtrim = function (str, chars) { + var pattern = chars ? new RegExp('[' + chars + ']+$', 'g') : /\s+$/g; + return str.replace(pattern, ''); + }; + + validator.trim = function (str, chars) { + var pattern = chars ? new RegExp('^[' + chars + ']+|[' + chars + ']+$', 'g') : /^\s+|\s+$/g; + return str.replace(pattern, ''); + }; + + validator.escape = function (str) { + return (str.replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>')); + }; + + validator.stripLow = function (str, keep_new_lines) { + var chars = keep_new_lines ? '\x00-\x09\x0B\x0C\x0E-\x1F\x7F' : '\x00-\x1F\x7F'; + return validator.blacklist(str, chars); + }; + + validator.whitelist = function (str, chars) { + return str.replace(new RegExp('[^' + chars + ']+', 'g'), ''); + }; + + validator.blacklist = function (str, chars) { + return str.replace(new RegExp('[' + chars + ']+', 'g'), ''); + }; + + validator.normalizeEmail = function (email) { + var parts = email.toLowerCase().split('@', 2); + if (parts[1] === 'gmail.com' || parts[1] === 'googlemail.com') { + parts[0] = parts[0].replace('.', '').split('+')[0]; + email = parts.join('@'); + } + return email; + }; + + function merge(obj, defaults) { + obj = obj || {}; + for (var key in defaults) { + if (typeof obj[key] === 'undefined') { + obj[key] = defaults[key]; + } + } + return obj; + } + + function domain(options) { + var sep = '-?-?' + (options.allow_underscores ? '_?' : '') + , alpha = 'a-z\\u00a1-\\uffff' + , alphanum = alpha + '0-9' + , subdomain = '(?:(?:[' + alphanum + ']+' + sep + ')*[' + alphanum + ']+)' + , tld = '(?:\\.(?:[' + alpha + ']{2,}))' + (options.require_tld ? '' : '?'); + + return '(?:' + subdomain + '(?:\\.' + subdomain + ')*' + tld + ')'; + } + + function filterInEx(str, options, filter) { + var passFilter = filter === 'include' ? false : true, + items; + + if (options[filter]) { + items = options[filter].split(','); + for (var item in items) { + if (filter === 'include' && (str.indexOf(items[item].trim()) > -1) || false) { + return !passFilter; + } else if (filter === 'exclude' && !((str.indexOf(items[item].trim()) < 0) || false)) { + return !passFilter; + } + } + } else { + passFilter = true; + } + + return passFilter; + } + + validator.init(); + + return validator; + + }); diff --git a/validator.min.js b/validator.min.js index 7510fd678..9066178a8 100644 --- a/validator.min.js +++ b/validator.min.js @@ -20,4 +20,4 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -!function(t,e){"undefined"!=typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&"object"==typeof define.amd?define(e):this[t]=e()}("validator",function(t){"use strict";function e(t,e){t=t||{};for(var n in e)"undefined"==typeof t[n]&&(t[n]=e[n]);return t}function n(t){var e="-?-?"+(t.allow_underscores?"_?":""),n="a-z\\u00a1-\\uffff",r=n+"0-9",u="(?:(?:["+r+"]+"+e+")*["+r+"]+)",i="(?:\\.(?:["+n+"]{2,}))"+(t.require_tld?"":"?");return"(?:"+u+"(?:\\."+u+")*"+i+")"}t={version:"3.18.1"};var r=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\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]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,u=/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|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})$/,i=/^(?:[0-9]{9}X|[0-9]{10})$/,F=/^(?:[0-9]{13})$/,o=/^(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)$/,a=/^::|^::1|^([a-fA-F0-9]{1,4}::?){1,7}([a-fA-F0-9]{1,4})$/,f={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i},c=/^[a-zA-Z]+$/,s=/^[a-zA-Z0-9]+$/,l=/^-?[0-9]+$/,d=/^(?:-?(?:0|[1-9][0-9]*))$/,p=/^(?:-?(?:[0-9]+))?(?:\.[0-9]*)?(?:[eE][\+\-]?(?:[0-9]+))?$/,D=/^[0-9a-fA-F]+$/,A=/^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/,x=/^[\x00-\x7F]+$/,g=/[^\x00-\x7F]/,E=/[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/,h=/[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/,$=/[\uD800-\uDBFF][\uDC00-\uDFFF]/,v=/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/;t.extend=function(e,n){t[e]=function(){var e=Array.prototype.slice.call(arguments);return e[0]=t.toString(e[0]),n.apply(t,e)}},t.init=function(){for(var e in t)"function"==typeof t[e]&&"toString"!==e&&"toDate"!==e&&"extend"!==e&&"init"!==e&&t.extend(e,t[e])},t.toString=function(t){return"object"==typeof t&&null!==t&&t.toString?t=t.toString():null===t||"undefined"==typeof t||isNaN(t)&&!t.length?t="":"string"!=typeof t&&(t+=""),t},t.toDate=function(t){return"[object Date]"===Object.prototype.toString.call(t)?t:(t=Date.parse(t),isNaN(t)?null:new Date(t))},t.toFloat=function(t){return parseFloat(t)},t.toInt=function(t,e){return parseInt(t,e||10)},t.toBoolean=function(t,e){return e?"1"===t||"true"===t:"0"!==t&&"false"!==t&&""!==t},t.equals=function(e,n){return e===t.toString(n)},t.contains=function(e,n){return e.indexOf(t.toString(n))>=0},t.matches=function(t,e,n){return"[object RegExp]"!==Object.prototype.toString.call(e)&&(e=new RegExp(e,n)),e.test(t)},t.isEmail=function(t){return r.test(t)};var y={protocols:["http","https","ftp"],require_tld:!0,require_protocol:!1,allow_underscores:!1};t.isURL=function(t,r){if(!t||t.length>=2083)return!1;r=e(r,y);var u=["(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])","(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}",,"(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))"],i="(?:(?:"+r.protocols.join("|")+")://)"+(r.require_protocol?"":"?"),F="(?:\\S+(?::\\S*)?@)?",o="(?:"+u.join("")+")",a="(?:"+o+"|"+n(r)+"|localhost)",f="(\\d{1,5})",c=a+"(?::"+f+")?",s="(?:(?:/|\\?|#)[^\\s]*)?",l=new RegExp("^(?!mailto:)"+i+F+c+s+"$","i"),d=t.match(l),p=d?d[1]:0;return!(!d||p&&!(p>0&&65535>=p))},t.isIP=function(e,n){if(n=t.toString(n),!n)return t.isIP(e,4)||t.isIP(e,6);if("4"===n){if(!o.test(e))return!1;var r=e.split(".").sort(function(t,e){return t-e});return r[3]<=255}return"6"===n&&a.test(e)};var m={require_tld:!0,allow_underscores:!1};return t.isFQDN=function(t,r){return r=e(r,m),new RegExp("^"+n(r)+"$","i").test(t)},t.isAlpha=function(t){return c.test(t)},t.isAlphanumeric=function(t){return s.test(t)},t.isNumeric=function(t){return l.test(t)},t.isHexadecimal=function(t){return D.test(t)},t.isHexColor=function(t){return A.test(t)},t.isLowercase=function(t){return t===t.toLowerCase()},t.isUppercase=function(t){return t===t.toUpperCase()},t.isInt=function(t){return d.test(t)},t.isFloat=function(t){return""!==t&&p.test(t)},t.isDivisibleBy=function(e,n){return t.toFloat(e)%t.toInt(n)===0},t.isNull=function(t){return 0===t.length},t.isLength=function(t,e,n){var r=t.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g)||[],u=t.length-r.length;return u>=e&&("undefined"==typeof n||n>=u)},t.isByteLength=function(t,e,n){return t.length>=e&&("undefined"==typeof n||t.length<=n)},t.isUUID=function(t,e){var n=f[e?e:"all"];return n&&n.test(t)},t.isDate=function(t){return!isNaN(Date.parse(t))},t.isAfter=function(e,n){var r=t.toDate(n||new Date),u=t.toDate(e);return!!(u&&r&&u>r)},t.isBefore=function(e,n){var r=t.toDate(n||new Date),u=t.toDate(e);return u&&r&&r>u},t.isIn=function(e,n){if(!n||"function"!=typeof n.indexOf)return!1;if("[object Array]"===Object.prototype.toString.call(n)){for(var r=[],u=0,i=n.length;i>u;u++)r[u]=t.toString(n[u]);n=r}return n.indexOf(e)>=0},t.isCreditCard=function(t){var e=t.replace(/[^0-9]+/g,"");if(!u.test(e))return!1;for(var n,r,i,F=0,o=e.length-1;o>=0;o--)n=e.substring(o,o+1),r=parseInt(n,10),i?(r*=2,F+=r>=10?r%10+1:r):F+=r,i=!i;return!!(F%10===0?e:!1)},t.isISBN=function(e,n){if(n=t.toString(n),!n)return t.isISBN(e,10)||t.isISBN(e,13);var r,u=e.replace(/[\s-]+/g,""),o=0;if("10"===n){if(!i.test(u))return!1;for(r=0;9>r;r++)o+=(r+1)*u.charAt(r);if(o+="X"===u.charAt(9)?100:10*u.charAt(9),o%11===0)return!!u}else if("13"===n){if(!F.test(u))return!1;var a=[1,3];for(r=0;12>r;r++)o+=a[r%2]*u.charAt(r);if(u.charAt(12)-(10-o%10)%10===0)return!!u}return!1},t.isJSON=function(t){try{JSON.parse(t)}catch(e){return!1}return!0},t.isMultibyte=function(t){return g.test(t)},t.isAscii=function(t){return x.test(t)},t.isFullWidth=function(t){return E.test(t)},t.isHalfWidth=function(t){return h.test(t)},t.isVariableWidth=function(t){return E.test(t)&&h.test(t)},t.isSurrogatePair=function(t){return $.test(t)},t.isBase64=function(t){return v.test(t)},t.ltrim=function(t,e){var n=e?new RegExp("^["+e+"]+","g"):/^\s+/g;return t.replace(n,"")},t.rtrim=function(t,e){var n=e?new RegExp("["+e+"]+$","g"):/\s+$/g;return t.replace(n,"")},t.trim=function(t,e){var n=e?new RegExp("^["+e+"]+|["+e+"]+$","g"):/^\s+|\s+$/g;return t.replace(n,"")},t.escape=function(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")},t.stripLow=function(e,n){var r=n?"\x00- \f-":"\x00-";return t.blacklist(e,r)},t.whitelist=function(t,e){return t.replace(new RegExp("[^"+e+"]+","g"),"")},t.blacklist=function(t,e){return t.replace(new RegExp("["+e+"]+","g"),"")},t.normalizeEmail=function(t){var e=t.toLowerCase().split("@",2);return("gmail.com"===e[1]||"googlemail.com"===e[1])&&(e[0]=e[0].replace(".","").split("+")[0],t=e.join("@")),t},t.init(),t}); \ No newline at end of file +!(function(e,t){if(typeof exports!=="undefined"&&typeof module!=="undefined"){module.exports=t()}else if(typeof define==="function"&&typeof define.amd==="object"){define(t)}else{this[e]=t()}})("validator",function(e){"use strict";function x(e,t){e=e||{};for(var n in t){if(typeof e[n]==="undefined"){e[n]=t[n]}}return e}function T(e){var t="-?-?"+(e.allow_underscores?"_?":""),n="a-z\\u00a1-\\uffff",r=n+"0-9",i="(?:(?:["+r+"]+"+t+")*["+r+"]+)",s="(?:\\.(?:["+n+"]{2,}))"+(e.require_tld?"":"?");return"(?:"+i+"(?:\\."+i+")*"+s+")"}function N(e,t,n){var r=n==="include"?false:true,i;if(t[n]){i=t[n].split(",");for(var s in i){if(n==="include"&&e.indexOf(i[s].trim())>-1||false){return!r}else if(n==="exclude"&&!(e.indexOf(i[s].trim())<0||false)){return!r}}}else{r=true}return r}e={version:"3.18.1"};var t=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\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]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;var n=/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|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})$/;var r=/^(?:[0-9]{9}X|[0-9]{10})$/,i=/^(?:[0-9]{13})$/;var s=/^(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)$/,o=/^::|^::1|^([a-fA-F0-9]{1,4}::?){1,7}([a-fA-F0-9]{1,4})$/;var u={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i};var a=/^[a-zA-Z]+$/,f=/^[a-zA-Z0-9]+$/,l=/^-?[0-9]+$/,c=/^(?:-?(?:0|[1-9][0-9]*))$/,h=/^(?:-?(?:[0-9]+))?(?:\.[0-9]*)?(?:[eE][\+\-]?(?:[0-9]+))?$/,p=/^[0-9a-fA-F]+$/,d=/^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;var v=/^[\x00-\x7F]+$/,m=/[^\x00-\x7F]/,g=/[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/,y=/[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var b=/[\uD800-\uDBFF][\uDC00-\uDFFF]/;var w=/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/;var E={protocols:["http","https","ftp"],require_tld:true,require_protocol:false,allow_underscores:false,include_domains:[],exclude_domains:[]};e.extend=function(t,n){e[t]=function(){var t=Array.prototype.slice.call(arguments);t[0]=e.toString(t[0]);return n.apply(e,t)}};e.init=function(){for(var t in e){if(typeof e[t]!=="function"||t==="toString"||t==="toDate"||t==="extend"||t==="init"){continue}e.extend(t,e[t])}};e.toString=function(e){if(typeof e==="object"&&e!==null&&e.toString){e=e.toString()}else if(e===null||typeof e==="undefined"||isNaN(e)&&!e.length){e=""}else if(typeof e!=="string"){e+=""}return e};e.toDate=function(e){if(Object.prototype.toString.call(e)==="[object Date]"){return e}e=Date.parse(e);return!isNaN(e)?new Date(e):null};e.toFloat=function(e){return parseFloat(e)};e.toInt=function(e,t){return parseInt(e,t||10)};e.toBoolean=function(e,t){if(t){return e==="1"||e==="true"}return e!=="0"&&e!=="false"&&e!==""};e.equals=function(t,n){return t===e.toString(n)};e.contains=function(t,n){return t.indexOf(e.toString(n))>=0};e.matches=function(e,t,n){if(Object.prototype.toString.call(t)!=="[object RegExp]"){t=new RegExp(t,n)}return t.test(e)};e.isEmail=function(e){return t.test(e)};e.isURL=function(e,t){if(!e||e.length>=2083){return false}t=x(t,E);var n=["(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])","(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}",,"(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))"];var r="(?:(?:"+t.protocols.join("|")+")://)"+(t.require_protocol?"":"?"),i="(?:\\S+(?::\\S*)?@)?",s="(?:"+n.join("")+")",o="(?:"+s+"|"+T(t)+"|localhost)",u="(\\d{1,5})",a=o+"(?::"+u+")?",f="(?:(?:/|\\?|#)[^\\s]*)?",l=t.include_domains.length?t.include_domains.indexOf(e)!==-1:true,c=t.exclude_domains.length?t.exclude_domains.indexOf(e)===-1:true;var h=new RegExp("^(?!mailto:)"+r+i+a+f+"$","i");var p=e.match(h),d=p?p[1]:0;return!!(p&&(!d||d>0&&d<=65535)&&l&&c)};e.isIP=function(t,n){n=e.toString(n);if(!n){return e.isIP(t,4)||e.isIP(t,6)}else if(n==="4"){if(!s.test(t)){return false}var r=t.split(".").sort(function(e,t){return e-t});return r[3]<=255}return n==="6"&&o.test(t)};var S={require_tld:true,allow_underscores:false};e.isFQDN=function(e,t){t=x(t,S);return(new RegExp("^"+T(t)+"$","i")).test(e)};e.isAlpha=function(e){return a.test(e)};e.isAlphanumeric=function(e){return f.test(e)};e.isNumeric=function(e){return l.test(e)};e.isHexadecimal=function(e){return p.test(e)};e.isHexColor=function(e){return d.test(e)};e.isLowercase=function(e){return e===e.toLowerCase()};e.isUppercase=function(e){return e===e.toUpperCase()};e.isInt=function(e){return c.test(e)};e.isFloat=function(e){return e!==""&&h.test(e)};e.isDivisibleBy=function(t,n){return e.toFloat(t)%e.toInt(n)===0};e.isNull=function(e){return e.length===0};e.isLength=function(e,t,n){var r=e.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g)||[];var i=e.length-r.length;return i>=t&&(typeof n==="undefined"||i<=n)};e.isByteLength=function(e,t,n){return e.length>=t&&(typeof n==="undefined"||e.length<=n)};e.isUUID=function(e,t){var n=u[t?t:"all"];return n&&n.test(e)};e.isDate=function(e){return!isNaN(Date.parse(e))};e.isAfter=function(t,n){var r=e.toDate(n||new Date),i=e.toDate(t);return!!(i&&r&&i>r)};e.isBefore=function(t,n){var r=e.toDate(n||new Date),i=e.toDate(t);return i&&r&&i=0};e.isCreditCard=function(e){var t=e.replace(/[^0-9]+/g,"");if(!n.test(t)){return false}var r=0,i,s,o;for(var u=t.length-1;u>=0;u--){i=t.substring(u,u+1);s=parseInt(i,10);if(o){s*=2;if(s>=10){r+=s%10+1}else{r+=s}}else{r+=s}o=!o}return!!(r%10===0?t:false)};e.isISBN=function(t,n){n=e.toString(n);if(!n){return e.isISBN(t,10)||e.isISBN(t,13)}var s=t.replace(/[\s-]+/g,""),o=0,u;if(n==="10"){if(!r.test(s)){return false}for(u=0;u<9;u++){o+=(u+1)*s.charAt(u)}if(s.charAt(9)==="X"){o+=10*10}else{o+=10*s.charAt(9)}if(o%11===0){return!!s}}else if(n==="13"){if(!i.test(s)){return false}var a=[1,3];for(u=0;u<12;u++){o+=a[u%2]*s.charAt(u)}if(s.charAt(12)-(10-o%10)%10===0){return!!s}}return false};e.isJSON=function(e){try{JSON.parse(e)}catch(t){return false}return true};e.isMultibyte=function(e){return m.test(e)};e.isAscii=function(e){return v.test(e)};e.isFullWidth=function(e){return g.test(e)};e.isHalfWidth=function(e){return y.test(e)};e.isVariableWidth=function(e){return g.test(e)&&y.test(e)};e.isSurrogatePair=function(e){return b.test(e)};e.isBase64=function(e){return w.test(e)};e.ltrim=function(e,t){var n=t?new RegExp("^["+t+"]+","g"):/^\s+/g;return e.replace(n,"")};e.rtrim=function(e,t){var n=t?new RegExp("["+t+"]+$","g"):/\s+$/g;return e.replace(n,"")};e.trim=function(e,t){var n=t?new RegExp("^["+t+"]+|["+t+"]+$","g"):/^\s+|\s+$/g;return e.replace(n,"")};e.escape=function(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")};e.stripLow=function(t,n){var r=n?"\0- \f-":"\0-";return e.blacklist(t,r)};e.whitelist=function(e,t){return e.replace(new RegExp("[^"+t+"]+","g"),"")};e.blacklist=function(e,t){return e.replace(new RegExp("["+t+"]+","g"),"")};e.normalizeEmail=function(e){var t=e.toLowerCase().split("@",2);if(t[1]==="gmail.com"||t[1]==="googlemail.com"){t[0]=t[0].replace(".","").split("+")[0];e=t.join("@")}return e};e.init();return e})