isahaq-barcode 1.8.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 +319 -519
- package/bin/generate.js +171 -134
- package/browser.js +163 -170
- package/index.d.ts +497 -0
- package/index.js +118 -38
- package/package.json +68 -34
- 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/README.md
CHANGED
|
@@ -1,302 +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
|
-
|
|
41
|
+
Requires Node.js 18 or newer.
|
|
46
42
|
|
|
47
|
-
|
|
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.
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
```bash
|
|
49
|
+
npm install canvas # only if you need QR logos/labels/watermarks
|
|
50
|
+
```
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
## Quick start
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
- **CLI Tools**: Command-line interface available
|
|
54
|
+
```javascript
|
|
55
|
+
const fs = require('fs/promises');
|
|
56
|
+
const BarcodeGenerator = require('isahaq-barcode');
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
// PNG (returns a Promise<Buffer>)
|
|
59
|
+
await fs.writeFile(
|
|
60
|
+
'code128.png',
|
|
61
|
+
await BarcodeGenerator.png('1234567890', 'code128')
|
|
62
|
+
);
|
|
59
63
|
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- **No Dependencies**: Works with just jsbarcode and qrcode
|
|
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');
|
|
64
67
|
|
|
65
|
-
|
|
68
|
+
// HTML fragment with an inline SVG
|
|
69
|
+
const html = BarcodeGenerator.htmlSync('1234567890', 'code128');
|
|
66
70
|
|
|
67
|
-
|
|
71
|
+
// PDF
|
|
72
|
+
await fs.writeFile(
|
|
73
|
+
'label.pdf',
|
|
74
|
+
await BarcodeGenerator.pdf('1234567890', 'code128', { fitToBarcode: true })
|
|
75
|
+
);
|
|
68
76
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const barcode = BarcodeGenerator.png(req.params.data, 'code128');
|
|
76
|
-
res.set('Content-Type', 'image/png');
|
|
77
|
-
res.send(barcode);
|
|
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
|
-
|
|
86
|
+
## Upgrading from 1.x
|
|
82
87
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
```
|
|
93
|
-
|
|
94
|
-
**โ
Client-Side (Browser/React/Vue):**
|
|
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
|
-
- **Server-side API** - Use this package on your backend
|
|
110
|
+
45 types across six categories. `BarcodeGenerator.getBarcodeTypeInfo(type)`
|
|
111
|
+
returns the metadata for any of them.
|
|
114
112
|
|
|
115
|
-
|
|
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` |
|
|
116
121
|
|
|
117
|
-
```
|
|
118
|
-
|
|
122
|
+
```javascript
|
|
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
|
+
// }
|
|
119
133
|
```
|
|
120
134
|
|
|
121
|
-
|
|
135
|
+
## Output formats
|
|
122
136
|
|
|
123
|
-
|
|
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>` |
|
|
124
143
|
|
|
125
|
-
|
|
126
|
-
const BarcodeGenerator = require('isahaq-barcode');
|
|
127
|
-
|
|
128
|
-
// Generate PNG barcode
|
|
129
|
-
const pngBuffer = BarcodeGenerator.png('1234567890', 'code128');
|
|
144
|
+
`generate()` takes the format as an argument:
|
|
130
145
|
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
// Generate QR code with logo
|
|
135
|
-
const qrCode = BarcodeGenerator.modernQr({
|
|
136
|
-
data: 'https://example.com',
|
|
137
|
-
size: 300,
|
|
138
|
-
logoPath: 'path/to/logo.png',
|
|
139
|
-
label: 'Scan me!',
|
|
146
|
+
```javascript
|
|
147
|
+
const output = await BarcodeGenerator.generate('1234567890', 'code128', 'pdf', {
|
|
148
|
+
pageSize: 'A4',
|
|
140
149
|
});
|
|
141
|
-
|
|
142
|
-
await qrCode.saveToFile('qr-code.png');
|
|
143
150
|
```
|
|
144
151
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
## ๐ Supported Barcode Types
|
|
148
|
-
|
|
149
|
-
### Linear Barcodes (1D)
|
|
150
|
-
|
|
151
|
-
| Type | Variants | Use Case |
|
|
152
|
-
| -------------- | ---------------------------------- | ----------------------------- |
|
|
153
|
-
| **Code 128** | A, B, C, Auto | General purpose, high density |
|
|
154
|
-
| **Code 39** | Standard, Extended, Checksum, Auto | Alphanumeric, automotive |
|
|
155
|
-
| **Code 93** | - | Compact alphanumeric |
|
|
156
|
-
| **EAN Family** | EAN-13, EAN-8, EAN-2, EAN-5 | Retail products (Europe) |
|
|
157
|
-
| **UPC Family** | UPC-A, UPC-E | Retail products (USA) |
|
|
158
|
-
| **Code 25** | Standard, Interleaved, Auto | Industrial, logistics |
|
|
159
|
-
| **ITF-14** | - | Shipping containers |
|
|
160
|
-
| **MSI** | Standard, Checksum, Auto | Inventory management |
|
|
161
|
-
| **Codabar** | - | Libraries, blood banks |
|
|
162
|
-
| **Code 11** | - | Telecommunications |
|
|
163
|
-
|
|
164
|
-
### 2D Barcodes
|
|
165
|
-
|
|
166
|
-
| Type | Data Capacity | Use Case |
|
|
167
|
-
| --------------- | ----------------- | ----------------------- |
|
|
168
|
-
| **QR Code** | Up to 4,296 chars | URLs, payments, general |
|
|
169
|
-
| **Data Matrix** | Up to 2,335 chars | Small item marking |
|
|
170
|
-
| **Aztec** | Up to 3,832 chars | Transport tickets |
|
|
171
|
-
| **PDF417** | Up to 1,850 chars | IDs, boarding passes |
|
|
172
|
-
| **Micro QR** | Up to 35 chars | Compact applications |
|
|
173
|
-
| **MaxiCode** | Up to 93 chars | Package tracking |
|
|
174
|
-
|
|
175
|
-
### Postal Barcodes
|
|
152
|
+
## Render options
|
|
176
153
|
|
|
177
|
-
|
|
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
|
+
```
|
|
178
172
|
|
|
179
|
-
|
|
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.
|
|
180
177
|
|
|
181
|
-
**
|
|
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.
|
|
182
181
|
|
|
183
|
-
|
|
182
|
+
PDF-only options: `pageWidth`, `pageHeight`, `pageSize` (for example `'A4'`),
|
|
183
|
+
`fitToBarcode` (size the page to the barcode plus its margins) and `title`.
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
HTML-only options: `id`, `className`, `includeStyles`.
|
|
186
186
|
|
|
187
|
-
|
|
187
|
+
Anything the encoder itself understands can be passed straight through:
|
|
188
188
|
|
|
189
189
|
```javascript
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// PNG with custom options
|
|
193
|
-
const barcode = BarcodeGenerator.png('1234567890', 'code128', {
|
|
194
|
-
width: 3,
|
|
195
|
-
height: 150,
|
|
196
|
-
displayValue: true,
|
|
197
|
-
foregroundColor: '#000000',
|
|
198
|
-
backgroundColor: '#FFFFFF',
|
|
199
|
-
margin: 10,
|
|
190
|
+
await BarcodeGenerator.png('1234567890', 'code128', {
|
|
191
|
+
bwipOptions: { alttext: 'custom caption' },
|
|
200
192
|
});
|
|
201
|
-
|
|
202
|
-
// Convert to Base64 for web display
|
|
203
|
-
const base64Image = barcode.toString('base64');
|
|
204
|
-
console.log(`<img src="data:image/png;base64,${base64Image}" alt="Barcode" />`);
|
|
205
193
|
```
|
|
206
194
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
```javascript
|
|
210
|
-
const qrCode = BarcodeGenerator.modernQr({
|
|
211
|
-
data: 'https://example.com',
|
|
212
|
-
size: 300,
|
|
213
|
-
margin: 10,
|
|
195
|
+
## QR codes with logos, labels and watermarks
|
|
214
196
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
logoSize: 60, // Percentage
|
|
197
|
+
`qrCode()` / `modernQr()` return a chainable builder. Plain codes need no extra
|
|
198
|
+
dependencies; a logo, label or watermark requires the optional `canvas` package.
|
|
218
199
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
watermarkPosition: 'bottom-center',
|
|
223
|
-
|
|
224
|
-
// Colors
|
|
225
|
-
foregroundColor: [0, 0, 0],
|
|
226
|
-
backgroundColor: [255, 255, 255],
|
|
227
|
-
|
|
228
|
-
// Error correction (H recommended for logos)
|
|
200
|
+
```javascript
|
|
201
|
+
const buffer = await BarcodeGenerator.qrCode('https://example.com', {
|
|
202
|
+
size: 400,
|
|
229
203
|
errorCorrectionLevel: 'H',
|
|
230
|
-
});
|
|
204
|
+
}).generate();
|
|
231
205
|
|
|
232
|
-
//
|
|
233
|
-
|
|
206
|
+
// Or with the builder API
|
|
207
|
+
const QrCodeBuilder = BarcodeGenerator.QrCodeBuilder;
|
|
234
208
|
|
|
235
|
-
|
|
236
|
-
|
|
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();
|
|
237
228
|
```
|
|
238
229
|
|
|
239
|
-
|
|
230
|
+
Watermark positions: `top-left`, `top-center`, `top-right`, `left-center`,
|
|
231
|
+
`center`, `right-center`, `bottom-left`, `bottom-center`, `bottom-right`
|
|
232
|
+
(`getWatermarkPositions()`).
|
|
240
233
|
|
|
241
|
-
|
|
242
|
-
|
|
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.
|
|
243
236
|
|
|
244
|
-
|
|
245
|
-
.data('https://example.com')
|
|
246
|
-
.size(300)
|
|
247
|
-
.margin(10)
|
|
248
|
-
.foregroundColor([0, 0, 0])
|
|
249
|
-
.backgroundColor([255, 255, 255])
|
|
250
|
-
.logoPath('path/to/logo.png')
|
|
251
|
-
.logoSize(60)
|
|
252
|
-
.label('Scan me!')
|
|
253
|
-
.watermark('Watermark Text', 'center')
|
|
254
|
-
.format('png')
|
|
255
|
-
.build();
|
|
237
|
+
## Validation
|
|
256
238
|
|
|
257
|
-
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
### Batch Generation
|
|
239
|
+
Validation runs automatically before generation, and is also available directly:
|
|
261
240
|
|
|
262
241
|
```javascript
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
{ data: '9876543210', type: 'code39', format: 'svg' },
|
|
266
|
-
{ data: 'https://example.com', type: 'qrcode', format: 'png' },
|
|
267
|
-
];
|
|
242
|
+
BarcodeGenerator.validate('5901234123457', 'ean13');
|
|
243
|
+
// { valid: true, data: '5901234123457', type: 'ean13', length: 13, charset: 'Numeric' }
|
|
268
244
|
|
|
269
|
-
|
|
245
|
+
BarcodeGenerator.validate('1234567890123', 'ean13');
|
|
246
|
+
// { valid: false, error: 'Invalid EAN-13 check digit (expected 8)' }
|
|
270
247
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
console.log(`โ Barcode ${index} generated`);
|
|
274
|
-
// result.data contains the generated barcode
|
|
275
|
-
} else {
|
|
276
|
-
console.error(`โ Barcode ${index} failed: ${result.error}`);
|
|
277
|
-
}
|
|
278
|
-
});
|
|
248
|
+
BarcodeGenerator.validate('123', 'ean13');
|
|
249
|
+
// { valid: false, error: 'Data too short. Minimum length: 12' }
|
|
279
250
|
```
|
|
280
251
|
|
|
281
|
-
|
|
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.
|
|
282
254
|
|
|
283
|
-
|
|
284
|
-
const validation = BarcodeGenerator.validate('1234567890', 'code128');
|
|
285
|
-
|
|
286
|
-
if (validation.valid) {
|
|
287
|
-
console.log('โ Valid data');
|
|
288
|
-
console.log(` Length: ${validation.length}`);
|
|
289
|
-
console.log(` Charset: ${validation.charset}`);
|
|
290
|
-
} else {
|
|
291
|
-
console.error(`โ Invalid: ${validation.error}`);
|
|
292
|
-
}
|
|
293
|
-
```
|
|
255
|
+
## Batch generation
|
|
294
256
|
|
|
295
|
-
|
|
257
|
+
Per-item failures are reported in the result rather than rejecting the batch:
|
|
296
258
|
|
|
297
|
-
|
|
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
|
+
```
|
|
298
277
|
|
|
299
|
-
|
|
278
|
+
## Express.js integration
|
|
300
279
|
|
|
301
280
|
```javascript
|
|
302
281
|
const express = require('express');
|
|
@@ -304,361 +283,182 @@ const BarcodeGenerator = require('isahaq-barcode');
|
|
|
304
283
|
|
|
305
284
|
const app = express();
|
|
306
285
|
|
|
307
|
-
|
|
308
|
-
app.get('/barcode/:data', (req, res) => {
|
|
309
|
-
const { data } = req.params;
|
|
286
|
+
app.get('/barcode/:data', async (req, res) => {
|
|
310
287
|
const { type = 'code128', format = 'png' } = req.query;
|
|
311
288
|
|
|
312
289
|
try {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
contentType = 'image/svg+xml';
|
|
323
|
-
break;
|
|
324
|
-
case 'html':
|
|
325
|
-
result = BarcodeGenerator.html(data, type);
|
|
326
|
-
contentType = 'text/html';
|
|
327
|
-
break;
|
|
328
|
-
default:
|
|
329
|
-
return res.status(400).json({ error: 'Invalid format' });
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
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
|
+
);
|
|
333
299
|
res.send(result);
|
|
334
300
|
} catch (error) {
|
|
335
301
|
res.status(400).json({ error: error.message });
|
|
336
302
|
}
|
|
337
303
|
});
|
|
338
304
|
|
|
339
|
-
//
|
|
340
|
-
app.get('/
|
|
341
|
-
|
|
342
|
-
const { size = 300, logo, label } = req.query;
|
|
343
|
-
|
|
344
|
-
try {
|
|
345
|
-
const qrCode = BarcodeGenerator.modernQr({
|
|
346
|
-
data: decodeURIComponent(data),
|
|
347
|
-
size: parseInt(size),
|
|
348
|
-
logoPath: logo,
|
|
349
|
-
label: label,
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
const result = await qrCode.generate();
|
|
353
|
-
res.set('Content-Type', 'image/png');
|
|
354
|
-
res.send(result);
|
|
355
|
-
} catch (error) {
|
|
356
|
-
res.status(400).json({ error: error.message });
|
|
357
|
-
}
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
app.listen(3000, () => {
|
|
361
|
-
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'));
|
|
362
308
|
});
|
|
363
309
|
```
|
|
364
310
|
|
|
365
|
-
|
|
311
|
+
A complete server, including QR and batch endpoints, is in
|
|
312
|
+
[examples/express-server.js](examples/express-server.js).
|
|
366
313
|
|
|
367
|
-
|
|
368
|
-
const express = require('express');
|
|
369
|
-
const BarcodeGenerator = require('isahaq-barcode');
|
|
314
|
+
## Browser usage
|
|
370
315
|
|
|
371
|
-
|
|
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.
|
|
372
319
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
req.generateBarcode = (
|
|
376
|
-
data,
|
|
377
|
-
type = 'code128',
|
|
378
|
-
format = 'png',
|
|
379
|
-
options = {}
|
|
380
|
-
) => {
|
|
381
|
-
try {
|
|
382
|
-
switch (format) {
|
|
383
|
-
case 'png':
|
|
384
|
-
return BarcodeGenerator.png(data, type, options);
|
|
385
|
-
case 'svg':
|
|
386
|
-
return BarcodeGenerator.svg(data, type, options);
|
|
387
|
-
case 'html':
|
|
388
|
-
return BarcodeGenerator.html(data, type, options);
|
|
389
|
-
default:
|
|
390
|
-
throw new Error(`Unsupported format: ${format}`);
|
|
391
|
-
}
|
|
392
|
-
} catch (error) {
|
|
393
|
-
throw new Error(`Generation failed: ${error.message}`);
|
|
394
|
-
}
|
|
395
|
-
};
|
|
396
|
-
next();
|
|
397
|
-
});
|
|
320
|
+
```javascript
|
|
321
|
+
import BarcodeGenerator from 'isahaq-barcode';
|
|
398
322
|
|
|
399
|
-
//
|
|
400
|
-
|
|
401
|
-
const { data } = req.params;
|
|
402
|
-
const { type, format = 'png', width, height } = req.query;
|
|
323
|
+
// Synchronous SVG - no DOM required
|
|
324
|
+
element.innerHTML = BarcodeGenerator.svg('1234567890', 'code128');
|
|
403
325
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
326
|
+
// Canvas rendering
|
|
327
|
+
BarcodeGenerator.toCanvas(
|
|
328
|
+
document.querySelector('canvas'),
|
|
329
|
+
'1234567890',
|
|
330
|
+
'code128'
|
|
331
|
+
);
|
|
407
332
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
svg: 'image/svg+xml',
|
|
413
|
-
html: 'text/html',
|
|
414
|
-
};
|
|
415
|
-
|
|
416
|
-
res.set('Content-Type', mimeTypes[format] || 'image/png');
|
|
417
|
-
res.send(result);
|
|
418
|
-
} catch (error) {
|
|
419
|
-
res.status(400).json({ error: error.message });
|
|
420
|
-
}
|
|
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,
|
|
421
337
|
});
|
|
422
338
|
```
|
|
423
339
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
## ๐ฅ๏ธ CLI Usage
|
|
427
|
-
|
|
428
|
-
### Generate Barcodes
|
|
340
|
+
## CLI
|
|
429
341
|
|
|
430
342
|
```bash
|
|
431
|
-
|
|
432
|
-
barcode-generate barcode -d "1234567890" -t code128 -f png -o barcode.png
|
|
433
|
-
|
|
434
|
-
# SVG with custom dimensions
|
|
435
|
-
barcode-generate barcode -d "1234567890" -t ean13 -f svg -w 3 -h 150 -o barcode.svg
|
|
436
|
-
|
|
437
|
-
# Custom colors
|
|
438
|
-
barcode-generate barcode -d "1234567890" -t code128 \
|
|
439
|
-
--foreground "#FF0000" --background "#FFFFFF" -o red-barcode.png
|
|
343
|
+
npx barcode-generate --help
|
|
440
344
|
```
|
|
441
345
|
|
|
442
|
-
### Generate QR Codes
|
|
443
|
-
|
|
444
346
|
```bash
|
|
445
|
-
#
|
|
446
|
-
barcode-generate
|
|
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
|
|
447
353
|
|
|
448
|
-
# QR
|
|
449
|
-
barcode-generate qr -d "https://example.com" -s
|
|
450
|
-
--logo "path/to/logo.png" --logo-size 60 -o qr-logo.png
|
|
451
|
-
|
|
452
|
-
# QR code with watermark
|
|
453
|
-
barcode-generate qr -d "https://example.com" -s 300 \
|
|
454
|
-
--watermark "Company Name" --watermark-position bottom-center -o qr-watermark.png
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
### Batch Operations
|
|
458
|
-
|
|
459
|
-
```bash
|
|
460
|
-
# Create batch configuration file
|
|
461
|
-
cat > batch.json << EOF
|
|
462
|
-
[
|
|
463
|
-
{"data": "1234567890", "type": "code128", "format": "png"},
|
|
464
|
-
{"data": "9876543210", "type": "code39", "format": "svg"},
|
|
465
|
-
{"data": "https://example.com", "type": "qrcode", "format": "png"}
|
|
466
|
-
]
|
|
467
|
-
EOF
|
|
468
|
-
|
|
469
|
-
# Generate batch
|
|
470
|
-
barcode-generate batch -i batch.json -o ./output
|
|
471
|
-
```
|
|
354
|
+
# QR codes with extras
|
|
355
|
+
barcode-generate qr -d "https://example.com" -s 400 -e H --label "Scan me" -o qr.png
|
|
472
356
|
|
|
473
|
-
|
|
357
|
+
# Batch generation from a JSON file
|
|
358
|
+
barcode-generate batch -i examples/batch-example.json -o ./output
|
|
474
359
|
|
|
475
|
-
|
|
476
|
-
# List supported barcode types
|
|
360
|
+
# Discovery and validation
|
|
477
361
|
barcode-generate types
|
|
478
|
-
|
|
479
|
-
# List output formats
|
|
362
|
+
barcode-generate types -c matrix_2d
|
|
480
363
|
barcode-generate formats
|
|
481
|
-
|
|
482
|
-
# Validate data for specific type
|
|
483
|
-
barcode-generate validate -d "1234567890" -t code128
|
|
364
|
+
barcode-generate validate -d 5901234123457 -t ean13
|
|
484
365
|
```
|
|
485
366
|
|
|
486
|
-
|
|
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`.
|
|
487
369
|
|
|
488
|
-
|
|
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`).
|
|
489
374
|
|
|
490
|
-
|
|
375
|
+
Install globally with `npm install -g isahaq-barcode` to drop the `npx` prefix.
|
|
491
376
|
|
|
492
|
-
|
|
377
|
+
## TypeScript
|
|
493
378
|
|
|
494
|
-
|
|
495
|
-
BarcodeGenerator.png(data, type, options?)
|
|
496
|
-
// Returns: Buffer
|
|
379
|
+
Type declarations ship with the package - no `@types` install needed.
|
|
497
380
|
|
|
498
|
-
|
|
499
|
-
|
|
381
|
+
```typescript
|
|
382
|
+
import BarcodeGenerator = require('isahaq-barcode');
|
|
383
|
+
// or, with esModuleInterop: import BarcodeGenerator from 'isahaq-barcode';
|
|
500
384
|
|
|
501
|
-
BarcodeGenerator.
|
|
502
|
-
|
|
385
|
+
const options: BarcodeGenerator.RenderOptions = { width: 3, height: 140 };
|
|
386
|
+
const png: Buffer = await BarcodeGenerator.png(
|
|
387
|
+
'1234567890',
|
|
388
|
+
'code128',
|
|
389
|
+
options
|
|
390
|
+
);
|
|
503
391
|
|
|
504
|
-
BarcodeGenerator.
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
// Returns: QrCodeInstance
|
|
392
|
+
const result = BarcodeGenerator.validate('5901234123457', 'ean13');
|
|
393
|
+
if (result.valid) {
|
|
394
|
+
console.log(result.charset); // narrowed to the success shape
|
|
395
|
+
}
|
|
509
396
|
```
|
|
510
397
|
|
|
511
|
-
|
|
398
|
+
## API reference
|
|
512
399
|
|
|
513
|
-
|
|
514
|
-
BarcodeGenerator.validate(data, type);
|
|
515
|
-
// Returns: { valid: boolean, error?: string, length?: number, charset?: string }
|
|
400
|
+
### Generation
|
|
516
401
|
|
|
517
|
-
|
|
518
|
-
|
|
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` |
|
|
519
414
|
|
|
520
|
-
|
|
521
|
-
// Returns: Array<string>
|
|
415
|
+
`type` defaults to `code128`, `format` to `png`.
|
|
522
416
|
|
|
523
|
-
|
|
524
|
-
// Returns: Array<string>
|
|
417
|
+
### Metadata
|
|
525
418
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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` |
|
|
529
430
|
|
|
530
|
-
###
|
|
431
|
+
### Building blocks
|
|
531
432
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
// Dimensions
|
|
535
|
-
width: 3, // Bar width
|
|
536
|
-
height: 150, // Bar height
|
|
537
|
-
|
|
538
|
-
// Display
|
|
539
|
-
displayValue: true, // Show text below barcode
|
|
540
|
-
fontSize: 20, // Text font size
|
|
541
|
-
textAlign: 'center', // 'left' | 'center' | 'right'
|
|
542
|
-
textPosition: 'bottom', // 'top' | 'bottom'
|
|
543
|
-
textMargin: 2, // Space between bars and text
|
|
544
|
-
|
|
545
|
-
// Colors
|
|
546
|
-
background: '#ffffff', // Background color
|
|
547
|
-
lineColor: '#000000', // Bar color (alias: foregroundColor)
|
|
548
|
-
|
|
549
|
-
// Margins
|
|
550
|
-
margin: 10, // All sides
|
|
551
|
-
marginTop: 10, // Individual sides
|
|
552
|
-
marginBottom: 10,
|
|
553
|
-
marginLeft: 10,
|
|
554
|
-
marginRight: 10
|
|
555
|
-
}
|
|
556
|
-
```
|
|
557
|
-
|
|
558
|
-
### QrCodeBuilder Methods
|
|
433
|
+
Attached to the default export for advanced use: `QrCodeBuilder`,
|
|
434
|
+
`BarcodeService`, `BarcodeEncoder`, `BarcodeTypes`, `RenderFormats`, `Validator`.
|
|
559
435
|
|
|
560
436
|
```javascript
|
|
561
|
-
|
|
562
|
-
.data(string) // Set data to encode
|
|
563
|
-
.size(number) // QR code size in pixels
|
|
564
|
-
.margin(number) // Margin size
|
|
565
|
-
.errorCorrectionLevel(level) // 'L' | 'M' | 'Q' | 'H'
|
|
566
|
-
.foregroundColor(rgb) // [R, G, B]
|
|
567
|
-
.backgroundColor(rgb) // [R, G, B]
|
|
568
|
-
.logoPath(string) // Path to logo image
|
|
569
|
-
.logoSize(number) // Logo size percentage
|
|
570
|
-
.label(string) // Label text
|
|
571
|
-
.watermark(text, position) // Watermark text and position
|
|
572
|
-
.format(format) // 'png' | 'svg'
|
|
573
|
-
.build() // Build QR code instance
|
|
574
|
-
|
|
575
|
-
// QR Code Instance Methods
|
|
576
|
-
qrCode.generate() // Returns: Promise<Buffer>
|
|
577
|
-
qrCode.saveToFile(path) // Returns: Promise<void>
|
|
578
|
-
qrCode.getDataUri() // Returns: Promise<string>
|
|
579
|
-
qrCode.getString() // Returns: Promise<string>
|
|
580
|
-
```
|
|
437
|
+
const { BarcodeEncoder, BarcodeTypes } = require('isahaq-barcode');
|
|
581
438
|
|
|
582
|
-
|
|
439
|
+
BarcodeEncoder.getDimensions('1234567890', 'code128', {
|
|
440
|
+
width: 2,
|
|
441
|
+
height: 100,
|
|
442
|
+
});
|
|
443
|
+
// { width: 220, height: 153 } bars + human readable text + quiet zone
|
|
583
444
|
|
|
584
|
-
|
|
585
|
-
('top-left',
|
|
586
|
-
'top-center',
|
|
587
|
-
'top-right',
|
|
588
|
-
'left-center',
|
|
589
|
-
'center',
|
|
590
|
-
'right-center',
|
|
591
|
-
'bottom-left',
|
|
592
|
-
'bottom-center',
|
|
593
|
-
'bottom-right');
|
|
445
|
+
BarcodeTypes.getSymbology('aztec'); // 'azteccode'
|
|
594
446
|
```
|
|
595
447
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
## ๐งช Testing
|
|
448
|
+
## Development
|
|
599
449
|
|
|
600
450
|
```bash
|
|
601
|
-
|
|
602
|
-
npm test
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
npm run
|
|
606
|
-
|
|
607
|
-
#
|
|
608
|
-
|
|
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
|
|
609
460
|
```
|
|
610
461
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
## ๐ค Contributing
|
|
614
|
-
|
|
615
|
-
We welcome contributions! Please follow these steps:
|
|
616
|
-
|
|
617
|
-
1. **Fork** the repository
|
|
618
|
-
2. **Create** a feature branch: `git checkout -b feature/amazing-feature`
|
|
619
|
-
3. **Commit** your changes: `git commit -m 'Add amazing feature'`
|
|
620
|
-
4. **Push** to the branch: `git push origin feature/amazing-feature`
|
|
621
|
-
5. **Open** a Pull Request
|
|
622
|
-
|
|
623
|
-
Please ensure your code:
|
|
624
|
-
|
|
625
|
-
- Follows the existing code style
|
|
626
|
-
- Includes tests for new features
|
|
627
|
-
- Updates documentation as needed
|
|
628
|
-
|
|
629
|
-
---
|
|
630
|
-
|
|
631
|
-
## ๐ License
|
|
632
|
-
|
|
633
|
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
634
|
-
|
|
635
|
-
---
|
|
636
|
-
|
|
637
|
-
## ๐ Acknowledgments
|
|
638
|
-
|
|
639
|
-
Built with these excellent libraries:
|
|
640
|
-
|
|
641
|
-
- [JsBarcode](https://github.com/lindell/JsBarcode) - Barcode generation
|
|
642
|
-
- [node-qrcode](https://github.com/soldair/node-qrcode) - QR code generation
|
|
643
|
-
- [node-canvas](https://github.com/Automattic/node-canvas) - Canvas implementation
|
|
644
|
-
- [PDFKit](https://github.com/foliojs/pdfkit) - PDF generation
|
|
645
|
-
|
|
646
|
-
---
|
|
647
|
-
|
|
648
|
-
## ๐ Support
|
|
649
|
-
|
|
650
|
-
Need help? Here's how to get support:
|
|
651
|
-
|
|
652
|
-
1. ๐ Check the [documentation](README.md)
|
|
653
|
-
2. ๐ Search [existing issues](https://github.com/isahaq1//npm-barcodegeneratop/issues)
|
|
654
|
-
3. ๐ฌ Create a [new issue](https://github.com/isahaq1//npm-barcodegeneratop/issues/new)
|
|
655
|
-
|
|
656
|
-
---
|
|
657
|
-
|
|
658
|
-
<div align="center">
|
|
659
|
-
|
|
660
|
-
**Made with โค๏ธ by [Isahaq](https://github.com/isahaq1)**
|
|
661
|
-
|
|
662
|
-
[โญ 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
|
|
663
463
|
|
|
664
|
-
|
|
464
|
+
MIT - see [LICENSE](LICENSE).
|