label-printer 0.2.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,4 +1,22 @@
1
1
  var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
2
20
  var __export = (target, all) => {
3
21
  for (var name in all)
4
22
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -24,16 +42,11 @@ var __async = (__this, __arguments, generator) => {
24
42
  });
25
43
  };
26
44
 
27
- // src/commands/index.ts
28
- var commands_exports = {};
29
- __export(commands_exports, {
30
- Command: () => Command,
31
- CommandGroup: () => CommandGroup,
32
- tspl: () => tspl_exports
33
- });
34
-
35
45
  // src/commands/Command.ts
36
46
  var Command = class {
47
+ print(fn) {
48
+ fn(this.commandString);
49
+ }
37
50
  /**
38
51
  * Write the command data to a USB device
39
52
  * @param device Device to write to
@@ -87,6 +100,11 @@ var CommandGroup = class extends Command {
87
100
  super();
88
101
  this.commands = commands;
89
102
  }
103
+ print(fn) {
104
+ for (let commandIndex in this.commands) {
105
+ this.commands[commandIndex].print(fn);
106
+ }
107
+ }
90
108
  write(device) {
91
109
  return __async(this, null, function* () {
92
110
  for (let commandIndex in this.commands) {
@@ -108,7 +126,10 @@ __export(tspl_exports, {
108
126
  TSPLCLSCommand: () => TSPLCLSCommand,
109
127
  TSPLCommand: () => TSPLCommand,
110
128
  TSPLCommandGroup: () => TSPLCommandGroup,
129
+ TSPLDiagonal: () => TSPLDiagonal,
111
130
  TSPLDirectionCommand: () => TSPLDirectionCommand,
131
+ TSPLDisplay: () => TSPLDisplay,
132
+ TSPLDownload: () => TSPLDownload,
112
133
  TSPLGapCommand: () => TSPLGapCommand,
113
134
  TSPLPrintCommand: () => TSPLPrintCommand,
114
135
  TSPLQRCommand: () => TSPLQRCommand,
@@ -116,7 +137,8 @@ __export(tspl_exports, {
116
137
  TSPLSizeCommand: () => TSPLSizeCommand,
117
138
  TSPLTextCommand: () => TSPLTextCommand,
118
139
  TSPLVisualCommand: () => TSPLVisualCommand,
119
- alignmentToNumber: () => alignmentToNumber
140
+ alignmentToNumber: () => alignmentToNumber,
141
+ commandGenerator: () => TSPLCommandGenerator_default
120
142
  });
121
143
 
122
144
  // src/commands/tspl/TSPLCommand.ts
@@ -153,6 +175,44 @@ var TSPLVisualCommand = class extends TSPLCommand {
153
175
 
154
176
  // src/helpers/ImageUtils.ts
155
177
  import pixels from "image-pixels";
178
+
179
+ // src/helpers/UnitUtils.ts
180
+ var pointsPerInch = 72;
181
+ function getSizePreserveAspect(width, height, desiredWidth, desiredHeight) {
182
+ if (desiredHeight && desiredWidth) {
183
+ return { width: desiredWidth, height: desiredHeight };
184
+ }
185
+ if (desiredHeight) {
186
+ const scaleFactor = desiredHeight / height;
187
+ return { width: width * scaleFactor, height: desiredHeight };
188
+ } else if (desiredWidth) {
189
+ const scaleFactor = desiredWidth / width;
190
+ return { width: desiredWidth, height: height * scaleFactor };
191
+ } else {
192
+ return { width, height };
193
+ }
194
+ }
195
+ function valueWithUnit(value, unitSystem) {
196
+ switch (unitSystem) {
197
+ case "dot":
198
+ return `${value} dot`;
199
+ case "imperial":
200
+ return value;
201
+ case "metric":
202
+ return `${value} mm`;
203
+ }
204
+ }
205
+ function dotToPoint(dots, dpi) {
206
+ const inch = dots / dpi;
207
+ return Math.round(inch * pointsPerInch);
208
+ }
209
+ function pointsToDots(points, dpi) {
210
+ const pointsPerInch2 = 72;
211
+ const dots = points * dpi / pointsPerInch2;
212
+ return dots;
213
+ }
214
+
215
+ // src/helpers/ImageUtils.ts
156
216
  var BLACK_PIXEL = 0;
157
217
  var WHITE_PIXEL = 1;
158
218
  var ImageUtils = class {
@@ -191,8 +251,9 @@ var ImageUtils = class {
191
251
  height,
192
252
  bitsPerPixel
193
253
  } = yield this.getPixels(image);
194
- const dWidth = destinationWidth != null ? destinationWidth : width;
195
- const dHeight = destinationHeight != null ? destinationHeight : height;
254
+ const dim = getSizePreserveAspect(width, height, destinationWidth, destinationHeight);
255
+ const dWidth = dim.width;
256
+ const dHeight = dim.height;
196
257
  const differenceToDividable = dWidth % 8 == 0 ? 0 : 8 - dWidth % 8;
197
258
  const dividableDWidth = dWidth + differenceToDividable;
198
259
  const bitmapData = new Uint8Array(dividableDWidth * dHeight);
@@ -359,17 +420,7 @@ var TSPLGapCommand = class extends TSPLCommand {
359
420
  this.unitSystem = unitSystem;
360
421
  }
361
422
  get commandString() {
362
- return `GAP ${this.valueWithUnit(this.gap)}, ${this.valueWithUnit(this.offset)}`;
363
- }
364
- valueWithUnit(value) {
365
- switch (this.unitSystem) {
366
- case "dot":
367
- return `${value} dot`;
368
- case "imperial":
369
- return value;
370
- case "metric":
371
- return `${value} mm`;
372
- }
423
+ return `GAP ${valueWithUnit(this.gap, this.unitSystem)}, ${valueWithUnit(this.offset, this.unitSystem)}`;
373
424
  }
374
425
  };
375
426
 
@@ -382,17 +433,7 @@ var TSPLSizeCommand = class extends TSPLCommand {
382
433
  this.unitSystem = unitSystem;
383
434
  }
384
435
  get commandString() {
385
- return `SIZE ${this.valueWithUnit(this.width)}, ${this.valueWithUnit(this.height)}`;
386
- }
387
- valueWithUnit(value) {
388
- switch (this.unitSystem) {
389
- case "dot":
390
- return `${value} dot`;
391
- case "imperial":
392
- return value;
393
- case "metric":
394
- return `${value} mm`;
395
- }
436
+ return `SIZE ${valueWithUnit(this.width, this.unitSystem)}, ${valueWithUnit(this.height, this.unitSystem)}`;
396
437
  }
397
438
  };
398
439
 
@@ -465,7 +506,7 @@ var TSPLQRCommand = class extends TSPLVisualCommand {
465
506
  }
466
507
  }
467
508
  get commandString() {
468
- return `QRCODE ${this.x}, ${this.y}, ${this.ecc}, ${this.cellWidth}, ${this.mode}, ${this.rotation}, ${this.model}, ${this.mask}, "${this.content}"`;
509
+ return `QRCODE ${this.x}, ${this.y}, ${this.ecc}, ${this.cellWidth}, ${this.mode}, ${this.rotation}, ${this.model}, "${this.content}"`;
469
510
  }
470
511
  };
471
512
 
@@ -482,12 +523,193 @@ var TSPLBlockCommand = class extends TSPLTextCommand {
482
523
  }
483
524
  };
484
525
 
485
- // src/printers/index.ts
486
- var printers_exports = {};
487
- __export(printers_exports, {
488
- Printer: () => Printer,
489
- PrinterService: () => PrinterService
490
- });
526
+ // src/commands/tspl/commands/basic/TSPLDownload.ts
527
+ var TSPLDownload = class extends TSPLCommand {
528
+ /**
529
+ * Initialize a command with a raw body
530
+ * @param body
531
+ */
532
+ constructor(fileName, data) {
533
+ super();
534
+ this.fileName = fileName;
535
+ this.data = data;
536
+ }
537
+ get commandString() {
538
+ return `DOWNLOAD "${this.fileName}", ${this.data.byteLength},`;
539
+ }
540
+ write(device) {
541
+ return __async(this, null, function* () {
542
+ yield this.writeString(this.commandString, device);
543
+ yield this.writeBytes(this.data, device);
544
+ yield this.terminateCommand(device);
545
+ });
546
+ }
547
+ };
548
+
549
+ // src/commands/tspl/commands/basic/TSPLDisplay.ts
550
+ var TSPLDisplay = class extends TSPLCommand {
551
+ constructor(type) {
552
+ super();
553
+ this.type = type;
554
+ }
555
+ get commandString() {
556
+ return `DISPLAY ${this.type}`;
557
+ }
558
+ };
559
+
560
+ // src/commands/tspl/commands/basic/TSPLDiagonal.ts
561
+ var TSPLDiagonal = class extends TSPLCommand {
562
+ constructor(start, end, thickness = 3) {
563
+ super();
564
+ this.start = start;
565
+ this.end = end;
566
+ this.thickness = thickness;
567
+ }
568
+ get commandString() {
569
+ return `DIAGONAL ${this.start.x}, ${this.start.y}, ${this.end.x}, ${this.end.y}, ${this.thickness}`;
570
+ }
571
+ };
572
+
573
+ // src/commands/tspl/commands/basic/TSPLBarcodeCommand.ts
574
+ var TSPLBarcodeCommand = class _TSPLBarcodeCommand extends TSPLVisualCommand {
575
+ /**
576
+ * @param x X coordinate in dots
577
+ * @param y Y Coordinate in dots
578
+ * @param type Type of the barcode
579
+ * @param height Height of the barcode in dots
580
+ * @param narrow Width of narrow elements in dots
581
+ * @param wide Width of the wide elements in dots
582
+ * @param content Content of the barcode. Supported content depends on the barcode type
583
+ * @param rotation Rotation
584
+ * @param alignment Alignment of the barcode
585
+ */
586
+ constructor(x, y, type, height, narrow, wide, content, rotation = 0, humanReadable = "left", alignment = "left") {
587
+ super(x, y);
588
+ this.type = type;
589
+ this.height = height;
590
+ this.narrow = narrow;
591
+ this.wide = wide;
592
+ this.content = content;
593
+ this.rotation = rotation;
594
+ this.humanReadable = _TSPLBarcodeCommand.humanReadableValue(humanReadable);
595
+ this.alignment = alignmentToNumber(alignment);
596
+ }
597
+ get commandString() {
598
+ return `BARCODE ${this.x}, ${this.y}, "${this.type}", ${this.height}, ${this.humanReadable},${this.rotation}, ${this.narrow}, ${this.wide},${this.alignment}, "${this.content}"`;
599
+ }
600
+ static humanReadableValue(hr) {
601
+ switch (hr) {
602
+ case "none":
603
+ return 0;
604
+ case "left":
605
+ return 1;
606
+ case "center":
607
+ return 2;
608
+ case "right":
609
+ return 3;
610
+ }
611
+ }
612
+ };
613
+
614
+ // src/helpers/QRCodeUtils.ts
615
+ var QRLengthMapping = {
616
+ 10: 21,
617
+ 20: 25,
618
+ 35: 29,
619
+ 50: 33,
620
+ 64: 37,
621
+ 84: 41,
622
+ 93: 45,
623
+ 122: 49,
624
+ 143: 53,
625
+ 174: 57,
626
+ 200: 61,
627
+ 227: 65,
628
+ 259: 69,
629
+ 283: 73,
630
+ 321: 77,
631
+ 365: 81,
632
+ 408: 85,
633
+ 452: 89,
634
+ 493: 93,
635
+ 557: 97,
636
+ 587: 101,
637
+ 640: 105,
638
+ 672: 109,
639
+ 744: 113,
640
+ 779: 117,
641
+ 864: 121,
642
+ 910: 125,
643
+ 958: 129,
644
+ 1016: 133,
645
+ 1080: 137,
646
+ 1150: 141,
647
+ 1226: 145,
648
+ 1307: 149,
649
+ 1394: 153,
650
+ 1431: 157,
651
+ 1530: 161,
652
+ 1591: 165,
653
+ 1658: 169,
654
+ 1774: 173,
655
+ 1852: 177
656
+ };
657
+
658
+ // src/commands/tspl/TSPLCommandGenerator.ts
659
+ var TSPLCommandGenerator = class {
660
+ commandGroup(commands) {
661
+ return new TSPLCommandGroup(commands);
662
+ }
663
+ print(sets, copiesPerSet) {
664
+ return new TSPLPrintCommand(sets, copiesPerSet);
665
+ }
666
+ text(content, x, y, font, size) {
667
+ const fontName = font == "default" ? "0" : font;
668
+ return new TSPLTextCommand(content, x, y, fontName, 0, size, size, "left");
669
+ }
670
+ upload(name, data) {
671
+ return new TSPLDownload(name, data);
672
+ }
673
+ setUp(width, height, gap, offset, direction, mirror = false, unitSystem) {
674
+ const commands = [
675
+ new TSPLSizeCommand(width, height, unitSystem),
676
+ new TSPLGapCommand(gap, offset, unitSystem),
677
+ new TSPLDirectionCommand(direction, mirror),
678
+ new TSPLCLSCommand()
679
+ ];
680
+ return new TSPLCommandGroup(commands);
681
+ }
682
+ display() {
683
+ return new TSPLCommandGroup([
684
+ new TSPLDisplay("CLS"),
685
+ new TSPLDisplay("IMAGE")
686
+ ]);
687
+ }
688
+ line(start, end, thickness) {
689
+ return new TSPLDiagonal(start, end, thickness);
690
+ }
691
+ image(image, x, y, mode) {
692
+ return new TSPLBitmapCommand(image, x, y, mode);
693
+ }
694
+ qrCode(content, width, x, y) {
695
+ const cellCount = this.cellCount(content);
696
+ const cellWidth = Math.round(width / cellCount);
697
+ return new TSPLQRCommand(`A${content}`, x, y, cellWidth, "H", "M");
698
+ }
699
+ barCode(content, x, y, type, height, rotation, humanReadable, alignment) {
700
+ return new TSPLBarcodeCommand(x, y, type, height, 1, 1, content, rotation, humanReadable, alignment);
701
+ }
702
+ cellCount(content) {
703
+ const limits = Object.keys(QRLengthMapping).map((limit) => Number(limit)).sort((a, b) => a - b);
704
+ const contentLength = content.length;
705
+ let i = 0;
706
+ while (limits[i] < contentLength && i < limits.length - 1) {
707
+ i++;
708
+ }
709
+ return QRLengthMapping[limits[i]];
710
+ }
711
+ };
712
+ var TSPLCommandGenerator_default = new TSPLCommandGenerator();
491
713
 
