Skip to content

Commit

Permalink
feat(isIdentityCard): add norway locale (#1324)
Browse files Browse the repository at this point in the history
* Fixes #1303

* Added postal code for nepal

* Added NP locale to postal code

* Added country code to passport READNE

* Added norway identity card
  • Loading branch information
parasg1999 authored May 28, 2020
1 parent 4407421 commit e807fb9
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 34 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Validator | Description
**isHexColor(str)** | check if the string is a hexadecimal color.
**isHSL(str)** | check if the string is an HSL (hue, saturation, lightness, optional alpha) color based on [CSS Colors Level 4 specification](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).<br/><br/>Comma-separated format supported. Space-separated format supported with the exception of a few edge cases (ex: `hsl(200grad+.1%62%/1)`).
**isRgbColor(str, [, includePercentValues])** | check if the string is a rgb or rgba color.<br/><br/>`includePercentValues` defaults to `true`. If you don't want to allow to set `rgb` or `rgba` values with percents, like `rgb(5%,5%,5%)`, or `rgba(90%,90%,90%,.3)`, then set it to false.
**isIdentityCard(str [, locale])** | check if the string is a valid identity card code.<br/><br/>`locale` is one of `['ES', 'IN', 'zh-TW', 'he-IL', 'ar-TN', 'zh-CN']` OR `'any'`. If 'any' is used, function will check if any of the locals match.<br/><br/>Defaults to 'any'.
**isIdentityCard(str [, locale])** | check if the string is a valid identity card code.<br/><br/>`locale` is one of `['ES', 'IN', 'NO', 'zh-TW', 'he-IL', 'ar-TN', 'zh-CN']` OR `'any'`. If 'any' is used, function will check if any of the locals match.<br/><br/>Defaults to 'any'.
**isIn(str, values)** | check if the string is in a array of allowed values.
**isInt(str [, options])** | check if the string is an integer.<br/><br/>`options` is an object which can contain the keys `min` and/or `max` to check the integer is within boundaries (e.g. `{ min: 10, max: 99 }`). `options` can also contain the key `allow_leading_zeroes`, which when set to false will disallow integer values with leading zeroes (e.g. `{ allow_leading_zeroes: false }`). Finally, `options` can contain the keys `gt` and/or `lt` which will enforce integers being greater than or less than, respectively, the value provided (e.g. `{gt: 1, lt: 4}` for a number between 1 and 4).
**isIP(str [, version])** | check if the string is an IP (version 4 or 6).
Expand Down
20 changes: 18 additions & 2 deletions es/lib/isIdentityCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ var validators = {

var p = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 5, 7, 6, 2, 8, 3, 0, 9, 4], [5, 8, 0, 3, 7, 9, 6, 1, 4, 2], [8, 9, 1, 6, 0, 4, 3, 5, 2, 7], [9, 4, 5, 3, 1, 2, 6, 8, 7, 0], [4, 2, 8, 6, 5, 7, 3, 9, 0, 1], [2, 7, 9, 3, 8, 0, 6, 4, 1, 5], [7, 0, 4, 6, 9, 1, 3, 2, 5, 8]]; // sanitize user input

var sanitized = str.trim();
console.log(sanitized); // validate the data structure
var sanitized = str.trim(); // validate the data structure

