label-printer 0.2.6 → 0.3.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.
package/dist/index.js CHANGED
@@ -1,10 +1,27 @@
1
1
  "use strict";
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
9
  var __getProtoOf = Object.getPrototypeOf;
7
10
  var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
+ var __spreadValues = (a, b) => {
14
+ for (var prop in b || (b = {}))
15
+ if (__hasOwnProp.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ if (__getOwnPropSymbols)
18
+ for (var prop of __getOwnPropSymbols(b)) {
19
+ if (__propIsEnum.call(b, prop))
20
+ __defNormalProp(a, prop, b[prop]);
21
+ }
22
+ return a;
23
+ };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
8
25
  var __export = (target, all) => {
9
26
  for (var name in all)
10
27
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -51,6 +68,7 @@ var __async = (__this, __arguments, generator) => {
51
68
  var src_exports = {};
52
69
  __export(src_exports, {
53
70
  commands: () => commands_exports,
71
+ labels: () => labels_exports,
54
72
  printers: () => printers_exports
55
73
  });
56
74
  module.exports = __toCommonJS(src_exports);
@@ -65,6 +83,9 @@ __export(commands_exports, {
65
83
 
66
84
  // src/commands/Command.ts
67
85
  var Command = class {
86
+ print(fn) {
87
+ fn(this.commandString);
88
+ }
68
89
  /**
69
90
  * Write the command data to a USB device
70
91
  * @param device Device to write to
@@ -118,6 +139,11 @@ var CommandGroup = class extends Command {
118
139
  super();
119
140
  this.commands = commands;
120
141
  }
142
+ print(fn) {
143
+ for (let commandIndex in this.commands) {
144
+ this.commands[commandIndex].print(fn);
145
+ }
146
+ }
121
147
  write(device) {
122
148
  return __async(this, null, function* () {
123
149
  for (let commandIndex in this.commands) {
@@ -139,7 +165,10 @@ __export(tspl_exports, {
139
165
  TSPLCLSCommand: () => TSPLCLSCommand,
140
166
  TSPLCommand: () => TSPLCommand,
141
167
  TSPLCommandGroup: () => TSPLCommandGroup,
168
+ TSPLDiagonal: () => TSPLDiagonal,
142
169
  TSPLDirectionCommand: () => TSPLDirectionCommand,
170
+ TSPLDisplay: () => TSPLDisplay,
171
+ TSPLDownload: () => TSPLDownload,
143
172
  TSPLGapCommand: () => TSPLGapCommand,
144
173
  TSPLPrintCommand: () => TSPLPrintCommand,
145
174
  TSPLQRCommand: () => TSPLQRCommand,
@@ -147,7 +176,8 @@ __export(tspl_exports, {
147
176
  TSPLSizeCommand: () => TSPLSizeCommand,
148
177
  TSPLTextCommand: () => TSPLTextCommand,
149
178
  TSPLVisualCommand: () => TSPLVisualCommand,
150
- alignmentToNumber: () => alignmentToNumber
179
+ alignmentToNumber: () => alignmentToNumber,
180
+ commandGenerator: () => TSPLCommandGenerator_default
151
181
  });
152
182
 
153
183
  // src/commands/tspl/TSPLCommand.ts
@@ -184,6 +214,44 @@ var TSPLVisualCommand = class extends TSPLCommand {
184
214
 
185
215
  // src/helpers/ImageUtils.ts
186
216
  var import_image_pixels = __toESM(require("image-pixels"));
217
+
218
+ // src/helpers/UnitUtils.ts
219
+ var pointsPerInch = 72;
220
+ function getSizePreserveAspect(width, height, desiredWidth, desiredHeight) {
221
+ if (desiredHeight && desiredWidth) {
222
+ return { width: desiredWidth, height: desiredHeight };
223
+ }
224
+ if (desiredHeight) {
225
+ const scaleFactor = desiredHeight / height;
226
+ return { width: width * scaleFactor, height: desiredHeight };
227
+ } else if (desiredWidth) {
228
+ const scaleFactor = desiredWidth / width;
229
+ return { width: desiredWidth, height: height * scaleFactor };
230
+ } else {
231
+ return { width, height };
232
+ }
233
+ }
234
+ function valueWithUnit(value, unitSystem) {
235
+ switch (unitSystem) {
236
+ case "dot":
237
+ return `${value} dot`;
238
+ case "imperial":
239
+ return value;
240
+ case "metric":
241
+ return `${value} mm`;
242
+ }
243
+ }
244
+ function dotToPoint(dots, dpi) {
245
+ const inch = dots / dpi;
246
+ return Math.round(inch * pointsPerInch);
247
+ }
248
+ function pointsToDots(points, dpi) {
249
+ const pointsPerInch2 = 72;
250
+ const dots = points * dpi / pointsPerInch2;
251
+ return dots;
252
+ }
253
+
254
+ // src/helpers/ImageUtils.ts
187
255
  var BLACK_PIXEL = 0;
188
256
  var WHITE_PIXEL = 1;
189
257
  var ImageUtils = class {
@@ -222,8 +290,9 @@ var ImageUtils = class {
222
290
  height,
223
291
  bitsPerPixel
224
292
  } = yield this.getPixels(image);
225
- const dWidth = destinationWidth != null ? destinationWidth : width;
226
- const dHeight = destinationHeight != null ? destinationHeight : height;
293
+ const dim = getSizePreserveAspect(width, height, destinationWidth, destinationHeight);
294
+ const dWidth = dim.width;
295
+ const dHeight = dim.height;
227
296
  const differenceToDividable = dWidth % 8 == 0 ? 0 : 8 - dWidth % 8;
228
297
  const dividableDWidth = dWidth + differenceToDividable;
229
298
  const bitmapData = new Uint8Array(dividableDWidth * dHeight);
@@ -390,17 +459,7 @@ var TSPLGapCommand = class extends TSPLCommand {
390
459
  this.unitSystem = unitSystem;
391
460
  }
392
461
  get commandString() {
393
- return `GAP ${this.valueWithUnit(this.gap)}, ${this.valueWithUnit(this.offset)}`;
394
- }
395
- valueWithUnit(value) {
396
- switch (this.unitSystem) {
397
- case "dot":
398
- return `${value} dot`;
399
- case "imperial":
400
- return value;
401
- case "metric":
402
- return `${value} mm`;
403
- }
462
+ return `GAP ${valueWithUnit(this.gap, this.unitSystem)}, ${valueWithUnit(this.offset, this.unitSystem)}`;
404
463
  }
405
464
  };
406
465
 
@@ -413,17 +472,7 @@ var TSPLSizeCommand = class extends TSPLCommand {
413
472
  this.unitSystem = unitSystem;
414
473
  }
415
474
  get commandString() {
416
- return `SIZE ${this.valueWithUnit(this.width)}, ${this.valueWithUnit(this.height)}`;
417
- }
418
- valueWithUnit(value) {
419
- switch (this.unitSystem) {
420
- case "dot":
421
- return `${value} dot`;
422
- case "imperial":
423
- return value;
424
- case "metric":
425
- return `${value} mm`;
426
- }
475
+ return `SIZE ${valueWithUnit(this.width, this.unitSystem)}, ${valueWithUnit(this.height, this.unitSystem)}`;
427
476
  }
428
477
  };
429
478
 
@@ -496,7 +545,7 @@ var TSPLQRCommand = class extends TSPLVisualCommand {
496
545
  }
497
546
  }
498
547
  get commandString() {
499
- return `QRCODE ${this.x}, ${this.y}, ${this.ecc}, ${this.cellWidth}, ${this.mode}, ${this.rotation}, ${this.model}, ${this.mask}, "${this.content}"`;
548
+ return `QRCODE ${this.x}, ${this.y}, ${this.ecc}, ${this.cellWidth}, ${this.mode}, ${this.rotation}, ${this.model}, "${this.content}"`;
500
549
  }
501
550
  };
502
551
 
@@ -513,6 +562,194 @@ var TSPLBlockCommand = class extends TSPLTextCommand {
513
562
  }
514
563
  };
515
564
 
565
+ // src/commands/tspl/commands/basic/TSPLDownload.ts
566
+ var TSPLDownload = class extends TSPLCommand {
567
+ /**
568
+ * Initialize a command with a raw body
569
+ * @param body
570
+ */
571
+ constructor(fileName, data) {
572
+ super();
573
+ this.fileName = fileName;
574
+ this.data = data;
575
+ }
576
+ get commandString() {
577
+ return `DOWNLOAD "${this.fileName}", ${this.data.byteLength},`;
578
+ }
579
+ write(device) {
580
+ return __async(this, null, function* () {
581
+ yield this.writeString(this.commandString, device);
582
+ yield this.writeBytes(this.data, device);
583
+ yield this.terminateCommand(device);
584
+ });
585
+ }
586
+ };
587
+
588
+ // src/commands/tspl/commands/basic/TSPLDisplay.ts
589
+ var TSPLDisplay = class extends TSPLCommand {
590
+ constructor(type) {
591
+ super();
592
+ this.type = type;
593
+ }
594
+ get commandString() {
595
+ return `DISPLAY ${this.type}`;
596
+ }
597
+ };
598
+
599
+ // src/commands/tspl/commands/basic/TSPLDiagonal.ts
600
+ var TSPLDiagonal = class extends TSPLCommand {
601
+ constructor(start, end, thickness = 3) {
602
+ super();
603
+ this.start = start;
604
+ this.end = end;
605
+ this.thickness = thickness;
606
+ }
607
+ get commandString() {
608
+ return `DIAGONAL ${this.start.x}, ${this.start.y}, ${this.end.x}, ${this.end.y}, ${this.thickness}`;
609
+ }
610
+ };
611
+
612
+ // src/commands/tspl/commands/basic/TSPLBarcodeCommand.ts
613
+ var TSPLBarcodeCommand = class _TSPLBarcodeCommand extends TSPLVisualCommand {
614
+ /**
615
+ * @param x X coordinate in dots
616
+ * @param y Y Coordinate in dots
617
+ * @param type Type of the barcode
618
+ * @param height Height of the barcode in dots
619
+ * @param narrow Width of narrow elements in dots
620
+ * @param wide Width of the wide elements in dots
621
+ * @param content Content of the barcode. Supported content depends on the barcode type
622
+ * @param rotation Rotation
623
+ * @param alignment Alignment of the barcode
624
+ */
625
+ constructor(x, y, type, height, narrow, wide, content, rotation = 0, humanReadable = "left", alignment = "left") {
626
+ super(x, y);
627
+ this.type = type;
628
+ this.height = height;
629
+ this.narrow = narrow;
630
+ this.wide = wide;
631
+ this.content = content;
632
+ this.rotation = rotation;
633
+ this.humanReadable = _TSPLBarcodeCommand.humanReadableValue(humanReadable);
634
+ this.alignment = alignmentToNumber(alignment);
635
+ }
636
+ get commandString() {
637
+ return `BARCODE ${this.x}, ${this.y}, "${this.type}", ${this.height}, ${this.humanReadable},${this.rotation}, ${this.narrow}, ${this.wide},${this.alignment}, "${this.content}"`;
638
+ }
639
+ static humanReadableValue(hr) {
640
+ switch (hr) {
641
+ case "none":
642
+ return 0;
643
+ case "left":
644
+ return 1;
645
+ case "center":
646
+ return 2;
647
+ case "right":
648
+ return 3;
649
+ }
650
+ }
651
+ };
652
+
653
+ // src/helpers/QRCodeUtils.ts
654
+ var QRLengthMapping = {
655
+ 10: 21,
656
+ 20: 25,
657
+ 35: 29,
658
+ 50: 33,
659
+ 64: 37,
660
+ 84: 41,
661
+ 93: 45,
662
+ 122: 49,
663
+ 143: 53,
664
+ 174: 57,
665
+ 200: 61,
666
+ 227: 65,
667
+ 259: 69,
668
+ 283: 73,
669
+ 321: 77,
670
+ 365: 81,
671
+ 408: 85,
672
+ 452: 89,
673
+ 493: 93,
674
+ 557: 97,
675
+ 587: 101,
676
+ 640: 105,
677
+ 672: 109,
678
+ 744: 113,
679
+ 779: 117,
680
+ 864: 121,
681
+ 910: 125,
682
+ 958: 129,
683
+ 1016: 133,
684
+ 1080: 137,
685
+ 1150: 141,
686
+ 1226: 145,
687
+ 1307: 149,
688
+ 1394: 153,
689
+ 1431: 157,
690
+ 1530: 161,
691
+ 1591: 165,
692
+ 1658: 169,
693
+ 1774: 173,
694
+ 1852: 177
695
+ };
696
+
697
+ // src/commands/tspl/TSPLCommandGenerator.ts
698
+ var TSPLCommandGenerator = class {
699
+ commandGroup(commands) {
700
+ return new TSPLCommandGroup(commands);
701
+ }
702
+ print(sets, copiesPerSet) {
703
+ return new TSPLPrintCommand(sets, copiesPerSet);
704
+ }
705
+ text(content, x, y, font, size) {
706
+ const fontName = font == "default" ? "0" : font;
707
+ return new TSPLTextCommand(content, x, y, fontName, 0, size, size, "left");
708
+ }
709
+ upload(name, data) {
710
+ return new TSPLDownload(name, data);
711
+ }
712
+ setUp(width, height, gap, offset, direction, mirror = false, unitSystem) {
713
+ const commands = [
714
+ new TSPLSizeCommand(width, height, unitSystem),
715
+ new TSPLGapCommand(gap, offset, unitSystem),
716
+ new TSPLDirectionCommand(direction, mirror),
717
+ new TSPLCLSCommand()
718
+ ];
719
+ return new TSPLCommandGroup(commands);
720
+ }
721
+ display() {
722
+ return new TSPLCommandGroup([
723
+ new TSPLDisplay("CLS"),
724
+ new TSPLDisplay("IMAGE")
725
+ ]);
726
+ }
727
+ line(start, end, thickness) {
728
+ return new TSPLDiagonal(start, end, thickness);
729
+ }
730
+ image(image, x, y, mode) {
731
+ return new TSPLBitmapCommand(image, x, y, mode);
732
+ }
733
+ qrCode(content, width, x, y) {
734
+ const cellCount = this.cellCount(content);
735
+ const cellWidth = Math.round(width / cellCount);
736
+ return new TSPLQRCommand(`A${content}`, x, y, cellWidth, "H", "M");
737
+ }
738
+ barCode(content, x, y, type, height, rotation, humanReadable, alignment) {
739
+ return new TSPLBarcodeCommand(x, y, type, height, 1, 1, content, rotation, humanReadable, alignment);
740
+ }
741
+ cellCount(content) {
742
+ const limits = Object.keys(QRLengthMapping).map((limit) => Number(limit)).sort((a, b) => a - b);
743
+ const contentLength = content.length;
744
+ let i = 0;
745
+ while (limits[i] < contentLength && i < limits.length - 1) {
746
+ i++;
747
+ }
748
+ return QRLengthMapping[limits[i]];
749
+ }
750
+ };
751
+ var TSPLCommandGenerator_default = new TSPLCommandGenerator();
752
+
516
753
  // src/printers/index.ts
517
754
  var printers_exports = {};
518
755
  __export(printers_exports, {
@@ -533,6 +770,26 @@ var Printer = class {
533
770
  yield this.usbDevice.close();
534
771
  });
535
772
  }
773
+ /**
774
+ * Prints a label
775
+ * @param label
776
+ */
777
+ print(label, sets, gap, copiesPerSet = 1, direction = "normal", mirror = false, gapOffset = 0) {
778
+ return __async(this, null, function* () {
779
+ const commands = yield label.fullPrintCommand(this.language, gap, direction, sets, copiesPerSet, mirror, gapOffset);
780
+ yield this.writeCommand(commands);
781
+ });
782
+ }
783
+ /**
784
+ * Display label on the printer's screen
785
+ * @param label
786
+ */
787
+ display(label, direction = "normal", mirror = false) {
788
+ return __async(this, null, function* () {
789
+ const command = yield label.fullDisplayCommand(this.language, direction, mirror);
790
+ yield this.writeCommand(command);
791
+ });
792
+ }
536
793
  /**
537
794
  * Writes a command to the printers usb
538
795
  * @param command Command to send to the usb
@@ -573,6 +830,7 @@ var StringUtils = class {
573
830
  return decoder.decode(bytes);
574
831
  }
575
832
  };
833
+ var isWhitespace = (text) => text.trim() === "";
576
834
 
577
835
  // src/helpers/USBUtils.ts
578
836
  var unsupportedUsbError = "usb-unsupported";
@@ -772,9 +1030,592 @@ var PrinterService = class _PrinterService {
772
1030
  });
773
1031
  }
774
1032
  };
1033
+
1034
+ // src/labels/index.ts
1035
+ var labels_exports = {};
1036
+ __export(labels_exports, {
1037
+ BarCode: () => BarCode,
1038
+ Image: () => Image,
1039
+ Label: () => Label,
1040
+ Line: () => Line,
1041
+ Text: () => Text,
1042
+ qrCode: () => QRCode
1043
+ });
1044
+
1045
+ // src/labels/Printable.ts
1046
+ var Printable = class {
1047
+ /**
1048
+ * Generates printable command for the given printer. Can be used to obtain a command for fields supported by the package then customizing it before printing
1049
+ * @param printer Printer to generate the command. Important because the command is printer language specific
1050
+ * @returns A promise for a command. Most commands are syncronouse but some may require to access async resources
1051
+ */
1052
+ commandForPrinter(printer, config) {
1053
+ return __async(this, null, function* () {
1054
+ return yield this.commandForLanguage(printer.language, config);
1055
+ });
1056
+ }
1057
+ /**
1058
+ * Obtain a command generator for the given language
1059
+ * @param language Language to get generator for
1060
+ */
1061
+ commandGeneratorFor(language) {
1062
+ switch (language) {
1063
+ case "tspl":
1064
+ return tspl_exports.commandGenerator;
1065
+ }
1066
+ }
1067
+ };
1068
+
1069
+ // src/labels/Label.ts
1070
+ var import_fontkit = __toESM(require("fontkit"));
1071
+ var DEFAULT_FONT_WEIGHT = 400;
1072
+ var DEFAULT_FONT_STYLE = "normal";
1073
+ var FONT_PREFIX = "f";
1074
+ var Label = class extends Printable {
1075
+ constructor(width, height, dimensionUnit = "metric", dpi = 203) {
1076
+ super();
1077
+ this.fonts = {};
1078
+ /**
1079
+ * List of fields on the label
1080
+ */
1081
+ this.fields = [];
1082
+ this.fontCounter = 0;
1083
+ this.width = width;
1084
+ this.height = height;
1085
+ this.unitSystem = dimensionUnit;
1086
+ this.dpi = dpi;
1087
+ }
1088
+ /**
1089
+ * Configuration used when generating commands
1090
+ */
1091
+ get printConfig() {
1092
+ return {
1093
+ dpi: this.dpi,
1094
+ textWidth: (text, font) => {
1095
+ const size = dotToPoint(font.size, this.dpi);
1096
+ const fontObject = this.getIndexedFont(font).font;
1097
+ const run = fontObject.layout(text);
1098
+ const scaledWidth = size * run.advanceWidth / fontObject.unitsPerEm;
1099
+ return pointsToDots(scaledWidth, this.dpi);
1100
+ },
1101
+ getFontName: this.getFontName.bind(this)
1102
+ };
1103
+ }
1104
+ commandForLanguage(language, config) {
1105
+ return __async(this, null, function* () {
1106
+ const commandList = yield Promise.all(this.fields.map((field) => field.commandForLanguage(language, config)));
1107
+ return this.commandGeneratorFor(language).commandGroup(commandList);
1108
+ });
1109
+ }
1110
+ /**
1111
+ * Place fields to a label
1112
+ * @param fields
1113
+ */
1114
+ add(...fields) {
1115
+ this.fields.push(...fields);
1116
+ }
1117
+ /**
1118
+ * Register a font to be used. Use the name provided in components to use the font.
1119
+ * For example: textField.setFont('myFont.ttf', 12)
1120
+ * @param file Font file. Can be a blob or a url
1121
+ * @param name Name to be used to reference the font
1122
+ */
1123
+ registerFont(font) {
1124
+ return __async(this, null, function* () {
1125
+ const key = this.fontKey(font.weight, font.style);
1126
+ if (!this.fonts[font.name]) {
1127
+ this.fonts[font.name] = {
1128
+ fonts: {}
1129
+ };
1130
+ }
1131
+ const fontBuffer = Buffer.from(font.data);
1132
+ this.fonts[font.name].fonts[key] = __spreadProps(__spreadValues({}, font), {
1133
+ font: import_fontkit.default.create(fontBuffer),
1134
+ alias: `${FONT_PREFIX}${this.fontCounter}.${this.fontExtension}`
1135
+ });
1136
+ this.fontCounter += 1;
1137
+ });
1138
+ }
1139
+ /**
1140
+ * Generate a command that is complete for printing
1141
+ * @param language Printing language to use
1142
+ * @param gap Distance between two labels. It is measured between the two points where the sensor
1143
+ * leaves the label and enters the next one
1144
+ * @param direction Direction relative to printing direction. See documentation for more details
1145
+ * @param sets Number of sets to print. If you have counters for example, it will not change in a set
1146
+ * @param copiesPerSet Number of labels per set
1147
+ * @param mirror Mirror the label along the vertical axis
1148
+ * @param gapOffset Used with non uniform shaped labels. Is the distance between the point where the sensor leaves the label and the
1149
+ * furthest point of the label in the direction of printing. Check documentation for more info
1150
+ * TODO: Is this too TSPL Specific?
1151
+ */
1152
+ fullPrintCommand(language, gap, direction, sets, copiesPerSet = 1, mirror = false, gapOffset = 0) {
1153
+ return __async(this, null, function* () {
1154
+ const generator = this.commandGeneratorFor(language);
1155
+ const commands = yield this.fullCommand(language, gap, direction, mirror, gapOffset, generator);
1156
+ commands.push(generator.print(sets, copiesPerSet));
1157
+ return generator.commandGroup(commands);
1158
+ });
1159
+ }
1160
+ /**
1161
+ * Generate commands needed to display the label on the printer screen
1162
+ * @param language Printing language to use
1163
+ * @param direction Direction relative to printing direction. See documentation for more details
1164
+ * @param mirror Mirror the label along the vertical axis
1165
+ */
1166
+ fullDisplayCommand(language, direction, mirror = false) {
1167
+ return __async(this, null, function* () {
1168
+ const generator = this.commandGeneratorFor(language);
1169
+ const commands = yield this.fullCommand(language, 0, direction, mirror, 0, generator);
1170
+ commands.push(generator.display());
1171
+ const group = generator.commandGroup(commands);
1172
+ group.print(console.log);
1173
+ return group;
1174
+ });
1175
+ }
1176
+ /**
1177
+ * Helper function that generates common commands for print and display
1178
+ */
1179
+ fullCommand(language, gap, direction, mirror = false, gapOffset = 0, generator) {
1180
+ return __async(this, null, function* () {
1181
+ const commands = [
1182
+ this.fontUploadCommands(generator),
1183
+ generator.setUp(this.width, this.height, gap, gapOffset, direction, mirror, this.unitSystem),
1184
+ yield this.commandForLanguage(language, this.printConfig)
1185
+ ];
1186
+ return commands;
1187
+ });
1188
+ }
1189
+ fontUploadCommands(generator) {
1190
+ const families = Object.keys(this.fonts);
1191
+ const commands = families.flatMap((family) => {
1192
+ const familyFonts = this.fonts[family].fonts;
1193
+ const fontNames = Object.keys(familyFonts);
1194
+ return fontNames.map((name) => {
1195
+ const font = familyFonts[name];
1196
+ const fileName = font.alias;
1197
+ return generator.upload(fileName, font.data);
1198
+ });
1199
+ });
1200
+ return generator.commandGroup(commands);
1201
+ }
1202
+ getIndexedFont(font) {
1203
+ var _a, _b;
1204
+ const family = this.fonts[font.name];
1205
+ const style = (_a = font.style) != null ? _a : DEFAULT_FONT_STYLE;
1206
+ const weigth = (_b = font.weight) != null ? _b : DEFAULT_FONT_WEIGHT;
1207
+ const fontKeys = Object.keys(family.fonts);
1208
+ const exactMatch = fontKeys.find(
1209
+ (key) => family.fonts[key].style == style && family.fonts[key].weight == weigth
1210
+ );
1211
+ if (exactMatch) {
1212
+ return family.fonts[exactMatch];
1213
+ } else {
1214
+ const sameStyleKeys = fontKeys.filter((key) => family.fonts[key].style == style);
1215
+ if (sameStyleKeys.length > 0) {
1216
+ let weigthDiff = 99999999;
1217
+ let selectedKey = "";
1218
+ sameStyleKeys.forEach((key) => {
1219
+ const diff = Math.abs(weigth - family.fonts[key].weight);
1220
+ if (diff < weigthDiff) {
1221
+ weigthDiff = diff;
1222
+ selectedKey = key;
1223
+ }
1224
+ });
1225
+ return family.fonts[selectedKey];
1226
+ } else {
1227
+ return family.fonts[fontKeys[0]];
1228
+ }
1229
+ }
1230
+ }
1231
+ getFontName(font) {
1232
+ const indexedFont = this.getIndexedFont(font);
1233
+ return indexedFont.alias;
1234
+ }
1235
+ /// This can be extended when we want support multiple fonts
1236
+ get fontExtension() {
1237
+ return "TTF";
1238
+ }
1239
+ fontKey(weight, style) {
1240
+ return `${weight}${style != null ? style : DEFAULT_FONT_STYLE}`;
1241
+ }
1242
+ };
1243
+
1244
+ // src/labels/fields/LabelField.ts
1245
+ var LabelField = class extends Printable {
1246
+ };
1247
+
1248
+ // src/labels/fields/Line.ts
1249
+ var Line = class extends LabelField {
1250
+ /**
1251
+ *
1252
+ * @param start Start point of the line. Values are in dots
1253
+ * @param end End point of the line. Values are in dots
1254
+ * @param thickness Thickness of the line in dots
1255
+ */
1256
+ constructor(start, end, thickness = 3) {
1257
+ super();
1258
+ this.start = start;
1259
+ this.end = end;
1260
+ this.thickness = thickness;
1261
+ }
1262
+ commandForLanguage(language) {
1263
+ return this.commandGeneratorFor(language).line(this.start, this.end, this.thickness);
1264
+ }
1265
+ };
1266
+
1267
+ // src/labels/fields/Text.ts
1268
+ var import_node_html_parser = require("node-html-parser");
1269
+ var BOLD_WEIGTH = 700;
1270
+ var BOLD_TAG = "b";
1271
+ var ITALIC_TAG = "i";
1272
+ var UNDERLINE_TAG = "u";
1273
+ var STRIKE_TAG = "s";
1274
+ var Text = class extends LabelField {
1275
+ constructor(content, x, y, formatted = true) {
1276
+ super();
1277
+ this.font = { name: "default", size: 10 };
1278
+ this.type = "singleline";
1279
+ this.context = void 0;
1280
+ this.lineSpacing = 1;
1281
+ this.content = content.replace("\n", "");
1282
+ this.x = x;
1283
+ this.y = y;
1284
+ this.formatted = formatted;
1285
+ }
1286
+ /**
1287
+ * Sets the field to single line
1288
+ * @param width Max width of the text. Leave it undefined to allow the field to grow
1289
+ */
1290
+ setSingleLine(width) {
1291
+ this.type = "singleline";
1292
+ this.width = width;
1293
+ this.height = void 0;
1294
+ }
1295
+ /**
1296
+ * Sets the field to multi line
1297
+ * @param width Max width of text before it gets wrapped to a new line
1298
+ * @param height Max height of the text box, leave undefined to allow the text box to grow infinitly
1299
+ */
1300
+ setMultiLine(width, height) {
1301
+ this.type = "multiline";
1302
+ this.width = width;
1303
+ this.height = height;
1304
+ }
1305
+ /**
1306
+ * Set a font to use as a base. If no formatting is set on the text with a html tag, this will be used
1307
+ * Note: The font name either has to be a built in font on your printer or a font
1308
+ * that is registered on the label using 'registerFont'.
1309
+ */
1310
+ setFont(font) {
1311
+ this.font = font;
1312
+ }
1313
+ commandForLanguage(language, config) {
1314
+ return __async(this, null, function* () {
1315
+ this.context = {
1316
+ config,
1317
+ language,
1318
+ generator: this.commandGeneratorFor(language)
1319
+ };
1320
+ let command;
1321
+ if (this.formatted) {
1322
+ command = this.generateFormattedText();
1323
+ } else {
1324
+ command = this.generatePlainText();
1325
+ }
1326
+ this.context = void 0;
1327
+ return command;
1328
+ });
1329
+ }
1330
+ /**
1331
+ * Generate commands for formatted text
1332
+ * @returns
1333
+ */
1334
+ generateFormattedText() {
1335
+ if (!this.context)
1336
+ throw "context-not-set";
1337
+ const rootNode = (0, import_node_html_parser.parse)(this.content);
1338
+ const { command } = this.generateFormattedRecursive(this.x, this.y, rootNode, this.font, []);
1339
+ return command;
1340
+ }
1341
+ /**
1342
+ * Generate commands for plain text
1343
+ * @returns
1344
+ */
1345
+ generatePlainText() {
1346
+ const { command } = this.generatePlainTextCore(this.content, this.x, this.y, this.font);
1347
+ return command;
1348
+ }
1349
+ /**
1350
+ * Iterats the nodes in a html text and generates text commands for it
1351
+ */
1352
+ generateFormattedRecursive(initialX, initialY, rootNode, font, features) {
1353
+ if (rootNode.nodeType == import_node_html_parser.NodeType.TEXT_NODE) {
1354
+ const result = this.generatePlainTextCore(rootNode.innerText, initialX, initialY, font, features);
1355
+ return result;
1356
+ } else {
1357
+ const elementNode = rootNode;
1358
+ const tag = elementNode.rawTagName;
1359
+ let commands = [];
1360
+ let currentX = initialX;
1361
+ let currentY = initialY;
1362
+ let baseFont = __spreadValues({}, font);
1363
+ let baseFeatures = [...features];
1364
+ if (tag == UNDERLINE_TAG) {
1365
+ baseFeatures.push("underline");
1366
+ } else if (tag == STRIKE_TAG) {
1367
+ baseFeatures.push("strike");
1368
+ } else if (tag == BOLD_TAG) {
1369
+ baseFont.weight = BOLD_WEIGTH;
1370
+ } else if (tag == ITALIC_TAG) {
1371
+ baseFont.style = "italic";
1372
+ }
1373
+ elementNode.childNodes.forEach((node) => {
1374
+ const { x, y, command } = this.generateFormattedRecursive(currentX, currentY, node, baseFont, baseFeatures);
1375
+ currentX = x;
1376
+ currentY = y;
1377
+ commands.push(command);
1378
+ });
1379
+ return {
1380
+ x: currentX,
1381
+ y: currentY,
1382
+ command: this.context.generator.commandGroup(commands)
1383
+ };
1384
+ }
1385
+ }
1386
+ /**
1387
+ * Generate commands for plain text
1388
+ * @param config
1389
+ * @returns
1390
+ */
1391
+ generatePlainTextCore(content, initialX, initialY, font, features = []) {
1392
+ if (!this.context)
1393
+ throw "context-not-set";
1394
+ const textWidhtFunction = this.textWithFunction;
1395
+ let fullWidth = textWidhtFunction(content, font);
1396
+ if (this.width) {
1397
+ const initialPadding = initialX - this.x;
1398
+ let rowWidth = this.width - initialPadding;
1399
+ if (rowWidth <= 0) {
1400
+ rowWidth = this.width;
1401
+ initialX = this.x;
1402
+ initialY += font.size + this.lineSpacing;
1403
+ }
1404
+ if (initialX == this.x) {
1405
+ content = content.trimStart();
1406
+ fullWidth = textWidhtFunction(content, font);
1407
+ }
1408
+ if (fullWidth <= rowWidth) {
1409
+ return {
1410
+ x: initialX + fullWidth,
1411
+ y: initialY,
1412
+ command: this.textCommand(content, initialX, initialY, font, features)
1413
+ };
1414
+ } else {
1415
+ const commands = [];
1416
+ let x = initialX;
1417
+ let y = initialY;
1418
+ let remainingContent = content;
1419
+ let remainingWidth = fullWidth;
1420
+ let currentHeight = 0;
1421
+ let finalX = x;
1422
+ let finalY = y;
1423
+ do {
1424
+ if (remainingWidth < rowWidth) {
1425
+ finalX = x + remainingWidth;
1426
+ finalY = y;
1427
+ commands.push(this.textCommand(remainingContent, x, y, font, features));
1428
+ remainingContent = "";
1429
+ } else {
1430
+ let rows = remainingWidth / rowWidth;
1431
+ rowWidth = this.width;
1432
+ let rowEndIndex = Math.floor(remainingContent.length / rows);
1433
+ let originalRowEndIndex = rowEndIndex;
1434
+ if (rowEndIndex == 0) {
1435
+ x = this.x;
1436
+ y += font.size + this.lineSpacing;
1437
+ continue;
1438
+ }
1439
+ while (!(!isWhitespace(remainingContent.charAt(rowEndIndex)) && (rowEndIndex == remainingContent.length - 1 || isWhitespace(remainingContent.charAt(rowEndIndex + 1)))) && rowEndIndex > 0) {
1440
+ rowEndIndex--;
1441
+ }
1442
+ let nextRowStartIndex = rowEndIndex + 1;
1443
+ if (rowEndIndex == 0) {
1444
+ rowEndIndex = originalRowEndIndex;
1445
+ nextRowStartIndex = originalRowEndIndex + 1;
1446
+ } else {
1447
+ while (isWhitespace(remainingContent.charAt(nextRowStartIndex)) && nextRowStartIndex < remainingContent.length) {
1448
+ nextRowStartIndex++;
1449
+ }
1450
+ }
1451
+ const thisRow = remainingContent.substring(0, rowEndIndex + 1);
1452
+ commands.push(this.textCommand(thisRow, x, y, font, features));
1453
+ if (nextRowStartIndex == remainingContent.length) {
1454
+ finalX = x + remainingWidth;
1455
+ finalY = y;
1456
+ }
1457
+ x = this.x;
1458
+ y += font.size + this.lineSpacing;
1459
+ currentHeight = y - this.y;
1460
+ remainingContent = remainingContent.substring(nextRowStartIndex);
1461
+ remainingWidth = textWidhtFunction(remainingContent, font);
1462
+ }
1463
+ } while (
1464
+ // We don't have a height constraint or we are still within bounds
1465
+ // and there is still content
1466
+ // and we are supporting multiline
1467
+ (this.height == void 0 || currentHeight + font.size <= this.height) && remainingContent != "" && this.type == "multiline"
1468
+ );
1469
+ return {
1470
+ x: finalX,
1471
+ y: finalY,
1472
+ command: this.context.generator.commandGroup(commands)
1473
+ };
1474
+ }
1475
+ } else {
1476
+ return {
1477
+ x: initialX + fullWidth,
1478
+ y: initialY,
1479
+ command: this.textCommand(content, initialX, initialY, font, features)
1480
+ };
1481
+ }
1482
+ }
1483
+ textCommand(text, x, y, font, features) {
1484
+ var _a, _b;
1485
+ if (!this.context)
1486
+ throw "no-context";
1487
+ const finalFontSize = dotToPoint(font.size, (_b = (_a = this.context.config) == null ? void 0 : _a.dpi) != null ? _b : 203);
1488
+ const finalFont = this.getFontName(font);
1489
+ const finalX = Math.round(x);
1490
+ const finalY = Math.round(y);
1491
+ let commands = [];
1492
+ const textCommand = this.context.generator.text(text, finalX, finalY, finalFont, finalFontSize);
1493
+ if (features.length == 0) {
1494
+ return textCommand;
1495
+ } else {
1496
+ let lineHeight = font.size * 0.1;
1497
+ let textWidth = this.textWithFunction(text, font);
1498
+ if (features.includes("strike")) {
1499
+ commands.push(this.textLineCommand(textWidth, x, y, lineHeight, 0.5, font.size));
1500
+ }
1501
+ if (features.includes("underline")) {
1502
+ commands.push(this.textLineCommand(textWidth, x, y, lineHeight, 0.9, font.size));
1503
+ }
1504
+ commands.push(textCommand);
1505
+ }
1506
+ return this.context.generator.commandGroup(commands);
1507
+ }
1508
+ textLineCommand(width, x, y, lineHeight, linePercentage, fontSize) {
1509
+ const sy = Math.round(y + fontSize * linePercentage - lineHeight / 2);
1510
+ const sx = Math.round(x);
1511
+ return this.context.generator.line(
1512
+ { x: sx, y: sy },
1513
+ { x: sx + width, y: sy },
1514
+ lineHeight
1515
+ );
1516
+ }
1517
+ getFontName(font) {
1518
+ var _a;
1519
+ if (!this.context)
1520
+ throw "no-context";
1521
+ if (font.name == "default") {
1522
+ return "default";
1523
+ } else {
1524
+ return (_a = this.context.config) == null ? void 0 : _a.getFontName(font);
1525
+ }
1526
+ }
1527
+ get textWithFunction() {
1528
+ var _a, _b, _c;
1529
+ if (this.font.name == "default") {
1530
+ return this.defaultTextWidth;
1531
+ } else {
1532
+ return (_c = (_b = (_a = this.context) == null ? void 0 : _a.config) == null ? void 0 : _b.textWidth) != null ? _c : this.defaultTextWidth;
1533
+ }
1534
+ }
1535
+ /**
1536
+ * This function is used to calculate the font size if no
1537
+ * print config is provided. This will asume that the font has square characters
1538
+ */
1539
+ defaultTextWidth(text, font) {
1540
+ return text.length * font.size;
1541
+ }
1542
+ };
1543
+
1544
+ // src/labels/fields/BarCode.ts
1545
+ var BarCode = class extends LabelField {
1546
+ constructor(content, x, y, type, height) {
1547
+ super();
1548
+ this.content = content;
1549
+ this.x = x;
1550
+ this.y = y;
1551
+ this.type = type;
1552
+ this.height = height;
1553
+ this.rotation = 0;
1554
+ this.humanReadable = "none";
1555
+ this.alignment = "left";
1556
+ }
1557
+ setRotation(rotation) {
1558
+ this.rotation = rotation;
1559
+ }
1560
+ setHumanReadable(humanReadable) {
1561
+ this.humanReadable = humanReadable;
1562
+ }
1563
+ commandForLanguage(language, _config) {
1564
+ return __async(this, null, function* () {
1565
+ return yield this.commandGeneratorFor(language).barCode(this.content, this.x, this.y, this.type, this.height, this.rotation, this.humanReadable, this.alignment);
1566
+ });
1567
+ }
1568
+ };
1569
+
1570
+ // src/labels/fields/Image.ts
1571
+ var Image = class _Image extends LabelField {
1572
+ constructor(x, y, image) {
1573
+ super();
1574
+ this.x = x;
1575
+ this.y = y;
1576
+ this.image = image;
1577
+ }
1578
+ commandForLanguage(language, _config) {
1579
+ return __async(this, null, function* () {
1580
+ return yield this.commandGeneratorFor(language).image(this.image, this.x, this.y);
1581
+ });
1582
+ }
1583
+ /**
1584
+ * Create an image field for an image
1585
+ * @param image
1586
+ * @param x
1587
+ * @param y
1588
+ * @param width
1589
+ * @param height
1590
+ * @returns
1591
+ */
1592
+ static create(image, x, y, width, height) {
1593
+ return __async(this, null, function* () {
1594
+ const bitmap = yield ImageUtils.getBWBitmap(image, width, height);
1595
+ return new _Image(x, y, bitmap);
1596
+ });
1597
+ }
1598
+ };
1599
+
1600
+ // src/labels/fields/QRCode.ts
1601
+ var QRCode = class extends LabelField {
1602
+ constructor(content, x, y, width) {
1603
+ super();
1604
+ this.content = content;
1605
+ this.x = x;
1606
+ this.y = y;
1607
+ this.width = width;
1608
+ }
1609
+ commandForLanguage(language, config) {
1610
+ return __async(this, null, function* () {
1611
+ return yield this.commandGeneratorFor(language).qrCode(this.content, this.width, this.x, this.y);
1612
+ });
1613
+ }
1614
+ };
775
1615
  // Annotate the CommonJS export names for ESM import in node:
776
1616
  0 && (module.exports = {
777
1617
  commands,
1618
+ labels,
778
1619
  printers
779
1620
  });
780
1621
  //# sourceMappingURL=index.js.map