Skip to content

Commit afdbd68

Browse files
authored
Merge branch 'master' into feature/all-country-regex
2 parents fba9680 + c193fe5 commit afdbd68

24 files changed

+800
-77
lines changed

.github/workflows/codeql-analysis.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# For most projects, this workflow file will not need changing; you simply need
2+
# to commit it to your repository.
3+
#
4+
# You may wish to alter this file to override the set of languages analyzed,
5+
# or to provide custom queries or build logic.
6+
#
7+
# ******** NOTE ********
8+
# We have attempted to detect the languages in your repository. Please check
9+
# the `language` matrix defined below to confirm you have the correct set of
10+
# supported CodeQL languages.
11+
#
12+
name: "CodeQL"
13+
14+
on:
15+
push:
16+
branches: [ master ]
17+
pull_request:
18+
# The branches below must be a subset of the branches above
19+
branches: [ master ]
20+
schedule:
21+
- cron: '38 10 * * 4'
22+
23+
jobs:
24+
analyze:
25+
name: Analyze
26+
runs-on: ubuntu-latest
27+
permissions:
28+
actions: read
29+
contents: read
30+
security-events: write
31+
32+
strategy:
33+
fail-fast: false
34+
matrix:
35+
language: [ 'javascript' ]
36+
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37+
# Learn more about CodeQL language support at https://git.io/codeql-language-support
38+
39+
steps:
40+
- name: Checkout repository
41+
uses: actions/checkout@v2
42+
43+
# Initializes the CodeQL tools for scanning.
44+
- name: Initialize CodeQL
45+
uses: github/codeql-action/init@v1
46+
with:
47+
languages: ${{ matrix.language }}
48+
# If you wish to specify custom queries, you can do so here or in a config file.
49+
# By default, queries listed here will override any specified in a config file.
50+
# Prefix the list here with "+" to use these queries and those in the config file.
51+
# queries: ./path/to/local/query, your-org/your-repo/queries@main
52+
53+
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
54+
# If this step fails, then you should remove it and run the build manually (see below)
55+
- name: Autobuild
56+
uses: github/codeql-action/autobuild@v1
57+
58+
# ℹ️ Command-line programs to run using the OS shell.
59+
# 📚 https://git.io/JvXDl
60+
61+
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
62+
# and modify them (or add more) to build your code if your project
63+
# uses a compiled language
64+
65+
#- run: |
66+
# make bootstrap
67+
# make release
68+
69+
- name: Perform CodeQL Analysis
70+
uses: github/codeql-action/analyze@v1

README.md

Lines changed: 21 additions & 10 deletions
Large diffs are not rendered by default.