if (!DNI.test(sanitized)) {
return false;
Expand All @@ -43,6 +42,23 @@ var validators = {
});
return c === 0;
},
NO: function NO(str) {
var sanitized = str.trim();
if (isNaN(Number(sanitized))) return false;
if (sanitized.length !== 11) return false;
if (sanitized === '00000000000') return false; // https://no.wikipedia.org/wiki/F%C3%B8dselsnummer

var f = sanitized.split('').map(Number);
var k1 = (11 - (3 * f[0] + 7 * f[1] + 6 * f[2] + 1 * f[3] + 8 * f[4] + 9 * f[5] + 4 * f[6] + 5 * f[7] + 2 * f[8]) % 11) % 11;
var k2 = (11 - (5 * f[0] + 4 * f[1] + 3 * f[2] + 2 * f[3] + 7 * f[4] + 6 * f[5] + 5 * f[6] + 4 * f[7] + 3 * f[8] + 2 * k1) % 11) % 11;

if (k1 === 11) {
k1 = 0;
}

if (k1 !== f[9] || k2 !== f[10]) return false;
return true;
},
'he-IL': function heIL(str) {
var DNI = /^\d{9}$/; // sanitize user input

Expand Down
20 changes: 18 additions & 2 deletions lib/isIdentityCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ var validators = {

var p = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 5, 7, 6, 2, 8, 3, 0, 9, 4], [5, 8, 0, 3, 7, 9, 6, 1, 4, 2], [8, 9, 1, 6, 0, 4, 3, 5, 2, 7], [9, 4, 5, 3, 1, 2, 6, 8, 7, 0], [4, 2, 8, 6, 5, 7, 3, 9, 0, 1], [2, 7, 9, 3, 8, 0, 6, 4, 1, 5], [7, 0, 4, 6, 9, 1, 3, 2, 5, 8]]; // sanitize user input

var sanitized = str.trim();
console.log(sanitized); // validate the data structure
var sanitized = str.trim(); // validate the data structure

