isahaq-barcode 1.9.0 → 2.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.
@@ -2,26 +2,11 @@
2
2
  * SVG Renderer - Renders barcodes as SVG
3
3
  */
4
4
 
5
- const JsBarcode = require('jsbarcode');
5
+ const { BarcodeEncoder } = require('../encoders/BarcodeEncoder');
6
6
 
7
7
  class SVGRenderer {
8
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
- };
9
+ this.defaultOptions = BarcodeEncoder.getDefaultOptions();
25
10
  }
26
11
 
27
12
  /**
@@ -29,176 +14,17 @@ class SVGRenderer {
29
14
  * @param {string} data - The data to encode
30
15
  * @param {string} type - The barcode type
31
16
  * @param {Object} options - Render options
32
- * @returns {string} SVG string
17
+ * @returns {string} SVG markup
33
18
  */
34
19
  render(data, type, options = {}) {
35
20
  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(),
21
+ return BarcodeEncoder.toSvg(data, type, {
22
+ ...this.defaultOptions,
23
+ ...options,
60
24
  });
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
- }
25
+ } catch (error) {
26
+ throw new Error(`SVG rendering failed: ${error.message}`);
151
27
  }
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
28
  }
203
29
 
204
30
  /**
@@ -10,6 +10,9 @@ const HTMLRenderer = require('../renderers/HTMLRenderer');
10
10
  const PDFRenderer = require('../renderers/PDFRenderer');
11
11
  const { Validator } = require('../validators/Validator');
12
12
 
13
+ /** Formats that can be produced without any asynchronous work */
14
+ const SYNC_FORMATS = ['svg', 'html'];
15
+
13
16
  class BarcodeService {
14
17
  constructor() {
15
18
  this.renderers = {
@@ -22,15 +25,13 @@ class BarcodeService {
22
25
  }
23
26
 
24
27
  /**
25
- * Generate a barcode
28
+ * Validate the arguments of a generate call and return the matching renderer
26
29
  * @param {string} data - The data to encode
27
30
  * @param {string} type - The barcode type
28
31
  * @param {string} format - The output format
29
- * @param {Object} options - Additional options
30
- * @returns {Buffer|string} Generated barcode
32
+ * @returns {Object} The renderer for the requested format
31
33
  */
32
- generate(data, type = 'code128', format = 'png', options = {}) {
33
- // Validate inputs
34
+ resolve(data, type, format) {
34
35
  if (!data || typeof data !== 'string') {
35
36
  throw new Error('Data must be a non-empty string');
36
37
  }
@@ -51,19 +52,45 @@ class BarcodeService {
51
52
  );
52
53
  }
53
54
 
54
- // Validate data for the specific barcode type
55
55
  const validation = this.validator.validate(data, type);
56
56
  if (!validation.valid) {
57
57
  throw new Error(`Invalid data for ${type}: ${validation.error}`);
58
58
  }
59
59
 
60
- // Get renderer
61
- const renderer = this.renderers[format];
62
- if (!renderer) {
63
- throw new Error(`No renderer available for format: ${format}`);
60
+ return this.renderers[format];
61
+ }
62
+
63
+ /**
64
+ * Generate a barcode
65
+ * @param {string} data - The data to encode
66
+ * @param {string} type - The barcode type
67
+ * @param {string} format - The output format
68
+ * @param {Object} options - Additional options
69
+ * @returns {Promise<Buffer|string>} Generated barcode
70
+ */
71
+ async generate(data, type = 'code128', format = 'png', options = {}) {
72
+ const renderer = this.resolve(data, type, format);
73
+ return renderer.render(data, type, options);
74
+ }
75
+
76
+ /**
77
+ * Generate a barcode synchronously (SVG and HTML only)
78
+ * @param {string} data - The data to encode
79
+ * @param {string} type - The barcode type
80
+ * @param {string} format - The output format (svg or html)
81
+ * @param {Object} options - Additional options
82
+ * @returns {string} Generated barcode
83
+ */
84
+ generateSync(data, type = 'code128', format = 'svg', options = {}) {
85
+ if (!SYNC_FORMATS.includes(format)) {
86
+ throw new Error(
87
+ `Format ${format} cannot be generated synchronously. Synchronous formats: ${SYNC_FORMATS.join(
88
+ ', '
89
+ )}`
90
+ );
64
91
  }
65
92
 
66
- // Generate barcode
93
+ const renderer = this.resolve(data, type, format);
67
94
  return renderer.render(data, type, options);
68
95
  }
69
96
 
@@ -72,9 +99,9 @@ class BarcodeService {
72
99
  * @param {string} data - The data to encode
73
100
  * @param {string} type - The barcode type
74
101
  * @param {Object} options - Additional options
75
- * @returns {Buffer} PNG buffer
102
+ * @returns {Promise<Buffer>} PNG buffer
76
103
  */
77
- png(data, type = 'code128', options = {}) {
104
+ async png(data, type = 'code128', options = {}) {
78
105
  return this.generate(data, type, 'png', options);
79
106
  }
80
107
 
@@ -83,66 +110,99 @@ class BarcodeService {
83
110
  * @param {string} data - The data to encode
84
111
  * @param {string} type - The barcode type
85
112
  * @param {Object} options - Additional options
86
- * @returns {string} SVG string
113
+ * @returns {Promise<string>} SVG markup
87
114
  */
88
- svg(data, type = 'code128', options = {}) {
115
+ async svg(data, type = 'code128', options = {}) {
89
116
  return this.generate(data, type, 'svg', options);
90
117
  }
91
118
 
119
+ /**
120
+ * Generate a barcode in SVG format synchronously
121
+ * @param {string} data - The data to encode
122
+ * @param {string} type - The barcode type
123
+ * @param {Object} options - Additional options
124
+ * @returns {string} SVG markup
125
+ */
126
+ svgSync(data, type = 'code128', options = {}) {
127
+ return this.generateSync(data, type, 'svg', options);
128
+ }
129
+
92
130
  /**
93
131
  * Generate a barcode in HTML format
94
132
  * @param {string} data - The data to encode
95
133
  * @param {string} type - The barcode type
96
134
  * @param {Object} options - Additional options
97
- * @returns {string} HTML string
135
+ * @returns {Promise<string>} HTML markup
98
136
  */
99
- html(data, type = 'code128', options = {}) {
137
+ async html(data, type = 'code128', options = {}) {
100
138
  return this.generate(data, type, 'html', options);
101
139
  }
102
140
 
141
+ /**
142
+ * Generate a barcode in HTML format synchronously
143
+ * @param {string} data - The data to encode
144
+ * @param {string} type - The barcode type
145
+ * @param {Object} options - Additional options
146
+ * @returns {string} HTML markup
147
+ */
148
+ htmlSync(data, type = 'code128', options = {}) {
149
+ return this.generateSync(data, type, 'html', options);
150
+ }
151
+
103
152
  /**
104
153
  * Generate a barcode in PDF format
105
154
  * @param {string} data - The data to encode
106
155
  * @param {string} type - The barcode type
107
156
  * @param {Object} options - Additional options
108
- * @returns {Buffer} PDF buffer
157
+ * @returns {Promise<Buffer>} PDF buffer
109
158
  */
110
- pdf(data, type = 'code128', options = {}) {
159
+ async pdf(data, type = 'code128', options = {}) {
111
160
  return this.generate(data, type, 'pdf', options);
112
161
  }
113
162
 
114
163
  /**
115
- * Generate multiple barcodes in batch
116
- * @param {Array} items - Array of barcode generation items
117
- * @returns {Array} Array of generated barcodes
164
+ * Generate multiple barcodes in batch. Individual failures are reported in
165
+ * the result instead of rejecting the whole batch.
166
+ * @param {Array<Object>} items - Array of barcode generation items
167
+ * @returns {Promise<Array<Object>>} Array of results
118
168
  */
119
- batch(items) {
169
+ async batch(items) {
120
170
  if (!Array.isArray(items)) {
121
171
  throw new Error('Items must be an array');
122
172
  }
123
173
 
124
- return items.map((item, index) => {
174
+ const results = [];
175
+
176
+ for (const [index, item] of items.entries()) {
177
+ const {
178
+ data,
179
+ type = 'code128',
180
+ format = 'png',
181
+ options = {},
182
+ } = item || {};
183
+
125
184
  try {
126
- const { data, type = 'code128', format = 'png', options = {} } = item;
127
- return {
185
+ results.push({
128
186
  index,
129
187
  success: true,
130
- result: this.generate(data, type, format, options),
188
+ result: await this.generate(data, type, format, options),
131
189
  data,
132
190
  type,
133
191
  format,
134
- };
192
+ });
135
193
  } catch (error) {
136
- return {
194
+ results.push({
137
195
  index,
138
196
  success: false,
139
197
  error: error.message,
140
- data: item.data,
141
- type: item.type || 'code128',
142
- format: item.format || 'png',
143
- };
198
+ data,
199
+ type,
200
+ format,
201
+ });
144
202
  }
145
- });
203
+ }
204
+
205
+ return results;
146
206
  }
147
207
 
148
208
  /**
@@ -157,7 +217,7 @@ class BarcodeService {
157
217
 
158
218
  /**
159
219
  * Get available barcode types
160
- * @returns {Array} Array of barcode types
220
+ * @returns {string[]} Array of barcode types
161
221
  */
162
222
  getBarcodeTypes() {
163
223
  return BarcodeTypes.getAll();
@@ -165,7 +225,7 @@ class BarcodeService {
165
225
 
166
226
  /**
167
227
  * Get available render formats
168
- * @returns {Array} Array of render formats
228
+ * @returns {string[]} Array of render formats
169
229
  */
170
230
  getRenderFormats() {
171
231
  return RenderFormats.getAll();