@sythos/js_barcode_universal 1.5.8 → 1.5.10

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 (179) hide show
  1. package/LICENSE +5 -4
  2. package/NOTICE.md +2 -2
  3. package/README.md +61 -13
  4. package/bundle/sythos-barcode.esm.js +11658 -11244
  5. package/bundle/sythos-barcode.js +11658 -11244
  6. package/package.json +10 -3
  7. package/src/index.d.ts +1 -1
  8. package/src/index.js +508 -516
  9. package/src/js/aztec/decoder.js +208 -199
  10. package/src/js/aztec/detector.js +153 -126
  11. package/src/js/aztec/encoder.js +172 -153
  12. package/src/js/aztec/high-level.js +106 -101
  13. package/src/js/aztec/index.js +1 -12
  14. package/src/js/aztec/tables.js +106 -120
  15. package/src/js/aztecrune/decoder.js +76 -85
  16. package/src/js/aztecrune/detector.js +107 -93
  17. package/src/js/aztecrune/encoder.js +50 -68
  18. package/src/js/aztecrune/index.js +1 -16
  19. package/src/js/aztecrune/tables.js +59 -54
  20. package/src/js/compactpdf417/decoder.js +69 -74
  21. package/src/js/compactpdf417/detector.js +74 -75
  22. package/src/js/compactpdf417/encoder.js +68 -81
  23. package/src/js/compactpdf417/index.js +1 -13
  24. package/src/js/compactpdf417/tables.js +71 -80
  25. package/src/js/core/bit-buffer.js +106 -122
  26. package/src/js/core/bit-matrix.js +196 -194
  27. package/src/js/core/errors.js +13 -15
  28. package/src/js/core/galois-field.js +119 -133
  29. package/src/js/core/index.js +2 -19
  30. package/src/js/core/reed-solomon.js +195 -204
  31. package/src/js/databar/codec.js +93 -108
  32. package/src/js/databar/decoder.js +149 -140
  33. package/src/js/databar/encoder.js +47 -55
  34. package/src/js/databar/gs1.js +122 -123
  35. package/src/js/databar/index.js +4 -36
  36. package/src/js/databar/patterns.js +81 -85
  37. package/src/js/databar/tables.js +51 -52
  38. package/src/js/datamatrix/decoder.js +216 -182
  39. package/src/js/datamatrix/detector.js +161 -132
  40. package/src/js/datamatrix/encoder.js +192 -133
  41. package/src/js/datamatrix/index.js +1 -9
  42. package/src/js/datamatrix/tables.js +68 -69
  43. package/src/js/frameqr/decoder.js +102 -125
  44. package/src/js/frameqr/detector.js +101 -94
  45. package/src/js/frameqr/encoder.js +67 -80
  46. package/src/js/frameqr/index.js +1 -10
  47. package/src/js/frameqr/tables.js +145 -163
  48. package/src/js/image/binarizer.js +146 -162
  49. package/src/js/image/grid-sampler.js +63 -79
  50. package/src/js/image/index.js +0 -2
  51. package/src/js/image/luminance.js +129 -140
  52. package/src/js/image/perspective.js +112 -149
  53. package/src/js/micropdf417/compaction.js +64 -65
  54. package/src/js/micropdf417/decoder.js +106 -109
  55. package/src/js/micropdf417/detector.js +73 -70
  56. package/src/js/micropdf417/encoder.js +129 -154
  57. package/src/js/micropdf417/error-correction.js +6 -11
  58. package/src/js/micropdf417/index.js +2 -16
  59. package/src/js/micropdf417/tables.js +112 -99
  60. package/src/js/microqr/decoder.js +177 -182
  61. package/src/js/microqr/detector.js +240 -256
  62. package/src/js/microqr/encoder.js +239 -194
  63. package/src/js/microqr/index.js +0 -2
  64. package/src/js/microqr/tables.js +208 -200
  65. package/src/js/oned/addons.js +167 -191
  66. package/src/js/oned/index.js +27 -58
  67. package/src/js/oned/patterns.js +194 -213
  68. package/src/js/oned/reader.js +1003 -984
  69. package/src/js/oned/writers.js +411 -466
  70. package/src/js/pdf417/compaction.js +315 -222
  71. package/src/js/pdf417/decoder.js +71 -36
  72. package/src/js/pdf417/detector.js +377 -361
  73. package/src/js/pdf417/encoder.js +57 -46
  74. package/src/js/pdf417/error-correction.js +5 -8
  75. package/src/js/pdf417/tables.js +248 -250
  76. package/src/js/qr/decoder.js +311 -347
  77. package/src/js/qr/detector.js +378 -395
  78. package/src/js/qr/encoder.js +514 -599
  79. package/src/js/qr/index.js +0 -2
  80. package/src/js/qr/tables.js +375 -422
  81. package/src/js/render/image-data.js +57 -62
  82. package/src/js/render/index.js +21 -23
  83. package/src/js/render/options.js +82 -90
  84. package/src/js/render/png.js +144 -169
  85. package/src/js/render/svg.js +41 -44
  86. package/src/js/render/webgl.js +103 -109
  87. package/src/js/render/webgpu.js +205 -217
  88. package/src/js/rmqr/decoder.js +161 -53
  89. package/src/js/rmqr/detector.js +73 -41
  90. package/src/js/rmqr/encoder.js +253 -104
  91. package/src/js/rmqr/index.js +1 -5
  92. package/src/js/rmqr/tables.js +108 -85
  93. package/src/ts/aztec/decoder.ts +317 -0
  94. package/src/ts/aztec/detector.ts +224 -0
  95. package/src/ts/aztec/encoder.ts +257 -0
  96. package/src/ts/aztec/high-level.ts +211 -0
  97. package/src/ts/aztec/index.ts +45 -0
  98. package/src/ts/aztec/tables.ts +210 -0
  99. package/src/ts/aztecrune/decoder.ts +155 -0
  100. package/src/ts/aztecrune/detector.ts +166 -0
  101. package/src/ts/aztecrune/encoder.ts +121 -0
  102. package/src/ts/aztecrune/index.ts +49 -0
  103. package/src/ts/aztecrune/tables.ts +137 -0
  104. package/src/ts/compactpdf417/decoder.ts +128 -0
  105. package/src/ts/compactpdf417/detector.ts +139 -0
  106. package/src/ts/compactpdf417/encoder.ts +140 -0
  107. package/src/ts/compactpdf417/index.ts +17 -0
  108. package/src/ts/compactpdf417/tables.ts +173 -0
  109. package/src/ts/core/bit-buffer.ts +174 -0
  110. package/src/ts/core/bit-matrix.ts +241 -0
  111. package/src/ts/core/errors.ts +61 -0
  112. package/src/ts/core/galois-field.ts +207 -0
  113. package/src/ts/core/index.ts +56 -0
  114. package/src/ts/core/reed-solomon.ts +327 -0
  115. package/src/ts/databar/codec.ts +181 -0
  116. package/src/ts/databar/decoder.ts +215 -0
  117. package/src/ts/databar/encoder.ts +96 -0
  118. package/src/ts/databar/gs1.ts +177 -0
  119. package/src/ts/databar/index.ts +68 -0
  120. package/src/ts/databar/patterns.ts +143 -0
  121. package/src/ts/databar/tables.ts +124 -0
  122. package/src/ts/datamatrix/decoder.ts +262 -0
  123. package/src/ts/datamatrix/detector.ts +225 -0
  124. package/src/ts/datamatrix/encoder.ts +191 -0
  125. package/src/ts/datamatrix/index.ts +42 -0
  126. package/src/ts/datamatrix/tables.ts +123 -0
  127. package/src/ts/frameqr/decoder.ts +239 -0
  128. package/src/ts/frameqr/detector.ts +192 -0
  129. package/src/ts/frameqr/encoder.ts +156 -0
  130. package/src/ts/frameqr/index.ts +42 -0
  131. package/src/ts/frameqr/tables.ts +270 -0
  132. package/src/ts/image/binarizer.ts +270 -0
  133. package/src/ts/image/grid-sampler.ts +164 -0
  134. package/src/ts/image/index.ts +40 -0
  135. package/src/ts/image/luminance.ts +196 -0
  136. package/src/ts/image/perspective.ts +195 -0
  137. package/src/ts/index.d.ts +1 -1
  138. package/src/ts/index.ts +790 -0
  139. package/src/ts/micropdf417/compaction.ts +116 -0
  140. package/src/ts/micropdf417/decoder.ts +183 -0
  141. package/src/ts/micropdf417/detector.ts +149 -0
  142. package/src/ts/micropdf417/encoder.ts +209 -0
  143. package/src/ts/micropdf417/error-correction.ts +55 -0
  144. package/src/ts/micropdf417/index.ts +49 -0
  145. package/src/ts/micropdf417/tables.ts +184 -0
  146. package/src/ts/microqr/decoder.ts +245 -0
  147. package/src/ts/microqr/detector.ts +355 -0
  148. package/src/ts/microqr/encoder.ts +269 -0
  149. package/src/ts/microqr/index.ts +36 -0
  150. package/src/ts/microqr/tables.ts +316 -0
  151. package/src/ts/oned/addons.ts +420 -0
  152. package/src/ts/oned/index.ts +106 -0
  153. package/src/ts/oned/patterns.ts +384 -0
  154. package/src/ts/oned/reader.ts +1364 -0
  155. package/src/ts/oned/writers.ts +746 -0
  156. package/src/ts/pdf417/compaction.ts +298 -0
  157. package/src/ts/pdf417/decoder.ts +75 -0
  158. package/src/ts/pdf417/detector.ts +468 -0
  159. package/src/ts/pdf417/encoder.ts +91 -0
  160. package/src/ts/pdf417/error-correction.ts +47 -0
  161. package/src/ts/pdf417/index.ts +6 -0
  162. package/src/ts/pdf417/tables.ts +317 -0
  163. package/src/ts/qr/decoder.ts +575 -0
  164. package/src/ts/qr/detector.ts +630 -0
  165. package/src/ts/qr/encoder.ts +958 -0
  166. package/src/ts/qr/index.ts +44 -0
  167. package/src/ts/qr/tables.ts +737 -0
  168. package/src/ts/render/image-data.ts +125 -0
  169. package/src/ts/render/index.ts +130 -0
  170. package/src/ts/render/options.ts +160 -0
  171. package/src/ts/render/png.ts +295 -0
  172. package/src/ts/render/svg.ts +120 -0
  173. package/src/ts/render/webgl.ts +206 -0
  174. package/src/ts/render/webgpu.ts +369 -0
  175. package/src/ts/rmqr/decoder.ts +101 -0
  176. package/src/ts/rmqr/detector.ts +90 -0
  177. package/src/ts/rmqr/encoder.ts +172 -0
  178. package/src/ts/rmqr/index.ts +37 -0
  179. package/src/ts/rmqr/tables.ts +154 -0
