@sythos/js_barcode_universal 1.2.5 → 1.4.1

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.
Files changed (124) hide show
  1. package/AI_USAGE.md +33 -0
  2. package/LICENSE +11 -2
  3. package/NOTICE.md +10 -4
  4. package/README.md +601 -465
  5. package/bundle/sythos-barcode.esm.js +4669 -74
  6. package/bundle/sythos-barcode.js +4575 -72
  7. package/examples/create.html +1010 -730
  8. package/examples/read.html +1 -0
  9. package/licenses/README.md +40 -58
  10. package/licenses/aztec-code.license +15 -13
  11. package/licenses/aztec-rune.license +76 -0
  12. package/licenses/codabar.license +18 -15
  13. package/licenses/code-11.license +11 -9
  14. package/licenses/code-128.license +10 -8
  15. package/licenses/code-39.license +10 -8
  16. package/licenses/code-93.license +16 -14
  17. package/licenses/compact-pdf417.license +76 -0
  18. package/licenses/data-matrix.license +15 -13
  19. package/licenses/ean-13.license +10 -8
  20. package/licenses/ean-2.license +74 -0
  21. package/licenses/ean-5.license +74 -0
  22. package/licenses/ean-8.license +10 -8
  23. package/licenses/frameqr.license +84 -0
  24. package/licenses/gs1-128.license +10 -8
  25. package/licenses/gs1-databar.license +81 -0
  26. package/licenses/isbn.license +10 -8
  27. package/licenses/itf-14.license +10 -8
  28. package/licenses/itf.license +9 -7
  29. package/licenses/micro-qr.license +79 -0
  30. package/licenses/micropdf417.license +52 -67
  31. package/licenses/msi-plessey.license +13 -11
  32. package/licenses/pdf417.license +78 -37
  33. package/licenses/pharmacode.license +14 -12
  34. package/licenses/qr-code.license +9 -7
  35. package/licenses/rmqr.license +79 -0
  36. package/licenses/upc-a.license +12 -10
  37. package/licenses/upc-e.license +10 -8
  38. package/package.json +109 -88
  39. package/src/aztec/decoder.js +1 -0
  40. package/src/aztec/detector.js +1 -0
  41. package/src/aztec/encoder.js +1 -0
  42. package/src/aztec/high-level.js +1 -0
  43. package/src/aztec/index.js +1 -0
  44. package/src/aztec/tables.js +1 -0
  45. package/src/aztecrune/decoder.js +156 -0
  46. package/src/aztecrune/detector.js +167 -0
  47. package/src/aztecrune/encoder.js +122 -0
  48. package/src/aztecrune/index.js +50 -0
  49. package/src/aztecrune/tables.js +138 -0
  50. package/src/compactpdf417/decoder.js +129 -0
  51. package/src/compactpdf417/detector.js +140 -0
  52. package/src/compactpdf417/encoder.js +141 -0
  53. package/src/compactpdf417/index.js +22 -0
  54. package/src/compactpdf417/tables.js +174 -0
  55. package/src/core/bit-buffer.js +1 -0
  56. package/src/core/bit-matrix.js +1 -0
  57. package/src/core/errors.js +1 -0
  58. package/src/core/galois-field.js +1 -0
  59. package/src/core/index.js +1 -0
  60. package/src/core/reed-solomon.js +1 -0
  61. package/src/databar/codec.js +182 -0
  62. package/src/databar/decoder.js +115 -0
  63. package/src/databar/encoder.js +97 -0
  64. package/src/databar/gs1.js +178 -0
  65. package/src/databar/index.js +69 -0
  66. package/src/databar/patterns.js +144 -0
  67. package/src/databar/tables.js +125 -0
  68. package/src/datamatrix/decoder.js +263 -262
  69. package/src/datamatrix/detector.js +226 -225
  70. package/src/datamatrix/encoder.js +192 -191
  71. package/src/datamatrix/index.js +43 -42
  72. package/src/datamatrix/tables.js +124 -123
  73. package/src/frameqr/decoder.js +240 -0
  74. package/src/frameqr/detector.js +193 -0
  75. package/src/frameqr/encoder.js +157 -0
  76. package/src/frameqr/index.js +43 -0
  77. package/src/frameqr/tables.js +271 -0
  78. package/src/image/binarizer.js +1 -0
  79. package/src/image/grid-sampler.js +1 -0
  80. package/src/image/index.js +1 -0
  81. package/src/image/luminance.js +1 -0
  82. package/src/image/perspective.js +1 -0
  83. package/src/index.js +155 -2
  84. package/src/micropdf417/compaction.js +1 -0
  85. package/src/micropdf417/decoder.js +1 -0
  86. package/src/micropdf417/detector.js +1 -0
  87. package/src/micropdf417/encoder.js +1 -0
  88. package/src/micropdf417/error-correction.js +1 -0
  89. package/src/micropdf417/index.js +1 -0
  90. package/src/micropdf417/tables.js +1 -0
  91. package/src/microqr/decoder.js +246 -0
  92. package/src/microqr/detector.js +356 -0
  93. package/src/microqr/encoder.js +270 -0
  94. package/src/microqr/index.js +37 -0
  95. package/src/microqr/tables.js +317 -0
  96. package/src/oned/addons.js +421 -0
  97. package/src/oned/index.js +77 -59
  98. package/src/oned/patterns.js +1 -0
  99. package/src/oned/reader.js +1 -0
  100. package/src/oned/writers.js +1 -0
  101. package/src/pdf417/compaction.js +1 -0
  102. package/src/pdf417/decoder.js +1 -0
  103. package/src/pdf417/detector.js +1 -0
  104. package/src/pdf417/encoder.js +1 -0
  105. package/src/pdf417/error-correction.js +1 -0
  106. package/src/pdf417/index.js +5 -0
  107. package/src/pdf417/tables.js +1 -0
  108. package/src/qr/decoder.js +1 -0
  109. package/src/qr/detector.js +1 -0
  110. package/src/qr/encoder.js +1 -0
  111. package/src/qr/index.js +1 -0
  112. package/src/qr/tables.js +1 -0
  113. package/src/render/image-data.js +1 -0
  114. package/src/render/index.js +1 -0
  115. package/src/render/options.js +1 -0
  116. package/src/render/png.js +1 -0
  117. package/src/render/svg.js +1 -0
  118. package/src/render/webgl.js +1 -0
  119. package/src/render/webgpu.js +1 -0
  120. package/src/rmqr/decoder.js +102 -0
  121. package/src/rmqr/detector.js +91 -0
  122. package/src/rmqr/encoder.js +173 -0
  123. package/src/rmqr/index.js +38 -0
  124. package/src/rmqr/tables.js +155 -0
