pdf-lib-extended 1.0.17 → 1.0.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdf-lib-extended",
3
- "version": "1.0.17",
3
+ "version": "1.0.20",
4
4
  "description": "This project extends the capabilities of the pdf-lib JavaScript library by providing a set of helper functions that simplify common PDF manipulation tasks. It includes utilities for drawing and formatting text, images, and shapes within PDF documents, allowing for more advanced customization and automation. The class-based architecture, designed as a toolkit, ensures that developers can easily integrate these enhanced features into their existing workflows. With this extension, users can streamline the creation of dynamic and complex PDFs with minimal effort.",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -464,69 +464,69 @@ class PDFLibExtended {
464
464
  * @param {import('pdf-lib').RGB} options.color - The color of the text
465
465
  * @param {number} options.opacity - The opacity of the text
466
466
  */
467
- drawParagraph(text, options = {}) {
468
- let defaultOptions = {
467
+ drawParagraph(pdf, text, options = {}) {
468
+ const defaultOptions = {
469
469
  align: "left",
470
470
  range: {
471
- left: this.getMargin().left,
472
- right: this.getCurrentPage().getWidth() - this.getMargin().right
471
+ left: pdf.getMargin().left,
472
+ right: pdf.getCurrentPage().getWidth() - pdf.getMargin().right
473
473
  },
474
- size: this.getTextSize(),
475
- color: this.getColor(),
474
+ size: pdf.getTextSize(),
475
+ color: pdf.getColor(),
476
476
  opacity: 1,
477
- padding: 0,
477
+ padding: 0, // extra spacing between lines
478
478
  wordWrap: true,
479
479
  characterWrap: false,
480
480
  ...options
481
481
  };
482
- if(options.range) this.getCurrentPage().moveTo(defaultOptions.range.left, this.getCurrentPage().getY());
483
-
484
- let maxWidth = defaultOptions.range.right - defaultOptions.range.left;
485
- let currentWidth = 0;
486
- let currentLine = "";
487
482
 
488
- if(defaultOptions.wordWrap){
489
- text = text.split(" ");
490
- }else{
491
- text = text.split("");
492
- }
483
+ // Always move to paragraph start (left edge of range)
484
+ pdf.getCurrentPage().moveTo(defaultOptions.range.left, pdf.getCurrentPage().getY());
493
485
 
494
- text.forEach((string, i) => {
495
- let wordWidth = this.getCurrentFont().widthOfTextAtSize(string, defaultOptions.size);
486
+ const maxWidth = defaultOptions.range.right - defaultOptions.range.left;
496
487
 
497
- // Check if adding this word would overflow
498
- if (currentWidth + wordWidth > maxWidth) {
499
- this.drawText(currentLine.trim(), {
500
- size: defaultOptions.size,
501
- color: defaultOptions.color,
502
- opacity: defaultOptions.opacity,
503
- align: defaultOptions.align,
504
- range: defaultOptions.range
505
- });
488
+ // Tokenize
489
+ const tokens = defaultOptions.wordWrap ? text.split(" ") : text.split("");
506
490
 
507
- // Move to the next line
508
- this.nextLine(defaultOptions.padding);
509
- this.getCurrentPage().moveTo(defaultOptions.range.left, this.getCurrentPage().getY());
510
- currentLine = "";
511
- currentWidth = 0;
512
- }
491
+ let currentLine = "";
492
+ let currentWidth = 0;
513
493
 
514
- if(defaultOptions.wordWrap){
515
- currentLine += string + " ";
516
- }else{
517
- currentLine += string;
494
+ tokens.forEach((tok, i) => {
495
+ // Build what we would append for this token on this line
496
+ const needsSpace = defaultOptions.wordWrap && currentLine.length > 0;
497
+ const piece = needsSpace ? (" " + tok) : tok;
498
+
499
+ // Measure exactly what we plan to add
500
+ const pieceWidth = pdf.getCurrentFont().widthOfTextAtSize(piece, defaultOptions.size);
501
+
502
+ // If this piece would overflow, draw current line and move down
503
+ if (currentLine && (currentWidth + pieceWidth > maxWidth)) {
504
+ pdf.drawText(currentLine, {
505
+ size: defaultOptions.size,
506
+ color: defaultOptions.color,
507
+ opacity: defaultOptions.opacity,
508
+ align: defaultOptions.align,
509
+ range: defaultOptions.range
510
+ });
511
+ pdf.nextLine(defaultOptions.padding);
512
+ pdf.getCurrentPage().moveTo(defaultOptions.range.left, pdf.getCurrentPage().getY());
513
+ currentLine = tok; // start new line with the token (no leading space)
514
+ currentWidth = pdf.getCurrentFont().widthOfTextAtSize(tok, defaultOptions.size);
515
+ } else {
516
+ // Safe to add to this line
517
+ currentLine += piece;
518
+ currentWidth += pieceWidth;
518
519
  }
519
- currentWidth += wordWidth;
520
520
 
521
- // If it's the last word, draw the remaining line
522
- if (i === text.length - 1) {
523
- this.drawText(currentLine.trim(), {
524
- size: defaultOptions.size,
525
- color: defaultOptions.color,
526
- opacity: defaultOptions.opacity,
527
- align: defaultOptions.align,
528
- range: defaultOptions.range
529
- });
521
+ // Last token: flush
522
+ if (i === tokens.length - 1 && currentLine) {
523
+ pdf.drawText(currentLine, {
524
+ size: defaultOptions.size,
525
+ color: defaultOptions.color,
526
+ opacity: defaultOptions.opacity,
527
+ align: defaultOptions.align,
528
+ range: defaultOptions.range
529
+ });
530
530
  }
531
531
  });
532
532
  }
@@ -906,16 +906,27 @@ class PDFLibExtended {
906
906
  * @param {base64} base64Image
907
907
  * @param {number} imageScale
908
908
  */
909
- async addImage(x, y, base64Image, imageScale = 1) {
909
+ async addImage(x, y, base64Image, imageScale = 1, options = {}) {
910
+ let defaultOptions = {
911
+ width: null,
912
+ height: null,
913
+ borderWidth: 2,
914
+ ...options
915
+ };
916
+
910
917
  if (base64Image.includes(",")) base64Image = base64Image.split(",")[1];
911
918
  let imageBytes = Uint8Array.from(atob(base64Image), c => c.charCodeAt(0));
912
919
  let embeddedImage = await this.getPDF().embedPng(imageBytes);
913
- let { width, height } = embeddedImage.scale(imageScale);
920
+ if(defaultOptions.width == null && defaultOptions.height == null){
921
+ let { width, height } = embeddedImage.scale(imageScale);
922
+ defaultOptions.width = width;
923
+ defaultOptions.height = height;
924
+ }
914
925
  this.getCurrentPage().drawImage(embeddedImage, {
915
926
  x: x,
916
927
  y: y,
917
- width: width,
918
- height: height,
928
+ width: defaultOptions.width,
929
+ height: defaultOptions.height,
919
930
  });
920
931
  }
921
932