diff --git a/README.md b/README.md
index 3329931e0..08cbe643b 100644
--- a/README.md
+++ b/README.md
@@ -127,7 +127,7 @@ Validator | Description
**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).
**isIPRange(str [, version])** | check if the string is an IP Range (version 4 or 6).
-**isISBN(str [, version])** | check if the string is an [ISBN][ISBN] (version 10 or 13).
+**isISBN(str [, options])** | check if the string is an [ISBN][ISBN].
`options` is an object that has no default.
**Options:**
`version`: ISBN version to compare to. Accepted values are '10' and '13'. If none provided, both will be tested.
**isISIN(str)** | check if the string is an [ISIN][ISIN] (stock/security identifier).
**isISO6391(str)** | check if the string is a valid [ISO 639-1][ISO 639-1] language code.
**isISO8601(str [, options])** | check if the string is a valid [ISO 8601][ISO 8601] date.
`options` is an object which defaults to `{ strict: false, strictSeparator: false }`. If `strict` is true, date strings with invalid dates like `2009-02-29` will be invalid. If `strictSeparator` is true, date strings with date and time separated by anything other than a T will be invalid.
diff --git a/src/lib/isISBN.js b/src/lib/isISBN.js
index c66c4c991..4499c59a0 100644
--- a/src/lib/isISBN.js
+++ b/src/lib/isISBN.js
@@ -1,43 +1,55 @@
import assertString from './util/assertString';
-const isbn10Maybe = /^(?:[0-9]{9}X|[0-9]{10})$/;
-const isbn13Maybe = /^(?:[0-9]{13})$/;
+const possibleIsbn10 = /^(?:[0-9]{9}X|[0-9]{10})$/;
+const possibleIsbn13 = /^(?:[0-9]{13})$/;
const factor = [1, 3];
-export default function isISBN(str, version = '') {
- assertString(str);
- version = String(version);
- if (!version) {
- return isISBN(str, 10) || isISBN(str, 13);
+export default function isISBN(isbn, options) {
+ assertString(isbn);
+
+ // For backwards compatibility:
+ // isISBN(str [, version]), i.e. `options` could be used as argument for the legacy `version`
+ const version = String(options?.version || options);
+
+ if (!(options?.version || options)) {
+ return isISBN(isbn, { version: 10 }) || isISBN(isbn, { version: 13 });
}
- const sanitized = str.replace(/[\s-]+/g, '');
+
+ const sanitizedIsbn = isbn.replace(/[\s-]+/g, '');
+
let checksum = 0;
- let i;
+
if (version === '10') {
- if (!isbn10Maybe.test(sanitized)) {
+ if (!possibleIsbn10.test(sanitizedIsbn)) {
return false;
}
- for (i = 0; i < 9; i++) {
- checksum += (i + 1) * sanitized.charAt(i);
+
+ for (let i = 0; i < version - 1; i++) {
+ checksum += (i + 1) * sanitizedIsbn.charAt(i);
}
- if (sanitized.charAt(9) === 'X') {
+
+ if (sanitizedIsbn.charAt(9) === 'X') {
checksum += 10 * 10;
} else {
- checksum += 10 * sanitized.charAt(9);
+ checksum += 10 * sanitizedIsbn.charAt(9);
}
+
if ((checksum % 11) === 0) {
- return !!sanitized;
+ return true;
}
} else if (version === '13') {
- if (!isbn13Maybe.test(sanitized)) {
+ if (!possibleIsbn13.test(sanitizedIsbn)) {
return false;
}
- for (i = 0; i < 12; i++) {
- checksum += factor[i % 2] * sanitized.charAt(i);
+
+ for (let i = 0; i < 12; i++) {
+ checksum += factor[i % 2] * sanitizedIsbn.charAt(i);
}
- if (sanitized.charAt(12) - ((10 - (checksum % 10)) % 10) === 0) {
- return !!sanitized;
+
+ if (sanitizedIsbn.charAt(12) - ((10 - (checksum % 10)) % 10) === 0) {
+ return true;
}
}
+
return false;
}
diff --git a/test/validators.test.js b/test/validators.test.js
index 79dcb1008..79a3fa9ff 100644
--- a/test/validators.test.js
+++ b/test/validators.test.js
@@ -5860,58 +5860,6 @@ describe('Validators', () => {
});
});
- it('should validate ISBNs', () => {
- test({
- validator: 'isISBN',
- args: [10],
- valid: [
- '3836221195', '3-8362-2119-5', '3 8362 2119 5',
- '1617290858', '1-61729-085-8', '1 61729 085-8',
- '0007269706', '0-00-726970-6', '0 00 726970 6',
- '3423214120', '3-423-21412-0', '3 423 21412 0',
- '340101319X', '3-401-01319-X', '3 401 01319 X',
- ],
- invalid: [
- '3423214121', '3-423-21412-1', '3 423 21412 1',
- '978-3836221191', '9783836221191',
- '123456789a', 'foo', '',
- ],
- });
- test({
- validator: 'isISBN',
- args: [13],
- valid: [
- '9783836221191', '978-3-8362-2119-1', '978 3 8362 2119 1',
- '9783401013190', '978-3401013190', '978 3401013190',
- '9784873113685', '978-4-87311-368-5', '978 4 87311 368 5',
- ],
- invalid: [
- '9783836221190', '978-3-8362-2119-0', '978 3 8362 2119 0',
- '3836221195', '3-8362-2119-5', '3 8362 2119 5',
- '01234567890ab', 'foo', '',
- ],
- });
- test({
- validator: 'isISBN',
- valid: [
- '340101319X',
- '9784873113685',
- ],
- invalid: [
- '3423214121',
- '9783836221190',
- ],
- });
- test({
- validator: 'isISBN',
- args: ['foo'],
- invalid: [
- '340101319X',
- '9784873113685',
- ],
- });
- });
-
it('should validate EANs', () => {
test({
validator: 'isEAN',
diff --git a/test/validators/isISBN.test.js b/test/validators/isISBN.test.js
new file mode 100644
index 000000000..99fb2e014
--- /dev/null
+++ b/test/validators/isISBN.test.js
@@ -0,0 +1,109 @@
+import test from '../testFunctions';
+
+describe('isISBN', () => {
+ it('should validate ISBNs', () => {
+ test({
+ validator: 'isISBN',
+ args: [{ version: 10 }],
+ valid: [
+ '3836221195', '3-8362-2119-5', '3 8362 2119 5',
+ '1617290858', '1-61729-085-8', '1 61729 085-8',
+ '0007269706', '0-00-726970-6', '0 00 726970 6',
+ '3423214120', '3-423-21412-0', '3 423 21412 0',
+ '340101319X', '3-401-01319-X', '3 401 01319 X',
+ ],
+ invalid: [
+ '3423214121', '3-423-21412-1', '3 423 21412 1',
+ '978-3836221191', '9783836221191',
+ '123456789a', 'foo', '',
+ ],
+ });
+ test({
+ validator: 'isISBN',
+ args: [{ version: 13 }],
+ valid: [
+ '9783836221191', '978-3-8362-2119-1', '978 3 8362 2119 1',
+ '9783401013190', '978-3401013190', '978 3401013190',
+ '9784873113685', '978-4-87311-368-5', '978 4 87311 368 5',
+ ],
+ invalid: [
+ '9783836221190', '978-3-8362-2119-0', '978 3 8362 2119 0',
+ '3836221195', '3-8362-2119-5', '3 8362 2119 5',
+ '01234567890ab', 'foo', '',
+ ],
+ });
+ test({
+ validator: 'isISBN',
+ valid: [
+ '340101319X',
+ '9784873113685',
+ ],
+ invalid: [
+ '3423214121',
+ '9783836221190',
+ ],
+ });
+ test({
+ validator: 'isISBN',
+ args: [{ version: 'foo' }],
+ invalid: [
+ '340101319X',
+ '9784873113685',
+ ],
+ });
+ });
+
+ describe('(legacy syntax)', () => {
+ it('should validate ISBNs', () => {
+ test({
+ validator: 'isISBN',
+ args: [10],
+ valid: [
+ '3836221195', '3-8362-2119-5', '3 8362 2119 5',
+ '1617290858', '1-61729-085-8', '1 61729 085-8',
+ '0007269706', '0-00-726970-6', '0 00 726970 6',
+ '3423214120', '3-423-21412-0', '3 423 21412 0',
+ '340101319X', '3-401-01319-X', '3 401 01319 X',
+ ],
+ invalid: [
+ '3423214121', '3-423-21412-1', '3 423 21412 1',
+ '978-3836221191', '9783836221191',
+ '123456789a', 'foo', '',
+ ],
+ });
+ test({
+ validator: 'isISBN',
+ args: [13],
+ valid: [
+ '9783836221191', '978-3-8362-2119-1', '978 3 8362 2119 1',
+ '9783401013190', '978-3401013190', '978 3401013190',
+ '9784873113685', '978-4-87311-368-5', '978 4 87311 368 5',
+ ],
+ invalid: [
+ '9783836221190', '978-3-8362-2119-0', '978 3 8362 2119 0',
+ '3836221195', '3-8362-2119-5', '3 8362 2119 5',
+ '01234567890ab', 'foo', '',
+ ],
+ });
+ test({
+ validator: 'isISBN',
+ valid: [
+ '340101319X',
+ '9784873113685',
+ ],
+ invalid: [
+ '3423214121',
+ '9783836221190',
+ ],
+ });
+ test({
+ validator: 'isISBN',
+ args: ['foo'],
+ invalid: [
+ '340101319X',
+ '9784873113685',
+ ],
+ });
+ });
+ });
+});