@@ -0,0 +1,421 @@
1
+ /*!
2
+ * Sythos Barcode Suite
3
+ *
4
+ * MIT License
5
+ *
6
+ * Copyright (c) 2026 Sythos
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in all
16
+ * copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ * SOFTWARE.
25
+ *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
27
+ * SPDX-License-Identifier: MIT
28
+ *
29
+ * Original work. No code from any other barcode implementation.
30
+ */
31
+
32
+ /**
33
+ * UPC/EAN two- and five-digit supplements.
34
+ *
35
+ * Supplements are small symbols printed to the right of an EAN/UPC symbol.
36
+ * They use the ordinary EAN odd/even digit patterns, a 1011 start guard and
37
+ * 01 separators between digits. EAN-2 selects its parity from the numeric
38
+ * value modulo four. EAN-5 derives a checksum from the five digits and uses
39
+ * that value to select one of ten parity rows.
40
+ *
41
+ * This module intentionally keeps supplements separate from the base EAN/UPC
42
+ * writers. `composeEANAddon` and the `*WithAddon` helpers are opt-in; existing
43
+ * EAN/UPC APIs continue to return their original one-row matrices unchanged.
44
+ *
45
+ * @module oned/addons
46
+ */
47
+
48
+ import { BitMatrix } from '../core/bit-matrix.js';
49
+ import { EncodeError, FormatError } from '../core/errors.js';
50
+ import {
51
+ EAN_L,
52
+ EAN_G,
53
+ } from './patterns.js';
54
+ import {
55
+ encodeEAN13,
56
+ encodeEAN8,
57
+ encodeUPCA,
58
+ encodeUPCE,
59
+ } from './writers.js';
60
+
61
+ /** EAN-2 parity rows, indexed by the two-digit value modulo four. */
62
+ export const EAN2_PARITY = Object.freeze([
63
+ 'AA', 'AB', 'BA', 'BB',
64
+ ]);
65
+
66
+ /** EAN-5 parity rows, indexed by the supplemental checksum. */
67
+ export const EAN5_PARITY = Object.freeze([
68
+ 'BBAAA', 'BABAA', 'BAABA', 'BAAAB', 'ABBAA',
69
+ 'AABBA', 'AAABB', 'ABABA', 'ABAAB', 'AABAB',
70
+ ]);
71
+
72
+ /** Start guard used by both UPC/EAN supplemental symbols. */
73
+ export const EAN_ADDON_START = '1011';
74
+
75
+ /** Separator inserted between adjacent supplemental digits. */
76
+ export const EAN_ADDON_SEPARATOR = '01';
77
+
78
+ export const EAN2_WIDTH = EAN_ADDON_START.length + 2 * 7 + EAN_ADDON_SEPARATOR.length;
79
+ export const EAN5_WIDTH = EAN_ADDON_START.length + 5 * 7 + EAN_ADDON_SEPARATOR.length * 4;
80
+
81
+ /**
82
+ * @param {unknown} value
83
+ * @param {number} length
84
+ * @param {string} format
85
+ * @returns {string}
86
+ */
87
+ function normalizeDigits(value, length, format) {
88
+ const digits = String(value);
89
+ if (!new RegExp(`^[0-9]{${length}}$`).test(digits)) {
90
+ throw new EncodeError(`${format}: payload must contain exactly ${length} digits`);
91
+ }
92
+ return digits;
93
+ }
94
+
95
+ /**
96
+ * EAN-5 supplemental checksum.
97
+ *
98
+ * The first, third and fifth digits carry weight three; the second and fourth
99
+ * carry weight nine. The checksum is not printed as a sixth digit: it selects
100
+ * the odd/even parity row for the five encoded digits.
101
+ *
102
+ * @param {string|number} value Five digits.
103
+ * @returns {number} Checksum value, 0-9.
104
+ */
105
+ export function ean5Checksum(value) {
106
+ const digits = normalizeDigits(value, 5, 'EAN-5');
107
+ const weighted =
108
+ 3 * (Number(digits[0]) + Number(digits[2]) + Number(digits[4])) +
109
+ 9 * (Number(digits[1]) + Number(digits[3]));
110
+ return weighted % 10;
111
+ }
112
+
113
+ /** Alias for callers that use the EAN family check-digit terminology. */
114
+ export const ean5CheckDigit = ean5Checksum;
115
+
116
+ /**
117
+ * Resolve the EAN-2 parity row for a payload.
118
+ *
119
+ * @param {string|number} value Two digits.
120
+ * @returns {string} Two-character A/B parity row.
121
+ */
122
+ export function ean2Parity(value) {
123
+ const digits = normalizeDigits(value, 2, 'EAN-2');
124
+ return EAN2_PARITY[Number(digits) % 4];
125
+ }
126
+
127
+ /**
128
+ * Resolve the EAN-5 parity row for a payload.
129
+ *
130
+ * @param {string|number} value Five digits.
131
+ * @returns {string} Five-character A/B parity row.
132
+ */
133
+ export function ean5Parity(value) {
134
+ return EAN5_PARITY[ean5Checksum(value)];
135
+ }
136
+
137
+ /**
138
+ * Expand an A/B parity row into EAN digit patterns.
139
+ *
140
+ * @param {string} digits
141
+ * @param {string} parity
142
+ * @returns {string}
143
+ */
144
+ function encodeDigitPatterns(digits, parity) {
145
+ let modules = EAN_ADDON_START;
146
+ for (let i = 0; i < digits.length; i++) {
147
+ if (i > 0) modules += EAN_ADDON_SEPARATOR;
148
+ const table = parity[i] === 'A' ? EAN_L : EAN_G;
149
+ modules += table[Number(digits[i])];
150
+ }
151
+ return modules;
152
+ }
153
+
154
+ /**
155
+ * Turn a module string into a one-row matrix and attach immutable source
156
+ * metadata for composition/rendering callers.
157
+ *
158
+ * @param {string} modules
159
+ * @param {{format: string, text: string, parity: string, checksum?: number}} metadata
160
+ * @returns {BitMatrix}
161
+ */
162
+ function toAddonMatrix(modules, metadata) {
163
+ const matrix = new BitMatrix(modules.length, 1);
164
+ for (let x = 0; x < modules.length; x++) {
165
+ if (modules[x] === '1') matrix.set(x, 0);
166
+ }
167
+ matrix.eanAddon = Object.freeze({ ...metadata });
168
+ return matrix;
169
+ }
170
+
171
+ /**
172
+ * Encode an EAN-2 supplement.
173
+ *
174
+ * @param {string|number} value Exactly two decimal digits.
175
+ * @returns {BitMatrix} A 20-module, one-row supplement.
176
+ */
177
+ export function encodeEAN2(value) {
178
+ const digits = normalizeDigits(value, 2, 'EAN-2');
179
+ const parity = ean2Parity(digits);
180
+ const matrix = toAddonMatrix(encodeDigitPatterns(digits, parity), {
181
+ format: 'ean2',
182
+ text: digits,
183
+ parity,
184
+ });
185
+ if (matrix.width !== EAN2_WIDTH) {
186
+ throw new EncodeError(`EAN-2: internal width is ${matrix.width}, expected ${EAN2_WIDTH}`);
187
+ }
188
+ return matrix;
189
+ }
190
+
191
+ /**
192
+ * Encode an EAN-5 supplement.
193
+ *
194
+ * @param {string|number} value Exactly five decimal digits.
195
+ * @returns {BitMatrix} A 47-module, one-row supplement.
196
+ */
197
+ export function encodeEAN5(value) {
198
+ const digits = normalizeDigits(value, 5, 'EAN-5');
199
+ const checksum = ean5Checksum(digits);
200
+ const parity = EAN5_PARITY[checksum];
201
+ const matrix = toAddonMatrix(encodeDigitPatterns(digits, parity), {
202
+ format: 'ean5',
203
+ text: digits,
204
+ parity,
205
+ checksum,
206
+ });
207
+ if (matrix.width !== EAN5_WIDTH) {
208
+ throw new EncodeError(`EAN-5: internal width is ${matrix.width}, expected ${EAN5_WIDTH}`);
209
+ }
210
+ return matrix;
211
+ }
212
+
213
+ /**
214
+ * Encode either supported supplement length.
215
+ *
216
+ * @param {string|number} value Two or five decimal digits.
217
+ * @returns {BitMatrix}
218
+ */
219
+ export function encodeEANAddon(value) {
220
+ const digits = String(value);
221
+ if (digits.length === 2) return encodeEAN2(digits);
222
+ if (digits.length === 5) return encodeEAN5(digits);
223
+ throw new EncodeError('EAN add-on: payload must contain exactly two or five digits');
224
+ }
225
+
226
+ /** Alias using the spelling used by some EAN documentation. */
227
+ export const encodeEANAddOn = encodeEANAddon;
228
+
229
+ /**
230
+ * @param {BitMatrix} matrix
231
+ * @param {number} offset
232
+ * @param {string} pattern
233
+ * @returns {boolean}
234
+ */
235
+ function matches(matrix, offset, pattern) {
236
+ if (offset < 0 || offset + pattern.length > matrix.width) return false;
237
+ for (let i = 0; i < pattern.length; i++) {
238
+ if ((matrix.get(offset + i, 0) ? '1' : '0') !== pattern[i]) return false;
239
+ }
240
+ return true;
241
+ }
242
+
243
+ /**
244
+ * @param {BitMatrix} matrix
245
+ * @param {number} start
246
+ * @param {2|5} digitCount
247
+ * @returns {{format:string,text:string,parity:string,checksum?:number,end:number}|null}
248
+ */
249
+ function decodeAt(matrix, start, digitCount) {
250
+ const width = digitCount === 2 ? EAN2_WIDTH : EAN5_WIDTH;
251
+ if (!matches(matrix, start, EAN_ADDON_START)) return null;
252
+ if (start > 0 && matrix.get(start - 1, 0)) return null;
253
+
254
+ let offset = start + EAN_ADDON_START.length;
255
+ let text = '';
256
+ let parity = '';
257
+
258
+ for (let i = 0; i < digitCount; i++) {
259
+ let found = null;
260
+ for (let digit = 0; digit < 10; digit++) {
261
+ for (const [letter, table] of [['A', EAN_L], ['B', EAN_G]]) {
262
+ if (matches(matrix, offset, table[digit]) &&
263
+ (!found || found.letter !== letter || found.digit !== digit)) {
264
+ if (found) return null;
265
+ found = { digit, letter };
266
+ }
267
+ }
268
+ }
269
+ if (!found) return null;
270
+ text += String(found.digit);
271
+ parity += found.letter;
272
+ offset += 7;
273
+ if (i < digitCount - 1) {
274
+ if (!matches(matrix, offset, EAN_ADDON_SEPARATOR)) return null;
275
+ offset += EAN_ADDON_SEPARATOR.length;
276
+ }
277
+ }
278
+
279
+ if (offset - start !== width) return null;
280
+ if (digitCount === 2) {
281
+ if (EAN2_PARITY[Number(text) % 4] !== parity) return null;
282
+ return { format: 'ean2', text, parity, end: offset };
283
+ }
284
+
285
+ const checksum = ean5Checksum(text);
286
+ if (EAN5_PARITY[checksum] !== parity) return null;
287
+ return { format: 'ean5', text, parity, checksum, end: offset };
288
+ }
289
+
290
+ /**
291
+ * Validate and decode an EAN-2 supplement. A leading quiet zone is accepted;
292
+ * the decoder searches the row for a valid start guard so a composed base
293
+ * EAN/UPC matrix can be passed directly as well.
294
+ *
295
+ * @param {BitMatrix} matrix One-row, module-aligned supplement or composition.
296
+ * @returns {{format:'ean2',text:string,parity:string}}
297
+ * @throws {FormatError} When no valid supplement is found.
298
+ */
299
+ export function decodeEAN2(matrix) {
300
+ if (!matrix || !Number.isInteger(matrix.width) || matrix.height !== 1) {
301
+ throw new FormatError('EAN-2: expected a one-row module matrix');
302
+ }
303
+ for (let start = 0; start + EAN2_WIDTH <= matrix.width; start++) {
304
+ const result = decodeAt(matrix, start, 2);
305
+ if (result) {
306
+ const { end, ...publicResult } = result;
307
+ void end;
308
+ return publicResult;
309
+ }
310
+ }
311
+ throw new FormatError('EAN-2: start, parity or digit pattern is invalid');
312
+ }
313
+
314
+ /**
315
+ * Validate and decode an EAN-5 supplement.
316
+ *
317
+ * @param {BitMatrix} matrix One-row, module-aligned supplement or composition.
318
+ * @returns {{format:'ean5',text:string,parity:string,checksum:number}}
319
+ * @throws {FormatError} When no valid supplement is found.
320
+ */
321
+ export function decodeEAN5(matrix) {
322
+ if (!matrix || !Number.isInteger(matrix.width) || matrix.height !== 1) {
323
+ throw new FormatError('EAN-5: expected a one-row module matrix');
324
+ }
325
+ for (let start = 0; start + EAN5_WIDTH <= matrix.width; start++) {
326
+ const result = decodeAt(matrix, start, 5);
327
+ if (result) {
328
+ const { end, ...publicResult } = result;
329
+ void end;
330
+ return publicResult;
331
+ }
332
+ }
333
+ throw new FormatError('EAN-5: start, parity, checksum or digit pattern is invalid');
334
+ }
335
+
336
+ /**
337
+ * Decode either supported supplement length.
338
+ *
339
+ * @param {BitMatrix} matrix One-row, module-aligned supplement or composition.
340
+ * @returns {{format:'ean2'|'ean5',text:string,parity:string,checksum?:number}}
341
+ * @throws {FormatError} When neither supplement grammar matches.
342
+ */
343
+ export function decodeEANAddon(matrix) {
344
+ try {
345
+ return decodeEAN5(matrix);
346
+ } catch (fiveError) {
347
+ try {
348
+ return decodeEAN2(matrix);
349
+ } catch (twoError) {
350
+ throw new FormatError(`EAN add-on: ${fiveError.message}; ${twoError.message}`);
351
+ }
352
+ }
353
+ }
354
+
355
+ /** Alias using the spelling used by some EAN documentation. */
356
+ export const decodeEANAddOn = decodeEANAddon;
357
+
358
+ /**
359
+ * Join a base EAN/UPC matrix and a supplement with the standard quiet gap.
360
+ *
361
+ * The helper does not alter either input. By default it inserts nine light
362
+ * modules, the conventional separation between the base symbol and an add-on.
363
+ * The result carries the supplement metadata under `eanAddon` for renderers or
364
+ * callers that need to label the composed symbol.
365
+ *
366
+ * @param {BitMatrix} base Base EAN/UPC matrix.
367
+ * @param {BitMatrix|string|number} addon Add-on matrix or two/five digits.
368
+ * @param {{gap?:number}} [options]
369
+ * @returns {BitMatrix}
370
+ */
371
+ export function composeEANAddon(base, addon, options = {}) {
372
+ if (!base || !Number.isInteger(base.width) || base.height !== 1) {
373
+ throw new TypeError('EAN add-on: base must be a one-row module matrix');
374
+ }
375
+ const addonMatrix = typeof addon === 'string' || typeof addon === 'number'
376
+ ? encodeEANAddon(addon)
377
+ : addon;
378
+ if (!addonMatrix || !Number.isInteger(addonMatrix.width) || addonMatrix.height !== 1) {
379
+ throw new TypeError('EAN add-on: supplement must be a one-row module matrix or digits');
380
+ }
381
+
382
+ const gap = options.gap === undefined ? 9 : Number(options.gap);
383
+ if (!Number.isInteger(gap) || gap < 1) {
384
+ throw new EncodeError(`EAN add-on: gap must be a positive integer, got ${options.gap}`);
385
+ }
386
+
387
+ const result = new BitMatrix(base.width + gap + addonMatrix.width, 1);
388
+ for (let x = 0; x < base.width; x++) if (base.get(x, 0)) result.set(x, 0);
389
+ for (let x = 0; x < addonMatrix.width; x++) {
390
+ if (addonMatrix.get(x, 0)) result.set(base.width + gap + x, 0);
391
+ }
392
+ if (addonMatrix.eanAddon) result.eanAddon = { ...addonMatrix.eanAddon, gap };
393
+ return result;
394
+ }
395
+
396
+ /**
397
+ * Compose an EAN-13 symbol with an EAN-2 or EAN-5 supplement.
398
+ *
399
+ * @param {string} value Base EAN-13 payload.
400
+ * @param {string|number} addon Two or five supplemental digits.
401
+ * @param {{gap?:number}} [options]
402
+ * @returns {BitMatrix}
403
+ */
404
+ export function encodeEAN13WithAddon(value, addon, options = {}) {
405
+ return composeEANAddon(encodeEAN13(value), addon, options);
406
+ }
407
+
408
+ /** @see encodeEAN13WithAddon */
409
+ export function encodeEAN8WithAddon(value, addon, options = {}) {
410
+ return composeEANAddon(encodeEAN8(value), addon, options);
411
+ }
412
+
413
+ /** @see encodeEAN13WithAddon */
414
+ export function encodeUPCAWithAddon(value, addon, options = {}) {
415
+ return composeEANAddon(encodeUPCA(value), addon, options);
416
+ }
417
+
418
+ /** @see encodeEAN13WithAddon */
419
+ export function encodeUPCEWithAddon(value, addon, options = {}) {
420
+ return composeEANAddon(encodeUPCE(value), addon, options);
421
+ }
package/src/oned/index.js CHANGED
@@ -23,67 +23,85 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
24
  * SOFTWARE.
