UNPKG

@shippack/isbn-verify

Version:

Verify ISBN string format and check digit.

174 lines (155 loc) 4.65 kB
interface isOption { check_digit?: boolean; // Verify format including check digit } /** * ISBN Verify */ export default class { #isbnNoHyphens: string; // ハイフンなしの ISBN #isbn13 = false; // 現行規格(13桁)の ISBN か #isbn10 = false; // 旧規格(10桁)の ISBN か /** * @param {string} isbn - ISBN value to check * @param {boolean} strict - Strict mode. If `true`, syntax without hyphens is an error. If not specified, it defaults to `false` */ constructor(isbn: string, strict = false) { const isbnNoHyphens = isbn.replace(/-/g, ''); this.#isbnNoHyphens = isbnNoHyphens; if (strict) { const length = isbn.length; if (length === 17 && /^(978|979)-\d{1,5}-\d{1,7}-\d{1,7}-\d$/.test(isbn)) { this.#isbn13 = true; } else if (length === 13 && /^\d{1,5}-\d{1,7}-\d{1,7}-[\dX]$/.test(isbn)) { this.#isbn10 = true; } } else { if (!isbn.includes('--')) { if (/^(978|979)\d{10}$/.test(isbnNoHyphens)) { if (/^\d[\d-]{11,15}\d$/.test(isbn)) { this.#isbn13 = true; } } else if (/^\d{9}[\dX]$/.test(isbnNoHyphens)) { if (/^\d[\d-]{8,11}[\dX]$/.test(isbn)) { this.#isbn10 = true; } } } } } /** * Alias of `verifyCheckDigit()` * * @returns {boolean} `true` if both format and check digit are correct */ isValid(): boolean { return this.verifyCheckDigit(); } /** * Whether it is a 13-digit ISBN * * @param {isOption} options - Specifies characteristics about the check item. * * @returns {boolean} `true` for current standard (13 digit) ISBN */ isIsbn13(options?: isOption): boolean { if (options !== undefined && options.check_digit) { return this.#isbn13 && this.verifyCheckDigit(); } return this.#isbn13; } /** * Whether it is a 10-digit ISBN * * @param {isOption} options - Specifies characteristics about the check item. * * @returns {boolean} `true` for old standard (10 digit) ISBN */ isIsbn10(options?: isOption): boolean { if (options !== undefined && options.check_digit) { return this.#isbn10 && this.verifyCheckDigit(); } return this.#isbn10; } /** * Verify format (do not verify check digit) * * @returns {boolean} `true` if the format is correct */ verifyFormat(): boolean { return this.#isbn13 || this.#isbn10; } /** * Verify format including check digit (not necessarily applicable publication) * * @returns {boolean} `true` if both format and check digit are correct */ verifyCheckDigit(): boolean { if (this.#isbn13) { const isbnNoHyphens = this.#isbnNoHyphens; return isbnNoHyphens.substring(12) === this._getCheckDigit13(isbnNoHyphens); } else if (this.#isbn10) { const isbnNoHyphens = this.#isbnNoHyphens; return isbnNoHyphens.substring(9) === this._getCheckDigit10(isbnNoHyphens); } return false; } /** * ISBN-13 のチェックデジットを取得する * * @param {string} isbnNoHyphens - ハイフンなしの ISBN * * @returns {string} チェックデジット */ private _getCheckDigit13(isbnNoHyphens: string): string { const checkDigit = String( 10 - ((Number(isbnNoHyphens.substring(0, 1)) + Number(isbnNoHyphens.substring(1, 2)) * 3 + Number(isbnNoHyphens.substring(2, 3)) + Number(isbnNoHyphens.substring(3, 4)) * 3 + Number(isbnNoHyphens.substring(4, 5)) + Number(isbnNoHyphens.substring(5, 6)) * 3 + Number(isbnNoHyphens.substring(6, 7)) + Number(isbnNoHyphens.substring(7, 8)) * 3 + Number(isbnNoHyphens.substring(8, 9)) + Number(isbnNoHyphens.substring(9, 10)) * 3 + Number(isbnNoHyphens.substring(10, 11)) + Number(isbnNoHyphens.substring(11, 12)) * 3) % 10) ); switch (checkDigit) { case '10': return '0'; } return checkDigit; } /** * ISBN-10 のチェックデジットを取得する * * @param {string} isbnNoHyphens - ハイフンなしの ISBN * * @returns {string} チェックデジット */ private _getCheckDigit10(isbnNoHyphens: string): string { const checkDigit = String( 11 - ((Number(isbnNoHyphens.substring(0, 1)) * 10 + Number(isbnNoHyphens.substring(1, 2)) * 9 + Number(isbnNoHyphens.substring(2, 3)) * 8 + Number(isbnNoHyphens.substring(3, 4)) * 7 + Number(isbnNoHyphens.substring(4, 5)) * 6 + Number(isbnNoHyphens.substring(5, 6)) * 5 + Number(isbnNoHyphens.substring(6, 7)) * 4 + Number(isbnNoHyphens.substring(7, 8)) * 3 + Number(isbnNoHyphens.substring(8, 9)) * 2) % 11) ); switch (checkDigit) { case '10': return 'X'; case '11': return '0'; } return checkDigit; } }