@@ -27,70 +27,62 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  /** GS1 DataBar Omnidirectional and Truncated encoder. @module databar/encoder */
32
-
33
31
  import { BitMatrix } from '../core/bit-matrix.js';
34
32
  import { EncodeError } from '../core/errors.js';
35
33
  import { encodeDataBar14GTIN } from './codec.js';
36
- import {
37
- DATABAR14_CHECKSUM_WEIGHTS,
38
- DATABAR14_FINDERS,
39
- dataBar14CharacterWidths,
40
- } from './patterns.js';
41
-
34
+ import { DATABAR14_CHECKSUM_WEIGHTS, DATABAR14_FINDERS, dataBar14CharacterWidths, } from './patterns.js';
42
35
  function finderIndexes(characters) {
43
- const widths = characters.map((value, index) =>
44
- dataBar14CharacterWidths(value, index === 0 || index === 3 ? 'outside' : 'inside')
45
- );
46
- let checksum = 0;
47
- const weightOffsets = [0, 8, 24, 16];
48
- for (let character = 0; character < 4; character++) {
49
- for (let element = 0; element < 8; element++) {
50
- checksum += widths[character][element] * DATABAR14_CHECKSUM_WEIGHTS[weightOffsets[character] + element];
36
+ const widths = characters.map((value, index) => dataBar14CharacterWidths(value, index === 0 || index === 3 ? 'outside' : 'inside'));
37
+ let checksum = 0;
38
+ const weightOffsets = [0, 8, 24, 16];
39
+ for (let character = 0; character < 4; character++) {
40
+ for (let element = 0; element < 8; element++) {
41
+ checksum += widths[character][element] * DATABAR14_CHECKSUM_WEIGHTS[weightOffsets[character] + element];
42
+ }
51
43
  }
52
- }
53
- checksum %= 79;
54
- if (checksum >= 8) checksum++;
55
- if (checksum >= 72) checksum++;
56
- return { widths, checksum, left: Math.floor(checksum / 9), right: checksum % 9 };
44
+ checksum %= 79;
45
+ if (checksum >= 8)
46
+ checksum++;
47
+ if (checksum >= 72)
48
+ checksum++;
49
+ return { widths, checksum, left: Math.floor(checksum / 9), right: checksum % 9 };
57
50
  }
58
-
59
51
  function widthsToMatrix(widths, height) {
60
- const width = widths.reduce((sum, value) => sum + value, 0);
61
- const matrix = new BitMatrix(width, height);
62
- let dark = false;
63
- let x = 0;
64
- for (const run of widths) {
65
- if (dark) matrix.setRegion(x, 0, run, height);
66
- x += run;
67
- dark = !dark;
68
- }
69
- return matrix;
52
+ const width = widths.reduce((sum, value) => sum + value, 0);
53
+ const matrix = new BitMatrix(width, height);
54
+ let dark = false;
55
+ let x = 0;
56
+ for (const run of widths) {
57
+ if (dark)
58
+ matrix.setRegion(x, 0, run, height);
59
+ x += run;
60
+ dark = !dark;
61
+ }
62
+ return matrix;
70
63
  }
71
-
72
64
  /** Encode a checked GTIN as DataBar Omnidirectional or Truncated. */
73
65
  export function encodeDataBar14(value, options = {}) {
74
- const variant = options.variant ?? 'omnidirectional';
75
- if (variant !== 'omnidirectional' && variant !== 'truncated') {
76
- throw new EncodeError('GS1 DataBar-14 physical encoder currently supports omnidirectional and truncated');
77
- }
78
- const height = options.height ?? (variant === 'omnidirectional' ? 33 : 13);
79
- if (!Number.isInteger(height) || height < (variant === 'omnidirectional' ? 33 : 13)) {
80
- throw new EncodeError(`GS1 DataBar ${variant} height is below its normative minimum`);
81
- }
82
- const compacted = encodeDataBar14GTIN(value, { linkage: options.linkage });
83
- const characters = compacted.physicalCharacters;
84
- const check = finderIndexes(characters);
85
- const widths = [1, 1];
86
- widths.push(...check.widths[0]);
87
- widths.push(...DATABAR14_FINDERS[check.left]);
88
- widths.push(...check.widths[1].slice().reverse());
89
- widths.push(...check.widths[2]);
90
- widths.push(...DATABAR14_FINDERS[check.right].slice().reverse());
91
- widths.push(...check.widths[3].slice().reverse());
92
- widths.push(1, 1);
93
- const matrix = widthsToMatrix(widths, height);
94
- matrix.databar = Object.freeze({ variant, gtin: compacted.gtin, linkage: compacted.linkage, checksum: check.checksum });
95
- return matrix;
66
+ const variant = options.variant ?? 'omnidirectional';
67
+ if (variant !== 'omnidirectional' && variant !== 'truncated') {
68
+ throw new EncodeError('GS1 DataBar-14 physical encoder currently supports omnidirectional and truncated');
69
+ }
70
+ const height = options.height ?? (variant === 'omnidirectional' ? 33 : 13);
71
+ if (!Number.isInteger(height) || height < (variant === 'omnidirectional' ? 33 : 13)) {
72
+ throw new EncodeError(`GS1 DataBar ${variant} height is below its normative minimum`);
73
+ }
74
+ const compacted = encodeDataBar14GTIN(value, { linkage: options.linkage });
75
+ const characters = compacted.physicalCharacters;
76
+ const check = finderIndexes(characters);
77
+ const widths = [1, 1];
78
+ widths.push(...check.widths[0]);
79
+ widths.push(...DATABAR14_FINDERS[check.left]);
80
+ widths.push(...check.widths[1].slice().reverse());
81
+ widths.push(...check.widths[2]);
82
+ widths.push(...DATABAR14_FINDERS[check.right].slice().reverse());
83
+ widths.push(...check.widths[3].slice().reverse());
84
+ widths.push(1, 1);
85
+ const matrix = widthsToMatrix(widths, height);
86
+ matrix.databar = Object.freeze({ variant, gtin: compacted.gtin, linkage: compacted.linkage, checksum: check.checksum });
87
+ return matrix;
96
88
  }
@@ -27,151 +27,150 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  /** GS1 element-string codec used by GS1 DataBar Expanded. @module databar/gs1 */
32
-
33
31
  import { EncodeError, FormatError } from '../core/errors.js';
34
-
35
32
  export const GS1_SEPARATOR = '\x1d';
36
-
37
33
  const EXACT = new Map([
38
- ['00', [18, true]], ['01', [14, true]], ['02', [14, true]],
39
- ['10', [20, false]], ['11', [6, true]], ['12', [6, true]],
40
- ['13', [6, true]], ['15', [6, true]], ['16', [6, true]],
41
- ['17', [6, true]], ['20', [2, true]], ['21', [20, false]],
42
- ['22', [29, false]], ['30', [8, false]], ['37', [8, false]],
43
- ['240', [30, false]], ['241', [30, false]], ['242', [6, false]],
44
- ['243', [20, false]], ['250', [30, false]], ['251', [30, false]],
45
- ['253', [30, false]], ['254', [20, false]], ['255', [13, true]],
46
- ['400', [30, false]], ['401', [30, false]], ['402', [17, true]],
47
- ['403', [30, false]], ['410', [13, true]], ['411', [13, true]],
48
- ['412', [13, true]], ['413', [13, true]], ['414', [13, true]],
49
- ['415', [13, true]], ['416', [13, true]], ['417', [13, true]],
50
- ['420', [20, false]], ['421', [15, false]], ['422', [3, true]],
51
- ['423', [15, false]], ['424', [3, true]], ['425', [3, true]],
52
- ['426', [3, true]], ['427', [3, false]],
53
- ['7001', [13, true]], ['7002', [30, false]], ['7003', [10, true]],
54
- ['7004', [4, false]], ['7005', [12, false]], ['7006', [6, true]],
55
- ['7007', [12, false]], ['7008', [3, false]], ['7009', [10, false]],
56
- ['7010', [2, false]], ['7020', [20, false]], ['7021', [20, false]],
57
- ['7022', [20, false]], ['710', [20, false]], ['711', [20, false]],
58
- ['712', [20, false]], ['713', [20, false]], ['714', [20, false]],
59
- ['715', [20, false]],
60
- ['8001', [14, true]], ['8002', [20, false]], ['8003', [30, false]],
61
- ['8004', [30, false]], ['8005', [6, true]], ['8006', [18, true]],
62
- ['8007', [34, false]], ['8008', [12, false]], ['8009', [50, false]],
63
- ['8010', [30, false]], ['8011', [12, false]], ['8012', [20, false]],
64
- ['8013', [30, false]], ['8017', [18, true]], ['8018', [18, true]],
65
- ['8019', [10, false]], ['8020', [25, false]], ['8026', [18, true]],
66
- ['8110', [70, false]], ['8111', [4, true]], ['8112', [70, false]],
67
- ['8200', [70, false]],
34
+ ['00', [18, true]], ['01', [14, true]], ['02', [14, true]],
35
+ ['10', [20, false]], ['11', [6, true]], ['12', [6, true]],
36
+ ['13', [6, true]], ['15', [6, true]], ['16', [6, true]],
37
+ ['17', [6, true]], ['20', [2, true]], ['21', [20, false]],
38
+ ['22', [29, false]], ['30', [8, false]], ['37', [8, false]],
39
+ ['240', [30, false]], ['241', [30, false]], ['242', [6, false]],
40
+ ['243', [20, false]], ['250', [30, false]], ['251', [30, false]],
41
+ ['253', [30, false]], ['254', [20, false]], ['255', [13, true]],
42
+ ['400', [30, false]], ['401', [30, false]], ['402', [17, true]],
43
+ ['403', [30, false]], ['410', [13, true]], ['411', [13, true]],
44
+ ['412', [13, true]], ['413', [13, true]], ['414', [13, true]],
45
+ ['415', [13, true]], ['416', [13, true]], ['417', [13, true]],
46
+ ['420', [20, false]], ['421', [15, false]], ['422', [3, true]],
47
+ ['423', [15, false]], ['424', [3, true]], ['425', [3, true]],
48
+ ['426', [3, true]], ['427', [3, false]],
49
+ ['7001', [13, true]], ['7002', [30, false]], ['7003', [10, true]],
50
+ ['7004', [4, false]], ['7005', [12, false]], ['7006', [6, true]],
51
+ ['7007', [12, false]], ['7008', [3, false]], ['7009', [10, false]],
52
+ ['7010', [2, false]], ['7020', [20, false]], ['7021', [20, false]],
53
+ ['7022', [20, false]], ['710', [20, false]], ['711', [20, false]],
54
+ ['712', [20, false]], ['713', [20, false]], ['714', [20, false]],
55
+ ['715', [20, false]],
56
+ ['8001', [14, true]], ['8002', [20, false]], ['8003', [30, false]],
57
+ ['8004', [30, false]], ['8005', [6, true]], ['8006', [18, true]],
58
+ ['8007', [34, false]], ['8008', [12, false]], ['8009', [50, false]],
59
+ ['8010', [30, false]], ['8011', [12, false]], ['8012', [20, false]],
60
+ ['8013', [30, false]], ['8017', [18, true]], ['8018', [18, true]],
61
+ ['8019', [10, false]], ['8020', [25, false]], ['8026', [18, true]],
62
+ ['8110', [70, false]], ['8111', [4, true]], ['8112', [70, false]],
63
+ ['8200', [70, false]],
68
64
  ]);
69
-
70
65
  function rangedAI(ai) {
71
- if (/^31[0-6]\d$/.test(ai) || /^32[0-7]\d$/.test(ai) ||
72
- /^33[0-7]\d$/.test(ai) || /^34[0-9]\d$/.test(ai) ||
73
- /^35[0-7]\d$/.test(ai) || /^36[0-9]\d$/.test(ai)) return [6, true];
74
- if (/^390\d$/.test(ai) || /^392\d$/.test(ai)) return [15, false];
75
- if (/^391\d$/.test(ai) || /^393\d$/.test(ai)) return [18, false];
76
- if (/^394\d$/.test(ai)) return [4, true];
77
- if (/^395\d$/.test(ai)) return [6, true];
78
- if (/^703\d$/.test(ai) || /^723\d$/.test(ai)) return [30, false];
79
- return undefined;
66
+ if (/^31[0-6]\d$/.test(ai) || /^32[0-7]\d$/.test(ai) ||
67
+ /^33[0-7]\d$/.test(ai) || /^34[0-9]\d$/.test(ai) ||
68
+ /^35[0-7]\d$/.test(ai) || /^36[0-9]\d$/.test(ai))
69
+ return [6, true];
70
+ if (/^390\d$/.test(ai) || /^392\d$/.test(ai))
71
+ return [15, false];
72
+ if (/^391\d$/.test(ai) || /^393\d$/.test(ai))
73
+ return [18, false];
74
+ if (/^394\d$/.test(ai))
75
+ return [4, true];
76
+ if (/^395\d$/.test(ai))
77
+ return [6, true];
78
+ if (/^703\d$/.test(ai) || /^723\d$/.test(ai))
79
+ return [30, false];
80
+ return undefined;
80
81
  }
81
-
82
82
  export function gs1AIInfo(ai) {
83
- if (typeof ai !== 'string' || !/^\d{2,4}$/.test(ai)) return undefined;
84
- const spec = EXACT.get(ai) || rangedAI(ai);
85
- if (!spec) return undefined;
86
- return { ai, length: spec[0], fixed: spec[1] };
83
+ if (typeof ai !== 'string' || !/^\d{2,4}$/.test(ai))
84
+ return undefined;
85
+ const spec = EXACT.get(ai) || rangedAI(ai);
86
+ if (!spec)
87
+ return undefined;
88
+ return { ai, length: spec[0], fixed: spec[1] };
87
89
  }
88
-
89
90
  function assertCharacters(value, label, ErrorType) {
90
- if (/[^\x20-\x7e]/.test(value)) {
91
- throw new ErrorType(`GS1: ${label} contains a character outside the GS1 element-string character set`);
92
- }
91
+ if (/[^\x20-\x7e]/.test(value)) {
92
+ throw new ErrorType(`GS1: ${label} contains a character outside the GS1 element-string character set`);
93
+ }
93
94
  }
94
-
95
95
  function validateElement(ai, value, ErrorType) {
96
- const info = gs1AIInfo(ai);
97
- if (!info) throw new ErrorType(`GS1: unsupported or invalid Application Identifier ${ai}`);
98
- if (value.length === 0) throw new ErrorType(`GS1: AI ${ai} must not be empty`);
99
- if (info.fixed ? value.length !== info.length : value.length > info.length) {
100
- const expectation = info.fixed ? `exactly ${info.length}` : `at most ${info.length}`;
101
- throw new ErrorType(`GS1: AI ${ai} requires ${expectation} characters`);
102
- }
103
- assertCharacters(value, `AI ${ai}`, ErrorType);
104
- return { ai, value, fixed: info.fixed };
96
+ const info = gs1AIInfo(ai);
97
+ if (!info)
98
+ throw new ErrorType(`GS1: unsupported or invalid Application Identifier ${ai}`);
99
+ if (value.length === 0)
100
+ throw new ErrorType(`GS1: AI ${ai} must not be empty`);
101
+ if (info.fixed ? value.length !== info.length : value.length > info.length) {
102
+ const expectation = info.fixed ? `exactly ${info.length}` : `at most ${info.length}`;
103
+ throw new ErrorType(`GS1: AI ${ai} requires ${expectation} characters`);
104
+ }
105
+ assertCharacters(value, `AI ${ai}`, ErrorType);
106
+ return { ai, value, fixed: info.fixed };
105
107
  }
106
-
107
108
  export function parseGS1ElementString(input) {
108
- if (typeof input !== 'string' || input.length === 0) {
109
- throw new EncodeError('GS1: element string must be a non-empty string');
110
- }
111
- const elements = [];
112
- let offset = 0;
113
- while (offset < input.length) {
114
- const match = /^\((\d{2,4})\)/.exec(input.slice(offset));
115
- if (!match) throw new EncodeError(`GS1: expected an Application Identifier at offset ${offset}`);
116
- const ai = match[1];
117
- offset += match[0].length;
118
- const next = input.indexOf('(', offset);
119
- const end = next < 0 ? input.length : next;
120
- elements.push(validateElement(ai, input.slice(offset, end), EncodeError));
121
- offset = end;
122
- }
123
- return elements;
109
+ if (typeof input !== 'string' || input.length === 0) {
110
+ throw new EncodeError('GS1: element string must be a non-empty string');
111
+ }
112
+ const elements = [];
113
+ let offset = 0;
114
+ while (offset < input.length) {
115
+ const match = /^\((\d{2,4})\)/.exec(input.slice(offset));
116
+ if (!match)
117
+ throw new EncodeError(`GS1: expected an Application Identifier at offset ${offset}`);
118
+ const ai = match[1];
119
+ offset += match[0].length;
120
+ const next = input.indexOf('(', offset);
121
+ const end = next < 0 ? input.length : next;
122
+ elements.push(validateElement(ai, input.slice(offset, end), EncodeError));
123
+ offset = end;
124
+ }
125
+ return elements;
124
126
  }
125
-
126
127
  export function encodeGS1ElementString(input) {
127
- const elements = Array.isArray(input)
128
- ? input.map(({ ai, value }) => validateElement(String(ai), String(value), EncodeError))
129
- : parseGS1ElementString(input);
130
- return elements.map((element, index) =>
131
- `${element.ai}${element.value}${!element.fixed && index + 1 < elements.length ? GS1_SEPARATOR : ''}`
132
- ).join('');
128
+ const elements = Array.isArray(input)
129
+ ? input.map(({ ai, value }) => validateElement(String(ai), String(value), EncodeError))
130
+ : parseGS1ElementString(input);
131
+ return elements.map((element, index) => `${element.ai}${element.value}${!element.fixed && index + 1 < elements.length ? GS1_SEPARATOR : ''}`).join('');
133
132
  }
134
-
135
133
  function matchAIAt(data, offset) {
136
- for (const length of [4, 3, 2]) {
137
- const ai = data.slice(offset, offset + length);
138
- if (gs1AIInfo(ai)) return ai;
139
- }
140
- return undefined;
134
+ for (const length of [4, 3, 2]) {
135
+ const ai = data.slice(offset, offset + length);
136
+ if (gs1AIInfo(ai))
137
+ return ai;
138
+ }
139
+ return undefined;
141
140
  }
142
-
143
141
  export function decodeGS1ElementString(data) {
144
- if (typeof data !== 'string' || data.length === 0) {
145
- throw new FormatError('GS1: encoded data must be a non-empty string');
146
- }
147
- const elements = [];
148
- let offset = 0;
149
- while (offset < data.length) {
150
- if (data[offset] === GS1_SEPARATOR) {
151
- throw new FormatError(`GS1: unexpected separator at offset ${offset}`);
142
+ if (typeof data !== 'string' || data.length === 0) {
143
+ throw new FormatError('GS1: encoded data must be a non-empty string');
152
144
  }
153
- const ai = matchAIAt(data, offset);
154
- if (!ai) throw new FormatError(`GS1: unknown Application Identifier at offset ${offset}`);
155
- offset += ai.length;
156
- const info = gs1AIInfo(ai);
157
- let value;
158
- if (info.fixed) {
159
- value = data.slice(offset, offset + info.length);
160
- if (value.length !== info.length || value.includes(GS1_SEPARATOR)) {
161
- throw new FormatError(`GS1: truncated fixed-length AI ${ai}`);
162
- }
163
- offset += info.length;
164
- } else {
165
- const separator = data.indexOf(GS1_SEPARATOR, offset);
166
- const end = separator < 0 ? data.length : separator;
167
- value = data.slice(offset, end);
168
- offset = separator < 0 ? data.length : separator + 1;
145
+ const elements = [];
146
+ let offset = 0;
147
+ while (offset < data.length) {
148
+ if (data[offset] === GS1_SEPARATOR) {
149
+ throw new FormatError(`GS1: unexpected separator at offset ${offset}`);
150
+ }
151
+ const ai = matchAIAt(data, offset);
152
+ if (!ai)
153
+ throw new FormatError(`GS1: unknown Application Identifier at offset ${offset}`);
154
+ offset += ai.length;
155
+ const info = gs1AIInfo(ai);
156
+ let value;
157
+ if (info.fixed) {
158
+ value = data.slice(offset, offset + info.length);
159
+ if (value.length !== info.length || value.includes(GS1_SEPARATOR)) {
160
+ throw new FormatError(`GS1: truncated fixed-length AI ${ai}`);
161
+ }
162
+ offset += info.length;
163
+ }
164
+ else {
165
+ const separator = data.indexOf(GS1_SEPARATOR, offset);
166
+ const end = separator < 0 ? data.length : separator;
167
+ value = data.slice(offset, end);
168
+ offset = separator < 0 ? data.length : separator + 1;
169
+ }
170
+ elements.push(validateElement(ai, value, FormatError));
169
171
  }
170
- elements.push(validateElement(ai, value, FormatError));
171
- }
172
- return elements;
172
+ return elements;
173
173
  }
174
-
175
174
  export function formatGS1Elements(elements) {
176
- return elements.map(({ ai, value }) => `(${ai})${value}`).join('');
175
+ return elements.map(({ ai, value }) => `(${ai})${value}`).join('');
177
176
  }
@@ -27,42 +27,10 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  /** Verified GS1 DataBar data-layer primitives. @module databar */
32
-
33
- export {
34
- dataBarGtinTransmission,
35
- decodeDataBar14GTIN,
36
- decodeDataBarLimitedGTIN,
37
- encodeDataBar14GTIN,
38
- encodeDataBarLimitedGTIN,
39
- gtinCheckDigit,
40
- makeGTIN14,
41
- normalizeGTIN,
42
- } from './codec.js';
43
-
44
- export {
45
- GS1_SEPARATOR,
46
- decodeGS1ElementString,
47
- encodeGS1ElementString,
48
- formatGS1Elements,
49
- gs1AIInfo,
50
- parseGS1ElementString,
51
- } from './gs1.js';
52
-
53
- export {
54
- DATABAR14_VARIANTS,
55
- DATABAR_LIMITED_VARIANT,
56
- dataBar14GroupFor,
57
- validateDataBarTables,
58
- } from './tables.js';
59
-
31
+ export { dataBarGtinTransmission, decodeDataBar14GTIN, decodeDataBarLimitedGTIN, encodeDataBar14GTIN, encodeDataBarLimitedGTIN, gtinCheckDigit, makeGTIN14, normalizeGTIN, } from './codec.js';
32
+ export { GS1_SEPARATOR, decodeGS1ElementString, encodeGS1ElementString, formatGS1Elements, gs1AIInfo, parseGS1ElementString, } from './gs1.js';
33
+ export { DATABAR14_VARIANTS, DATABAR_LIMITED_VARIANT, dataBar14GroupFor, validateDataBarTables, } from './tables.js';
60
34
  export { encodeDataBar14 } from './encoder.js';
61
35
  export { decodeDataBar14, decodeDataBar14Scanline } from './decoder.js';
62
- export {
63
- DATABAR14_CHECKSUM_WEIGHTS,
64
- DATABAR14_FINDERS,
65
- dataBar14CharacterWidths,
66
- dataBar14ValueForWidths,
67
- dataBarWidths,
68
- } from './patterns.js';
36
+ export { DATABAR14_CHECKSUM_WEIGHTS, DATABAR14_FINDERS, dataBar14CharacterWidths, dataBar14ValueForWidths, dataBarWidths, } from './patterns.js';
@@ -27,20 +27,19 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  /** Mathematical width construction for GS1 DataBar characters. @module databar/patterns */
32
-
33
31
  import { dataBar14GroupFor } from './tables.js';
34
-
35
32
  function combinations(n, r) {
36
- if (n < r || r < 0) return 0;
37
- if (r === 0 || n === r) return 1;
38
- let result = 1;
39
- const k = Math.min(r, n - r);
40
- for (let i = 1; i <= k; i++) result = result * (n - k + i) / i;
41
- return result;
33
+ if (n < r || r < 0)
34
+ return 0;
35
+ if (r === 0 || n === r)
36
+ return 1;
37
+ let result = 1;
38
+ const k = Math.min(r, n - r);
39
+ for (let i = 1; i <= k; i++)
40
+ result = result * (n - k + i) / i;
41
+ return result;
42
42
  }
43
-
44
43
  /**
45
44
  * Unrank one constrained positive composition.
46
45
  *
@@ -49,95 +48,92 @@ function combinations(n, r) {
49
48
  * every remaining admissible suffix rather than storing third-party patterns.
50
49
  */
51
50
  export function dataBarWidths(rank, modules, elements, maximumWidth, noNarrow) {
52
- if (!Number.isInteger(rank) || rank < 0) throw new RangeError('GS1 DataBar width rank must be non-negative');
53
- const widths = new Array(elements).fill(0);
54
- let remaining = modules;
55
- let narrowMask = 0;
56
-
57
- for (let bar = 0; bar < elements - 1; bar++) {
58
- let count = 0;
59
- for (let width = 1; ; width++) {
60
- narrowMask |= width === 1 ? 1 << bar : 0;
61
- count = combinations(remaining - width - 1, elements - bar - 2);
62
-
63
- if (noNarrow && narrowMask === 0 && remaining - width - (elements - bar - 1) >= elements - bar - 1) {
64
- count -= combinations(remaining - width - (elements - bar), elements - bar - 2);
65
- }
66
-
67
- if (elements - bar - 1 > 1) {
68
- let tooWide = 0;
69
- for (let last = remaining - width - (elements - bar - 2); last > maximumWidth; last--) {
70
- tooWide += combinations(remaining - width - last - 1, elements - bar - 3);
51
+ if (!Number.isInteger(rank) || rank < 0)
52
+ throw new RangeError('GS1 DataBar width rank must be non-negative');
53
+ const widths = new Array(elements).fill(0);
54
+ let remaining = modules;
55
+ let narrowMask = 0;
56
+ for (let bar = 0; bar < elements - 1; bar++) {
57
+ let count = 0;
58
+ for (let width = 1;; width++) {
59
+ narrowMask |= width === 1 ? 1 << bar : 0;
60
+ count = combinations(remaining - width - 1, elements - bar - 2);
61
+ if (noNarrow && narrowMask === 0 && remaining - width - (elements - bar - 1) >= elements - bar - 1) {
62
+ count -= combinations(remaining - width - (elements - bar), elements - bar - 2);
63
+ }
64
+ if (elements - bar - 1 > 1) {
65
+ let tooWide = 0;
66
+ for (let last = remaining - width - (elements - bar - 2); last > maximumWidth; last--) {
67
+ tooWide += combinations(remaining - width - last - 1, elements - bar - 3);
68
+ }
69
+ count -= tooWide * (elements - 1 - bar);
70
+ }
71
+ else if (remaining - width > maximumWidth) {
72
+ count--;
73
+ }
74
+ if (rank < count) {
75
+ widths[bar] = width;
76
+ remaining -= width;
77
+ break;
78
+ }
79
+ rank -= count;
80
+ narrowMask &= ~(1 << bar);
71
81
  }
72
- count -= tooWide * (elements - 1 - bar);
73
- } else if (remaining - width > maximumWidth) {
74
- count--;
75
- }
76
-
77
- if (rank < count) {
78
- widths[bar] = width;
79
- remaining -= width;
80
- break;
81
- }
82
- rank -= count;
83
- narrowMask &= ~(1 << bar);
84
82
  }
85
- }
86
- widths[elements - 1] = remaining;
87
- if (rank !== 0 || widths.some((width) => width < 1 || width > maximumWidth)) {
88
- throw new RangeError('GS1 DataBar width rank exceeds its character group');
89
- }
90
- return widths;
83
+ widths[elements - 1] = remaining;
84
+ if (rank !== 0 || widths.some((width) => width < 1 || width > maximumWidth)) {
85
+ throw new RangeError('GS1 DataBar width rank exceeds its character group');
86
+ }
87
+ return widths;
91
88
  }
92
-
93
89
  /** Convert one DataBar-14 character value into its eight alternating widths. */
94
90
  export function dataBar14CharacterWidths(value, kind) {
95
- const group = dataBar14GroupFor(value, kind);
96
- const offset = value - group.gsum;
97
- const outside = kind === 'outside';
98
- const oddRank = outside ? Math.floor(offset / group.evenTotal) : offset % group.oddTotal;
99
- const evenRank = outside ? offset % group.evenTotal : Math.floor(offset / group.oddTotal);
100
- const odd = dataBarWidths(oddRank, group.oddModules, 4, group.oddWidest, !outside);
101
- const even = dataBarWidths(evenRank, group.evenModules, 4, group.evenWidest, outside);
102
- const result = [];
103
- for (let i = 0; i < 4; i++) result.push(odd[i], even[i]);
104
- return result;
91
+ const group = dataBar14GroupFor(value, kind);
92
+ const offset = value - group.gsum;
93
+ const outside = kind === 'outside';
94
+ const oddRank = outside ? Math.floor(offset / group.evenTotal) : offset % group.oddTotal;
95
+ const evenRank = outside ? offset % group.evenTotal : Math.floor(offset / group.oddTotal);
96
+ const odd = dataBarWidths(oddRank, group.oddModules, 4, group.oddWidest, !outside);
97
+ const even = dataBarWidths(evenRank, group.evenModules, 4, group.evenWidest, outside);
98
+ const result = [];
99
+ for (let i = 0; i < 4; i++)
100
+ result.push(odd[i], even[i]);
101
+ return result;
105
102
  }
106
-
107
103
  const inverseCharacterMaps = new Map();
108
-
109
104
  /** Recover a character value from its canonical eight-width representation. */
110
105
  export function dataBar14ValueForWidths(widths, kind) {
111
- if (!Array.isArray(widths) || widths.length !== 8 || widths.some((width) => !Number.isInteger(width) || width < 1)) {
112
- throw new TypeError('GS1 DataBar character widths must contain eight positive integers');
113
- }
114
- if (kind !== 'outside' && kind !== 'inside') throw new RangeError(`Unknown GS1 DataBar character kind "${kind}"`);
115
- let inverse = inverseCharacterMaps.get(kind);
116
- if (!inverse) {
117
- inverse = new Map();
118
- const maximum = kind === 'outside' ? 2840 : 1596;
119
- for (let value = 0; value <= maximum; value++) {
120
- inverse.set(dataBar14CharacterWidths(value, kind).join(','), value);
106
+ if (!Array.isArray(widths) || widths.length !== 8 || widths.some((width) => !Number.isInteger(width) || width < 1)) {
107
+ throw new TypeError('GS1 DataBar character widths must contain eight positive integers');
108
+ }
109
+ if (kind !== 'outside' && kind !== 'inside')
110
+ throw new RangeError(`Unknown GS1 DataBar character kind "${kind}"`);
111
+ let inverse = inverseCharacterMaps.get(kind);
112
+ if (!inverse) {
113
+ inverse = new Map();
114
+ const maximum = kind === 'outside' ? 2840 : 1596;
115
+ for (let value = 0; value <= maximum; value++) {
116
+ inverse.set(dataBar14CharacterWidths(value, kind).join(','), value);
117
+ }
118
+ inverseCharacterMaps.set(kind, inverse);
121
119
  }
122
- inverseCharacterMaps.set(kind, inverse);
123
- }
124
- const value = inverse.get(widths.join(','));
125
- if (value === undefined) throw new RangeError(`Invalid GS1 DataBar ${kind} character widths`);
126
- return value;
120
+ const value = inverse.get(widths.join(','));
121
+ if (value === undefined)
122
+ throw new RangeError(`Invalid GS1 DataBar ${kind} character widths`);
123
+ return value;
127
124
  }
128
-
129
125
  /** Nine finder patterns, expressed as normative five-element widths. */
130
126
  export const DATABAR14_FINDERS = Object.freeze([
131
- Object.freeze([3, 8, 2, 1, 1]), Object.freeze([3, 5, 5, 1, 1]),
132
- Object.freeze([3, 3, 7, 1, 1]), Object.freeze([3, 1, 9, 1, 1]),
133
- Object.freeze([2, 7, 4, 1, 1]), Object.freeze([2, 5, 6, 1, 1]),
134
- Object.freeze([2, 3, 8, 1, 1]), Object.freeze([1, 5, 7, 1, 1]),
135
- Object.freeze([1, 3, 9, 1, 1]),
127
+ Object.freeze([3, 8, 2, 1, 1]), Object.freeze([3, 5, 5, 1, 1]),
128
+ Object.freeze([3, 3, 7, 1, 1]), Object.freeze([3, 1, 9, 1, 1]),
129
+ Object.freeze([2, 7, 4, 1, 1]), Object.freeze([2, 5, 6, 1, 1]),
130
+ Object.freeze([2, 3, 8, 1, 1]), Object.freeze([1, 5, 7, 1, 1]),
131
+ Object.freeze([1, 3, 9, 1, 1]),
136
132
  ]);
137
-
138
133
  /** Weight sequence generated as powers of three modulo 79. */
139
134
  export const DATABAR14_CHECKSUM_WEIGHTS = Object.freeze(Array.from({ length: 32 }, (_, index) => {
140
- let value = 1;
141
- for (let i = 0; i < index; i++) value = (value * 3) % 79;
142
- return value;
135
+ let value = 1;
136
+ for (let i = 0; i < index; i++)
137
+ value = (value * 3) % 79;
138
+ return value;
143
139
  }));