25
25
  *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
26
27
  * SPDX-License-Identifier: MIT
27
28
  *
28
29
  * Original work. No code from any other barcode implementation.
29
30
  */
30
31
 
31
- /**
32
- * Linear symbologies.
33
- *
34
- * @module oned
35
- */
36
-
37
- export {
38
- encodeEAN13, encodeEAN8, encodeUPCA, encodeUPCE, encodeISBN,
39
- encodeCode39, encodeCode93, encodeCode128,
40
- encodeITF, encodeITF14, encodeCodabar, encodeCode11,
41
- encodeMSI, encodePharmacode,
42
- ean13CheckDigit,
43
- } from './writers.js';
44
-
45
- export {
46
- decodeOneD, decodeOneDStrict,
47
- patternVariance, recordPattern, toNarrowWidePattern,
48
- } from './reader.js';
49
-
50
- export { validateTables } from './patterns.js';
51
-
52
- import {
53
- encodeEAN13, encodeEAN8, encodeUPCA, encodeUPCE, encodeISBN,
54
- encodeCode39, encodeCode93, encodeCode128,
55
- encodeITF, encodeITF14, encodeCodabar, encodeCode11,
56
- encodeMSI, encodePharmacode,
57
- } from './writers.js';
58
-
59
- /**
60
- * Writers by format id, for the top-level `encode()` dispatcher.
61
- *
62
- * `readable` marks the formats this suite can also decode. Writing is a table
63
- * lookup and easy to support broadly; reading needs a detector per symbology,
64
- * so the two lists legitimately differ and the API says so rather than
65
- * failing at runtime.
66
- *
67
- * @type {Record<string, {encode: Function, readable: boolean, label: string}>}
68
- */
69
- export const ONED_FORMATS = {
70
- ean13: { encode: encodeEAN13, readable: true, label: 'EAN-13' },
71
- ean8: { encode: encodeEAN8, readable: true, label: 'EAN-8' },
72
- upca: { encode: encodeUPCA, readable: true, label: 'UPC-A' },
73
- isbn: { encode: encodeISBN, readable: true, label: 'ISBN (Bookland EAN-13)' },
74
- upce: { encode: encodeUPCE, readable: true, label: 'UPC-E' },
75
- code128: { encode: encodeCode128, readable: true, label: 'Code 128' },
76
- gs1128: {
77
- encode: (v, o) => encodeCode128(v, { ...o, gs1: true }),
78
- readable: true,
79
- label: 'GS1-128',
80
- },
81
- code39: { encode: encodeCode39, readable: true, label: 'Code 39' },
82
- code93: { encode: encodeCode93, readable: true, label: 'Code 93' },
83
- itf: { encode: encodeITF, readable: true, label: 'ITF (Interleaved 2 of 5)' },
84
- itf14: { encode: encodeITF14, readable: true, label: 'ITF-14' },
85
- codabar: { encode: encodeCodabar, readable: true, label: 'Codabar' },
86
- code11: { encode: encodeCode11, readable: false, label: 'Code 11' },
87
- msi: { encode: encodeMSI, readable: false, label: 'MSI Plessey' },
88
- pharmacode: { encode: encodePharmacode, readable: false, label: 'Pharmacode' },
89
- };
32
+ /**
33
+ * Linear symbologies.
34
+ *
35
+ * @module oned
36
+ */
37
+
38
+ export {
39
+ encodeEAN13, encodeEAN8, encodeUPCA, encodeUPCE, encodeISBN,
40
+ encodeCode39, encodeCode93, encodeCode128,
41
+ encodeITF, encodeITF14, encodeCodabar, encodeCode11,
42
+ encodeMSI, encodePharmacode,
43
+ ean13CheckDigit,
44
+ } from './writers.js';
45
+
46
+ export {
47
+ EAN2_PARITY, EAN5_PARITY, EAN2_WIDTH, EAN5_WIDTH,
48
+ EAN_ADDON_START, EAN_ADDON_SEPARATOR,
49
+ ean2Parity, ean5Checksum, ean5CheckDigit, ean5Parity,
50
+ encodeEAN2, encodeEAN5, encodeEANAddon, encodeEANAddOn,
51
+ decodeEAN2, decodeEAN5, decodeEANAddon, decodeEANAddOn,
52
+ composeEANAddon,
53
+ encodeEAN13WithAddon, encodeEAN8WithAddon,
54
+ encodeUPCAWithAddon, encodeUPCEWithAddon,
55
+ } from './addons.js';
56
+
57
+ export {
58
+ decodeOneD, decodeOneDStrict,
59
+ patternVariance, recordPattern, toNarrowWidePattern,
60
+ } from './reader.js';
61
+
62
+ export { validateTables } from './patterns.js';
63
+
64
+ import {
65
+ encodeEAN13, encodeEAN8, encodeUPCA, encodeUPCE, encodeISBN,
66
+ encodeCode39, encodeCode93, encodeCode128,
67
+ encodeITF, encodeITF14, encodeCodabar, encodeCode11,
68
+ encodeMSI, encodePharmacode,
69
+ } from './writers.js';
70
+ import { encodeEAN2, encodeEAN5 } from './addons.js';
71
+
72
+ /**
73
+ * Writers by format id, for the top-level `encode()` dispatcher.
74
+ *
75
+ * `readable` marks the formats this suite can also decode. Writing is a table
76
+ * lookup and easy to support broadly; reading needs a detector per symbology,
77
+ * so the two lists legitimately differ and the API says so rather than
78
+ * failing at runtime.
79
+ *
80
+ * @type {Record<string, {encode: Function, readable: boolean, label: string}>}
81
+ */
82
+ export const ONED_FORMATS = {
83
+ ean13: { encode: encodeEAN13, readable: true, label: 'EAN-13' },
84
+ ean8: { encode: encodeEAN8, readable: true, label: 'EAN-8' },
85
+ upca: { encode: encodeUPCA, readable: true, label: 'UPC-A' },
86
+ isbn: { encode: encodeISBN, readable: true, label: 'ISBN (Bookland EAN-13)' },
87
+ upce: { encode: encodeUPCE, readable: true, label: 'UPC-E' },
88
+ code128: { encode: encodeCode128, readable: true, label: 'Code 128' },
89
+ gs1128: {
90
+ encode: (v, o) => encodeCode128(v, { ...o, gs1: true }),
91
+ readable: true,
92
+ label: 'GS1-128',
93
+ },
94
+ code39: { encode: encodeCode39, readable: true, label: 'Code 39' },
95
+ code93: { encode: encodeCode93, readable: true, label: 'Code 93' },
96
+ itf: { encode: encodeITF, readable: true, label: 'ITF (Interleaved 2 of 5)' },
97
+ itf14: { encode: encodeITF14, readable: true, label: 'ITF-14' },
98
+ codabar: { encode: encodeCodabar, readable: true, label: 'Codabar' },
99
+ code11: { encode: encodeCode11, readable: false, label: 'Code 11' },
100
+ msi: { encode: encodeMSI, readable: false, label: 'MSI Plessey' },
101
+ pharmacode: { encode: encodePharmacode, readable: false, label: 'Pharmacode' },
102
+ // Supplements are writable standalone matrices, but their reader is
103
+ // intentionally exposed through the EAN/UPC add-on helpers rather than the
104
+ // generic one-dimensional scan pipeline.
105
+ ean2: { encode: encodeEAN2, readable: false, label: 'EAN-2 supplement' },
106
+ ean5: { encode: encodeEAN5, readable: false, label: 'EAN-5 supplement' },
107
+ };
@@ -23,6 +23,7 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
24
  * SOFTWARE.
