-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
Copy pathisEAN.js
74 lines (65 loc) · 2.1 KB
/
isEAN.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
* The most commonly used EAN standard is
* the thirteen-digit EAN-13, while the
* less commonly used 8-digit EAN-8 barcode was
* introduced for use on small packages.
* Also EAN/UCC-14 is used for Grouping of individual
* trade items above unit level(Intermediate, Carton or Pallet).
* For more info about EAN-14 checkout: https://www.gtin.info/itf-14-barcodes/
* EAN consists of:
* GS1 prefix, manufacturer code, product code and check digit
* Reference: https://en.wikipedia.org/wiki/International_Article_Number
* Reference: https://www.gtin.info/
*/
import assertString from './util/assertString';
/**
* Define EAN Lenghts; 8 for EAN-8; 13 for EAN-13; 14 for EAN-14
* and Regular Expression for valid EANs (EAN-8, EAN-13, EAN-14),
* with exact numberic matching of 8 or 13 or 14 digits [0-9]
*/
const LENGTH_EAN_8 = 8;
const LENGTH_EAN_14 = 14;
const validEanRegex = /^(\d{8}|\d{13}|\d{14})$/;
/**
* Get position weight given:
* EAN length and digit index/position
*
* @param {number} length
* @param {number} index
* @return {number}
*/
function getPositionWeightThroughLengthAndIndex(length, index) {
if (length === LENGTH_EAN_8 || length === LENGTH_EAN_14) {
return (index % 2 === 0) ? 3 : 1;
}
return (index % 2 === 0) ? 1 : 3;
}
/**
* Calculate EAN Check Digit
* Reference: https://en.wikipedia.org/wiki/International_Article_Number#Calculation_of_checksum_digit
*
* @param {string} ean
* @return {number}
*/
function calculateCheckDigit(ean) {
const checksum = ean
.slice(0, -1)
.split('')
.map((char, index) => Number(char) * getPositionWeightThroughLengthAndIndex(ean.length, index))
.reduce((acc, partialSum) => acc + partialSum, 0);
const remainder = 10 - (checksum % 10);
return remainder < 10 ? remainder : 0;
}
/**
* Check if string is valid EAN:
* Matches EAN-8/EAN-13/EAN-14 regex
* Has valid check digit.
*
* @param {string} str
* @return {boolean}
*/
export default function isEAN(str) {
assertString(str);
const actualCheckDigit = Number(str.slice(-1));
return validEanRegex.test(str) && actualCheckDigit === calculateCheckDigit(str);
}