From c99c4e17e53f65a09f7e0dee044c1b58e80208be Mon Sep 17 00:00:00 2001 From: Hamza Hejja Date: Sun, 16 Feb 2020 19:08:14 +0200 Subject: [PATCH 1/4] feat: implement isPassportNumber validator --- README.md | 1 + index.js | 6 + lib/isPassportNumber.js | 110 ++++++++ src/index.js | 2 + src/lib/isPassportNumber.js | 61 +++++ test/validators.js | 516 ++++++++++++++++++++++++++++++++++++ validator.js | 116 +++++++- validator.min.js | 2 +- 8 files changed, 812 insertions(+), 2 deletions(-) create mode 100644 lib/isPassportNumber.js create mode 100644 src/lib/isPassportNumber.js 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..12b8f5447 --- /dev/null +++ b/lib/isPassportNumber.js @@ -0,0 +1,110 @@ +"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-zA-Z]{2}\d{7}$/, + // ARMENIA + AR: /^[a-zA-Z]{3}\d{6}$/, + // ARGENTINA + AT: /^[a-zA-Z](\s?)\d{7}$/, + // AUSTRIA + AU: /^[a-zA-Z]\d{7}$/, + // AUSTRALIA + BE: /^[a-zA-Z]{2}\d{6}$/, + // BELGIUM + BG: /^\d{9}$/, + // BULGARIA + CA: /^[a-zA-Z]{2}\d{6}$/, + // CANADA + CH: /^[a-zA-Z]\d{7}$/, + // SWITZERLAND + CN: /^[GE]\d{8}$/, + // CHINA [G=Ordinary, E=Electronic] followed by 8-digits + CY: /^[a-zA-Z](\d{6}|\d{8})$/, + // CYPRUS + CZ: /^\d{8}$/, + // CZECH REPUBLIC + DE: /^[CFGHJKLMNPRTVWXYZ0-9]{9}$/, + // GERMANY + DK: /^\d{9}$/, + // DENMARK + EE: /^([a-zA-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-zA-Z0-9]{2}([a-zA-Z0-9]?)\d{6}$/, + // SPAIN + FI: /^[a-zA-Z]{2}\d{7}$/, + // FINLAND + FR: /^\d{2}[a-zA-Z]{2}\d{5}$/, + // FRANCE + GB: /^\d{9}$/, + // UNITED KINGDOM + GR: /^[a-zA-Z]{2}\d{7}$/, + // GREECE + HR: /^\d{9}$/, + // CROATIA + HU: /^[a-zA-Z]{2}(\d{6}|\d{7})$/, + // HUNGARY + IE: /^[a-zA-Z0-9]{2}\d{7}$/, + // IRELAND + IS: /^(A)\d{7}$/, + // ICELAND + IT: /^[a-zA-Z0-9]{2}\d{7}$/, + // ITALY + JP: /^[a-zA-Z]{2}\d{7}$/, + // JAPAN + KR: /^[MS]\d{8}$/, + // SOUTH KOREA, REPUBLIC OF KOREA, [S=PS Passports, M=PM Passports] + LT: /^[a-zA-Z0-9]{8}$/, + // LITHUANIA + LU: /^[a-zA-Z0-9]{8}$/, + // LUXEMBURG + LV: /^[a-zA-Z0-9]{2}\d{7}$/, + // LATVIA + MT: /^\d{7}$/, + // MALTA + NL: /^[a-zA-Z]{2}[a-zA-Z0-9]{6}\d$/, + // NETHERLANDS + PO: /^[a-zA-Z]{2}(\s?)\d{7}$/, + // POLAND + PT: /^[a-zA-Z]\d{6}$/, + // PORTUGAL + RO: /^\d{8,9}$/, + // ROMANIA + SE: /^\d{8}$/, + // SWEDEN + SL: /^(P)[a-zA-Z]\d{7}$/, + // SLOVANIA + SK: /^[0-9a-zA-Z]\d{7}$/, + // SLOVAKIA + TR: /^[a-zA-Z](\s?)\d{8}$/, + // TURKEY + UA: /^[a-zA-Z]{2}\d{6}$/, + // UKRAINE + US: /^\d{9}$/ // UNITED STATES + +}; +/** + * Check if str is a valid passport number + * relative to provided country code. + * + * @param {string} str + * @param {string} countryCode + * @return {boolean} + */ + +function isPassportNumber(str, countryCode) { + return countryCode.toUpperCase() in passportRegexByCountryCode && passportRegexByCountryCode[countryCode].test(str); +} + +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..f78b66dac --- /dev/null +++ b/src/lib/isPassportNumber.js @@ -0,0 +1,61 @@ +/** + * 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-zA-Z]{2}\d{7}$/, // ARMENIA + AR: /^[a-zA-Z]{3}\d{6}$/, // ARGENTINA + AT: /^[a-zA-Z](\s?)\d{7}$/, // AUSTRIA + AU: /^[a-zA-Z]\d{7}$/, // AUSTRALIA + BE: /^[a-zA-Z]{2}\d{6}$/, // BELGIUM + BG: /^\d{9}$/, // BULGARIA + CA: /^[a-zA-Z]{2}\d{6}$/, // CANADA + CH: /^[a-zA-Z]\d{7}$/, // SWITZERLAND + CN: /^[GE]\d{8}$/, // CHINA [G=Ordinary, E=Electronic] followed by 8-digits + CY: /^[a-zA-Z](\d{6}|\d{8})$/, // CYPRUS + CZ: /^\d{8}$/, // CZECH REPUBLIC + DE: /^[CFGHJKLMNPRTVWXYZ0-9]{9}$/, // GERMANY + DK: /^\d{9}$/, // DENMARK + EE: /^([a-zA-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-zA-Z0-9]{2}([a-zA-Z0-9]?)\d{6}$/, // SPAIN + FI: /^[a-zA-Z]{2}\d{7}$/, // FINLAND + FR: /^\d{2}[a-zA-Z]{2}\d{5}$/, // FRANCE + GB: /^\d{9}$/, // UNITED KINGDOM + GR: /^[a-zA-Z]{2}\d{7}$/, // GREECE + HR: /^\d{9}$/, // CROATIA + HU: /^[a-zA-Z]{2}(\d{6}|\d{7})$/, // HUNGARY + IE: /^[a-zA-Z0-9]{2}\d{7}$/, // IRELAND + IS: /^(A)\d{7}$/, // ICELAND + IT: /^[a-zA-Z0-9]{2}\d{7}$/, // ITALY + JP: /^[a-zA-Z]{2}\d{7}$/, // JAPAN + KR: /^[MS]\d{8}$/, // SOUTH KOREA, REPUBLIC OF KOREA, [S=PS Passports, M=PM Passports] + LT: /^[a-zA-Z0-9]{8}$/, // LITHUANIA + LU: /^[a-zA-Z0-9]{8}$/, // LUXEMBURG + LV: /^[a-zA-Z0-9]{2}\d{7}$/, // LATVIA + MT: /^\d{7}$/, // MALTA + NL: /^[a-zA-Z]{2}[a-zA-Z0-9]{6}\d$/, // NETHERLANDS + PO: /^[a-zA-Z]{2}(\s?)\d{7}$/, // POLAND + PT: /^[a-zA-Z]\d{6}$/, // PORTUGAL + RO: /^\d{8,9}$/, // ROMANIA + SE: /^\d{8}$/, // SWEDEN + SL: /^(P)[a-zA-Z]\d{7}$/, // SLOVANIA + SK: /^[0-9a-zA-Z]\d{7}$/, // SLOVAKIA + TR: /^[a-zA-Z](\s?)\d{8}$/, // TURKEY + UA: /^[a-zA-Z]{2}\d{6}$/, // UKRAINE + US: /^\d{9}$/, // UNITED STATES +}; + +/** + * Check if str is a valid passport number + * relative to provided country code. + * + * @param {string} str + * @param {string} countryCode + * @return {boolean} + */ +export default function isPassportNumber(str, countryCode) { + return (countryCode.toUpperCase() in passportRegexByCountryCode) && + passportRegexByCountryCode[countryCode].test(str); +} 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..7cf04bab0 100644 --- a/validator.js +++ b/validator.js @@ -402,7 +402,7 @@ function isFQDN(str, options) { to the 5th link, and "interface10" belongs to the 10th organization. * * */ -var ipv4Maybe = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/; +var ipv4Maybe = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/; var ipv6Block = /^[0-9A-F]{1,4}$/i; function isIP(str) { var version = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; @@ -848,6 +848,17 @@ function isBoolean(str) { return ['true', 'false', '1', '0'].indexOf(str) >= 0; } +var localeReg = /^[A-z]{2,4}([_-]([A-z]{4}|[\d]{3}))?([_-]([A-z]{2}|[\d]{3}))?$/; +function isLocale(str) { + assertString(str); + + if (str === 'en_US_POSIX' || str === 'ca_ES_VALENCIA') { + return true; + } + + return localeReg.test(str); +} + function isAlpha(str) { var locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'en-US'; assertString(str); @@ -884,6 +895,107 @@ 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-zA-Z]{2}\d{7}$/, + // ARMENIA + AR: /^[a-zA-Z]{3}\d{6}$/, + // ARGENTINA + AT: /^[a-zA-Z](\s?)\d{7}$/, + // AUSTRIA + AU: /^[a-zA-Z]\d{7}$/, + // AUSTRALIA + BE: /^[a-zA-Z]{2}\d{6}$/, + // BELGIUM + BG: /^\d{9}$/, + // BULGARIA + CA: /^[a-zA-Z]{2}\d{6}$/, + // CANADA + CH: /^[a-zA-Z]\d{7}$/, + // SWITZERLAND + CN: /^[GE]\d{8}$/, + // CHINA [G=Ordinary, E=Electronic] followed by 8-digits + CY: /^[a-zA-Z](\d{6}|\d{8})$/, + // CYPRUS + CZ: /^\d{8}$/, + // CZECH REPUBLIC + DE: /^[CFGHJKLMNPRTVWXYZ0-9]{9}$/, + // GERMANY + DK: /^\d{9}$/, + // DENMARK + EE: /^([a-zA-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-zA-Z0-9]{2}([a-zA-Z0-9]?)\d{6}$/, + // SPAIN + FI: /^[a-zA-Z]{2}\d{7}$/, + // FINLAND + FR: /^\d{2}[a-zA-Z]{2}\d{5}$/, + // FRANCE + GB: /^\d{9}$/, + // UNITED KINGDOM + GR: /^[a-zA-Z]{2}\d{7}$/, + // GREECE + HR: /^\d{9}$/, + // CROATIA + HU: /^[a-zA-Z]{2}(\d{6}|\d{7})$/, + // HUNGARY + IE: /^[a-zA-Z0-9]{2}\d{7}$/, + // IRELAND + IS: /^(A)\d{7}$/, + // ICELAND + IT: /^[a-zA-Z0-9]{2}\d{7}$/, + // ITALY + JP: /^[a-zA-Z]{2}\d{7}$/, + // JAPAN + KR: /^[MS]\d{8}$/, + // SOUTH KOREA, REPUBLIC OF KOREA, [S=PS Passports, M=PM Passports] + LT: /^[a-zA-Z0-9]{8}$/, + // LITHUANIA + LU: /^[a-zA-Z0-9]{8}$/, + // LUXEMBURG + LV: /^[a-zA-Z0-9]{2}\d{7}$/, + // LATVIA + MT: /^\d{7}$/, + // MALTA + NL: /^[a-zA-Z]{2}[a-zA-Z0-9]{6}\d$/, + // NETHERLANDS + PO: /^[a-zA-Z]{2}(\s?)\d{7}$/, + // POLAND + PT: /^[a-zA-Z]\d{6}$/, + // PORTUGAL + RO: /^\d{8,9}$/, + // ROMANIA + SE: /^\d{8}$/, + // SWEDEN + SL: /^(P)[a-zA-Z]\d{7}$/, + // SLOVANIA + SK: /^[0-9a-zA-Z]\d{7}$/, + // SLOVAKIA + TR: /^[a-zA-Z](\s?)\d{8}$/, + // TURKEY + UA: /^[a-zA-Z]{2}\d{6}$/, + // UKRAINE + US: /^\d{9}$/ // UNITED STATES + +}; +/** + * Check if str is a valid passport number + * relative to provided country code. + * + * @param {string} str + * @param {string} countryCode + * @return {boolean} + */ + +function isPassportNumber(str, countryCode) { + return countryCode.toUpperCase() in passportRegexByCountryCode && passportRegexByCountryCode[countryCode].test(str); +} + var _int = /^(?:[-+]?(?:0|[1-9][0-9]*))$/; var intLeadingZeroes = /^[-+]?[0-9]+$/; function isInt(str, options) { @@ -2394,6 +2506,7 @@ var validator = { isAlphanumeric: isAlphanumeric, isAlphanumericLocales: locales$2, isNumeric: isNumeric, + isPassportNumber: isPassportNumber, isPort: isPort, isLowercase: isLowercase, isUppercase: isUppercase, @@ -2420,6 +2533,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..3f46261ae 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},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 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 Date: Sun, 16 Feb 2020 19:36:14 +0200 Subject: [PATCH 2/4] normalize str by cleaning spaces and converting to UPPERCASE --- lib/isPassportNumber.js | 57 ++++++++++++++++++------------------ src/lib/isPassportNumber.js | 58 +++++++++++++++++++------------------ validator.js | 57 ++++++++++++++++++------------------ validator.min.js | 2 +- 4 files changed, 89 insertions(+), 85 deletions(-) diff --git a/lib/isPassportNumber.js b/lib/isPassportNumber.js index 12b8f5447..b277bff10 100644 --- a/lib/isPassportNumber.js +++ b/lib/isPassportNumber.js @@ -12,25 +12,25 @@ exports.default = isPassportNumber; * https://countrycode.org/ -- Country Codes */ var passportRegexByCountryCode = { - AM: /^[a-zA-Z]{2}\d{7}$/, + AM: /^[A-Z]{2}\d{7}$/, // ARMENIA - AR: /^[a-zA-Z]{3}\d{6}$/, + AR: /^[A-Z]{3}\d{6}$/, // ARGENTINA - AT: /^[a-zA-Z](\s?)\d{7}$/, + AT: /^[A-Z]\d{7}$/, // AUSTRIA - AU: /^[a-zA-Z]\d{7}$/, + AU: /^[A-Z]\d{7}$/, // AUSTRALIA - BE: /^[a-zA-Z]{2}\d{6}$/, + BE: /^[A-Z]{2}\d{6}$/, // BELGIUM BG: /^\d{9}$/, // BULGARIA - CA: /^[a-zA-Z]{2}\d{6}$/, + CA: /^[A-Z]{2}\d{6}$/, // CANADA - CH: /^[a-zA-Z]\d{7}$/, + CH: /^[A-Z]\d{7}$/, // SWITZERLAND CN: /^[GE]\d{8}$/, // CHINA [G=Ordinary, E=Electronic] followed by 8-digits - CY: /^[a-zA-Z](\d{6}|\d{8})$/, + CY: /^[A-Z](\d{6}|\d{8})$/, // CYPRUS CZ: /^\d{8}$/, // CZECH REPUBLIC @@ -38,57 +38,57 @@ var passportRegexByCountryCode = { // GERMANY DK: /^\d{9}$/, // DENMARK - EE: /^([a-zA-Z]\d{7}|[A-Z]{2}\d{7})$/, + 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-zA-Z0-9]{2}([a-zA-Z0-9]?)\d{6}$/, + ES: /^[A-Z0-9]{2}([A-Z0-9]?)\d{6}$/, // SPAIN - FI: /^[a-zA-Z]{2}\d{7}$/, + FI: /^[A-Z]{2}\d{7}$/, // FINLAND - FR: /^\d{2}[a-zA-Z]{2}\d{5}$/, + FR: /^\d{2}[A-Z]{2}\d{5}$/, // FRANCE GB: /^\d{9}$/, // UNITED KINGDOM - GR: /^[a-zA-Z]{2}\d{7}$/, + GR: /^[A-Z]{2}\d{7}$/, // GREECE HR: /^\d{9}$/, // CROATIA - HU: /^[a-zA-Z]{2}(\d{6}|\d{7})$/, + HU: /^[A-Z]{2}(\d{6}|\d{7})$/, // HUNGARY - IE: /^[a-zA-Z0-9]{2}\d{7}$/, + IE: /^[A-Z0-9]{2}\d{7}$/, // IRELAND IS: /^(A)\d{7}$/, // ICELAND - IT: /^[a-zA-Z0-9]{2}\d{7}$/, + IT: /^[A-Z0-9]{2}\d{7}$/, // ITALY - JP: /^[a-zA-Z]{2}\d{7}$/, + JP: /^[A-Z]{2}\d{7}$/, // JAPAN KR: /^[MS]\d{8}$/, // SOUTH KOREA, REPUBLIC OF KOREA, [S=PS Passports, M=PM Passports] - LT: /^[a-zA-Z0-9]{8}$/, + LT: /^[A-Z0-9]{8}$/, // LITHUANIA - LU: /^[a-zA-Z0-9]{8}$/, + LU: /^[A-Z0-9]{8}$/, // LUXEMBURG - LV: /^[a-zA-Z0-9]{2}\d{7}$/, + LV: /^[A-Z0-9]{2}\d{7}$/, // LATVIA MT: /^\d{7}$/, // MALTA - NL: /^[a-zA-Z]{2}[a-zA-Z0-9]{6}\d$/, + NL: /^[A-Z]{2}[A-Z0-9]{6}\d$/, // NETHERLANDS - PO: /^[a-zA-Z]{2}(\s?)\d{7}$/, + PO: /^[A-Z]{2}\d{7}$/, // POLAND - PT: /^[a-zA-Z]\d{6}$/, + PT: /^[A-Z]\d{6}$/, // PORTUGAL RO: /^\d{8,9}$/, // ROMANIA SE: /^\d{8}$/, // SWEDEN - SL: /^(P)[a-zA-Z]\d{7}$/, + SL: /^(P)[A-Z]\d{7}$/, // SLOVANIA - SK: /^[0-9a-zA-Z]\d{7}$/, + SK: /^[0-9A-Z]\d{7}$/, // SLOVAKIA - TR: /^[a-zA-Z](\s?)\d{8}$/, + TR: /^[A-Z]\d{8}$/, // TURKEY - UA: /^[a-zA-Z]{2}\d{6}$/, + UA: /^[A-Z]{2}\d{6}$/, // UKRAINE US: /^\d{9}$/ // UNITED STATES @@ -103,7 +103,8 @@ var passportRegexByCountryCode = { */ function isPassportNumber(str, countryCode) { - return countryCode.toUpperCase() in passportRegexByCountryCode && passportRegexByCountryCode[countryCode].test(str); + var normalizedStr = str.replace(/\s/g, '').toUpperCase(); + return countryCode.toUpperCase() in passportRegexByCountryCode && passportRegexByCountryCode[countryCode].test(normalizedStr); } module.exports = exports.default; diff --git a/src/lib/isPassportNumber.js b/src/lib/isPassportNumber.js index f78b66dac..fb55de37e 100644 --- a/src/lib/isPassportNumber.js +++ b/src/lib/isPassportNumber.js @@ -5,45 +5,45 @@ * https://countrycode.org/ -- Country Codes */ const passportRegexByCountryCode = { - AM: /^[a-zA-Z]{2}\d{7}$/, // ARMENIA - AR: /^[a-zA-Z]{3}\d{6}$/, // ARGENTINA - AT: /^[a-zA-Z](\s?)\d{7}$/, // AUSTRIA - AU: /^[a-zA-Z]\d{7}$/, // AUSTRALIA - BE: /^[a-zA-Z]{2}\d{6}$/, // BELGIUM + 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-zA-Z]{2}\d{6}$/, // CANADA - CH: /^[a-zA-Z]\d{7}$/, // SWITZERLAND + 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-zA-Z](\d{6}|\d{8})$/, // CYPRUS + CY: /^[A-Z](\d{6}|\d{8})$/, // CYPRUS CZ: /^\d{8}$/, // CZECH REPUBLIC DE: /^[CFGHJKLMNPRTVWXYZ0-9]{9}$/, // GERMANY DK: /^\d{9}$/, // DENMARK - EE: /^([a-zA-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-zA-Z0-9]{2}([a-zA-Z0-9]?)\d{6}$/, // SPAIN - FI: /^[a-zA-Z]{2}\d{7}$/, // FINLAND - FR: /^\d{2}[a-zA-Z]{2}\d{5}$/, // FRANCE + 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-zA-Z]{2}\d{7}$/, // GREECE + GR: /^[A-Z]{2}\d{7}$/, // GREECE HR: /^\d{9}$/, // CROATIA - HU: /^[a-zA-Z]{2}(\d{6}|\d{7})$/, // HUNGARY - IE: /^[a-zA-Z0-9]{2}\d{7}$/, // IRELAND + HU: /^[A-Z]{2}(\d{6}|\d{7})$/, // HUNGARY + IE: /^[A-Z0-9]{2}\d{7}$/, // IRELAND IS: /^(A)\d{7}$/, // ICELAND - IT: /^[a-zA-Z0-9]{2}\d{7}$/, // ITALY - JP: /^[a-zA-Z]{2}\d{7}$/, // JAPAN + 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-zA-Z0-9]{8}$/, // LITHUANIA - LU: /^[a-zA-Z0-9]{8}$/, // LUXEMBURG - LV: /^[a-zA-Z0-9]{2}\d{7}$/, // LATVIA + 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-zA-Z]{2}[a-zA-Z0-9]{6}\d$/, // NETHERLANDS - PO: /^[a-zA-Z]{2}(\s?)\d{7}$/, // POLAND - PT: /^[a-zA-Z]\d{6}$/, // PORTUGAL + 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-zA-Z]\d{7}$/, // SLOVANIA - SK: /^[0-9a-zA-Z]\d{7}$/, // SLOVAKIA - TR: /^[a-zA-Z](\s?)\d{8}$/, // TURKEY - UA: /^[a-zA-Z]{2}\d{6}$/, // UKRAINE + 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 }; @@ -56,6 +56,8 @@ const passportRegexByCountryCode = { * @return {boolean} */ export default function isPassportNumber(str, countryCode) { + const normalizedStr = str.replace(/\s/g, '').toUpperCase(); + return (countryCode.toUpperCase() in passportRegexByCountryCode) && - passportRegexByCountryCode[countryCode].test(str); + passportRegexByCountryCode[countryCode].test(normalizedStr); } diff --git a/validator.js b/validator.js index 7cf04bab0..f87a73d22 100644 --- a/validator.js +++ b/validator.js @@ -902,25 +902,25 @@ function isNumeric(str, options) { * https://countrycode.org/ -- Country Codes */ var passportRegexByCountryCode = { - AM: /^[a-zA-Z]{2}\d{7}$/, + AM: /^[A-Z]{2}\d{7}$/, // ARMENIA - AR: /^[a-zA-Z]{3}\d{6}$/, + AR: /^[A-Z]{3}\d{6}$/, // ARGENTINA - AT: /^[a-zA-Z](\s?)\d{7}$/, + AT: /^[A-Z]\d{7}$/, // AUSTRIA - AU: /^[a-zA-Z]\d{7}$/, + AU: /^[A-Z]\d{7}$/, // AUSTRALIA - BE: /^[a-zA-Z]{2}\d{6}$/, + BE: /^[A-Z]{2}\d{6}$/, // BELGIUM BG: /^\d{9}$/, // BULGARIA - CA: /^[a-zA-Z]{2}\d{6}$/, + CA: /^[A-Z]{2}\d{6}$/, // CANADA - CH: /^[a-zA-Z]\d{7}$/, + CH: /^[A-Z]\d{7}$/, // SWITZERLAND CN: /^[GE]\d{8}$/, // CHINA [G=Ordinary, E=Electronic] followed by 8-digits - CY: /^[a-zA-Z](\d{6}|\d{8})$/, + CY: /^[A-Z](\d{6}|\d{8})$/, // CYPRUS CZ: /^\d{8}$/, // CZECH REPUBLIC @@ -928,57 +928,57 @@ var passportRegexByCountryCode = { // GERMANY DK: /^\d{9}$/, // DENMARK - EE: /^([a-zA-Z]\d{7}|[A-Z]{2}\d{7})$/, + 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-zA-Z0-9]{2}([a-zA-Z0-9]?)\d{6}$/, + ES: /^[A-Z0-9]{2}([A-Z0-9]?)\d{6}$/, // SPAIN - FI: /^[a-zA-Z]{2}\d{7}$/, + FI: /^[A-Z]{2}\d{7}$/, // FINLAND - FR: /^\d{2}[a-zA-Z]{2}\d{5}$/, + FR: /^\d{2}[A-Z]{2}\d{5}$/, // FRANCE GB: /^\d{9}$/, // UNITED KINGDOM - GR: /^[a-zA-Z]{2}\d{7}$/, + GR: /^[A-Z]{2}\d{7}$/, // GREECE HR: /^\d{9}$/, // CROATIA - HU: /^[a-zA-Z]{2}(\d{6}|\d{7})$/, + HU: /^[A-Z]{2}(\d{6}|\d{7})$/, // HUNGARY - IE: /^[a-zA-Z0-9]{2}\d{7}$/, + IE: /^[A-Z0-9]{2}\d{7}$/, // IRELAND IS: /^(A)\d{7}$/, // ICELAND - IT: /^[a-zA-Z0-9]{2}\d{7}$/, + IT: /^[A-Z0-9]{2}\d{7}$/, // ITALY - JP: /^[a-zA-Z]{2}\d{7}$/, + JP: /^[A-Z]{2}\d{7}$/, // JAPAN KR: /^[MS]\d{8}$/, // SOUTH KOREA, REPUBLIC OF KOREA, [S=PS Passports, M=PM Passports] - LT: /^[a-zA-Z0-9]{8}$/, + LT: /^[A-Z0-9]{8}$/, // LITHUANIA - LU: /^[a-zA-Z0-9]{8}$/, + LU: /^[A-Z0-9]{8}$/, // LUXEMBURG - LV: /^[a-zA-Z0-9]{2}\d{7}$/, + LV: /^[A-Z0-9]{2}\d{7}$/, // LATVIA MT: /^\d{7}$/, // MALTA - NL: /^[a-zA-Z]{2}[a-zA-Z0-9]{6}\d$/, + NL: /^[A-Z]{2}[A-Z0-9]{6}\d$/, // NETHERLANDS - PO: /^[a-zA-Z]{2}(\s?)\d{7}$/, + PO: /^[A-Z]{2}\d{7}$/, // POLAND - PT: /^[a-zA-Z]\d{6}$/, + PT: /^[A-Z]\d{6}$/, // PORTUGAL RO: /^\d{8,9}$/, // ROMANIA SE: /^\d{8}$/, // SWEDEN - SL: /^(P)[a-zA-Z]\d{7}$/, + SL: /^(P)[A-Z]\d{7}$/, // SLOVANIA - SK: /^[0-9a-zA-Z]\d{7}$/, + SK: /^[0-9A-Z]\d{7}$/, // SLOVAKIA - TR: /^[a-zA-Z](\s?)\d{8}$/, + TR: /^[A-Z]\d{8}$/, // TURKEY - UA: /^[a-zA-Z]{2}\d{6}$/, + UA: /^[A-Z]{2}\d{6}$/, // UKRAINE US: /^\d{9}$/ // UNITED STATES @@ -993,7 +993,8 @@ var passportRegexByCountryCode = { */ function isPassportNumber(str, countryCode) { - return countryCode.toUpperCase() in passportRegexByCountryCode && passportRegexByCountryCode[countryCode].test(str); + var normalizedStr = str.replace(/\s/g, '').toUpperCase(); + return countryCode.toUpperCase() in passportRegexByCountryCode && passportRegexByCountryCode[countryCode].test(normalizedStr); } var _int = /^(?:[-+]?(?:0|[1-9][0-9]*))$/; diff --git a/validator.min.js b/validator.min.js index 3f46261ae..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 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},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 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=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 Date: Sun, 16 Feb 2020 19:41:44 +0200 Subject: [PATCH 3/4] style: function docs, helper comments --- lib/isPassportNumber.js | 3 ++- src/lib/isPassportNumber.js | 3 ++- validator.js | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/isPassportNumber.js b/lib/isPassportNumber.js index b277bff10..6b101bc60 100644 --- a/lib/isPassportNumber.js +++ b/lib/isPassportNumber.js @@ -95,7 +95,7 @@ var passportRegexByCountryCode = { }; /** * Check if str is a valid passport number - * relative to provided country code. + * relative to provided ISO Country Code. * * @param {string} str * @param {string} countryCode @@ -103,6 +103,7 @@ var passportRegexByCountryCode = { */ 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); } diff --git a/src/lib/isPassportNumber.js b/src/lib/isPassportNumber.js index fb55de37e..304f72fae 100644 --- a/src/lib/isPassportNumber.js +++ b/src/lib/isPassportNumber.js @@ -49,13 +49,14 @@ const passportRegexByCountryCode = { /** * Check if str is a valid passport number - * relative to provided country code. + * 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) && diff --git a/validator.js b/validator.js index f87a73d22..680f3d982 100644 --- a/validator.js +++ b/validator.js @@ -985,7 +985,7 @@ var passportRegexByCountryCode = { }; /** * Check if str is a valid passport number - * relative to provided country code. + * relative to provided ISO Country Code. * * @param {string} str * @param {string} countryCode @@ -993,6 +993,7 @@ var passportRegexByCountryCode = { */ 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); } From 8ccc0f118911f2c06980ecfd4b07436f2957e6c8 Mon Sep 17 00:00:00 2001 From: Hamza Hejja Date: Sun, 16 Feb 2020 23:58:46 +0200 Subject: [PATCH 4/4] remove unrelated changes --- validator.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/validator.js b/validator.js index 680f3d982..645c79876 100644 --- a/validator.js +++ b/validator.js @@ -402,7 +402,7 @@ function isFQDN(str, options) { to the 5th link, and "interface10" belongs to the 10th organization. * * */ -var ipv4Maybe = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/; +var ipv4Maybe = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/; var ipv6Block = /^[0-9A-F]{1,4}$/i; function isIP(str) { var version = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; @@ -848,17 +848,6 @@ function isBoolean(str) { return ['true', 'false', '1', '0'].indexOf(str) >= 0; } -var localeReg = /^[A-z]{2,4}([_-]([A-z]{4}|[\d]{3}))?([_-]([A-z]{2}|[\d]{3}))?$/; -function isLocale(str) { - assertString(str); - - if (str === 'en_US_POSIX' || str === 'ca_ES_VALENCIA') { - return true; - } - - return localeReg.test(str); -} - function isAlpha(str) { var locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'en-US'; assertString(str);