isahaq-barcode 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +29 -29
- package/.prettierignore +11 -0
- package/.prettierrc +11 -0
- package/README.md +596 -549
- package/bin/generate.js +274 -274
- package/eslint.config.js +66 -68
- package/examples/basic-usage.js +58 -58
- package/examples/batch-example.json +56 -56
- package/examples/express-server.js +163 -159
- package/index.js +134 -134
- package/jest.config.js +13 -13
- package/package.json +27 -15
- package/src/builders/QrCodeBuilder.js +401 -401
- package/src/renderers/HTMLRenderer.js +212 -212
- package/src/renderers/PDFRenderer.js +184 -184
- package/src/renderers/PNGRenderer.js +123 -123
- package/src/renderers/RenderFormats.js +87 -87
- package/src/renderers/SVGRenderer.js +221 -221
- package/src/services/BarcodeService.js +175 -175
- package/src/types/BarcodeTypes.js +195 -195
- package/src/validators/Validator.js +352 -352
- package/tests/BarcodeGenerator.test.js +187 -187
- package/tests/BarcodeService.test.js +76 -76
- package/tests/QrCodeBuilder.test.js +130 -130
- package/tests/setup.js +59 -59
|
@@ -1,352 +1,352 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validator - Data validation for different barcode types
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const { BarcodeTypes } = require('../types/BarcodeTypes');
|
|
6
|
-
|
|
7
|
-
class Validator {
|
|
8
|
-
constructor() {
|
|
9
|
-
this.patterns = {
|
|
10
|
-
// Numeric patterns
|
|
11
|
-
numeric: /^[0-9]+$/,
|
|
12
|
-
// Alphanumeric patterns
|
|
13
|
-
alphanumeric: /^[A-Za-z0-9]+$/,
|
|
14
|
-
// Code 39 pattern
|
|
15
|
-
code39: /^[A-Z0-9\s\-\.\$\/\+\%]+$/,
|
|
16
|
-
// Code 39 extended pattern
|
|
17
|
-
code39extended: /^[\x00-\x7F]+$/,
|
|
18
|
-
// EAN/UPC patterns
|
|
19
|
-
ean13: /^[0-9]{12,13}$/,
|
|
20
|
-
ean8: /^[0-9]{7,8}$/,
|
|
21
|
-
upca: /^[0-9]{11,12}$/,
|
|
22
|
-
upce: /^[0-9]{6,8}$/,
|
|
23
|
-
// QR Code pattern (supports Unicode)
|
|
24
|
-
qrcode: /^[\s\S]+$/,
|
|
25
|
-
// Data Matrix pattern
|
|
26
|
-
datamatrix: /^[\s\S]+$/,
|
|
27
|
-
// PDF417 pattern
|
|
28
|
-
pdf417: /^[\s\S]+$/,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Validate data for a specific barcode type
|
|
34
|
-
* @param {string} data - The data to validate
|
|
35
|
-
* @param {string} type - The barcode type
|
|
36
|
-
* @returns {Object} Validation result
|
|
37
|
-
*/
|
|
38
|
-
validate(data, type) {
|
|
39
|
-
if (!data || typeof data !== 'string') {
|
|
40
|
-
return {
|
|
41
|
-
valid: false,
|
|
42
|
-
error: 'Data must be a non-empty string',
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (!BarcodeTypes.isValid(type)) {
|
|
47
|
-
return {
|
|
48
|
-
valid: false,
|
|
49
|
-
error: `Invalid barcode type: ${type}`,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Get configuration for the barcode type
|
|
54
|
-
const config = BarcodeTypes.getConfig(type);
|
|
55
|
-
|
|
56
|
-
// Check length constraints
|
|
57
|
-
if (data.length < config.minLength) {
|
|
58
|
-
return {
|
|
59
|
-
valid: false,
|
|
60
|
-
error: `Data too short. Minimum length: ${config.minLength}`,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (data.length > config.maxLength) {
|
|
65
|
-
return {
|
|
66
|
-
valid: false,
|
|
67
|
-
error: `Data too long. Maximum length: ${config.maxLength}`,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Type-specific validation
|
|
72
|
-
const validationResult = this.validateByType(data, type);
|
|
73
|
-
if (!validationResult.valid) {
|
|
74
|
-
return validationResult;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
valid: true,
|
|
79
|
-
data,
|
|
80
|
-
type,
|
|
81
|
-
length: data.length,
|
|
82
|
-
charset: config.charset,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Validate data by barcode type
|
|
88
|
-
* @param {string} data - The data to validate
|
|
89
|
-
* @param {string} type - The barcode type
|
|
90
|
-
* @returns {Object} Validation result
|
|
91
|
-
*/
|
|
92
|
-
validateByType(data, type) {
|
|
93
|
-
switch (type) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Validate Code 128 data
|
|
142
|
-
* @param {string} data - The data to validate
|
|
143
|
-
* @param {string} type - The Code 128 variant
|
|
144
|
-
* @returns {Object} Validation result
|
|
145
|
-
*/
|
|
146
|
-
validateCode128(data) {
|
|
147
|
-
// Code 128 supports ASCII characters
|
|
148
|
-
if (!/^[\x00-\x7F]+$/.test(data)) {
|
|
149
|
-
return {
|
|
150
|
-
valid: false,
|
|
151
|
-
error: 'Code 128 supports ASCII characters only',
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return { valid: true };
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Validate Code 39 data
|
|
160
|
-
* @param {string} data - The data to validate
|
|
161
|
-
* @param {string} type - The Code 39 variant
|
|
162
|
-
* @returns {Object} Validation result
|
|
163
|
-
*/
|
|
164
|
-
validateCode39(data, type) {
|
|
165
|
-
if (type === 'code39extended') {
|
|
166
|
-
// Extended Code 39 supports full ASCII
|
|
167
|
-
if (!/^[\x00-\x7F]+$/.test(data)) {
|
|
168
|
-
return {
|
|
169
|
-
valid: false,
|
|
170
|
-
error: 'Extended Code 39 supports ASCII characters only',
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
} else {
|
|
174
|
-
// Standard Code 39 supports limited character set
|
|
175
|
-
if (!this.patterns.code39.test(data)) {
|
|
176
|
-
return {
|
|
177
|
-
valid: false,
|
|
178
|
-
error: 'Code 39 supports characters: A-Z, 0-9, space, -.$/+%',
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return { valid: true };
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Validate Code 93 data
|
|
188
|
-
* @param {string} data - The data to validate
|
|
189
|
-
* @returns {Object} Validation result
|
|
190
|
-
*/
|
|
191
|
-
validateCode93(data) {
|
|
192
|
-
if (!this.patterns.alphanumeric.test(data)) {
|
|
193
|
-
return {
|
|
194
|
-
valid: false,
|
|
195
|
-
error: 'Code 93 supports alphanumeric characters only',
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return { valid: true };
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Validate EAN-13 data
|
|
204
|
-
* @param {string} data - The data to validate
|
|
205
|
-
* @returns {Object} Validation result
|
|
206
|
-
*/
|
|
207
|
-
validateEAN13(data) {
|
|
208
|
-
if (!this.patterns.ean13.test(data)) {
|
|
209
|
-
return {
|
|
210
|
-
valid: false,
|
|
211
|
-
error: 'EAN-13 must be 12 or 13 digits',
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Validate check digit if 13 digits provided
|
|
216
|
-
if (data.length === 13) {
|
|
217
|
-
const checkDigit = this.calculateEANCheckDigit(data.substring(0, 12));
|
|
218
|
-
if (parseInt(data[12]) !== checkDigit) {
|
|
219
|
-
return {
|
|
220
|
-
valid: false,
|
|
221
|
-
error: 'Invalid EAN-13 check digit',
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
return { valid: true };
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Validate EAN-8 data
|
|
231
|
-
* @param {string} data - The data to validate
|
|
232
|
-
* @returns {Object} Validation result
|
|
233
|
-
*/
|
|
234
|
-
validateEAN8(data) {
|
|
235
|
-
if (!this.patterns.ean8.test(data)) {
|
|
236
|
-
return {
|
|
237
|
-
valid: false,
|
|
238
|
-
error: 'EAN-8 must be 7 or 8 digits',
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Validate check digit if 8 digits provided
|
|
243
|
-
if (data.length === 8) {
|
|
244
|
-
const checkDigit = this.calculateEANCheckDigit(data.substring(0, 7));
|
|
245
|
-
if (parseInt(data[7]) !== checkDigit) {
|
|
246
|
-
return {
|
|
247
|
-
valid: false,
|
|
248
|
-
error: 'Invalid EAN-8 check digit',
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return { valid: true };
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Validate UPC-A data
|
|
258
|
-
* @param {string} data - The data to validate
|
|
259
|
-
* @returns {Object} Validation result
|
|
260
|
-
*/
|
|
261
|
-
validateUPCA(data) {
|
|
262
|
-
if (!this.patterns.upca.test(data)) {
|
|
263
|
-
return {
|
|
264
|
-
valid: false,
|
|
265
|
-
error: 'UPC-A must be 11 or 12 digits',
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
return { valid: true };
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Validate UPC-E data
|
|
274
|
-
* @param {string} data - The data to validate
|
|
275
|
-
* @returns {Object} Validation result
|
|
276
|
-
*/
|
|
277
|
-
validateUPCE(data) {
|
|
278
|
-
if (!this.patterns.upce.test(data)) {
|
|
279
|
-
return {
|
|
280
|
-
valid: false,
|
|
281
|
-
error: 'UPC-E must be 6 to 8 digits',
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
return { valid: true };
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Validate QR Code data
|
|
290
|
-
* @param {string} data - The data to validate
|
|
291
|
-
* @returns {Object} Validation result
|
|
292
|
-
*/
|
|
293
|
-
validateQRCode(data) {
|
|
294
|
-
// QR Code supports Unicode, so we just check if it's not empty
|
|
295
|
-
if (data.length === 0) {
|
|
296
|
-
return {
|
|
297
|
-
valid: false,
|
|
298
|
-
error: 'QR Code data cannot be empty',
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
return { valid: true };
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Validate Data Matrix data
|
|
307
|
-
* @param {string} data - The data to validate
|
|
308
|
-
* @returns {Object} Validation result
|
|
309
|
-
*/
|
|
310
|
-
validateDataMatrix(data) {
|
|
311
|
-
if (data.length === 0) {
|
|
312
|
-
return {
|
|
313
|
-
valid: false,
|
|
314
|
-
error: 'Data Matrix data cannot be empty',
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
return { valid: true };
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* Validate PDF417 data
|
|
323
|
-
* @param {string} data - The data to validate
|
|
324
|
-
* @returns {Object} Validation result
|
|
325
|
-
*/
|
|
326
|
-
validatePDF417(data) {
|
|
327
|
-
if (data.length === 0) {
|
|
328
|
-
return {
|
|
329
|
-
valid: false,
|
|
330
|
-
error: 'PDF417 data cannot be empty',
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
return { valid: true };
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Calculate EAN check digit
|
|
339
|
-
* @param {string} data - The data without check digit
|
|
340
|
-
* @returns {number} Check digit
|
|
341
|
-
*/
|
|
342
|
-
calculateEANCheckDigit(data) {
|
|
343
|
-
let sum = 0;
|
|
344
|
-
for (let i = 0; i < data.length; i++) {
|
|
345
|
-
const digit = parseInt(data[i]);
|
|
346
|
-
sum += i % 2 === 0 ? digit : digit * 3;
|
|
347
|
-
}
|
|
348
|
-
return (10 - (sum % 10)) % 10;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
module.exports = { Validator };
|
|
1
|
+
/**
|
|
2
|
+
* Validator - Data validation for different barcode types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const { BarcodeTypes } = require('../types/BarcodeTypes');
|
|
6
|
+
|
|
7
|
+
class Validator {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.patterns = {
|
|
10
|
+
// Numeric patterns
|
|
11
|
+
numeric: /^[0-9]+$/,
|
|
12
|
+
// Alphanumeric patterns
|
|
13
|
+
alphanumeric: /^[A-Za-z0-9]+$/,
|
|
14
|
+
// Code 39 pattern
|
|
15
|
+
code39: /^[A-Z0-9\s\-\.\$\/\+\%]+$/,
|
|
16
|
+
// Code 39 extended pattern
|
|
17
|
+
code39extended: /^[\x00-\x7F]+$/,
|
|
18
|
+
// EAN/UPC patterns
|
|
19
|
+
ean13: /^[0-9]{12,13}$/,
|
|
20
|
+
ean8: /^[0-9]{7,8}$/,
|
|
21
|
+
upca: /^[0-9]{11,12}$/,
|
|
22
|
+
upce: /^[0-9]{6,8}$/,
|
|
23
|
+
// QR Code pattern (supports Unicode)
|
|
24
|
+
qrcode: /^[\s\S]+$/,
|
|
25
|
+
// Data Matrix pattern
|
|
26
|
+
datamatrix: /^[\s\S]+$/,
|
|
27
|
+
// PDF417 pattern
|
|
28
|
+
pdf417: /^[\s\S]+$/,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Validate data for a specific barcode type
|
|
34
|
+
* @param {string} data - The data to validate
|
|
35
|
+
* @param {string} type - The barcode type
|
|
36
|
+
* @returns {Object} Validation result
|
|
37
|
+
*/
|
|
38
|
+
validate(data, type) {
|
|
39
|
+
if (!data || typeof data !== 'string') {
|
|
40
|
+
return {
|
|
41
|
+
valid: false,
|
|
42
|
+
error: 'Data must be a non-empty string',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!BarcodeTypes.isValid(type)) {
|
|
47
|
+
return {
|
|
48
|
+
valid: false,
|
|
49
|
+
error: `Invalid barcode type: ${type}`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Get configuration for the barcode type
|
|
54
|
+
const config = BarcodeTypes.getConfig(type);
|
|
55
|
+
|
|
56
|
+
// Check length constraints
|
|
57
|
+
if (data.length < config.minLength) {
|
|
58
|
+
return {
|
|
59
|
+
valid: false,
|
|
60
|
+
error: `Data too short. Minimum length: ${config.minLength}`,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (data.length > config.maxLength) {
|
|
65
|
+
return {
|
|
66
|
+
valid: false,
|
|
67
|
+
error: `Data too long. Maximum length: ${config.maxLength}`,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Type-specific validation
|
|
72
|
+
const validationResult = this.validateByType(data, type);
|
|
73
|
+
if (!validationResult.valid) {
|
|
74
|
+
return validationResult;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
valid: true,
|
|
79
|
+
data,
|
|
80
|
+
type,
|
|
81
|
+
length: data.length,
|
|
82
|
+
charset: config.charset,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Validate data by barcode type
|
|
88
|
+
* @param {string} data - The data to validate
|
|
89
|
+
* @param {string} type - The barcode type
|
|
90
|
+
* @returns {Object} Validation result
|
|
91
|
+
*/
|
|
92
|
+
validateByType(data, type) {
|
|
93
|
+
switch (type) {
|
|
94
|
+
case 'code128':
|
|
95
|
+
case 'code128a':
|
|
96
|
+
case 'code128b':
|
|
97
|
+
case 'code128c':
|
|
98
|
+
case 'code128auto':
|
|
99
|
+
return this.validateCode128(data, type);
|
|
100
|
+
|
|
101
|
+
case 'code39':
|
|
102
|
+
case 'code39extended':
|
|
103
|
+
case 'code39checksum':
|
|
104
|
+
case 'code39auto':
|
|
105
|
+
return this.validateCode39(data, type);
|
|
106
|
+
|
|
107
|
+
case 'code93':
|
|
108
|
+
return this.validateCode93(data);
|
|
109
|
+
|
|
110
|
+
case 'ean13':
|
|
111
|
+
return this.validateEAN13(data);
|
|
112
|
+
|
|
113
|
+
case 'ean8':
|
|
114
|
+
return this.validateEAN8(data);
|
|
115
|
+
|
|
116
|
+
case 'upca':
|
|
117
|
+
return this.validateUPCA(data);
|
|
118
|
+
|
|
119
|
+
case 'upce':
|
|
120
|
+
return this.validateUPCE(data);
|
|
121
|
+
|
|
122
|
+
case 'qrcode':
|
|
123
|
+
return this.validateQRCode(data);
|
|
124
|
+
|
|
125
|
+
case 'datamatrix':
|
|
126
|
+
return this.validateDataMatrix(data);
|
|
127
|
+
|
|
128
|
+
case 'pdf417':
|
|
129
|
+
return this.validatePDF417(data);
|
|
130
|
+
|
|
131
|
+
default:
|
|
132
|
+
// For other types, just check if data is not empty
|
|
133
|
+
return {
|
|
134
|
+
valid: data.length > 0,
|
|
135
|
+
error: data.length === 0 ? 'Data cannot be empty' : null,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Validate Code 128 data
|
|
142
|
+
* @param {string} data - The data to validate
|
|
143
|
+
* @param {string} type - The Code 128 variant
|
|
144
|
+
* @returns {Object} Validation result
|
|
145
|
+
*/
|
|
146
|
+
validateCode128(data) {
|
|
147
|
+
// Code 128 supports ASCII characters
|
|
148
|
+
if (!/^[\x00-\x7F]+$/.test(data)) {
|
|
149
|
+
return {
|
|
150
|
+
valid: false,
|
|
151
|
+
error: 'Code 128 supports ASCII characters only',
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return { valid: true };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Validate Code 39 data
|
|
160
|
+
* @param {string} data - The data to validate
|
|
161
|
+
* @param {string} type - The Code 39 variant
|
|
162
|
+
* @returns {Object} Validation result
|
|
163
|
+
*/
|
|
164
|
+
validateCode39(data, type) {
|
|
165
|
+
if (type === 'code39extended') {
|
|
166
|
+
// Extended Code 39 supports full ASCII
|
|
167
|
+
if (!/^[\x00-\x7F]+$/.test(data)) {
|
|
168
|
+
return {
|
|
169
|
+
valid: false,
|
|
170
|
+
error: 'Extended Code 39 supports ASCII characters only',
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
// Standard Code 39 supports limited character set
|
|
175
|
+
if (!this.patterns.code39.test(data)) {
|
|
176
|
+
return {
|
|
177
|
+
valid: false,
|
|
178
|
+
error: 'Code 39 supports characters: A-Z, 0-9, space, -.$/+%',
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return { valid: true };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Validate Code 93 data
|
|
188
|
+
* @param {string} data - The data to validate
|
|
189
|
+
* @returns {Object} Validation result
|
|
190
|
+
*/
|
|
191
|
+
validateCode93(data) {
|
|
192
|
+
if (!this.patterns.alphanumeric.test(data)) {
|
|
193
|
+
return {
|
|
194
|
+
valid: false,
|
|
195
|
+
error: 'Code 93 supports alphanumeric characters only',
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return { valid: true };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Validate EAN-13 data
|
|
204
|
+
* @param {string} data - The data to validate
|
|
205
|
+
* @returns {Object} Validation result
|
|
206
|
+
*/
|
|
207
|
+
validateEAN13(data) {
|
|
208
|
+
if (!this.patterns.ean13.test(data)) {
|
|
209
|
+
return {
|
|
210
|
+
valid: false,
|
|
211
|
+
error: 'EAN-13 must be 12 or 13 digits',
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Validate check digit if 13 digits provided
|
|
216
|
+
if (data.length === 13) {
|
|
217
|
+
const checkDigit = this.calculateEANCheckDigit(data.substring(0, 12));
|
|
218
|
+
if (parseInt(data[12]) !== checkDigit) {
|
|
219
|
+
return {
|
|
220
|
+
valid: false,
|
|
221
|
+
error: 'Invalid EAN-13 check digit',
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return { valid: true };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Validate EAN-8 data
|
|
231
|
+
* @param {string} data - The data to validate
|
|
232
|
+
* @returns {Object} Validation result
|
|
233
|
+
*/
|
|
234
|
+
validateEAN8(data) {
|
|
235
|
+
if (!this.patterns.ean8.test(data)) {
|
|
236
|
+
return {
|
|
237
|
+
valid: false,
|
|
238
|
+
error: 'EAN-8 must be 7 or 8 digits',
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Validate check digit if 8 digits provided
|
|
243
|
+
if (data.length === 8) {
|
|
244
|
+
const checkDigit = this.calculateEANCheckDigit(data.substring(0, 7));
|
|
245
|
+
if (parseInt(data[7]) !== checkDigit) {
|
|
246
|
+
return {
|
|
247
|
+
valid: false,
|
|
248
|
+
error: 'Invalid EAN-8 check digit',
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return { valid: true };
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Validate UPC-A data
|
|
258
|
+
* @param {string} data - The data to validate
|
|
259
|
+
* @returns {Object} Validation result
|
|
260
|
+
*/
|
|
261
|
+
validateUPCA(data) {
|
|
262
|
+
if (!this.patterns.upca.test(data)) {
|
|
263
|
+
return {
|
|
264
|
+
valid: false,
|
|
265
|
+
error: 'UPC-A must be 11 or 12 digits',
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return { valid: true };
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Validate UPC-E data
|
|
274
|
+
* @param {string} data - The data to validate
|
|
275
|
+
* @returns {Object} Validation result
|
|
276
|
+
*/
|
|
277
|
+
validateUPCE(data) {
|
|
278
|
+
if (!this.patterns.upce.test(data)) {
|
|
279
|
+
return {
|
|
280
|
+
valid: false,
|
|
281
|
+
error: 'UPC-E must be 6 to 8 digits',
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return { valid: true };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Validate QR Code data
|
|
290
|
+
* @param {string} data - The data to validate
|
|
291
|
+
* @returns {Object} Validation result
|
|
292
|
+
*/
|
|
293
|
+
validateQRCode(data) {
|
|
294
|
+
// QR Code supports Unicode, so we just check if it's not empty
|
|
295
|
+
if (data.length === 0) {
|
|
296
|
+
return {
|
|
297
|
+
valid: false,
|
|
298
|
+
error: 'QR Code data cannot be empty',
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return { valid: true };
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Validate Data Matrix data
|
|
307
|
+
* @param {string} data - The data to validate
|
|
308
|
+
* @returns {Object} Validation result
|
|
309
|
+
*/
|
|
310
|
+
validateDataMatrix(data) {
|
|
311
|
+
if (data.length === 0) {
|
|
312
|
+
return {
|
|
313
|
+
valid: false,
|
|
314
|
+
error: 'Data Matrix data cannot be empty',
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return { valid: true };
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Validate PDF417 data
|
|
323
|
+
* @param {string} data - The data to validate
|
|
324
|
+
* @returns {Object} Validation result
|
|
325
|
+
*/
|
|
326
|
+
validatePDF417(data) {
|
|
327
|
+
if (data.length === 0) {
|
|
328
|
+
return {
|
|
329
|
+
valid: false,
|
|
330
|
+
error: 'PDF417 data cannot be empty',
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return { valid: true };
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Calculate EAN check digit
|
|
339
|
+
* @param {string} data - The data without check digit
|
|
340
|
+
* @returns {number} Check digit
|
|
341
|
+
*/
|
|
342
|
+
calculateEANCheckDigit(data) {
|
|
343
|
+
let sum = 0;
|
|
344
|
+
for (let i = 0; i < data.length; i++) {
|
|
345
|
+
const digit = parseInt(data[i]);
|
|
346
|
+
sum += i % 2 === 0 ? digit : digit * 3;
|
|
347
|
+
}
|
|
348
|
+
return (10 - (sum % 10)) % 10;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
module.exports = { Validator };
|