if (!DNI.test(sanitized)) {
return false;
Expand All @@ -53,6 +52,23 @@ var validators = {
});
return c === 0;
},
NO: function NO(str) {
var sanitized = str.trim();
if (isNaN(Number(sanitized))) return false;
if (sanitized.length !== 11) return false;
if (sanitized === '00000000000') return false; // https://no.wikipedia.org/wiki/F%C3%B8dselsnummer

var f = sanitized.split('').map(Number);
var k1 = (11 - (3 * f[0] + 7 * f[1] + 6 * f[2] + 1 * f[3] + 8 * f[4] + 9 * f[5] + 4 * f[6] + 5 * f[7] + 2 * f[8]) % 11) % 11;
var k2 = (11 - (5 * f[0] + 4 * f[1] + 3 * f[2] + 2 * f[3] + 7 * f[4] + 6 * f[5] + 5 * f[6] + 4 * f[7] + 3 * f[8] + 2 * k1) % 11) % 11;

if (k1 === 11) {
k1 = 0;
}

if (k1 !== f[9] || k2 !== f[10]) return false;
return true;
},
'he-IL': function heIL(str) {
var DNI = /^\d{9}$/; // sanitize user input

Expand Down
21 changes: 20 additions & 1 deletion src/lib/isIdentityCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ const validators = {

// sanitize user input
const sanitized = str.trim();
console.log(sanitized);

// validate the data structure
if (!DNI.test(sanitized)) {
Expand All @@ -76,6 +75,26 @@ const validators = {

return c === 0;
},
NO: (str) => {
const sanitized = str.trim();
if (isNaN(Number(sanitized))) return false;
if (sanitized.length !== 11) return false;
if (sanitized === '00000000000') return false;

// https://no.wikipedia.org/wiki/F%C3%B8dselsnummer
const f = sanitized.split('').map(Number);
let k1 = (11 - (((3 * f[0]) + (7 * f[1]) + (6 * f[2])
+ (1 * f[3]) + (8 * f[4]) + (9 * f[5]) + (4 * f[6])
+ (5 * f[7]) + (2 * f[8])) % 11)) % 11;
let k2 = (11 - (((5 * f[0]) + (4 * f[1]) + (3 * f[2])
+ (2 * f[3]) + (7 * f[4]) + (6 * f[5]) + (5 * f[6])
+ (4 * f[7]) + (3 * f[8]) + (2 * k1)) % 11)) % 11;
if (k1 === 11) {
k1 = 0;
}
if (k1 !== f[9] || k2 !== f[10]) return false;
return true;
},
'he-IL': (str) => {
const DNI = /^\d{9}$/;

Expand Down
18 changes: 18 additions & 0 deletions test/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -3978,6 +3978,24 @@ describe('Validators', () => {
'X1234567L',
],
},
{
locale: 'NO',
valid: [
'09053426694',
'26028338723',
'08031470790',
'12051539514',
'02077448074',
'14035638319',
'13031379673',
'29126214926',
],
invalid: [
'09053426699',
'26028338724',
'92031470790',
],
},
{
locale: 'he-IL',
valid: [
Expand Down
115 changes: 87 additions & 28 deletions validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function _unsupportedIterableToArray(o, minLen) {
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(n);
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}

Expand Down Expand Up @@ -1023,6 +1023,7 @@ function isNumeric(str, options) {
* https://docs.microsoft.com/en-us/microsoft-365/compliance/eu-passport-number -- EU Passport Number
* https://countrycode.org/ -- Country Codes
*/

var passportRegexByCountryCode = {
AM: /^[A-Z]{2}\d{7}$/,
// ARMENIA
Expand Down Expand Up @@ -1070,6 +1071,8 @@ var passportRegexByCountryCode = {
// HUNGARY
IE: /^[A-Z0-9]{2}\d{7}$/,
// IRELAND
IN: /^[A-Z]{1}-?\d{7}$/,
// INDIA
IS: /^(A)\d{7}$/,
// ICELAND
IT: /^[A-Z0-9]{2}\d{7}$/,
Expand Down Expand Up @@ -1117,7 +1120,9 @@ var passportRegexByCountryCode = {
*/

function isPassportNumber(str, countryCode) {
assertString(str);
/** Remove All Whitespaces, Convert to UPPERCASE */

var normalizedStr = str.replace(/\s/g, '').toUpperCase();
return countryCode.toUpperCase() in passportRegexByCountryCode && passportRegexByCountryCode[countryCode].test(normalizedStr);
}
Expand Down Expand Up @@ -1345,6 +1350,7 @@ var ibanRegexThroughCountryCode = {
IE: /^(IE[0-9]{2})[A-Z0-9]{4}\d{14}$/,
IL: /^(IL[0-9]{2})\d{19}$/,
IQ: /^(IQ[0-9]{2})[A-Z]{4}\d{15}$/,
IR: /^(IR[0-9]{2})0\d{2}0\d{18}$/,
IS: /^(IS[0-9]{2})\d{22}$/,
IT: /^(IT[0-9]{2})[A-Z]{1}\d{10}[A-Z0-9]{12}$/,
JO: /^(JO[0-9]{2})[A-Z]{4}\d{22}$/,
Expand All @@ -1356,7 +1362,6 @@ var ibanRegexThroughCountryCode = {
LT: /^(LT[0-9]{2})\d{16}$/,
LU: /^(LU[0-9]{2})\d{3}[A-Z0-9]{13}$/,
LV: /^(LV[0-9]{2})[A-Z]{4}[A-Z0-9]{13}$/,
LY: /^((\+?218)|0)?(9[1-6]\d{7}|[1-8]\d{7,9})$/,
MC: /^(MC[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/,
MD: /^(MD[0-9]{2})[A-Z0-9]{20}$/,
ME: /^(ME[0-9]{2})\d{18}$/,
Expand Down Expand Up @@ -1471,10 +1476,42 @@ function isHash(str, algorithm) {
return hash.test(str);
}

var jwt = /^([A-Za-z0-9\-_~+\/]+[=]{0,2})\.([A-Za-z0-9\-_~+\/]+[=]{0,2})(?:\.([A-Za-z0-9\-_~+\/]+[=]{0,2}))?$/;
var notBase64 = /[^A-Z0-9+\/=]/i;
var urlSafeBase64 = /^[A-Z0-9_\-]+$/i;
var defaultBase64Options = {
urlSafe: false
};
function isBase64(str, options) {
assertString(str);
options = merge(options, defaultBase64Options);
var len = str.length;

if (options.urlSafe) {
return urlSafeBase64.test(str);
}

if (!len || len % 4 !== 0 || notBase64.test(str)) {
return false;
}

var firstPaddingChar = str.indexOf('=');
return firstPaddingChar === -1 || firstPaddingChar === len - 1 || firstPaddingChar === len - 2 && str[len - 1] === '=';
}

function isJWT(str) {
assertString(str);
return jwt.test(str);
var dotSplit = str.split('.');
var len = dotSplit.length;

if (len > 3 || len < 2) {
return false;
}

return dotSplit.reduce(function (acc, currElem) {
return acc && isBase64(currElem, {
urlSafe: true
});
}, true);
}

function isJSON(str) {
Expand Down Expand Up @@ -1642,6 +1679,43 @@ var validators = {
});
return sanitized.endsWith(controlDigits[number % 23]);
},
IN: function IN(str) {
var DNI = /^[1-9]\d{3}\s?\d{4}\s?\d{4}$/; // multiplication table

var d = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 0, 6, 7, 8, 9, 5], [2, 3, 4, 0, 1, 7, 8, 9, 5, 6], [3, 4, 0, 1, 2, 8, 9, 5, 6, 7], [4, 0, 1, 2, 3, 9, 5, 6, 7, 8], [5, 9, 8, 7, 6, 0, 4, 3, 2, 1], [6, 5, 9, 8, 7, 1, 0, 4, 3, 2], [7, 6, 5, 9, 8, 2, 1, 0, 4, 3], [8, 7, 6, 5, 9, 3, 2, 1, 0, 4], [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]; // permutation table

var p = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 5, 7, 6, 2, 8, 3, 0, 9, 4], [5, 8, 0, 3, 7, 9, 6, 1, 4, 2], [8, 9, 1, 6, 0, 4, 3, 5, 2, 7], [9, 4, 5, 3, 1, 2, 6, 8, 7, 0], [4, 2, 8, 6, 5, 7, 3, 9, 0, 1], [2, 7, 9, 3, 8, 0, 6, 4, 1, 5], [7, 0, 4, 6, 9, 1, 3, 2, 5, 8]]; // sanitize user input

var sanitized = str.trim(); // validate the data structure

if (!DNI.test(sanitized)) {
return false;
}

var c = 0;
var invertedArray = sanitized.replace(/\s/g, '').split('').map(Number).reverse();
invertedArray.forEach(function (val, i) {
c = d[c][p[i % 8][val]];
});
return c === 0;
},
NO: function NO(str) {
var sanitized = str.trim();
if (isNaN(Number(sanitized))) return false;
if (sanitized.length !== 11) return false;
if (sanitized === '00000000000') return false; // https://no.wikipedia.org/wiki/F%C3%B8dselsnummer

var f = sanitized.split('').map(Number);
var k1 = (11 - (3 * f[0] + 7 * f[1] + 6 * f[2] + 1 * f[3] + 8 * f[4] + 9 * f[5] + 4 * f[6] + 5 * f[7] + 2 * f[8]) % 11) % 11;
var k2 = (11 - (5 * f[0] + 4 * f[1] + 3 * f[2] + 2 * f[3] + 7 * f[4] + 6 * f[5] + 5 * f[6] + 4 * f[7] + 3 * f[8] + 2 * k1) % 11) % 11;

if (k1 === 11) {
k1 = 0;
}

if (k1 !== f[9] || k2 !== f[10]) return false;
return true;
},
'he-IL': function heIL(str) {
var DNI = /^\d{9}$/; // sanitize user input

Expand Down Expand Up @@ -2054,6 +2128,7 @@ var phones = {
'ar-IQ': /^(\+?964|0)?7[0-9]\d{8}$/,
'ar-JO': /^(\+?962|0)?7[789]\d{7}$/,
'ar-KW': /^(\+?965)[569]\d{7}$/,
'ar-LY': /^((\+?218)|0)?(9[1-6]\d{7}|[1-8]\d{7,9})$/,
'ar-SA': /^(!?(\+?966)|0)?5\d{8}$/,
'ar-SY': /^(!?(\+?963)|0)?9\d{8}$/,
'ar-TN': /^(\+?216)?[2459]\d{7}$/,
Expand All @@ -2064,6 +2139,7 @@ var phones = {
'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}$/,
'de-AT': /^(\+43|0)\d{1,4}\d{3,12}$/,
'de-CH': /^(\+41|0)(7[5-9])\d{1,7}$/,
'el-GR': /^(\+?30|0)?(69\d{8})$/,
'en-AU': /^(\+?61|0)4\d{8}$/,
'en-GB': /^(\+?44|0)7\d{9}$/,
Expand All @@ -2087,6 +2163,7 @@ var phones = {
'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)?09[567]\d{7}$/,
'en-ZW': /^(\+263)[0-9]{9}$/,
'es-CL': /^(\+?56|0)[2-9]\d{1}\d{7}$/,
'es-CR': /^(\+506)?[2-8]\d{7}$/,
'es-EC': /^(\+?593|0)([2-7]|9[2-9])\d{7}$/,
Expand Down Expand Up @@ -2133,7 +2210,7 @@ var phones = {
'tr-TR': /^(\+?90|0)?5\d{9}$/,
'uk-UA': /^(\+?38|8)?0\d{9}$/,
'vi-VN': /^(\+?84|0)((3([2-9]))|(5([2689]))|(7([0|6-9]))|(8([1-6|89]))|(9([0-9])))([0-9]{7})$/,
'zh-CN': /^((\+|00)86)?1([358][0-9]|4[579]|6[67]|7[01235678]|9[189])[0-9]{8}$/,
'zh-CN': /^((\+|00)86)?1([3568][0-9]|4[579]|6[67]|7[01235678]|9[189])[0-9]{8}$/,
'zh-TW': /^(\+?886\-?|0)?9\d{8}$/
};
/* eslint-enable max-len */
Expand Down Expand Up @@ -2361,25 +2438,6 @@ function isBase32(str) {
return false;
}

var notBase64 = /[^A-Z0-9+\/=]/i;
function isBase64(str) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
assertString(str);

if (options.urlSafe) {
return /^[A-Za-z0-9_-]+$/.test(str);
}

var len = str.length;

if (!len || len % 4 !== 0 || notBase64.test(str)) {
return false;
}

var firstPaddingChar = str.indexOf('=');
return firstPaddingChar === -1 || firstPaddingChar === len - 1 || firstPaddingChar === len - 2 && str[len - 1] === '=';
}

var validMediaType = /^[a-z]+\/[a-z0-9\-\+]+$/i;
var validAttribute = /^[a-z\-]+=[a-z0-9\-]+$/i;
var validData = /^[a-z0-9!\$&'\(\)\*\+,;=\-\._~:@\/\?%\s]*$/i;
Expand Down Expand Up @@ -2467,13 +2525,13 @@ function isMimeType(str) {

var lat = /^\(?[+-]?(90(\.0+)?|[1-8]?\d(\.\d+)?)$/;
var _long = /^\s?[+-]?(180(\.0+)?|1[0-7]\d(\.\d+)?|\d{1,2}(\.\d+)?)\)?$/;
var isLatLong = function (str) {
function isLatLong(str) {
assertString(str);
if (!str.includes(',')) return false;
var pair = str.split(',');
if (pair[0].startsWith('(') && !pair[1].endsWith(')') || pair[1].endsWith(')') && !pair[0].startsWith('(')) return false;
return lat.test(pair[0]) && _long.test(pair[1]);
};
}

var threeDigit = /^\d{3}$/;
var fourDigit = /^\d{4}$/;
Expand Down Expand Up @@ -2516,6 +2574,7 @@ var patterns = {
MT: /^[A-Za-z]{3}\s{0,1}\d{4}$/,
NL: /^\d{4}\s?[a-z]{2}$/i,
NO: fourDigit,
NP: /^(10|21|22|32|33|34|44|45|56|57)\d{3}$|^(977)$/i,
NZ: fourDigit,
PL: /^\d{2}\-\d{3}$/,
PR: /^00[679]\d{2}([ -]\d{4})?$/,
Expand All @@ -2534,7 +2593,7 @@ var patterns = {
ZM: fiveDigit
};
var locales$4 = Object.keys(patterns);
var isPostalCode = function (str, locale) {
function isPostalCode(str, locale) {
assertString(str);

if (locale in patterns) {
Expand All @@ -2556,7 +2615,7 @@ var isPostalCode = function (str, locale) {
}

throw new Error("Invalid locale '".concat(locale, "'"));
};
}

function ltrim(str, chars) {
assertString(str); // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
Expand Down

0 comments on commit e807fb9

Please sign in to comment.