diff --git a/src/index.js b/src/index.js index 87be711..047cbf6 100644 --- a/src/index.js +++ b/src/index.js @@ -1,250 +1,507 @@ -import toDate from './lib/toDate'; -import toFloat from './lib/toFloat'; -import toInt from './lib/toInt'; -import toBoolean from './lib/toBoolean'; -import equals from './lib/equals'; -import contains from './lib/contains'; -import matches from './lib/matches'; - -import isEmail from './lib/isEmail'; -import isURL from './lib/isURL'; -import isMACAddress from './lib/isMACAddress'; -import isIP from './lib/isIP'; -import isIPRange from './lib/isIPRange'; -import isFQDN from './lib/isFQDN'; -import isDate from './lib/isDate'; -import isTime from './lib/isTime'; - -import isBoolean from './lib/isBoolean'; -import isLocale from './lib/isLocale'; - -import isAbaRouting from './lib/isAbaRouting'; -import isAlpha, { locales as isAlphaLocales } from './lib/isAlpha'; -import isAlphanumeric, { locales as isAlphanumericLocales } from './lib/isAlphanumeric'; -import isNumeric from './lib/isNumeric'; -import isPassportNumber, { locales as passportNumberLocales } from './lib/isPassportNumber'; -import isPort from './lib/isPort'; -import isLowercase from './lib/isLowercase'; -import isUppercase from './lib/isUppercase'; - -import isIMEI from './lib/isIMEI'; - -import isAscii from './lib/isAscii'; -import isFullWidth from './lib/isFullWidth'; -import isHalfWidth from './lib/isHalfWidth'; -import isVariableWidth from './lib/isVariableWidth'; -import isMultibyte from './lib/isMultibyte'; -import isSemVer from './lib/isSemVer'; -import isSurrogatePair from './lib/isSurrogatePair'; - -import isInt from './lib/isInt'; -import isFloat, { locales as isFloatLocales } from './lib/isFloat'; -import isDecimal from './lib/isDecimal'; -import isHexadecimal from './lib/isHexadecimal'; -import isOctal from './lib/isOctal'; -import isDivisibleBy from './lib/isDivisibleBy'; - -import isHexColor from './lib/isHexColor'; -import isRgbColor from './lib/isRgbColor'; -import isHSL from './lib/isHSL'; - -import isISRC from './lib/isISRC'; - -import isIBAN, { locales as ibanLocales } from './lib/isIBAN'; -import isBIC from './lib/isBIC'; - -import isMD5 from './lib/isMD5'; -import isHash from './lib/isHash'; -import isJWT from './lib/isJWT'; - -import isJSON from './lib/isJSON'; -import isEmpty from './lib/isEmpty'; - -import isLength from './lib/isLength'; -import isByteLength from './lib/isByteLength'; - -import isULID from './lib/isULID'; -import isUUID from './lib/isUUID'; -import isMongoId from './lib/isMongoId'; - -import isAfter from './lib/isAfter'; -import isBefore from './lib/isBefore'; - -import isIn from './lib/isIn'; - -import isLuhnNumber from './lib/isLuhnNumber'; -import isCreditCard from './lib/isCreditCard'; -import isIdentityCard from './lib/isIdentityCard'; - -import isEAN from './lib/isEAN'; -import isISIN from './lib/isISIN'; -import isISBN from './lib/isISBN'; -import isISSN from './lib/isISSN'; -import isTaxID from './lib/isTaxID'; - -import isMobilePhone, { locales as isMobilePhoneLocales } from './lib/isMobilePhone'; - -import isEthereumAddress from './lib/isEthereumAddress'; - -import isCurrency from './lib/isCurrency'; - -import isBtcAddress from './lib/isBtcAddress'; - -import { isISO6346, isFreightContainerID } from './lib/isISO6346'; -import isISO6391 from './lib/isISO6391'; -import isISO8601 from './lib/isISO8601'; -import isRFC3339 from './lib/isRFC3339'; -import isISO15924 from './lib/isISO15924'; -import isISO31661Alpha2 from './lib/isISO31661Alpha2'; -import isISO31661Alpha3 from './lib/isISO31661Alpha3'; -import isISO31661Numeric from './lib/isISO31661Numeric'; -import isISO4217 from './lib/isISO4217'; - -import isBase32 from './lib/isBase32'; -import isBase58 from './lib/isBase58'; -import isBase64 from './lib/isBase64'; -import isDataURI from './lib/isDataURI'; -import isMagnetURI from './lib/isMagnetURI'; -import isMailtoURI from './lib/isMailtoURI'; - -import isMimeType from './lib/isMimeType'; - -import isLatLong from './lib/isLatLong'; -import isPostalCode, { locales as isPostalCodeLocales } from './lib/isPostalCode'; - -import ltrim from './lib/ltrim'; -import rtrim from './lib/rtrim'; -import trim from './lib/trim'; -import escape from './lib/escape'; -import unescape from './lib/unescape'; -import stripLow from './lib/stripLow'; -import whitelist from './lib/whitelist'; -import blacklist from './lib/blacklist'; -import isWhitelisted from './lib/isWhitelisted'; - -import normalizeEmail from './lib/normalizeEmail'; - -import isSlug from './lib/isSlug'; -import isLicensePlate from './lib/isLicensePlate'; -import isStrongPassword from './lib/isStrongPassword'; - -import isVAT from './lib/isVAT'; - -const version = '13.15.15'; - -const validator = { - version, - toDate, - toFloat, - toInt, - toBoolean, - equals, - contains, - matches, - isEmail, - isURL, - isMACAddress, - isIP, - isIPRange, - isFQDN, - isBoolean, - isIBAN, - isBIC, - isAbaRouting, - isAlpha, - isAlphaLocales, - isAlphanumeric, - isAlphanumericLocales, - isNumeric, - isPassportNumber, - passportNumberLocales, - isPort, - isLowercase, - isUppercase, - isAscii, - isFullWidth, - isHalfWidth, - isVariableWidth, - isMultibyte, - isSemVer, - isSurrogatePair, - isInt, - isIMEI, - isFloat, - isFloatLocales, - isDecimal, - isHexadecimal, - isOctal, - isDivisibleBy, - isHexColor, - isRgbColor, - isHSL, - isISRC, - isMD5, - isHash, - isJWT, - isJSON, - isEmpty, - isLength, - isLocale, - isByteLength, - isULID, - isUUID, - isMongoId, - isAfter, - isBefore, - isIn, - isLuhnNumber, - isCreditCard, - isIdentityCard, - isEAN, - isISIN, - isISBN, - isISSN, - isMobilePhone, - isMobilePhoneLocales, - isPostalCode, - isPostalCodeLocales, - isEthereumAddress, - isCurrency, - isBtcAddress, - isISO6346, - isFreightContainerID, - isISO6391, - isISO8601, - isISO15924, - isRFC3339, - isISO31661Alpha2, - isISO31661Alpha3, - isISO31661Numeric, - isISO4217, - isBase32, - isBase58, - isBase64, - isDataURI, - isMagnetURI, - isMailtoURI, - isMimeType, - isLatLong, - ltrim, - rtrim, - trim, - escape, - unescape, - stripLow, - whitelist, - blacklist, - isWhitelisted, - normalizeEmail, - toString, - isSlug, - isStrongPassword, - isTaxID, - isDate, - isTime, - isLicensePlate, - isVAT, - ibanLocales, -}; - -export default validator; +import toDate from './lib/toDate'; + +import toFloat from './lib/toFloat'; + +import toInt from './lib/toInt'; + +import toBoolean from './lib/toBoolean'; + +import equals from './lib/equals'; + +import contains from './lib/contains'; + +import matches from './lib/matches'; + + + +import isEmail from './lib/isEmail'; + +import isURL from './lib/isURL'; + +import isMACAddress from './lib/isMACAddress'; + +import isIP from './lib/isIP'; + +import isIPRange from './lib/isIPRange'; + +import isFQDN from './lib/isFQDN'; + +import isDate from './lib/isDate'; + +import isTime from './lib/isTime'; + + + +import isBoolean from './lib/isBoolean'; + +import isLocale from './lib/isLocale'; + + + +import isAbaRouting from './lib/isAbaRouting'; + +import isAlpha, { locales as isAlphaLocales } from './lib/isAlpha'; + +import isAlphanumeric, { locales as isAlphanumericLocales } from './lib/isAlphanumeric'; + +import isNumeric from './lib/isNumeric'; + +import isThousandSeparated from './lib/isThousandSeparated'; + +import isPassportNumber, { locales as passportNumberLocales } from './lib/isPassportNumber'; + +import isPort from './lib/isPort'; + +import isLowercase from './lib/isLowercase'; + +import isUppercase from './lib/isUppercase'; + + + +import isIMEI from './lib/isIMEI'; + + + +import isAscii from './lib/isAscii'; + +import isFullWidth from './lib/isFullWidth'; + +import isHalfWidth from './lib/isHalfWidth'; + +import isVariableWidth from './lib/isVariableWidth'; + +import isMultibyte from './lib/isMultibyte'; + +import isSemVer from './lib/isSemVer'; + +import isSurrogatePair from './lib/isSurrogatePair'; + + + +import isInt from './lib/isInt'; + +import isFloat, { locales as isFloatLocales } from './lib/isFloat'; + +import isDecimal from './lib/isDecimal'; + +import isHexadecimal from './lib/isHexadecimal'; + +import isOctal from './lib/isOctal'; + +import isDivisibleBy from './lib/isDivisibleBy'; + + + +import isHexColor from './lib/isHexColor'; + +import isRgbColor from './lib/isRgbColor'; + +import isHSL from './lib/isHSL'; + +import isColor from './lib/isColor'; + + + +import isISRC from './lib/isISRC'; + + + +import isIBAN, { locales as ibanLocales } from './lib/isIBAN'; + +import isBIC from './lib/isBIC'; + + + +import isMD5 from './lib/isMD5'; + +import isHash from './lib/isHash'; + +import isJWT from './lib/isJWT'; + + + +import isJSON from './lib/isJSON'; + +import isEmpty from './lib/isEmpty'; + + + +import isLength from './lib/isLength'; + +import isByteLength from './lib/isByteLength'; + + + +import isULID from './lib/isULID'; + +import isUUID from './lib/isUUID'; + +import isMongoId from './lib/isMongoId'; + + + +import isAfter from './lib/isAfter'; + +import isBefore from './lib/isBefore'; + + + +import isIn from './lib/isIn'; + + + +import isLuhnNumber from './lib/isLuhnNumber'; + +import isCreditCard from './lib/isCreditCard'; + +import isIdentityCard from './lib/isIdentityCard'; + + + +import isEAN from './lib/isEAN'; + +import isISIN from './lib/isISIN'; + +import isISBN from './lib/isISBN'; + +import isISSN from './lib/isISSN'; + +import isTaxID from './lib/isTaxID'; + + + +import isMobilePhone, { locales as isMobilePhoneLocales } from './lib/isMobilePhone'; + + + +import isEthereumAddress from './lib/isEthereumAddress'; + + + +import isCurrency from './lib/isCurrency'; + + + +import isBtcAddress from './lib/isBtcAddress'; + + + +import { isISO6346, isFreightContainerID } from './lib/isISO6346'; + +import isISO6391 from './lib/isISO6391'; + +import isISO8601 from './lib/isISO8601'; + +import isRFC3339 from './lib/isRFC3339'; + +import isISO15924 from './lib/isISO15924'; + +import isISO31661Alpha2 from './lib/isISO31661Alpha2'; + +import isISO31661Alpha3 from './lib/isISO31661Alpha3'; + +import isISO31661Numeric from './lib/isISO31661Numeric'; + +import isISO4217 from './lib/isISO4217'; + + + +import isBase32 from './lib/isBase32'; + +import isBase58 from './lib/isBase58'; + +import isBase64 from './lib/isBase64'; + +import isDataURI from './lib/isDataURI'; + +import isMagnetURI from './lib/isMagnetURI'; + +import isMailtoURI from './lib/isMailtoURI'; + + + +import isMimeType from './lib/isMimeType'; + + + +import isLatLong from './lib/isLatLong'; + +import isPostalCode, { locales as isPostalCodeLocales } from './lib/isPostalCode'; + + + +import ltrim from './lib/ltrim'; + +import rtrim from './lib/rtrim'; + +import trim from './lib/trim'; + +import escape from './lib/escape'; + +import unescape from './lib/unescape'; + +import stripLow from './lib/stripLow'; + +import whitelist from './lib/whitelist'; + +import blacklist from './lib/blacklist'; + +import isWhitelisted from './lib/isWhitelisted'; + + + +import normalizeEmail from './lib/normalizeEmail'; + + + +import isSlug from './lib/isSlug'; + +import isLicensePlate from './lib/isLicensePlate'; + +import isStrongPassword from './lib/isStrongPassword'; + + + +import isVAT from './lib/isVAT'; + + + +const version = '13.15.15'; + + + +const validator = { + +version, + +toDate, + +toFloat, + +toInt, + +toBoolean, + +equals, + +contains, + +matches, + +isEmail, + +isURL, + +isMACAddress, + +isIP, + +isIPRange, + +isFQDN, + +isBoolean, + +isIBAN, + +isBIC, + +isAbaRouting, + +isAlpha, + +isAlphaLocales, + +isAlphanumeric, + +isAlphanumericLocales, + +isNumeric, + +isThousandSeparated, + +isPassportNumber, + +passportNumberLocales, + +isPort, + +isLowercase, + +isUppercase, + +isAscii, + +isFullWidth, + +isHalfWidth, + +isVariableWidth, + +isMultibyte, + +isSemVer, + +isSurrogatePair, + +isInt, + +isIMEI, + +isFloat, + +isFloatLocales, + +isDecimal, + +isHexadecimal, + +isOctal, + +isDivisibleBy, + +isHexColor, + +isRgbColor, + +isHSL, + +isColor, + +isISRC, + +isMD5, + +isHash, + +isJWT, + +isJSON, + +isEmpty, + +isLength, + +isLocale, + +isByteLength, + +isULID, + +isUUID, + +isMongoId, + +isAfter, + +isBefore, + +isIn, + +isLuhnNumber, + +isCreditCard, + +isIdentityCard, + +isEAN, + +isISIN, + +isISBN, + +isISSN, + +isMobilePhone, + +isMobilePhoneLocales, + +isPostalCode, + +isPostalCodeLocales, + +isEthereumAddress, + +isCurrency, + +isBtcAddress, + +isISO6346, + +isFreightContainerID, + +isISO6391, + +isISO8601, + +isISO15924, + +isRFC3339, + +isISO31661Alpha2, + +isISO31661Alpha3, + +isISO31661Numeric, + +isISO4217, + +isBase32, + +isBase58, + +isBase64, + +isDataURI, + +isMagnetURI, + +isMailtoURI, + +isMimeType, + +isLatLong, + +ltrim, + +rtrim, + +trim, + +escape, + +unescape, + +stripLow, + +whitelist, + +blacklist, + +isWhitelisted, + +normalizeEmail, + +toString, + +isSlug, + +isStrongPassword, + +isTaxID, + +isDate, + +isTime, + +isLicensePlate, + +isVAT, + +ibanLocales, + +}; + + + +export default validator; \ No newline at end of file diff --git a/src/lib/isColor.js b/src/lib/isColor.js new file mode 100644 index 0000000..438a5c8 --- /dev/null +++ b/src/lib/isColor.js @@ -0,0 +1,167 @@ +import assertString from './util/assertString'; + +import merge from './util/merge'; + + + +// Hex color patterns + +const hexColor = /^#?([0-9A-F]{3}|[0-9A-F]{6})$/i; + +const hexColorWithAlpha = /^#?([0-9A-F]{4}|[0-9A-F]{8})$/i; + + + +// RGB/RGBA patterns (both number and percentage formats) + +const rgbColor = /^rgb\(\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*\)$/i; + +const rgbaColor = /^rgba\(\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*,\s*(0?\.\d+|1(\.0+)?|0(\.0+)?|1)\s*\)$/i; + +const rgbColorPercent = /^rgb\(\s*([0-9]%|[1-9][0-9]%|100%)\s*,\s*([0-9]%|[1-9][0-9]%|100%)\s*,\s*([0-9]%|[1-9][0-9]%|100%)\s*\)$/i; + +const rgbaColorPercent = /^rgba\(\s*([0-9]%|[1-9][0-9]%|100%)\s*,\s*([0-9]%|[1-9][0-9]%|100%)\s*,\s*([0-9]%|[1-9][0-9]%|100%)\s*,\s*(0?\.\d+|1(\.0+)?|0(\.0+)?|1)\s*\)$/i; + + + +// Modern space-separated RGB/RGBA format (CSS Color Module Level 4) + +const rgbColorModern = /^rgb\(\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s+([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s+([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*(\/\s*(0?\.\d+|1(\.0+)?|0(\.0+)?|1|\d+%))?\s*\)$/i; + +const rgbColorPercentModern = /^rgb\(\s*([0-9]%|[1-9][0-9]%|100%)\s+([0-9]%|[1-9][0-9]%|100%)\s+([0-9]%|[1-9][0-9]%|100%)\s*(\/\s*(0?\.\d+|1(\.0+)?|0(\.0+)?|1|\d+%))?\s*\)$/i; + + + +// HSL/HSLA patterns + +const hslComma = /^hsl\(\s*((\+|\-)?([0-9]+(\.[0-9]+)?(e(\+|\-)?[0-9]+)?|\.[0-9]+(e(\+|\-)?[0-9]+)?))(deg|grad|rad|turn)?\s*,\s*((\+|\-)?([0-9]+(\.[0-9]+)?(e(\+|\-)?[0-9]+)?|\.[0-9]+(e(\+|\-)?[0-9]+)?)%)\s*,\s*((\+|\-)?([0-9]+(\.[0-9]+)?(e(\+|\-)?[0-9]+)?|\.[0-9]+(e(\+|\-)?[0-9]+)?)%)\s*\)$/i; + +const hslaComma = /^hsla\(\s*((\+|\-)?([0-9]+(\.[0-9]+)?(e(\+|\-)?[0-9]+)?|\.[0-9]+(e(\+|\-)?[0-9]+)?))(deg|grad|rad|turn)?\s*,\s*((\+|\-)?([0-9]+(\.[0-9]+)?(e(\+|\-)?[0-9]+)?|\.[0-9]+(e(\+|\-)?[0-9]+)?)%)\s*,\s*((\+|\-)?([0-9]+(\.[0-9]+)?(e(\+|\-)?[0-9]+)?|\.[0-9]+(e(\+|\-)?[0-9]+)?)%)\s*,\s*((\+|\-)?([0-9]+(\.[0-9]+)?(e(\+|\-)?[0-9]+)?|\.[0-9]+(e(\+|\-)?[0-9]+)?)%?)\s*\)$/i; + +const hslSpace = /^hsl\(\s*((\+|\-)?([0-9]+(\.[0-9]+)?(e(\+|\-)?[0-9]+)?|\.[0-9]+(e(\+|\-)?[0-9]+)?))(deg|grad|rad|turn)?\s+((\+|\-)?([0-9]+(\.[0-9]+)?(e(\+|\-)?[0-9]+)?|\.[0-9]+(e(\+|\-)?[0-9]+)?)%)\s+((\+|\-)?([0-9]+(\.[0-9]+)?(e(\+|\-)?[0-9]+)?|\.[0-9]+(e(\+|\-)?[0-9]+)?)%)\s*(\/\s*((\+|\-)?([0-9]+(\.[0-9]+)?(e(\+|\-)?[0-9]+)?|\.[0-9]+(e(\+|\-)?[0-9]+)?)%?)\s*)?\s*\)$/i; + + + +const default_color_options = { + +format: null, // null means all formats, or can be 'hex', 'hexa', 'rgb', 'rgba', 'hsl', 'hsla' + +}; + + + +function testHex(str) { + +return hexColor.test(str); + +} + + + +function testHexa(str) { + +return hexColorWithAlpha.test(str); + +} + + + +function testRgb(str) { + +return rgbColor.test(str) || rgbColorPercent.test(str) || rgbColorModern.test(str) || rgbColorPercentModern.test(str); + +} + + + +function testRgba(str) { + +return rgbaColor.test(str) || rgbaColorPercent.test(str) || rgbColorModern.test(str) || rgbColorPercentModern.test(str); + +} + + + +function testHsl(str) { + +return hslComma.test(str) || hslSpace.test(str); + +} + + + +function testHsla(str) { + +return hslaComma.test(str) || hslSpace.test(str); + +} + + + +export default function isColor(str, options) { + +assertString(str); + +options = merge(options, default_color_options); + + + +const { format } = options; + + + +// If a specific format is requested, validate against that format only + +if (format) { + +switch (format.toLowerCase()) { + +case 'hex': + +return testHex(str); + +case 'hexa': + +return testHexa(str); + +case 'rgb': + +return testRgb(str); + +case 'rgba': + +return testRgba(str); + +case 'hsl': + +return testHsl(str); + +case 'hsla': + +return testHsla(str); + +default: + +throw new Error(`Invalid color format '${format}'`); + +} + +} + + + +// If no format specified, validate against all formats + +return testHex(str) || + +testHexa(str) || + +testRgb(str) || + +testRgba(str) || + +testHsl(str) || + +testHsla(str); + +} \ No newline at end of file diff --git a/src/lib/isDate.js b/src/lib/isDate.js index 3a1e4af..fdc0405 100644 --- a/src/lib/isDate.js +++ b/src/lib/isDate.js @@ -28,6 +28,16 @@ export default function isDate(input, options) { options = merge(options, default_date_options); } if (typeof input === 'string' && isValidFormat(options.format)) { + // Reject dates that start with a hyphen or delimiter + if (/^[-\/]/.test(input)) { + return false; + } + + // Reject dates that end with a delimiter + if (/[-\/]$/.test(input)) { + return false; + } + if (options.strictMode && input.length !== options.format.length) return false; const formatDelimiter = options.delimiters .find(delimiter => options.format.indexOf(delimiter) !== -1); @@ -45,16 +55,16 @@ export default function isDate(input, options) { return false; } + // Check if any part contains a hyphen (invalid for date components) + if (dateWord.includes('-')) { + return false; + } + dateObj[formatWord.charAt(0)] = dateWord; } let fullYear = dateObj.y; - // Check if the year starts with a hyphen - if (fullYear.startsWith('-')) { - return false; // Hyphen before year is not allowed - } - if (dateObj.y.length === 2) { const parsedYear = parseInt(dateObj.y, 10); @@ -91,4 +101,4 @@ export default function isDate(input, options) { } return false; -} +} \ No newline at end of file diff --git a/src/lib/isMobilePhone.js b/src/lib/isMobilePhone.js index b00391e..f6d3656 100644 --- a/src/lib/isMobilePhone.js +++ b/src/lib/isMobilePhone.js @@ -1,213 +1,425 @@ -import assertString from './util/assertString'; - -/* eslint-disable max-len */ -const phones = { - 'am-AM': /^(\+?374|0)(33|4[134]|55|77|88|9[13-689])\d{6}$/, - 'ar-AE': /^((\+?971)|0)?5[024568]\d{7}$/, - 'ar-BH': /^(\+?973)?(3|6)\d{7}$/, - 'ar-DZ': /^(\+?213|0)(5|6|7)\d{8}$/, - 'ar-LB': /^(\+?961)?((3|81)\d{6}|7\d{7})$/, - 'ar-EG': /^((\+?20)|0)?1[0125]\d{8}$/, - 'ar-IQ': /^(\+?964|0)?7[0-9]\d{8}$/, - 'ar-JO': /^(\+?962|0)?7[789]\d{7}$/, - 'ar-KW': /^(\+?965)([569]\d{7}|41\d{6})$/, - 'ar-LY': /^((\+?218)|0)?(9[1-6]\d{7}|[1-8]\d{7,9})$/, - 'ar-MA': /^(?:(?:\+|00)212|0)[5-7]\d{8}$/, - 'ar-OM': /^((\+|00)968)?([79][1-9])\d{6}$/, - 'ar-PS': /^(\+?970|0)5[6|9](\d{7})$/, - 'ar-SA': /^(!?(\+?966)|0)?5\d{8}$/, - 'ar-SD': /^((\+?249)|0)?(9[012369]|1[012])\d{7}$/, - 'ar-SY': /^(!?(\+?963)|0)?9\d{8}$/, - 'ar-TN': /^(\+?216)?[2459]\d{7}$/, - 'az-AZ': /^(\+994|0)(10|5[015]|7[07]|99)\d{7}$/, - 'ar-QA': /^(\+?974|0)?([3567]\d{7})$/, - 'bs-BA': /^((((\+|00)3876)|06))((([0-3]|[5-6])\d{6})|(4\d{7}))$/, - 'be-BY': /^(\+?375)?(24|25|29|33|44)\d{7}$/, - 'bg-BG': /^(\+?359|0)?8[789]\d{7}$/, - 'bn-BD': /^(\+?880|0)1[13456789][0-9]{8}$/, - 'ca-AD': /^(\+376)?[346]\d{5}$/, - '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|0)1)(5[0-25-9]\d|6([23]|0\d?)|7([0-57-9]|6\d))\d{7,9}$/, - 'de-AT': /^(\+43|0)\d{1,4}\d{3,12}$/, - 'de-CH': /^(\+41|0)([1-9])\d{1,9}$/, - 'de-LU': /^(\+352)?((6\d1)\d{6})$/, - 'dv-MV': /^(\+?960)?(7[2-9]|9[1-9])\d{5}$/, - 'el-GR': /^(\+?30|0)?6(8[5-9]|9(?![26])[0-9])\d{7}$/, - 'el-CY': /^(\+?357?)?(9(9|7|6|5|4)\d{6})$/, - 'en-AI': /^(\+?1|0)264(?:2(35|92)|4(?:6[1-2]|76|97)|5(?:3[6-9]|8[1-4])|7(?:2(4|9)|72))\d{4}$/, - 'en-AU': /^(\+?61|0)4\d{8}$/, - 'en-AG': /^(?:\+1|1)268(?:464|7(?:1[3-9]|[28]\d|3[0246]|64|7[0-689]))\d{4}$/, - 'en-BM': /^(\+?1)?441(((3|7)\d{6}$)|(5[0-3][0-9]\d{4}$)|(59\d{5}$))/, - 'en-BS': /^(\+?1[-\s]?|0)?\(?242\)?[-\s]?\d{3}[-\s]?\d{4}$/, - 'en-GB': /^(\+?44|0)7[1-9]\d{8}$/, - 'en-GG': /^(\+?44|0)1481\d{6}$/, - 'en-GH': /^(\+233|0)(20|50|24|54|27|57|26|56|23|53|28|55|59)\d{7}$/, - 'en-GY': /^(\+592|0)6\d{6}$/, - 'en-HK': /^(\+?852[-\s]?)?[456789]\d{3}[-\s]?\d{4}$/, - 'en-MO': /^(\+?853[-\s]?)?[6]\d{3}[-\s]?\d{4}$/, - 'en-IE': /^(\+?353|0)8[356789]\d{7}$/, - 'en-IN': /^(\+?91|0)?[6789]\d{9}$/, - 'en-JM': /^(\+?876)?\d{7}$/, - 'en-KE': /^(\+?254|0)(7|1)\d{8}$/, - 'fr-CF': /^(\+?236| ?)(70|75|77|72|21|22)\d{6}$/, - 'en-SS': /^(\+?211|0)(9[1257])\d{7}$/, - 'en-KI': /^((\+686|686)?)?( )?((6|7)(2|3|8)[0-9]{6})$/, - 'en-KN': /^(?:\+1|1)869(?:46\d|48[89]|55[6-8]|66\d|76[02-7])\d{4}$/, - 'en-LS': /^(\+?266)(22|28|57|58|59|27|52)\d{6}$/, - 'en-MT': /^(\+?356|0)?(99|79|77|21|27|22|25)[0-9]{6}$/, - 'en-MU': /^(\+?230|0)?\d{8}$/, - 'en-MW': /^(\+?265|0)(((77|88|31|99|98|21)\d{7})|(((111)|1)\d{6})|(32000\d{4}))$/, - 'en-NA': /^(\+?264|0)(6|8)\d{7}$/, - 'en-NG': /^(\+?234|0)?[789]\d{9}$/, - 'en-NZ': /^(\+?64|0)[28]\d{7,9}$/, - 'en-PG': /^(\+?675|0)?(7\d|8[18])\d{6}$/, - 'en-PK': /^((00|\+)?92|0)3[0-6]\d{8}$/, - 'en-PH': /^(09|\+639)\d{9}$/, - 'en-RW': /^(\+?250|0)?[7]\d{8}$/, - 'en-SG': /^(\+65)?[3689]\d{7}$/, - 'en-SL': /^(\+?232|0)\d{8}$/, - 'en-TZ': /^(\+?255|0)?[67]\d{8}$/, - 'en-UG': /^(\+?256|0)?[7]\d{8}$/, - 'en-US': /^((\+1|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)?0[79][567]\d{7}$/, - 'en-ZW': /^(\+263)[0-9]{9}$/, - 'en-BW': /^(\+?267)?(7[1-8]{1})\d{6}$/, - 'es-AR': /^\+?549(11|[2368]\d)\d{8}$/, - 'es-BO': /^(\+?591)?(6|7)\d{7}$/, - '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-CU': /^(\+53|0053)?5\d{7}$/, - 'es-DO': /^(\+?1)?8[024]9\d{7}$/, - 'es-HN': /^(\+?504)?[9|8|3|2]\d{7}$/, - 'es-EC': /^(\+?593|0)([2-7]|9[2-9])\d{7}$/, - 'es-ES': /^(\+?34)?[6|7]\d{8}$/, - 'es-GT': /^(\+?502)?[2|6|7]\d{7}$/, - 'es-PE': /^(\+?51)?9\d{8}$/, - 'es-MX': /^(\+?52)?(1|01)?\d{10,11}$/, - 'es-NI': /^(\+?505)\d{7,8}$/, - 'es-PA': /^(\+?507)\d{7,8}$/, - 'es-PY': /^(\+?595|0)9[9876]\d{7}$/, - 'es-SV': /^(\+?503)?[67]\d{7}$/, - 'es-UY': /^(\+598|0)9[1-9][\d]{6}$/, - 'es-VE': /^(\+?58)?(2|4)\d{9}$/, - 'et-EE': /^(\+?372)?\s?(5|8[1-4])\s?([0-9]\s?){6,7}$/, - 'fa-IR': /^(\+?98[\-\s]?|0)9[0-39]\d[\-\s]?\d{3}[\-\s]?\d{4}$/, - 'fi-FI': /^(\+?358|0)\s?(4[0-6]|50)\s?(\d\s?){4,8}$/, - 'fj-FJ': /^(\+?679)?\s?\d{3}\s?\d{4}$/, - '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}$/, - 'fr-GP': /^(\+?590|0|00590)[67]\d{8}$/, - 'fr-MQ': /^(\+?596|0|00596)[67]\d{8}$/, - 'fr-PF': /^(\+?689)?8[789]\d{6}$/, - 'fr-RE': /^(\+?262|0|00262)[67]\d{8}$/, - 'fr-WF': /^(\+681)?\d{6}$/, - 'he-IL': /^(\+972|0)([23489]|5[012345689]|77)[1-9]\d{6}$/, - 'hu-HU': /^(\+?36|06)(20|30|31|50|70)\d{7}$/, - 'id-ID': /^(\+?62|0)8(1[123456789]|2[1238]|3[1238]|5[12356789]|7[78]|9[56789]|8[123456789])([\s?|\d]{5,11})$/, - 'ir-IR': /^(\+98|0)?9\d{9}$/, - 'it-IT': /^(\+?39)?\s?3\d{2} ?\d{6,7}$/, - 'it-SM': /^((\+378)|(0549)|(\+390549)|(\+3780549))?6\d{5,9}$/, - 'ja-JP': /^(\+81[ \-]?(\(0\))?|0)[6789]0[ \-]?\d{4}[ \-]?\d{4}$/, - 'ka-GE': /^(\+?995)?(79\d{7}|5\d{8})$/, - 'kk-KZ': /^(\+?7|8)?7\d{9}$/, - 'kl-GL': /^(\+?299)?\s?\d{2}\s?\d{2}\s?\d{2}$/, - 'ko-KR': /^((\+?82)[ \-]?)?0?1([0|1|6|7|8|9]{1})[ \-]?\d{3,4}[ \-]?\d{4}$/, - 'ky-KG': /^(\+996\s?)?(22[0-9]|50[0-9]|55[0-9]|70[0-9]|75[0-9]|77[0-9]|880|990|995|996|997|998)\s?\d{3}\s?\d{3}$/, - 'lt-LT': /^(\+370|8)\d{8}$/, - 'lv-LV': /^(\+?371)2\d{7}$/, - 'mg-MG': /^((\+?261|0)(2|3)\d)?\d{7}$/, - 'mn-MN': /^(\+|00|011)?976(77|81|88|91|94|95|96|99)\d{6}$/, - 'my-MM': /^(\+?959|09|9)(2[5-7]|3[1-2]|4[0-5]|6[6-9]|7[5-9]|9[6-9])[0-9]{7}$/, - 'ms-MY': /^(\+?60|0)1(([0145](-|\s)?\d{7,8})|([236-9](-|\s)?\d{7}))$/, - 'mz-MZ': /^(\+?258)?8[234567]\d{7}$/, - 'nb-NO': /^(\+?47)?[49]\d{7}$/, - 'ne-NP': /^(\+?977)?9[78]\d{8}$/, - 'nl-BE': /^(\+?32|0)4\d{8}$/, - 'nl-NL': /^(((\+|00)?31\(0\))|((\+|00)?31)|0)6{1}\d{8}$/, - 'nl-AW': /^(\+)?297(56|59|64|73|74|99)\d{5}$/, - 'nn-NO': /^(\+?47)?[49]\d{7}$/, - 'pl-PL': /^(\+?48)? ?([5-8]\d|45) ?\d{3} ?\d{2} ?\d{2}$/, - '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)?9\d{8}$/, - '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}$/, - 'sl-SI': /^(\+386\s?|0)(\d{1}\s?\d{3}\s?\d{2}\s?\d{2}|\d{2}\s?\d{3}\s?\d{3})$/, - 'sk-SK': /^(\+?421)? ?[1-9][0-9]{2} ?[0-9]{3} ?[0-9]{3}$/, - 'so-SO': /^(\+?252|0)((6[0-9])\d{7}|(7[1-9])\d{7})$/, - 'sq-AL': /^(\+355|0)6[2-9]\d{7}$/, - 'sr-RS': /^(\+3816|06)[- \d]{5,9}$/, - 'sv-SE': /^(\+?46|0)[\s\-]?7[\s\-]?[02369]([\s\-]?\d){7}$/, - 'tg-TJ': /^(\+?992)?[5][5]\d{7}$/, - 'th-TH': /^(\+66|66|0)\d{9}$/, - 'tr-TR': /^(\+?90|0)?5\d{9}$/, - 'tk-TM': /^(\+993|993|8)\d{8}$/, - 'uk-UA': /^(\+?38)?0(50|6[36-8]|7[357]|9[1-9])\d{7}$/, - 'uz-UZ': /^(\+?998)?(6[125-79]|7[1-69]|88|9\d)\d{7}$/, - 'vi-VN': /^((\+?84)|0)((3([2-9]))|(5([25689]))|(7([0|6-9]))|(8([1-9]))|(9([0-9])))([0-9]{7})$/, - 'zh-CN': /^((\+|00)86)?(1[3-9]|9[28])\d{9}$/, - 'zh-TW': /^(\+?886\-?|0)?9\d{8}$/, - 'dz-BT': /^(\+?975|0)?(17|16|77|02)\d{6}$/, - 'ar-YE': /^(((\+|00)9677|0?7)[0137]\d{7}|((\+|00)967|0)[1-7]\d{6})$/, - 'ar-EH': /^(\+?212|0)[\s\-]?(5288|5289)[\s\-]?\d{5}$/, - 'fa-AF': /^(\+93|0)?(2{1}[0-8]{1}|[3-5]{1}[0-4]{1})(\d{7})$/, - 'mk-MK': /^(\+?389|0)?((?:2[2-9]\d{6}|(?:3[1-4]|4[2-8])\d{6}|500\d{5}|5[2-9]\d{6}|7[0-9][2-9]\d{5}|8[1-9]\d{6}|800\d{5}|8009\d{4}))$/, -}; -/* eslint-enable max-len */ - -// aliases -phones['en-CA'] = phones['en-US']; -phones['fr-CA'] = phones['en-CA']; -phones['fr-BE'] = phones['nl-BE']; -phones['zh-HK'] = phones['en-HK']; -phones['zh-MO'] = phones['en-MO']; -phones['ga-IE'] = phones['en-IE']; -phones['fr-CH'] = phones['de-CH']; -phones['it-CH'] = phones['fr-CH']; - -export default function isMobilePhone(str, locale, options) { - assertString(str); - if (options && options.strictMode && !str.startsWith('+')) { - return false; - } - if (Array.isArray(locale)) { - return locale.some((key) => { - // https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md#ignoring-code-for-coverage-purposes - // istanbul ignore else - if (phones.hasOwnProperty(key)) { - const phone = phones[key]; - if (phone.test(str)) { - return true; - } - } - return false; - }); - } else if (locale in phones) { - return phones[locale].test(str); - // alias falsey locale as 'any' - } else if (!locale || locale === 'any') { - for (const key in phones) { - // istanbul ignore else - if (phones.hasOwnProperty(key)) { - const phone = phones[key]; - if (phone.test(str)) { - return true; - } - } - } - return false; - } - throw new Error(`Invalid locale '${locale}'`); -} - -export const locales = Object.keys(phones); +import assertString from './util/assertString'; + + + +/* eslint-disable max-len */ + +const phones = { + +'am-AM': /^(\+?374|0)(33|4[134]|55|77|88|9[13-689])\d{6}$/, + +'ar-AE': /^((\+?971)|0)?5[024568]\d{7}$/, + +'ar-BH': /^(\+?973)?(3|6)\d{7}$/, + +'ar-DZ': /^(\+?213|0)(5|6|7)\d{8}$/, + +'ar-LB': /^(\+?961)?((3|81)\d{6}|7\d{7})$/, + +'ar-EG': /^((\+?20)|0)?1[0125]\d{8}$/, + +'ar-IQ': /^(\+?964|0)?7[0-9]\d{8}$/, + +'ar-JO': /^(\+?962|0)?7[789]\d{7}$/, + +'ar-KW': /^(\+?965)([569]\d{7}|41\d{6})$/, + +'ar-LY': /^((\+?218)|0)?(9[1-6]\d{7}|[1-8]\d{7,9})$/, + +'ar-MA': /^(?:(?:\+|00)212|0)[5-7]\d{8}$/, + +'ar-OM': /^((\+|00)968)?([79][1-9])\d{6}$/, + +'ar-PS': /^(\+?970|0)5[6|9](\d{7})$/, + +'ar-SA': /^(!?(\+?966)|0)?5\d{8}$/, + +'ar-SD': /^((\+?249)|0)?(9[012369]|1[012])\d{7}$/, + +'ar-SY': /^(!?(\+?963)|0)?9\d{8}$/, + +'ar-TN': /^(\+?216)?[2459]\d{7}$/, + +'az-AZ': /^(\+994|0)(10|5[015]|7[07]|99)\d{7}$/, + +'ar-QA': /^(\+?974|0)?([3567]\d{7})$/, + +'bs-BA': /^((((\+|00)3876)|06))((([0-3]|[5-6])\d{6})|(4\d{7}))$/, + +'be-BY': /^(\+?375)?(24|25|29|33|44)\d{7}$/, + +'bg-BG': /^(\+?359|0)?8[789]\d{7}$/, + +'bn-BD': /^(\+?880|0)1[13456789][0-9]{8}$/, + +'ca-AD': /^(\+376)?[346]\d{5}$/, + +'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|0)1)(5[0-25-9]\d|6([23]|0\d?)|7([0-57-9]|6\d))\d{7,9}$/, + +'de-AT': /^(\+43|0)\d{1,4}\d{3,12}$/, + +'de-CH': /^(\+41|0)([1-9])\d{1,9}$/, + +'de-LU': /^(\+352)?((6\d1)\d{6})$/, + +'dv-MV': /^(\+?960)?(7[2-9]|9[1-9])\d{5}$/, + +'el-GR': /^(\+?30|0)?6(8[5-9]|9(?![26])[0-9])\d{7}$/, + +'el-CY': /^(\+?357?)?(9(9|7|6|5|4)\d{6})$/, + +'en-AI': /^(\+?1|0)264(?:2(35|92)|4(?:6[1-2]|76|97)|5(?:3[6-9]|8[1-4])|7(?:2(4|9)|72))\d{4}$/, + +'en-AU': /^(\+?61|0)4\d{8}$/, + +'en-AG': /^(?:\+1|1)268(?:464|7(?:1[3-9]|[28]\d|3[0246]|64|7[0-689]))\d{4}$/, + +'en-BM': /^(\+?1)?441(((3|7)\d{6}$)|(5[0-3][0-9]\d{4}$)|(59\d{5}$))/, + +'en-BS': /^(\+?1[-\s]?|0)?\(?242\)?[-\s]?\d{3}[-\s]?\d{4}$/, + +'en-GB': /^(\+?44|0)7[1-9]\d{8}$/, + +'en-GG': /^(\+?44|0)1481\d{6}$/, + +'en-GH': /^(\+233|0)(20|50|24|54|27|57|26|56|23|53|28|55|59)\d{7}$/, + +'en-GY': /^(\+592|0)6\d{6}$/, + +'en-HK': /^(\+?852[-\s]?)?[456789]\d{3}[-\s]?\d{4}$/, + +'en-MO': /^(\+?853[-\s]?)?[6]\d{3}[-\s]?\d{4}$/, + +'en-IE': /^(\+?353|0)8[356789]\d{7}$/, + +'en-IN': /^(\+?91|0)?[6789]\d{9}$/, + +'en-JM': /^(\+?876)?\d{7}$/, + +'en-KE': /^(\+?254|0)(7|1)\d{8}$/, + +'fr-CF': /^(\+?236| ?)(70|75|77|72|21|22)\d{6}$/, + +'en-SS': /^(\+?211|0)(9[1257])\d{7}$/, + +'en-KI': /^((\+686|686)?)?( )?((6|7)(2|3|8)[0-9]{6})$/, + +'en-KN': /^(?:\+1|1)869(?:46\d|48[89]|55[6-8]|66\d|76[02-7])\d{4}$/, + +'en-LS': /^(\+?266)(22|28|57|58|59|27|52)\d{6}$/, + +'en-MT': /^(\+?356|0)?(99|79|77|21|27|22|25)[0-9]{6}$/, + +'en-MU': /^(\+?230|0)?\d{8}$/, + +'en-MW': /^(\+?265|0)(((77|88|31|99|98|21)\d{7})|(((111)|1)\d{6})|(32000\d{4}))$/, + +'en-NA': /^(\+?264|0)(6|8)\d{7}$/, + +'en-NG': /^(\+?234|0)?[789]\d{9}$/, + +'en-NZ': /^(\+?64|0)[28]\d{7,9}$/, + +'en-PG': /^(\+?675|0)?(7\d|8[18])\d{6}$/, + +'en-PK': /^((00|\+)?92|0)3[0-6]\d{8}$/, + +'en-PH': /^(09|\+639)\d{9}$/, + +'en-RW': /^(\+?250|0)?[7]\d{8}$/, + +'en-SG': /^(\+65)?[3689]\d{7}$/, + +'en-SL': /^(\+?232|0)\d{8}$/, + +'en-TZ': /^(\+?255|0)?[67]\d{8}$/, + +'en-UG': /^(\+?256|0)?[7]\d{8}$/, + +'en-US': /^((\+1|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)?0[79][567]\d{7}$/, + +'en-ZW': /^(\+263)[0-9]{9}$/, + +'en-BW': /^(\+?267)?(7[1-8]{1})\d{6}$/, + +'es-AR': /^\+?549(11|[2368]\d)\d{8}$/, + +'es-BO': /^(\+?591)?(6|7)\d{7}$/, + +'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-CU': /^(\+53|0053)?5\d{7}$/, + +'es-DO': /^(\+?1)?8[024]9\d{7}$/, + +'es-HN': /^(\+?504)?[9|8|3|2]\d{7}$/, + +'es-EC': /^(\+?593|0)([2-7]|9[2-9])\d{7}$/, + +'es-ES': /^(\+?34)?[6|7]\d{8}$/, + +'es-GT': /^(\+?502)?[2|6|7]\d{7}$/, + +'es-PE': /^(\+?51)?9\d{8}$/, + +'es-MX': /^(\+?52)?(1|01)?\d{10,11}$/, + +'es-NI': /^(\+?505)\d{7,8}$/, + +'es-PA': /^(\+?507)\d{7,8}$/, + +'es-PY': /^(\+?595|0)9[9876]\d{7}$/, + +'es-SV': /^(\+?503)?[67]\d{7}$/, + +'es-UY': /^(\+598|0)9[1-9][\d]{6}$/, + +'es-VE': /^(\+?58)?(2|4)\d{9}$/, + +'et-EE': /^(\+?372)?\s?(5|8[1-4])\s?([0-9]\s?){6,7}$/, + +'fa-IR': /^(\+?98[\-\s]?|0)9[0-39]\d[\-\s]?\d{3}[\-\s]?\d{4}$/, + +'fi-FI': /^(\+?358|0)\s?(4[0-6]|50)\s?(\d\s?){4,8}$/, + +'fj-FJ': /^(\+?679)?\s?\d{3}\s?\d{4}$/, + +'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}$/, + +'fr-GP': /^(\+?590|0|00590)[67]\d{8}$/, + +'fr-MQ': /^(\+?596|0|00596)[67]\d{8}$/, + +'fr-PF': /^(\+?689)?8[789]\d{6}$/, + +'fr-RE': /^(\+?262|0|00262)[67]\d{8}$/, + +'fr-WF': /^(\+681)?\d{6}$/, + +'he-IL': /^(\+972|0)([23489]|5[012345689]|77)[1-9]\d{6}$/, + +'hu-HU': /^(\+?36|06)(20|30|31|50|70)\d{7}$/, + +'id-ID': /^(\+?62|0)8(1[123456789]|2[1238]|3[1238]|5[12356789]|7[78]|9[56789]|8[123456789])([\s?|\d]{5,11})$/, + +'ir-IR': /^(\+98|0)?9\d{9}$/, + +'it-IT': /^(\+?39)?\s?3\d{2} ?\d{6,7}$/, + +'it-SM': /^((\+378)|(0549)|(\+390549)|(\+3780549))?6\d{5,9}$/, + +'ja-JP': /^(\+81[ \-]?(\(0\))?|0)[6789]0[ \-]?\d{4}[ \-]?\d{4}$/, + +'ka-GE': /^(\+?995)?(79\d{7}|5\d{8})$/, + +'kk-KZ': /^(\+?7|8)?7\d{9}$/, + +'kl-GL': /^(\+?299)?\s?\d{2}\s?\d{2}\s?\d{2}$/, + +'ko-KR': /^((\+?82)[ \-]?)?0?1([0|1|6|7|8|9]{1})[ \-]?\d{3,4}[ \-]?\d{4}$/, + +'ky-KG': /^(\+996\s?)?(22[0-9]|50[0-9]|55[0-9]|70[0-9]|75[0-9]|77[0-9]|880|990|995|996|997|998)\s?\d{3}\s?\d{3}$/, + +'lt-LT': /^(\+370|8)\d{8}$/, + +'lv-LV': /^(\+?371)2\d{7}$/, + +'mg-MG': /^((\+?261|0)(2|3)\d)?\d{7}$/, + +'mn-MN': /^(\+|00|011)?976(77|81|88|91|94|95|96|99)\d{6}$/, + +'my-MM': /^(\+?959|09|9)(2[5-7]|3[1-2]|4[0-5]|6[6-9]|7[5-9]|9[6-9])[0-9]{7}$/, + +'ms-MY': /^(\+?60|0)1(([0145](-|\s)?\d{7,8})|([236-9](-|\s)?\d{7}))$/, + +'mz-MZ': /^(\+?258)?8[234567]\d{7}$/, + +'nb-NO': /^(\+?47)?[49]\d{7}$/, + +'ne-NP': /^(\+?977)?9[78]\d{8}$/, + +'nl-BE': /^(\+?32|0)4\d{8}$/, + +'nl-NL': /^(((\+|00)?31\(0\))|((\+|00)?31)|0)6{1}\d{8}$/, + +'nl-AW': /^(\+)?297(56|59|64|73|74|99)\d{5}$/, + +'nn-NO': /^(\+?47)?[49]\d{7}$/, + +'pl-PL': /^(\+?48)? ?([5-8]\d|45) ?\d{3} ?\d{2} ?\d{2}$/, + +'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)?9\d{8}$/, + +'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}$/, + +'sl-SI': /^(\+386\s?|0)(\d{1}\s?\d{3}\s?\d{2}\s?\d{2}|\d{2}\s?\d{3}\s?\d{3})$/, + +'sk-SK': /^(\+?421)? ?[1-9][0-9]{2} ?[0-9]{3} ?[0-9]{3}$/, + +'so-SO': /^(\+?252|0)((6[0-9])\d{7}|(7[1-9])\d{7})$/, + +'sq-AL': /^(\+355|0)6[2-9]\d{7}$/, + +'sr-RS': /^(\+3816|06)[- \d]{5,9}$/, + +'sv-SE': /^(\+?46|0)[\s\-]?7[\s\-]?[02369]([\s\-]?\d){7}$/, + +'tg-TJ': /^(\+?992)?[5][5]\d{7}$/, + +'th-TH': /^(\+66|66|0)\d{9}$/, + +'tr-TR': /^(\+?90|0)?5\d{9}$/, + +'tk-TM': /^(\+993|993|8)\d{8}$/, + +'uk-UA': /^(\+?38)?0(50|6[36-8]|7[357]|9[1-9])\d{7}$/, + +'uz-UZ': /^(\+?998)?(6[125-79]|7[1-69]|88|9\d)\d{7}$/, + +'vi-VN': /^((\+?84)|0)((3([2-9]))|(5([25689]))|(7([0|6-9]))|(8([1-9]))|(9([0-9])))([0-9]{7})$/, + +'zh-CN': /^((\+|00)86)?(1[3-9]|9[28])\d{9}$/, + +'zh-TW': /^(\+?886\-?|0)?9\d{8}$/, + +'dz-BT': /^(\+?975|0)?(17|16|77|02)\d{6}$/, + +'ar-YE': /^(((\+|00)9677|0?7)[0137]\d{7}|((\+|00)967|0)[1-7]\d{6})$/, + +'ar-EH': /^(\+?212|0)[\s\-]?(5288|5289)[\s\-]?\d{5}$/, + +'fa-AF': /^(\+93|0)?(2{1}[0-8]{1}|[3-5]{1}[0-4]{1})(\d{7})$/, + +'mk-MK': /^(\+?389)?0?7\d{7}$/, + +}; + +/* eslint-enable max-len */ + + + +// aliases + +phones['en-CA'] = phones['en-US']; + +phones['fr-CA'] = phones['en-CA']; + +phones['fr-BE'] = phones['nl-BE']; + +phones['zh-HK'] = phones['en-HK']; + +phones['zh-MO'] = phones['en-MO']; + +phones['ga-IE'] = phones['en-IE']; + +phones['fr-CH'] = phones['de-CH']; + +phones['it-CH'] = phones['fr-CH']; + + + +export default function isMobilePhone(str, locale, options) { + +assertString(str); + +if (options && options.strictMode && !str.startsWith('+')) { + +return false; + +} + +if (Array.isArray(locale)) { + +return locale.some((key) => { + +// https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md#ignoring-code-for-coverage-purposes + +// istanbul ignore else + +if (phones.hasOwnProperty(key)) { + +const phone = phones[key]; + +if (phone.test(str)) { + +return true; + +} + +} + +return false; + +}); + +} else if (locale in phones) { + +return phones[locale].test(str); + + + +} else if (!locale || locale === 'any') { + +for (const key in phones) { + +// istanbul ignore else + +if (phones.hasOwnProperty(key)) { + +const phone = phones[key]; + +if (phone.test(str)) { + +return true; + +} + +} + +} + +return false; + +} + +throw new Error(`Invalid locale '${locale}'`); + +} + + + +export const locales = Object.keys(phones); \ No newline at end of file diff --git a/src/lib/isThousandSeparated.js b/src/lib/isThousandSeparated.js new file mode 100644 index 0000000..6561d8c --- /dev/null +++ b/src/lib/isThousandSeparated.js @@ -0,0 +1,44 @@ +import assertString from './util/assertString'; +import merge from './util/merge'; + +const default_thousand_separated_options = { + thousands_separator: ',', + decimal_separator: '.', + allow_negatives: true, +}; + +export default function isThousandSeparated(str, options) { + assertString(str); + options = merge(options, default_thousand_separated_options); + + const { thousands_separator, decimal_separator, allow_negatives } = options; + + // Escape special regex characters + const escapedThousandsSep = thousands_separator.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const escapedDecimalSep = decimal_separator.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + + // Build regex pattern + // Pattern explanation: + // ^(-?) - optional negative sign + // ([1-9]\\d{0,2}(escapedThousandsSep\\d{3})+|\\d{1,3}) - number with thousand separators OR 1-3 digit number + // (escapedDecimalSep\\d+)? - optional decimal part + // $ + + const negativeSign = allow_negatives ? '-?' : ''; + + // Pattern for numbers with thousand separators (e.g., 1,000 or 10,000 or 1,000,000) + const numbersWithSeparators = `[1-9]\\d{0,2}(${escapedThousandsSep}\\d{3})+`; + + // Pattern for numbers without separators (only 1-3 digits are valid without separators) + const numbersWithoutSeparators = '\\d{1,3}'; + + // Combine both patterns + const wholePart = `(${numbersWithSeparators}|${numbersWithoutSeparators})`; + + // Optional decimal part + const decimalPart = `(${escapedDecimalSep}\\d+)?`; + + const pattern = new RegExp(`^${negativeSign}${wholePart}${decimalPart}$`); + + return pattern.test(str); +} \ No newline at end of file diff --git a/test/validators.test.js b/test/validators.test.js index 12c5fc2..4792e82 100644 --- a/test/validators.test.js +++ b/test/validators.test.js @@ -66,9 +66,9 @@ describe('Validators', () => { '"wrong()[]",:;<>@@gmail.com', 'username@domain.com�', 'username@domain.com©', - 'nbsp test@test.com', - 'nbsp_test@te st.com', - 'nbsp_test@test.co m', + 'nbsp test@test.com', + 'nbsp_test@te st.com', + 'nbsp_test@test.co m', '"foobar@gmail.com', '"foo"bar@gmail.com', 'foo"bar"@gmail.com', @@ -133,7 +133,7 @@ describe('Validators', () => { 'hans.m端ller@test.com', 'z@co.c', 'tüst@invalid.com', - 'nbsp test@test.com', + 'nbsp test@test.com', ], }); }); @@ -15911,4 +15911,4 @@ describe('Validators', () => { ], }); }); -}); +}); \ No newline at end of file