Repository: validatorjs/validator.js (js)

Issue:
`isBIC` country code does not accept `XK`
**Describe the bug**
A clear and concise description of what the bug is.

The `isBIC` validator uses the list of country codes in ['./isISO31661Alpha2'](https://github.com/validatorjs/validator.js/blob/86a07ba4f3f710f639e92a62cf81dd3321ef9ee8/src/lib/isISO31661Alpha2.js) and that list of country codes does not include `"XK"` (Republic of Kosovo).

However, on the ISO 9362 page, Wikipedia says that the country code in a SWIFT/BIC code is "a [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country code (exceptionally, SWIFT has assigned the code XK to [Republic of Kosovo](https://en.wikipedia.org/wiki/Republic_of_Kosovo), which does not have an ISO 3166-1 country code)".

Kosovo's code is not in the ISO 3166-1 alpha-2, but for assigning BIC country codes, it is a valid code.

Because `isBIC` only uses the list of country codes on the ISO 3166-1 alpha-2 format, a BIC code with `"XK"` as the country code would not pass.

https://github.com/validatorjs/validator.js/blob/86a07ba4f3f710f639e92a62cf81dd3321ef9ee8/src/lib/isBIC.js#L12-L14

We should change the check above in `isBIC.js` to this to account for `"XK"` being an allowed country code:

```js
if (!CountryCodes.has(str.slice(4, 6).toUpperCase()) && str.slice(4, 6).toUpperCase() !== "XK" ) {
    return false;
  }
```

**Examples**
If applicable, add screenshots to help explain your problem.

**Additional context**
Validator.js version: 13.7.0
Node.js version: 16
OS platform: [windows, linux, macOS, etc]: Linux


Pull request:
fix(isBIC): add `XK` to accepted BIC country codes
Adds the country code `XK` (Republic of Kosovo) to `isBIC`'s allowed country codes

closes #2045

## Checklist

- [X] PR contains only changes related; no stray files, etc.
- [X] README updated (where applicable)
- [X] Tests written (where applicable)


Patch:
diff --git a/README.md b/README.md
index 08cbe64..de00deb 100644
--- a/README.md
+++ b/README.md
@@ -113,7 +113,7 @@ Validator                               | Description
 **isEmpty(str [, options])**            | check if the string has a length of zero.<br/><br/>`options` is an object which defaults to `{ ignore_whitespace: false }`.
 **isEthereumAddress(str)**              | check if the string is an [Ethereum][Ethereum] address. Does not validate address checksums.
 **isFloat(str [, options])**            | check if the string is a float.<br/><br/>`options` is an object which can contain the keys `min`, `max`, `gt`, and/or `lt` to validate the float is within boundaries (e.g. `{ min: 7.22, max: 9.55 }`) it also has `locale` as an option.<br/><br/>`min` and `max` are equivalent to 'greater or equal' and 'less or equal', respectively while `gt` and `lt` are their strict counterparts.<br/><br/>`locale` determines the decimal separator and is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fr-CA', 'fr-FR', 'hu-HU', 'it-IT', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'sl-SI', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`. Locale list is `validator.isFloatLocales`.
-**isFQDN(str [, options])**             | check if the string is a fully qualified domain name (e.g. domain.com).<br/><br/>`options` is an object which defaults to `{ require_tld: true, allow_underscores: false, allow_trailing_dot: false, allow_numeric_tld: false, allow_wildcard: false }`. If `allow_wildcard` is set to true, the validator will allow domain starting with `*.` (e.g. `*.example.com` or `*.shop.example.com`).
+**isFQDN(str [, options])**             | check if the string is a fully qualified domain name (e.g. domain.com).<br/><br/>`options` is an object which defaults to `{ require_tld: true, allow_underscores: false, allow_trailing_dot: false, allow_numeric_tld: false, allow_wildcard: false, ignore_max_length: false }`. If `allow_wildcard` is set to true, the validator will allow domain starting with `*.` (e.g. `*.example.com` or `*.shop.example.com`).
 **isFullWidth(str)**                    | check if the string contains any full-width chars.
 **isHalfWidth(str)**                    | check if the string contains any half-width chars.
 **isHash(str, algorithm)**              | check if the string is a hash of type algorithm.<br/><br/>Algorithm is one of `['crc32', 'crc32b', 'md4', 'md5', 'ripemd128', 'ripemd160', 'sha1', 'sha256', 'sha384', 'sha512', 'tiger128', 'tiger160', 'tiger192']`.
@@ -140,7 +140,7 @@ Validator                               | Description
 **isJWT(str)**                         | check if the string is valid JWT token.
 **isLatLong(str [, options])**                      | check if the string is a valid latitude-longitude coordinate in the format `lat,long` or `lat, long`.<br/><br/>`options` is an object that defaults to `{ checkDMS: false }`. Pass `checkDMS` as `true` to validate DMS(degrees, minutes, and seconds) latitude-longitude format.
 **isLength(str [, options])**              | check if the string's length falls in a range.<br/><br/>`options` is an object which defaults to `{ min: 0, max: undefined }`. Note: this function takes into account surrogate pairs.
-**isLicensePlate(str, locale)**     | check if the string matches the format of a country's license plate.<br/><br/>`locale` is one of `['cs-CZ', 'de-DE', 'de-LI', 'fi-FI', 'pt-BR', 'pt-PT', 'sq-AL', 'sv-SE', 'en-IN', 'hi-IN', 'gu-IN', 'as-IN', 'bn-IN', 'kn-IN', 'ml-IN', 'mr-IN', 'or-IN', 'pa-IN', 'sa-IN', 'ta-IN', 'te-IN', 'kok-IN']` or `'any'`.
+**isLicensePlate(str, locale)**     | check if the string matches the format of a country's license plate.<br/><br/>`locale` is one of `['cs-CZ', 'de-DE', 'de-LI', 'en-IN', 'es-AR', 'hu-HU', 'pt-BR', 'pt-PT', 'sq-AL', 'sv-SE']` or `'any'`.
 **isLocale(str)**                       | check if the string is a locale.
 **isLowercase(str)**                    | check if the string is lowercase.
 **isLuhnValid(str)**                    | check if the string passes the [Luhn check][Luhn Check].
@@ -148,12 +148,12 @@ Validator                               | Description
 **isMagnetURI(str)**                      | check if the string is a [Magnet URI format][Magnet URI Format].
 **isMD5(str)**                          | check if the string is a MD5 hash.<br/><br/>Please note that you can also use the `isHash(str, 'md5')` function. Keep in mind that MD5 has some collision weaknesses compared to other algorithms (e.g., SHA).
 **isMimeType(str)**                     | check if the string matches to a valid [MIME type][MIME Type] format.
-**isMobilePhone(str [, locale [, options]])**          | check if the string is a mobile phone number,<br/><br/>`locale` is either an array of locales (e.g. `['sk-SK', 'sr-RS']`) OR one of `['am-Am', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-EH', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-PS', 'ar-SA', 'ar-SY', 'ar-TN', 'ar-YE', 'az-AZ', 'az-LB', 'az-LY', 'be-BY', 'bg-BG', 'bn-BD', 'bs-BA', 'ca-AD', 'cs-CZ', 'da-DK', 'de-AT', 'de-CH', 'de-DE', 'de-LU', 'dv-MV', 'dz-BT', 'el-CY', 'el-GR', 'en-AG', 'en-AI', 'en-AU', 'en-BM', 'en-BS', 'en-BW', 'en-CA', 'en-GB', 'en-GG', 'en-GH', 'en-GY', 'en-HK', 'en-IE', 'en-IN', 'en-JM', 'en-KE', 'en-KI', 'en-KN', 'en-LS', 'en-MO', 'en-MT', 'en-MU', 'en-NG', 'en-NZ', 'en-PG', 'en-PH', 'en-PK', 'en-RW', 'en-SG', 'en-SL', 'en-SS', 'en-TZ', 'en-UG', 'en-US', 'en-ZA', 'en-ZM', 'en-ZW', 'es-AR', 'es-BO', 'es-CL', 'es-CO', 'es-CR', 'es-CU', 'es-DO', 'es-EC', 'es-ES', 'es-HN', 'es-MX', 'es-NI', 'es-PA', 'es-PE', 'es-PY', 'es-SV', 'es-UY', 'es-VE', 'et-EE', 'fa-AF', 'fa-IR', 'fi-FI', 'fj-FJ', 'fo-FO', 'fr-BE', 'fr-BF', 'fr-BJ', 'fr-FR', 'fr-GF', 'fr-GP', 'fr-MQ', 'fr-PF', 'fr-RE', 'ga-IE', 'he-IL', 'hu-HU', 'id-ID', 'ir-IR', 'it-IT', 'it-SM', 'ja-JP', 'ka-GE', 'kk-KZ', 'kl-GL', 'ko-KR', 'ky-KG', 'lt-LT', 'mg-MG', 'mn-MN', 'ms-MY', 'my-MM', 'mz-MZ', 'nb-NO', 'ne-NP', 'nl-AW', 'nl-BE', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-AO', 'pt-BR', 'pt-PT', 'ro-RO', 'ru-RU', 'si-LK', 'sk-SK', 'sl-SI', 'sq-AL', 'sr-RS', 'sv-SE', 'tg-TJ', 'th-TH', 'tk-TM', 'tr-TR', 'uk-UA', 'uz-UZ', 'vi-VN', 'zh-CN', 'zh-HK', 'zh-MO', 'zh-TW']` OR defaults to `'any'`. If 'any' or a falsey value is used, function will check if any of the locales match).<br/><br/>`options` is an optional object that can be supplied with the following keys: `strictMode`, if this is set to `true`, the mobile phone number must be supplied with the country code and therefore must start with `+`. Locale list is `validator.isMobilePhoneLocales`.
+**isMobilePhone(str [, locale [, options]])**          | check if the string is a mobile phone number,<br/><br/>`locale` is either an array of locales (e.g. `['sk-SK', 'sr-RS']`) OR one of `['am-Am', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-EH', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-PS', 'ar-SA', 'ar-SY', 'ar-TN', 'ar-YE', 'az-AZ', 'az-LB', 'az-LY', 'be-BY', 'bg-BG', 'bn-BD', 'bs-BA', 'ca-AD', 'cs-CZ', 'da-DK', 'de-AT', 'de-CH', 'de-DE', 'de-LU', 'dv-MV', 'dz-BT', 'el-CY', 'el-GR', 'en-AG', 'en-AI', 'en-AU', 'en-BM', 'en-BS', 'en-BW', 'en-CA', 'en-GB', 'en-GG', 'en-GH', 'en-GY', 'en-HK', 'en-IE', 'en-IN', 'en-JM', 'en-KE', 'en-KI', 'en-KN', 'en-LS', 'en-MO', 'en-MT', 'en-MU', 'en-NG', 'en-NZ', 'en-PG', 'en-PH', 'en-PK', 'en-RW', 'en-SG', 'en-SL', 'en-SS', 'en-TZ', 'en-UG', 'en-US', 'en-ZA', 'en-ZM', 'en-ZW', 'es-AR', 'es-BO', 'es-CL', 'es-CO', 'es-CR', 'es-CU', 'es-DO', 'es-EC', 'es-ES', 'es-HN', 'es-MX', 'es-NI', 'es-PA', 'es-PE', 'es-PY', 'es-SV', 'es-UY', 'es-VE', 'et-EE', 'fa-AF', 'fa-IR', 'fi-FI', 'fj-FJ', 'fo-FO', 'fr-BE', 'fr-BF', 'fr-BJ', 'fr-CD', 'fr-FR', 'fr-GF', 'fr-GP', 'fr-MQ', 'fr-PF', 'fr-RE', 'ga-IE', 'he-IL', 'hu-HU', 'id-ID', 'ir-IR', 'it-IT', 'it-SM', 'ja-JP', 'ka-GE', 'kk-KZ', 'kl-GL', 'ko-KR', 'ky-KG', 'lt-LT', 'mg-MG', 'mn-MN', 'ms-MY', 'my-MM', 'mz-MZ', 'nb-NO', 'ne-NP', 'nl-AW', 'nl-BE', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-AO', 'pt-BR', 'pt-PT', 'ro-Md', 'ro-RO', 'ru-RU', 'si-LK', 'sk-SK', 'sl-SI', 'sq-AL', 'sr-RS', 'sv-SE', 'tg-TJ', 'th-TH', 'tk-TM', 'tr-TR', 'uk-UA', 'uz-UZ', 'vi-VN', 'zh-CN', 'zh-HK', 'zh-MO', 'zh-TW']` OR defaults to `'any'`. If 'any' or a falsey value is used, function will check if any of the locales match).<br/><br/>`options` is an optional object that can be supplied with the following keys: `strictMode`, if this is set to `true`, the mobile phone number must be supplied with the country code and therefore must start with `+`. Locale list is `validator.isMobilePhoneLocales`.
 **isMongoId(str)**                      | check if the string is a valid hex-encoded representation of a [MongoDB ObjectId][mongoid].
 **isMultibyte(str)**                    | check if the string contains one or more multibyte chars.
 **isNumeric(str [, options])**                      | check if the string contains only numbers.<br/><br/>`options` is an object which defaults to `{ no_symbols: false }` it also has `locale` as an option. If `no_symbols` is true, the validator will reject numeric strings that feature a symbol (e.g. `+`, `-`, or `.`).<br/><br/>`locale` determines the decimal separator and is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fr-FR', 'fr-CA', 'hu-HU', 'it-IT', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'sl-SI', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`.
 **isOctal(str)**                        | check if the string is a valid octal number.
