isahaq-barcode 1.0.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.
@@ -0,0 +1,221 @@
1
+ /**
2
+ * SVG Renderer - Renders barcodes as SVG
3
+ */
4
+
5
+ const JsBarcode = require('jsbarcode');
6
+
7
+ class SVGRenderer {
8
+ constructor() {
9
+ this.defaultOptions = {
10
+ width: 2,
11
+ height: 100,
12
+ displayValue: true,
13
+ fontSize: 20,
14
+ textAlign: 'center',
15
+ textPosition: 'bottom',
16
+ textMargin: 2,
17
+ background: '#ffffff',
18
+ lineColor: '#000000',
19
+ margin: 10,
20
+ marginTop: 10,
21
+ marginBottom: 10,
22
+ marginLeft: 10,
23
+ marginRight: 10,
24
+ };
25
+ }
26
+
27
+ /**
28
+ * Render a barcode as SVG
29
+ * @param {string} data - The data to encode
30
+ * @param {string} type - The barcode type
31
+ * @param {Object} options - Render options
32
+ * @returns {string} SVG string
33
+ */
34
+ render(data, type, options = {}) {
35
+ try {
36
+ // Merge options with defaults
37
+ const renderOptions = { ...this.defaultOptions, ...options };
38
+
39
+ // Create a temporary canvas element for JsBarcode
40
+ const canvas = document.createElement('canvas');
41
+
42
+ // Generate barcode using JsBarcode
43
+ JsBarcode(canvas, data, {
44
+ format: this.mapBarcodeType(type),
45
+ width: renderOptions.width,
46
+ height: renderOptions.height,
47
+ displayValue: renderOptions.displayValue,
48
+ fontSize: renderOptions.fontSize,
49
+ textAlign: renderOptions.textAlign,
50
+ textPosition: renderOptions.textPosition,
51
+ textMargin: renderOptions.textMargin,
52
+ background: renderOptions.background,
53
+ lineColor: renderOptions.lineColor,
54
+ margin: renderOptions.margin,
55
+ marginTop: renderOptions.marginTop,
56
+ marginBottom: renderOptions.marginBottom,
57
+ marginLeft: renderOptions.marginLeft,
58
+ marginRight: renderOptions.marginRight,
59
+ xmlDocument: this.createXMLDocument(),
60
+ });
61
+
62
+ // Get SVG string from canvas
63
+ const svgString = canvas.toSVG();
64
+ return svgString;
65
+ } catch {
66
+ // Fallback: create SVG manually
67
+ return this.createManualSVG(data, type, options);
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Create SVG manually as fallback
73
+ * @param {string} data - The data to encode
74
+ * @param {string} type - The barcode type
75
+ * @param {Object} options - Render options
76
+ * @returns {string} SVG string
77
+ */
78
+ createManualSVG(data, type, options = {}) {
79
+ const renderOptions = { ...this.defaultOptions, ...options };
80
+
81
+ // Simple SVG structure for basic barcodes
82
+ const width = 300;
83
+ const height = renderOptions.height + (renderOptions.displayValue ? 30 : 0);
84
+
85
+ let svg = `<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">`;
86
+ svg += `<rect width="${width}" height="${height}" fill="${renderOptions.background}"/>`;
87
+
88
+ // Add barcode representation (simplified)
89
+ if (type === 'qrcode') {
90
+ svg += this.createQRCodeSVG(data, width, height, renderOptions);
91
+ } else {
92
+ svg += this.createLinearBarcodeSVG(data, width, height, renderOptions);
93
+ }
94
+
95
+ // Add text if displayValue is true
96
+ if (renderOptions.displayValue) {
97
+ svg += `<text x="${width / 2}" y="${
98
+ height - 5
99
+ }" text-anchor="middle" font-family="Arial" font-size="${
100
+ renderOptions.fontSize
101
+ }" fill="${renderOptions.lineColor}">${data}</text>`;
102
+ }
103
+
104
+ svg += '</svg>';
105
+ return svg;
106
+ }
107
+
108
+ /**
109
+ * Create QR Code SVG representation
110
+ * @param {string} data - The data to encode
111
+ * @param {number} width - SVG width
112
+ * @param {number} height - SVG height
113
+ * @param {Object} options - Render options
114
+ * @returns {string} SVG content
115
+ */
116
+ createQRCodeSVG(data, width, height, options) {
117
+ // This is a simplified representation
118
+ // In a real implementation, you would use a QR code library
119
+ const size = Math.min(width, height) - 40;
120
+ const x = (width - size) / 2;
121
+ const y = (height - size) / 2;
122
+
123
+ return `<rect x="${x}" y="${y}" width="${size}" height="${size}" fill="${options.lineColor}" stroke="${options.lineColor}" stroke-width="1"/>`;
124
+ }
125
+
126
+ /**
127
+ * Create linear barcode SVG representation
128
+ * @param {string} data - The data to encode
129
+ * @param {number} width - SVG width
130
+ * @param {number} height - SVG height
131
+ * @param {Object} options - Render options
132
+ * @returns {string} SVG content
133
+ */
134
+ createLinearBarcodeSVG(data, width, height, options) {
135
+ // This is a simplified representation
136
+ // In a real implementation, you would use a barcode library
137
+ const barWidth = 2;
138
+ const barHeight = height - (options.displayValue ? 30 : 0);
139
+ const startX = 20;
140
+ let currentX = startX;
141
+
142
+ let svg = '';
143
+ for (let i = 0; i < data.length; i++) {
144
+ const char = data.charCodeAt(i);
145
+ const barCount = (char % 5) + 1;
146
+
147
+ for (let j = 0; j < barCount; j++) {
148
+ svg += `<rect x="${currentX}" y="10" width="${barWidth}" height="${barHeight}" fill="${options.lineColor}"/>`;
149
+ currentX += barWidth * 2;
150
+ }
151
+ }
152
+
153
+ return svg;
154
+ }
155
+
156
+ /**
157
+ * Create XML document for JsBarcode
158
+ * @returns {Object} XML document
159
+ */
160
+ createXMLDocument() {
161
+ // Create a minimal XML document for JsBarcode
162
+ return {
163
+ createElement: (tagName) => ({
164
+ tagName,
165
+ setAttribute: () => {},
166
+ appendChild: () => {},
167
+ toSVG: () => '<svg></svg>',
168
+ }),
169
+ };
170
+ }
171
+
172
+ /**
173
+ * Map barcode type to JsBarcode format
174
+ * @param {string} type - The barcode type
175
+ * @returns {string} JsBarcode format
176
+ */
177
+ mapBarcodeType(type) {
178
+ const typeMap = {
179
+ code128: 'CODE128',
180
+ code128a: 'CODE128A',
181
+ code128b: 'CODE128B',
182
+ code128c: 'CODE128C',
183
+ code128auto: 'CODE128',
184
+ code39: 'CODE39',
185
+ code39extended: 'CODE39',
186
+ code39checksum: 'CODE39',
187
+ code39auto: 'CODE39',
188
+ code93: 'CODE93',
189
+ ean13: 'EAN13',
190
+ ean8: 'EAN8',
191
+ upca: 'UPC',
192
+ upce: 'UPC',
193
+ codabar: 'codabar',
194
+ code11: 'CODE11',
195
+ msi: 'MSI',
196
+ pharmazentral: 'pharmazentral',
197
+ interleaved25: 'ITF',
198
+ standard25: 'STD25',
199
+ };
200
+
201
+ return typeMap[type] || 'CODE128';
202
+ }
203
+
204
+ /**
205
+ * Get default options
206
+ * @returns {Object} Default options
207
+ */
208
+ getDefaultOptions() {
209
+ return { ...this.defaultOptions };
210
+ }
211
+
212
+ /**
213
+ * Set default options
214
+ * @param {Object} options - New default options
215
+ */
216
+ setDefaultOptions(options) {
217
+ this.defaultOptions = { ...this.defaultOptions, ...options };
218
+ }
219
+ }
220
+
221
+ module.exports = SVGRenderer;
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Barcode Service - Core service for barcode generation
3
+ */
4
+
5
+ const { BarcodeTypes } = require('../types/BarcodeTypes');
6
+ const { RenderFormats } = require('../renderers/RenderFormats');
7
+ const PNGRenderer = require('../renderers/PNGRenderer');
8
+ const SVGRenderer = require('../renderers/SVGRenderer');
9
+ const HTMLRenderer = require('../renderers/HTMLRenderer');
10
+ const PDFRenderer = require('../renderers/PDFRenderer');
11
+ const { Validator } = require('../validators/Validator');
12
+
13
+ class BarcodeService {
14
+ constructor() {
15
+ this.renderers = {
16
+ png: new PNGRenderer(),
17
+ svg: new SVGRenderer(),
18
+ html: new HTMLRenderer(),
19
+ pdf: new PDFRenderer(),
20
+ };
21
+ this.validator = new Validator();
22
+ }
23
+
24
+ /**
25
+ * Generate a barcode
26
+ * @param {string} data - The data to encode
27
+ * @param {string} type - The barcode type
28
+ * @param {string} format - The output format
29
+ * @param {Object} options - Additional options
30
+ * @returns {Buffer|string} Generated barcode
31
+ */
32
+ generate(data, type = 'code128', format = 'png', options = {}) {
33
+ // Validate inputs
34
+ if (!data || typeof data !== 'string') {
35
+ throw new Error('Data must be a non-empty string');
36
+ }
37
+
38
+ if (!BarcodeTypes.isValid(type)) {
39
+ throw new Error(
40
+ `Invalid barcode type: ${type}. Supported types: ${BarcodeTypes.getAll().join(
41
+ ', '
42
+ )}`
43
+ );
44
+ }
45
+
46
+ if (!RenderFormats.isValid(format)) {
47
+ throw new Error(
48
+ `Invalid format: ${format}. Supported formats: ${RenderFormats.getAll().join(
49
+ ', '
50
+ )}`
51
+ );
52
+ }
53
+
54
+ // Validate data for the specific barcode type
55
+ const validation = this.validator.validate(data, type);
56
+ if (!validation.valid) {
57
+ throw new Error(`Invalid data for ${type}: ${validation.error}`);
58
+ }
59
+
60
+ // Get renderer
61
+ const renderer = this.renderers[format];
62
+ if (!renderer) {
63
+ throw new Error(`No renderer available for format: ${format}`);
64
+ }
65
+
66
+ // Generate barcode
67
+ return renderer.render(data, type, options);
68
+ }
69
+
70
+ /**
71
+ * Generate a barcode in PNG format
72
+ * @param {string} data - The data to encode
73
+ * @param {string} type - The barcode type
74
+ * @param {Object} options - Additional options
75
+ * @returns {Buffer} PNG buffer
76
+ */
77
+ png(data, type = 'code128', options = {}) {
78
+ return this.generate(data, type, 'png', options);
79
+ }
80
+
81
+ /**
82
+ * Generate a barcode in SVG format
83
+ * @param {string} data - The data to encode
84
+ * @param {string} type - The barcode type
85
+ * @param {Object} options - Additional options
86
+ * @returns {string} SVG string
87
+ */
88
+ svg(data, type = 'code128', options = {}) {
89
+ return this.generate(data, type, 'svg', options);
90
+ }
91
+
92
+ /**
93
+ * Generate a barcode in HTML format
94
+ * @param {string} data - The data to encode
95
+ * @param {string} type - The barcode type
96
+ * @param {Object} options - Additional options
97
+ * @returns {string} HTML string
98
+ */
99
+ html(data, type = 'code128', options = {}) {
100
+ return this.generate(data, type, 'html', options);
101
+ }
102
+
103
+ /**
104
+ * Generate a barcode in PDF format
105
+ * @param {string} data - The data to encode
106
+ * @param {string} type - The barcode type
107
+ * @param {Object} options - Additional options
108
+ * @returns {Buffer} PDF buffer
109
+ */
110
+ pdf(data, type = 'code128', options = {}) {
111
+ return this.generate(data, type, 'pdf', options);
112
+ }
113
+
114
+ /**
115
+ * Generate multiple barcodes in batch
116
+ * @param {Array} items - Array of barcode generation items
117
+ * @returns {Array} Array of generated barcodes
118
+ */
119
+ batch(items) {
120
+ if (!Array.isArray(items)) {
121
+ throw new Error('Items must be an array');
122
+ }
123
+
124
+ return items.map((item, index) => {
125
+ try {
126
+ const { data, type = 'code128', format = 'png', options = {} } = item;
127
+ return {
128
+ index,
129
+ success: true,
130
+ result: this.generate(data, type, format, options),
131
+ data,
132
+ type,
133
+ format,
134
+ };
135
+ } catch (error) {
136
+ return {
137
+ index,
138
+ success: false,
139
+ error: error.message,
140
+ data: item.data,
141
+ type: item.type || 'code128',
142
+ format: item.format || 'png',
143
+ };
144
+ }
145
+ });
146
+ }
147
+
148
+ /**
149
+ * Validate data for a specific barcode type
150
+ * @param {string} data - The data to validate
151
+ * @param {string} type - The barcode type
152
+ * @returns {Object} Validation result
153
+ */
154
+ validate(data, type) {
155
+ return this.validator.validate(data, type);
156
+ }
157
+
158
+ /**
159
+ * Get available barcode types
160
+ * @returns {Array} Array of barcode types
161
+ */
162
+ getBarcodeTypes() {
163
+ return BarcodeTypes.getAll();
164
+ }
165
+
166
+ /**
167
+ * Get available render formats
168
+ * @returns {Array} Array of render formats
169
+ */
170
+ getRenderFormats() {
171
+ return RenderFormats.getAll();
172
+ }
173
+ }
174
+
175
+ module.exports = BarcodeService;
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Barcode Types - Supported barcode types and their configurations
3
+ */
4
+
5
+ class BarcodeTypes {
6
+ static TYPES = {
7
+ // Linear Barcodes
8
+ CODE128: 'code128',
9
+ CODE128A: 'code128a',
10
+ CODE128B: 'code128b',
11
+ CODE128C: 'code128c',
12
+ CODE128AUTO: 'code128auto',
13
+ CODE39: 'code39',
14
+ CODE39EXTENDED: 'code39extended',
15
+ CODE39CHECKSUM: 'code39checksum',
16
+ CODE39AUTO: 'code39auto',
17
+ CODE93: 'code93',
18
+ CODE25: 'code25',
19
+ CODE25AUTO: 'code25auto',
20
+ CODE32: 'code32',
21
+ STANDARD25: 'standard25',
22
+ STANDARD25CHECKSUM: 'standard25checksum',
23
+ INTERLEAVED25: 'interleaved25',
24
+ INTERLEAVED25CHECKSUM: 'interleaved25checksum',
25
+ INTERLEAVED25AUTO: 'interleaved25auto',
26
+ MSI: 'msi',
27
+ MSICHECKSUM: 'msichecksum',
28
+ MSIAUTO: 'msiauto',
29
+
30
+ // EAN/UPC Family
31
+ EAN13: 'ean13',
32
+ EAN8: 'ean8',
33
+ EAN2: 'ean2',
34
+ EAN5: 'ean5',
35
+ UPCA: 'upca',
36
+ UPCE: 'upce',
37
+ ITF14: 'itf14',
38
+
39
+ // Postal Barcodes
40
+ POSTNET: 'postnet',
41
+ PLANET: 'planet',
42
+ RMS4CC: 'rms4cc',
43
+ KIX: 'kix',
44
+ IMB: 'imb',
45
+
46
+ // Specialized Barcodes
47
+ CODABAR: 'codabar',
48
+ CODE11: 'code11',
49
+ PHARMACODE: 'pharmacode',
50
+ PHARMACODETWOTRACKS: 'pharmacodetwotracks',
51
+
52
+ // 2D Matrix Codes
53
+ QRCODE: 'qrcode',
54
+ DATAMATRIX: 'datamatrix',
55
+ AZTEC: 'aztec',
56
+ PDF417: 'pdf417',
57
+ MICROQR: 'microqr',
58
+ MAXICODE: 'maxicode',
59
+
60
+ // Stacked Linear Codes
61
+ CODE16K: 'code16k',
62
+ CODE49: 'code49',
63
+ };
64
+
65
+ static CATEGORIES = {
66
+ LINEAR: [
67
+ 'code128',
68
+ 'code128a',
69
+ 'code128b',
70
+ 'code128c',
71
+ 'code128auto',
72
+ 'code39',
73
+ 'code39extended',
74
+ 'code39checksum',
75
+ 'code39auto',
76
+ 'code93',
77
+ 'code25',
78
+ 'code25auto',
79
+ 'code32',
80
+ 'standard25',
81
+ 'standard25checksum',
82
+ 'interleaved25',
83
+ 'interleaved25checksum',
84
+ 'interleaved25auto',
85
+ 'msi',
86
+ 'msichecksum',
87
+ 'msiauto',
88
+ ],
89
+ EAN_UPC: ['ean13', 'ean8', 'ean2', 'ean5', 'upca', 'upce', 'itf14'],
90
+ POSTAL: ['postnet', 'planet', 'rms4cc', 'kix', 'imb'],
91
+ SPECIALIZED: ['codabar', 'code11', 'pharmacode', 'pharmacodetwotracks'],
92
+ MATRIX_2D: [
93
+ 'qrcode',
94
+ 'datamatrix',
95
+ 'aztec',
96
+ 'pdf417',
97
+ 'microqr',
98
+ 'maxicode',
99
+ ],
100
+ STACKED: ['code16k', 'code49'],
101
+ };
102
+
103
+ /**
104
+ * Get all supported barcode types
105
+ * @returns {Array} Array of all barcode types
106
+ */
107
+ static getAll() {
108
+ return Object.values(this.TYPES);
109
+ }
110
+
111
+ /**
112
+ * Get barcode types by category
113
+ * @param {string} category - The category name
114
+ * @returns {Array} Array of barcode types in the category
115
+ */
116
+ static getByCategory(category) {
117
+ return this.CATEGORIES[category.toUpperCase()] || [];
118
+ }
119
+
120
+ /**
121
+ * Get all categories
122
+ * @returns {Array} Array of category names
123
+ */
124
+ static getCategories() {
125
+ return Object.keys(this.CATEGORIES);
126
+ }
127
+
128
+ /**
129
+ * Check if a barcode type is valid
130
+ * @param {string} type - The barcode type to check
131
+ * @returns {boolean} True if valid
132
+ */
133
+ static isValid(type) {
134
+ return Object.values(this.TYPES).includes(type);
135
+ }
136
+
137
+ /**
138
+ * Get barcode type configuration
139
+ * @param {string} type - The barcode type
140
+ * @returns {Object} Configuration object
141
+ */
142
+ static getConfig(type) {
143
+ const configs = {
144
+ code128: { minLength: 1, maxLength: 80, charset: 'ASCII' },
145
+ code128a: { minLength: 1, maxLength: 80, charset: 'ASCII A' },
146
+ code128b: { minLength: 1, maxLength: 80, charset: 'ASCII B' },
147
+ code128c: { minLength: 2, maxLength: 80, charset: 'Numeric' },
148
+ code39: {
149
+ minLength: 1,
150
+ maxLength: 43,
151
+ charset: '0-9, A-Z, space, -.$/+%',
152
+ },
153
+ code39extended: {
154
+ minLength: 1,
155
+ maxLength: 43,
156
+ charset: 'Extended ASCII',
157
+ },
158
+ code93: { minLength: 1, maxLength: 43, charset: '0-9, A-Z, -.$/+%' },
159
+ ean13: { minLength: 12, maxLength: 13, charset: 'Numeric' },
160
+ ean8: { minLength: 7, maxLength: 8, charset: 'Numeric' },
161
+ upca: { minLength: 11, maxLength: 12, charset: 'Numeric' },
162
+ upce: { minLength: 6, maxLength: 8, charset: 'Numeric' },
163
+ qrcode: { minLength: 1, maxLength: 2953, charset: 'Unicode' },
164
+ datamatrix: { minLength: 1, maxLength: 2335, charset: 'Unicode' },
165
+ pdf417: { minLength: 1, maxLength: 1850, charset: 'Unicode' },
166
+ };
167
+
168
+ return (
169
+ configs[type] || { minLength: 1, maxLength: 100, charset: 'Unknown' }
170
+ );
171
+ }
172
+
173
+ /**
174
+ * Get barcode type description
175
+ * @param {string} type - The barcode type
176
+ * @returns {string} Description
177
+ */
178
+ static getDescription(type) {
179
+ const descriptions = {
180
+ code128: 'Code 128 - High-density linear barcode',
181
+ code39: 'Code 39 - Alphanumeric barcode',
182
+ ean13: 'EAN-13 - European Article Number',
183
+ ean8: 'EAN-8 - European Article Number (short)',
184
+ upca: 'UPC-A - Universal Product Code',
185
+ upce: 'UPC-E - Universal Product Code (compressed)',
186
+ qrcode: 'QR Code - 2D matrix barcode',
187
+ datamatrix: 'Data Matrix - 2D matrix barcode',
188
+ pdf417: 'PDF417 - 2D stacked barcode',
189
+ };
190
+
191
+ return descriptions[type] || 'Unknown barcode type';
192
+ }
193
+ }
194
+
195
+ module.exports = { BarcodeTypes };