25
25
  *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
26
27
  * SPDX-License-Identifier: MIT
27
28
  *
28
29
  * Original work. No code from any other barcode implementation.
@@ -23,6 +23,7 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
24
  * SOFTWARE.
25
25
  *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
26
27
  * SPDX-License-Identifier: MIT
27
28
  *
28
29
  * Original work. No code from any other barcode implementation.
@@ -23,6 +23,7 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
24
  * SOFTWARE.
25
25
  *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
26
27
  * SPDX-License-Identifier: MIT
27
28
  *
28
29
  * Original work. No code from any other barcode implementation.
@@ -23,6 +23,7 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
24
  * SOFTWARE.
25
25
  *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
26
27
  * SPDX-License-Identifier: MIT
27
28
  *
28
29
  * Original work. No code from any other barcode implementation.
@@ -23,6 +23,7 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
24
  * SOFTWARE.
25
25
  *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
26
27
  * SPDX-License-Identifier: MIT
27
28
  *
28
29
  * Original work. No code from any other barcode implementation.
@@ -23,6 +23,7 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
24
  * SOFTWARE.
25
25
  *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
26
27
  * SPDX-License-Identifier: MIT
27
28
  *
28
29
  * Original work. No code from any other barcode implementation.
@@ -23,6 +23,7 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
24
  * SOFTWARE.
