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.
- package/CHANGELOG.md +107 -0
- package/LICENSE +21 -0
- package/README.md +317 -553
- package/bin/generate.js +171 -134
- package/browser.js +163 -170
- package/index.d.ts +497 -0
- package/index.js +119 -51
- package/package.json +69 -41
- package/src/builders/QrCodeBuilder.js +328 -165
- package/src/encoders/BarcodeEncoder.js +260 -0
- package/src/renderers/HTMLRenderer.js +36 -169
- package/src/renderers/PDFRenderer.js +108 -130
- package/src/renderers/PNGRenderer.js +7 -83
- package/src/renderers/RenderFormats.js +89 -38
- package/src/renderers/SVGRenderer.js +8 -182
- package/src/services/BarcodeService.js +96 -36
- package/src/types/BarcodeTypes.js +535 -144
- package/src/validators/Validator.js +140 -122
- package/.eslintrc.js +0 -29
- package/.prettierignore +0 -11
- package/.prettierrc +0 -11
- package/eslint.config.js +0 -67
- package/examples/basic-usage.js +0 -58
- package/examples/batch-example.json +0 -56
- package/examples/express-server.js +0 -163
- package/jest.config.js +0 -13
- package/tests/BarcodeGenerator.test.js +0 -187
- package/tests/BarcodeService.test.js +0 -76
- package/tests/QrCodeBuilder.test.js +0 -130
- package/tests/setup.js +0 -59
- package/webpack.config.js +0 -26
package/README.md
CHANGED
|
@@ -1,338 +1,281 @@
|
|
|
1
1
|
# Isahaq Barcode Generator
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Barcode and QR code generation for Node.js and the browser. 45 symbologies, PNG / SVG / HTML / PDF output, a CLI, and a builder for QR codes with logos and watermarks.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/isahaq-barcode)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- [Features](#-features)
|
|
13
|
-
- [Installation](#-installation)
|
|
14
|
-
- [Quick Start](#-quick-start)
|
|
15
|
-
- [Supported Barcode Types](#-supported-barcode-types)
|
|
16
|
-
- [Usage Examples](#-usage-examples)
|
|
17
|
-
- [Express.js Integration](#-expressjs-integration)
|
|
18
|
-
- [CLI Usage](#-cli-usage)
|
|
19
|
-
- [API Reference](#-api-reference)
|
|
20
|
-
- [Contributing](#-contributing)
|
|
8
|
+
Encoding is done by [bwip-js](https://github.com/metafloor/bwip-js) (a port of the
|
|
9
|
+
BWIPP reference implementation), so every advertised type and output format
|
|
10
|
+
produces a real, scannable symbology. `npm run verify:scan` proves it by decoding
|
|
11
|
+
generated barcodes with ZXing.
|
|
21
12
|
|
|
22
13
|
---
|
|
23
14
|
|
|
24
|
-
##
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
15
|
+
## Contents
|
|
16
|
+
|
|
17
|
+
- [Installation](#installation)
|
|
18
|
+
- [Quick start](#quick-start)
|
|
19
|
+
- [Upgrading from 1.x](#upgrading-from-1x)
|
|
20
|
+
- [Supported barcode types](#supported-barcode-types)
|
|
21
|
+
- [Output formats](#output-formats)
|
|
22
|
+
- [Render options](#render-options)
|
|
23
|
+
- [QR codes with logos, labels and watermarks](#qr-codes-with-logos-labels-and-watermarks)
|
|
24
|
+
- [Validation](#validation)
|
|
25
|
+
- [Batch generation](#batch-generation)
|
|
26
|
+
- [Express.js integration](#expressjs-integration)
|
|
27
|
+
- [Browser usage](#browser-usage)
|
|
28
|
+
- [CLI](#cli)
|
|
29
|
+
- [TypeScript](#typescript)
|
|
30
|
+
- [API reference](#api-reference)
|
|
31
|
+
- [Development](#development)
|
|
36
32
|
|
|
37
33
|
---
|
|
38
34
|
|
|
39
|
-
##
|
|
35
|
+
## Installation
|
|
40
36
|
|
|
41
37
|
```bash
|
|
42
38
|
npm install isahaq-barcode
|
|
43
39
|
```
|
|
44
40
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
## ๐ Universal Compatibility
|
|
41
|
+
Requires Node.js 18 or newer.
|
|
48
42
|
|
|
49
|
-
|
|
43
|
+
`canvas` is an **optional** dependency. It is only needed for QR codes that
|
|
44
|
+
composite a logo, label or watermark. Everything else - all barcode types, all
|
|
45
|
+
output formats, plain QR codes - works without it, so installs never fail on a
|
|
46
|
+
missing native toolchain.
|
|
50
47
|
|
|
51
|
-
|
|
48
|
+
```bash
|
|
49
|
+
npm install canvas # only if you need QR logos/labels/watermarks
|
|
50
|
+
```
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
- **Canvas Support**: High-quality image generation with Node.js canvas
|
|
55
|
-
- **File Operations**: Save files directly to filesystem
|
|
56
|
-
- **CLI Tools**: Command-line interface available
|
|
52
|
+
## Quick start
|
|
57
53
|
|
|
58
|
-
|
|
54
|
+
```javascript
|
|
55
|
+
const fs = require('fs/promises');
|
|
56
|
+
const BarcodeGenerator = require('isahaq-barcode');
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
// PNG (returns a Promise<Buffer>)
|
|
59
|
+
await fs.writeFile(
|
|
60
|
+
'code128.png',
|
|
61
|
+
await BarcodeGenerator.png('1234567890', 'code128')
|
|
62
|
+
);
|
|
64
63
|
|
|
65
|
-
|
|
64
|
+
// SVG - async or sync, whichever suits the call site
|
|
65
|
+
const svg = await BarcodeGenerator.svg('5901234123457', 'ean13');
|
|
66
|
+
const svgNow = BarcodeGenerator.svgSync('5901234123457', 'ean13');
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
// HTML fragment with an inline SVG
|
|
69
|
+
const html = BarcodeGenerator.htmlSync('1234567890', 'code128');
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
// PDF
|
|
72
|
+
await fs.writeFile(
|
|
73
|
+
'label.pdf',
|
|
74
|
+
await BarcodeGenerator.pdf('1234567890', 'code128', { fitToBarcode: true })
|
|
75
|
+
);
|
|
72
76
|
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
// 2D symbologies - size them in pixels
|
|
78
|
+
const qr = await BarcodeGenerator.png('https://example.com', 'qrcode', {
|
|
79
|
+
size: 400,
|
|
80
|
+
});
|
|
81
|
+
const dm = await BarcodeGenerator.svg('SHIPMENT-000123', 'datamatrix', {
|
|
82
|
+
size: 200,
|
|
78
83
|
});
|
|
79
84
|
```
|
|
80
85
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
```javascript
|
|
84
|
-
// pages/api/barcode.js or app/api/barcode/route.js
|
|
85
|
-
import BarcodeGenerator from 'isahaq-barcode';
|
|
86
|
-
|
|
87
|
-
export default function handler(req, res) {
|
|
88
|
-
const barcode = BarcodeGenerator.png(req.query.data, 'code128');
|
|
89
|
-
res.setHeader('Content-Type', 'image/png');
|
|
90
|
-
res.send(barcode);
|
|
91
|
-
}
|
|
92
|
-
```
|
|
86
|
+
## Upgrading from 1.x
|
|
93
87
|
|
|
94
|
-
|
|
88
|
+
Version 2 rewrote the rendering core. In 1.x only PNG output was a real barcode:
|
|
89
|
+
SVG, HTML and PDF drew decorative bars from character codes, and unsupported
|
|
90
|
+
types silently produced a Code 128. Fixing that required two API changes:
|
|
95
91
|
|
|
96
92
|
```javascript
|
|
97
|
-
//
|
|
98
|
-
|
|
93
|
+
// 1.x - synchronous
|
|
94
|
+
const buffer = BarcodeGenerator.png('1234567890', 'code128');
|
|
95
|
+
const svg = BarcodeGenerator.svg('1234567890', 'code128');
|
|
96
|
+
const results = BarcodeGenerator.batch(items);
|
|
99
97
|
|
|
100
|
-
//
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
};
|
|
98
|
+
// 2.x - promises, with sync variants for the text formats
|
|
99
|
+
const buffer = await BarcodeGenerator.png('1234567890', 'code128');
|
|
100
|
+
const svg = BarcodeGenerator.svgSync('1234567890', 'code128'); // or await .svg(...)
|
|
101
|
+
const results = await BarcodeGenerator.batch(items);
|
|
105
102
|
```
|
|
106
103
|
|
|
107
|
-
|
|
104
|
+
See the [CHANGELOG](CHANGELOG.md) for the full list, including the removal of the
|
|
105
|
+
`jpg`/`jpeg` render formats (they never worked) and the corrected EAN-8 / UPC-A
|
|
106
|
+
check digit validation.
|
|
108
107
|
|
|
109
|
-
|
|
108
|
+
## Supported barcode types
|
|
110
109
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
resolve: {
|
|
114
|
-
fallback: {
|
|
115
|
-
fs: false,
|
|
116
|
-
path: false,
|
|
117
|
-
os: false,
|
|
118
|
-
canvas: false,
|
|
119
|
-
pdfkit: false,
|
|
120
|
-
chalk: false,
|
|
121
|
-
ora: false,
|
|
122
|
-
commander: false,
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
|
-
};
|
|
126
|
-
```
|
|
110
|
+
45 types across six categories. `BarcodeGenerator.getBarcodeTypeInfo(type)`
|
|
111
|
+
returns the metadata for any of them.
|
|
127
112
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
113
|
+
| Category | Types |
|
|
114
|
+
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
115
|
+
| **Linear** | `code128`, `code128a`, `code128b`, `code128c`, `code128auto`, `code39`, `code39extended`, `code39checksum`, `code39auto`, `code93`, `code25`, `code25auto`, `code32`, `standard25`, `standard25checksum`, `interleaved25`, `interleaved25checksum`, `interleaved25auto`, `msi`, `msichecksum`, `msiauto` |
|
|
116
|
+
| **EAN / UPC** | `ean13`, `ean8`, `ean2`, `ean5`, `upca`, `upce`, `itf14` |
|
|
117
|
+
| **Postal** | `postnet`, `planet`, `rms4cc`, `kix`, `imb` |
|
|
118
|
+
| **Specialized** | `codabar`, `code11`, `pharmacode`, `pharmacodetwotracks` |
|
|
119
|
+
| **2D matrix** | `qrcode`, `datamatrix`, `aztec`, `pdf417`, `microqr`, `maxicode` |
|
|
120
|
+
| **Stacked** | `code16k`, `code49` |
|
|
131
121
|
|
|
132
122
|
```javascript
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
ora: false,
|
|
144
|
-
commander: false,
|
|
145
|
-
};
|
|
146
|
-
return config;
|
|
147
|
-
},
|
|
148
|
-
};
|
|
123
|
+
BarcodeGenerator.getBarcodeTypes(); // all 45 ids
|
|
124
|
+
BarcodeGenerator.getBarcodeCategories(); // ['LINEAR', 'EAN_UPC', ...]
|
|
125
|
+
BarcodeGenerator.getBarcodeTypesByCategory('matrix_2d'); // ['qrcode', 'datamatrix', ...]
|
|
126
|
+
|
|
127
|
+
BarcodeGenerator.getBarcodeTypeInfo('ean13');
|
|
128
|
+
// {
|
|
129
|
+
// type: 'ean13', name: 'EAN-13', category: 'EAN_UPC', symbology: 'ean13',
|
|
130
|
+
// description: 'EAN-13 - European Article Number',
|
|
131
|
+
// minLength: 12, maxLength: 13, charset: 'Numeric'
|
|
132
|
+
// }
|
|
149
133
|
```
|
|
150
134
|
|
|
151
|
-
|
|
135
|
+
## Output formats
|
|
152
136
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
137
|
+
| Format | Method | Returns |
|
|
138
|
+
| ------ | ----------------------- | ---------------------------- |
|
|
139
|
+
| `png` | `png()` | `Promise<Buffer>` |
|
|
140
|
+
| `svg` | `svg()` / `svgSync()` | `Promise<string>` / `string` |
|
|
141
|
+
| `html` | `html()` / `htmlSync()` | `Promise<string>` / `string` |
|
|
142
|
+
| `pdf` | `pdf()` | `Promise<Buffer>` |
|
|
156
143
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
## ๐ Quick Start
|
|
144
|
+
`generate()` takes the format as an argument:
|
|
160
145
|
|
|
161
146
|
```javascript
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
// Generate PNG barcode
|
|
165
|
-
const pngBuffer = BarcodeGenerator.png('1234567890', 'code128');
|
|
166
|
-
|
|
167
|
-
// Generate SVG barcode
|
|
168
|
-
const svgString = BarcodeGenerator.svg('1234567890', 'ean13');
|
|
169
|
-
|
|
170
|
-
// Generate QR code with logo
|
|
171
|
-
const qrCode = BarcodeGenerator.modernQr({
|
|
172
|
-
data: 'https://example.com',
|
|
173
|
-
size: 300,
|
|
174
|
-
logoPath: 'path/to/logo.png',
|
|
175
|
-
label: 'Scan me!',
|
|
147
|
+
const output = await BarcodeGenerator.generate('1234567890', 'code128', 'pdf', {
|
|
148
|
+
pageSize: 'A4',
|
|
176
149
|
});
|
|
177
|
-
|
|
178
|
-
await qrCode.saveToFile('qr-code.png');
|
|
179
150
|
```
|
|
180
151
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
## ๐ Supported Barcode Types
|
|
184
|
-
|
|
185
|
-
### Linear Barcodes (1D)
|
|
186
|
-
|
|
187
|
-
| Type | Variants | Use Case |
|
|
188
|
-
| -------------- | ---------------------------------- | ----------------------------- |
|
|
189
|
-
| **Code 128** | A, B, C, Auto | General purpose, high density |
|
|
190
|
-
| **Code 39** | Standard, Extended, Checksum, Auto | Alphanumeric, automotive |
|
|
191
|
-
| **Code 93** | - | Compact alphanumeric |
|
|
192
|
-
| **EAN Family** | EAN-13, EAN-8, EAN-2, EAN-5 | Retail products (Europe) |
|
|
193
|
-
| **UPC Family** | UPC-A, UPC-E | Retail products (USA) |
|
|
194
|
-
| **Code 25** | Standard, Interleaved, Auto | Industrial, logistics |
|
|
195
|
-
| **ITF-14** | - | Shipping containers |
|
|
196
|
-
| **MSI** | Standard, Checksum, Auto | Inventory management |
|
|
197
|
-
| **Codabar** | - | Libraries, blood banks |
|
|
198
|
-
| **Code 11** | - | Telecommunications |
|
|
152
|
+
## Render options
|
|
199
153
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
154
|
+
```javascript
|
|
155
|
+
await BarcodeGenerator.png('1234567890', 'code128', {
|
|
156
|
+
width: 3, // module (narrow bar) width in px default 2
|
|
157
|
+
height: 140, // bar height in px, 1D only default 100
|
|
158
|
+
size: 400, // target size in px, 2D/stacked only
|
|
159
|
+
displayValue: true, // print the human readable text default true
|
|
160
|
+
fontSize: 24, // text size in px default 20
|
|
161
|
+
textAlign: 'center', // center | left | right | justify
|
|
162
|
+
textMargin: 2, // gap between bars and text in px
|
|
163
|
+
textColor: '#1d3557', // defaults to lineColor
|
|
164
|
+
lineColor: '#1d3557', // bar colour default #000000
|
|
165
|
+
background: '#f1faee', // background colour default #ffffff
|
|
166
|
+
margin: 24, // quiet zone in px, or use quietZone
|
|
167
|
+
marginTop: 10, // per-side overrides
|
|
168
|
+
quietZone: 10, // quiet zone in modules default 10
|
|
169
|
+
rotate: 'N', // N | R | L | I
|
|
170
|
+
});
|
|
171
|
+
```
|
|
214
172
|
|
|
215
|
-
|
|
173
|
+
**Quiet zone:** when no `margin` is given, the quiet zone is `quietZone` modules
|
|
174
|
+
(10 by default) rather than a fixed pixel count. Most specifications require at
|
|
175
|
+
least 10 narrow modules of clear space, and scanners reject codes with less. Pass
|
|
176
|
+
`margin` in pixels when you need an exact figure, or `margin: 0` for none.
|
|
216
177
|
|
|
217
|
-
**
|
|
178
|
+
**2D symbologies** keep their own aspect ratio: `height` does not apply, and
|
|
179
|
+
`size` is honoured by scaling the module size to the nearest whole number, so the
|
|
180
|
+
result lands close to - not exactly on - the requested pixel size.
|
|
218
181
|
|
|
219
|
-
|
|
182
|
+
PDF-only options: `pageWidth`, `pageHeight`, `pageSize` (for example `'A4'`),
|
|
183
|
+
`fitToBarcode` (size the page to the barcode plus its margins) and `title`.
|
|
220
184
|
|
|
221
|
-
|
|
185
|
+
HTML-only options: `id`, `className`, `includeStyles`.
|
|
222
186
|
|
|
223
|
-
|
|
187
|
+
Anything the encoder itself understands can be passed straight through:
|
|
224
188
|
|
|
225
189
|
```javascript
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
// PNG with custom options
|
|
229
|
-
const barcode = BarcodeGenerator.png('1234567890', 'code128', {
|
|
230
|
-
width: 3,
|
|
231
|
-
height: 150,
|
|
232
|
-
displayValue: true,
|
|
233
|
-
foregroundColor: '#000000',
|
|
234
|
-
backgroundColor: '#FFFFFF',
|
|
235
|
-
margin: 10,
|
|
190
|
+
await BarcodeGenerator.png('1234567890', 'code128', {
|
|
191
|
+
bwipOptions: { alttext: 'custom caption' },
|
|
236
192
|
});
|
|
237
|
-
|
|
238
|
-
// Convert to Base64 for web display
|
|
239
|
-
const base64Image = barcode.toString('base64');
|
|
240
|
-
console.log(`<img src="data:image/png;base64,${base64Image}" alt="Barcode" />`);
|
|
241
193
|
```
|
|
242
194
|
|
|
243
|
-
|
|
195
|
+
## QR codes with logos, labels and watermarks
|
|
244
196
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
data: 'https://example.com',
|
|
248
|
-
size: 300,
|
|
249
|
-
margin: 10,
|
|
250
|
-
|
|
251
|
-
// Logo configuration
|
|
252
|
-
logoPath: 'path/to/logo.png',
|
|
253
|
-
logoSize: 60, // Percentage
|
|
254
|
-
|
|
255
|
-
// Text elements
|
|
256
|
-
label: 'Scan me!',
|
|
257
|
-
watermark: 'Company Name',
|
|
258
|
-
watermarkPosition: 'bottom-center',
|
|
259
|
-
|
|
260
|
-
// Colors
|
|
261
|
-
foregroundColor: [0, 0, 0],
|
|
262
|
-
backgroundColor: [255, 255, 255],
|
|
197
|
+
`qrCode()` / `modernQr()` return a chainable builder. Plain codes need no extra
|
|
198
|
+
dependencies; a logo, label or watermark requires the optional `canvas` package.
|
|
263
199
|
|
|
264
|
-
|
|
200
|
+
```javascript
|
|
201
|
+
const buffer = await BarcodeGenerator.qrCode('https://example.com', {
|
|
202
|
+
size: 400,
|
|
265
203
|
errorCorrectionLevel: 'H',
|
|
266
|
-
});
|
|
204
|
+
}).generate();
|
|
267
205
|
|
|
268
|
-
//
|
|
269
|
-
|
|
206
|
+
// Or with the builder API
|
|
207
|
+
const QrCodeBuilder = BarcodeGenerator.QrCodeBuilder;
|
|
270
208
|
|
|
271
|
-
|
|
272
|
-
|
|
209
|
+
await QrCodeBuilder.create()
|
|
210
|
+
.data('https://example.com')
|
|
211
|
+
.size(400)
|
|
212
|
+
.margin(12)
|
|
213
|
+
.errorCorrectionLevel('H')
|
|
214
|
+
.foregroundColor([29, 53, 87]) // RGB array or '#1d3557'
|
|
215
|
+
.backgroundColor('#ffffff')
|
|
216
|
+
.logoPath('./logo.png') // path, URL or data URI
|
|
217
|
+
.logoSize(20) // percent of the QR code
|
|
218
|
+
.label('Scan me!')
|
|
219
|
+
.watermark('DRAFT', 'center')
|
|
220
|
+
.saveToFile('qr.png');
|
|
221
|
+
|
|
222
|
+
// Other outputs
|
|
223
|
+
const svg = await BarcodeGenerator.modernQr({
|
|
224
|
+
data: 'x',
|
|
225
|
+
format: 'svg',
|
|
226
|
+
}).generate();
|
|
227
|
+
const uri = await BarcodeGenerator.modernQr({ data: 'x' }).getDataUri();
|
|
273
228
|
```
|
|
274
229
|
|
|
275
|
-
|
|
230
|
+
Watermark positions: `top-left`, `top-center`, `top-right`, `left-center`,
|
|
231
|
+
`center`, `right-center`, `bottom-left`, `bottom-center`, `bottom-right`
|
|
232
|
+
(`getWatermarkPositions()`).
|
|
276
233
|
|
|
277
|
-
|
|
278
|
-
|
|
234
|
+
Keep `logoSize` at or below roughly 25%. A larger logo covers too many modules
|
|
235
|
+
for the error correction to recover, and the code stops scanning.
|
|
279
236
|
|
|
280
|
-
|
|
281
|
-
.data('https://example.com')
|
|
282
|
-
.size(300)
|
|
283
|
-
.margin(10)
|
|
284
|
-
.foregroundColor([0, 0, 0])
|
|
285
|
-
.backgroundColor([255, 255, 255])
|
|
286
|
-
.logoPath('path/to/logo.png')
|
|
287
|
-
.logoSize(60)
|
|
288
|
-
.label('Scan me!')
|
|
289
|
-
.watermark('Watermark Text', 'center')
|
|
290
|
-
.format('png')
|
|
291
|
-
.build();
|
|
292
|
-
|
|
293
|
-
await qrCode.saveToFile('qr-code.png');
|
|
294
|
-
```
|
|
237
|
+
## Validation
|
|
295
238
|
|
|
296
|
-
|
|
239
|
+
Validation runs automatically before generation, and is also available directly:
|
|
297
240
|
|
|
298
241
|
```javascript
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
{ data: '9876543210', type: 'code39', format: 'svg' },
|
|
302
|
-
{ data: 'https://example.com', type: 'qrcode', format: 'png' },
|
|
303
|
-
];
|
|
242
|
+
BarcodeGenerator.validate('5901234123457', 'ean13');
|
|
243
|
+
// { valid: true, data: '5901234123457', type: 'ean13', length: 13, charset: 'Numeric' }
|
|
304
244
|
|
|
305
|
-
|
|
245
|
+
BarcodeGenerator.validate('1234567890123', 'ean13');
|
|
246
|
+
// { valid: false, error: 'Invalid EAN-13 check digit (expected 8)' }
|
|
306
247
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
console.log(`โ Barcode ${index} generated`);
|
|
310
|
-
// result.data contains the generated barcode
|
|
311
|
-
} else {
|
|
312
|
-
console.error(`โ Barcode ${index} failed: ${result.error}`);
|
|
313
|
-
}
|
|
314
|
-
});
|
|
248
|
+
BarcodeGenerator.validate('123', 'ean13');
|
|
249
|
+
// { valid: false, error: 'Data too short. Minimum length: 12' }
|
|
315
250
|
```
|
|
316
251
|
|
|
317
|
-
|
|
252
|
+
EAN-13, EAN-8, UPC-A and ITF-14 accept the code with or without its trailing
|
|
253
|
+
check digit; when one is supplied it is verified.
|
|
318
254
|
|
|
319
|
-
|
|
320
|
-
const validation = BarcodeGenerator.validate('1234567890', 'code128');
|
|
321
|
-
|
|
322
|
-
if (validation.valid) {
|
|
323
|
-
console.log('โ Valid data');
|
|
324
|
-
console.log(` Length: ${validation.length}`);
|
|
325
|
-
console.log(` Charset: ${validation.charset}`);
|
|
326
|
-
} else {
|
|
327
|
-
console.error(`โ Invalid: ${validation.error}`);
|
|
328
|
-
}
|
|
329
|
-
```
|
|
255
|
+
## Batch generation
|
|
330
256
|
|
|
331
|
-
|
|
257
|
+
Per-item failures are reported in the result rather than rejecting the batch:
|
|
332
258
|
|
|
333
|
-
|
|
259
|
+
```javascript
|
|
260
|
+
const results = await BarcodeGenerator.batch([
|
|
261
|
+
{ data: '1234567890', type: 'code128', format: 'png' },
|
|
262
|
+
{
|
|
263
|
+
data: '5901234123457',
|
|
264
|
+
type: 'ean13',
|
|
265
|
+
format: 'svg',
|
|
266
|
+
options: { width: 3 },
|
|
267
|
+
},
|
|
268
|
+
{ data: 'nope', type: 'ean13', format: 'png' },
|
|
269
|
+
]);
|
|
270
|
+
|
|
271
|
+
// [
|
|
272
|
+
// { index: 0, success: true, result: <Buffer ...>, data: '1234567890', type: 'code128', format: 'png' },
|
|
273
|
+
// { index: 1, success: true, result: '<svg ...', data: '5901234123457', type: 'ean13', format: 'svg' },
|
|
274
|
+
// { index: 2, success: false, error: 'Invalid data for ean13: Data too short. Minimum length: 12', ... }
|
|
275
|
+
// ]
|
|
276
|
+
```
|
|
334
277
|
|
|
335
|
-
|
|
278
|
+
## Express.js integration
|
|
336
279
|
|
|
337
280
|
```javascript
|
|
338
281
|
const express = require('express');
|
|
@@ -340,361 +283,182 @@ const BarcodeGenerator = require('isahaq-barcode');
|
|
|
340
283
|
|
|
341
284
|
const app = express();
|
|
342
285
|
|
|
343
|
-
|
|
344
|
-
app.get('/barcode/:data', (req, res) => {
|
|
345
|
-
const { data } = req.params;
|
|
286
|
+
app.get('/barcode/:data', async (req, res) => {
|
|
346
287
|
const { type = 'code128', format = 'png' } = req.query;
|
|
347
288
|
|
|
348
289
|
try {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
contentType = 'image/svg+xml';
|
|
359
|
-
break;
|
|
360
|
-
case 'html':
|
|
361
|
-
result = BarcodeGenerator.html(data, type);
|
|
362
|
-
contentType = 'text/html';
|
|
363
|
-
break;
|
|
364
|
-
default:
|
|
365
|
-
return res.status(400).json({ error: 'Invalid format' });
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
res.set('Content-Type', contentType);
|
|
290
|
+
const result = await BarcodeGenerator.generate(
|
|
291
|
+
req.params.data,
|
|
292
|
+
type,
|
|
293
|
+
format
|
|
294
|
+
);
|
|
295
|
+
res.set(
|
|
296
|
+
'Content-Type',
|
|
297
|
+
BarcodeGenerator.getRenderFormatInfo(format).mimeType
|
|
298
|
+
);
|
|
369
299
|
res.send(result);
|
|
370
300
|
} catch (error) {
|
|
371
301
|
res.status(400).json({ error: error.message });
|
|
372
302
|
}
|
|
373
303
|
});
|
|
374
304
|
|
|
375
|
-
//
|
|
376
|
-
app.get('/
|
|
377
|
-
|
|
378
|
-
const { size = 300, logo, label } = req.query;
|
|
379
|
-
|
|
380
|
-
try {
|
|
381
|
-
const qrCode = BarcodeGenerator.modernQr({
|
|
382
|
-
data: decodeURIComponent(data),
|
|
383
|
-
size: parseInt(size),
|
|
384
|
-
logoPath: logo,
|
|
385
|
-
label: label,
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
const result = await qrCode.generate();
|
|
389
|
-
res.set('Content-Type', 'image/png');
|
|
390
|
-
res.send(result);
|
|
391
|
-
} catch (error) {
|
|
392
|
-
res.status(400).json({ error: error.message });
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
app.listen(3000, () => {
|
|
397
|
-
console.log('๐ Barcode server running on port 3000');
|
|
305
|
+
// Inline SVG needs no await
|
|
306
|
+
app.get('/inline/:data', (req, res) => {
|
|
307
|
+
res.type('svg').send(BarcodeGenerator.svgSync(req.params.data, 'code128'));
|
|
398
308
|
});
|
|
399
309
|
```
|
|
400
310
|
|
|
401
|
-
|
|
311
|
+
A complete server, including QR and batch endpoints, is in
|
|
312
|
+
[examples/express-server.js](examples/express-server.js).
|
|
402
313
|
|
|
403
|
-
|
|
404
|
-
const express = require('express');
|
|
405
|
-
const BarcodeGenerator = require('isahaq-barcode');
|
|
314
|
+
## Browser usage
|
|
406
315
|
|
|
407
|
-
|
|
316
|
+
Bundlers resolve the package to the browser build automatically through the
|
|
317
|
+
`browser` field. It shares the encoder and type registry with the Node build, so
|
|
318
|
+
output is identical; PDF generation and file writing are Node-only.
|
|
408
319
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
req.generateBarcode = (
|
|
412
|
-
data,
|
|
413
|
-
type = 'code128',
|
|
414
|
-
format = 'png',
|
|
415
|
-
options = {}
|
|
416
|
-
) => {
|
|
417
|
-
try {
|
|
418
|
-
switch (format) {
|
|
419
|
-
case 'png':
|
|
420
|
-
return BarcodeGenerator.png(data, type, options);
|
|
421
|
-
case 'svg':
|
|
422
|
-
return BarcodeGenerator.svg(data, type, options);
|
|
423
|
-
case 'html':
|
|
424
|
-
return BarcodeGenerator.html(data, type, options);
|
|
425
|
-
default:
|
|
426
|
-
throw new Error(`Unsupported format: ${format}`);
|
|
427
|
-
}
|
|
428
|
-
} catch (error) {
|
|
429
|
-
throw new Error(`Generation failed: ${error.message}`);
|
|
430
|
-
}
|
|
431
|
-
};
|
|
432
|
-
next();
|
|
433
|
-
});
|
|
320
|
+
```javascript
|
|
321
|
+
import BarcodeGenerator from 'isahaq-barcode';
|
|
434
322
|
|
|
435
|
-
//
|
|
436
|
-
|
|
437
|
-
const { data } = req.params;
|
|
438
|
-
const { type, format = 'png', width, height } = req.query;
|
|
323
|
+
// Synchronous SVG - no DOM required
|
|
324
|
+
element.innerHTML = BarcodeGenerator.svg('1234567890', 'code128');
|
|
439
325
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
326
|
+
// Canvas rendering
|
|
327
|
+
BarcodeGenerator.toCanvas(
|
|
328
|
+
document.querySelector('canvas'),
|
|
329
|
+
'1234567890',
|
|
330
|
+
'code128'
|
|
331
|
+
);
|
|
443
332
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
svg: 'image/svg+xml',
|
|
449
|
-
html: 'text/html',
|
|
450
|
-
};
|
|
451
|
-
|
|
452
|
-
res.set('Content-Type', mimeTypes[format] || 'image/png');
|
|
453
|
-
res.send(result);
|
|
454
|
-
} catch (error) {
|
|
455
|
-
res.status(400).json({ error: error.message });
|
|
456
|
-
}
|
|
333
|
+
const dataUrl = BarcodeGenerator.dataUrl('1234567890', 'code128');
|
|
334
|
+
const blob = await BarcodeGenerator.png('1234567890', 'code128'); // Blob, not Buffer
|
|
335
|
+
const qrDataUrl = await BarcodeGenerator.qrCode('https://example.com', {
|
|
336
|
+
size: 300,
|
|
457
337
|
});
|
|
458
338
|
```
|
|
459
339
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
## ๐ฅ๏ธ CLI Usage
|
|
463
|
-
|
|
464
|
-
### Generate Barcodes
|
|
340
|
+
## CLI
|
|
465
341
|
|
|
466
342
|
```bash
|
|
467
|
-
|
|
468
|
-
barcode-generate barcode -d "1234567890" -t code128 -f png -o barcode.png
|
|
469
|
-
|
|
470
|
-
# SVG with custom dimensions
|
|
471
|
-
barcode-generate barcode -d "1234567890" -t ean13 -f svg -w 3 -h 150 -o barcode.svg
|
|
472
|
-
|
|
473
|
-
# Custom colors
|
|
474
|
-
barcode-generate barcode -d "1234567890" -t code128 \
|
|
475
|
-
--foreground "#FF0000" --background "#FFFFFF" -o red-barcode.png
|
|
343
|
+
npx barcode-generate --help
|
|
476
344
|
```
|
|
477
345
|
|
|
478
|
-
### Generate QR Codes
|
|
479
|
-
|
|
480
346
|
```bash
|
|
481
|
-
#
|
|
482
|
-
barcode-generate
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
barcode-generate
|
|
486
|
-
|
|
347
|
+
# Barcodes
|
|
348
|
+
barcode-generate barcode -d 1234567890 -t code128 -f png -o barcode.png
|
|
349
|
+
barcode-generate barcode -d 5901234123457 -t ean13 -f pdf -o label.pdf
|
|
350
|
+
barcode-generate barcode -d "https://example.com" -t qrcode -s 400 -o qr.png
|
|
351
|
+
barcode-generate barcode -d 1234567890 -f svg # writes SVG to stdout
|
|
352
|
+
barcode-generate barcode -d 1234567890 --no-text --width 3 --height 140 -o bars.png
|
|
487
353
|
|
|
488
|
-
# QR
|
|
489
|
-
barcode-generate qr -d "https://example.com" -s
|
|
490
|
-
--watermark "Company Name" --watermark-position bottom-center -o qr-watermark.png
|
|
491
|
-
```
|
|
354
|
+
# QR codes with extras
|
|
355
|
+
barcode-generate qr -d "https://example.com" -s 400 -e H --label "Scan me" -o qr.png
|
|
492
356
|
|
|
493
|
-
|
|
357
|
+
# Batch generation from a JSON file
|
|
358
|
+
barcode-generate batch -i examples/batch-example.json -o ./output
|
|
494
359
|
|
|
495
|
-
|
|
496
|
-
# Create batch configuration file
|
|
497
|
-
cat > batch.json << EOF
|
|
498
|
-
[
|
|
499
|
-
{"data": "1234567890", "type": "code128", "format": "png"},
|
|
500
|
-
{"data": "9876543210", "type": "code39", "format": "svg"},
|
|
501
|
-
{"data": "https://example.com", "type": "qrcode", "format": "png"}
|
|
502
|
-
]
|
|
503
|
-
EOF
|
|
504
|
-
|
|
505
|
-
# Generate batch
|
|
506
|
-
barcode-generate batch -i batch.json -o ./output
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
### Utility Commands
|
|
510
|
-
|
|
511
|
-
```bash
|
|
512
|
-
# List supported barcode types
|
|
360
|
+
# Discovery and validation
|
|
513
361
|
barcode-generate types
|
|
514
|
-
|
|
515
|
-
# List output formats
|
|
362
|
+
barcode-generate types -c matrix_2d
|
|
516
363
|
barcode-generate formats
|
|
517
|
-
|
|
518
|
-
# Validate data for specific type
|
|
519
|
-
barcode-generate validate -d "1234567890" -t code128
|
|
364
|
+
barcode-generate validate -d 5901234123457 -t ean13
|
|
520
365
|
```
|
|
521
366
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
## ๐ API Reference
|
|
367
|
+
Data goes to stdout and diagnostics to stderr, so the CLI pipes cleanly. Without
|
|
368
|
+
`-o`, binary formats are printed as base64. Colour output honours `NO_COLOR`.
|
|
525
369
|
|
|
526
|
-
|
|
370
|
+
Sizing flags mirror the render options: `-w/--width` (module width in px),
|
|
371
|
+
`-h/--height` (bar height in px), `-s/--size` (2D target size in px),
|
|
372
|
+
`-q/--quiet-zone` (quiet zone in modules, default 10) and `-m/--margin` (quiet
|
|
373
|
+
zone in px, overrides `--quiet-zone`).
|
|
527
374
|
|
|
528
|
-
|
|
375
|
+
Install globally with `npm install -g isahaq-barcode` to drop the `npx` prefix.
|
|
529
376
|
|
|
530
|
-
|
|
531
|
-
BarcodeGenerator.png(data, type, options?)
|
|
532
|
-
// Returns: Buffer
|
|
377
|
+
## TypeScript
|
|
533
378
|
|
|
534
|
-
|
|
535
|
-
// Returns: String
|
|
379
|
+
Type declarations ship with the package - no `@types` install needed.
|
|
536
380
|
|
|
537
|
-
|
|
538
|
-
|
|
381
|
+
```typescript
|
|
382
|
+
import BarcodeGenerator = require('isahaq-barcode');
|
|
383
|
+
// or, with esModuleInterop: import BarcodeGenerator from 'isahaq-barcode';
|
|
539
384
|
|
|
540
|
-
BarcodeGenerator.
|
|
541
|
-
|
|
385
|
+
const options: BarcodeGenerator.RenderOptions = { width: 3, height: 140 };
|
|
386
|
+
const png: Buffer = await BarcodeGenerator.png(
|
|
387
|
+
'1234567890',
|
|
388
|
+
'code128',
|
|
389
|
+
options
|
|
390
|
+
);
|
|
542
391
|
|
|
543
|
-
BarcodeGenerator.
|
|
544
|
-
|
|
392
|
+
const result = BarcodeGenerator.validate('5901234123457', 'ean13');
|
|
393
|
+
if (result.valid) {
|
|
394
|
+
console.log(result.charset); // narrowed to the success shape
|
|
395
|
+
}
|
|
545
396
|
```
|
|
546
397
|
|
|
547
|
-
|
|
398
|
+
## API reference
|
|
548
399
|
|
|
549
|
-
|
|
550
|
-
BarcodeGenerator.validate(data, type);
|
|
551
|
-
// Returns: { valid: boolean, error?: string, length?: number, charset?: string }
|
|
552
|
-
|
|
553
|
-
BarcodeGenerator.batch(items);
|
|
554
|
-
// Returns: Array<{ success: boolean, data?: Buffer|String, error?: string }>
|
|
400
|
+
### Generation
|
|
555
401
|
|
|
556
|
-
|
|
557
|
-
|
|
402
|
+
| Method | Returns |
|
|
403
|
+
| --------------------------------------- | --------------------------- |
|
|
404
|
+
| `generate(data, type?, format?, opts?)` | `Promise<Buffer \| string>` |
|
|
405
|
+
| `png(data, type?, opts?)` | `Promise<Buffer>` |
|
|
406
|
+
| `svg(data, type?, opts?)` | `Promise<string>` |
|
|
407
|
+
| `svgSync(data, type?, opts?)` | `string` |
|
|
408
|
+
| `html(data, type?, opts?)` | `Promise<string>` |
|
|
409
|
+
| `htmlSync(data, type?, opts?)` | `string` |
|
|
410
|
+
| `pdf(data, type?, opts?)` | `Promise<Buffer>` |
|
|
411
|
+
| `batch(items)` | `Promise<BatchResult[]>` |
|
|
412
|
+
| `qrCode(data, opts?)` | `QrCodeBuilder` |
|
|
413
|
+
| `modernQr(opts?)` | `QrCodeBuilder` |
|
|
558
414
|
|
|
559
|
-
|
|
560
|
-
// Returns: Array<string>
|
|
415
|
+
`type` defaults to `code128`, `format` to `png`.
|
|
561
416
|
|
|
562
|
-
|
|
563
|
-
// Returns: Array<string>
|
|
564
|
-
```
|
|
417
|
+
### Metadata
|
|
565
418
|
|
|
566
|
-
|
|
419
|
+
| Method | Returns |
|
|
420
|
+
| -------------------------------- | -------------------------- |
|
|
421
|
+
| `validate(data, type)` | `ValidationResult` |
|
|
422
|
+
| `getBarcodeTypes()` | `string[]` |
|
|
423
|
+
| `getBarcodeCategories()` | `string[]` |
|
|
424
|
+
| `getBarcodeTypesByCategory(cat)` | `string[]` |
|
|
425
|
+
| `getBarcodeTypeInfo(type)` | `BarcodeTypeInfo \| null` |
|
|
426
|
+
| `getRenderFormats()` | `string[]` |
|
|
427
|
+
| `getRenderFormatInfo(format)` | `RenderFormatInfo \| null` |
|
|
428
|
+
| `getWatermarkPositions()` | `string[]` |
|
|
429
|
+
| `getDefaultOptions()` | `RenderOptions` |
|
|
567
430
|
|
|
568
|
-
|
|
569
|
-
{
|
|
570
|
-
// Dimensions
|
|
571
|
-
width: 3, // Bar width
|
|
572
|
-
height: 150, // Bar height
|
|
573
|
-
|
|
574
|
-
// Display
|
|
575
|
-
displayValue: true, // Show text below barcode
|
|
576
|
-
fontSize: 20, // Text font size
|
|
577
|
-
textAlign: 'center', // 'left' | 'center' | 'right'
|
|
578
|
-
textPosition: 'bottom', // 'top' | 'bottom'
|
|
579
|
-
textMargin: 2, // Space between bars and text
|
|
580
|
-
|
|
581
|
-
// Colors
|
|
582
|
-
background: '#ffffff', // Background color
|
|
583
|
-
lineColor: '#000000', // Bar color (alias: foregroundColor)
|
|
584
|
-
|
|
585
|
-
// Margins
|
|
586
|
-
margin: 10, // All sides
|
|
587
|
-
marginTop: 10, // Individual sides
|
|
588
|
-
marginBottom: 10,
|
|
589
|
-
marginLeft: 10,
|
|
590
|
-
marginRight: 10
|
|
591
|
-
}
|
|
592
|
-
```
|
|
431
|
+
### Building blocks
|
|
593
432
|
|
|
594
|
-
|
|
433
|
+
Attached to the default export for advanced use: `QrCodeBuilder`,
|
|
434
|
+
`BarcodeService`, `BarcodeEncoder`, `BarcodeTypes`, `RenderFormats`, `Validator`.
|
|
595
435
|
|
|
596
436
|
```javascript
|
|
597
|
-
|
|
598
|
-
.data(string) // Set data to encode
|
|
599
|
-
.size(number) // QR code size in pixels
|
|
600
|
-
.margin(number) // Margin size
|
|
601
|
-
.errorCorrectionLevel(level) // 'L' | 'M' | 'Q' | 'H'
|
|
602
|
-
.foregroundColor(rgb) // [R, G, B]
|
|
603
|
-
.backgroundColor(rgb) // [R, G, B]
|
|
604
|
-
.logoPath(string) // Path to logo image
|
|
605
|
-
.logoSize(number) // Logo size percentage
|
|
606
|
-
.label(string) // Label text
|
|
607
|
-
.watermark(text, position) // Watermark text and position
|
|
608
|
-
.format(format) // 'png' | 'svg'
|
|
609
|
-
.build() // Build QR code instance
|
|
610
|
-
|
|
611
|
-
// QR Code Instance Methods
|
|
612
|
-
qrCode.generate() // Returns: Promise<Buffer>
|
|
613
|
-
qrCode.saveToFile(path) // Returns: Promise<void>
|
|
614
|
-
qrCode.getDataUri() // Returns: Promise<string>
|
|
615
|
-
qrCode.getString() // Returns: Promise<string>
|
|
616
|
-
```
|
|
437
|
+
const { BarcodeEncoder, BarcodeTypes } = require('isahaq-barcode');
|
|
617
438
|
|
|
618
|
-
|
|
439
|
+
BarcodeEncoder.getDimensions('1234567890', 'code128', {
|
|
440
|
+
width: 2,
|
|
441
|
+
height: 100,
|
|
442
|
+
});
|
|
443
|
+
// { width: 220, height: 153 } bars + human readable text + quiet zone
|
|
619
444
|
|
|
620
|
-
|
|
621
|
-
('top-left',
|
|
622
|
-
'top-center',
|
|
623
|
-
'top-right',
|
|
624
|
-
'left-center',
|
|
625
|
-
'center',
|
|
626
|
-
'right-center',
|
|
627
|
-
'bottom-left',
|
|
628
|
-
'bottom-center',
|
|
629
|
-
'bottom-right');
|
|
445
|
+
BarcodeTypes.getSymbology('aztec'); // 'azteccode'
|
|
630
446
|
```
|
|
631
447
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
## ๐งช Testing
|
|
448
|
+
## Development
|
|
635
449
|
|
|
636
450
|
```bash
|
|
637
|
-
|
|
638
|
-
npm test
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
npm run
|
|
642
|
-
|
|
643
|
-
#
|
|
644
|
-
|
|
451
|
+
npm install
|
|
452
|
+
npm test # jest
|
|
453
|
+
npm run lint # eslint
|
|
454
|
+
npm run format # prettier --write
|
|
455
|
+
npm run typecheck # tsc against index.d.ts
|
|
456
|
+
npm run verify:scan # generate barcodes and decode them with ZXing
|
|
457
|
+
npm run build # lint + format:check + typecheck + test
|
|
458
|
+
node examples/basic-usage.js
|
|
459
|
+
npm run dev # express example on :3000
|
|
645
460
|
```
|
|
646
461
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
## ๐ค Contributing
|
|
650
|
-
|
|
651
|
-
We welcome contributions! Please follow these steps:
|
|
652
|
-
|
|
653
|
-
1. **Fork** the repository
|
|
654
|
-
2. **Create** a feature branch: `git checkout -b feature/amazing-feature`
|
|
655
|
-
3. **Commit** your changes: `git commit -m 'Add amazing feature'`
|
|
656
|
-
4. **Push** to the branch: `git push origin feature/amazing-feature`
|
|
657
|
-
5. **Open** a Pull Request
|
|
658
|
-
|
|
659
|
-
Please ensure your code:
|
|
660
|
-
|
|
661
|
-
- Follows the existing code style
|
|
662
|
-
- Includes tests for new features
|
|
663
|
-
- Updates documentation as needed
|
|
664
|
-
|
|
665
|
-
---
|
|
666
|
-
|
|
667
|
-
## ๐ License
|
|
668
|
-
|
|
669
|
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
670
|
-
|
|
671
|
-
---
|
|
672
|
-
|
|
673
|
-
## ๐ Acknowledgments
|
|
674
|
-
|
|
675
|
-
Built with these excellent libraries:
|
|
676
|
-
|
|
677
|
-
- [JsBarcode](https://github.com/lindell/JsBarcode) - Barcode generation
|
|
678
|
-
- [node-qrcode](https://github.com/soldair/node-qrcode) - QR code generation
|
|
679
|
-
- [node-canvas](https://github.com/Automattic/node-canvas) - Canvas implementation
|
|
680
|
-
- [PDFKit](https://github.com/foliojs/pdfkit) - PDF generation
|
|
681
|
-
|
|
682
|
-
---
|
|
683
|
-
|
|
684
|
-
## ๐ Support
|
|
685
|
-
|
|
686
|
-
Need help? Here's how to get support:
|
|
687
|
-
|
|
688
|
-
1. ๐ Check the [documentation](README.md)
|
|
689
|
-
2. ๐ Search [existing issues](https://github.com/isahaq1//npm-barcodegeneratop/issues)
|
|
690
|
-
3. ๐ฌ Create a [new issue](https://github.com/isahaq1//npm-barcodegeneratop/issues/new)
|
|
691
|
-
|
|
692
|
-
---
|
|
693
|
-
|
|
694
|
-
<div align="center">
|
|
695
|
-
|
|
696
|
-
**Made with โค๏ธ by [Isahaq](https://github.com/isahaq1)**
|
|
697
|
-
|
|
698
|
-
[โญ Star this repo](https://github.com/isahaq1//npm-barcodegeneratop) โข [๐ Report Bug](https://github.com/isahaq1//npm-barcodegeneratop/issues) โข [โจ Request Feature](https://github.com/isahaq1//npm-barcodegeneratop/issues)
|
|
462
|
+
## License
|
|
699
463
|
|
|
700
|
-
|
|
464
|
+
MIT - see [LICENSE](LICENSE).
|