492
714
  // src/printers/Printer.ts
493
715
  var Printer = class {
@@ -502,6 +724,26 @@ var Printer = class {
502
724
  yield this.usbDevice.close();
503
725
  });
504
726
  }
727
+ /**
728
+ * Prints a label
729
+ * @param label
730
+ */
731
+ print(label, sets, gap, copiesPerSet = 1, direction = "normal", mirror = false, gapOffset = 0) {
732
+ return __async(this, null, function* () {
733
+ const commands = yield label.fullPrintCommand(this.language, gap, direction, sets, copiesPerSet, mirror, gapOffset);
734
+ yield this.writeCommand(commands);
735
+ });
736
+ }
737
+ /**
738
+ * Display label on the printer's screen
739
+ * @param label
740
+ */
741
+ display(label, direction = "normal", mirror = false) {
742
+ return __async(this, null, function* () {
743
+ const command = yield label.fullDisplayCommand(this.language, direction, mirror);
744
+ yield this.writeCommand(command);
745
+ });
746
+ }
505
747
  /**
506
748
  * Writes a command to the printers usb
507
749
  * @param command Command to send to the usb
@@ -542,6 +784,7 @@ var StringUtils = class {
542
784
  return decoder.decode(bytes);
543
785
  }
544
786
  };
787
+ var isWhitespace = (text) => text.trim() === "";
545
788
 
546
789
  // src/helpers/USBUtils.ts
547
790
  var unsupportedUsbError = "usb-unsupported";
@@ -741,8 +984,588 @@ var PrinterService = class _PrinterService {
741
984
  });
742
985
  }
743
986
  };
987
+
988
+ // src/labels/Printable.ts
989
+ var Printable = class {
990
+ /**
991
+ * 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
992
+ * @param printer Printer to generate the command. Important because the command is printer language specific
993
+ * @returns A promise for a command. Most commands are syncronouse but some may require to access async resources
994
+ */
995
+ commandForPrinter(printer, config) {
996
+ return __async(this, null, function* () {
997
+ return yield this.commandForLanguage(printer.language, config);
998
+ });
999
+ }
1000
+ /**
1001
+ * Obtain a command generator for the given language
1002
+ * @param language Language to get generator for
1003
+ */
1004
+ commandGeneratorFor(language) {
1005
+ switch (language) {
1006
+ case "tspl":
1007
+ return tspl_exports.commandGenerator;
1008
+ }
1009
+ }
1010
+ };
1011
+
1012
+ // src/labels/Label.ts
1013
+ import fontkit from "fontkit";
1014
+ var DEFAULT_FONT_WEIGHT = 400;
1015
+ var DEFAULT_FONT_STYLE = "normal";
1016
+ var FONT_PREFIX = "f";
1017
+ var Label = class extends Printable {
1018
+ constructor(width, height, dimensionUnit = "metric", dpi = 203) {
1019
+ super();
1020
+ this.fonts = {};
1021
+ /**
1022
+ * List of fields on the label
1023
+ */
1024
+ this.fields = [];
1025
+ this.fontCounter = 0;
1026
+ this.width = width;
1027
+ this.height = height;
1028
+ this.unitSystem = dimensionUnit;
1029
+ this.dpi = dpi;
1030
+ }
1031
+ /**
1032
+ * Configuration used when generating commands
1033
+ */
1034
+ get printConfig() {
1035
+ return {
1036
+ dpi: this.dpi,
1037
+ textWidth: (text, font) => {
1038
+ const size = dotToPoint(font.size, this.dpi);
1039
+ const fontObject = this.getIndexedFont(font).font;
1040
+ const run = fontObject.layout(text);
1041
+ const scaledWidth = size * run.advanceWidth / fontObject.unitsPerEm;
1042
+ return pointsToDots(scaledWidth, this.dpi);
1043
+ },
1044
+ getFontName: this.getFontName.bind(this)
1045
+ };
1046
+ }
1047
+ commandForLanguage(language, config) {
1048
+ return __async(this, null, function* () {
1049
+ const commandList = yield Promise.all(this.fields.map((field) => field.commandForLanguage(language, config)));
1050
+ return this.commandGeneratorFor(language).commandGroup(commandList);
1051
+ });
1052
+ }
1053
+ /**
1054
+ * Place fields to a label
1055
+ * @param fields
1056
+ */
1057
+ add(...fields) {
1058
+ this.fields.push(...fields);
1059
+ }
1060
+ /**
1061
+ * Register a font to be used. Use the name provided in components to use the font.
1062
+ * For example: textField.setFont('myFont.ttf', 12)
1063
+ * @param file Font file. Can be a blob or a url
1064
+ * @param name Name to be used to reference the font
1065
+ */
1066
+ registerFont(font) {
1067
+ return __async(this, null, function* () {
1068
+ const key = this.fontKey(font.weight, font.style);
1069
+ if (!this.fonts[font.name]) {
1070
+ this.fonts[font.name] = {
1071
+ fonts: {}
1072
+ };
1073
+ }
1074
+ const fontBuffer = Buffer.from(font.data);
1075
+ this.fonts[font.name].fonts[key] = __spreadProps(__spreadValues({}, font), {
1076
+ font: fontkit.create(fontBuffer),
1077
+ alias: `${FONT_PREFIX}${this.fontCounter}.${this.fontExtension}`
1078
+ });
1079
+ this.fontCounter += 1;
1080
+ });
1081
+ }
1082
+ /**
1083
+ * Generate a command that is complete for printing
1084
+ * @param language Printing language to use
1085
+ * @param gap Distance between two labels. It is measured between the two points where the sensor
1086
+ * leaves the label and enters the next one
1087
+ * @param direction Direction relative to printing direction. See documentation for more details
1088
+ * @param sets Number of sets to print. If you have counters for example, it will not change in a set
1089
+ * @param copiesPerSet Number of labels per set
1090
+ * @param mirror Mirror the label along the vertical axis
1091
+ * @param gapOffset Used with non uniform shaped labels. Is the distance between the point where the sensor leaves the label and the
1092
+ * furthest point of the label in the direction of printing. Check documentation for more info
1093
+ * TODO: Is this too TSPL Specific?
1094
+ */
1095
+ fullPrintCommand(language, gap, direction, sets, copiesPerSet = 1, mirror = false, gapOffset = 0) {
1096
+ return __async(this, null, function* () {
1097
+ const generator = this.commandGeneratorFor(language);
1098
+ const commands = yield this.fullCommand(language, gap, direction, mirror, gapOffset, generator);
1099
+ commands.push(generator.print(sets, copiesPerSet));
1100
+ return generator.commandGroup(commands);
1101
+ });
1102
+ }
1103
+ /**
1104
+ * Generate commands needed to display the label on the printer screen
1105
+ * @param language Printing language to use
1106
+ * @param direction Direction relative to printing direction. See documentation for more details
1107
+ * @param mirror Mirror the label along the vertical axis
1108
+ */
1109
+ fullDisplayCommand(language, direction, mirror = false) {
1110
+ return __async(this, null, function* () {
1111
+ const generator = this.commandGeneratorFor(language);
1112
+ const commands = yield this.fullCommand(language, 0, direction, mirror, 0, generator);
1113
+ commands.push(generator.display());
1114
+ const group = generator.commandGroup(commands);
1115
+ group.print(console.log);
1116
+ return group;
1117
+ });
1118
+ }
1119
+ /**
1120
+ * Helper function that generates common commands for print and display
1121
+ */
1122
+ fullCommand(language, gap, direction, mirror = false, gapOffset = 0, generator) {
1123
+ return __async(this, null, function* () {
1124
+ const commands = [
1125
+ this.fontUploadCommands(generator),
1126
+ generator.setUp(this.width, this.height, gap, gapOffset, direction, mirror, this.unitSystem),
1127
+ yield this.commandForLanguage(language, this.printConfig)
1128
+ ];
1129
+ return commands;
1130
+ });
1131
+ }
1132
+ fontUploadCommands(generator) {
1133
+ const families = Object.keys(this.fonts);
1134
+ const commands = families.flatMap((family) => {
1135
+ const familyFonts = this.fonts[family].fonts;
1136
+ const fontNames = Object.keys(familyFonts);
1137
+ return fontNames.map((name) => {
1138
+ const font = familyFonts[name];
1139
+ const fileName = font.alias;
1140
+ return generator.upload(fileName, font.data);
1141
+ });
1142
+ });
1143
+ return generator.commandGroup(commands);
1144
+ }
1145
+ getIndexedFont(font) {
1146
+ var _a, _b;
1147
+ const family = this.fonts[font.name];
1148
+ const style = (_a = font.style) != null ? _a : DEFAULT_FONT_STYLE;
1149
+ const weigth = (_b = font.weight) != null ? _b : DEFAULT_FONT_WEIGHT;
1150
+ const fontKeys = Object.keys(family.fonts);
1151
+ const exactMatch = fontKeys.find(
1152
+ (key) => family.fonts[key].style == style && family.fonts[key].weight == weigth
1153
+ );
1154
+ if (exactMatch) {
1155
+ return family.fonts[exactMatch];
1156
+ } else {
1157
+ const sameStyleKeys = fontKeys.filter((key) => family.fonts[key].style == style);
1158
+ if (sameStyleKeys.length > 0) {
1159
+ let weigthDiff = 99999999;
1160
+ let selectedKey = "";
1161
+ sameStyleKeys.forEach((key) => {
1162
+ const diff = Math.abs(weigth - family.fonts[key].weight);
1163
+ if (diff < weigthDiff) {
1164
+ weigthDiff = diff;
1165
+ selectedKey = key;
1166
+ }
1167
+ });
1168
+ return family.fonts[selectedKey];
1169
+ } else {
1170
+ return family.fonts[fontKeys[0]];
1171
+ }
1172
+ }
1173
+ }
1174
+ getFontName(font) {
1175
+ const indexedFont = this.getIndexedFont(font);
1176
+ return indexedFont.alias;
1177
+ }
1178
+ /// This can be extended when we want support multiple fonts
1179
+ get fontExtension() {
1180
+ return "TTF";
1181
+ }
1182
+ fontKey(weight, style) {
1183
+ return `${weight}${style != null ? style : DEFAULT_FONT_STYLE}`;
1184
+ }
1185
+ };
1186
+
1187
+ // src/labels/fields/LabelField.ts
1188
+ var LabelField = class extends Printable {
1189
+ };
1190
+
1191
+ // src/labels/fields/Line.ts
1192
+ var Line = class extends LabelField {
1193
+ /**
1194
+ *
1195
+ * @param start Start point of the line. Values are in dots
1196
+ * @param end End point of the line. Values are in dots
1197
+ * @param thickness Thickness of the line in dots
1198
+ */
1199
+ constructor(start, end, thickness = 3) {
1200
+ super();
1201
+ this.start = start;
1202
+ this.end = end;
1203
+ this.thickness = thickness;
1204
+ }
1205
+ commandForLanguage(language) {
1206
+ return this.commandGeneratorFor(language).line(this.start, this.end, this.thickness);
1207
+ }
1208
+ };
1209
+
1210
+ // src/labels/fields/Text.ts
1211
+ import { NodeType, parse } from "node-html-parser";
1212
+ var BOLD_WEIGTH = 700;
1213
+ var BOLD_TAG = "b";
1214
+ var ITALIC_TAG = "i";
1215
+ var UNDERLINE_TAG = "u";
1216
+ var STRIKE_TAG = "s";
1217
+ var Text = class extends LabelField {
1218
+ constructor(content, x, y, formatted = true) {
1219
+ super();
1220
+ this.font = { name: "default", size: 10 };
1221
+ this.type = "singleline";
1222
+ this.context = void 0;
1223
+ this.lineSpacing = 1;
1224
+ this.content = content.replace("\n", "");
1225
+ this.x = x;
1226
+ this.y = y;
1227
+ this.formatted = formatted;
1228
+ }
1229
+ /**
1230
+ * Sets the field to single line
1231
+ * @param width Max width of the text. Leave it undefined to allow the field to grow
1232
+ */
1233
+ setSingleLine(width) {
1234
+ this.type = "singleline";
1235
+ this.width = width;
1236
+ this.height = void 0;
1237
+ }
1238
+ /**
1239
+ * Sets the field to multi line
1240
+ * @param width Max width of text before it gets wrapped to a new line
1241
+ * @param height Max height of the text box, leave undefined to allow the text box to grow infinitly
1242
+ */
1243
+ setMultiLine(width, height) {
1244
+ this.type = "multiline";
1245
+ this.width = width;
1246
+ this.height = height;
1247
+ }
1248
+ /**
1249
+ * Set a font to use as a base. If no formatting is set on the text with a html tag, this will be used
1250
+ * Note: The font name either has to be a built in font on your printer or a font
1251
+ * that is registered on the label using 'registerFont'.
1252
+ */
1253
+ setFont(font) {
1254
+ this.font = font;
1255
+ }
1256
+ commandForLanguage(language, config) {
1257
+ return __async(this, null, function* () {
1258
+ this.context = {
1259
+ config,
1260
+ language,
1261
+ generator: this.commandGeneratorFor(language)
1262
+ };
1263
+ let command;
1264
+ if (this.formatted) {
1265
+ command = this.generateFormattedText();
1266
+ } else {
1267
+ command = this.generatePlainText();
1268
+ }
1269
+ this.context = void 0;
1270
+ return command;
1271
+ });
1272
+ }
1273
+ /**
1274
+ * Generate commands for formatted text
1275
+ * @returns
1276
+ */
1277
+ generateFormattedText() {
1278
+ if (!this.context)
1279
+ throw "context-not-set";
1280
+ const rootNode = parse(this.content);
1281
+ const { command } = this.generateFormattedRecursive(this.x, this.y, rootNode, this.font, []);
1282
+ return command;
1283
+ }
1284
+ /**
1285
+ * Generate commands for plain text
1286
+ * @returns
1287
+ */
1288
+ generatePlainText() {
1289
+ const { command } = this.generatePlainTextCore(this.content, this.x, this.y, this.font);
1290
+ return command;
1291
+ }
1292
+ /**
1293
+ * Iterats the nodes in a html text and generates text commands for it
1294
+ */
1295
+ generateFormattedRecursive(initialX, initialY, rootNode, font, features) {
1296
+ if (rootNode.nodeType == NodeType.TEXT_NODE) {
1297
+ const result = this.generatePlainTextCore(rootNode.innerText, initialX, initialY, font, features);
1298
+ return result;
1299
+ } else {
1300
+ const elementNode = rootNode;
1301
+ const tag = elementNode.rawTagName;
1302
+ let commands = [];
1303
+ let currentX = initialX;
1304
+ let currentY = initialY;
1305
+ let baseFont = __spreadValues({}, font);
1306
+ let baseFeatures = [...features];
1307
+ if (tag == UNDERLINE_TAG) {
1308
+ baseFeatures.push("underline");
1309
+ } else if (tag == STRIKE_TAG) {
1310
+ baseFeatures.push("strike");
1311
+ } else if (tag == BOLD_TAG) {
1312
+ baseFont.weight = BOLD_WEIGTH;
1313
+ } else if (tag == ITALIC_TAG) {
1314
+ baseFont.style = "italic";
1315
+ }
1316
+ elementNode.childNodes.forEach((node) => {
1317
+ const { x, y, command } = this.generateFormattedRecursive(currentX, currentY, node, baseFont, baseFeatures);
1318
+ currentX = x;
1319
+ currentY = y;
1320
+ commands.push(command);
1321
+ });
1322
+ return {
1323
+ x: currentX,
1324
+ y: currentY,
1325
+ command: this.context.generator.commandGroup(commands)
1326
+ };
1327
+ }
1328
+ }
1329
+ /**
1330
+ * Generate commands for plain text
1331
+ * @param config
1332
+ * @returns
1333
+ */
1334
+ generatePlainTextCore(content, initialX, initialY, font, features = []) {
1335
+ if (!this.context)
1336
+ throw "context-not-set";
1337
+ const textWidhtFunction = this.textWithFunction;
1338
+ let fullWidth = textWidhtFunction(content, font);
1339
+ if (this.width) {
1340
+ const initialPadding = initialX - this.x;
1341
+ let rowWidth = this.width - initialPadding;
1342
+ if (rowWidth <= 0) {
1343
+ rowWidth = this.width;
1344
+ initialX = this.x;
1345
+ initialY += font.size + this.lineSpacing;
1346
+ }
1347
+ if (initialX == this.x) {
1348
+ content = content.trimStart();
1349
+ fullWidth = textWidhtFunction(content, font);
1350
+ }
1351
+ if (fullWidth <= rowWidth) {
1352
+ return {
1353
+ x: initialX + fullWidth,
1354
+ y: initialY,
1355
+ command: this.textCommand(content, initialX, initialY, font, features)
1356
+ };
1357
+ } else {
1358
+ const commands = [];
1359
+ let x = initialX;
1360
+ let y = initialY;
1361
+ let remainingContent = content;
1362
+ let remainingWidth = fullWidth;
1363
+ let currentHeight = 0;
1364
+ let finalX = x;
1365
+ let finalY = y;
1366
+ do {
1367
+ if (remainingWidth < rowWidth) {
1368
+ finalX = x + remainingWidth;
1369
+ finalY = y;
1370
+ commands.push(this.textCommand(remainingContent, x, y, font, features));
1371
+ remainingContent = "";
1372
+ } else {
1373
+ let rows = remainingWidth / rowWidth;
1374
+ rowWidth = this.width;
1375
+ let rowEndIndex = Math.floor(remainingContent.length / rows);
1376
+ let originalRowEndIndex = rowEndIndex;
1377
+ if (rowEndIndex == 0) {
1378
+ x = this.x;
1379
+ y += font.size + this.lineSpacing;
1380
+ continue;
1381
+ }
1382
+ while (!(!isWhitespace(remainingContent.charAt(rowEndIndex)) && (rowEndIndex == remainingContent.length - 1 || isWhitespace(remainingContent.charAt(rowEndIndex + 1)))) && rowEndIndex > 0) {
1383
+ rowEndIndex--;
1384
+ }
1385
+ let nextRowStartIndex = rowEndIndex + 1;
1386
+ if (rowEndIndex == 0) {
1387
+ rowEndIndex = originalRowEndIndex;
1388
+ nextRowStartIndex = originalRowEndIndex + 1;
1389
+ } else {
1390
+ while (isWhitespace(remainingContent.charAt(nextRowStartIndex)) && nextRowStartIndex < remainingContent.length) {
1391
+ nextRowStartIndex++;
1392
+ }
1393
+ }
1394
+ const thisRow = remainingContent.substring(0, rowEndIndex + 1);
1395
+ commands.push(this.textCommand(thisRow, x, y, font, features));
1396
+ if (nextRowStartIndex == remainingContent.length) {
1397
+ finalX = x + remainingWidth;
1398
+ finalY = y;
1399
+ }
1400
+ x = this.x;
1401
+ y += font.size + this.lineSpacing;
1402
+ currentHeight = y - this.y;
1403
+ remainingContent = remainingContent.substring(nextRowStartIndex);
1404
+ remainingWidth = textWidhtFunction(remainingContent, font);
1405
+ }
1406
+ } while (
1407
+ // We don't have a height constraint or we are still within bounds
1408
+ // and there is still content
1409
+ // and we are supporting multiline
1410
+ (this.height == void 0 || currentHeight + font.size <= this.height) && remainingContent != "" && this.type == "multiline"
1411
+ );
1412
+ return {
1413
+ x: finalX,
1414
+ y: finalY,
1415
+ command: this.context.generator.commandGroup(commands)
1416
+ };
1417
+ }
1418
+ } else {
1419
+ return {
1420
+ x: initialX + fullWidth,
1421
+ y: initialY,
1422
+ command: this.textCommand(content, initialX, initialY, font, features)
1423
+ };
1424
+ }
1425
+ }
1426
+ textCommand(text, x, y, font, features) {
1427
+ var _a, _b;
1428
+ if (!this.context)
1429
+ throw "no-context";
1430
+ const finalFontSize = dotToPoint(font.size, (_b = (_a = this.context.config) == null ? void 0 : _a.dpi) != null ? _b : 203);
1431
+ const finalFont = this.getFontName(font);
1432
+ const finalX = Math.round(x);
1433
+ const finalY = Math.round(y);
1434
+ let commands = [];
1435
+ const textCommand = this.context.generator.text(text, finalX, finalY, finalFont, finalFontSize);
1436
+ if (features.length == 0) {
1437
+ return textCommand;
1438
+ } else {
1439
+ let lineHeight = font.size * 0.1;
1440
+ let textWidth = this.textWithFunction(text, font);
1441
+ if (features.includes("strike")) {
1442
+ commands.push(this.textLineCommand(textWidth, x, y, lineHeight, 0.5, font.size));
1443
+ }
1444
+ if (features.includes("underline")) {
1445
+ commands.push(this.textLineCommand(textWidth, x, y, lineHeight, 0.9, font.size));
1446
+ }
1447
+ commands.push(textCommand);
1448
+ }
1449
+ return this.context.generator.commandGroup(commands);
1450
+ }
1451
+ textLineCommand(width, x, y, lineHeight, linePercentage, fontSize) {
1452
+ const sy = Math.round(y + fontSize * linePercentage - lineHeight / 2);
1453
+ const sx = Math.round(x);
1454
+ return this.context.generator.line(
1455
+ { x: sx, y: sy },
1456
+ { x: sx + width, y: sy },
1457
+ lineHeight
1458
+ );
1459
+ }
1460
+ getFontName(font) {
1461
+ var _a;
1462
+ if (!this.context)
1463
+ throw "no-context";
1464
+ if (font.name == "default") {
1465
+ return "default";
1466
+ } else {
1467
+ return (_a = this.context.config) == null ? void 0 : _a.getFontName(font);
1468
+ }
1469
+ }
1470
+ get textWithFunction() {
1471
+ var _a, _b, _c;
1472
+ if (this.font.name == "default") {
1473
+ return this.defaultTextWidth;
1474
+ } else {
1475
+ return (_c = (_b = (_a = this.context) == null ? void 0 : _a.config) == null ? void 0 : _b.textWidth) != null ? _c : this.defaultTextWidth;
1476
+ }
1477
+ }
1478
+ /**
1479
+ * This function is used to calculate the font size if no
1480
+ * print config is provided. This will asume that the font has square characters
1481
+ */
1482
+ defaultTextWidth(text, font) {
1483
+ return text.length * font.size;
1484
+ }
1485
+ };
1486
+
1487
+ // src/labels/fields/BarCode.ts
1488
+ var BarCode = class extends LabelField {
1489
+ constructor(content, x, y, type, height) {
1490
+ super();
1491
+ this.content = content;
1492
+ this.x = x;
1493
+ this.y = y;
1494
+ this.type = type;
1495
+ this.height = height;
1496
+ this.rotation = 0;
1497
+ this.humanReadable = "none";
1498
+ this.alignment = "left";
1499
+ }
1500
+ setRotation(rotation) {
1501
+ this.rotation = rotation;
1502
+ }
1503
+ setHumanReadable(humanReadable) {
1504
+ this.humanReadable = humanReadable;
1505
+ }
1506
+ commandForLanguage(language, _config) {
1507
+ return __async(this, null, function* () {
1508
+ return yield this.commandGeneratorFor(language).barCode(this.content, this.x, this.y, this.type, this.height, this.rotation, this.humanReadable, this.alignment);
1509
+ });
1510
+ }
1511
+ };
1512
+
1513
+ // src/labels/fields/Image.ts
1514
+ var Image = class _Image extends LabelField {
1515
+ constructor(x, y, image) {
1516
+ super();
1517
+ this.x = x;
1518
+ this.y = y;
1519
+ this.image = image;
1520
+ }
1521
+ commandForLanguage(language, _config) {
1522
+ return __async(this, null, function* () {
1523
+ return yield this.commandGeneratorFor(language).image(this.image, this.x, this.y);
1524
+ });
1525
+ }
1526
+ /**
1527
+ * Create an image field for an image
1528
+ * @param image
1529
+ * @param x
1530
+ * @param y
1531
+ * @param width
1532
+ * @param height
1533
+ * @returns
1534
+ */
1535
+ static create(image, x, y, width, height) {
1536
+ return __async(this, null, function* () {
1537
+ const bitmap = yield ImageUtils.getBWBitmap(image, width, height);
1538
+ return new _Image(x, y, bitmap);
1539
+ });
1540
+ }
1541
+ };
1542
+
1543
+ // src/labels/fields/QRCode.ts
1544
+ var QRCode = class extends LabelField {
1545
+ constructor(content, x, y, width) {
1546
+ super();
1547
+ this.content = content;
1548
+ this.x = x;
1549
+ this.y = y;
1550
+ this.width = width;
1551
+ }
1552
+ commandForLanguage(language, config) {
1553
+ return __async(this, null, function* () {
1554
+ return yield this.commandGeneratorFor(language).qrCode(this.content, this.width, this.x, this.y);
1555
+ });
1556
+ }
1557
+ };
744
1558
  export {
745
- commands_exports as commands,
746
- printers_exports as printers
1559
+ BarCode,
1560
+ Command,
1561
+ CommandGroup,
1562
+ Image,
1563
+ Label,
1564
+ Line,
1565
+ Printer,
1566
+ PrinterService,
1567
+ Text,
1568
+ QRCode as qrCode,
1569
+ tspl_exports as tspl
747
1570
  };
748
1571
  //# sourceMappingURL=index.mjs.map