label-printer 0.9.0 → 0.10.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.d.mts CHANGED
@@ -102,7 +102,7 @@ interface CommandGenerator<T extends Command> {
102
102
  line: (start: Point, end: Point, thickness: number) => T;
103
103
  image: (image: BitmapLike, x: number, y: number, mode?: GraphicMode) => T;
104
104
  qrCode: (content: string, width: number, x: number, y: number) => T;
105
- barCode: (content: string, x: number, y: number, type: BarcodeType, height: number, rotation: Rotation, humanReadable: BarcodeHumanReable, alignment: Alignment) => T;
105
+ barCode: (content: string, x: number, y: number, type: BarcodeType, height: number, rotation: Rotation, humanReadable: BarcodeHumanReable, alignment: Alignment, barWidth?: number) => T;
106
106
  /**
107
107
  * Should instruct the printer to display the image of the label on its screen instead of printing it
108
108
  */
@@ -110,7 +110,7 @@ interface CommandGenerator<T extends Command> {
110
110
  /**
111
111
  * This should generate the needed commands to set up a label before printing
112
112
  */
113
- setUp: (width: number, height: number, gap: number, offset: number, direction: LabelDirection, mirror: boolean, unitSystem: UnitSystem) => T;
113
+ setUp: (width: number, height: number, gap: number, offset: number, direction: LabelDirection, mirror: boolean, unitSystem: UnitSystem, density: number) => T;
114
114
  }
115
115
 
116
116
  /**
@@ -162,7 +162,7 @@ type LabelDirection = "normal" | "inverse";
162
162
  type ECCLevel = "L" | "M" | "Q" | "H";
163
163
  type AutoManual = "A" | "M";
164
164
  type QRModel = "M1" | "M2";
165
- type BarcodeType = "CODE128" | "EAN13" | "EAN8" | "EAN5" | "EAN2" | "UPC" | "CODE39" | "ITF14" | "MSI10" | "MSI11" | "MSI1010" | "MSI1110" | "pharmacode" | "codabar";
165
+ type BarcodeType = "128" | "EAN128" | "25" | "25C" | "39" | "39C" | "93" | "EAN13" | "EAN13+2" | "EAN13+5" | "EAN8" | "EAN8+2" | "EAN8+5" | "CODA" | "POST" | "UPCA" | "UPCA+2" | "UPCA+5" | "UPCE" | "UPCE+2" | "UPCE+5" | "CPOST" | "MSI" | "MSIC" | "PLESSEY" | "ITF14" | "EAN14" | "11" | "TELEPEN" | "TELEPENN" | "PLANET" | "CODE49" | "DPI" | "DPL";
166
166
  type BarcodeHumanReable = "none" | "left" | "right" | "center";
167
167
 
168
168
  /**
@@ -397,6 +397,16 @@ declare class TSPLDiagonal extends TSPLCommand {
397
397
  get commandString(): string;
398
398
  }
399
399
 
400
+ /**
401
+ * Clear the image buffer
402
+ * {@link /documentsions/TSPL.pdf}
403
+ */
404
+ declare class TSPLDensityCommand extends TSPLCommand {
405
+ private density;
406
+ constructor(density: number);
407
+ get commandString(): string;
408
+ }
409
+
400
410
  /**
401
411
  * Command generator for tspl commands
402
412
  */
@@ -405,12 +415,21 @@ declare class TSPLCommandGenerator implements CommandGenerator<TSPLCommand> {
405
415
  print(sets: number, copiesPerSet: number): TSPLCommand;
406
416
  text(content: string, x: number, y: number, font: string | "default", size: number): TSPLCommand;
407
417
  upload(name: string, data: ArrayBuffer | Uint8Array): TSPLCommand;
408
- setUp(width: number, height: number, gap: number, offset: number, direction: LabelDirection, mirror: boolean | undefined, unitSystem: UnitSystem): TSPLCommand;
418
+ setUp(width: number, height: number, gap: number, offset: number, direction: LabelDirection, mirror: boolean | undefined, unitSystem: UnitSystem, density: number): TSPLCommand;
409
419
  display(): TSPLCommandGroup;
410
420
  line(start: Point, end: Point, thickness: number): TSPLCommand;
411
421
  image(image: BitmapLike, x: number, y: number, mode?: GraphicMode | undefined): TSPLCommand;
412
422
  qrCode(content: string, width: number, x: number, y: number): TSPLCommand;
413
- barCode(content: string, x: number, y: number, type: BarcodeType, height: number, rotation: Rotation, humanReadable: BarcodeHumanReable, alignment: Alignment): TSPLCommand;
423
+ barCode(content: string, x: number, y: number, type: BarcodeType, height: number, rotation: Rotation, humanReadable: BarcodeHumanReable, alignment: Alignment, barWidth?: number): TSPLCommand;
424
+ /**
425
+ * Calculates the narrow and wide element widths for a barcode type based on the
426
+ * TSPL documentation's standard narrow:wide ratios.
427
+ *
428
+ * Types that only support 1:1 (continuous barcodes like CODE128, EAN, UPC) get
429
+ * narrow === wide. All other types use the 1:3 ratio, which is the industry
430
+ * standard for variable-ratio symbologies (CODE39, ITF14, codabar, MSI…).
431
+ */
432
+ private static narrowWideFor;
414
433
  private cellCount;
415
434
  }
416
435
  declare const _default: TSPLCommandGenerator;
@@ -436,6 +455,8 @@ type index$3_TSPLCommand = TSPLCommand;
436
455
  declare const index$3_TSPLCommand: typeof TSPLCommand;
437
456
  type index$3_TSPLCommandGroup = TSPLCommandGroup;
438
457
  declare const index$3_TSPLCommandGroup: typeof TSPLCommandGroup;
458
+ type index$3_TSPLDensityCommand = TSPLDensityCommand;
459
+ declare const index$3_TSPLDensityCommand: typeof TSPLDensityCommand;
439
460
  type index$3_TSPLDiagonal = TSPLDiagonal;
440
461
  declare const index$3_TSPLDiagonal: typeof TSPLDiagonal;
441
462
  type index$3_TSPLDirectionCommand = TSPLDirectionCommand;
@@ -460,7 +481,7 @@ type index$3_TSPLVisualCommand = TSPLVisualCommand;
460
481
  declare const index$3_TSPLVisualCommand: typeof TSPLVisualCommand;
461
482
  declare const index$3_alignmentToNumber: typeof alignmentToNumber;
462
483
  declare namespace index$3 {
463
- export { type index$3_Alignment as Alignment, type index$3_AutoManual as AutoManual, type index$3_BarcodeHumanReable as BarcodeHumanReable, type index$3_BarcodeType as BarcodeType, type index$3_ECCLevel as ECCLevel, type index$3_GraphicMode as GraphicMode, type index$3_LabelDirection as LabelDirection, type index$3_QRModel as QRModel, type index$3_Rotation as Rotation, index$3_TSPLBarCommand as TSPLBarCommand, index$3_TSPLBitmapCommand as TSPLBitmapCommand, index$3_TSPLBlockCommand as TSPLBlockCommand, index$3_TSPLCLSCommand as TSPLCLSCommand, index$3_TSPLCommand as TSPLCommand, index$3_TSPLCommandGroup as TSPLCommandGroup, index$3_TSPLDiagonal as TSPLDiagonal, index$3_TSPLDirectionCommand as TSPLDirectionCommand, index$3_TSPLDisplay as TSPLDisplay, index$3_TSPLDownload as TSPLDownload, index$3_TSPLGapCommand as TSPLGapCommand, index$3_TSPLPrintCommand as TSPLPrintCommand, index$3_TSPLQRCommand as TSPLQRCommand, index$3_TSPLRawCommand as TSPLRawCommand, index$3_TSPLSizeCommand as TSPLSizeCommand, index$3_TSPLTextCommand as TSPLTextCommand, index$3_TSPLVisualCommand as TSPLVisualCommand, index$3_alignmentToNumber as alignmentToNumber, _default as commandGenerator };
484
+ export { type index$3_Alignment as Alignment, type index$3_AutoManual as AutoManual, type index$3_BarcodeHumanReable as BarcodeHumanReable, type index$3_BarcodeType as BarcodeType, type index$3_ECCLevel as ECCLevel, type index$3_GraphicMode as GraphicMode, type index$3_LabelDirection as LabelDirection, type index$3_QRModel as QRModel, type index$3_Rotation as Rotation, index$3_TSPLBarCommand as TSPLBarCommand, index$3_TSPLBitmapCommand as TSPLBitmapCommand, index$3_TSPLBlockCommand as TSPLBlockCommand, index$3_TSPLCLSCommand as TSPLCLSCommand, index$3_TSPLCommand as TSPLCommand, index$3_TSPLCommandGroup as TSPLCommandGroup, index$3_TSPLDensityCommand as TSPLDensityCommand, index$3_TSPLDiagonal as TSPLDiagonal, index$3_TSPLDirectionCommand as TSPLDirectionCommand, index$3_TSPLDisplay as TSPLDisplay, index$3_TSPLDownload as TSPLDownload, index$3_TSPLGapCommand as TSPLGapCommand, index$3_TSPLPrintCommand as TSPLPrintCommand, index$3_TSPLQRCommand as TSPLQRCommand, index$3_TSPLRawCommand as TSPLRawCommand, index$3_TSPLSizeCommand as TSPLSizeCommand, index$3_TSPLTextCommand as TSPLTextCommand, index$3_TSPLVisualCommand as TSPLVisualCommand, index$3_alignmentToNumber as alignmentToNumber, _default as commandGenerator };
464
485
  }
465
486
 
466
487
  type Point = {
@@ -502,6 +523,8 @@ type PrintConfig = {
502
523
  /** Width of the text in dots */
503
524
  textWidth: (text: string, font: FontOption) => number;
504
525
  getFontName: (font: FontOption) => string;
526
+ /** Factor to correct text width measurement vs printer rendering (default 1.0, typical 0.9-1.0) */
527
+ textWidthCorrectionFactor: number;
505
528
  };
506
529
  /**
507
530
  * A component that can be directly printed to label printer
@@ -547,16 +570,25 @@ declare class Label extends Printable {
547
570
  private readonly unitSystem;
548
571
  private fonts;
549
572
  private dpi;
573
+ private density;
550
574
  /**
551
575
  * List of fields on the label
552
576
  */
553
577
  private fields;
554
578
  private fontCounter;
579
+ private _textWidthCorrectionFactor;
555
580
  /**
556
581
  * Configuration used when generating commands
557
582
  */
558
583
  get printConfig(): PrintConfig;
559
- constructor(width: number, height: number, dimensionUnit?: UnitSystem, dpi?: number);
584
+ /**
585
+ * Sets a correction factor for text width measurement.
586
+ * Values < 1.0 make text wrap less aggressively (more chars per line).
587
+ * Useful when the printer renders text narrower than fontkit measures.
588
+ * @param factor Correction factor (default 1.0, typical range 0.9-1.0)
589
+ */
590
+ setTextWidthCorrectionFactor(factor: number): void;
591
+ constructor(width: number, height: number, dimensionUnit?: UnitSystem, dpi?: number, density?: number);
560
592
  commandForLanguage(language: PrinterLanguage, config?: PrintConfig): Promise<Command>;
561
593
  /**
562
594
  * Place fields to a label
@@ -640,7 +672,6 @@ declare class Text extends LabelField {
640
672
  private type;
641
673
  private context;
642
674
  private readonly lineSpacing;
643
- private endsWithBreak;
644
675
  /**
645
676
  * Width of the text.
646
677
  * If set, the text will be clipped to this size
@@ -651,6 +682,7 @@ declare class Text extends LabelField {
651
682
  * Height of the text box, if empty and the type is multiline, the box can grow infinitely
652
683
  */
653
684
  private height;
685
+ private endsWithBreak;
654
686
  constructor(content: string, x: number, y: number, formatted?: boolean);
655
687
  /**
656
688
  * Sets the field to single line
@@ -707,10 +739,20 @@ declare class BarCode extends LabelField {
707
739
  private readonly y;
708
740
  private readonly type;
709
741
  private readonly height;
742
+ private readonly barWidth;
710
743
  private rotation;
711
744
  private humanReadable;
712
745
  private readonly alignment;
713
- constructor(content: string, x: number, y: number, type: BarcodeType, height: number);
746
+ /**
747
+ * @param content Content to encode
748
+ * @param x X coordinate in dots
749
+ * @param y Y coordinate in dots
750
+ * @param type Barcode symbology
751
+ * @param height Height of the barcode in dots
752
+ * @param barWidth Width of the narrow bar element in dots. The wide element width is
753
+ * calculated automatically based on the symbology's standard ratio.
754
+ */
755
+ constructor(content: string, x: number, y: number, type: BarcodeType, height: number, barWidth?: number);
714
756
  setRotation(rotation: Rotation): void;
715
757
  setHumanReadable(humanReadable: BarcodeHumanReable): void;
716
758
  commandForLanguage(language: PrinterLanguage, _config?: PrintConfig | undefined): Promise<Command>;
package/dist/index.d.ts CHANGED
@@ -102,7 +102,7 @@ interface CommandGenerator<T extends Command> {
102
102
  line: (start: Point, end: Point, thickness: number) => T;
103
103
  image: (image: BitmapLike, x: number, y: number, mode?: GraphicMode) => T;
104
104
  qrCode: (content: string, width: number, x: number, y: number) => T;
105
- barCode: (content: string, x: number, y: number, type: BarcodeType, height: number, rotation: Rotation, humanReadable: BarcodeHumanReable, alignment: Alignment) => T;
105
+ barCode: (content: string, x: number, y: number, type: BarcodeType, height: number, rotation: Rotation, humanReadable: BarcodeHumanReable, alignment: Alignment, barWidth?: number) => T;
106
106
  /**
107
107
  * Should instruct the printer to display the image of the label on its screen instead of printing it
108
108
  */
@@ -110,7 +110,7 @@ interface CommandGenerator<T extends Command> {
110
110
  /**
111
111
  * This should generate the needed commands to set up a label before printing
112
112
  */
113
- setUp: (width: number, height: number, gap: number, offset: number, direction: LabelDirection, mirror: boolean, unitSystem: UnitSystem) => T;
113
+ setUp: (width: number, height: number, gap: number, offset: number, direction: LabelDirection, mirror: boolean, unitSystem: UnitSystem, density: number) => T;
114
114
  }
115
115
 
116
116
  /**
@@ -162,7 +162,7 @@ type LabelDirection = "normal" | "inverse";
162
162
  type ECCLevel = "L" | "M" | "Q" | "H";
163
163
  type AutoManual = "A" | "M";
164
164
  type QRModel = "M1" | "M2";
165
- type BarcodeType = "CODE128" | "EAN13" | "EAN8" | "EAN5" | "EAN2" | "UPC" | "CODE39" | "ITF14" | "MSI10" | "MSI11" | "MSI1010" | "MSI1110" | "pharmacode" | "codabar";
165
+ type BarcodeType = "128" | "EAN128" | "25" | "25C" | "39" | "39C" | "93" | "EAN13" | "EAN13+2" | "EAN13+5" | "EAN8" | "EAN8+2" | "EAN8+5" | "CODA" | "POST" | "UPCA" | "UPCA+2" | "UPCA+5" | "UPCE" | "UPCE+2" | "UPCE+5" | "CPOST" | "MSI" | "MSIC" | "PLESSEY" | "ITF14" | "EAN14" | "11" | "TELEPEN" | "TELEPENN" | "PLANET" | "CODE49" | "DPI" | "DPL";
166
166
  type BarcodeHumanReable = "none" | "left" | "right" | "center";
167
167
 
168
168
  /**
@@ -397,6 +397,16 @@ declare class TSPLDiagonal extends TSPLCommand {
397
397
  get commandString(): string;
398
398
  }
399
399
 
400
+ /**
401
+ * Clear the image buffer
402
+ * {@link /documentsions/TSPL.pdf}
403
+ */
404
+ declare class TSPLDensityCommand extends TSPLCommand {
405
+ private density;
406
+ constructor(density: number);
407
+ get commandString(): string;
408
+ }
409
+
400
410
  /**
401
411
  * Command generator for tspl commands
402
412
  */
@@ -405,12 +415,21 @@ declare class TSPLCommandGenerator implements CommandGenerator<TSPLCommand> {
405
415
  print(sets: number, copiesPerSet: number): TSPLCommand;
406
416
  text(content: string, x: number, y: number, font: string | "default", size: number): TSPLCommand;
407
417
  upload(name: string, data: ArrayBuffer | Uint8Array): TSPLCommand;
408
- setUp(width: number, height: number, gap: number, offset: number, direction: LabelDirection, mirror: boolean | undefined, unitSystem: UnitSystem): TSPLCommand;
418
+ setUp(width: number, height: number, gap: number, offset: number, direction: LabelDirection, mirror: boolean | undefined, unitSystem: UnitSystem, density: number): TSPLCommand;
409
419
  display(): TSPLCommandGroup;
410
420
  line(start: Point, end: Point, thickness: number): TSPLCommand;
411
421
  image(image: BitmapLike, x: number, y: number, mode?: GraphicMode | undefined): TSPLCommand;
412
422
  qrCode(content: string, width: number, x: number, y: number): TSPLCommand;
413
- barCode(content: string, x: number, y: number, type: BarcodeType, height: number, rotation: Rotation, humanReadable: BarcodeHumanReable, alignment: Alignment): TSPLCommand;
423
+ barCode(content: string, x: number, y: number, type: BarcodeType, height: number, rotation: Rotation, humanReadable: BarcodeHumanReable, alignment: Alignment, barWidth?: number): TSPLCommand;
424
+ /**
425
+ * Calculates the narrow and wide element widths for a barcode type based on the
426
+ * TSPL documentation's standard narrow:wide ratios.
427
+ *
428
+ * Types that only support 1:1 (continuous barcodes like CODE128, EAN, UPC) get
429
+ * narrow === wide. All other types use the 1:3 ratio, which is the industry
430
+ * standard for variable-ratio symbologies (CODE39, ITF14, codabar, MSI…).
431
+ */
432
+ private static narrowWideFor;
414
433
  private cellCount;
415
434
  }
416
435
  declare const _default: TSPLCommandGenerator;
@@ -436,6 +455,8 @@ type index$3_TSPLCommand = TSPLCommand;
436
455
  declare const index$3_TSPLCommand: typeof TSPLCommand;
437
456
  type index$3_TSPLCommandGroup = TSPLCommandGroup;
438
457
  declare const index$3_TSPLCommandGroup: typeof TSPLCommandGroup;
458
+ type index$3_TSPLDensityCommand = TSPLDensityCommand;
459
+ declare const index$3_TSPLDensityCommand: typeof TSPLDensityCommand;
439
460
  type index$3_TSPLDiagonal = TSPLDiagonal;
440
461
  declare const index$3_TSPLDiagonal: typeof TSPLDiagonal;
441
462
  type index$3_TSPLDirectionCommand = TSPLDirectionCommand;
@@ -460,7 +481,7 @@ type index$3_TSPLVisualCommand = TSPLVisualCommand;
460
481
  declare const index$3_TSPLVisualCommand: typeof TSPLVisualCommand;
461
482
  declare const index$3_alignmentToNumber: typeof alignmentToNumber;
462
483
  declare namespace index$3 {
463
- export { type index$3_Alignment as Alignment, type index$3_AutoManual as AutoManual, type index$3_BarcodeHumanReable as BarcodeHumanReable, type index$3_BarcodeType as BarcodeType, type index$3_ECCLevel as ECCLevel, type index$3_GraphicMode as GraphicMode, type index$3_LabelDirection as LabelDirection, type index$3_QRModel as QRModel, type index$3_Rotation as Rotation, index$3_TSPLBarCommand as TSPLBarCommand, index$3_TSPLBitmapCommand as TSPLBitmapCommand, index$3_TSPLBlockCommand as TSPLBlockCommand, index$3_TSPLCLSCommand as TSPLCLSCommand, index$3_TSPLCommand as TSPLCommand, index$3_TSPLCommandGroup as TSPLCommandGroup, index$3_TSPLDiagonal as TSPLDiagonal, index$3_TSPLDirectionCommand as TSPLDirectionCommand, index$3_TSPLDisplay as TSPLDisplay, index$3_TSPLDownload as TSPLDownload, index$3_TSPLGapCommand as TSPLGapCommand, index$3_TSPLPrintCommand as TSPLPrintCommand, index$3_TSPLQRCommand as TSPLQRCommand, index$3_TSPLRawCommand as TSPLRawCommand, index$3_TSPLSizeCommand as TSPLSizeCommand, index$3_TSPLTextCommand as TSPLTextCommand, index$3_TSPLVisualCommand as TSPLVisualCommand, index$3_alignmentToNumber as alignmentToNumber, _default as commandGenerator };
484
+ export { type index$3_Alignment as Alignment, type index$3_AutoManual as AutoManual, type index$3_BarcodeHumanReable as BarcodeHumanReable, type index$3_BarcodeType as BarcodeType, type index$3_ECCLevel as ECCLevel, type index$3_GraphicMode as GraphicMode, type index$3_LabelDirection as LabelDirection, type index$3_QRModel as QRModel, type index$3_Rotation as Rotation, index$3_TSPLBarCommand as TSPLBarCommand, index$3_TSPLBitmapCommand as TSPLBitmapCommand, index$3_TSPLBlockCommand as TSPLBlockCommand, index$3_TSPLCLSCommand as TSPLCLSCommand, index$3_TSPLCommand as TSPLCommand, index$3_TSPLCommandGroup as TSPLCommandGroup, index$3_TSPLDensityCommand as TSPLDensityCommand, index$3_TSPLDiagonal as TSPLDiagonal, index$3_TSPLDirectionCommand as TSPLDirectionCommand, index$3_TSPLDisplay as TSPLDisplay, index$3_TSPLDownload as TSPLDownload, index$3_TSPLGapCommand as TSPLGapCommand, index$3_TSPLPrintCommand as TSPLPrintCommand, index$3_TSPLQRCommand as TSPLQRCommand, index$3_TSPLRawCommand as TSPLRawCommand, index$3_TSPLSizeCommand as TSPLSizeCommand, index$3_TSPLTextCommand as TSPLTextCommand, index$3_TSPLVisualCommand as TSPLVisualCommand, index$3_alignmentToNumber as alignmentToNumber, _default as commandGenerator };
464
485
  }
465
486
 
466
487
  type Point = {
@@ -502,6 +523,8 @@ type PrintConfig = {
502
523
  /** Width of the text in dots */
503
524
  textWidth: (text: string, font: FontOption) => number;
504
525
  getFontName: (font: FontOption) => string;
526
+ /** Factor to correct text width measurement vs printer rendering (default 1.0, typical 0.9-1.0) */
527
+ textWidthCorrectionFactor: number;
505
528
  };
506
529
  /**
507
530
  * A component that can be directly printed to label printer
@@ -547,16 +570,25 @@ declare class Label extends Printable {
547
570
  private readonly unitSystem;
548
571
  private fonts;
549
572
  private dpi;
573
+ private density;
550
574
  /**
551
575
  * List of fields on the label
552
576
  */
553
577
  private fields;
554
578
  private fontCounter;
579
+ private _textWidthCorrectionFactor;
555
580
  /**
556
581
  * Configuration used when generating commands
557
582
  */
558
583
  get printConfig(): PrintConfig;
559
- constructor(width: number, height: number, dimensionUnit?: UnitSystem, dpi?: number);
584
+ /**
585
+ * Sets a correction factor for text width measurement.
586
+ * Values < 1.0 make text wrap less aggressively (more chars per line).
587
+ * Useful when the printer renders text narrower than fontkit measures.
588
+ * @param factor Correction factor (default 1.0, typical range 0.9-1.0)
589
+ */
590
+ setTextWidthCorrectionFactor(factor: number): void;
591
+ constructor(width: number, height: number, dimensionUnit?: UnitSystem, dpi?: number, density?: number);
560
592
  commandForLanguage(language: PrinterLanguage, config?: PrintConfig): Promise<Command>;
561
593
  /**
562
594
  * Place fields to a label
@@ -640,7 +672,6 @@ declare class Text extends LabelField {
640
672
  private type;
641
673
  private context;
642
674
  private readonly lineSpacing;
643
- private endsWithBreak;
644
675
  /**
645
676
  * Width of the text.
646
677
  * If set, the text will be clipped to this size
@@ -651,6 +682,7 @@ declare class Text extends LabelField {
651
682
  * Height of the text box, if empty and the type is multiline, the box can grow infinitely
652
683
  */
653
684
  private height;
685
+ private endsWithBreak;
654
686
  constructor(content: string, x: number, y: number, formatted?: boolean);
655
687
  /**
656
688
  * Sets the field to single line
@@ -707,10 +739,20 @@ declare class BarCode extends LabelField {
707
739
  private readonly y;
708
740
  private readonly type;
709
741
  private readonly height;
742
+ private readonly barWidth;
710
743
  private rotation;
711
744
  private humanReadable;
712
745
  private readonly alignment;
713
- constructor(content: string, x: number, y: number, type: BarcodeType, height: number);
746
+ /**
747
+ * @param content Content to encode
748
+ * @param x X coordinate in dots
749
+ * @param y Y coordinate in dots
750
+ * @param type Barcode symbology
751
+ * @param height Height of the barcode in dots
752
+ * @param barWidth Width of the narrow bar element in dots. The wide element width is
753
+ * calculated automatically based on the symbology's standard ratio.
754
+ */
755
+ constructor(content: string, x: number, y: number, type: BarcodeType, height: number, barWidth?: number);
714
756
  setRotation(rotation: Rotation): void;
715
757
  setHumanReadable(humanReadable: BarcodeHumanReable): void;
716
758
  commandForLanguage(language: PrinterLanguage, _config?: PrintConfig | undefined): Promise<Command>;
package/dist/index.js CHANGED
@@ -193,6 +193,7 @@ __export(tspl_exports, {
193
193
  TSPLCLSCommand: () => TSPLCLSCommand,
194
194
  TSPLCommand: () => TSPLCommand,
195
195
  TSPLCommandGroup: () => TSPLCommandGroup,
196
+ TSPLDensityCommand: () => TSPLDensityCommand,
196
197
  TSPLDiagonal: () => TSPLDiagonal,
197
198
  TSPLDirectionCommand: () => TSPLDirectionCommand,
198
199
  TSPLDisplay: () => TSPLDisplay,
@@ -270,11 +271,6 @@ function dotToPoint(dots, dpi) {
270
271
  const inch = dots / dpi;
271
272
  return Math.round(inch * pointsPerInch);
272
273
  }
273
- function pointsToDots(points, dpi) {
274
- const pointsPerInch2 = 72;
275
- const dots = points * dpi / pointsPerInch2;
276
- return dots;
277
- }
278
274
 
279
275
  // src/helpers/ImageDataParser.ts
280
276
  function parsePNG(buffer2) {
@@ -1409,6 +1405,17 @@ var TSPLDiagonal = class extends TSPLCommand {
1409
1405
  }
1410
1406
  };
1411
1407
 
1408
+ // src/commands/tspl/commands/basic/TSPLDensityCommand.ts
1409
+ var TSPLDensityCommand = class extends TSPLCommand {
1410
+ constructor(density) {
1411
+ super();
1412
+ this.density = density;
1413
+ }
1414
+ get commandString() {
1415
+ return `DENSITY ${this.density}`;
1416
+ }
1417
+ };
1418
+
1412
1419
  // src/commands/tspl/commands/basic/TSPLBarcodeCommand.ts
1413
1420
  var TSPLBarcodeCommand = class _TSPLBarcodeCommand extends TSPLVisualCommand {
1414
1421
  /**
@@ -1495,7 +1502,7 @@ var QRLengthMapping = {
1495
1502
  };
1496
1503
 
1497
1504
  // src/commands/tspl/TSPLCommandGenerator.ts
1498
- var TSPLCommandGenerator = class {
1505
+ var TSPLCommandGenerator = class _TSPLCommandGenerator {
1499
1506
  commandGroup(commands) {
1500
1507
  return new TSPLCommandGroup(commands);
1501
1508
  }
@@ -1509,11 +1516,12 @@ var TSPLCommandGenerator = class {
1509
1516
  upload(name, data) {
1510
1517
  return new TSPLDownload(name, data);
1511
1518
  }
1512
- setUp(width, height, gap, offset, direction, mirror = false, unitSystem) {
1519
+ setUp(width, height, gap, offset, direction, mirror = false, unitSystem, density) {
1513
1520
  const commands = [
1514
1521
  new TSPLSizeCommand(width, height, unitSystem),
1515
1522
  new TSPLGapCommand(gap, offset, unitSystem),
1516
1523
  new TSPLDirectionCommand(direction, mirror),
1524
+ new TSPLDensityCommand(density),
1517
1525
  new TSPLCLSCommand()
1518
1526
  ];
1519
1527
  return new TSPLCommandGroup(commands);
@@ -1535,8 +1543,41 @@ var TSPLCommandGenerator = class {
1535
1543
  const cellWidth = Math.round(width / cellCount);
1536
1544
  return new TSPLQRCommand(`A${content}`, x, y, cellWidth, "H", "M");
1537
1545
  }
1538
- barCode(content, x, y, type, height, rotation, humanReadable, alignment) {
1539
- return new TSPLBarcodeCommand(x, y, type, height, 1, 1, content, rotation, humanReadable, alignment);
1546
+ barCode(content, x, y, type, height, rotation, humanReadable, alignment, barWidth = 2) {
1547
+ const { narrow, wide } = _TSPLCommandGenerator.narrowWideFor(type, barWidth);
1548
+ return new TSPLBarcodeCommand(x, y, type, height, narrow, wide, content, rotation, humanReadable, alignment);
1549
+ }
1550
+ /**
1551
+ * Calculates the narrow and wide element widths for a barcode type based on the
1552
+ * TSPL documentation's standard narrow:wide ratios.
1553
+ *
1554
+ * Types that only support 1:1 (continuous barcodes like CODE128, EAN, UPC) get
1555
+ * narrow === wide. All other types use the 1:3 ratio, which is the industry
1556
+ * standard for variable-ratio symbologies (CODE39, ITF14, codabar, MSI…).
1557
+ */
1558
+ static narrowWideFor(type, barWidth) {
1559
+ switch (type) {
1560
+ case "25":
1561
+ case "25C":
1562
+ case "39":
1563
+ case "39C":
1564
+ case "93":
1565
+ case "CODA":
1566
+ case "MSI":
1567
+ case "MSIC":
1568
+ case "PLESSEY":
1569
+ case "ITF14":
1570
+ case "11":
1571
+ case "TELEPEN":
1572
+ case "TELEPENN":
1573
+ case "DPI":
1574
+ case "DPL":
1575
+ return { narrow: barWidth, wide: 3 * barWidth };
1576
+ case "CPOST":
1577
+ return { narrow: barWidth, wide: barWidth * 7 / 3 };
1578
+ default:
1579
+ return { narrow: barWidth, wide: barWidth };
1580
+ }
1540
1581
  }
1541
1582
  cellCount(content) {
1542
1583
  const limits = Object.keys(QRLengthMapping).map((limit) => Number(limit)).sort((a, b) => a - b);
@@ -1652,6 +1693,8 @@ var StringUtils = class {
1652
1693
  }
1653
1694
  };
1654
1695
  var isWhitespace = (text) => text.trim() === "";
1696
+ var BREAK_AFTER_CHARS = /* @__PURE__ */ new Set([",", ";", ":", "."]);
1697
+ var isBreakAfterChar = (ch) => BREAK_AFTER_CHARS.has(ch);
1655
1698
 
1656
1699
  // src/helpers/USBUtils.ts
1657
1700
  var unsupportedUsbError = "usb-unsupported";
@@ -2068,7 +2111,6 @@ var TSPLPrinter = class _TSPLPrinter extends Printer {
2068
2111
  static try(device) {
2069
2112
  return __async(this, null, function* () {
2070
2113
  if (!device.opened) yield device.openAndConfigure();
2071
- console.log("Response: ", device.opened);
2072
2114
  const testCommand = new TSPLRawCommand("~!I");
2073
2115
  yield testCommand.writeTo(device);
2074
2116
  const response = yield device.readString(64);
@@ -2401,18 +2443,21 @@ var DEFAULT_FONT_WEIGHT = 400;
2401
2443
  var DEFAULT_FONT_STYLE = "normal";
2402
2444
  var FONT_PREFIX = "f";
2403
2445
  var Label = class extends Printable {
2404
- constructor(width, height, dimensionUnit = "metric", dpi = 203) {
2446
+ constructor(width, height, dimensionUnit = "metric", dpi = 203, density = 8) {
2405
2447
  super();
2406
2448
  this.fonts = {};
2449
+ this.density = 8;
2407
2450
  /**
2408
2451
  * List of fields on the label
2409
2452
  */
2410
2453
  this.fields = [];
2411
2454
  this.fontCounter = 0;
2455
+ this._textWidthCorrectionFactor = 0.935;
2412
2456
  this.width = width;
2413
2457
  this.height = height;
2414
2458
  this.unitSystem = dimensionUnit;
2415
2459
  this.dpi = dpi;
2460
+ this.density = density;
2416
2461
  }
2417
2462
  /**
2418
2463
  * Configuration used when generating commands
@@ -2425,16 +2470,24 @@ var Label = class extends Printable {
2425
2470
  if (indexedFont == null) {
2426
2471
  return text.length * font.size;
2427
2472
  } else {
2428
- const size = dotToPoint(font.size, this.dpi);
2429
2473
  const fontObject = indexedFont.font;
2430
2474
  const run = fontObject.layout(text);
2431
- const scaledWidth = size * run.advanceWidth / fontObject.unitsPerEm;
2432
- return pointsToDots(scaledWidth, this.dpi);
2475
+ return font.size * this._textWidthCorrectionFactor * run.advanceWidth / fontObject.unitsPerEm;
2433
2476
  }
2434
2477
  },
2435
- getFontName: this.getFontName.bind(this)
2478
+ getFontName: this.getFontName.bind(this),
2479
+ textWidthCorrectionFactor: this._textWidthCorrectionFactor
2436
2480
  };
2437
2481
  }
2482
+ /**
2483
+ * Sets a correction factor for text width measurement.
2484
+ * Values < 1.0 make text wrap less aggressively (more chars per line).
2485
+ * Useful when the printer renders text narrower than fontkit measures.
2486
+ * @param factor Correction factor (default 1.0, typical range 0.9-1.0)
2487
+ */
2488
+ setTextWidthCorrectionFactor(factor) {
2489
+ this._textWidthCorrectionFactor = factor;
2490
+ }
2438
2491
  commandForLanguage(language, config) {
2439
2492
  return __async(this, null, function* () {
2440
2493
  const configuration = config != null ? config : this.printConfig;
@@ -2515,7 +2568,16 @@ var Label = class extends Printable {
2515
2568
  return __async(this, null, function* () {
2516
2569
  const commands = [
2517
2570
  this.fontUploadCommands(generator),
2518
- generator.setUp(this.width, this.height, gap, gapOffset, direction, mirror, this.unitSystem),
2571
+ generator.setUp(
2572
+ this.width,
2573
+ this.height,
2574
+ gap,
2575
+ gapOffset,
2576
+ direction,
2577
+ mirror,
2578
+ this.unitSystem,
2579
+ this.density
2580
+ ),
2519
2581
  yield this.commandForLanguage(language, this.printConfig)
2520
2582
  ];
2521
2583
  return commands;
@@ -2803,22 +2865,91 @@ var Text = class extends LabelField {
2803
2865
  commands.push(this.textCommand(remainingContent, x, y, font, features));
2804
2866
  remainingContent = "";
2805
2867
  } else {
2806
- let rows = remainingWidth / rowWidth;
2807
- rowWidth = this.width;
2808
- let rowEndIndex = Math.floor(remainingContent.length / rows);
2868
+ let lo = 0, hi = remainingContent.length - 1;
2869
+ let rowEndIndex = -1;
2870
+ while (lo <= hi) {
2871
+ const mid = Math.floor((lo + hi) / 2);
2872
+ if (textWidhtFunction(remainingContent.substring(0, mid + 1), font) <= rowWidth) {
2873
+ rowEndIndex = mid;
2874
+ lo = mid + 1;
2875
+ } else {
2876
+ hi = mid - 1;
2877
+ }
2878
+ }
2809
2879
  let originalRowEndIndex = rowEndIndex;
2810
- if (rowEndIndex == 0) {
2880
+ rowWidth = this.width;
2881
+ if (rowEndIndex < 0) {
2811
2882
  x = this.x;
2812
2883
  y += font.size + this.lineSpacing;
2813
2884
  continue;
2814
2885
  }
2815
- while (!(!isWhitespace(remainingContent.charAt(rowEndIndex)) && (rowEndIndex == remainingContent.length - 1 || isWhitespace(remainingContent.charAt(rowEndIndex + 1)))) && rowEndIndex > 0) {
2886
+ while (!(!isWhitespace(remainingContent.charAt(rowEndIndex)) && (rowEndIndex == remainingContent.length - 1 || isWhitespace(remainingContent.charAt(rowEndIndex + 1))) || isBreakAfterChar(remainingContent.charAt(rowEndIndex))) && rowEndIndex > 0) {
2816
2887
  rowEndIndex--;
2817
2888
  }
2818
2889
  let nextRowStartIndex = rowEndIndex + 1;
2819
- if (rowEndIndex == 0) {
2890
+ const foundWordBoundary = !isWhitespace(remainingContent.charAt(rowEndIndex)) && (rowEndIndex == remainingContent.length - 1 || isWhitespace(remainingContent.charAt(rowEndIndex + 1))) || isBreakAfterChar(remainingContent.charAt(rowEndIndex));
2891
+ const MIN_WORD_BREAK_CHARS = 2;
2892
+ if (!foundWordBoundary) {
2820
2893
  rowEndIndex = originalRowEndIndex;
2821
2894
  nextRowStartIndex = originalRowEndIndex + 1;
2895
+ let wordEnd = originalRowEndIndex + 1;
2896
+ while (wordEnd < remainingContent.length && !isWhitespace(remainingContent.charAt(wordEnd))) {
2897
+ wordEnd++;
2898
+ }
2899
+ const charsOnNext = wordEnd - originalRowEndIndex - 1;
2900
+ if (charsOnNext > 0 && charsOnNext < MIN_WORD_BREAK_CHARS) {
2901
+ const adjusted = originalRowEndIndex - (MIN_WORD_BREAK_CHARS - charsOnNext);
2902
+ if (adjusted >= 0) {
2903
+ rowEndIndex = adjusted;
2904
+ nextRowStartIndex = adjusted + 1;
2905
+ }
2906
+ }
2907
+ } else if (originalRowEndIndex > rowEndIndex) {
2908
+ let wordStart = rowEndIndex + 1;
2909
+ while (wordStart <= originalRowEndIndex && isWhitespace(remainingContent.charAt(wordStart))) {
2910
+ wordStart++;
2911
+ }
2912
+ let fullWordEnd = wordStart;
2913
+ while (fullWordEnd < remainingContent.length && !isWhitespace(remainingContent.charAt(fullWordEnd))) {
2914
+ fullWordEnd++;
2915
+ }
2916
+ const lineWithFullWord = textWidhtFunction(remainingContent.substring(0, fullWordEnd), font);
2917
+ if (lineWithFullWord <= rowWidth) {
2918
+ rowEndIndex = fullWordEnd - 1;
2919
+ nextRowStartIndex = fullWordEnd;
2920
+ } else {
2921
+ let lo2 = wordStart, hi2 = fullWordEnd - 1;
2922
+ let midBreak = -1;
2923
+ while (lo2 <= hi2) {
2924
+ const mid2 = Math.floor((lo2 + hi2) / 2);
2925
+ if (textWidhtFunction(remainingContent.substring(0, mid2 + 1), font) <= rowWidth) {
2926
+ midBreak = mid2;
2927
+ lo2 = mid2 + 1;
2928
+ } else {
2929
+ hi2 = mid2 - 1;
2930
+ }
2931
+ }
2932
+ let usedMidWordBreak = false;
2933
+ if (midBreak >= wordStart) {
2934
+ let charsOnLine = midBreak - wordStart + 1;
2935
+ let charsOnNext = fullWordEnd - midBreak - 1;
2936
+ if (charsOnNext > 0 && charsOnNext < MIN_WORD_BREAK_CHARS) {
2937
+ midBreak -= MIN_WORD_BREAK_CHARS - charsOnNext;
2938
+ charsOnLine = midBreak - wordStart + 1;
2939
+ }
2940
+ if (charsOnLine >= MIN_WORD_BREAK_CHARS) {
2941
+ rowEndIndex = midBreak;
2942
+ nextRowStartIndex = midBreak + 1;
2943
+ usedMidWordBreak = true;
2944
+ }
2945
+ }
2946
+ if (!usedMidWordBreak) {
2947
+ nextRowStartIndex = rowEndIndex + 1;
2948
+ while (isWhitespace(remainingContent.charAt(nextRowStartIndex)) && nextRowStartIndex < remainingContent.length) {
2949
+ nextRowStartIndex++;
2950
+ }
2951
+ }
2952
+ }
2822
2953
  } else {
2823
2954
  while (isWhitespace(remainingContent.charAt(nextRowStartIndex)) && nextRowStartIndex < remainingContent.length) {
2824
2955
  nextRowStartIndex++;
@@ -2917,13 +3048,23 @@ var Text = class extends LabelField {
2917
3048
 
2918
3049
  // src/labels/fields/BarCode.ts
2919
3050
  var BarCode = class extends LabelField {
2920
- constructor(content, x, y, type, height) {
3051
+ /**
3052
+ * @param content Content to encode
3053
+ * @param x X coordinate in dots
3054
+ * @param y Y coordinate in dots
3055
+ * @param type Barcode symbology
3056
+ * @param height Height of the barcode in dots
3057
+ * @param barWidth Width of the narrow bar element in dots. The wide element width is
3058
+ * calculated automatically based on the symbology's standard ratio.
3059
+ */
3060
+ constructor(content, x, y, type, height, barWidth = 2) {
2921
3061
  super();
2922
3062
  this.content = content;
2923
3063
  this.x = x;
2924
3064
  this.y = y;
2925
3065
  this.type = type;
2926
3066
  this.height = height;
3067
+ this.barWidth = barWidth;
2927
3068
  this.rotation = 0;
2928
3069
  this.humanReadable = "none";
2929
3070
  this.alignment = "left";
@@ -2936,7 +3077,7 @@ var BarCode = class extends LabelField {
2936
3077
  }
2937
3078
  commandForLanguage(language, _config) {
2938
3079
  return __async(this, null, function* () {
2939
- return yield this.commandGeneratorFor(language).barCode(this.content, this.x, this.y, this.type, this.height, this.rotation, this.humanReadable, this.alignment);
3080
+ return yield this.commandGeneratorFor(language).barCode(this.content, this.x, this.y, this.type, this.height, this.rotation, this.humanReadable, this.alignment, this.barWidth);
2940
3081
  });
2941
3082
  }
2942
3083
  };