diff --git a/README.md b/README.md
index 040d4ef26..e3fc8eaa7 100644
--- a/README.md
+++ b/README.md
@@ -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).
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.
`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.
`locale` is one of `['ES', 'zh-TW', 'he-IL', 'ar-TN', 'zh-CN']` OR `'any'`. If 'any' is used, function will check if any of the locals match.
Defaults to 'any'.
+**isIdentityCard(str [, locale])** | check if the string is a valid identity card code.
`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.
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.
`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).
diff --git a/es/lib/isIdentityCard.js b/es/lib/isIdentityCard.js
index 5a780c727..b845a397b 100644
--- a/es/lib/isIdentityCard.js
+++ b/es/lib/isIdentityCard.js
@@ -22,6 +22,27 @@ 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();
+ console.log(sanitized); // 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;
+ },
'he-IL': function heIL(str) {
var DNI = /^\d{9}$/; // sanitize user input
diff --git a/lib/isIdentityCard.js b/lib/isIdentityCard.js
index 1d37631ff..8c8575952 100644
--- a/lib/isIdentityCard.js
+++ b/lib/isIdentityCard.js
@@ -9,9 +9,6 @@ var _assertString = _interopRequireDefault(require("./util/assertString"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-
-
var validators = {
ES: function ES(str) {
(0, _assertString.default)(str);
@@ -35,6 +32,27 @@ 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();
+ console.log(sanitized); // 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;
+ },
'he-IL': function heIL(str) {
var DNI = /^\d{9}$/; // sanitize user input
@@ -46,7 +64,7 @@ var validators = {
var id = sanitized;
var sum = 0,
- incNum;
+ incNum;
for (var i = 0; i < id.length; i++) {
incNum = Number(id[i]) * (i % 2 + 1); // Multiply number by 1 or 2
@@ -56,8 +74,137 @@ var validators = {
return sum % 10 === 0;
},
+ 'ar-TN': function arTN(str) {
+ var DNI = /^\d{8}$/; // sanitize user input
+
+ var sanitized = str.trim(); // validate the data structure
+
+ if (!DNI.test(sanitized)) {
+ return false;
+ }
+
+ return true;
+ },
'zh-CN': function zhCN(str) {
- return zhCNidCardNoValidator.checkIdCardNo(str)
+ var provinceAndCitys = {
+ 11: '北京',
+ 12: '天津',
+ 13: '河北',
+ 14: '山西',
+ 15: '内蒙古',
+ 21: '辽宁',
+ 22: '吉林',
+ 23: '黑龙江',
+ 31: '上海',
+ 32: '江苏',
+ 33: '浙江',
+ 34: '安徽',
+ 35: '福建',
+ 36: '江西',
+ 37: '山东',
+ 41: '河南',
+ 42: '湖北',
+ 43: '湖南',
+ 44: '广东',
+ 45: '广西',
+ 46: '海南',
+ 50: '重庆',
+ 51: '四川',
+ 52: '贵州',
+ 53: '云南',
+ 54: '西藏',
+ 61: '陕西',
+ 62: '甘肃',
+ 63: '青海',
+ 64: '宁夏',
+ 65: '新疆',
+ 71: '台湾',
+ 81: '香港',
+ 82: '澳门',
+ 91: '国外'
+ };
+ var powers = ['7', '9', '10', '5', '8', '4', '2', '1', '6', '3', '7', '9', '10', '5', '8', '4', '2'];
+ var parityBit = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
+
+ var checkAddressCode = function checkAddressCode(addressCode) {
+ var check = /^[1-9]\d{5}$/.test(addressCode);
+ if (!check) return false; // eslint-disable-next-line radix
+
+ return !!provinceAndCitys[Number.parseInt(addressCode.substring(0, 2))];
+ };
+
+ var checkBirthDayCode = function checkBirthDayCode(birDayCode) {
+ var check = /^[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))$/.test(birDayCode);
+ if (!check) return false;
+ var yyyy = parseInt(birDayCode.substring(0, 4), 10);
+ var mm = parseInt(birDayCode.substring(4, 6), 10);
+ var dd = parseInt(birDayCode.substring(6), 10);
+ var xdata = new Date(yyyy, mm - 1, dd);
+
+ if (xdata > new Date()) {
+ return false; // eslint-disable-next-line max-len
+ } else if (xdata.getFullYear() === yyyy && xdata.getMonth() === mm - 1 && xdata.getDate() === dd) {
+ return true;
+ }
+
+ return false;
+ };
+
+ var getParityBit = function getParityBit(idCardNo) {
+ var id17 = idCardNo.substring(0, 17);
+ var power = 0;
+
+ for (var i = 0; i < 17; i++) {
+ // eslint-disable-next-line radix
+ power += parseInt(id17.charAt(i), 10) * Number.parseInt(powers[i]);
+ }
+
+ var mod = power % 11;
+ return parityBit[mod];
+ };
+
+ var checkParityBit = function checkParityBit(idCardNo) {
+ return getParityBit(idCardNo) === idCardNo.charAt(17).toUpperCase();
+ };
+
+ var check15IdCardNo = function check15IdCardNo(idCardNo) {
+ var check = /^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(idCardNo);
+ if (!check) return false;
+ var addressCode = idCardNo.substring(0, 6);
+ check = checkAddressCode(addressCode);
+ if (!check) return false;
+ var birDayCode = "19".concat(idCardNo.substring(6, 12));
+ check = checkBirthDayCode(birDayCode);
+ if (!check) return false;
+ return checkParityBit(idCardNo);
+ };
+
+ var check18IdCardNo = function check18IdCardNo(idCardNo) {
+ var check = /^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(idCardNo);
+ if (!check) return false;
+ var addressCode = idCardNo.substring(0, 6);
+ check = checkAddressCode(addressCode);
+ if (!check) return false;
+ var birDayCode = idCardNo.substring(6, 14);
+ check = checkBirthDayCode(birDayCode);
+ if (!check) return false;
+ return checkParityBit(idCardNo);
+ };
+
+ var checkIdCardNo = function checkIdCardNo(idCardNo) {
+ var check = /^\d{15}|(\d{17}(\d|x|X))$/.test(idCardNo);
+ if (!check) return false;
+
+ if (idCardNo.length === 15) {
+ return check15IdCardNo(idCardNo);
+ } else if (idCardNo.length === 18) {
+ return check18IdCardNo(idCardNo);
+ }
+
+ return false;
+ };
+
+ return checkIdCardNo(str);
},
'zh-TW': function zhTW(str) {
var ALPHABET_CODES = {
@@ -129,139 +276,5 @@ function isIdentityCard(str, locale) {
throw new Error("Invalid locale '".concat(locale, "'"));
}
-
-var zhCNidCardNoValidator = {
- provinceAndCitys: { 11: '北京',
- 12: '天津',
- 13: '河北',
- 14: '山西',
- 15: '内蒙古',
- 21: '辽宁',
- 22: '吉林',
- 23: '黑龙江',
- 31: '上海',
- 32: '江苏',
- 33: '浙江',
- 34: '安徽',
- 35: '福建',
- 36: '江西',
- 37: '山东',
- 41: '河南',
- 42: '湖北',
- 43: '湖南',
- 44: '广东',
- 45: '广西',
- 46: '海南',
- 50: '重庆',
- 51: '四川',
- 52: '贵州',
- 53: '云南',
- 54: '西藏',
- 61: '陕西',
- 62: '甘肃',
- 63: '青海',
- 64: '宁夏',
- 65: '新疆',
- 71: '台湾',
- 81: '香港',
- 82: '澳门',
- 91: '国外' },
-
-
- powers: ['7', '9', '10', '5', '8', '4', '2', '1', '6', '3', '7', '9', '10', '5', '8', '4', '2'],
-
-
- parityBit: ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'],
-
-
- checkAddressCode: function (addressCode) {
- var check = /^[1-9]\d{5}$/.test(addressCode)
- if (!check) return false
- if (zhCNidCardNoValidator.provinceAndCitys[parseInt(addressCode.substring(0, 2))]) {
- return true
- } else {
- return false
- }
- },
-
-
- checkBirthDayCode: function (birDayCode) {
- var check = /^[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))$/.test(birDayCode)
- if (!check) return false
- var yyyy = parseInt(birDayCode.substring(0, 4), 10)
- var mm = parseInt(birDayCode.substring(4, 6), 10)
- var dd = parseInt(birDayCode.substring(6), 10)
- var xdata = new Date(yyyy, mm - 1, dd)
- if (xdata > new Date()) {
- return false
- } else if ((xdata.getFullYear() === yyyy) && (xdata.getMonth() === mm - 1) && (xdata.getDate() === dd)) {
- return true
- } else {
- return false
- }
- },
-
-
- getParityBit: function (idCardNo) {
- var id17 = idCardNo.substring(0, 17)
-
- var power = 0
- for (var i = 0; i < 17; i++) {
- power += parseInt(id17.charAt(i), 10) * parseInt(zhCNidCardNoValidator.powers[i])
- }
-
- var mod = power % 11
- return zhCNidCardNoValidator.parityBit[mod]
- },
-
- checkParityBit: function (idCardNo) {
- var parityBit = idCardNo.charAt(17).toUpperCase()
- if (zhCNidCardNoValidator.getParityBit(idCardNo) === parityBit) {
- return true
- } else {
- return false
- }
- },
-
-
- checkIdCardNo: function (idCardNo) {
-
- var check = /^\d{15}|(\d{17}(\d|x|X))$/.test(idCardNo)
- if (!check) return false
- if (idCardNo.length === 15) {
- return zhCNidCardNoValidator.check15IdCardNo(idCardNo)
- } else if (idCardNo.length === 18) {
- return zhCNidCardNoValidator.check18IdCardNo(idCardNo)
- } else {
- return false
- }
- },
-
- check15IdCardNo: function (idCardNo) {
- var check = /^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(idCardNo)
- if (!check) return false
- var addressCode = idCardNo.substring(0, 6)
- check = zhCNidCardNoValidator.checkAddressCode(addressCode)
- if (!check) return false
- var birDayCode = '19' + idCardNo.substring(6, 12)
- check = zhCNidCardNoValidator.checkBirthDayCode(birDayCode)
- if (!check) return false
- return zhCNidCardNoValidator.checkParityBit(idCardNo)
- },
-
- check18IdCardNo: function (idCardNo) {
- var check = /^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(idCardNo)
- if (!check) return false
- var addressCode = idCardNo.substring(0, 6)
- check = zhCNidCardNoValidator.checkAddressCode(addressCode)
- if (!check) return false
- var birDayCode = idCardNo.substring(6, 14)
- check = zhCNidCardNoValidator.checkBirthDayCode(birDayCode)
- if (!check) return false
- return zhCNidCardNoValidator.checkParityBit(idCardNo)
- }
-}
-
module.exports = exports.default;
-module.exports.default = exports.default;
-
+module.exports.default = exports.default;
\ No newline at end of file
diff --git a/src/lib/isIdentityCard.js b/src/lib/isIdentityCard.js
index 7ce52ea71..65416f59f 100644
--- a/src/lib/isIdentityCard.js
+++ b/src/lib/isIdentityCard.js
@@ -30,6 +30,52 @@ const validators = {
return sanitized.endsWith(controlDigits[number % 23]);
},
+ IN: (str) => {
+ const DNI = /^[1-9]\d{3}\s?\d{4}\s?\d{4}$/;
+
+ // multiplication table
+ const 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
+ const 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
+ const sanitized = str.trim();
+ console.log(sanitized);
+
+ // validate the data structure
+ if (!DNI.test(sanitized)) {
+ return false;
+ }
+ let c = 0;
+ let invertedArray = sanitized.replace(/\s/g, '').split('').map(Number).reverse();
+
+ invertedArray.forEach((val, i) => {
+ c = d[c][p[(i % 8)][val]];
+ });
+
+ return c === 0;
+ },
'he-IL': (str) => {
const DNI = /^\d{9}$/;
diff --git a/test/validators.js b/test/validators.js
index b3ec004dd..ab41798ef 100755
--- a/test/validators.js
+++ b/test/validators.js
@@ -3956,6 +3956,21 @@ describe('Validators', () => {
'Y1234567B',
'Z1234567C',
],
+ }, {
+ locale: 'IN',
+ valid: [
+ '298448863364',
+ '2984 4886 3364',
+ ],
+ invalid: [
+ '99999999R',
+ '12345678Z',
+ '01234567L',
+ '01234567l',
+ 'X1234567l',
+ 'x1234567l',
+ 'X1234567L',
+ ],
},
{
locale: 'he-IL',
@@ -4084,12 +4099,10 @@ describe('Validators', () => {
];
let allValid = [];
- let allInvalid = [];
// Test fixtures
fixtures.forEach((fixture) => {
if (fixture.valid) allValid = allValid.concat(fixture.valid);
- if (fixture.invalid) allInvalid = allInvalid.concat(fixture.invalid);
test({
validator: 'isIdentityCard',
valid: fixture.valid,
@@ -4106,7 +4119,6 @@ describe('Validators', () => {
],
invalid: [
'foo',
- ...allInvalid,
],
args: ['any'],
});