-**isPassportNumber(str, countryCode)**    | check if the string is a valid passport number.<br/><br/>`countryCode` is one of `['AM', 'AR', 'AT', 'AU', 'BE', 'BG', 'BY', 'BR', 'CA', 'CH', 'CN', 'CY', 'CZ', 'DE', 'DK', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE', 'IN', 'IR', 'ID', 'IS', 'IT', 'JP', 'KR', 'LT', 'LU', 'LV', 'LY', 'MT', 'MX', 'MY', 'MZ', 'NL', 'PL', 'PT', 'RO', 'RU', 'SE', 'SL', 'SK', 'TH', 'TR', 'UA', 'US']`.
+**isPassportNumber(str, countryCode)**    | check if the string is a valid passport number.<br/><br/>`countryCode` is one of `['AM', 'AR', 'AT', 'AU', 'AZ', 'BE', 'BG', 'BY', 'BR', 'CA', 'CH', 'CN', 'CY', 'CZ', 'DE', 'DK', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE', 'IN', 'IR', 'ID', 'IS', 'IT', 'JM', 'JP', 'KR', 'KZ', 'LI', 'LT', 'LU', 'LV', 'LY', 'MT', 'MX', 'MY', 'MZ', 'NL', 'NZ', 'PH', 'PK', 'PL', 'PT', 'RO', 'RU', 'SE', 'SL', 'SK', 'TH', 'TR', 'UA', 'US']`.
 **isPort(str)**                         | check if the string is a valid port number.
 **isPostalCode(str, locale)**           | check if the string is a postal code.<br/><br/>`locale` is one of `['AD', 'AT', 'AU', 'AZ', 'BA', 'BE', 'BG', 'BR', 'BY', 'CA', 'CH', 'CN', 'CZ', 'DE', 'DK', 'DO', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IN', 'IR', 'IS', 'IT', 'JP', 'KE', 'KR', 'LI', 'LK', 'LT', 'LU', 'LV', 'MG', 'MT', 'MX', 'MY', 'NL', 'NO', 'NP', 'NZ', 'PL', 'PR', 'PT', 'RO', 'RU', 'SA', 'SE', 'SG', 'SI', 'SK', 'TH', 'TN', 'TW', 'UA', 'US', 'ZA', 'ZM']` OR `'any'`. If 'any' is used, function will check if any of the locales match. Locale list is `validator.isPostalCodeLocales`.
 **isRFC3339(str)**                      | check if the string is a valid [RFC 3339][RFC 3339] date.
