-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(isEAN): implement isEAN validator (#1244)
* feat(isEAN): implement isEAN validator * add testcase to cover 0 as EAN check digit * modify EAN regex to avoid lookbehind assertions
- Loading branch information
1 parent
46585ef
commit fc253c4
Showing
8 changed files
with
244 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
"use strict"; | ||
|
||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = isEAN; | ||
|
||
var _assertString = _interopRequireDefault(require("./util/assertString")); | ||
|
||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
|
||
/** | ||
* 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. | ||
* EAN consists of: | ||
* GS1 prefix, manufacturer code, product code and check digit | ||
* Reference: https://en.wikipedia.org/wiki/International_Article_Number | ||
*/ | ||
|
||
/** | ||
* Define EAN Lenghts; 8 for EAN-8; 13 for EAN-13 | ||
* and Regular Expression for valid EANs (EAN-8, EAN-13), | ||
* with exact numberic matching of 8 or 13 digits [0-9] | ||
*/ | ||
var LENGTH_EAN_8 = 8; | ||
var validEanRegex = /^(\d{8}|\d{13})$/; | ||
/** | ||
* 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) { | ||
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) { | ||
var checksum = ean.slice(0, -1).split('').map(function (char, index) { | ||
return Number(char) * getPositionWeightThroughLengthAndIndex(ean.length, index); | ||
}).reduce(function (acc, partialSum) { | ||
return acc + partialSum; | ||
}, 0); | ||
var remainder = 10 - checksum % 10; | ||
return remainder < 10 ? remainder : 0; | ||
} | ||
/** | ||
* Check if string is valid EAN: | ||
* Matches EAN-8/EAN-13 regex | ||
* Has valid check digit. | ||
* | ||
* @param {string} str | ||
* @return {boolean} | ||
*/ | ||
|
||
|
||
function isEAN(str) { | ||
(0, _assertString.default)(str); | ||
var actualCheckDigit = Number(str.slice(-1)); | ||
return validEanRegex.test(str) && actualCheckDigit === calculateCheckDigit(str); | ||
} | ||
|
||
module.exports = exports.default; | ||
module.exports.default = exports.default; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/** | ||
* 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. | ||
* EAN consists of: | ||
* GS1 prefix, manufacturer code, product code and check digit | ||
* Reference: https://en.wikipedia.org/wiki/International_Article_Number | ||
*/ | ||
|
||
import assertString from './util/assertString'; | ||
|
||
/** | ||
* Define EAN Lenghts; 8 for EAN-8; 13 for EAN-13 | ||
* and Regular Expression for valid EANs (EAN-8, EAN-13), | ||
* with exact numberic matching of 8 or 13 digits [0-9] | ||
*/ | ||
const LENGTH_EAN_8 = 8; | ||
const validEanRegex = /^(\d{8}|\d{13})$/; | ||
|
||
|
||
/** | ||
* 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) { | ||
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 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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.