Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
mhf-ir authored Mar 14, 2021
2 parents ec435d5 + 63b6162 commit 9be5e50
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 17 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[![Downloads][downloads-image]][npm-url]
[![Backers on Open Collective](https://opencollective.com/validatorjs/backers/badge.svg)](#backers)
[![Sponsors on Open Collective](https://opencollective.com/validatorjs/sponsors/badge.svg)](#sponsors)
[![Gitter](https://badges.gitter.im/validatorjs/community.svg)](https://gitter.im/validatorjs/community)

A library of string validators and sanitizers.

Expand Down Expand Up @@ -131,7 +132,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 string matches the format of a country's license plate.<br/><br/>(locale is one of `['de-DE', 'de-LI', 'pt-PT', 'sq-AL']` or `any`)
**isLicensePlate(str [, locale])** | check if string matches the format of a country's license plate.<br/><br/>(locale is one of `['de-DE', 'de-LI', 'pt-PT', 'sq-AL', 'pt-BR'']` or `any`).
**isLocale(str)** | check if the string is a locale
**isLowercase(str)** | check if the string is lowercase.
**isLuhn(str)** | check if the string is a valid [Luhn](https://en.wikipedia.org/wiki/Luhn_algorithm).
Expand All @@ -144,7 +145,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.<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` determine 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', 'CA', 'CH', 'CN', 'CY', 'CZ', 'DE', 'DK', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE' 'IN', 'IR', 'IS', 'IT', 'JP', 'KR', 'LT', 'LU', 'LV', 'LY', 'MT', 'NL', 'PO', 'PT', 'RO', 'RU', 'SE', 'SL', 'SK', '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', 'BE', 'BG', 'BY', 'BR', 'CA', 'CH', 'CN', 'CY', 'CZ', 'DE', 'DK', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE' 'IN', 'IR', 'IS', 'IT', 'JP', 'KR', 'LT', 'LU', 'LV', 'LY', 'MT', 'MY', 'NL', 'PO', 'PT', 'RO', 'RU', 'SE', 'SL', 'SK', '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', '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', 'LI', 'LT', 'LU', 'LV', 'MT', 'MX', 'MY', 'NL', 'NO', 'NP', 'NZ', 'PL', 'PR', 'PT', 'RO', 'RU', 'SA', 'SE', 'SG', 'SI', 'TH', '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`.).
**isRFC3339(str)** | check if the string is a valid [RFC 3339](https://tools.ietf.org/html/rfc3339) date.
Expand All @@ -154,7 +155,7 @@ Validator | Description
**isUppercase(str)** | check if the string is uppercase.
**isSlug** | Check if the string is of type slug. `Options` allow a single hyphen between string. e.g. [`cn-cn`, `cn-c-c`]
**isStrongPassword(str [, options])** | Check if a password is strong or not. Allows for custom requirements or scoring rules. If `returnScore` is true, then the function returns an integer score for the password rather than a boolean.<br/>Default options: <br/>`{ minLength: 8, minLowercase: 1, minUppercase: 1, minNumbers: 1, minSymbols: 1, returnScore: false, pointsPerUnique: 1, pointsPerRepeat: 0.5, pointsForContainingLower: 10, pointsForContainingUpper: 10, pointsForContainingNumber: 10, pointsForContainingSymbol: 10 }`
**isTaxID(str, locale)** | Check if the given value is a valid Tax Identification Number. Default locale is `en-US`.<br/><br/>More info about exact TIN support can be found in `src/lib/isTaxID.js`<br/><br/>Supported locales: `[ 'bg-BG', 'cs-CZ', 'de-AT', 'de-DE', 'dk-DK', 'el-CY', 'el-GR', 'en-GB', 'en-IE', 'en-US', 'es-ES', 'et-EE', 'fi-FI', 'fr-BE', 'fr-FR', 'fr-LU', 'hr-HR', 'hu-HU', 'it-IT', 'lb-LU', 'lt-LT', 'lv-LV' 'mt-MT', 'nl-BE', 'nl-NL', 'pl-PL', 'pt-PT', 'ro-RO', 'sk-SK', 'sl-SI', 'sv-SE' ]`
**isTaxID(str, locale)** | Check if the given value is a valid Tax Identification Number. Default locale is `en-US`.<br/><br/>More info about exact TIN support can be found in `src/lib/isTaxID.js`<br/><br/>Supported locales: `[ 'bg-BG', 'cs-CZ', 'de-AT', 'de-DE', 'dk-DK', 'el-CY', 'el-GR', 'en-GB', 'en-IE', 'en-US', 'es-ES', 'et-EE', 'fi-FI', 'fr-BE', 'fr-FR', 'fr-LU', 'hr-HR', 'hu-HU', 'it-IT', 'lb-LU', 'lt-LT', 'lv-LV' 'mt-MT', 'nl-BE', 'nl-NL', 'pl-PL', 'pt-BR', 'pt-PT', 'ro-RO', 'sk-SK', 'sl-SI', 'sv-SE' ]`
**isURL(str [, options])** | check if the string is an URL.<br/><br/>`options` is an object which defaults to `{ protocols: ['http','https','ftp'], require_tld: true, require_protocol: false, require_host: true, require_valid_protocol: true, allow_underscores: false, host_whitelist: false, host_blacklist: false, allow_trailing_dot: false, allow_protocol_relative_urls: false, disallow_auth: false }`.<br/><br/>require_protocol - if set as true isURL will return false if protocol is not present in the URL.<br/>require_valid_protocol - isURL will check if the URL's protocol is present in the protocols option.<br/>protocols - valid protocols can be modified with this option.<br/>require_host - if set as false isURL will not check if host is present in the URL.<br/>require_port - if set as true isURL will check if port is present in the URL.<br/>allow_protocol_relative_urls - if set as true protocol relative URLs will be allowed.<br/>validate_length - if set as false isURL will skip string length validation (2083 characters is IE max URL length).
**isUUID(str [, version])** | check if the string is a UUID (version 3, 4 or 5).
**isVariableWidth(str)** | check if the string contains a mixture of full and half-width chars.
Expand Down
11 changes: 6 additions & 5 deletions src/lib/isLicensePlate.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const validators = {
/^([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),
};

export default function isLicensePlate(str, locale) {
Expand All @@ -16,11 +18,10 @@ export default function isLicensePlate(str, locale) {
return validators[locale](str);
} else if (locale === 'any') {
for (const key in validators) {
if (validators.hasOwnProperty(key)) {
const validator = validators[key];
if (validator(str)) {
return true;
}
/* eslint guard-for-in: 0 */
const validator = validators[key];
if (validator(str)) {
return true;
}
}
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/isMobilePhone.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const phones = {
'en-ZW': /^(\+263)[0-9]{9}$/,
'es-AR': /^\+?549(11|[2368]\d)\d{8}$/,
'es-BO': /^(\+?591)?(6|7)\d{7}$/,
'es-CO': /^(\+?57)?([1-8]{1}|3[0-9]{2})?[0-9]{1}\d{6}$/,
'es-CO': /^(\+?57)?3(0(0|1|2|4|5)|1\d|2[0-4]|5(0|1))\d{7}$/,
'es-CL': /^(\+?56|0)[2-9]\d{1}\d{7}$/,
'es-CR': /^(\+506)?[2-8]\d{7}$/,
'es-DO': /^(\+?1)?8[024]9\d{7}$/,
Expand Down
2 changes: 2 additions & 0 deletions src/lib/isPassportNumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const passportRegexByCountryCode = {
AU: /^[A-Z]\d{7}$/, // AUSTRALIA
BE: /^[A-Z]{2}\d{6}$/, // BELGIUM
BG: /^\d{9}$/, // BULGARIA
BR: /^[A-Z]{2}\d{6}$/, // BRAZIL
BY: /^[A-Z]{2}\d{7}$/, // BELARUS
CA: /^[A-Z]{2}\d{6}$/, // CANADA
CH: /^[A-Z]\d{7}$/, // SWITZERLAND
Expand Down Expand Up @@ -42,6 +43,7 @@ const passportRegexByCountryCode = {
LV: /^[A-Z0-9]{2}\d{7}$/, // LATVIA
LY: /^[A-Z0-9]{8}$/, // LIBYA
MT: /^\d{7}$/, // MALTA
MY: /^[AHK]\d{8}$/, // MALAYSIA
NL: /^[A-Z]{2}[A-Z0-9]{6}\d$/, // NETHERLANDS
PO: /^[A-Z]{2}\d{7}$/, // POLAND
PT: /^[A-Z]\d{6}$/, // PORTUGAL
Expand Down
1 change: 1 addition & 0 deletions src/lib/isStrongPassword.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function analyzePassword(password) {
symbolCount: 0,
};
Object.keys(charMap).forEach((char) => {
/* istanbul ignore else */
if (upperCaseRegex.test(char)) {
analysis.uppercaseCount += charMap[char];
} else if (lowerCaseRegex.test(char)) {
Expand Down
89 changes: 89 additions & 0 deletions src/lib/isTaxID.js
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,93 @@ function plPlCheck(tin) {
return checksum === parseInt(tin[10], 10);
}

/*
* pt-BR validation function
* (Cadastro de Pessoas Físicas (CPF, persons)
* Cadastro Nacional de Pessoas Jurídicas (CNPJ, entities)
* Both inputs will be validated
*/

function ptBrCheck(tin) {
tin = tin.replace(/[^\d]+/g, '');
if (tin === '') return false;

if (tin.length === 11) {
let sum;
let ramainder;
sum = 0;
tin = tin.replace(/[^\d]+/g, '');

if ( // Reject known invalid CPFs
tin === '11111111111' ||
tin === '22222222222' ||
tin === '33333333333' ||
tin === '44444444444' ||
tin === '55555555555' ||
tin === '66666666666' ||
tin === '77777777777' ||
tin === '88888888888' ||
tin === '99999999999' ||
tin === '00000000000'
) return false;

for (let i = 1; i <= 9; i++) sum += parseInt(tin.substring(i - 1, i), 10) * (11 - i);
ramainder = (sum * 10) % 11;
if ((ramainder === 10) || (ramainder === 11)) ramainder = 0;
if (ramainder !== parseInt(tin.substring(9, 10), 10)) return false;
sum = 0;

for (let i = 1; i <= 10; i++) sum += parseInt(tin.substring(i - 1, i), 10) * (12 - i);
ramainder = (sum * 10) % 11;
if ((ramainder === 10) || (ramainder === 11)) ramainder = 0;
if (ramainder !== parseInt(tin.substring(10, 11), 10)) return false;

return true;
}

if (tin.length !== 14) { return false; }

if ( // Reject know invalid CNPJs
tin === '00000000000000' ||
tin === '11111111111111' ||
tin === '22222222222222' ||
tin === '33333333333333' ||
tin === '44444444444444' ||
tin === '55555555555555' ||
tin === '66666666666666' ||
tin === '77777777777777' ||
tin === '88888888888888' ||
tin === '99999999999999') { return false; }

let length = tin.length - 2;
let identifiers = tin.substring(0, length);
let verificators = tin.substring(length);
let sum = 0;
let pos = length - 7;

for (let i = length; i >= 1; i--) {
sum += identifiers.charAt(length - i) * pos;
pos -= 1;
if (pos < 2) { pos = 9; }
}
let result = sum % 11 < 2 ? 0 : 11 - (sum % 11);
if (result !== parseInt(verificators.charAt(0), 10)) { return false; }

length += 1;
identifiers = tin.substring(0, length);
sum = 0;
pos = length - 7;
for (let i = length; i >= 1; i--) {
sum += identifiers.charAt(length - i) * pos;
pos -= 1;
if (pos < 2) { pos = 9; }
}
result = sum % 11 < 2 ? 0 : 11 - (sum % 11);
if (result !== parseInt(verificators.charAt(1), 10)) { return false; }

return true;
}

/*
* pt-PT validation function
* (Número de identificação fiscal (NIF), persons/entities)
Expand Down Expand Up @@ -1039,6 +1126,7 @@ const taxIdFormat = {
'mt-MT': /^\d{3,7}[APMGLHBZ]$|^([1-8])\1\d{7}$/i,
'nl-NL': /^\d{9}$/,
'pl-PL': /^\d{10,11}$/,
'pt-BR': /^\d{11,14}$/,
'pt-PT': /^\d{9}$/,
'ro-RO': /^\d{13}$/,
'sk-SK': /^\d{6}\/{0,1}\d{3,4}$/,
Expand Down Expand Up @@ -1076,6 +1164,7 @@ const taxIdCheck = {
'mt-MT': mtMtCheck,
'nl-NL': nlNlCheck,
'pl-PL': plPlCheck,
'pt-BR': ptBrCheck,
'pt-PT': ptPtCheck,
'ro-RO': roRoCheck,
'sk-SK': skSkCheck,
Expand Down
80 changes: 72 additions & 8 deletions test/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -2289,6 +2289,18 @@ describe('Validators', () => {
],
});

test({
validator: 'isPassportNumber',
args: ['BR'],
valid: [
'FZ973689',
'GH231233',
],
invalid: [
'ABX29332',
],
});

test({
validator: 'isPassportNumber',
args: ['BY'],
Expand Down Expand Up @@ -2673,6 +2685,20 @@ describe('Validators', () => {
],
});

test({
validator: 'isPassportNumber',
args: ['MY'],
valid: [
'A00000000',
'H12345678',
'K43143233',
],
invalid: [
'A1234567',
'C01234567',
],
});

test({
validator: 'isPassportNumber',
args: ['NL'],
Expand Down Expand Up @@ -6569,18 +6595,11 @@ describe('Validators', () => {
valid: [
'+573003321235',
'573003321235',
'579871235',
'3003321235',
'3213321235',
'3103321235',
'3253321235',
'3321235',
'574321235',
'5784321235',
'5784321235',
'9821235',
'3243321235',
'573011140876',
'0698345',
],
invalid: [
'1234',
Expand All @@ -6593,6 +6612,13 @@ describe('Validators', () => {
'5703013347567',
'069834567',
'969834567',
'579871235',
'574321235',
'5784321235',
'5784321235',
'9821235',
'0698345',
'3321235',
],
},
{
Expand Down Expand Up @@ -10028,6 +10054,22 @@ describe('Validators', () => {
'2234567855',
'02223013623'],
});
test({
validator: 'isTaxID',
args: ['pt-BR'],
valid: [
'35161990910',
'74407265027',
'05423994000172',
'11867044000130'],
invalid: [
'170.691.440-72',
'01494282042',
'11111111111',
'94.592.973/0001-82',
'28592361000192',
'11111111111111'],
});
test({
validator: 'isTaxID',
args: ['pt-PT'],
Expand Down Expand Up @@ -10438,6 +10480,28 @@ describe('Validators', () => {
'AAA 00 AAA',
],
});
test({
validator: 'isLicensePlate',
args: ['pt-BR'],
valid: [
'ABC1234',
'ABC 1234',
'ABC-1234',
'ABC1D23',
'ABC1K23',
'ABC1Z23',
'ABC 1D23',
'ABC-1D23',
],
invalid: [
'',
'AA 0 A',
'AAA 00 AAA',
'ABCD123',
'AB12345',
'AB123DC',
],
});
test({
validator: 'isLicensePlate',
args: ['any'],
Expand Down

0 comments on commit 9be5e50

Please sign in to comment.