25
25
  *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
26
27
  * SPDX-License-Identifier: MIT
27
28
  *
28
29
  * Original work. No code from any other barcode implementation.
@@ -23,6 +23,7 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
24
  * SOFTWARE.
25
25
  *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
26
27
  * SPDX-License-Identifier: MIT
27
28
  *
28
29
  * Original work. No code from any other barcode implementation.
@@ -1,3 +1,8 @@
1
+ /*!
2
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
1
6
  export { compactPdf417, compactPdf417Text, compactPdf417Bytes, compactPdf417Numeric, decodePdf417Compaction, decodePdf417CompactionDetailed } from './compaction.js';
2
7
  export { encodePDF417 } from './encoder.js';
3
8
  export { decodePDF417 } from './decoder.js';
@@ -23,6 +23,7 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
24
  * SOFTWARE.
25
25
  *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
26
27
  * SPDX-License-Identifier: MIT
27
28
  *
28
29
  * Original work. No code from any other barcode implementation.
package/src/qr/decoder.js CHANGED
@@ -23,6 +23,7 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
24
  * SOFTWARE.
25
25
  *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
26
27
  * SPDX-License-Identifier: MIT
27
28
  *
28
29
  * Original work. No code from any other barcode implementation.
@@ -23,6 +23,7 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
24
  * SOFTWARE.
25
25
  *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
26
27
  * SPDX-License-Identifier: MIT
27
28
  *
28
29
  * Original work. No code from any other barcode implementation.