@point-of-sale/barcode-parser
Version:
[](https://www.npmjs.com/@point-of-sale/barcode-parser) 
2,530 lines (2,394 loc) • 47.9 kB
JavaScript
'use strict';
class Aim {
static decode(aim, value) {
let data = {
symbology: null
};
let code = aim[1];
let modifier = aim[2];
switch (code) {
case 'A': data.symbology = 'code39'; break;
case 'B': data.symbology = 'telepen'; break;
case 'C':
data.symbology = 'code128';
if (modifier === '1') {
data.symbology = 'gs1-128';
data.fnc1 = 1;
}
break;
case 'D': data.symbology = 'code1'; break;
case 'E':
if (value.length === 13) {
data.symbology = 'ean13';
}
else if (value.length === 12) {
data.symbology = 'upca';
}
else if (value.length === 8) {
if (modifier === '4') {
data.symbology = 'ean8';
}
else {
data.symbology = 'upce';
}
}
break;
case 'F': data.symbology = 'codabar'; break;
case 'G': data.symbology = 'code93'; break;
case 'H': data.symbology = 'code11'; break;
case 'I': data.symbology = 'interleaved-2-of-5'; break;
case 'K': data.symbology = 'code16k'; break;
case 'L': data.symbology = 'pdf417'; break;
case 'M': data.symbology = 'msi'; break;
case 'N': data.symbology = 'anker'; break;
case 'O':
if (modifier === '4' || modifier === '5') {
data.symbology = 'codablock-f';
}
if (modifier === '6') {
data.symbology = 'codablock-a';
}
break;
case 'P': data.symbology = 'plessey'; break;
case 'R': data.symbology = 'straight-2-of-5'; break;
case 'S': data.symbology = 'straight-2-of-5'; break;
case 'Q':
data.symbology = 'qr-code';
if (modifier === '0') {
data.model = 1;
}
else {
data.model = 2;
if (modifier === '3' || modifier === '4') {
data.fnc1 = 1;
}
if (modifier === '5' || modifier === '6') {
data.fnc1 = 2;
}
}
break;
case 'U': data.symbology = 'maxicode'; break;
case 'X':
/* Other barcode */
/* According to Honeywell, this is the identifier for Bookland/ISSN EAN-13 */
if (modifier === '0') {
data.symbology = 'ean13';
}
/* Zebra / Motorola uses it for duplicate identifiers already defined by AIM */
else {
switch(modifier) {
case '9': data.symbology = 'ean13'; break;
case 'C': data.symbology = 'ean8'; break;
case 'g': data.symbology = 'upca'; break;
case 'k': data.symbology = 'upce'; break;
case 'r': data.symbology = 'gs1-databar-omni'; break;
case 's': data.symbology = 'gs1-databar-limited'; break;
case 't': data.symbology = 'gs1-databar-expanded'; break;
case 'V': data.symbology = 'pdf417'; break;
case 'S': data.symbology = 'qr-code-micro'; break;
}
}
break;
case 'c': data.symbology = 'channel-code'; break;
case 'd':
data.symbology = 'data-matrix';
if (modifier === '2' || modifier === '5') {
data.fnc1 = 1;
}
if (modifier === '3' || modifier === '6') {
data.fnc1 = 2;
}
break;
case 'e': data.symbology = 'gs1-databar-omni'; break;
case 'h': data.symbology = 'chinese-sensible-code'; break;
case 'o': data.symbology = 'ocr'; break;
case 'p': data.symbology = 'posi-code'; break;
case 's': data.symbology = 'super-code'; break;
case 'z':
data.symbology = 'aztec-code';
if (modifier === '1' || modifier === '4' || modifier === '7' || modifier === 'A') {
data.fnc1 = 1;
}
if (modifier === '2' || modifier === '5' || modifier === '8' || modifier === 'B') {
data.fnc1 = true; /* Following an initial letter or pair of digits */
}
break;
}
return data;
}
}
const labelValues = [
[
"SSCC",
[
"00"
]
],
[
"GTIN",
[
"01"
]
],
[
"CONTENT",
[
"02"
]
],
[
"BATCH/LOT",
[
"10"
]
],
[
"PROD DATE",
[
"11"
]
],
[
"DUE DATE",
[
"12"
]
],
[
"PACK DATE",
[
"13"
]
],
[
"BEST BEFORE or BEST BY",
[
"15"
]
],
[
"SELL BY",
[
"16"
]
],
[
"USE BY OR EXPIRY",
[
"17"
]
],
[
"VARIANT",
[
"20"
]
],
[
"SERIAL",
[
"21"
]
],
[
"CPV",
[
"22"
]
],
[
"VAR. COUNT",
[
"30"
]
],
[
"COUNT",
[
"37"
]
],
[
"INTERNAL",
[
"90",
"91",
"92",
"93",
"94",
"95",
"96",
"97",
"98",
"99"
]
],
[
"ADDITIONAL ID",
[
"240"
]
],
[
"CUST. PART NO.",
[
"241"
]
],
[
"MTO VARIANT",
[
"242"
]
],
[
"PCN",
[
"243"
]
],
[
"SECONDARY SERIAL",
[
"250"
]
],
[
"REF. TO SOURCE ",
[
"251"
]
],
[
"GDTI",
[
"253"
]
],
[
"GLN EXTENSION COMPONENT",
[
"254"
]
],
[
"GCN",
[
"255"
]
],
[
"ORDER NUMBER",
[
"400"
]
],
[
"GINC",
[
"401"
]
],
[
"GSIN",
[
"402"
]
],
[
"ROUTE",
[
"403"
]
],
[
"SHIP TO LOC",
[
"410"
]
],
[
"BILL TO ",
[
"411"
]
],
[
"PURCHASE FROM",
[
"412"
]
],
[
"SHIP FOR LOC",
[
"413"
]
],
[
"LOC No",
[
"414"
]
],
[
"PAY TO",
[
"415"
]
],
[
"PROD/SERV LOC",
[
"416"
]
],
[
"SHIP TO POST",
[
"420",
"421"
]
],
[
"ORIGIN",
[
"422"
]
],
[
"COUNTRY - INITIAL PROCESS.",
[
"423"
]
],
[
"COUNTRY - PROCESS.",
[
"424"
]
],
[
"COUNTRY - DISASSEMBLY",
[
"425"
]
],
[
"COUNTRY - FULL PROCESS",
[
"426"
]
],
[
"ORIGIN SUBDIVISION",
[
"427"
]
],
[
"NHRN PZN",
[
"710"
]
],
[
"NHRN CIP",
[
"711"
]
],
[
"NHRN CN",
[
"712"
]
],
[
"NHRN DRN",
[
"713"
]
],
[
"NHRN AIM",
[
"714"
]
],
[
"NET WEIGHT (kg)",
[
"3100",
"3101",
"3102",
"3103",
"3104",
"3105"
]
],
[
"LENGTH (m)",
[
"3110",
"3111",
"3112",
"3113",
"3114",
"3115"
]
],
[
"WIDTH (m)",
[
"3120",
"3121",
"3122",
"3123",
"3124",
"3125"
]
],
[
"HEIGHT (m)",
[
"3130",
"3131",
"3132",
"3133",
"3134",
"3135"
]
],
[
"AREA (m^2)",
[
"3140",
"3141",
"3142",
"3143",
"3144",
"3145"
]
],
[
"NET VOLUME (l)",
[
"3150",
"3151",
"3152",
"3153",
"3154",
"3155"
]
],
[
"NET VOLUME (m^3)",
[
"3160",
"3161",
"3162",
"3163",
"3164",
"3165"
]
],
[
"NET WEIGHT (lb)",
[
"3200",
"3201",
"3202",
"3203",
"3204",
"3205"
]
],
[
"LENGTH (in)",
[
"3210",
"3211",
"3212",
"3213",
"3214",
"3215"
]
],
[
"LENGTH (ft)",
[
"3220",
"3221",
"3222",
"3223",
"3224",
"3225"
]
],
[
"LENGTH (yd)",
[
"3230",
"3231",
"3232",
"3233",
"3234",
"3235"
]
],
[
"WIDTH (in)",
[
"3240",
"3241",
"3242",
"3243",
"3244",
"3245"
]
],
[
"WIDTH (ft)",
[
"3250",
"3251",
"3252",
"3253",
"3254",
"3255"
]
],
[
"WIDTH (yd)",
[
"3260",
"3261",
"3262",
"3263",
"3264",
"3265"
]
],
[
"HEIGHT (in)",
[
"3270",
"3271",
"3272",
"3273",
"3274",
"3275"
]
],
[
"HEIGHT (ft)",
[
"3280",
"3281",
"3282",
"3283",
"3284",
"3285"
]
],
[
"HEIGHT (yd)",
[
"3290",
"3291",
"3292",
"3293",
"3294",
"3295"
]
],
[
"GROSS WEIGHT (kg)",
[
"3300",
"3301",
"3302",
"3303",
"3304",
"3305"
]
],
[
"LENGTH (m), log",
[
"3310",
"3311",
"3312",
"3313",
"3314",
"3315"
]
],
[
"WIDTH (m), log",
[
"3320",
"3321",
"3322",
"3323",
"3324",
"3325"
]
],
[
"HEIGHT (m), log",
[
"3330",
"3331",
"3332",
"3333",
"3334",
"3335"
]
],
[
"AREA (m^2), log",
[
"3340",
"3341",
"3342",
"3343",
"3344",
"3345"
]
],
[
"VOLUME (l), log",
[
"3350",
"3351",
"3352",
"3353",
"3354",
"3355"
]
],
[
"VOLUME (m^3), log",
[
"3360",
"3361",
"3362",
"3363",
"3364",
"3365"
]
],
[
"KG PER m^2",
[
"3370",
"3371",
"3372",
"3373",
"3374",
"3375"
]
],
[
"GROSS WEIGHT (lb)",
[
"3400",
"3401",
"3402",
"3403",
"3404",
"3405"
]
],
[
"LENGTH (in), log",
[
"3410",
"3411",
"3412",
"3413",
"3414",
"3415"
]
],
[
"LENGTH (ft), log",
[
"3420",
"3421",
"3422",
"3423",
"3424",
"3425"
]
],
[
"LENGTH (yd), log",
[
"3430",
"3431",
"3432",
"3433",
"3434",
"3435"
]
],
[
"WIDTH (in), log",
[
"3440",
"3441",
"3442",
"3443",
"3444",
"3445"
]
],
[
"WIDTH (ft), log",
[
"3450",
"3451",
"3452",
"3453",
"3454",
"3455"
]
],
[
"WIDTH (yd), log",
[
"3460",
"3461",
"3462",
"3463",
"3464",
"3465"
]
],
[
"HEIGHT (in), log",
[
"3470",
"3471",
"3472",
"3473",
"3474",
"3475"
]
],
[
"HEIGHT (ft), log",
[
"3480",
"3481",
"3482",
"3483",
"3484",
"3485"
]
],
[
"HEIGHT (yd), log",
[
"3490",
"3491",
"3492",
"3493",
"3494",
"3495"
]
],
[
"AREA (in^2)",
[
"3500",
"3501",
"3502",
"3503",
"3504",
"3505"
]
],
[
"AREA (ft^2)",
[
"3510",
"3511",
"3512",
"3513",
"3514",
"3515"
]
],
[
"AREA (yd^2)",
[
"3520",
"3521",
"3522",
"3523",
"3524",
"3525"
]
],
[
"AREA (in^2), log",
[
"3530",
"3531",
"3532",
"3533",
"3534",
"3535"
]
],
[
"AREA (ft^2), log",
[
"3540",
"3541",
"3542",
"3543",
"3544",
"3545"
]
],
[
"AREA (yd^2), log",
[
"3550",
"3551",
"3552",
"3553",
"3554",
"3555"
]
],
[
"NET WEIGHT (t oz)",
[
"3560",
"3561",
"3562",
"3563",
"3564",
"3565"
]
],
[
"NET VOLUME (oz)",
[
"3570",
"3571",
"3572",
"3573",
"3574",
"3575"
]
],
[
"NET VOLUME (qt)",
[
"3600",
"3601",
"3602",
"3603",
"3604",
"3605"
]
],
[
"NET VOLUME (gal.)",
[
"3610",
"3611",
"3612",
"3613",
"3614",
"3615"
]
],
[
"VOLUME (qt), log",
[
"3620",
"3621",
"3622",
"3623",
"3624",
"3625"
]
],
[
"VOLUME (gal.), log",
[
"3630",
"3631",
"3632",
"3633",
"3634",
"3635"
]
],
[
"VOLUME (in^3) ",
[
"3640",
"3641",
"3642",
"3643",
"3644",
"3645"
]
],
[
"VOLUME (ft^3) ",
[
"3650",
"3651",
"3652",
"3653",
"3654",
"3655"
]
],
[
"VOLUME (yd^3) ",
[
"3660",
"3661",
"3662",
"3663",
"3664",
"3665"
]
],
[
"VOLUME (in^3), log",
[
"3670",
"3671",
"3672",
"3673",
"3674",
"3675"
]
],
[
"VOLUME (ft^3), log",
[
"3680",
"3681",
"3682",
"3683",
"3684",
"3685"
]
],
[
"VOLUME (yd^3), log",
[
"3690",
"3691",
"3692",
"3693",
"3694",
"3695"
]
],
[
"AMOUNT",
[
"3900",
"3901",
"3902",
"3903",
"3904",
"3905",
"3906",
"3907",
"3908",
"3909",
"3910",
"3911",
"3912",
"3913",
"3914",
"3915",
"3916",
"3917",
"3918",
"3919"
]
],
[
"PRICE",
[
"3920",
"3921",
"3922",
"3923",
"3924",
"3925",
"3926",
"3927",
"3928",
"3929",
"3930",
"3931",
"3932",
"3933",
"3934",
"3935",
"3936",
"3937",
"3938",
"3939"
]
],
[
"PRCNT OFF",
[
"3940",
"3941",
"3942",
"3943"
]
],
[
"NSN",
[
"7001"
]
],
[
"MEAT CUT",
[
"7002"
]
],
[
"EXPIRY TIME",
[
"7003"
]
],
[
"ACTIVE POTENCY",
[
"7004"
]
],
[
"CATCH AREA",
[
"7005"
]
],
[
"FIRST FREEZE DATE",
[
"7006"
]
],
[
"HARVEST DATE",
[
"7007"
]
],
[
"AQUATIC SPECIES",
[
"7008"
]
],
[
"FISHING GEAR TYPE",
[
"7009"
]
],
[
"PROD METHOD",
[
"7010"
]
],
[
"REFURB LOT",
[
"7020"
]
],
[
"FUNC STAT",
[
"7021"
]
],
[
"REV STAT",
[
"7022"
]
],
[
"GIAI - ASSEMBLY",
[
"7023"
]
],
[
"PROCESSOR # 0",
[
"7030"
]
],
[
"PROCESSOR # 1",
[
"7031"
]
],
[
"PROCESSOR # 2",
[
"7032"
]
],
[
"PROCESSOR # 3",
[
"7033"
]
],
[
"PROCESSOR # 4",
[
"7034"
]
],
[
"PROCESSOR # 5",
[
"7035"
]
],
[
"PROCESSOR # 6",
[
"7036"
]
],
[
"PROCESSOR # 7",
[
"7037"
]
],
[
"PROCESSOR # 8",
[
"7038"
]
],
[
"PROCESSOR # 9",
[
"7039"
]
],
[
"CERT # 0",
[
"7230"
]
],
[
"CERT # 1",
[
"7231"
]
],
[
"CERT # 2",
[
"7232"
]
],
[
"CERT # 3",
[
"7233"
]
],
[
"CERT # 4",
[
"7234"
]
],
[
"CERT # 5",
[
"7235"
]
],
[
"CERT # 6",
[
"7236"
]
],
[
"CERT # 7",
[
"7237"
]
],
[
"CERT # 8",
[
"7238"
]
],
[
"CERT # 9",
[
"7239"
]
],
[
"DIMENSIONS",
[
"8001"
]
],
[
"CMT No",
[
"8002"
]
],
[
"GRAI",
[
"8003"
]
],
[
"GIAI",
[
"8004"
]
],
[
"PRICE PER UNIT",
[
"8005"
]
],
[
"ITIP",
[
"8006"
]
],
[
"IBAN",
[
"8007"
]
],
[
"PROD TIME",
[
"8008"
]
],
[
"OPT SEN",
[
"8009"
]
],
[
"CPID",
[
"8010"
]
],
[
"CPID SERIAL",
[
"8011"
]
],
[
"VERSION",
[
"8012"
]
],
[
"GMN (for medical devices, the default, global data title is BUDI-DI )",
[
"8013"
]
],
[
"GSRN - PROVIDER",
[
"8017"
]
],
[
"GSRN - RECIPIENT",
[
"8018"
]
],
[
"SRIN",
[
"8019"
]
],
[
"REF No",
[
"8020"
]
],
[
"ITIP CONTENT",
[
"8026"
]
],
[
"POINTS",
[
"8111"
]
],
[
"PRODUCT URL",
[
"8200"
]
]
];
const labels = Object.fromEntries(
labelValues
.map(i => i[1]
.map(j => [ j, i[0] ]))
.reduce((a,c) => [ ...a, ...c], [])
);
const fixedLength = {
"00": 20,
"01": 16,
"02": 16,
"03": 16,
"04": 18,
"11": 8,
"12": 8,
"13": 8,
"14": 8,
"15": 8,
"16": 8,
"17": 8,
"18": 8,
"19": 8,
"20": 4,
"31": 10,
"32": 10,
"33": 10,
"34": 10,
"35": 10,
"36": 10,
"41": 16
};
const patternsValues = [
[
"(\\d{12,14}|\\d{8})",
[
"01"
]
],
[
"([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,20})",
[
"10",
"21",
"22",
"243",
"254",
"420",
"710",
"711",
"712",
"713",
"714",
"7020",
"7021",
"7022",
"8002",
"8012"
]
],
[
"(\\d{6})",
[
"11",
"12",
"13",
"15",
"16",
"17",
"3100",
"3101",
"3102",
"3103",
"3104",
"3105",
"3110",
"3111",
"3112",
"3113",
"3114",
"3115",
"3120",
"3121",
"3122",
"3123",
"3124",
"3125",
"3130",
"3131",
"3132",
"3133",
"3134",
"3135",
"3140",
"3141",
"3142",
"3143",
"3144",
"3145",
"3150",
"3151",
"3152",
"3153",
"3154",
"3155",
"3160",
"3161",
"3162",
"3163",
"3164",
"3165",
"3200",
"3201",
"3202",
"3203",
"3204",
"3205",
"3210",
"3211",
"3212",
"3213",
"3214",
"3215",
"3220",
"3221",
"3222",
"3223",
"3224",
"3225",
"3230",
"3231",
"3232",
"3233",
"3234",
"3235",
"3240",
"3241",
"3242",
"3243",
"3244",
"3245",
"3250",
"3251",
"3252",
"3253",
"3254",
"3255",
"3260",
"3261",
"3262",
"3263",
"3264",
"3265",
"3270",
"3271",
"3272",
"3273",
"3274",
"3275",
"3280",
"3281",
"3282",
"3283",
"3284",
"3285",
"3290",
"3291",
"3292",
"3293",
"3294",
"3295",
"3300",
"3301",
"3302",
"3303",
"3304",
"3305",
"3310",
"3311",
"3312",
"3313",
"3314",
"3315",
"3320",
"3321",
"3322",
"3323",
"3324",
"3325",
"3330",
"3331",
"3332",
"3333",
"3334",
"3335",
"3340",
"3341",
"3342",
"3343",
"3344",
"3345",
"3350",
"3351",
"3352",
"3353",
"3354",
"3355",
"3360",
"3361",
"3362",
"3363",
"3364",
"3365",
"3370",
"3371",
"3372",
"3373",
"3374",
"3375",
"3400",
"3401",
"3402",
"3403",
"3404",
"3405",
"3410",
"3411",
"3412",
"3413",
"3414",
"3415",
"3420",
"3421",
"3422",
"3423",
"3424",
"3425",
"3430",
"3431",
"3432",
"3433",
"3434",
"3435",
"3440",
"3441",
"3442",
"3443",
"3444",
"3445",
"3450",
"3451",
"3452",
"3453",
"3454",
"3455",
"3460",
"3461",
"3462",
"3463",
"3464",
"3465",
"3470",
"3471",
"3472",
"3473",
"3474",
"3475",
"3480",
"3481",
"3482",
"3483",
"3484",
"3485",
"3490",
"3491",
"3492",
"3493",
"3494",
"3495",
"3500",
"3501",
"3502",
"3503",
"3504",
"3505",
"3510",
"3511",
"3512",
"3513",
"3514",
"3515",
"3520",
"3521",
"3522",
"3523",
"3524",
"3525",
"3530",
"3531",
"3532",
"3533",
"3534",
"3535",
"3540",
"3541",
"3542",
"3543",
"3544",
"3545",
"3550",
"3551",
"3552",
"3553",
"3554",
"3555",
"3560",
"3561",
"3562",
"3563",
"3564",
"3565",
"3570",
"3571",
"3572",
"3573",
"3574",
"3575",
"3600",
"3601",
"3602",
"3603",
"3604",
"3605",
"3610",
"3611",
"3612",
"3613",
"3614",
"3615",
"3620",
"3621",
"3622",
"3623",
"3624",
"3625",
"3630",
"3631",
"3632",
"3633",
"3634",
"3635",
"3640",
"3641",
"3642",
"3643",
"3644",
"3645",
"3650",
"3651",
"3652",
"3653",
"3654",
"3655",
"3660",
"3661",
"3662",
"3663",
"3664",
"3665",
"3670",
"3671",
"3672",
"3673",
"3674",
"3675",
"3680",
"3681",
"3682",
"3683",
"3684",
"3685",
"3690",
"3691",
"3692",
"3693",
"3694",
"3695",
"7006",
"8005"
]
],
[
"(\\d{2})",
[
"20"
]
],
[
"(\\d{0,8})",
[
"30",
"37"
]
],
[
"([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,30})",
[
"90",
"240",
"241",
"250",
"251",
"400",
"401",
"403",
"7002",
"7023",
"8004",
"8013"
]
],
[
"([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,90})",
[
"91",
"92",
"93",
"94",
"95",
"96",
"97",
"98",
"99"
]
],
[
"(\\d{0,6})",
[
"242"
]
],
[
"(\\d{13})([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,17})",
[
"253"
]
],
[
"(\\d{13})(\\d{0,12})",
[
"255"
]
],
[
"(\\d{17})",
[
"402"
]
],
[
"(\\d{13})",
[
"410",
"411",
"412",
"413",
"414",
"415",
"416",
"7001"
]
],
[
"(\\d{3})([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,9})",
[
"421"
]
],
[
"(\\d{3})",
[
"422",
"424",
"426"
]
],
[
"(\\d{3})(\\d{0,12})",
[
"423",
"425"
]
],
[
"([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,3})",
[
"427",
"7008"
]
],
[
"(\\d{0,15})",
[
"3900",
"3901",
"3902",
"3903",
"3904",
"3905",
"3906",
"3907",
"3908",
"3909",
"3920",
"3921",
"3922",
"3923",
"3924",
"3925",
"3926",
"3927",
"3928",
"3929"
]
],
[
"(\\d{3})(\\d{0,15})",
[
"3910",
"3911",
"3912",
"3913",
"3914",
"3915",
"3916",
"3917",
"3918",
"3919",
"3930",
"3931",
"3932",
"3933",
"3934",
"3935",
"3936",
"3937",
"3938",
"3939"
]
],
[
"(\\d{4})",
[
"3940",
"3941",
"3942",
"3943",
"8111"
]
],
[
"(\\d{10})",
[
"7003"
]
],
[
"(\\d{0,4})",
[
"7004"
]
],
[
"([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,12})",
[
"7005"
]
],
[
"(\\d{6,12})",
[
"7007"
]
],
[
"([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,10})",
[
"7009"
]
],
[
"([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,2})",
[
"7010"
]
],
[
"(\\d{3})([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,27})",
[
"7030",
"7031",
"7032",
"7033",
"7034",
"7035",
"7036",
"7037",
"7038",
"7039"
]
],
[
"([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{2,30})",
[
"7230",
"7231",
"7232",
"7233",
"7234",
"7235",
"7236",
"7237",
"7238",
"7239"
]
],
[
"(\\d{14})",
[
"8001",
"02"
]
],
[
"(\\d{14})([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,16})",
[
"8003"
]
],
[
"(\\d{14})(\\d{2})(\\d{2})",
[
"8006",
"8026"
]
],
[
"([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,34})",
[
"8007"
]
],
[
"(\\d{8})(\\d{0,4})",
[
"8008"
]
],
[
"([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,50})",
[
"8009"
]
],
[
"([\\x23\\x2D\\x2F\\x30-\\x39\\x41-\\x5A]{0,30})",
[
"8010"
]
],
[
"(\\d{0,12})",
[
"8011"
]
],
[
"(\\d{18})",
[
"8017",
"8018",
"00"
]
],
[
"(\\d{0,10})",
[
"8019"
]
],
[
"([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,25})",
[
"8020"
]
],
[
"([\\x21-\\x22\\x25-\\x2F\\x30-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,70})",
[
"8110",
"8112",
"8200"
]
]
];
const patterns = Object.fromEntries(
patternsValues
.map(i => i[1]
.map(j => [ j, i[0] ]))
.reduce((a,c) => [ ...a, ...c], [])
);
const checkDigitPositions = {
"253": 13,
"255": 13,
"402": "L",
"410": "L",
"411": "L",
"412": "L",
"413": "L",
"414": "L",
"415": "L",
"416": "L",
"8003": 14,
"8006": 14,
"8017": "L",
"8018": "L",
"8026": 14,
"00": "L",
"01": "L",
"02": "L"
};
class DigitalLink {
static is(data) {
return typeof data === 'string' && (
data.match(/^(https?|HTTPS?):(\/\/((([^\/?#]*)@)?([^\/?#:]*)(:([^\/?#]*))?))?([^?#]*)(((\/(01|8006|8013|8010|414|415|417|8017|8018|255|00|253|401|402|8003|8004|240)\/)(\d{4}[^\/]+)(\/[^/]+\/[^/]+)?[/]?(\?([^?\n]*))?(#([^\n]*))?))/) ||
data.match(/^(https?|HTTPS?):(\/\/((([^\/?#]*)@)?([^\/?#:]*)(:([^\/?#]*))?))?([^?#]*)((\/[0-9A-Za-z_-]{10,}$))/)
);
}
static calculateCheckDigit(ai, value) {
let counter = 0;
let total = 0;
let checkDigitPosition = checkDigitPositions[ai] === "L" ? value.length : checkDigitPositions[ai];
for (let i = checkDigitPosition - 2; i >= 0; i--) {
let digit = value.charAt(i);
let multiplier;
if (counter % 2 === 0) {
multiplier = 3;
} else {
multiplier = 1;
}
total += digit * multiplier;
counter++;
}
return (10 - (total % 10)) % 10;
}
static verifyCheckDigit(ai, value) {
if (!checkDigitPositions[ai]) {
return true;
}
let checkDigitPosition = checkDigitPositions[ai] === "L" ? value.length : checkDigitPositions[ai];
let actualCheckDigit = parseInt(value.charAt(checkDigitPosition - 1), 10);
let expectedCheckDigit = DigitalLink.calculateCheckDigit(ai, value);
if (actualCheckDigit !== expectedCheckDigit) {
console.log(`Invalid check digit: An invalid check digit was found for the primary identification key (${ai})${value}; the correct check digit should be ${expectedCheckDigit} at position ${checkDigitPosition}`);
return false;
}
return true;
}
static verifySyntax(ai, value) {
let re = new RegExp("^" + patterns[ai] + "$");
if (!re.test(value)) {
console.log(`Syntax error: Invalid syntax for value of (${ai}): ${value}`);
return false;
}
return true;
}
static parse(link) {
let candidates = [];
/* Extract the AI and value pairs from the link */
let url = new URL(link);
if (url.pathname != '/') {
let pairs = url.pathname.substr(1).split('/');
while (pairs.length >= 2) {
candidates.push([ pairs.shift(), decodeURIComponent(pairs.shift()) ]);
}
}
if (url.search != '') {
let pairs = [ ...(new URLSearchParams(url.search.replace(/;/, '&'))) ];
for (let [ai, value] of pairs) {
candidates.push([ ai, value ]);
}
}
/* Verify the syntax and check digits of the elements */
let elements = [];
for (let [ai, value] of candidates) {
let valid = true;
valid &= DigitalLink.verifySyntax(ai, value);
valid &= DigitalLink.verifyCheckDigit(ai, value);
if (valid) {
if (ai == "01" || ai == "02") {
value = value.padStart(14, '0');
}
elements.push({
ai,
value,
label: labels[ai]
});
}
}
/* Sort elements by AI */
elements.sort((a, b) => {
return a.ai.localeCompare(b.ai);
});
return elements;
}
}
const GS = String.fromCharCode(29);
class Elements {
static parse(data) {
let elements = [];
/* Split the data into elements */
let segments = data.split(GS);
for (let segment of segments) {
while (segment.length) {
let ai = segment.substr(0, 2);
if (ai in fixedLength) {
elements.push({ value: segment.substr(0, fixedLength[ai]) });
segment = segment.substr(fixedLength[ai]);
}
else {
elements.push({ value: segment });
segment = '';
}
}
}
/* Parse the elements */
for (let element of elements) {
let aiSize;
for (let i = 2; i <=4; i++) {
if (element.value.substr(0, i) in labels) {
aiSize = i;
break;
}
}
if (aiSize) {
element.ai = element.value.substr(0, aiSize);
element.value = element.value.substr(aiSize);
element.label = labels[element.ai];
}
}
return elements;
}
}
class UPCA {
static compress(value) {
if (typeof value !== "string" || value.length !== 12 || !/^\d{12}$/.test(value)) {
return value;
}
if (value.slice(4, 8) == "0000" && value[3] >= "0" && value[3] <= "2") {
return value.slice(0, 3) + value.slice(8, 11) + value[3] + value[11];
}
if (value.slice(4, 9) == "00000") {
return value.slice(0, 4) + value.slice(9, 11) + "3" + value[11];
}
if (value.slice(5, 10) == "00000") {
return value.slice(0, 5) + value.slice(10, 11) + "4" + value[11];
}
if (value.slice(6, 10) == "0000" && value[11] >= 5 && value[11] <= 9) {
return value.slice(0, 6) + value[10] + value[11];
}
return value;
}
}
class UPCE {
static expand(value) {
/* Digits 2 to 7 (UPC-E has a leading digit) */
const digits = value.substring(1, 7);
/* The last digit (check digit) */
const lastDigit = value.charAt(7);
let result = value.charAt(0);
switch (digits.charAt(5)) {
case '0':
case '1':
case '2':
// If the 4th digit is 0, 1, or 2: Expand to form 0XXX00NNNN
result += digits.substring(0, 2) + digits.charAt(5) + "0000" + digits.substring(2, 5);
break;
case '3':
// If the 4th digit is 3: Expand to form 0XXX00000NNNN
result += digits.substring(0, 3) + "00000" + digits.substring(3, 5);
break;
case '4':
// If the 4th digit is 4: Expand to form 0XXXX00000NNNN
result += digits.substring(0, 4) + "00000" + digits.charAt(4);
break;
default:
// If the 4th digit is 5-9: Expand to form 0XXXXXNNNN
result += digits.substring(0, 5) + "0000" + + digits.charAt(5);
break;
}
result += lastDigit;
return result;
}
}
var Symbologies = { UPCA, UPCE };
class GS1 {
static DigitalLink = DigitalLink;
static parse(result) {
let elements = [];
/* Decode GS1 data if we have a FNC1 character or a GS character */
if (result.fnc1 || result.value.includes(String.fromCharCode(29))) {
elements = Elements.parse(result.value);
}
/* Decode GS1 data if it is a GS1 Digital Link */
else if (DigitalLink.is(result.value)) {
elements = DigitalLink.parse(result.value);
}
/* Decode GS1 data based on the symbology */
else if (typeof result.symbology === 'string') {
/* Decode GS1 data if it is a GS1 DataBar */
if (result.symbology?.startsWith('gs1-databar')) {
elements = Elements.parse(result.value);
}
/* Extract data from an ITF-14 barcode */
else if (result.symbology === 'itf' && result.value.length === 14) {
elements = [
{ ai: '01', label: 'GTIN', value: result.value }
];
}
/* Extract data from EAN and UPC barcodes */
else if (['upca','ean8','ean13'].includes(result.symbology)) {
elements = [
{ ai: '01', label: 'GTIN', value: result.value.padStart(14, '0') }
];
}
else if (result.symbology === 'upce') {
elements = [
{ ai: '01', label: 'GTIN', value: Symbologies.UPCE.expand(result.value).padStart(14, '0') }
];
}
}
/* Prepare return value */
if (elements.length) {
let data = {
elements
};
let gtin = elements.find(e => e.ai === '01');
if (gtin) {
data.gtin = gtin.value;
}
return data;
}
}
}
class Detector {
static checkdigit(barcode) {
const digits = barcode.split('').map(i => parseInt(i, 10)).reverse();
const total = digits.reduce((acc, number, i) => {
return acc + (i % 2 === 1 ? number : number * 3);
}, 0);
return (Math.ceil(total / 10) * 10) - total;
}
static detect(barcode) {
if (barcode.startsWith('http')) {
return { symbology: 'qr-code', guess: true };
}
else if (barcode.startsWith('X-HM:')) {
return { symbology: 'qr-code', guess: false };
}
else if (barcode.startsWith('MT:')) {
return { symbology: 'qr-code', guess: false };
}
else if (barcode.startsWith('WIFI:')) {
return { symbology: 'qr-code', guess: false };
}
else if (barcode.match(/^[0-9]+$/) && barcode.length == 8) {
if (Detector.checkdigit(barcode.slice(0, -1)) == barcode.slice(-1)) {
if (barcode.charAt(0) == '0' || barcode.charAt(0) == '1') {
return { symbology: 'upce', guess: true };
}
return { symbology: 'ean8', guess: false };
}
}
else if (barcode.match(/^[0-9]+$/) && barcode.length == 12) {
if (Detector.checkdigit(barcode.slice(0, -1)) == barcode.slice(-1)) {
return { symbology: 'upca', guess: false };
}
}
else if (barcode.match(/^[0-9]+$/) && barcode.length == 13) {
if (Detector.checkdigit(barcode.slice(0, -1)) == barcode.slice(-1)) {
return { symbology: 'ean13', guess: false };
}
}
else if (barcode.match(/^[0-9]+$/) && barcode.length == 14) {
return { symbology: 'itf', guess: false };
}
else if (barcode.match(/^M[0-9]/)) {
return { symbology: 'aztec-code', guess: true };
}
else if (barcode.length > 128) {
return { symbology: 'pdf417', guess: true };
}
else if (barcode.length > 32) {
return { symbology: 'qr-code', guess: true };
}
}
}
exports.Aim = Aim;
exports.Detector = Detector;
exports.GS1 = GS1;
exports.Symbologies = Symbologies;