Skip to content

Commit

Permalink
Merge branch 'master' into mac
Browse files Browse the repository at this point in the history
  • Loading branch information
chriso authored Jul 31, 2018
2 parents baea866 + c192d7c commit 340df7b
Show file tree
Hide file tree
Showing 11 changed files with 250 additions and 94 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@ language: node_js
node_js:
- stable
- 8
- 6
notifications:
email: false
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
#### HEAD

- New locale
([#856](https://github.com/chriso/validator.js/pull/856))
- Added support for IP hostnames in `isEmail()`
([#845](https://github.com/chriso/validator.js/pull/845))
- Added a `no_symbols` option to `isNumeric()`
([#848](https://github.com/chriso/validator.js/pull/848))
- New and improved locales
([#856](https://github.com/chriso/validator.js/pull/856),
[#870](https://github.com/chriso/validator.js/pull/870),
[#872](https://github.com/chriso/validator.js/pull/872))

#### 10.4.0

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Validator | Description
**isDataURI(str)** | check if the string is a [data uri format](https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs).
**isDecimal(str [, options])** | check if the string represents a decimal number, such as 0.1, .3, 1.1, 1.00003, 4.0, etc.<br/><br/>`options` is an object which defaults to `{force_decimal: false, decimal_digits: '1,', locale: 'en-US'}`<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', 'hu-HU', 'it-IT', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`.<br/>**Note:** `decimal_digits` is given as a range like '1,3', a specific value like '3' or min like '1,'.
**isDivisibleBy(str, number)** | check if the string is a number that's divisible by another.
**isEmail(str [, options])** | check if the string is an email.<br/><br/>`options` is an object which defaults to `{ allow_display_name: false, require_display_name: false, allow_utf8_local_part: true, require_tld: true }`. If `allow_display_name` is set to true, the validator will also match `Display Name <email-address>`. If `require_display_name` is set to true, the validator will reject strings without the format `Display Name <email-address>`. If `allow_utf8_local_part` is set to false, the validator will not allow any non-English UTF8 character in email address' local part. If `require_tld` is set to false, e-mail addresses without having TLD in their domain will also be matched.
**isEmail(str [, options])** | check if the string is an email.<br/><br/>`options` is an object which defaults to `{ allow_display_name: false, require_display_name: false, allow_utf8_local_part: true, require_tld: true, allow_ip_domain: false }`. If `allow_display_name` is set to true, the validator will also match `Display Name <email-address>`. If `require_display_name` is set to true, the validator will reject strings without the format `Display Name <email-address>`. If `allow_utf8_local_part` is set to false, the validator will not allow any non-English UTF8 character in email address' local part. If `require_tld` is set to false, e-mail addresses without having TLD in their domain will also be matched. If `allow_ip_domain` is set to true, the validator will allow IP addresses in the host part.
**isEmpty(str)** | check if the string has a length of zero.
**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 }`.
**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` 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', 'hu-HU', 'it-IT', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`.
Expand Down Expand Up @@ -103,10 +103,10 @@ Validator | Description
**isMACAddress(str)** | check if the string is a MAC address.<br/><br/>`options` is an object which defaults to `{noColons: false}`, meaning that it will only validate MAC addresses containing 5 colons.
**isMD5(str)** | check if the string is a MD5 hash.
**isMimeType(str)** | check if the string matches to a valid [MIME type](https://en.wikipedia.org/wiki/Media_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 `['ar-AE', 'ar-DZ', 'ar-EG', 'ar-IQ', ar-JO', 'ar-KW', 'ar-SA', 'ar-SY', 'ar-TN', 'be-BY', 'bg-BG', 'cs-CZ', 'de-DE', 'da-DK', 'el-GR', 'en-AU', 'en-CA', 'en-GB', 'en-HK', 'en-IN', 'en-KE', 'en-NG', 'en-NZ', 'en-RW', 'en-SG', 'en-UG', 'en-US', 'en-TZ', 'en-ZA', 'en-ZM', 'en-PK', 'es-ES', 'et-EE', 'fa-IR', 'fi-FI', 'fr-FR', 'he-IL', 'hu-HU', 'it-IT', 'ja-JP', 'kk-KZ', 'ko-KR', 'lt-LT', 'ms-MY', 'nb-NO', 'nn-NO', 'pl-PL', 'pt-PT', 'pt-BR', 'ro-RO', 'ru-RU', 'sk-SK', 'sr-RS', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA', 'vi-VN', 'zh-CN', 'zh-HK', 'zh-TW']` OR 'any'. If 'any' 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 `+`.
**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 `['ar-AE', 'ar-DZ', 'ar-EG', 'ar-IQ', ar-JO', 'ar-KW', 'ar-SA', 'ar-SY', 'ar-TN', 'be-BY', 'bg-BG', 'bn-BD', 'cs-CZ', 'de-DE', 'da-DK', 'el-GR', 'en-AU', 'en-CA', 'en-GB', 'en-HK', 'en-IN', 'en-KE', 'en-NG', 'en-NZ', 'en-RW', 'en-SG', 'en-UG', 'en-US', 'en-TZ', 'en-ZA', 'en-ZM', 'en-PK', 'es-ES', 'et-EE', 'fa-IR', 'fi-FI', 'fr-FR', 'he-IL', 'hu-HU', 'it-IT', 'ja-JP', 'kk-KZ', 'ko-KR', 'lt-LT', 'ms-MY', 'nb-NO', 'nn-NO', 'pl-PL', 'pt-PT', 'pt-BR', 'ro-RO', 'ru-RU', 'sk-SK', 'sr-RS', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA', 'vi-VN', 'zh-CN', 'zh-HK', 'zh-TW']` OR 'any'. If 'any' 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 `+`.
**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)** | check if the string contains only numbers.
**isNumeric(str [, options])** | check if the string contains only numbers.<br/><br/>`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 `.`).
**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 `[ 'AT', 'AU', 'BE', 'BG', 'CA', 'CH', 'CZ', 'DE', 'DK', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IL', 'IN', 'IS', 'IT', 'JP', 'KE', 'LI', 'LT', 'LU', 'LV', 'MX', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'SA', 'SE', 'SI', 'TN', 'TW', 'US', 'ZA', 'ZM' ]` OR 'any'. If 'any' is used, function will check if any of the locals match. locale list is `validator.isPostalCodeLocales`.).
**isSurrogatePair(str)** | check if the string contains any surrogate pairs chars.
Expand Down
20 changes: 19 additions & 1 deletion lib/isEmail.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ var _isFQDN = require('./isFQDN');

var _isFQDN2 = _interopRequireDefault(_isFQDN);

var _isIP = require('./isIP');

var _isIP2 = _interopRequireDefault(_isIP);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var default_email_options = {
Expand Down Expand Up @@ -91,7 +95,21 @@ function isEmail(str, options) {
}

if (!(0, _isFQDN2.default)(domain, { require_tld: options.require_tld })) {
return false;
if (!options.allow_ip_domain) {
return false;
}

if (!(0, _isIP2.default)(domain)) {
if (!domain.startsWith('[') || !domain.endsWith(']')) {
return false;
}

var noBracketdomain = domain.substr(1, domain.length - 2);

if (noBracketdomain.length === 0 || !(0, _isIP2.default)(noBracketdomain)) {
return false;
}
}
}

if (user[0] === '"') {
Expand Down
3 changes: 2 additions & 1 deletion lib/isMobilePhone.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var phones = {
'ar-TN': /^(\+?216)?[2459]\d{7}$/,
'be-BY': /^(\+?375)?(24|25|29|33|44)\d{7}$/,
'bg-BG': /^(\+?359|0)?8[789]\d{7}$/,
'bn-BD': /\+?(88)?0?1[156789][0-9]{8}\b/,
'cs-CZ': /^(\+?420)? ?[1-9][0-9]{2} ?[0-9]{3} ?[0-9]{3}$/,
'da-DK': /^(\+?45)?\s?\d{2}\s?\d{2}\s?\d{2}\s?\d{2}$/,
'de-DE': /^(\+?49[ \.\-]?)?([\(]{1}[0-9]{1,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/,
Expand All @@ -40,7 +41,7 @@ var phones = {
'en-SG': /^(\+65)?[89]\d{7}$/,
'en-TZ': /^(\+?255|0)?[67]\d{8}$/,
'en-UG': /^(\+?256|0)?[7]\d{8}$/,
'en-US': /^(\+?1)?[2-9]\d{2}[2-9](?!11)\d{6}$/,
'en-US': /^(\+?1?( |-)?)?(\([2-9][0-9]{2}\)|[2-9][0-9]{2})( |-)?([2-9][0-9]{2}( |-)?[0-9]{4})$/,
'en-ZA': /^(\+?27|0)\d{9}$/,
'en-ZM': /^(\+?26)?09[567]\d{7}$/,
'es-ES': /^(\+?34)?(6\d{1}|7[1234])\d{7}$/,
Expand Down
6 changes: 5 additions & 1 deletion lib/isNumeric.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ var _assertString2 = _interopRequireDefault(_assertString);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var numeric = /^[+-]?([0-9]*[.])?[0-9]+$/;
var numericNoSymbols = /^[0-9]+$/;

function isNumeric(str) {
function isNumeric(str, options) {
(0, _assertString2.default)(str);
if (options && options.no_symbols) {
return numericNoSymbols.test(str);
}
return numeric.test(str);
}
module.exports = exports['default'];
17 changes: 16 additions & 1 deletion src/lib/isEmail.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import assertString from './util/assertString';
import merge from './util/merge';
import isByteLength from './isByteLength';
import isFQDN from './isFQDN';
import isIP from './isIP';

const default_email_options = {
allow_display_name: false,
Expand Down Expand Up @@ -73,7 +74,21 @@ export default function isEmail(str, options) {
}

if (!isFQDN(domain, { require_tld: options.require_tld })) {
return false;
if (!options.allow_ip_domain) {
return false;
}

if (!isIP(domain)) {
if (!domain.startsWith('[') || !domain.endsWith(']')) {
return false;
}

let noBracketdomain = domain.substr(1, domain.length - 2);

if (noBracketdomain.length === 0 || !isIP(noBracketdomain)) {
return false;
}
}
}

if (user[0] === '"') {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/isMobilePhone.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const phones = {
'ar-TN': /^(\+?216)?[2459]\d{7}$/,
'be-BY': /^(\+?375)?(24|25|29|33|44)\d{7}$/,
'bg-BG': /^(\+?359|0)?8[789]\d{7}$/,
'bn-BD': /\+?(88)?0?1[156789][0-9]{8}\b/,
'cs-CZ': /^(\+?420)? ?[1-9][0-9]{2} ?[0-9]{3} ?[0-9]{3}$/,
'da-DK': /^(\+?45)?\s?\d{2}\s?\d{2}\s?\d{2}\s?\d{2}$/,
'de-DE': /^(\+?49[ \.\-]?)?([\(]{1}[0-9]{1,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/,
Expand All @@ -29,7 +30,7 @@ const phones = {
'en-SG': /^(\+65)?[89]\d{7}$/,
'en-TZ': /^(\+?255|0)?[67]\d{8}$/,
'en-UG': /^(\+?256|0)?[7]\d{8}$/,
'en-US': /^(\+?1)?[2-9]\d{2}[2-9](?!11)\d{6}$/,
'en-US': /^(\+?1?( |-)?)?(\([2-9][0-9]{2}\)|[2-9][0-9]{2})( |-)?([2-9][0-9]{2}( |-)?[0-9]{4})$/,
'en-ZA': /^(\+?27|0)\d{9}$/,
'en-ZM': /^(\+?26)?09[567]\d{7}$/,
'es-ES': /^(\+?34)?(6\d{1}|7[1234])\d{7}$/,
Expand Down
6 changes: 5 additions & 1 deletion src/lib/isNumeric.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import assertString from './util/assertString';

const numeric = /^[+-]?([0-9]*[.])?[0-9]+$/;
const numericNoSymbols = /^[0-9]+$/;

export default function isNumeric(str) {
export default function isNumeric(str, options) {
assertString(str);
if (options && options.no_symbols) {
return numericNoSymbols.test(str);
}
return numeric.test(str);
}
111 changes: 100 additions & 11 deletions test/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ describe('Validators', () => {
'[email protected]',
'[email protected]',
'test123+invalid! [email protected]',
'[email protected]',
'[email protected]',
],
});
});
Expand Down Expand Up @@ -228,6 +230,52 @@ describe('Validators', () => {
});
});

it('should validate email addresses with allowed IPs', () => {
test({
validator: 'isEmail',
args: [{ allow_ip_domain: true }],
valid: [
'email@[123.123.123.123]',
'[email protected]',
],
invalid: [
'invalidemail@',
'invalid.com',
'@invalid.com',
'[email protected].',
'somename@gmail.com',
'[email protected].',
'[email protected]',
'gmailgmailgmailgmailgmail@gmail.com',
`${repeat('a', 64)}@${repeat('a', 251)}.com`,
`${repeat('a', 65)}@${repeat('a', 250)}.com`,
`${repeat('a', 64)}@${repeat('a', 64)}.com`,
`${repeat('a', 31)}@gmail.com`,
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected]',
'[email protected]',
'[email protected]',
'[email protected]',
'[email protected]',
'[email protected]',
'test123+invalid! [email protected]',
'[email protected]',
'[email protected]',
],
});
});

it('should validate URLs', () => {
test({
Expand Down Expand Up @@ -1530,8 +1578,34 @@ describe('Validators', () => {
'-0',
'+123',
'123.123',
'+000000',
],
invalid: [
' ',
'',
'.',
],
});
});

it('should validate numeric strings without symbols', () => {
test({
validator: 'isNumeric',
args: [{
no_symbols: true,
}],
valid: [
'123',
'00123',
'0',
],
invalid: [
'-0',
'+000000',
'',
'+123',
'123.123',
'-00123',
' ',
'.',
],
Expand Down Expand Up @@ -3289,6 +3363,22 @@ describe('Validators', () => {
'12125559999',
],
},
{
locale: 'bn-BD',
valid: [
'+8801794626846',
'01199098893',
'8801671163269',
'01717112029',
],
invalid: [
'',
'0174626346',
'017943563469',
'18001234567',
'01494676946',
],
},
{
locale: 'cs-CZ',
valid: [
Expand Down Expand Up @@ -3597,34 +3687,33 @@ describe('Validators', () => {
'19876543210',
'8005552222',
'+15673628910',
'+1(567)3628910',
'+1(567)362-8910',
'+1(567) 362-8910',
'1(567)362-8910',
'1(567)362 8910',
'223-456-7890',
],
invalid: [
'564785',
'0123456789',
'1437439210',
'8009112340',
'+10345672645',
'11435213543',
'2436119753',
'16532116190',
'1(067)362-8910',
'1(167)362-8910',
'+2(267)362-8910',
],
},
{
locale: 'en-CA',
valid: [
'19876543210',
'8005552222',
'+15673628910',
],
valid: ['19876543210', '8005552222', '+15673628910'],
invalid: [
'564785',
'0123456789',
'1437439210',
'8009112340',
'+10345672645',
'11435213543',
'2436119753',
'16532116190',
],
},
{
Expand Down
Loading

0 comments on commit 340df7b

Please sign in to comment.