SECURITY.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Security Policy
2+
3+
## Supported Versions
4+
5+
In the case of a confirmed security issue, only the current version of validator is guaranteed to be patched.
6+
7+
## Reporting a Vulnerability
8+
9+
**Please don't disclose security-related issues publicly.**
10+
11+
If you discover a vulnerability within validator, please use [huntr.dev disclosure form](https://huntr.dev/bounties/disclose/?target=https://github.com/validatorjs/validator.js). We will try to validate and respond to reports in a reasonable time. if the issue is confirmed, we will create a security advisory and a patch as soon as possible.

src/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import isBefore from './lib/isBefore';
6969

7070
import isIn from './lib/isIn';
7171

72+
import isLuhnValid from './lib/isLuhnValid';
7273
import isCreditCard from './lib/isCreditCard';
7374
import isIdentityCard from './lib/isIdentityCard';
7475

@@ -86,6 +87,7 @@ import isCurrency from './lib/isCurrency';
8687

8788
import isBtcAddress from './lib/isBtcAddress';
8889

90+
import isISO6391 from './lib/isISO6391';
8991
import isISO8601 from './lib/isISO8601';
9092
import isRFC3339 from './lib/isRFC3339';
9193
import isISO31661Alpha2 from './lib/isISO31661Alpha2';
@@ -182,6 +184,7 @@ const validator = {
182184
isAfter,
183185
isBefore,
184186
isIn,
187+
isLuhnValid,
185188
isCreditCard,
186189
isIdentityCard,
187190
isEAN,
@@ -195,6 +198,7 @@ const validator = {
195198
isEthereumAddress,
196199
isCurrency,
197200
isBtcAddress,
201+
isISO6391,
198202
isISO8601,
199203
isRFC3339,
200204
isISO31661Alpha2,

src/lib/alpha.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export const alpha = {
3232
he: /^[א-ת]+$/,
3333
fa: /^['آاءأؤئبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهةی']+$/i,
3434
'hi-IN': /^[\u0900-\u0961]+[\u0972-\u097F]*$/i,
35+
'si-LK': /^[\u0D80-\u0DFF]+$/,
3536
};
3637

3738
export const alphanumeric = {
@@ -67,6 +68,7 @@ export const alphanumeric = {
6768
he: /^[0-9א-ת]+$/,
6869
fa: /^['0-9آاءأؤئبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهةی۱۲۳۴۵۶۷۸۹۰']+$/i,
6970
'hi-IN': /^[\u0900-\u0963]+[\u0966-\u097F]*$/i,
71+
'si-LK': /^[0-9\u0D80-\u0DFF]+$/,
7072
};
7173

7274
export const decimal = {
@@ -112,7 +114,7 @@ export const dotDecimal = ['ar-EG', 'ar-LB', 'ar-LY'];
112114
export const commaDecimal = [
113115
'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-ZM', 'es-ES', 'fr-CA', 'fr-FR',
114116
'id-ID', 'it-IT', 'ku-IQ', 'hi-IN', 'hu-HU', 'nb-NO', 'nn-NO', 'nl-NL', 'pl-PL', 'pt-PT',
115-
'ru-RU', 'sl-SI', 'sr-RS@latin', 'sr-RS', 'sv-SE', 'tr-TR', 'uk-UA', 'vi-VN',
117+
'ru-RU', 'si-LK', 'sl-SI', 'sr-RS@latin', 'sr-RS', 'sv-SE', 'tr-TR', 'uk-UA', 'vi-VN',
116118
];
117119

118120
for (let i = 0; i < dotDecimal.length; i++) {

src/lib/isBase32.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
import assertString from './util/assertString';
2+
import merge from './util/merge';
23

34
const base32 = /^[A-Z2-7]+=*$/;
5+
const crockfordBase32 = /^[A-HJKMNP-TV-Z0-9]+$/;
46

5-
export default function isBase32(str) {
7+
const defaultBase32Options = {
8+
crockford: false,
9+
};
10+
11+
export default function isBase32(str, options) {
612
assertString(str);
13+
options = merge(options, defaultBase32Options);
14+
15+
if (options.crockford) {
16+
return crockfordBase32.test(str);
17+
}
18+
719
const len = str.length;
820
if (len % 8 === 0 && base32.test(str)) {
921
return true;

src/lib/isCreditCard.js

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import assertString from './util/assertString';
2+
import isLuhnValid from './isLuhnValid';
23

34
/* eslint-disable max-len */
45
const creditCard = /^(?:4[0-9]{12}(?:[0-9]{3,6})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12,15}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11}|6[27][0-9]{14}|^(81[0-9]{14,17}))$/;
@@ -10,24 +11,5 @@ export default function isCreditCard(str) {
1011
if (!creditCard.test(sanitized)) {
1112
return false;
1213
}
13-
let sum = 0;
14-
let digit;
15-
let tmpNum;
16-
let shouldDouble;
17-
for (let i = sanitized.length - 1; i >= 0; i--) {
18-
digit = sanitized.substring(i, (i + 1));
19-
tmpNum = parseInt(digit, 10);
20-
if (shouldDouble) {
21-
tmpNum *= 2;
22-
if (tmpNum >= 10) {
23-
sum += ((tmpNum % 10) + 1);
24-
} else {
25-
sum += tmpNum;
26-
}
27-
} else {
28-
sum += tmpNum;
29-
}
30-
shouldDouble = !shouldDouble;
31-
}
32-
return !!((sum % 10) === 0 ? sanitized : false);
14+
return isLuhnValid(str);
3315
}

src/lib/isDataURI.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import assertString from './util/assertString';
22

3-
const validMediaType = /^[a-z]+\/[a-z0-9\-\+]+$/i;
3+
const validMediaType = /^[a-z]+\/[a-z0-9\-\+\.]+$/i;
44

55
const validAttribute = /^[a-z\-]+=[a-z0-9\-]+$/i;
66

@@ -14,10 +14,10 @@ export default function isDataURI(str) {
1414
}
1515
const attributes = data.shift().trim().split(';');
1616
const schemeAndMediaType = attributes.shift();
17-
if (schemeAndMediaType.substr(0, 5) !== 'data:') {
17+
if (schemeAndMediaType.slice(0, 5) !== 'data:') {
1818
return false;
1919
}
20-
const mediaType = schemeAndMediaType.substr(5);
20+
const mediaType = schemeAndMediaType.slice(5);
2121
if (mediaType !== '' && !validMediaType.test(mediaType)) {
2222
return false;
2323
}

src/lib/isEmail.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export default function isEmail(str, options) {
7777
// eg. myname <[email protected]>
7878
// the display name is `myname` instead of `myname `, so need to trim the last space
7979
if (display_name.endsWith(' ')) {
80-
display_name = display_name.substr(0, display_name.length - 1);
80+
display_name = display_name.slice(0, -1);
8181
}
8282

8383
if (!validateDisplayName(display_name)) {
@@ -144,7 +144,7 @@ export default function isEmail(str, options) {
144144
return false;
145145
}
146146

147-
let noBracketdomain = domain.substr(1, domain.length - 2);
147+
let noBracketdomain = domain.slice(1, -1);
148148

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

src/lib/isFQDN.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export default function isFQDN(str, options) {
3232
return false;
3333
}
3434

35-
if (!/^([a-z\u00A1-\u00A8\u00AA-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}|xn[a-z0-9-]{2,})$/i.test(tld)) {
35+
if (!options.allow_numeric_tld && !/^([a-z\u00A1-\u00A8\u00AA-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}|xn[a-z0-9-]{2,})$/i.test(tld)) {
3636
return false;
3737
}
3838

src/lib/isIP.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,10 @@ export default function isIP(str, version = '') {
5151
return isIP(str, 4) || isIP(str, 6);
5252
}
5353
if (version === '4') {
54-
if (!IPv4AddressRegExp.test(str)) {
55-
return false;
56-
}
57-
const parts = str.split('.').sort((a, b) => a - b);
58-
return parts[3] <= 255;
54+
return IPv4AddressRegExp.test(str);
5955
}
6056
if (version === '6') {
61-
return !!IPv6AddressRegExp.test(str);
57+
return IPv6AddressRegExp.test(str);
6258
}
6359
return false;
6460
}

src/lib/isISO6391.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import assertString from './util/assertString';
2+
3+
const isISO6391Set = new Set([
4+
'aa', 'ab', 'ae', 'af', 'ak', 'am', 'an', 'ar', 'as', 'av', 'ay', 'az', 'az',
5+
'ba', 'be', 'bg', 'bh', 'bi', 'bm', 'bn', 'bo', 'br', 'bs',
6+
'ca', 'ce', 'ch', 'co', 'cr', 'cs', 'cu', 'cv', 'cy',
7+
'da', 'de', 'dv', 'dz',
8+
'ee', 'el', 'en', 'eo', 'es', 'et', 'eu',
9+
'fa', 'ff', 'fi', 'fj', 'fo', 'fr', 'fy',
10+
'ga', 'gd', 'gl', 'gn', 'gu', 'gv',
11+
'ha', 'he', 'hi', 'ho', 'hr', 'ht', 'hu', 'hy', 'hz',
12+
'ia', 'id', 'ie', 'ig', 'ii', 'ik', 'io', 'is', 'it', 'iu',
13+
'ja', 'jv',
14+
'ka', 'kg', 'ki', 'kj', 'kk', 'kl', 'km', 'kn', 'ko', 'kr', 'ks', 'ku', 'kv', 'kw', 'ky',
15+
'la', 'lb', 'lg', 'li', 'ln', 'lo', 'lt', 'lu', 'lv',
16+
'mg', 'mh', 'mi', 'mk', 'ml', 'mn', 'mr', 'ms', 'mt', 'my',
17+
'na', 'nb', 'nd', 'ne', 'ng', 'nl', 'nn', 'no', 'nr', 'nv', 'ny',
18+
'oc', 'oj', 'om', 'or', 'os',
19+
'pa', 'pi', 'pl', 'ps', 'pt',
20+
'qu',
21+
'rm', 'rn', 'ro', 'ru', 'rw',
22+
'sa', 'sc', 'sd', 'se', 'sg', 'si', 'sk', 'sl', 'sm', 'sn', 'so', 'sq', 'sr', 'ss', 'st', 'su', 'sv', 'sw',
23+
'ta', 'te', 'tg', 'th', 'ti', 'tk', 'tl', 'tn', 'to', 'tr', 'ts', 'tt', 'tw', 'ty',
24+
'ug', 'uk', 'ur', 'uz',
25+
've', 'vi', 'vo',
26+
'wa', 'wo',
27+
'xh',
28+
'yi', 'yo',
29+
'za', 'zh', 'zu',
30+
]);
31+
32+
export default function isISO6391(str) {
33+
assertString(str);
34+
return isISO6391Set.has(str);
35+
}

src/lib/isIdentityCard.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,15 +130,15 @@ const validators = {
130130
},
131131
IR: (str) => {
132132
if (!str.match(/^\d{10}$/)) return false;
133-
str = (`0000${str}`).substr(str.length - 6);
133+
str = (`0000${str}`).slice(str.length - 6);
134134

135-
if (parseInt(str.substr(3, 6), 10) === 0) return false;
135+
if (parseInt(str.slice(3, 9), 10) === 0) return false;
136136

137-
const lastNumber = parseInt(str.substr(9, 1), 10);
137+
const lastNumber = parseInt(str.slice(9, 10), 10);
138138
let sum = 0;
139139

140140
for (let i = 0; i < 9; i++) {
141-
sum += parseInt(str.substr(i, 1), 10) * (10 - i);
141+
sum += parseInt(str.slice(i, i + 1), 10) * (10 - i);
142142
}
143143

144144
sum %= 11;

src/lib/isLength.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ export default function isLength(str, options) {
1212
min = arguments[1] || 0;
1313
max = arguments[2];
1414
}
15+
const presentationSequences = str.match(/(\uFE0F|\uFE0E)/g) || [];
1516
const surrogatePairs = str.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g) || [];
16-
const len = str.length - surrogatePairs.length;
17+
const len = str.length - presentationSequences.length - surrogatePairs.length;
1718
return len >= min && (typeof max === 'undefined' || len <= max);
1819
}

src/lib/isLicensePlate.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const validators = {
44
'cs-CZ': str =>
55
/^(([ABCDEFHKIJKLMNPRSTUVXYZ]|[0-9])-?){5,8}$/.test(str),
66
'de-DE': str =>
7-
/^((AW|UL|AK|GA|AÖ|LF|AZ|AM|AS|ZE|AN|AB|A|KG|KH|BA|EW|BZ|HY|KM|BT|HP|B|BC|BI|BO|FN|TT|ÜB|BN|AH|BS|FR|HB|ZZ|BB|BK|BÖ|OC|OK|CW|CE|C|CO|LH|CB|KW|LC|LN|DA|DI|DE|DH|SY|NÖ|DO|DD|DU|DN|D|EI|EA|EE|FI|EM|EL|EN|PF|ED|EF|ER|AU|ZP|E|ES|NT|EU|FL|FO|FT|FF|F|FS|FD|FÜ|GE|G|GI|GF|GS|ZR|GG|GP|GR|NY|ZI|GÖ|GZ|GT|HA|HH|HM|HU|WL|HZ|WR|RN|HK|HD|HN|HS|GK|HE|HF|RZ|HI|HG|HO|HX|IK|IL|IN|J|JL|KL|KA|KS|KF|KE|KI|KT|KO|KN|KR|KC|KU|K|LD|LL|LA|L|OP|LM|LI|LB|LU|LÖ|HL|LG|MD|GN|MZ|MA|ML|MR|MY|AT|DM|MC|NZ|RM|RG|MM|ME|MB|MI|FG|DL|HC|MW|RL|MK|MG|MÜ|WS|MH|M|MS|NU|NB|ND|NM|NK|NW|NR|NI|NF|DZ|EB|OZ|TG|TO|N|OA|GM|OB|CA|EH|FW|OF|OL|OE|OG|BH|LR|OS|AA|GD|OH|KY|NP|WK|PB|PA|PE|PI|PS|P|PM|PR|RA|RV|RE|R|H|SB|WN|RS|RD|RT|BM|NE|GV|RP|SU|GL|RO|GÜ|RH|EG|RW|PN|SK|MQ|RU|SZ|RI|SL|SM|SC|HR|FZ|VS|SW|SN|CR|SE|SI|SO|LP|SG|NH|SP|IZ|ST|BF|TE|HV|OD|SR|S|AC|DW|ZW|TF|TS|TR|TÜ|UM|PZ|TP|UE|UN|UH|MN|KK|VB|V|AE|PL|RC|VG|GW|PW|VR|VK|KB|WA|WT|BE|WM|WE|AP|MO|WW|FB|WZ|WI|WB|JE|WF|WO|W|WÜ|BL|Z|GC)[- ]?[A-Z]{1,2}[- ]?\d{1,4}|(AIC|FDB|ABG|SLN|SAW|KLZ|BUL|ESB|NAB|SUL|WST|ABI|AZE|BTF|KÖT|DKB|FEU|ROT|ALZ|SMÜ|WER|AUR|NOR|DÜW|BRK|HAB|TÖL|WOR|BAD|BAR|BER|BIW|EBS|KEM|MÜB|PEG|BGL|BGD|REI|WIL|BKS|BIR|WAT|BOR|BOH|BOT|BRB|BLK|HHM|NEB|NMB|WSF|LEO|HDL|WMS|WZL|BÜS|CHA|KÖZ|ROD|WÜM|CLP|NEC|COC|ZEL|COE|CUX|DAH|LDS|DEG|DEL|RSL|DLG|DGF|LAN|HEI|MED|DON|KIB|ROK|JÜL|MON|SLE|EBE|EIC|HIG|WBS|BIT|PRÜ|LIB|EMD|WIT|ERH|HÖS|ERZ|ANA|ASZ|MAB|MEK|STL|SZB|FDS|HCH|HOR|WOL|FRG|GRA|WOS|FRI|FFB|GAP|GER|BRL|CLZ|GTH|NOH|HGW|GRZ|LÖB|NOL|WSW|DUD|HMÜ|OHA|KRU|HAL|HAM|HBS|QLB|HVL|NAU|HAS|EBN|GEO|HOH|HDH|ERK|HER|WAN|HEF|ROF|HBN|ALF|HSK|USI|NAI|REH|SAN|KÜN|ÖHR|HOL|WAR|ARN|BRG|GNT|HOG|WOH|KEH|MAI|PAR|RID|ROL|KLE|GEL|KUS|KYF|ART|SDH|LDK|DIL|MAL|VIB|LER|BNA|GHA|GRM|MTL|WUR|LEV|LIF|STE|WEL|LIP|VAI|LUP|HGN|LBZ|LWL|PCH|STB|DAN|MKK|SLÜ|MSP|TBB|MGH|MTK|BIN|MSH|EIL|HET|SGH|BID|MYK|MSE|MST|MÜR|WRN|MEI|GRH|RIE|MZG|MIL|OBB|BED|FLÖ|MOL|FRW|SEE|SRB|AIB|MOS|BCH|ILL|SOB|NMS|NEA|SEF|UFF|NEW|VOH|NDH|TDO|NWM|GDB|GVM|WIS|NOM|EIN|GAN|LAU|HEB|OHV|OSL|SFB|ERB|LOS|BSK|KEL|BSB|MEL|WTL|OAL|FÜS|MOD|OHZ|OPR|BÜR|PAF|PLÖ|CAS|GLA|REG|VIT|ECK|SIM|GOA|EMS|DIZ|GOH|RÜD|SWA|NES|KÖN|MET|LRO|BÜZ|DBR|ROS|TET|HRO|ROW|BRV|HIP|PAN|GRI|SHK|EIS|SRO|SOK|LBS|SCZ|MER|QFT|SLF|SLS|HOM|SLK|ASL|BBG|SBK|SFT|SHG|MGN|MEG|ZIG|SAD|NEN|OVI|SHA|BLB|SIG|SON|SPN|FOR|GUB|SPB|IGB|WND|STD|STA|SDL|OBG|HST|BOG|SHL|PIR|FTL|SEB|SÖM|SÜW|TIR|SAB|TUT|ANG|SDT|LÜN|LSZ|MHL|VEC|VER|VIE|OVL|ANK|OVP|SBG|UEM|UER|WLG|GMN|NVP|RDG|RÜG|DAU|FKB|WAF|WAK|SLZ|WEN|SOG|APD|WUG|GUN|ESW|WIZ|WES|DIN|BRA|BÜD|WHV|HWI|GHC|WTM|WOB|WUN|MAK|SEL|OCH|HOT|WDA)[- ]?(([A-Z][- ]?\d{1,4})|([A-Z]{2}[- ]?\d{1,3})))[- ]?(E|H)?$/.test(str),
7+
/^((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),
88
'de-LI': str => /^FL[- ]?\d{1,5}[UZ]?$/.test(str),
99
'fi-FI': str => /^(?=.{4,7})(([A-Z]{1,3}|[0-9]{1,3})[\s-]?([A-Z]{1,3}|[0-9]{1,5}))$/.test(str),
1010
'pt-PT': str =>
@@ -13,8 +13,25 @@ const validators = {
1313
/^[A-Z]{2}[- ]?((\d{3}[- ]?(([A-Z]{2})|T))|(R[- ]?\d{3}))$/.test(str),
1414
'pt-BR': str =>
1515
/^[A-Z]{3}[ -]?[0-9][A-Z][0-9]{2}|[A-Z]{3}[ -]?[0-9]{4}$/.test(str),
16+
'sv-SE': str =>
17+
/^[A-HJ-PR-UW-Z]{3} ?[\d]{2}[A-HJ-PR-UW-Z1-9]$|(^[A-ZÅÄÖ ]{2,7}$)/.test(str.trim()),
18+
'en-IN': str => /^[A-Z]{2}[ -]?[0-9]{1,2}(?:[ -]?[A-Z])(?:[ -]?[A-Z]*)?[ -]?[0-9]{4}$/.test(str),
1619
};
1720

21+
validators['hi-IN'] = validators['en-IN'];
22+
validators['gu-IN'] = validators['en-IN'];
23+
validators['as-IN'] = validators['en-IN'];
24+
validators['bn-IN'] = validators['en-IN'];
25+
validators['kn-IN'] = validators['en-IN'];
26+
validators['ml-IN'] = validators['en-IN'];
27+
validators['mr-IN'] = validators['en-IN'];
28+
validators['or-IN'] = validators['en-IN'];
29+
validators['pa-IN'] = validators['en-IN'];
30+
validators['sa-IN'] = validators['en-IN'];
31+
validators['ta-IN'] = validators['en-IN'];
32+
validators['te-IN'] = validators['en-IN'];
33+
validators['kok-IN'] = validators['en-IN'];
34+
1835
export default function isLicensePlate(str, locale) {
1936
assertString(str);
2037
if (locale in validators) {

src/lib/isLuhnValid.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import assertString from './util/assertString';
2+
3+
export default function isLuhnValid(str) {
4+
assertString(str);
5+
const sanitized = str.replace(/[- ]+/g, '');
6+
let sum = 0;
7+
let digit;
8+
let tmpNum;
9+
let shouldDouble;
10+
for (let i = sanitized.length - 1; i >= 0; i--) {
11+
digit = sanitized.substring(i, (i + 1));
12+
tmpNum = parseInt(digit, 10);
13+
if (shouldDouble) {
14+
tmpNum *= 2;
15+
if (tmpNum >= 10) {
16+
sum += ((tmpNum % 10) + 1);
17+
} else {
18+
sum += tmpNum;
19+
}
20+
} else {
21+
sum += tmpNum;
22+
}
23+
shouldDouble = !shouldDouble;
24+
}
25+
return !!((sum % 10) === 0 ? sanitized : false);
26+
}

0 commit comments

Comments
 (0)