diff --git a/README.md b/README.md index 671d4862c..e3533e1ae 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,7 @@ Validator | Description **isMultibyte(str)** | check if the string contains one or more multibyte chars. **isNumeric(str [, options])** | check if the string contains only numbers.

`options` is an object which defaults to `{no_symbols: false}`. If `no_symbols` is true, the validator will reject numeric strings that feature a symbol (e.g. `+`, `-`, or `.`). **isOctal(str)** | check if the string is a valid octal number. +**isPassportNumber(str, countryCode) | check if the string is a valid passport number relative to a specific country code. **isPort(str)** | check if the string is a valid port number. **isPostalCode(str, locale)** | check if the string is a postal code,

(locale is one of `[ 'AD', 'AT', 'AU', 'BE', 'BG', 'BR', 'CA', 'CH', 'CZ', 'DE', 'DK', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'ID', 'IE' 'IL', 'IN', 'IR', 'IS', 'IT', 'JP', 'KE', 'LI', 'LT', 'LU', 'LV', 'MT', 'MX', 'NL', 'NO', 'NZ', 'PL', 'PR', 'PT', 'RO', 'RU', 'SA', 'SE', 'SI', 'TN', 'TW', 'UA', 'US', 'ZA', 'ZM' ]` OR 'any'. If 'any' is used, function will check if any of the locals match. Locale list is `validator.isPostalCodeLocales`.). **isSemVer(str)** | check if the string is a Semantic Versioning Specification (SemVer). diff --git a/index.js b/index.js index 75851f449..b02bf86ae 100644 --- a/index.js +++ b/index.js @@ -35,12 +35,16 @@ var _isFQDN = _interopRequireDefault(require("./lib/isFQDN")); var _isBoolean = _interopRequireDefault(require("./lib/isBoolean")); +var _isLocale = _interopRequireDefault(require("./lib/isLocale")); + var _isAlpha = _interopRequireWildcard(require("./lib/isAlpha")); var _isAlphanumeric = _interopRequireWildcard(require("./lib/isAlphanumeric")); var _isNumeric = _interopRequireDefault(require("./lib/isNumeric")); +var _isPassportNumber = _interopRequireDefault(require("./lib/isPassportNumber")); + var _isPort = _interopRequireDefault(require("./lib/isPort")); var _isLowercase = _interopRequireDefault(require("./lib/isLowercase")); @@ -201,6 +205,7 @@ var validator = { isAlphanumeric: _isAlphanumeric.default, isAlphanumericLocales: _isAlphanumeric.locales, isNumeric: _isNumeric.default, + isPassportNumber: _isPassportNumber.default, isPort: _isPort.default, isLowercase: _isLowercase.default, isUppercase: _isUppercase.default, @@ -227,6 +232,7 @@ var validator = { isJSON: _isJSON.default, isEmpty: _isEmpty.default, isLength: _isLength.default, + isLocale: _isLocale.default, isByteLength: _isByteLength.default, isUUID: _isUUID.default, isMongoId: _isMongoId.default, diff --git a/lib/isPassportNumber.js b/lib/isPassportNumber.js new file mode 100644 index 000000000..6b101bc60 --- /dev/null +++ b/lib/isPassportNumber.js @@ -0,0 +1,112 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = isPassportNumber; + +/** + * Reference: + * https://en.wikipedia.org/ -- Wikipedia + * https://docs.microsoft.com/en-us/microsoft-365/compliance/eu-passport-number -- EU Passport Number + * https://countrycode.org/ -- Country Codes + */ +var passportRegexByCountryCode = { + AM: /^[A-Z]{2}\d{7}$/, + // ARMENIA + AR: /^[A-Z]{3}\d{6}$/, + // ARGENTINA + AT: /^[A-Z]\d{7}$/, + // AUSTRIA + AU: /^[A-Z]\d{7}$/, + // AUSTRALIA + BE: /^[A-Z]{2}\d{6}$/, + // BELGIUM + BG: /^\d{9}$/, + // BULGARIA + CA: /^[A-Z]{2}\d{6}$/, + // CANADA + CH: /^[A-Z]\d{7}$/, + // SWITZERLAND + CN: /^[GE]\d{8}$/, + // CHINA [G=Ordinary, E=Electronic] followed by 8-digits + CY: /^[A-Z](\d{6}|\d{8})$/, + // CYPRUS + CZ: /^\d{8}$/, + // CZECH REPUBLIC + DE: /^[CFGHJKLMNPRTVWXYZ0-9]{9}$/, + // GERMANY + DK: /^\d{9}$/, + // DENMARK + EE: /^([A-Z]\d{7}|[A-Z]{2}\d{7})$/, + // ESTONIA (K followed by 7-digits), e-passports have 2 UPPERCASE followed by 7 digits + ES: /^[A-Z0-9]{2}([A-Z0-9]?)\d{6}$/, + // SPAIN + FI: /^[A-Z]{2}\d{7}$/, + // FINLAND + FR: /^\d{2}[A-Z]{2}\d{5}$/, + // FRANCE + GB: /^\d{9}$/, + // UNITED KINGDOM + GR: /^[A-Z]{2}\d{7}$/, + // GREECE + HR: /^\d{9}$/, + // CROATIA + HU: /^[A-Z]{2}(\d{6}|\d{7})$/, + // HUNGARY + IE: /^[A-Z0-9]{2}\d{7}$/, + // IRELAND + IS: /^(A)\d{7}$/, + // ICELAND + IT: /^[A-Z0-9]{2}\d{7}$/, + // ITALY + JP: /^[A-Z]{2}\d{7}$/, + // JAPAN + KR: /^[MS]\d{8}$/, + // SOUTH KOREA, REPUBLIC OF KOREA, [S=PS Passports, M=PM Passports] + LT: /^[A-Z0-9]{8}$/, + // LITHUANIA + LU: /^[A-Z0-9]{8}$/, + // LUXEMBURG + LV: /^[A-Z0-9]{2}\d{7}$/, + // LATVIA + MT: /^\d{7}$/, + // MALTA + NL: /^[A-Z]{2}[A-Z0-9]{6}\d$/, + // NETHERLANDS + PO: /^[A-Z]{2}\d{7}$/, + // POLAND + PT: /^[A-Z]\d{6}$/, + // PORTUGAL + RO: /^\d{8,9}$/, + // ROMANIA + SE: /^\d{8}$/, + // SWEDEN + SL: /^(P)[A-Z]\d{7}$/, + // SLOVANIA + SK: /^[0-9A-Z]\d{7}$/, + // SLOVAKIA + TR: /^[A-Z]\d{8}$/, + // TURKEY + UA: /^[A-Z]{2}\d{6}$/, + // UKRAINE + US: /^\d{9}$/ // UNITED STATES + +}; +/** + * Check if str is a valid passport number + * relative to provided ISO Country Code. + * + * @param {string} str + * @param {string} countryCode + * @return {boolean} + */ + +function isPassportNumber(str, countryCode) { + /** Remove All Whitespaces, Convert to UPPERCASE */ + var normalizedStr = str.replace(/\s/g, '').toUpperCase(); + return countryCode.toUpperCase() in passportRegexByCountryCode && passportRegexByCountryCode[countryCode].test(normalizedStr); +} + +module.exports = exports.default; +module.exports.default = exports.default; \ No newline at end of file diff --git a/src/index.js b/src/index.js index 4bf522d34..68645f78e 100644 --- a/src/index.js +++ b/src/index.js @@ -19,6 +19,7 @@ import isLocale from './lib/isLocale'; import isAlpha, { locales as isAlphaLocales } from './lib/isAlpha'; import isAlphanumeric, { locales as isAlphanumericLocales } from './lib/isAlphanumeric'; import isNumeric from './lib/isNumeric'; +import isPassportNumber from './lib/isPassportNumber'; import isPort from './lib/isPort'; import isLowercase from './lib/isLowercase'; import isUppercase from './lib/isUppercase'; @@ -134,6 +135,7 @@ const validator = { isAlphanumeric, isAlphanumericLocales, isNumeric, + isPassportNumber, isPort, isLowercase, isUppercase, diff --git a/src/lib/isPassportNumber.js b/src/lib/isPassportNumber.js new file mode 100644 index 000000000..304f72fae --- /dev/null +++ b/src/lib/isPassportNumber.js @@ -0,0 +1,64 @@ +/** + * Reference: + * https://en.wikipedia.org/ -- Wikipedia + * https://docs.microsoft.com/en-us/microsoft-365/compliance/eu-passport-number -- EU Passport Number + * https://countrycode.org/ -- Country Codes + */ +const passportRegexByCountryCode = { + AM: /^[A-Z]{2}\d{7}$/, // ARMENIA + AR: /^[A-Z]{3}\d{6}$/, // ARGENTINA + AT: /^[A-Z]\d{7}$/, // AUSTRIA + AU: /^[A-Z]\d{7}$/, // AUSTRALIA + BE: /^[A-Z]{2}\d{6}$/, // BELGIUM + BG: /^\d{9}$/, // BULGARIA + CA: /^[A-Z]{2}\d{6}$/, // CANADA + CH: /^[A-Z]\d{7}$/, // SWITZERLAND + CN: /^[GE]\d{8}$/, // CHINA [G=Ordinary, E=Electronic] followed by 8-digits + CY: /^[A-Z](\d{6}|\d{8})$/, // CYPRUS + CZ: /^\d{8}$/, // CZECH REPUBLIC + DE: /^[CFGHJKLMNPRTVWXYZ0-9]{9}$/, // GERMANY + DK: /^\d{9}$/, // DENMARK + EE: /^([A-Z]\d{7}|[A-Z]{2}\d{7})$/, // ESTONIA (K followed by 7-digits), e-passports have 2 UPPERCASE followed by 7 digits + ES: /^[A-Z0-9]{2}([A-Z0-9]?)\d{6}$/, // SPAIN + FI: /^[A-Z]{2}\d{7}$/, // FINLAND + FR: /^\d{2}[A-Z]{2}\d{5}$/, // FRANCE + GB: /^\d{9}$/, // UNITED KINGDOM + GR: /^[A-Z]{2}\d{7}$/, // GREECE + HR: /^\d{9}$/, // CROATIA + HU: /^[A-Z]{2}(\d{6}|\d{7})$/, // HUNGARY + IE: /^[A-Z0-9]{2}\d{7}$/, // IRELAND + IS: /^(A)\d{7}$/, // ICELAND + IT: /^[A-Z0-9]{2}\d{7}$/, // ITALY + JP: /^[A-Z]{2}\d{7}$/, // JAPAN + KR: /^[MS]\d{8}$/, // SOUTH KOREA, REPUBLIC OF KOREA, [S=PS Passports, M=PM Passports] + LT: /^[A-Z0-9]{8}$/, // LITHUANIA + LU: /^[A-Z0-9]{8}$/, // LUXEMBURG + LV: /^[A-Z0-9]{2}\d{7}$/, // LATVIA + MT: /^\d{7}$/, // MALTA + NL: /^[A-Z]{2}[A-Z0-9]{6}\d$/, // NETHERLANDS + PO: /^[A-Z]{2}\d{7}$/, // POLAND + PT: /^[A-Z]\d{6}$/, // PORTUGAL + RO: /^\d{8,9}$/, // ROMANIA + SE: /^\d{8}$/, // SWEDEN + SL: /^(P)[A-Z]\d{7}$/, // SLOVANIA + SK: /^[0-9A-Z]\d{7}$/, // SLOVAKIA + TR: /^[A-Z]\d{8}$/, // TURKEY + UA: /^[A-Z]{2}\d{6}$/, // UKRAINE + US: /^\d{9}$/, // UNITED STATES +}; + +/** + * Check if str is a valid passport number + * relative to provided ISO Country Code. + * + * @param {string} str + * @param {string} countryCode + * @return {boolean} + */ +export default function isPassportNumber(str, countryCode) { + /** Remove All Whitespaces, Convert to UPPERCASE */ + const normalizedStr = str.replace(/\s/g, '').toUpperCase(); + + return (countryCode.toUpperCase() in passportRegexByCountryCode) && + passportRegexByCountryCode[countryCode].test(normalizedStr); +} diff --git a/test/validators.js b/test/validators.js index 404c1d928..b5e413403 100644 --- a/test/validators.js +++ b/test/validators.js @@ -1853,6 +1853,522 @@ describe('Validators', () => { }); }); + it('should validate passport number', () => { + test({ + validator: 'isPassportNumber', + args: ['AM'], + valid: [ + 'AF0549358', + ], + invalid: [ + 'A1054935', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['AR'], + valid: [ + 'AAC811035', + ], + invalid: [ + 'A11811035', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['AT'], + valid: [ + 'P 1630837', + 'P 4366918', + ], + invalid: [ + '0 1630837', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['AU'], + valid: [ + 'N0995852', + 'L4819236', + ], + invalid: [ + '1A012345', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['BE'], + valid: [ + 'EM000000', + 'LA080402', + ], + invalid: [ + '00123456', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['BG'], + valid: [ + '346395366', + '039903356', + ], + invalid: [ + 'ABC123456', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['CA'], + valid: [ + 'GA302922', + 'ZE000509', + ], + invalid: [ + 'AB0123456', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['CH'], + valid: [ + 'S1100409', + 'S5200073', + 'X4028791', + ], + invalid: [ + 'AB123456', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['CN'], + valid: [ + 'G25352389', + 'E00160027', + ], + invalid: [ + 'K0123456', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['CY'], + valid: [ + 'K00000413', + ], + invalid: [ + 'K10100', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['CZ'], + valid: [ + '99003853', + '42747260', + ], + invalid: [ + '012345678', + 'AB123456', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['DE'], + valid: [ + 'C01X00T47', + 'C26VMVVC3', + ], + invalid: [ + 'AS0123456', + 'A012345678', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['DK'], + valid: [ + '900010172', + ], + invalid: [ + '01234567', + 'K01234567', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['EE'], + valid: [ + 'K4218285', + 'K3295867', + 'KB0167630', + 'VD0023777', + ], + invalid: [ + 'K01234567', + 'KB00112233', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['ES'], + valid: [ + 'AF238143', + 'ZAB000254', + ], + invalid: [ + 'AF01234567', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['FI'], + valid: [ + 'XP8271602', + 'XD8500003', + ], + invalid: [ + 'A01234567', + 'ABC012345', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['FR'], + valid: [ + '10CV28144', + '60RF19342', + '05RP34083', + ], + invalid: [ + '012345678', + 'AB0123456', + '01C234567', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['GB'], + valid: [ + '925076473', + '107182890', + '104121156', + ], + invalid: [ + 'A012345678', + 'K000000000', + '0123456789', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['GR'], + valid: [ + 'AE0000005', + 'AK0219304', + ], + invalid: [ + 'A01234567', + '012345678', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['HR'], + valid: [ + '007007007', + '138463188', + ], + invalid: [ + 'A01234567', + '00112233', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['HU'], + valid: [ + 'ZA084505', + 'BA0006902', + ], + invalid: [ + 'A01234567', + '012345678', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['IE'], + valid: [ + 'D23145890', + 'X65097105', + 'XN0019390', + ], + invalid: [ + 'XND012345', + '0123456789', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['IS'], + valid: [ + 'A2040611', + 'A1197783', + ], + invalid: [ + 'K0000000', + '01234567', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['IT'], + valid: [ + 'YA8335453', + 'KK0000000', + ], + invalid: [ + '01234567', + 'KAK001122', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['JP'], + valid: [ + 'NH1106002', + 'TE3180251', + 'XS1234567', + ], + invalid: [ + 'X12345678', + '012345678', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['KR'], + valid: [ + 'M35772699', + 'M70689098', + ], + invalid: [ + 'X12345678', + '012345678', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['LT'], + valid: [ + '20200997', + 'LB311756', + ], + invalid: [ + 'LB01234567', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['LU'], + valid: [ + 'JCU9J4T2', + 'JC4E7L2H', + ], + invalid: [ + 'JCU9J4T', + 'JC4E7L2H0', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['LV'], + valid: [ + 'LV9000339', + 'LV4017173', + ], + invalid: [ + 'LV01234567', + '4017173LV', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['MT'], + valid: [ + '1026564', + ], + invalid: [ + '01234567', + 'MT01234', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['NL'], + valid: [ + 'XTR110131', + 'XR1001R58', + ], + invalid: [ + 'XTR11013R', + 'XR1001R58A', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['PO'], + valid: [ + 'ZS 0000177', + 'AN 3000011', + ], + invalid: [ + 'A1 0000177', + '012345678', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['PT'], + valid: [ + 'I700044', + 'K453286', + ], + invalid: [ + '0700044', + 'K4532861', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['RO'], + valid: [ + '05485968', + '040005646', + ], + invalid: [ + 'R05485968', + '0511060461', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['SE'], + valid: [ + '59000001', + '56702928', + ], + invalid: [ + 'SE012345', + '012345678', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['SL'], + valid: [ + 'PB0036440', + 'PB1390281', + ], + invalid: [ + 'SL0123456', + 'P01234567', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['SK'], + valid: [ + 'P0000000', + ], + invalid: [ + 'SK012345', + '012345678', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['TR'], + valid: [ + 'U 06764100', + 'U 01048537', + ], + invalid: [ + '06764100U', + '010485371', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['UA'], + valid: [ + 'EH345655', + 'EK000001', + 'AP841503', + ], + invalid: [ + '01234567', + '012345EH', + 'A012345P', + ], + }); + + test({ + validator: 'isPassportNumber', + args: ['US'], + valid: [ + '790369937', + '340007237', + ], + invalid: [ + 'US0123456', + '0123456US', + '7903699371', + ], + }); + }); + it('should validate decimal numbers', () => { test({ validator: 'isDecimal', diff --git a/validator.js b/validator.js index 96e0e000b..645c79876 100644 --- a/validator.js +++ b/validator.js @@ -884,6 +884,109 @@ function isNumeric(str, options) { return numeric.test(str); } +/** + * Reference: + * https://en.wikipedia.org/ -- Wikipedia + * https://docs.microsoft.com/en-us/microsoft-365/compliance/eu-passport-number -- EU Passport Number + * https://countrycode.org/ -- Country Codes + */ +var passportRegexByCountryCode = { + AM: /^[A-Z]{2}\d{7}$/, + // ARMENIA + AR: /^[A-Z]{3}\d{6}$/, + // ARGENTINA + AT: /^[A-Z]\d{7}$/, + // AUSTRIA + AU: /^[A-Z]\d{7}$/, + // AUSTRALIA + BE: /^[A-Z]{2}\d{6}$/, + // BELGIUM + BG: /^\d{9}$/, + // BULGARIA + CA: /^[A-Z]{2}\d{6}$/, + // CANADA + CH: /^[A-Z]\d{7}$/, + // SWITZERLAND + CN: /^[GE]\d{8}$/, + // CHINA [G=Ordinary, E=Electronic] followed by 8-digits + CY: /^[A-Z](\d{6}|\d{8})$/, + // CYPRUS + CZ: /^\d{8}$/, + // CZECH REPUBLIC + DE: /^[CFGHJKLMNPRTVWXYZ0-9]{9}$/, + // GERMANY + DK: /^\d{9}$/, + // DENMARK + EE: /^([A-Z]\d{7}|[A-Z]{2}\d{7})$/, + // ESTONIA (K followed by 7-digits), e-passports have 2 UPPERCASE followed by 7 digits + ES: /^[A-Z0-9]{2}([A-Z0-9]?)\d{6}$/, + // SPAIN + FI: /^[A-Z]{2}\d{7}$/, + // FINLAND + FR: /^\d{2}[A-Z]{2}\d{5}$/, + // FRANCE + GB: /^\d{9}$/, + // UNITED KINGDOM + GR: /^[A-Z]{2}\d{7}$/, + // GREECE + HR: /^\d{9}$/, + // CROATIA + HU: /^[A-Z]{2}(\d{6}|\d{7})$/, + // HUNGARY + IE: /^[A-Z0-9]{2}\d{7}$/, + // IRELAND + IS: /^(A)\d{7}$/, + // ICELAND + IT: /^[A-Z0-9]{2}\d{7}$/, + // ITALY + JP: /^[A-Z]{2}\d{7}$/, + // JAPAN + KR: /^[MS]\d{8}$/, + // SOUTH KOREA, REPUBLIC OF KOREA, [S=PS Passports, M=PM Passports] + LT: /^[A-Z0-9]{8}$/, + // LITHUANIA + LU: /^[A-Z0-9]{8}$/, + // LUXEMBURG + LV: /^[A-Z0-9]{2}\d{7}$/, + // LATVIA + MT: /^\d{7}$/, + // MALTA + NL: /^[A-Z]{2}[A-Z0-9]{6}\d$/, + // NETHERLANDS + PO: /^[A-Z]{2}\d{7}$/, + // POLAND + PT: /^[A-Z]\d{6}$/, + // PORTUGAL + RO: /^\d{8,9}$/, + // ROMANIA + SE: /^\d{8}$/, + // SWEDEN + SL: /^(P)[A-Z]\d{7}$/, + // SLOVANIA + SK: /^[0-9A-Z]\d{7}$/, + // SLOVAKIA + TR: /^[A-Z]\d{8}$/, + // TURKEY + UA: /^[A-Z]{2}\d{6}$/, + // UKRAINE + US: /^\d{9}$/ // UNITED STATES + +}; +/** + * Check if str is a valid passport number + * relative to provided ISO Country Code. + * + * @param {string} str + * @param {string} countryCode + * @return {boolean} + */ + +function isPassportNumber(str, countryCode) { + /** Remove All Whitespaces, Convert to UPPERCASE */ + var normalizedStr = str.replace(/\s/g, '').toUpperCase(); + return countryCode.toUpperCase() in passportRegexByCountryCode && passportRegexByCountryCode[countryCode].test(normalizedStr); +} + var _int = /^(?:[-+]?(?:0|[1-9][0-9]*))$/; var intLeadingZeroes = /^[-+]?[0-9]+$/; function isInt(str, options) { @@ -2394,6 +2497,7 @@ var validator = { isAlphanumeric: isAlphanumeric, isAlphanumericLocales: locales$2, isNumeric: isNumeric, + isPassportNumber: isPassportNumber, isPort: isPort, isLowercase: isLowercase, isUppercase: isUppercase, @@ -2420,6 +2524,7 @@ var validator = { isJSON: isJSON, isEmpty: isEmpty, isLength: isLength, + isLocale: isLocale, isByteLength: isByteLength, isUUID: isUUID, isMongoId: isMongoId, diff --git a/validator.min.js b/validator.min.js index a2f8abf4d..4ead8d57b 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){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.validator=e()}(this,function(){"use strict";function a(t){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function g(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){if(!(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t)))return;var r=[],n=!0,o=!1,i=void 0;try{for(var a,s=t[Symbol.iterator]();!(n=(a=s.next()).done)&&(r.push(a.value),!e||r.length!==e);n=!0);}catch(t){o=!0,i=t}finally{try{n||null==s.return||s.return()}finally{if(o)throw i}}return r}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function h(t){var e;if(!("string"==typeof t||t instanceof String))throw e=null===t?"null":"object"===(e=a(t))&&t.constructor&&t.constructor.hasOwnProperty("name")?t.constructor.name:"a ".concat(e),new TypeError("Expected string but received ".concat(e,"."))}function o(t){return h(t),t=Date.parse(t),isNaN(t)?null:new Date(t)}for(var t,r={"en-US":/^[A-Z]+$/i,"bg-BG":/^[А-Я]+$/i,"cs-CZ":/^[A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]+$/i,"da-DK":/^[A-ZÆØÅ]+$/i,"de-DE":/^[A-ZÄÖÜß]+$/i,"el-GR":/^[Α-ώ]+$/i,"es-ES":/^[A-ZÁÉÍÑÓÚÜ]+$/i,"fr-FR":/^[A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ]+$/i,"it-IT":/^[A-ZÀÉÈÌÎÓÒÙ]+$/i,"nb-NO":/^[A-ZÆØÅ]+$/i,"nl-NL":/^[A-ZÁÉËÏÓÖÜÚ]+$/i,"nn-NO":/^[A-ZÆØÅ]+$/i,"hu-HU":/^[A-ZÁÉÍÓÖŐÚÜŰ]+$/i,"pl-PL":/^[A-ZĄĆĘŚŁŃÓŻŹ]+$/i,"pt-PT":/^[A-ZÃÁÀÂÄÇÉÊËÍÏÕÓÔÖÚÜ]+$/i,"ru-RU":/^[А-ЯЁ]+$/i,"sl-SI":/^[A-ZČĆĐŠŽ]+$/i,"sk-SK":/^[A-ZÁČĎÉÍŇÓŠŤÚÝŽĹŔĽÄÔ]+$/i,"sr-RS@latin":/^[A-ZČĆŽŠĐ]+$/i,"sr-RS":/^[А-ЯЂЈЉЊЋЏ]+$/i,"sv-SE":/^[A-ZÅÄÖ]+$/i,"tr-TR":/^[A-ZÇĞİıÖŞÜ]+$/i,"uk-UA":/^[А-ЩЬЮЯЄIЇҐі]+$/i,"ku-IQ":/^[ئابپتجچحخدرڕزژسشعغفڤقکگلڵمنوۆھەیێيطؤثآإأكضصةظذ]+$/i,ar:/^[ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]+$/,he:/^[א-ת]+$/,"fa-IR":/^['آابپتثجچهخدذرزژسشصضطظعغفقکگلمنوهی']+$/i},n={"en-US":/^[0-9A-Z]+$/i,"bg-BG":/^[0-9А-Я]+$/i,"cs-CZ":/^[0-9A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]+$/i,"da-DK":/^[0-9A-ZÆØÅ]+$/i,"de-DE":/^[0-9A-ZÄÖÜß]+$/i,"el-GR":/^[0-9Α-ω]+$/i,"es-ES":/^[0-9A-ZÁÉÍÑÓÚÜ]+$/i,"fr-FR":/^[0-9A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ]+$/i,"it-IT":/^[0-9A-ZÀÉÈÌÎÓÒÙ]+$/i,"hu-HU":/^[0-9A-ZÁÉÍÓÖŐÚÜŰ]+$/i,"nb-NO":/^[0-9A-ZÆØÅ]+$/i,"nl-NL":/^[0-9A-ZÁÉËÏÓÖÜÚ]+$/i,"nn-NO":/^[0-9A-ZÆØÅ]+$/i,"pl-PL":/^[0-9A-ZĄĆĘŚŁŃÓŻŹ]+$/i,"pt-PT":/^[0-9A-ZÃÁÀÂÄÇÉÊËÍÏÕÓÔÖÚÜ]+$/i,"ru-RU":/^[0-9А-ЯЁ]+$/i,"sl-SI":/^[0-9A-ZČĆĐŠŽ]+$/i,"sk-SK":/^[0-9A-ZÁČĎÉÍŇÓŠŤÚÝŽĹŔĽÄÔ]+$/i,"sr-RS@latin":/^[0-9A-ZČĆŽŠĐ]+$/i,"sr-RS":/^[0-9А-ЯЂЈЉЊЋЏ]+$/i,"sv-SE":/^[0-9A-ZÅÄÖ]+$/i,"tr-TR":/^[0-9A-ZÇĞİıÖŞÜ]+$/i,"uk-UA":/^[0-9А-ЩЬЮЯЄIЇҐі]+$/i,"ku-IQ":/^[٠١٢٣٤٥٦٧٨٩0-9ئابپتجچحخدرڕزژسشعغفڤقکگلڵمنوۆھەیێيطؤثآإأكضصةظذ]+$/i,ar:/^[٠١٢٣٤٥٦٧٨٩0-9ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]+$/,he:/^[0-9א-ת]+$/,"fa-IR":/^['0-9آابپتثجچهخدذرزژسشصضطظعغفقکگلمنوهی۱۲۳۴۵۶۷۸۹۰']+$/i},i={"en-US":".",ar:"٫"},e=["AU","GB","HK","IN","NZ","ZA","ZM"],s=0;s=e.min)&&(!e.hasOwnProperty("max")||n<=e.max)&&(!e.hasOwnProperty("lt")||ne.gt)}r["pt-BR"]=r["pt-PT"],n["pt-BR"]=n["pt-PT"],i["pt-BR"]=i["pt-PT"],r["pl-Pl"]=r["pl-PL"],n["pl-Pl"]=n["pl-PL"],i["pl-Pl"]=i["pl-PL"];var m=Object.keys(i);function v(t){return p(t)?parseFloat(t):NaN}function _(t){return"object"===a(t)&&null!==t?t="function"==typeof t.toString?t.toString():"[object Object]":(null==t||isNaN(t)&&!t.length)&&(t=""),String(t)}function Z(t,e){var r=0a)return!1;if("::"===t)return!0;"::"===t.substr(0,2)?(n.shift(),n.shift(),o=!0):"::"===t.substr(t.length-2)&&(n.pop(),n.pop(),o=!0);for(var s=0;s$/i,N=/^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~]+$/i,T=/^[a-z\d]+$/,x=/^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f]))*$/i,B=/^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+$/i,w=/^([\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;var G={protocols:["http","https","ftp"],require_tld:!0,require_protocol:!1,require_host:!0,require_valid_protocol:!0,allow_underscores:!1,allow_trailing_dot:!1,allow_protocol_relative_urls:!1},b=/^\[([^\]]+)\](?::([0-9]+))?$/;function O(t,e){for(var r=0;r=e.min,o=!e.hasOwnProperty("max")||t<=e.max,i=!e.hasOwnProperty("lt")||te.gt;return r.test(t)&&n&&o&&i&&a}var Q=/^[\x00-\x7F]+$/;var X=/[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var q=/[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var tt=/[^\x00-\x7F]/;var et=function(t,e){var r=1]/.test(r)){if(!e)return;if(!(r.split('"').length===r.split('\\"').length))return}return 1}}(n))return!1}else if(e.require_display_name)return!1}if(!e.ignore_max_length&&254]/.test(t))return!1;if(0===t.indexOf("mailto:"))return!1;var r,n,o,i,a,s,l,u;if(e=Z(e,G),1<(l=(t=(l=(t=(l=t.split("#")).shift()).split("?")).shift()).split("://")).length){if(r=l.shift().toLowerCase(),e.require_valid_protocol&&-1===e.protocols.indexOf(r))return!1}else{if(e.require_protocol)return!1;if("//"===t.substr(0,2)){if(!e.allow_protocol_relative_urls)return!1;l[0]=t.substr(2)}}if(""===(t=l.join("://")))return!1;if(""===(t=(l=t.split("/")).shift())&&!e.require_host)return!0;if(1<(l=t.split("@")).length){if(e.disallow_auth)return!1;if(0<=(n=l.shift()).indexOf(":")&&2/g,">").replace(/\//g,"/").replace(/\\/g,"\").replace(/`/g,"`")},unescape:function(t){return h(t),t.replace(/&/g,"&").replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(///g,"/").replace(/\/g,"\\").replace(/`/g,"`")},stripLow:function(t,e){return h(t),de(t,e?"\\x00-\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F":"\\x00-\\x1F\\x7F")},whitelist:function(t,e){return h(t),t.replace(new RegExp("[^".concat(e,"]+"),"g"),"")},blacklist:de,isWhitelisted:function(t,e){h(t);for(var r=t.length-1;0<=r;r--)if(-1===e.indexOf(t[r]))return!1;return!0},normalizeEmail:function(t,e){e=Z(e,fe);var r=t.split("@"),n=r.pop(),o=[r.join("@"),n];if(o[1]=o[1].toLowerCase(),"gmail.com"===o[1]||"googlemail.com"===o[1]){if(e.gmail_remove_subaddress&&(o[0]=o[0].split("+")[0]),e.gmail_remove_dots&&(o[0]=o[0].replace(/\.+/g,he)),!o[0].length)return!1;(e.all_lowercase||e.gmail_lowercase)&&(o[0]=o[0].toLowerCase()),o[1]=e.gmail_convert_googlemaildotcom?"gmail.com":o[1]}else if(0<=Ae.indexOf(o[1])){if(e.icloud_remove_subaddress&&(o[0]=o[0].split("+")[0]),!o[0].length)return!1;(e.all_lowercase||e.icloud_lowercase)&&(o[0]=o[0].toLowerCase())}else if(0<=$e.indexOf(o[1])){if(e.outlookdotcom_remove_subaddress&&(o[0]=o[0].split("+")[0]),!o[0].length)return!1;(e.all_lowercase||e.outlookdotcom_lowercase)&&(o[0]=o[0].toLowerCase())}else if(0<=pe.indexOf(o[1])){if(e.yahoo_remove_subaddress){var i=o[0].split("-");o[0]=1=e.min)&&(!e.hasOwnProperty("max")||n<=e.max)&&(!e.hasOwnProperty("lt")||ne.gt)}r["pt-BR"]=r["pt-PT"],n["pt-BR"]=n["pt-PT"],i["pt-BR"]=i["pt-PT"],r["pl-Pl"]=r["pl-PL"],n["pl-Pl"]=n["pl-PL"],i["pl-Pl"]=i["pl-PL"];var m=Object.keys(i);function v(t){return p(t)?parseFloat(t):NaN}function Z(t){return"object"===a(t)&&null!==t?t="function"==typeof t.toString?t.toString():"[object Object]":(null==t||isNaN(t)&&!t.length)&&(t=""),String(t)}function S(t,e){var r=0a)return!1;if("::"===t)return!0;"::"===t.substr(0,2)?(n.shift(),n.shift(),o=!0):"::"===t.substr(t.length-2)&&(n.pop(),n.pop(),o=!0);for(var s=0;s$/i,N=/^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~]+$/i,T=/^[a-z\d]+$/,B=/^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f]))*$/i,x=/^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+$/i,w=/^([\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;var G={protocols:["http","https","ftp"],require_tld:!0,require_protocol:!1,require_host:!0,require_valid_protocol:!0,allow_underscores:!1,allow_trailing_dot:!1,allow_protocol_relative_urls:!1},U=/^\[([^\]]+)\](?::([0-9]+))?$/;function b(t,e){for(var r=0;r=e.min,o=!e.hasOwnProperty("max")||t<=e.max,i=!e.hasOwnProperty("lt")||te.gt;return r.test(t)&&n&&o&&i&&a}var X=/^[\x00-\x7F]+$/;var q=/[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var tt=/[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var et=/[^\x00-\x7F]/;var rt=function(t,e){var r=1]/.test(r)){if(!e)return;if(!(r.split('"').length===r.split('\\"').length))return}return 1}}(n))return!1}else if(e.require_display_name)return!1}if(!e.ignore_max_length&&254]/.test(t))return!1;if(0===t.indexOf("mailto:"))return!1;var r,n,o,i,a,s,l,u;if(e=S(e,G),1<(l=(t=(l=(t=(l=t.split("#")).shift()).split("?")).shift()).split("://")).length){if(r=l.shift().toLowerCase(),e.require_valid_protocol&&-1===e.protocols.indexOf(r))return!1}else{if(e.require_protocol)return!1;if("//"===t.substr(0,2)){if(!e.allow_protocol_relative_urls)return!1;l[0]=t.substr(2)}}if(""===(t=l.join("://")))return!1;if(""===(t=(l=t.split("/")).shift())&&!e.require_host)return!0;if(1<(l=t.split("@")).length){if(e.disallow_auth)return!1;if(0<=(n=l.shift()).indexOf(":")&&2/g,">").replace(/\//g,"/").replace(/\\/g,"\").replace(/`/g,"`")},unescape:function(t){return h(t),t.replace(/&/g,"&").replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(///g,"/").replace(/\/g,"\\").replace(/`/g,"`")},stripLow:function(t,e){return h(t),fe(t,e?"\\x00-\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F":"\\x00-\\x1F\\x7F")},whitelist:function(t,e){return h(t),t.replace(new RegExp("[^".concat(e,"]+"),"g"),"")},blacklist:fe,isWhitelisted:function(t,e){h(t);for(var r=t.length-1;0<=r;r--)if(-1===e.indexOf(t[r]))return!1;return!0},normalizeEmail:function(t,e){e=S(e,Ae);var r=t.split("@"),n=r.pop(),o=[r.join("@"),n];if(o[1]=o[1].toLowerCase(),"gmail.com"===o[1]||"googlemail.com"===o[1]){if(e.gmail_remove_subaddress&&(o[0]=o[0].split("+")[0]),e.gmail_remove_dots&&(o[0]=o[0].replace(/\.+/g,me)),!o[0].length)return!1;(e.all_lowercase||e.gmail_lowercase)&&(o[0]=o[0].toLowerCase()),o[1]=e.gmail_convert_googlemaildotcom?"gmail.com":o[1]}else if(0<=$e.indexOf(o[1])){if(e.icloud_remove_subaddress&&(o[0]=o[0].split("+")[0]),!o[0].length)return!1;(e.all_lowercase||e.icloud_lowercase)&&(o[0]=o[0].toLowerCase())}else if(0<=pe.indexOf(o[1])){if(e.outlookdotcom_remove_subaddress&&(o[0]=o[0].split("+")[0]),!o[0].length)return!1;(e.all_lowercase||e.outlookdotcom_lowercase)&&(o[0]=o[0].toLowerCase())}else if(0<=ge.indexOf(o[1])){if(e.yahoo_remove_subaddress){var i=o[0].split("-");o[0]=1