diff --git a/src/lib/isBIC.js b/src/lib/isBIC.js
index b5576b2..b0f5867 100644
--- a/src/lib/isBIC.js
+++ b/src/lib/isBIC.js
@@ -9,7 +9,9 @@ export default function isBIC(str) {
 
   // toUpperCase() should be removed when a new major version goes out that changes
   // the regex to [A-Z] (per the spec).
-  if (!CountryCodes.has(str.slice(4, 6).toUpperCase())) {
+  const countryCode = str.slice(4, 6).toUpperCase();
+
+  if (!CountryCodes.has(countryCode) && countryCode !== 'XK') {
     return false;
   }
 
diff --git a/src/lib/isEmail.js b/src/lib/isEmail.js
index 6db0019..d1c35bd 100644
--- a/src/lib/isEmail.js
+++ b/src/lib/isEmail.js
@@ -139,7 +139,10 @@ export default function isEmail(str, options) {
     return false;
   }
 
-  if (!isFQDN(domain, { require_tld: options.require_tld })) {
+  if (!isFQDN(domain, {
+    require_tld: options.require_tld,
+    ignore_max_length: options.ignore_max_length,
+  })) {
     if (!options.allow_ip_domain) {
       return false;
     }
diff --git a/src/lib/isFQDN.js b/src/lib/isFQDN.js
index 884d1dd..eb6928f 100644
--- a/src/lib/isFQDN.js
+++ b/src/lib/isFQDN.js
@@ -7,6 +7,7 @@ const default_fqdn_options = {
   allow_trailing_dot: false,
   allow_numeric_tld: false,
   allow_wildcard: false,
+  ignore_max_length: false,
 };
 
 export default function isFQDN(str, options) {
@@ -48,7 +49,7 @@ export default function isFQDN(str, options) {
   }
 
   return parts.every((part) => {
-    if (part.length > 63) {
+    if (part.length > 63 && !options.ignore_max_length) {
       return false;
     }
 
diff --git a/src/lib/isFloat.js b/src/lib/isFloat.js
index e6cced0..643f972 100644
--- a/src/lib/isFloat.js
+++ b/src/lib/isFloat.js
@@ -5,7 +5,7 @@ export default function isFloat(str, options) {
   assertString(str);
   options = options || {};
   const float = new RegExp(`^(?:[-+])?(?:[0-9]+)?(?:\\${options.locale ? decimal[options.locale] : '.'}[0-9]*)?(?:[eE][\\+\\-]?(?:[0-9]+))?$`);
-  if (str === '' || str === '.' || str === '-' || str === '+') {
+  if (str === '' || str === '.' || str === ',' || str === '-' || str === '+') {
     return false;
   }
   const value = parseFloat(str.replace(',', '.'));
diff --git a/src/lib/isLicensePlate.js b/src/lib/isLicensePlate.js
index 0af2320..48f8ebe 100644
--- a/src/lib/isLicensePlate.js
+++ b/src/lib/isLicensePlate.js
@@ -6,32 +6,20 @@ const validators = {
   'de-DE': str =>
     /^((A|AA|AB|AC|AE|AH|AK|AM|AN|AÖ|AP|AS|AT|AU|AW|AZ|B|BA|BB|BC|BE|BF|BH|BI|BK|BL|BM|BN|BO|BÖ|BS|BT|BZ|C|CA|CB|CE|CO|CR|CW|D|DA|DD|DE|DH|DI|DL|DM|DN|DO|DU|DW|DZ|E|EA|EB|ED|EE|EF|EG|EH|EI|EL|EM|EN|ER|ES|EU|EW|F|FB|FD|FF|FG|FI|FL|FN|FO|FR|FS|FT|FÜ|FW|FZ|G|GA|GC|GD|GE|GF|GG|GI|GK|GL|GM|GN|GÖ|GP|GR|GS|GT|GÜ|GV|GW|GZ|H|HA|HB|HC|HD|HE|HF|HG|HH|HI|HK|HL|HM|HN|HO|HP|HR|HS|HU|HV|HX|HY|HZ|IK|IL|IN|IZ|J|JE|JL|K|KA|KB|KC|KE|KF|KG|KH|KI|KK|KL|KM|KN|KO|KR|KS|KT|KU|KW|KY|L|LA|LB|LC|LD|LF|LG|LH|LI|LL|LM|LN|LÖ|LP|LR|LU|M|MA|MB|MC|MD|ME|MG|MH|MI|MK|ML|MM|MN|MO|MQ|MR|MS|MÜ|MW|MY|MZ|N|NB|ND|NE|NF|NH|NI|NK|NM|NÖ|NP|NR|NT|NU|NW|NY|NZ|OA|OB|OC|OD|OE|OF|OG|OH|OK|OL|OP|OS|OZ|P|PA|PB|PE|PF|PI|PL|PM|PN|PR|PS|PW|PZ|R|RA|RC|RD|RE|RG|RH|RI|RL|RM|RN|RO|RP|RS|RT|RU|RV|RW|RZ|S|SB|SC|SE|SG|SI|SK|SL|SM|SN|SO|SP|SR|ST|SU|SW|SY|SZ|TE|TF|TG|TO|TP|TR|TS|TT|TÜ|ÜB|UE|UH|UL|UM|UN|V|VB|VG|VK|VR|VS|W|WA|WB|WE|WF|WI|WK|WL|WM|WN|WO|WR|WS|WT|WÜ|WW|WZ|Z|ZE|ZI|ZP|ZR|ZW|ZZ)[- ]?[A-Z]{1,2}[- ]?\d{1,4}|(ABG|ABI|AIB|AIC|ALF|ALZ|ANA|ANG|ANK|APD|ARN|ART|ASL|ASZ|AUR|AZE|BAD|BAR|BBG|BCH|BED|BER|BGD|BGL|BID|BIN|BIR|BIT|BIW|BKS|BLB|BLK|BNA|BOG|BOH|BOR|BOT|BRA|BRB|BRG|BRK|BRL|BRV|BSB|BSK|BTF|BÜD|BUL|BÜR|BÜS|BÜZ|CAS|CHA|CLP|CLZ|COC|COE|CUX|DAH|DAN|DAU|DBR|DEG|DEL|DGF|DIL|DIN|DIZ|DKB|DLG|DON|DUD|DÜW|EBE|EBN|EBS|ECK|EIC|EIL|EIN|EIS|EMD|EMS|ERB|ERH|ERK|ERZ|ESB|ESW|FDB|FDS|FEU|FFB|FKB|FLÖ|FOR|FRG|FRI|FRW|FTL|FÜS|GAN|GAP|GDB|GEL|GEO|GER|GHA|GHC|GLA|GMN|GNT|GOA|GOH|GRA|GRH|GRI|GRM|GRZ|GTH|GUB|GUN|GVM|HAB|HAL|HAM|HAS|HBN|HBS|HCH|HDH|HDL|HEB|HEF|HEI|HER|HET|HGN|HGW|HHM|HIG|HIP|HMÜ|HOG|HOH|HOL|HOM|HOR|HÖS|HOT|HRO|HSK|HST|HVL|HWI|IGB|ILL|JÜL|KEH|KEL|KEM|KIB|KLE|KLZ|KÖN|KÖT|KÖZ|KRU|KÜN|KUS|KYF|LAN|LAU|LBS|LBZ|LDK|LDS|LEO|LER|LEV|LIB|LIF|LIP|LÖB|LOS|LRO|LSZ|LÜN|LUP|LWL|MAB|MAI|MAK|MAL|MED|MEG|MEI|MEK|MEL|MER|MET|MGH|MGN|MHL|MIL|MKK|MOD|MOL|MON|MOS|MSE|MSH|MSP|MST|MTK|MTL|MÜB|MÜR|MYK|MZG|NAB|NAI|NAU|NDH|NEA|NEB|NEC|NEN|NES|NEW|NMB|NMS|NOH|NOL|NOM|NOR|NVP|NWM|OAL|OBB|OBG|OCH|OHA|ÖHR|OHV|OHZ|OPR|OSL|OVI|OVL|OVP|PAF|PAN|PAR|PCH|PEG|PIR|PLÖ|PRÜ|QFT|QLB|RDG|REG|REH|REI|RID|RIE|ROD|ROF|ROK|ROL|ROS|ROT|ROW|RSL|RÜD|RÜG|SAB|SAD|SAN|SAW|SBG|SBK|SCZ|SDH|SDL|SDT|SEB|SEE|SEF|SEL|SFB|SFT|SGH|SHA|SHG|SHK|SHL|SIG|SIM|SLE|SLF|SLK|SLN|SLS|SLÜ|SLZ|SMÜ|SOB|SOG|SOK|SÖM|SON|SPB|SPN|SRB|SRO|STA|STB|STD|STE|STL|SUL|SÜW|SWA|SZB|TBB|TDO|TET|TIR|TÖL|TUT|UEM|UER|UFF|USI|VAI|VEC|VER|VIB|VIE|VIT|VOH|WAF|WAK|WAN|WAR|WAT|WBS|WDA|WEL|WEN|WER|WES|WHV|WIL|WIS|WIT|WIZ|WLG|WMS|WND|WOB|WOH|WOL|WOR|WOS|WRN|WSF|WST|WSW|WTL|WTM|WUG|WÜM|WUN|WUR|WZL|ZEL|ZIG)[- ]?(([A-Z][- ]?\d{1,4})|([A-Z]{2}[- ]?\d{1,3})))[- ]?(E|H)?$/.test(str),
   'de-LI': str => /^FL[- ]?\d{1,5}[UZ]?$/.test(str),
+  'en-IN': str => /^[A-Z]{2}[ -]?[0-9]{1,2}(?:[ -]?[A-Z])(?:[ -]?[A-Z]*)?[ -]?[0-9]{4}$/.test(str),
+  'es-AR': str => /^(([A-Z]{2} ?[0-9]{3} ?[A-Z]{2})|([A-Z]{3} ?[0-9]{3}))$/.test(str),
   'fi-FI': str => /^(?=.{4,7})(([A-Z]{1,3}|[0-9]{1,3})[\s-]?([A-Z]{1,3}|[0-9]{1,5}))$/.test(str),
+  'hu-HU': str => /^((((?!AAA)(([A-NPRSTVZWXY]{1})([A-PR-Z]{1})([A-HJ-NPR-Z]))|(A[ABC]I)|A[ABC]O|A[A-W]Q|BPI|BPO|UCO|UDO|XAO)-(?!000)\d{3})|(M\d{6})|((CK|DT|CD|HC|H[ABEFIKLMNPRSTVX]|MA|OT|R[A-Z]) \d{2}-\d{2})|(CD \d{3}-\d{3})|(C-(C|X) \d{4})|(X-(A|B|C) \d{4})|(([EPVZ]-\d{5}))|(S A[A-Z]{2} \d{2})|(SP \d{2}-\d{2}))$/.test(str),
+  'pt-BR': str =>
+    /^[A-Z]{3}[ -]?[0-9][A-Z][0-9]{2}|[A-Z]{3}[ -]?[0-9]{4}$/.test(str),
   'pt-PT': str =>
     /^([A-Z]{2}|[0-9]{2})[ -·]?([A-Z]{2}|[0-9]{2})[ -·]?([A-Z]{2}|[0-9]{2})$/.test(str),
   'sq-AL': str =>
     /^[A-Z]{2}[- ]?((\d{3}[- ]?(([A-Z]{2})|T))|(R[- ]?\d{3}))$/.test(str),
-  'pt-BR': str =>
-    /^[A-Z]{3}[ -]?[0-9][A-Z][0-9]{2}|[A-Z]{3}[ -]?[0-9]{4}$/.test(str),
   'sv-SE': str =>
     /^[A-HJ-PR-UW-Z]{3} ?[\d]{2}[A-HJ-PR-UW-Z1-9]$|(^[A-ZÅÄÖ ]{2,7}$)/.test(str.trim()),
-  'en-IN': str => /^[A-Z]{2}[ -]?[0-9]{1,2}(?:[ -]?[A-Z])(?:[ -]?[A-Z]*)?[ -]?[0-9]{4}$/.test(str),
 };
 
-validators['hi-IN'] = validators['en-IN'];
-validators['gu-IN'] = validators['en-IN'];
-validators['as-IN'] = validators['en-IN'];
-validators['bn-IN'] = validators['en-IN'];
-validators['kn-IN'] = validators['en-IN'];
-validators['ml-IN'] = validators['en-IN'];
-validators['mr-IN'] = validators['en-IN'];
-validators['or-IN'] = validators['en-IN'];
-validators['pa-IN'] = validators['en-IN'];
-validators['sa-IN'] = validators['en-IN'];
-validators['ta-IN'] = validators['en-IN'];
-validators['te-IN'] = validators['en-IN'];
-validators['kok-IN'] = validators['en-IN'];
-
 export default function isLicensePlate(str, locale) {
   assertString(str);
   if (locale in validators) {
diff --git a/src/lib/isMobilePhone.js b/src/lib/isMobilePhone.js
index c046c90..5c37d42 100644
--- a/src/lib/isMobilePhone.js
+++ b/src/lib/isMobilePhone.js
@@ -95,6 +95,7 @@ const phones = {
   'fo-FO': /^(\+?298)?\s?\d{2}\s?\d{2}\s?\d{2}$/,
   'fr-BF': /^(\+226|0)[67]\d{7}$/,
   'fr-BJ': /^(\+229)\d{8}$/,
+  'fr-CD': /^(\+?243|0)?(8|9)\d{8}$/,
   'fr-CM': /^(\+?237)6[0-9]{8}$/,
   'fr-FR': /^(\+?33|0)[67]\d{8}$/,
   'fr-GF': /^(\+?594|0|00594)[67]\d{8}$/,
@@ -131,6 +132,7 @@ const phones = {
   'pt-BR': /^((\+?55\ ?[1-9]{2}\ ?)|(\+?55\ ?\([1-9]{2}\)\ ?)|(0[1-9]{2}\ ?)|(\([1-9]{2}\)\ ?)|([1-9]{2}\ ?))((\d{4}\-?\d{4})|(9[1-9]{1}\d{3}\-?\d{4}))$/,
   'pt-PT': /^(\+?351)?9[1236]\d{7}$/,
   'pt-AO': /^(\+244)\d{9}$/,
+  'ro-MD': /^(\+?373|0)((6(0|1|2|6|7|8|9))|(7(6|7|8|9)))\d{6}$/,
   'ro-RO': /^(\+?40|0)\s?7\d{2}(\/|\s|\.|-)?\d{3}(\s|\.|-)?\d{3}$/,
   'ru-RU': /^(\+?7|8)?9\d{9}$/,
   'si-LK': /^(?:0|94|\+94)?(7(0|1|2|4|5|6|7|8)( |-)?)\d{7}$/,
diff --git a/src/lib/isPassportNumber.js b/src/lib/isPassportNumber.js
index 5b2ebfd..11d01e8 100644
--- a/src/lib/isPassportNumber.js
+++ b/src/lib/isPassportNumber.js
@@ -11,6 +11,7 @@ const passportRegexByCountryCode = {
   AR: /^[A-Z]{3}\d{6}$/, // ARGENTINA
   AT: /^[A-Z]\d{7}$/, // AUSTRIA
   AU: /^[A-Z]\d{7}$/, // AUSTRALIA
+  AZ: /^[A-Z]{2,3}\d{7,8}$/, // AZERBAIJAN
   BE: /^[A-Z]{2}\d{6}$/, // BELGIUM
   BG: /^\d{9}$/, // BULGARIA
   BR: /^[A-Z]{2}\d{6}$/, // BRAZIL
@@ -37,8 +38,11 @@ const passportRegexByCountryCode = {
   IR: /^[A-Z]\d{8}$/, // IRAN
   IS: /^(A)\d{7}$/, // ICELAND
   IT: /^[A-Z0-9]{2}\d{7}$/, // ITALY
+  JM: /^[Aa]\d{7}$/, // JAMAICA
   JP: /^[A-Z]{2}\d{7}$/, // JAPAN
   KR: /^[MS]\d{8}$/, // SOUTH KOREA, REPUBLIC OF KOREA, [S=PS Passports, M=PM Passports]
+  KZ: /^[a-zA-Z]\d{7}$/, // KAZAKHSTAN
+  LI: /^[a-zA-Z]\d{5}$/, // LIECHTENSTEIN
   LT: /^[A-Z0-9]{8}$/, // LITHUANIA
   LU: /^[A-Z0-9]{8}$/, // LUXEMBURG
   LV: /^[A-Z0-9]{2}\d{7}$/, // LATVIA
@@ -48,12 +52,15 @@ const passportRegexByCountryCode = {
   MY: /^[AHK]\d{8}$/, // MALAYSIA
   MX: /^\d{10,11}$/, // MEXICO
   NL: /^[A-Z]{2}[A-Z0-9]{6}\d$/, // NETHERLANDS
+  NZ: /^([Ll]([Aa]|[Dd]|[Ff]|[Hh])|[Ee]([Aa]|[Pp])|[Nn])\d{6}$/, // NEW ZEALAND
+  PH: /^([A-Z](\d{6}|\d{7}[A-Z]))|([A-Z]{2}(\d{6}|\d{7}))$/, // PHILIPPINES
+  PK: /^[A-Z]{2}\d{7}$/, // PAKISTAN
   PL: /^[A-Z]{2}\d{7}$/, // POLAND
   PT: /^[A-Z]\d{6}$/, // PORTUGAL
   RO: /^\d{8,9}$/, // ROMANIA
   RU: /^\d{9}$/, // RUSSIAN FEDERATION
   SE: /^\d{8}$/, // SWEDEN
-  SL: /^(P)[A-Z]\d{7}$/, // SLOVANIA
+  SL: /^(P)[A-Z]\d{7}$/, // SLOVENIA
   SK: /^[0-9A-Z]\d{7}$/, // SLOVAKIA
   TH: /^[A-Z]{1,2}\d{6,7}$/, // THAILAND
   TR: /^[A-Z]\d{8}$/, // TURKEY


Test patch:
diff --git a/test/validators.test.js b/test/validators.test.js
index 79a3fa9..3a46a35 100644
--- a/test/validators.test.js
+++ b/test/validators.test.js
@@ -278,6 +278,15 @@ describe('Validators', () => {
       ],
       invalid: [],
     });
+
+    test({
+      validator: 'isEmail',
+      args: [{ ignore_max_length: true }],
+      valid: [
+        'Deleted-user-id-19430-Team-5051deleted-user-id-19430-team-5051XXXXXX@Deleted-user-id-19430-Team-5051deleted-user-id-19430-team-5051XXXXXX.com',
+      ],
+      invalid: [],
+    });
   });
 
   it('should not validate email addresses with denylisted domains', () => {
@@ -2855,6 +2864,18 @@ describe('Validators', () => {
       ],
     });
 
+    test({
+      validator: 'isPassportNumber',
+      args: ['AZ'],
+      valid: [
+        'AZE16175905',
+        'AA1617595',
+      ],
+      invalid: [
+        'A12345843',
+      ],
+    });
+
     test({
       validator: 'isPassportNumber',
       args: ['BE'],
@@ -3190,6 +3211,18 @@ describe('Validators', () => {
       ],
     });
 
+    test({
+      validator: 'isPassportNumber',
+      args: ['JM'],
+      valid: [
+        'A0123456',
+      ],
+      invalid: [
+        's0123456',
+        'a01234567',
+      ],
+    });
+
     test({
       validator: 'isPassportNumber',
       args: ['JP'],
@@ -3217,6 +3250,31 @@ describe('Validators', () => {
       ],
     });
 
+    test({
+      validator: 'isPassportNumber',
+      args: ['KZ'],
+      valid: [
+        'A0123456',
+        'b0123456',
+      ],
+      invalid: [
+        '01234567',
+        'bb0123456',
+      ],
+    });
+
+    test({
+      validator: 'isPassportNumber',
+      args: ['LI'],
+      valid: [
+        'a01234',
+        'f01234',
+      ],
+      invalid: [
+        '012345',
+      ],
+    });
+
     test({
       validator: 'isPassportNumber',
       args: ['LT'],
@@ -3331,6 +3389,55 @@ describe('Validators', () => {
         'XR1001R58A',
       ],
     });
+    test({
+      validator: 'isPassportNumber',
+      args: ['PK'],
+      valid: [
+        'QZ1791293',
+        'XR1001458',
+      ],
+      invalid: [
+        'XTR11013R',
+        'XR1001R58A',
+      ],
+    });
+
+    test({
+      validator: 'isPassportNumber',
+      args: ['PH'],
+      valid: [
+        'X123456',
+        'XY123456',
+        'XY1234567',
+        'X1234567Y',
+      ],
+      invalid: [
+        'XY12345',
+        'X12345Z',
+        'XY12345Z',
+      ],
+    });
+
+    test({
+      validator: 'isPassportNumber',
+      args: ['NZ'],
+      valid: [
+        'Lf012345',
+        'La012345',
+        'Ld012345',
+        'Lh012345',
+        'ea012345',
+        'ep012345',
+        'n012345',
+      ],
+      invalid: [
+        'Lp012345',
+        'nd012345',
+        'ed012345',
+        'eh012345',
+        'ef012345',
+      ],
+    });
 
     test({
       validator: 'isPassportNumber',
@@ -4015,6 +4122,7 @@ describe('Validators', () => {
         '  ',
         '',
         '.',
+        ',',
         'foo',
         '20.foo',
         '2020-01-06T14:31:00.135Z',
@@ -5075,6 +5183,7 @@ describe('Validators', () => {
         'SBICKEN1',
         'SBICKENY',
         'SBICKEN1YYP',
+        'SBICXKN1YYP',
       ],
       invalid: [
         'SBIC23NXXX',
@@ -5083,6 +5192,7 @@ describe('Validators', () => {
         'SBICKENXX9',
         'SBICKEN13458',
         'SBICKEN',
+        'SBICXK',
       ],
     });
   });
@@ -7489,6 +7599,24 @@ describe('Validators', () => {
           '11435213543',
         ],
       },
+      {
+        locale: 'fr-CD',
+        valid: [
+          '+243818590432',
+          '+243893875610',
+          '243978590234',
+          '0813346543',
+          '0820459022',
+          '+243902590221',
+        ],
+        invalid: [
+          '243',
+          '+254818590432',
+          '+24389032',
+          '123456789',
+          '+243700723845',
+        ],
+      },
       {
         locale: 'fr-GF',
         valid: [
@@ -8758,6 +8886,36 @@ describe('Validators', () => {
           'number',
         ],
       },
+      {
+        locale: 'ro-MD',
+        valid: [
+          '+37360375781',
+          '+37361945673',
+          '+37362387563',
+          '+37368447788',
+          '+37369000101',
+          '+37367568910',
+          '+37376758294',
+          '+37378457892',
+          '+37379067436',
+          '37362387563',
+          '37368447788',
+          '37369000101',
+          '37367568910',
+        ],
+        invalid: [
+          '',
+          '+37363373381',
+          '+37364310581',
+          '+37365578199',
+          '+37371088636',
+          'Vml2YW11cyBmZXJtZtesting123',
+          '123456',
+          '740123456',
+          '+40640123456',
+          '+40210123456',
+        ],
+      },
       {
         locale: 'ro-RO',
         valid: [
@@ -12687,6 +12845,26 @@ describe('Validators', () => {
     });
   });
   it('should be valid license plate', () => {
+    test({
+      validator: 'isLicensePlate',
+      args: ['es-AR'],
+      valid: [
+        'AB 123 CD',
+        'AB123CD',
+        'ABC 123',
+        'ABC123',
+      ],
+      invalid: [
+        '',
+        'notalicenseplate',
+        'AB-123-CD',
+        'ABC-123',
+        'AABC 123',
+        'AB CDE FG',
+        'ABC DEF',
+        '12 ABC 34',
+      ],
+    });
     test({
       validator: 'isLicensePlate',
       args: ['pt-PT'],
@@ -12865,6 +13043,76 @@ describe('Validators', () => {
         'AB123DC',
       ],
     });
+    test({
+      validator: 'isLicensePlate',
+      args: ['hu-HU'],
+      valid: [
+        'AAB-001',
+        'AVC-987',
+        'KOC-124',
+        'JCM-871',
+        'AWQ-777',
+        'BPO-001',
+        'BPI-002',
+        'UCO-342',
+        'UDO-385',
+        'XAO-987',
+        'AAI-789',
+        'ABI-789',
+        'ACI-789',
+        'AAO-789',
+        'ABO-789',
+        'ACO-789',
+        'YAA-123',
+        'XAA-123',
+        'WAA-258',
+        'XZZ-784',
+        'M123456',
+        'CK 12-34',
+        'DT 12-34',
+        'CD 12-34',
+        'HC 12-34',
+        'HB 12-34',
+        'HK 12-34',
+        'MA 12-34',
+        'OT 12-34',
+        'RR 17-87',
+        'CD 124-348',
+        'C-C 2021',
+        'C-X 2458',
+        'X-A 7842',
+        'E-72345',
+        'Z-07458',
+        'S ACF 83',
+        'SP 04-68',
+      ],
+      invalid: [
+        'AAA-547',
+        'aab-001',
+        'AAB 001',
+        'AB34',
+        '789-LKJ',
+        'BBO-987',
+        'BBI-987',
+        'BWQ-777',
+        'BQW-987',
+        'BAI-789',
+        'BBI-789',
+        'BCI-789',
+        'BAO-789',
+        'BBO-789',
+        'BCO-789',
+        'ADI-789',
+        'ADO-789',
+        'KOC-1234',
+        'M1234567',
+        'W-12345',
+        'S BCF 83',
+        'X-D 1234',
+        'C-D 1234',
+        'HU 12-34',
+      ],
+    });
     test({
       validator: 'isLicensePlate',
       args: ['any'],