Functional Weave
Code in TypeScript

validation.isbn@1.0.0

README.md

2,748 bytes · view raw

# validation.isbn

Checks an International Standard Book Number in either form and hands back
both. The answer is always normalised to the ISBN-13, because that is the form
every ISBN has had since 2007 and the one to store and compare: the ISBN-10
0-306-40615-2 and the ISBN-13 978-0-306-40615-7 are the same book.

TWO CHECK DIGITS, TWO ALGORITHMS:

- ISBN-10: weight the ten characters 10, 9, 8 ... 1 and the sum must be a
  multiple of 11. The check digit can therefore be 10, written `X` (or `x`),
  and `X` is allowed only in that last position.
- ISBN-13: the GS1/EAN-13 rule - weights 1, 3, 1, 3 ... from the left, and the
  check digit brings the sum to a multiple of 10. The first three digits must
  be 978 or 979 ("Bookland"); any other EAN-13 is a barcode, not an ISBN.

CONVERSION is where naive code goes wrong: the two check digits are computed
differently, so converting means recomputing, never copying the old check
digit across. An ISBN-10 becomes `978` + its first nine digits + a fresh EAN
check digit. An ISBN-13 has an ISBN-10 only when it starts with 978; `979`
ISBNs (issued since the 978 range began running out) have none, and `isbn10`
is null for them.

ACCEPTED INPUT: ASCII digits and `X`, with ASCII spaces and hyphens ignored
anywhere (hyphen positions depend on the registration group and publisher, so
they are not checked), and an optional leading `ISBN` in any case, optionally
followed by a colon: `ISBN 978-0-306-40615-7`, `isbn:0306406152`. Forms such as
`ISBN-13:` are not recognised.

| reason            | meaning                                                          |
|-------------------|------------------------------------------------------------------|
| `empty`           | nothing left after removing separators and the prefix, or not a string |
| `bad-character`   | a character other than a digit, `X`, space or hyphen             |
| `bad-length`      | not 10 or 13 characters                                          |
| `bad-format`      | an `X` anywhere but the last place of an ISBN-10                 |
| `bad-prefix`      | a 13-digit number that does not start with 978 or 979            |
| `bad-check-digit` | the check digit does not match                                   |

The checks run in that order; the first failure is the reason. Validators
answer rather than throw.

A valid ISBN is well formed, not necessarily assigned: only the ISBN agency's
records say whether a book carries it. Hyphenation (splitting into group,
publisher, title and check) needs the International ISBN Agency's range table
and is out of scope.

Source: International ISBN Agency, ISBN Users' Manual, 7th edition, sections
5 and 9 (https://www.isbn-international.org/content/isbn-users-manual).