pdfkit 0.17.2 → 0.19.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/js/pdfkit.es.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import stream from 'stream';
2
2
  import zlib from 'zlib';
3
- import CryptoJS from 'crypto-js';
3
+ import { concatBytes } from '@noble/hashes/utils';
4
+ import md5 from 'js-md5';
5
+ import { sha256 } from '@noble/hashes/sha2';
6
+ import { cbc, ecb } from '@noble/ciphers/aes';
4
7
  import fs from 'fs';
5
- import * as fontkit from 'fontkit';
6
- import { EventEmitter } from 'events';
8
+ import { create } from 'fontkit';
7
9
  import LineBreaker from 'linebreak';
8
- import exif from 'jpeg-exif';
9
10
  import PNG from 'png-js';
10
11
 
11
12
  class PDFAbstractReference {
@@ -15,8 +16,7 @@ class PDFAbstractReference {
15
16
  }
16
17
 
17
18
  class PDFTree {
18
- constructor() {
19
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
19
+ constructor(options = {}) {
20
20
  this._items = {};
21
21
  this.limits = typeof options.limits === 'boolean' ? options.limits : true;
22
22
  }
@@ -58,7 +58,7 @@ class SpotColor {
58
58
  this.id = 'CS' + Object.keys(doc.spotColors).length;
59
59
  this.name = name;
60
60
  this.values = [C, M, Y, K];
61
- this.ref = doc.ref(['Separation', this.name, 'DeviceCMYK', {
61
+ this.ref = doc.ref(['Separation', escapeName(this.name), 'DeviceCMYK', {
62
62
  Range: [0, 1, 0, 1, 0, 1, 0, 1],
63
63
  C0: [0, 0, 0, 0],
64
64
  C1: this.values.map(value => value / 100),
@@ -74,6 +74,10 @@ class SpotColor {
74
74
  }
75
75
 
76
76
  const pad = (str, length) => (Array(length + 1).join('0') + str).slice(-length);
77
+ const isSafeCharCode = code => {
78
+ if (code > 0x7f) return true;
79
+ return code > 0x20 && code !== 0x7f && code !== 0x23 && code !== 0x25 && code !== 0x28 && code !== 0x29 && code !== 0x2f && code !== 0x3c && code !== 0x3e && code !== 0x5b && code !== 0x5d && code !== 0x7b && code !== 0x7d;
80
+ };
77
81
  const escapableRe = /[\n\r\t\b\f()\\]/g;
78
82
  const escapable = {
79
83
  '\n': '\\n',
@@ -85,6 +89,18 @@ const escapable = {
85
89
  '(': '\\(',
86
90
  ')': '\\)'
87
91
  };
92
+ const escapeName = function (name) {
93
+ let escapedName = '';
94
+ for (const char of name) {
95
+ const code = char.charCodeAt(0);
96
+ if (isSafeCharCode(code)) {
97
+ escapedName += char;
98
+ } else {
99
+ escapedName += `#${code.toString(16).toUpperCase().padStart(2, '0')}`;
100
+ }
101
+ }
102
+ return escapedName;
103
+ };
88
104
  const swapBytes = function (buff) {
89
105
  const l = buff.length;
90
106
  if (l & 0x01) {
@@ -99,8 +115,7 @@ const swapBytes = function (buff) {
99
115
  return buff;
100
116
  };
101
117
  class PDFObject {
102
- static convert(object) {
103
- let encryptFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
118
+ static convert(object, encryptFn = null) {
104
119
  if (typeof object === 'string') {
105
120
  return `/${object}`;
106
121
  } else if (object instanceof String) {
@@ -162,8 +177,7 @@ class PDFObject {
162
177
  }
163
178
 
164
179
  class PDFReference extends PDFAbstractReference {
165
- constructor(document, id) {
166
- let data = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
180
+ constructor(document, id, data = {}) {
167
181
  super();
168
182
  this.document = document;
169
183
  this.id = id;
@@ -235,9 +249,7 @@ function PDFNumber(n) {
235
249
  }
236
250
  return fArray[0];
237
251
  }
238
- function normalizeSides(sides) {
239
- let defaultDefinition = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
240
- let transformer = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : v => v;
252
+ function normalizeSides(sides, defaultDefinition = undefined, transformer = v => v) {
241
253
  if (sides == null || typeof sides === 'object' && Object.keys(sides).length === 0) {
242
254
  sides = defaultDefinition;
243
255
  }
@@ -357,12 +369,12 @@ const SIZES = {
357
369
  TABLOID: [792.0, 1224.0]
358
370
  };
359
371
  class PDFPage {
360
- constructor(document) {
361
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
372
+ constructor(document, options = {}) {
362
373
  this.document = document;
363
374
  this._options = options;
364
375
  this.size = options.size || 'letter';
365
376
  this.layout = options.layout || 'portrait';
377
+ this.userUnit = options.userUnit || 1.0;
366
378
  const dimensions = Array.isArray(this.size) ? this.size : SIZES[this.size.toUpperCase()];
367
379
  this.width = dimensions[this.layout === 'portrait' ? 0 : 1];
368
380
  this.height = dimensions[this.layout === 'portrait' ? 1 : 0];
@@ -378,7 +390,8 @@ class PDFPage {
378
390
  Parent: this.document._root.data.Pages,
379
391
  MediaBox: [0, 0, this.width, this.height],
380
392
  Contents: this.content,
381
- Resources: this.resources
393
+ Resources: this.resources,
394
+ UserUnit: this.userUnit
382
395
  });
383
396
  this.markings = [];
384
397
  }
@@ -451,6 +464,54 @@ class PDFNameTree extends PDFTree {
451
464
  }
452
465
  }
453
466
 
467
+ function md5Hash(data) {
468
+ return new Uint8Array(md5.arrayBuffer(data));
469
+ }
470
+ function md5Hex(data) {
471
+ return md5(data);
472
+ }
473
+
474
+ function sha256Hash(data) {
475
+ return sha256(data);
476
+ }
477
+
478
+ function aesCbcEncrypt(data, key, iv, padding = true) {
479
+ return cbc(key, iv, {
480
+ disablePadding: !padding
481
+ }).encrypt(data);
482
+ }
483
+ function aesEcbEncrypt(data, key) {
484
+ return ecb(key, {
485
+ disablePadding: true
486
+ }).encrypt(data);
487
+ }
488
+
489
+ function rc4(data, key) {
490
+ const s = new Uint8Array(256);
491
+ for (let i = 0; i < 256; i++) {
492
+ s[i] = i;
493
+ }
494
+ let j = 0;
495
+ for (let i = 0; i < 256; i++) {
496
+ j = j + s[i] + key[i % key.length] & 0xff;
497
+ [s[i], s[j]] = [s[j], s[i]];
498
+ }
499
+ const output = new Uint8Array(data.length);
500
+ for (let i = 0, j = 0, k = 0; k < data.length; k++) {
501
+ i = i + 1 & 0xff;
502
+ j = j + s[i] & 0xff;
503
+ [s[i], s[j]] = [s[j], s[i]];
504
+ output[k] = data[k] ^ s[s[i] + s[j] & 0xff];
505
+ }
506
+ return output;
507
+ }
508
+
509
+ function randomBytes(length) {
510
+ const bytes = new Uint8Array(length);
511
+ globalThis.crypto.getRandomValues(bytes);
512
+ return bytes;
513
+ }
514
+
454
515
  function inRange(value, rangeGroup) {
455
516
  if (value < rangeGroup[0]) return false;
456
517
  let startRange = 0;
@@ -507,8 +568,7 @@ function toCodePoints(input) {
507
568
  }
508
569
  return codepoints;
509
570
  }
510
- function saslprep(input) {
511
- let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
571
+ function saslprep(input, opts = {}) {
512
572
  if (typeof input !== 'string') {
513
573
  throw new TypeError('Expected string.');
514
574
  }
@@ -542,8 +602,7 @@ function saslprep(input) {
542
602
  }
543
603
 
544
604
  class PDFSecurity {
545
- static generateFileID() {
546
- let info = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
605
+ static generateFileID(info = {}) {
547
606
  let infoStr = `${info.CreationDate.getTime()}\n`;
548
607
  for (let key in info) {
549
608
  if (!info.hasOwnProperty(key)) {
@@ -551,20 +610,18 @@ class PDFSecurity {
551
610
  }
552
611
  infoStr += `${key}: ${info[key].valueOf()}\n`;
553
612
  }
554
- return wordArrayToBuffer(CryptoJS.MD5(infoStr));
613
+ return Buffer.from(md5Hash(infoStr));
555
614
  }
556
615
  static generateRandomWordArray(bytes) {
557
- return CryptoJS.lib.WordArray.random(bytes);
616
+ return randomBytes(bytes);
558
617
  }
559
- static create(document) {
560
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
618
+ static create(document, options = {}) {
561
619
  if (!options.ownerPassword && !options.userPassword) {
562
620
  return null;
563
621
  }
564
622
  return new PDFSecurity(document, options);
565
623
  }
566
- constructor(document) {
567
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
624
+ constructor(document, options = {}) {
568
625
  if (!options.ownerPassword && !options.userPassword) {
569
626
  throw new Error('None of owner password and user password is defined.');
570
627
  }
@@ -648,8 +705,8 @@ class PDFSecurity {
648
705
  encDict.StrF = 'StdCF';
649
706
  }
650
707
  encDict.R = r;
651
- encDict.O = wordArrayToBuffer(ownerPasswordEntry);
652
- encDict.U = wordArrayToBuffer(userPasswordEntry);
708
+ encDict.O = Buffer.from(ownerPasswordEntry);
709
+ encDict.U = Buffer.from(userPasswordEntry);
653
710
  encDict.P = permissions;
654
711
  }
655
712
  _setupEncryptionV5(encDict, options) {
@@ -659,10 +716,10 @@ class PDFSecurity {
659
716
  const processedOwnerPassword = options.ownerPassword ? processPasswordR5(options.ownerPassword) : processedUserPassword;
660
717
  this.encryptionKey = getEncryptionKeyR5(PDFSecurity.generateRandomWordArray);
661
718
  const userPasswordEntry = getUserPasswordR5(processedUserPassword, PDFSecurity.generateRandomWordArray);
662
- const userKeySalt = CryptoJS.lib.WordArray.create(userPasswordEntry.words.slice(10, 12), 8);
719
+ const userKeySalt = userPasswordEntry.slice(40, 48);
663
720
  const userEncryptionKeyEntry = getUserEncryptionKeyR5(processedUserPassword, userKeySalt, this.encryptionKey);
664
721
  const ownerPasswordEntry = getOwnerPasswordR5(processedOwnerPassword, userPasswordEntry, PDFSecurity.generateRandomWordArray);
665
- const ownerKeySalt = CryptoJS.lib.WordArray.create(ownerPasswordEntry.words.slice(10, 12), 8);
722
+ const ownerKeySalt = ownerPasswordEntry.slice(40, 48);
666
723
  const ownerEncryptionKeyEntry = getOwnerEncryptionKeyR5(processedOwnerPassword, ownerKeySalt, userPasswordEntry, this.encryptionKey);
667
724
  const permsEntry = getEncryptedPermissionsR5(permissions, this.encryptionKey, PDFSecurity.generateRandomWordArray);
668
725
  encDict.V = 5;
@@ -677,43 +734,43 @@ class PDFSecurity {
677
734
  encDict.StmF = 'StdCF';
678
735
  encDict.StrF = 'StdCF';
679
736
  encDict.R = 5;
680
- encDict.O = wordArrayToBuffer(ownerPasswordEntry);
681
- encDict.OE = wordArrayToBuffer(ownerEncryptionKeyEntry);
682
- encDict.U = wordArrayToBuffer(userPasswordEntry);
683
- encDict.UE = wordArrayToBuffer(userEncryptionKeyEntry);
737
+ encDict.O = Buffer.from(ownerPasswordEntry);
738
+ encDict.OE = Buffer.from(ownerEncryptionKeyEntry);
739
+ encDict.U = Buffer.from(userPasswordEntry);
740
+ encDict.UE = Buffer.from(userEncryptionKeyEntry);
684
741
  encDict.P = permissions;
685
- encDict.Perms = wordArrayToBuffer(permsEntry);
742
+ encDict.Perms = Buffer.from(permsEntry);
686
743
  }
687
744
  getEncryptFn(obj, gen) {
688
745
  let digest;
689
746
  if (this.version < 5) {
690
- digest = this.encryptionKey.clone().concat(CryptoJS.lib.WordArray.create([(obj & 0xff) << 24 | (obj & 0xff00) << 8 | obj >> 8 & 0xff00 | gen & 0xff, (gen & 0xff00) << 16], 5));
747
+ const suffix = new Uint8Array([obj & 0xff, obj >> 8 & 0xff, obj >> 16 & 0xff, gen & 0xff, gen >> 8 & 0xff]);
748
+ digest = concatBytes(this.encryptionKey, suffix);
691
749
  }
692
750
  if (this.version === 1 || this.version === 2) {
693
- let key = CryptoJS.MD5(digest);
694
- key.sigBytes = Math.min(16, this.keyBits / 8 + 5);
695
- return buffer => wordArrayToBuffer(CryptoJS.RC4.encrypt(CryptoJS.lib.WordArray.create(buffer), key).ciphertext);
751
+ let key = md5Hash(digest);
752
+ const keyLen = Math.min(16, this.keyBits / 8 + 5);
753
+ key = key.slice(0, keyLen);
754
+ return buffer => Buffer.from(rc4(new Uint8Array(buffer), key));
696
755
  }
697
756
  let key;
698
757
  if (this.version === 4) {
699
- key = CryptoJS.MD5(digest.concat(CryptoJS.lib.WordArray.create([0x73416c54], 4)));
758
+ const saltMarker = new Uint8Array([0x73, 0x41, 0x6c, 0x54]);
759
+ key = md5Hash(concatBytes(digest, saltMarker));
700
760
  } else {
701
761
  key = this.encryptionKey;
702
762
  }
703
763
  const iv = PDFSecurity.generateRandomWordArray(16);
704
- const options = {
705
- mode: CryptoJS.mode.CBC,
706
- padding: CryptoJS.pad.Pkcs7,
707
- iv
764
+ return buffer => {
765
+ const encrypted = aesCbcEncrypt(new Uint8Array(buffer), key, iv, true);
766
+ return Buffer.from(concatBytes(iv, encrypted));
708
767
  };
709
- return buffer => wordArrayToBuffer(iv.clone().concat(CryptoJS.AES.encrypt(CryptoJS.lib.WordArray.create(buffer), key, options).ciphertext));
710
768
  }
711
769
  end() {
712
770
  this.dictionary.end();
713
771
  }
714
772
  }
715
- function getPermissionsR2() {
716
- let permissionObject = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
773
+ function getPermissionsR2(permissionObject = {}) {
717
774
  let permissions = 0xffffffc0 >> 0;
718
775
  if (permissionObject.printing) {
719
776
  permissions |= 0b000000000100;
@@ -729,8 +786,7 @@ function getPermissionsR2() {
729
786
  }
730
787
  return permissions;
731
788
  }
732
- function getPermissionsR3() {
733
- let permissionObject = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
789
+ function getPermissionsR3(permissionObject = {}) {
734
790
  let permissions = 0xfffff0c0 >> 0;
735
791
  if (permissionObject.printing === 'lowResolution') {
736
792
  permissions |= 0b000000000100;
@@ -759,90 +815,97 @@ function getPermissionsR3() {
759
815
  return permissions;
760
816
  }
761
817
  function getUserPasswordR2(encryptionKey) {
762
- return CryptoJS.RC4.encrypt(processPasswordR2R3R4(), encryptionKey).ciphertext;
818
+ return rc4(processPasswordR2R3R4(), encryptionKey);
763
819
  }
764
820
  function getUserPasswordR3R4(documentId, encryptionKey) {
765
- const key = encryptionKey.clone();
766
- let cipher = CryptoJS.MD5(processPasswordR2R3R4().concat(CryptoJS.lib.WordArray.create(documentId)));
821
+ const key = encryptionKey.slice();
822
+ let cipher = md5Hash(concatBytes(processPasswordR2R3R4(), new Uint8Array(documentId)));
767
823
  for (let i = 0; i < 20; i++) {
768
- const xorRound = Math.ceil(key.sigBytes / 4);
769
- for (let j = 0; j < xorRound; j++) {
770
- key.words[j] = encryptionKey.words[j] ^ (i | i << 8 | i << 16 | i << 24);
824
+ const xorKey = new Uint8Array(key.length);
825
+ for (let j = 0; j < key.length; j++) {
826
+ xorKey[j] = encryptionKey[j] ^ i;
771
827
  }
772
- cipher = CryptoJS.RC4.encrypt(cipher, key).ciphertext;
828
+ cipher = rc4(cipher, xorKey);
773
829
  }
774
- return cipher.concat(CryptoJS.lib.WordArray.create(null, 16));
830
+ const result = new Uint8Array(32);
831
+ result.set(cipher);
832
+ return result;
775
833
  }
776
834
  function getOwnerPasswordR2R3R4(r, keyBits, paddedUserPassword, paddedOwnerPassword) {
777
835
  let digest = paddedOwnerPassword;
778
836
  let round = r >= 3 ? 51 : 1;
779
837
  for (let i = 0; i < round; i++) {
780
- digest = CryptoJS.MD5(digest);
838
+ digest = md5Hash(digest);
781
839
  }
782
- const key = digest.clone();
783
- key.sigBytes = keyBits / 8;
840
+ const keyLen = keyBits / 8;
841
+ let key = digest.slice(0, keyLen);
784
842
  let cipher = paddedUserPassword;
785
843
  round = r >= 3 ? 20 : 1;
786
844
  for (let i = 0; i < round; i++) {
787
- const xorRound = Math.ceil(key.sigBytes / 4);
788
- for (let j = 0; j < xorRound; j++) {
789
- key.words[j] = digest.words[j] ^ (i | i << 8 | i << 16 | i << 24);
845
+ const xorKey = new Uint8Array(keyLen);
846
+ for (let j = 0; j < keyLen; j++) {
847
+ xorKey[j] = key[j] ^ i;
790
848
  }
791
- cipher = CryptoJS.RC4.encrypt(cipher, key).ciphertext;
849
+ cipher = rc4(cipher, xorKey);
792
850
  }
793
851
  return cipher;
794
852
  }
795
853
  function getEncryptionKeyR2R3R4(r, keyBits, documentId, paddedUserPassword, ownerPasswordEntry, permissions) {
796
- let key = paddedUserPassword.clone().concat(ownerPasswordEntry).concat(CryptoJS.lib.WordArray.create([lsbFirstWord(permissions)], 4)).concat(CryptoJS.lib.WordArray.create(documentId));
854
+ const permBytes = new Uint8Array([permissions & 0xff, permissions >> 8 & 0xff, permissions >> 16 & 0xff, permissions >> 24 & 0xff]);
855
+ let key = concatBytes(paddedUserPassword, ownerPasswordEntry, permBytes, new Uint8Array(documentId));
797
856
  const round = r >= 3 ? 51 : 1;
857
+ const keyLen = keyBits / 8;
798
858
  for (let i = 0; i < round; i++) {
799
- key = CryptoJS.MD5(key);
800
- key.sigBytes = keyBits / 8;
859
+ key = md5Hash(key);
860
+ key = key.slice(0, keyLen);
801
861
  }
802
862
  return key;
803
863
  }
804
864
  function getUserPasswordR5(processedUserPassword, generateRandomWordArray) {
805
865
  const validationSalt = generateRandomWordArray(8);
806
866
  const keySalt = generateRandomWordArray(8);
807
- return CryptoJS.SHA256(processedUserPassword.clone().concat(validationSalt)).concat(validationSalt).concat(keySalt);
867
+ const hash = sha256Hash(concatBytes(processedUserPassword, validationSalt));
868
+ return concatBytes(hash, validationSalt, keySalt);
808
869
  }
809
870
  function getUserEncryptionKeyR5(processedUserPassword, userKeySalt, encryptionKey) {
810
- const key = CryptoJS.SHA256(processedUserPassword.clone().concat(userKeySalt));
811
- const options = {
812
- mode: CryptoJS.mode.CBC,
813
- padding: CryptoJS.pad.NoPadding,
814
- iv: CryptoJS.lib.WordArray.create(null, 16)
815
- };
816
- return CryptoJS.AES.encrypt(encryptionKey, key, options).ciphertext;
871
+ const key = sha256Hash(concatBytes(processedUserPassword, userKeySalt));
872
+ const iv = new Uint8Array(16);
873
+ return aesCbcEncrypt(encryptionKey, key, iv, false);
817
874
  }
818
875
  function getOwnerPasswordR5(processedOwnerPassword, userPasswordEntry, generateRandomWordArray) {
819
876
  const validationSalt = generateRandomWordArray(8);
820
877
  const keySalt = generateRandomWordArray(8);
821
- return CryptoJS.SHA256(processedOwnerPassword.clone().concat(validationSalt).concat(userPasswordEntry)).concat(validationSalt).concat(keySalt);
878
+ const hash = sha256Hash(concatBytes(processedOwnerPassword, validationSalt, userPasswordEntry));
879
+ return concatBytes(hash, validationSalt, keySalt);
822
880
  }
823
881
  function getOwnerEncryptionKeyR5(processedOwnerPassword, ownerKeySalt, userPasswordEntry, encryptionKey) {
824
- const key = CryptoJS.SHA256(processedOwnerPassword.clone().concat(ownerKeySalt).concat(userPasswordEntry));
825
- const options = {
826
- mode: CryptoJS.mode.CBC,
827
- padding: CryptoJS.pad.NoPadding,
828
- iv: CryptoJS.lib.WordArray.create(null, 16)
829
- };
830
- return CryptoJS.AES.encrypt(encryptionKey, key, options).ciphertext;
882
+ const key = sha256Hash(concatBytes(processedOwnerPassword, ownerKeySalt, userPasswordEntry));
883
+ const iv = new Uint8Array(16);
884
+ return aesCbcEncrypt(encryptionKey, key, iv, false);
831
885
  }
832
886
  function getEncryptionKeyR5(generateRandomWordArray) {
833
887
  return generateRandomWordArray(32);
834
888
  }
835
889
  function getEncryptedPermissionsR5(permissions, encryptionKey, generateRandomWordArray) {
836
- const cipher = CryptoJS.lib.WordArray.create([lsbFirstWord(permissions), 0xffffffff, 0x54616462], 12).concat(generateRandomWordArray(4));
837
- const options = {
838
- mode: CryptoJS.mode.ECB,
839
- padding: CryptoJS.pad.NoPadding
840
- };
841
- return CryptoJS.AES.encrypt(cipher, encryptionKey, options).ciphertext;
890
+ const data = new Uint8Array(16);
891
+ data[0] = permissions & 0xff;
892
+ data[1] = permissions >> 8 & 0xff;
893
+ data[2] = permissions >> 16 & 0xff;
894
+ data[3] = permissions >> 24 & 0xff;
895
+ data[4] = 0xff;
896
+ data[5] = 0xff;
897
+ data[6] = 0xff;
898
+ data[7] = 0xff;
899
+ data[8] = 0x54;
900
+ data[9] = 0x61;
901
+ data[10] = 0x64;
902
+ data[11] = 0x62;
903
+ const randomPart = generateRandomWordArray(4);
904
+ data.set(randomPart, 12);
905
+ return aesEcbEncrypt(data, encryptionKey);
842
906
  }
843
- function processPasswordR2R3R4() {
844
- let password = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
845
- const out = Buffer.alloc(32);
907
+ function processPasswordR2R3R4(password = '') {
908
+ const out = new Uint8Array(32);
846
909
  const length = password.length;
847
910
  let index = 0;
848
911
  while (index < length && index < 32) {
@@ -857,34 +920,23 @@ function processPasswordR2R3R4() {
857
920
  out[index] = PASSWORD_PADDING[index - length];
858
921
  index++;
859
922
  }
860
- return CryptoJS.lib.WordArray.create(out);
923
+ return out;
861
924
  }
862
- function processPasswordR5() {
863
- let password = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
925
+ function processPasswordR5(password = '') {
864
926
  password = unescape(encodeURIComponent(saslprep(password)));
865
927
  const length = Math.min(127, password.length);
866
- const out = Buffer.alloc(length);
928
+ const out = new Uint8Array(length);
867
929
  for (let i = 0; i < length; i++) {
868
930
  out[i] = password.charCodeAt(i);
869
931
  }
870
- return CryptoJS.lib.WordArray.create(out);
871
- }
872
- function lsbFirstWord(data) {
873
- return (data & 0xff) << 24 | (data & 0xff00) << 8 | data >> 8 & 0xff00 | data >> 24 & 0xff;
874
- }
875
- function wordArrayToBuffer(wordArray) {
876
- const byteArray = [];
877
- for (let i = 0; i < wordArray.sigBytes; i++) {
878
- byteArray.push(wordArray.words[Math.floor(i / 4)] >> 8 * (3 - i % 4) & 0xff);
879
- }
880
- return Buffer.from(byteArray);
932
+ return out;
881
933
  }
882
934
  const PASSWORD_PADDING = [0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a];
883
935
 
884
936
  const {
885
937
  number: number$2
886
938
  } = PDFObject;
887
- class PDFGradient$1 {
939
+ let PDFGradient$1 = class PDFGradient {
888
940
  constructor(doc) {
889
941
  this.doc = doc;
890
942
  this.stops = [];
@@ -1042,8 +1094,8 @@ class PDFGradient$1 {
1042
1094
  const op = stroke ? 'SCN' : 'scn';
1043
1095
  return this.doc.addContent(`/${this.id} ${op}`);
1044
1096
  }
1045
- }
1046
- class PDFLinearGradient$1 extends PDFGradient$1 {
1097
+ };
1098
+ let PDFLinearGradient$1 = class PDFLinearGradient extends PDFGradient$1 {
1047
1099
  constructor(doc, x1, y1, x2, y2) {
1048
1100
  super(doc);
1049
1101
  this.x1 = x1;
@@ -1061,10 +1113,10 @@ class PDFLinearGradient$1 extends PDFGradient$1 {
1061
1113
  });
1062
1114
  }
1063
1115
  opacityGradient() {
1064
- return new PDFLinearGradient$1(this.doc, this.x1, this.y1, this.x2, this.y2);
1116
+ return new PDFLinearGradient(this.doc, this.x1, this.y1, this.x2, this.y2);
1065
1117
  }
1066
- }
1067
- class PDFRadialGradient$1 extends PDFGradient$1 {
1118
+ };
1119
+ let PDFRadialGradient$1 = class PDFRadialGradient extends PDFGradient$1 {
1068
1120
  constructor(doc, x1, y1, r1, x2, y2, r2) {
1069
1121
  super(doc);
1070
1122
  this.doc = doc;
@@ -1085,9 +1137,9 @@ class PDFRadialGradient$1 extends PDFGradient$1 {
1085
1137
  });
1086
1138
  }
1087
1139
  opacityGradient() {
1088
- return new PDFRadialGradient$1(this.doc, this.x1, this.y1, this.r1, this.x2, this.y2, this.r2);
1140
+ return new PDFRadialGradient(this.doc, this.x1, this.y1, this.r1, this.x2, this.y2, this.r2);
1089
1141
  }
1090
- }
1142
+ };
1091
1143
  var Gradient = {
1092
1144
  PDFGradient: PDFGradient$1,
1093
1145
  PDFLinearGradient: PDFLinearGradient$1,
@@ -1095,7 +1147,7 @@ var Gradient = {
1095
1147
  };
1096
1148
 
1097
1149
  const underlyingColorSpaces = ['DeviceCMYK', 'DeviceRGB'];
1098
- class PDFTilingPattern$1 {
1150
+ let PDFTilingPattern$1 = class PDFTilingPattern {
1099
1151
  constructor(doc, bBox, xStep, yStep, stream) {
1100
1152
  this.doc = doc;
1101
1153
  this.bBox = bBox;
@@ -1155,7 +1207,7 @@ class PDFTilingPattern$1 {
1155
1207
  const op = stroke ? 'SCN' : 'scn';
1156
1208
  return this.doc.addContent(`${normalizedColor.join(' ')} /${this.id} ${op}`);
1157
1209
  }
1158
- }
1210
+ };
1159
1211
  var pattern = {
1160
1212
  PDFTilingPattern: PDFTilingPattern$1
1161
1213
  };
@@ -1485,86 +1537,176 @@ const parameters = {
1485
1537
  Z: 0,
1486
1538
  z: 0
1487
1539
  };
1540
+ const isCommand = function (c) {
1541
+ return c in parameters;
1542
+ };
1543
+ const isWsp = function (c) {
1544
+ const codePoint = c.codePointAt(0);
1545
+ return codePoint === 0x20 || codePoint === 0x9 || codePoint === 0xd || codePoint === 0xa;
1546
+ };
1547
+ const isDigit = function (c) {
1548
+ const codePoint = c.codePointAt(0);
1549
+ if (codePoint == null) {
1550
+ return false;
1551
+ }
1552
+ return 48 <= codePoint && codePoint <= 57;
1553
+ };
1554
+ const readNumber = function (string, cursor) {
1555
+ let i = cursor;
1556
+ let value = '';
1557
+ let state = 'none';
1558
+ for (; i < string.length; i += 1) {
1559
+ const c = string[i];
1560
+ if (c === '+' || c === '-') {
1561
+ if (state === 'none') {
1562
+ state = 'sign';
1563
+ value += c;
1564
+ continue;
1565
+ }
1566
+ if (state === 'e') {
1567
+ state = 'exponent_sign';
1568
+ value += c;
1569
+ continue;
1570
+ }
1571
+ }
1572
+ if (isDigit(c)) {
1573
+ if (state === 'none' || state === 'sign' || state === 'whole') {
1574
+ state = 'whole';
1575
+ value += c;
1576
+ continue;
1577
+ }
1578
+ if (state === 'decimal_point' || state === 'decimal') {
1579
+ state = 'decimal';
1580
+ value += c;
1581
+ continue;
1582
+ }
1583
+ if (state === 'e' || state === 'exponent_sign' || state === 'exponent') {
1584
+ state = 'exponent';
1585
+ value += c;
1586
+ continue;
1587
+ }
1588
+ }
1589
+ if (c === '.') {
1590
+ if (state === 'none' || state === 'sign' || state === 'whole') {
1591
+ state = 'decimal_point';
1592
+ value += c;
1593
+ continue;
1594
+ }
1595
+ }
1596
+ if (c === 'E' || c === 'e') {
1597
+ if (state === 'whole' || state === 'decimal_point' || state === 'decimal') {
1598
+ state = 'e';
1599
+ value += c;
1600
+ continue;
1601
+ }
1602
+ }
1603
+ break;
1604
+ }
1605
+ const number = Number.parseFloat(value);
1606
+ if (Number.isNaN(number)) {
1607
+ return [cursor, null];
1608
+ }
1609
+ return [i - 1, number];
1610
+ };
1488
1611
  const parse = function (path) {
1489
- let cmd;
1490
- const ret = [];
1612
+ const pathData = [];
1613
+ let command = null;
1491
1614
  let args = [];
1492
- let curArg = '';
1493
- let foundDecimal = false;
1494
- let params = 0;
1495
- for (let c of path) {
1496
- if (parameters[c] != null) {
1497
- params = parameters[c];
1498
- if (cmd) {
1499
- if (curArg.length > 0) {
1500
- args[args.length] = +curArg;
1615
+ let argsCount = 0;
1616
+ let canHaveComma = false;
1617
+ let hadComma = false;
1618
+ for (let i = 0; i < path.length; i += 1) {
1619
+ const c = path.charAt(i);
1620
+ if (isWsp(c)) {
1621
+ continue;
1622
+ }
1623
+ if (canHaveComma && c === ',') {
1624
+ if (hadComma) {
1625
+ break;
1626
+ }
1627
+ hadComma = true;
1628
+ continue;
1629
+ }
1630
+ if (isCommand(c)) {
1631
+ if (hadComma) {
1632
+ return pathData;
1633
+ }
1634
+ if (command == null) {
1635
+ if (c !== 'M' && c !== 'm') {
1636
+ return pathData;
1637
+ }
1638
+ } else {
1639
+ if (args.length !== 0) {
1640
+ return pathData;
1501
1641
  }
1502
- ret[ret.length] = {
1503
- cmd,
1504
- args
1505
- };
1506
- args = [];
1507
- curArg = '';
1508
- foundDecimal = false;
1509
- }
1510
- cmd = c;
1511
- } else if ([' ', ','].includes(c) || c === '-' && curArg.length > 0 && curArg[curArg.length - 1] !== 'e' || c === '.' && foundDecimal) {
1512
- if (curArg.length === 0) {
1513
- continue;
1514
1642
  }
1515
- if (args.length === params) {
1516
- ret[ret.length] = {
1517
- cmd,
1643
+ command = c;
1644
+ args = [];
1645
+ argsCount = parameters[command];
1646
+ canHaveComma = false;
1647
+ if (argsCount === 0) {
1648
+ pathData.push({
1649
+ command,
1518
1650
  args
1519
- };
1520
- args = [+curArg];
1521
- if (cmd === 'M') {
1522
- cmd = 'L';
1651
+ });
1652
+ }
1653
+ continue;
1654
+ }
1655
+ if (command == null) {
1656
+ return pathData;
1657
+ }
1658
+ let newCursor = i;
1659
+ let number = null;
1660
+ if (command === 'A' || command === 'a') {
1661
+ const position = args.length;
1662
+ if (position === 0 || position === 1) {
1663
+ if (c !== '+' && c !== '-') {
1664
+ [newCursor, number] = readNumber(path, i);
1523
1665
  }
1524
- if (cmd === 'm') {
1525
- cmd = 'l';
1666
+ }
1667
+ if (position === 2 || position === 5 || position === 6) {
1668
+ [newCursor, number] = readNumber(path, i);
1669
+ }
1670
+ if (position === 3 || position === 4) {
1671
+ if (c === '0') {
1672
+ number = 0;
1673
+ }
1674
+ if (c === '1') {
1675
+ number = 1;
1526
1676
  }
1527
- } else {
1528
- args[args.length] = +curArg;
1529
1677
  }
1530
- foundDecimal = c === '.';
1531
- curArg = ['-', '.'].includes(c) ? c : '';
1532
1678
  } else {
1533
- curArg += c;
1534
- if (c === '.') {
1535
- foundDecimal = true;
1536
- }
1537
- }
1538
- }
1539
- if (curArg.length > 0) {
1540
- if (args.length === params) {
1541
- ret[ret.length] = {
1542
- cmd,
1679
+ [newCursor, number] = readNumber(path, i);
1680
+ }
1681
+ if (number == null) {
1682
+ return pathData;
1683
+ }
1684
+ args.push(number);
1685
+ canHaveComma = true;
1686
+ hadComma = false;
1687
+ i = newCursor;
1688
+ if (args.length === argsCount) {
1689
+ pathData.push({
1690
+ command,
1543
1691
  args
1544
- };
1545
- args = [+curArg];
1546
- if (cmd === 'M') {
1547
- cmd = 'L';
1692
+ });
1693
+ if (command === 'M') {
1694
+ command = 'L';
1548
1695
  }
1549
- if (cmd === 'm') {
1550
- cmd = 'l';
1696
+ if (command === 'm') {
1697
+ command = 'l';
1551
1698
  }
1552
- } else {
1553
- args[args.length] = +curArg;
1699
+ args = [];
1554
1700
  }
1555
1701
  }
1556
- ret[ret.length] = {
1557
- cmd,
1558
- args
1559
- };
1560
- return ret;
1702
+ return pathData;
1561
1703
  };
1562
1704
  const apply = function (commands, doc) {
1563
1705
  cx = cy = px = py = sx = sy = 0;
1564
1706
  for (let i = 0; i < commands.length; i++) {
1565
1707
  const c = commands[i];
1566
- if (typeof runners[c.cmd] === 'function') {
1567
- runners[c.cmd](doc, c.args);
1708
+ if (typeof runners[c.command] === 'function') {
1709
+ runners[c.command](doc, c.args);
1568
1710
  }
1569
1711
  }
1570
1712
  };
@@ -1844,8 +1986,7 @@ var VectorMixin = {
1844
1986
  miterLimit(m) {
1845
1987
  return this.addContent(`${number$1(m)} M`);
1846
1988
  },
1847
- dash(length) {
1848
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1989
+ dash(length, options = {}) {
1849
1990
  const originalLength = length;
1850
1991
  if (!Array.isArray(length)) {
1851
1992
  length = [length, options.space || length];
@@ -1875,21 +2016,42 @@ var VectorMixin = {
1875
2016
  rect(x, y, w, h) {
1876
2017
  return this.addContent(`${number$1(x)} ${number$1(y)} ${number$1(w)} ${number$1(h)} re`);
1877
2018
  },
1878
- roundedRect(x, y, w, h, r) {
1879
- if (r == null) {
1880
- r = 0;
1881
- }
1882
- r = Math.min(r, 0.5 * w, 0.5 * h);
1883
- const c = r * (1.0 - KAPPA);
1884
- this.moveTo(x + r, y);
1885
- this.lineTo(x + w - r, y);
1886
- this.bezierCurveTo(x + w - c, y, x + w, y + c, x + w, y + r);
1887
- this.lineTo(x + w, y + h - r);
1888
- this.bezierCurveTo(x + w, y + h - c, x + w - c, y + h, x + w - r, y + h);
1889
- this.lineTo(x + r, y + h);
1890
- this.bezierCurveTo(x + c, y + h, x, y + h - c, x, y + h - r);
1891
- this.lineTo(x, y + r);
1892
- this.bezierCurveTo(x, y + c, x + c, y, x + r, y);
2019
+ roundedRect(x, y, w, h, borderRadius) {
2020
+ if (borderRadius == null) {
2021
+ borderRadius = 0;
2022
+ }
2023
+ let radii;
2024
+ if (Array.isArray(borderRadius)) {
2025
+ radii = borderRadius.slice(0, 4);
2026
+ } else {
2027
+ radii = [borderRadius, borderRadius, borderRadius, borderRadius];
2028
+ }
2029
+ const limit = Math.min(0.5 * w, 0.5 * h);
2030
+ const rTL = Math.max(0, Math.min(radii[0] || 0, limit));
2031
+ const rTR = Math.max(0, Math.min(radii[1] || 0, limit));
2032
+ const rBR = Math.max(0, Math.min(radii[2] || 0, limit));
2033
+ const rBL = Math.max(0, Math.min(radii[3] || 0, limit));
2034
+ const cpTR = rTR * (1.0 - KAPPA);
2035
+ const cpBR = rBR * (1.0 - KAPPA);
2036
+ const cpBL = rBL * (1.0 - KAPPA);
2037
+ const cpTL = rTL * (1.0 - KAPPA);
2038
+ this.moveTo(x + rTL, y);
2039
+ this.lineTo(x + w - rTR, y);
2040
+ if (rTR > 0) {
2041
+ this.bezierCurveTo(x + w - cpTR, y, x + w, y + cpTR, x + w, y + rTR);
2042
+ }
2043
+ this.lineTo(x + w, y + h - rBR);
2044
+ if (rBR > 0) {
2045
+ this.bezierCurveTo(x + w, y + h - cpBR, x + w - cpBR, y + h, x + w - rBR, y + h);
2046
+ }
2047
+ this.lineTo(x + rBL, y + h);
2048
+ if (rBL > 0) {
2049
+ this.bezierCurveTo(x + cpBL, y + h, x, y + h - cpBL, x, y + h - rBL);
2050
+ }
2051
+ this.lineTo(x, y + rTL);
2052
+ if (rTL > 0) {
2053
+ this.bezierCurveTo(x, y + cpTL, x + cpTL, y, x + rTL, y);
2054
+ }
1893
2055
  return this.closePath();
1894
2056
  },
1895
2057
  ellipse(x, y, r1, r2) {
@@ -1950,10 +2112,7 @@ var VectorMixin = {
1950
2112
  }
1951
2113
  return this;
1952
2114
  },
1953
- polygon() {
1954
- for (var _len = arguments.length, points = new Array(_len), _key = 0; _key < _len; _key++) {
1955
- points[_key] = arguments[_key];
1956
- }
2115
+ polygon(...points) {
1957
2116
  this.moveTo(...(points.shift() || []));
1958
2117
  for (let point of points) {
1959
2118
  this.lineTo(...(point || []));
@@ -2026,8 +2185,7 @@ var VectorMixin = {
2026
2185
  translate(x, y) {
2027
2186
  return this.transform(1, 0, 0, 1, x, y);
2028
2187
  },
2029
- rotate(angle) {
2030
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2188
+ rotate(angle, options = {}) {
2031
2189
  let y;
2032
2190
  const rad = angle * Math.PI / 180;
2033
2191
  const cos = Math.cos(rad);
@@ -2042,8 +2200,7 @@ var VectorMixin = {
2042
2200
  }
2043
2201
  return this.transform(cos, sin, -sin, cos, x, y);
2044
2202
  },
2045
- scale(xFactor, yFactor) {
2046
- let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2203
+ scale(xFactor, yFactor, options = {}) {
2047
2204
  let y;
2048
2205
  if (yFactor == null) {
2049
2206
  yFactor = xFactor;
@@ -2186,7 +2343,7 @@ class AFMFont {
2186
2343
  if (match = line.match(/^Start(\w+)/)) {
2187
2344
  section = match[1];
2188
2345
  continue;
2189
- } else if (match = line.match(/^End(\w+)/)) {
2346
+ } else if (line.match(/^End(\w+)/)) {
2190
2347
  section = '';
2191
2348
  continue;
2192
2349
  }
@@ -2278,8 +2435,7 @@ class PDFFont {
2278
2435
  embed() {
2279
2436
  throw new Error('Must be implemented by subclasses');
2280
2437
  }
2281
- lineHeight(size) {
2282
- let includeGap = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
2438
+ lineHeight(size, includeGap = false) {
2283
2439
  const gap = includeGap ? this.lineGap : 0;
2284
2440
  return (this.ascender + gap - this.descender) / 1000 * size;
2285
2441
  }
@@ -2531,9 +2687,15 @@ class EmbeddedFont extends PDFFont {
2531
2687
  descriptor.data.FontFile2 = fontFile;
2532
2688
  }
2533
2689
  if (this.document.subset && this.document.subset === 1) {
2534
- const CIDSet = Buffer.from('FFFFFFFFC0', 'hex');
2690
+ const maxCID = this.widths.length - 1;
2691
+ const cidSetBuffer = Buffer.alloc(Math.ceil((maxCID + 1) / 8), 0);
2692
+ for (let cid = 0; cid <= maxCID; cid++) {
2693
+ if (this.widths[cid] != null) {
2694
+ cidSetBuffer[Math.floor(cid / 8)] |= 0x80 >> cid % 8;
2695
+ }
2696
+ }
2535
2697
  const CIDSetRef = this.document.ref();
2536
- CIDSetRef.write(CIDSet);
2698
+ CIDSetRef.write(cidSetBuffer);
2537
2699
  CIDSetRef.end();
2538
2700
  descriptor.data.CIDSet = CIDSetRef;
2539
2701
  }
@@ -2603,7 +2765,7 @@ begincmap
2603
2765
  1 begincodespacerange
2604
2766
  <0000><ffff>
2605
2767
  endcodespacerange
2606
- 1 beginbfrange
2768
+ ${ranges.length} beginbfrange
2607
2769
  ${ranges.join('\n')}
2608
2770
  endbfrange
2609
2771
  endcmap
@@ -2625,9 +2787,9 @@ class PDFFontFactory {
2625
2787
  src = fs.readFileSync(src);
2626
2788
  }
2627
2789
  if (src instanceof Uint8Array) {
2628
- font = fontkit.create(src, family);
2790
+ font = create(src, family);
2629
2791
  } else if (src instanceof ArrayBuffer) {
2630
- font = fontkit.create(new Uint8Array(src), family);
2792
+ font = create(new Uint8Array(src), family);
2631
2793
  }
2632
2794
  if (font == null) {
2633
2795
  throw new Error('Not a supported font format or standard PDF font.');
@@ -2646,10 +2808,7 @@ const isEqualFont = (font1, font2) => {
2646
2808
  return true;
2647
2809
  };
2648
2810
  var FontsMixin = {
2649
- initFonts() {
2650
- let defaultFont = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Helvetica';
2651
- let defaultFontFamily = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
2652
- let defaultFontSize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 12;
2811
+ initFonts(defaultFont = 'Helvetica', defaultFontFamily = null, defaultFontSize = 12) {
2653
2812
  this._fontFamilies = {};
2654
2813
  this._fontCount = 0;
2655
2814
  this._fontSource = defaultFont;
@@ -2698,9 +2857,12 @@ var FontsMixin = {
2698
2857
  if (cacheKey) {
2699
2858
  this._fontFamilies[cacheKey] = this._font;
2700
2859
  }
2701
- if (this._font.name) {
2860
+ if (this._font.name && !this._fontFamilies[this._font.name]) {
2702
2861
  this._fontFamilies[this._font.name] = this._font;
2703
2862
  }
2863
+ if (!cacheKey && (!this._font.name || this._fontFamilies[this._font.name] !== this._font)) {
2864
+ this._fontFamilies[this._font.id] = this._font;
2865
+ }
2704
2866
  return this;
2705
2867
  },
2706
2868
  fontSize(_fontSize) {
@@ -2717,10 +2879,7 @@ var FontsMixin = {
2717
2879
  };
2718
2880
  return this;
2719
2881
  },
2720
- sizeToPoint(size) {
2721
- let defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
2722
- let page = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.page;
2723
- let percentageWidth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined;
2882
+ sizeToPoint(size, defaultValue = 0, page = this.page, percentageWidth = undefined) {
2724
2883
  if (!percentageWidth) percentageWidth = this._fontSize;
2725
2884
  if (typeof defaultValue !== 'number') defaultValue = this.sizeToPoint(defaultValue);
2726
2885
  if (size === undefined) return defaultValue;
@@ -2782,12 +2941,13 @@ var FontsMixin = {
2782
2941
 
2783
2942
  const SOFT_HYPHEN = '\u00AD';
2784
2943
  const HYPHEN = '-';
2785
- class LineWrapper extends EventEmitter {
2944
+ class LineWrapper {
2786
2945
  constructor(document, options) {
2787
- super();
2946
+ this._listeners = Object.create(null);
2788
2947
  this.document = document;
2789
2948
  this.horizontalScaling = options.horizontalScaling || 100;
2790
2949
  this.indent = (options.indent || 0) * this.horizontalScaling / 100;
2950
+ this.indentAllLines = options.indentAllLines || false;
2791
2951
  this.characterSpacing = (options.characterSpacing || 0) * this.horizontalScaling / 100;
2792
2952
  this.wordSpacing = (options.wordSpacing === 0) * this.horizontalScaling / 100;
2793
2953
  this.columns = options.columns || 1;
@@ -2839,6 +2999,22 @@ class LineWrapper extends EventEmitter {
2839
2999
  });
2840
3000
  });
2841
3001
  }
3002
+ on(event, listener) {
3003
+ (this._listeners[event] || (this._listeners[event] = [])).push(listener);
3004
+ }
3005
+ once(event, listener) {
3006
+ const wrapper = (...args) => {
3007
+ const listeners = this._listeners[event];
3008
+ listeners.splice(listeners.indexOf(wrapper), 1);
3009
+ listener(...args);
3010
+ };
3011
+ this.on(event, wrapper);
3012
+ }
3013
+ emit(event, ...args) {
3014
+ const listeners = this._listeners[event];
3015
+ if (!listeners) return;
3016
+ for (const listener of listeners.slice()) listener(...args);
3017
+ }
2842
3018
  wordWidth(word) {
2843
3019
  return PDFNumber(this.document.widthOfString(word, this) + this.characterSpacing + this.wordSpacing);
2844
3020
  }
@@ -2904,6 +3080,9 @@ class LineWrapper extends EventEmitter {
2904
3080
  }
2905
3081
  }
2906
3082
  wrap(text, options) {
3083
+ const {
3084
+ document
3085
+ } = this;
2907
3086
  this.horizontalScaling = options.horizontalScaling || 100;
2908
3087
  if (options.indent != null) {
2909
3088
  this.indent = options.indent * this.horizontalScaling / 100;
@@ -2917,24 +3096,20 @@ class LineWrapper extends EventEmitter {
2917
3096
  if (options.ellipsis != null) {
2918
3097
  this.ellipsis = options.ellipsis;
2919
3098
  }
2920
- const nextY = this.document.y + this.document.currentLineHeight(true);
2921
- if (this.document.y > this.maxY || nextY > this.maxY) {
3099
+ const nextY = document.y + document.currentLineHeight(true);
3100
+ if (document.y > this.maxY || nextY > this.maxY) {
2922
3101
  this.nextSection();
2923
3102
  }
2924
3103
  let buffer = '';
2925
3104
  let textWidth = 0;
2926
3105
  let wc = 0;
2927
3106
  let lc = 0;
2928
- let {
2929
- y
2930
- } = this.document;
3107
+ let continueY = document.y;
2931
3108
  const emitLine = () => {
2932
3109
  options.textWidth = textWidth + this.wordSpacing * (wc - 1);
2933
3110
  options.wordCount = wc;
2934
3111
  options.lineWidth = this.lineWidth;
2935
- ({
2936
- y
2937
- } = this.document);
3112
+ continueY = document.y;
2938
3113
  this.emit('line', buffer, options, this);
2939
3114
  return lc++;
2940
3115
  };
@@ -2950,8 +3125,8 @@ class LineWrapper extends EventEmitter {
2950
3125
  wc++;
2951
3126
  }
2952
3127
  if (bk.required || !this.canFit(word, w)) {
2953
- const lh = this.document.currentLineHeight(true);
2954
- if (this.height != null && this.ellipsis && PDFNumber(this.document.y + lh * 2) > this.maxY && this.column >= this.columns) {
3128
+ const lh = document.currentLineHeight(true);
3129
+ if (this.height != null && this.ellipsis && PDFNumber(document.y + lh * 2) > this.maxY && this.column >= this.columns) {
2955
3130
  if (this.ellipsis === true) {
2956
3131
  this.ellipsis = '…';
2957
3132
  }
@@ -2980,7 +3155,7 @@ class LineWrapper extends EventEmitter {
2980
3155
  this.spaceLeft -= this.wordWidth(HYPHEN);
2981
3156
  }
2982
3157
  emitLine();
2983
- if (PDFNumber(this.document.y + lh) > this.maxY) {
3158
+ if (PDFNumber(document.y + lh) > this.maxY) {
2984
3159
  this.emit('sectionEnd', options, this);
2985
3160
  const shouldContinue = this.nextSection();
2986
3161
  if (!shouldContinue) {
@@ -3015,9 +3190,9 @@ class LineWrapper extends EventEmitter {
3015
3190
  this.continuedX = 0;
3016
3191
  }
3017
3192
  this.continuedX += options.textWidth || 0;
3018
- this.document.y = y;
3193
+ document.y = continueY;
3019
3194
  } else {
3020
- this.document.x = this.startX;
3195
+ document.x = this.startX;
3021
3196
  }
3022
3197
  }
3023
3198
  nextSection(options) {
@@ -3029,7 +3204,13 @@ class LineWrapper extends EventEmitter {
3029
3204
  this.column = 1;
3030
3205
  this.startY = this.document.page.margins.top;
3031
3206
  this.maxY = this.document.page.maxY();
3032
- this.document.x = this.startX;
3207
+ if (this.indentAllLines) {
3208
+ const indent = this.continuedX || this.indent;
3209
+ this.document.x += indent;
3210
+ this.lineWidth -= indent;
3211
+ } else {
3212
+ this.document.x = this.startX;
3213
+ }
3033
3214
  if (this.document._fillColor) {
3034
3215
  this.document.fillColor(...this.document._fillColor);
3035
3216
  }
@@ -3119,8 +3300,7 @@ var TextMixin = {
3119
3300
  text(text, x, y, options) {
3120
3301
  return this._text(text, x, y, options, this._line);
3121
3302
  },
3122
- widthOfString(string) {
3123
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
3303
+ widthOfString(string, options = {}) {
3124
3304
  const horizontalScaling = options.horizontalScaling || 100;
3125
3305
  return (this._font.widthOfString(string, this._fontSize, options.features) + (options.characterSpacing || 0) * (string.length - 1)) * horizontalScaling / 100;
3126
3306
  },
@@ -3326,11 +3506,8 @@ var TextMixin = {
3326
3506
  }
3327
3507
  return this;
3328
3508
  },
3329
- _initOptions() {
3330
- let x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3331
- let y = arguments.length > 1 ? arguments[1] : undefined;
3332
- let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
3333
- if (typeof x === 'object') {
3509
+ _initOptions(x = {}, y, options = {}) {
3510
+ if (x && typeof x === 'object') {
3334
3511
  options = x;
3335
3512
  x = null;
3336
3513
  }
@@ -3363,13 +3540,11 @@ var TextMixin = {
3363
3540
  if (result.columnGap == null) {
3364
3541
  result.columnGap = 18;
3365
3542
  }
3366
- result.rotation = Number(options.rotation ?? 0) % 360;
3543
+ result.rotation = Number(result.rotation ?? 0) % 360;
3367
3544
  if (result.rotation < 0) result.rotation += 360;
3368
3545
  return result;
3369
3546
  },
3370
- _line(text) {
3371
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
3372
- let wrapper = arguments.length > 2 ? arguments[2] : undefined;
3547
+ _line(text, options = {}, wrapper) {
3373
3548
  this._fragment(text, this.x, this.y, options);
3374
3549
  if (wrapper) {
3375
3550
  const lineGap = options.lineGap || this._lineGap || 0;
@@ -3439,7 +3614,11 @@ var TextMixin = {
3439
3614
  }
3440
3615
  const renderedWidth = options.textWidth + wordSpacing * (options.wordCount - 1) + characterSpacing * (text.length - 1);
3441
3616
  if (options.link != null) {
3442
- this.link(x, y, renderedWidth, this.currentLineHeight(), options.link);
3617
+ const linkOptions = {};
3618
+ if (this._currentStructureElement && this._currentStructureElement.dictionary.data.S === 'Link') {
3619
+ linkOptions.structParent = this._currentStructureElement;
3620
+ }
3621
+ this.link(x, y, renderedWidth, this.currentLineHeight(), options.link, linkOptions);
3443
3622
  }
3444
3623
  if (options.goTo != null) {
3445
3624
  this.goTo(x, y, renderedWidth, this.currentLineHeight(), options.goTo);
@@ -3568,6 +3747,61 @@ var TextMixin = {
3568
3747
  }
3569
3748
  };
3570
3749
 
3750
+ const toBinaryString = bytes => {
3751
+ const chunkSize = 0x8000;
3752
+ let out = '';
3753
+ for (let i = 0; i < bytes.length; i += chunkSize) {
3754
+ const end = Math.min(i + chunkSize, bytes.length);
3755
+ out += String.fromCharCode.apply(null, bytes.subarray(i, end));
3756
+ }
3757
+ return out;
3758
+ };
3759
+ const readUInt16BE = (bytes, offset = 0) => (bytes[offset] << 8 | bytes[offset + 1]) >>> 0;
3760
+ const readUInt16LE = (bytes, offset = 0) => (bytes[offset + 1] << 8 | bytes[offset]) >>> 0;
3761
+ const readUInt32BE = (bytes, offset = 0) => bytes[offset] * 0x1000000 + (bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
3762
+ const readUInt32LE = (bytes, offset = 0) => (bytes[offset] | bytes[offset + 1] << 8 | bytes[offset + 2] << 16) + bytes[offset + 3] * 0x1000000 >>> 0;
3763
+
3764
+ const parseExifOrientation = data => {
3765
+ if (!data || data.length < 20) return null;
3766
+ let pos = 2;
3767
+ while (pos < data.length - 4) {
3768
+ while (pos < data.length && data[pos] !== 0xff) pos++;
3769
+ if (pos >= data.length - 4) return null;
3770
+ const marker = readUInt16BE(data, pos);
3771
+ pos += 2;
3772
+ if (marker === 0xffda) return null;
3773
+ if (marker >= 0xffd0 && marker <= 0xffd9 || marker === 0xff01) continue;
3774
+ if (pos + 2 > data.length) return null;
3775
+ const segmentLength = readUInt16BE(data, pos);
3776
+ if (marker === 0xffe1 && pos + 8 <= data.length) {
3777
+ const exifHeader = toBinaryString(data.subarray(pos + 2, pos + 8));
3778
+ if (exifHeader === 'Exif\x00\x00') {
3779
+ const tiffStart = pos + 8;
3780
+ if (tiffStart + 8 > data.length) return null;
3781
+ const byteOrder = toBinaryString(data.subarray(tiffStart, tiffStart + 2));
3782
+ const isLittleEndian = byteOrder === 'II';
3783
+ if (!isLittleEndian && byteOrder !== 'MM') return null;
3784
+ const read16 = isLittleEndian ? o => readUInt16LE(data, o) : o => readUInt16BE(data, o);
3785
+ const read32 = isLittleEndian ? o => readUInt32LE(data, o) : o => readUInt32BE(data, o);
3786
+ if (read16(tiffStart + 2) !== 42) return null;
3787
+ const ifdPos = tiffStart + read32(tiffStart + 4);
3788
+ if (ifdPos + 2 > data.length) return null;
3789
+ const entryCount = read16(ifdPos);
3790
+ for (let i = 0; i < entryCount; i++) {
3791
+ const entryPos = ifdPos + 2 + i * 12;
3792
+ if (entryPos + 12 > data.length) return null;
3793
+ if (read16(entryPos) === 0x0112) {
3794
+ const value = read16(entryPos + 8);
3795
+ return value >= 1 && value <= 8 ? value : null;
3796
+ }
3797
+ }
3798
+ return null;
3799
+ }
3800
+ }
3801
+ pos += segmentLength;
3802
+ }
3803
+ return null;
3804
+ };
3571
3805
  const MARKERS = [0xffc0, 0xffc1, 0xffc2, 0xffc3, 0xffc5, 0xffc6, 0xffc7, 0xffc8, 0xffc9, 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf];
3572
3806
  const COLOR_SPACE_MAP = {
3573
3807
  1: 'DeviceGray',
@@ -3582,9 +3816,11 @@ class JPEG {
3582
3816
  if (this.data.readUInt16BE(0) !== 0xffd8) {
3583
3817
  throw 'SOI not found in JPEG';
3584
3818
  }
3585
- this.orientation = exif.fromBuffer(this.data).Orientation || 1;
3819
+ this.orientation = parseExifOrientation(this.data) || 1;
3586
3820
  let pos = 2;
3587
3821
  while (pos < this.data.length) {
3822
+ while (pos < this.data.length && this.data[pos] !== 0xff) pos++;
3823
+ if (pos >= this.data.length) break;
3588
3824
  marker = this.data.readUInt16BE(pos);
3589
3825
  pos += 2;
3590
3826
  if (MARKERS.includes(marker)) {
@@ -3601,7 +3837,7 @@ class JPEG {
3601
3837
  pos += 2;
3602
3838
  this.width = this.data.readUInt16BE(pos);
3603
3839
  pos += 2;
3604
- const channels = this.data[pos++];
3840
+ const channels = this.data[pos + 1];
3605
3841
  this.colorSpace = COLOR_SPACE_MAP[channels];
3606
3842
  this.obj = null;
3607
3843
  }
@@ -3636,58 +3872,60 @@ class PNGImage {
3636
3872
  this.obj = null;
3637
3873
  }
3638
3874
  embed(document) {
3639
- let dataDecoded = false;
3640
3875
  this.document = document;
3641
3876
  if (this.obj) {
3642
3877
  return;
3643
3878
  }
3644
- const hasAlphaChannel = this.image.hasAlphaChannel;
3645
- const isInterlaced = this.image.interlaceMethod === 1;
3646
- this.obj = this.document.ref({
3879
+ const {
3880
+ image,
3881
+ height,
3882
+ width
3883
+ } = this;
3884
+ const hasAlphaChannel = image.hasAlphaChannel;
3885
+ const isInterlaced = image.interlaceMethod === 1;
3886
+ const obj = this.obj = document.ref({
3647
3887
  Type: 'XObject',
3648
3888
  Subtype: 'Image',
3649
- BitsPerComponent: hasAlphaChannel ? 8 : this.image.bits,
3650
- Width: this.width,
3651
- Height: this.height,
3889
+ BitsPerComponent: hasAlphaChannel ? 8 : image.bits,
3890
+ Width: width,
3891
+ Height: height,
3652
3892
  Filter: 'FlateDecode'
3653
3893
  });
3654
3894
  if (!hasAlphaChannel) {
3655
- const params = this.document.ref({
3895
+ const params = document.ref({
3656
3896
  Predictor: isInterlaced ? 1 : 15,
3657
- Colors: this.image.colors,
3658
- BitsPerComponent: this.image.bits,
3659
- Columns: this.width
3897
+ Colors: image.colors,
3898
+ BitsPerComponent: image.bits,
3899
+ Columns: width
3660
3900
  });
3661
- this.obj.data['DecodeParms'] = params;
3901
+ obj.data['DecodeParms'] = params;
3662
3902
  params.end();
3663
3903
  }
3664
- if (this.image.palette.length === 0) {
3665
- this.obj.data['ColorSpace'] = this.image.colorSpace;
3904
+ if (image.palette.length === 0) {
3905
+ obj.data['ColorSpace'] = image.colorSpace;
3666
3906
  } else {
3667
- const palette = this.document.ref();
3668
- palette.end(Buffer.from(this.image.palette));
3669
- this.obj.data['ColorSpace'] = ['Indexed', 'DeviceRGB', this.image.palette.length / 3 - 1, palette];
3670
- }
3671
- if (this.image.transparency.grayscale != null) {
3672
- const val = this.image.transparency.grayscale;
3673
- this.obj.data['Mask'] = [val, val];
3674
- } else if (this.image.transparency.rgb) {
3907
+ const palette = document.ref();
3908
+ palette.end(Buffer.from(image.palette));
3909
+ obj.data['ColorSpace'] = ['Indexed', 'DeviceRGB', image.palette.length / 3 - 1, palette];
3910
+ }
3911
+ if (image.transparency.grayscale != null) {
3912
+ const val = image.transparency.grayscale;
3913
+ obj.data['Mask'] = [val, val];
3914
+ } else if (image.transparency.rgb) {
3675
3915
  const {
3676
3916
  rgb
3677
- } = this.image.transparency;
3917
+ } = image.transparency;
3678
3918
  const mask = [];
3679
3919
  for (let x of rgb) {
3680
3920
  mask.push(x, x);
3681
3921
  }
3682
- this.obj.data['Mask'] = mask;
3683
- } else if (this.image.transparency.indexed) {
3684
- dataDecoded = true;
3922
+ obj.data['Mask'] = mask;
3923
+ } else if (image.transparency.indexed) {
3685
3924
  return this.loadIndexedAlphaChannel();
3686
3925
  } else if (hasAlphaChannel) {
3687
- dataDecoded = true;
3688
3926
  return this.splitAlphaChannel();
3689
3927
  }
3690
- if (isInterlaced && !dataDecoded) {
3928
+ if (isInterlaced && true) {
3691
3929
  return this.decodeData();
3692
3930
  }
3693
3931
  this.finalize();
@@ -3736,12 +3974,16 @@ class PNGImage {
3736
3974
  }
3737
3975
  loadIndexedAlphaChannel() {
3738
3976
  const transparency = this.image.transparency.indexed;
3977
+ const isInterlaced = this.image.interlaceMethod === 1;
3739
3978
  return this.image.decodePixels(pixels => {
3740
3979
  const alphaChannel = Buffer.alloc(this.width * this.height);
3741
3980
  let i = 0;
3742
3981
  for (let j = 0, end = pixels.length; j < end; j++) {
3743
3982
  alphaChannel[i++] = transparency[pixels[j]];
3744
3983
  }
3984
+ if (isInterlaced) {
3985
+ this.imgData = zlib.deflateSync(Buffer.from(pixels));
3986
+ }
3745
3987
  this.alphaChannel = zlib.deflateSync(alphaChannel);
3746
3988
  return this.finalize();
3747
3989
  });
@@ -3774,7 +4016,7 @@ class PDFImage {
3774
4016
  }
3775
4017
  if (data[0] === 0xff && data[1] === 0xd8) {
3776
4018
  return new JPEG(data, label);
3777
- } else if (data[0] === 0x89 && data.toString('ascii', 1, 4) === 'PNG') {
4019
+ } else if (data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4e && data[3] === 0x47) {
3778
4020
  return new PNGImage(data, label);
3779
4021
  } else {
3780
4022
  throw new Error('Unknown image format.');
@@ -3787,8 +4029,7 @@ var ImagesMixin = {
3787
4029
  this._imageRegistry = {};
3788
4030
  this._imageCount = 0;
3789
4031
  },
3790
- image(src, x, y) {
3791
- let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
4032
+ image(src, x, y, options = {}) {
3792
4033
  let bh, bp, bw, image, ip, left, left1, originX, originY;
3793
4034
  if (typeof x === 'object') {
3794
4035
  options = x;
@@ -3946,6 +4187,9 @@ var ImagesMixin = {
3946
4187
  this.y += h;
3947
4188
  }
3948
4189
  this.save();
4190
+ if (options.opacity != null) {
4191
+ this._doOpacity(options.opacity, null);
4192
+ }
3949
4193
  if (rotateAngle) {
3950
4194
  this.rotate(rotateAngle, {
3951
4195
  origin: [originX, originY]
@@ -3971,6 +4215,12 @@ var ImagesMixin = {
3971
4215
  }
3972
4216
  };
3973
4217
 
4218
+ class PDFAnnotationReference {
4219
+ constructor(annotationRef) {
4220
+ this.annotationRef = annotationRef;
4221
+ }
4222
+ }
4223
+
3974
4224
  var AnnotationsMixin = {
3975
4225
  annotate(x, y, w, h, options) {
3976
4226
  options.Type = 'Annot';
@@ -3988,17 +4238,22 @@ var AnnotationsMixin = {
3988
4238
  if (typeof options.Dest === 'string') {
3989
4239
  options.Dest = new String(options.Dest);
3990
4240
  }
4241
+ const structParent = options.structParent;
4242
+ delete options.structParent;
3991
4243
  for (let key in options) {
3992
4244
  const val = options[key];
3993
4245
  options[key[0].toUpperCase() + key.slice(1)] = val;
3994
4246
  }
3995
4247
  const ref = this.ref(options);
3996
4248
  this.page.annotations.push(ref);
4249
+ if (structParent && typeof structParent.add === 'function') {
4250
+ const annotRef = new PDFAnnotationReference(ref);
4251
+ structParent.add(annotRef);
4252
+ }
3997
4253
  ref.end();
3998
4254
  return this;
3999
4255
  },
4000
- note(x, y, w, h, contents) {
4001
- let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
4256
+ note(x, y, w, h, contents, options = {}) {
4002
4257
  options.Subtype = 'Text';
4003
4258
  options.Contents = new String(contents);
4004
4259
  if (options.Name == null) {
@@ -4009,8 +4264,7 @@ var AnnotationsMixin = {
4009
4264
  }
4010
4265
  return this.annotate(x, y, w, h, options);
4011
4266
  },
4012
- goTo(x, y, w, h, name) {
4013
- let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
4267
+ goTo(x, y, w, h, name, options = {}) {
4014
4268
  options.Subtype = 'Link';
4015
4269
  options.A = this.ref({
4016
4270
  S: 'GoTo',
@@ -4019,8 +4273,7 @@ var AnnotationsMixin = {
4019
4273
  options.A.end();
4020
4274
  return this.annotate(x, y, w, h, options);
4021
4275
  },
4022
- link(x, y, w, h, url) {
4023
- let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
4276
+ link(x, y, w, h, url, options = {}) {
4024
4277
  options.Subtype = 'Link';
4025
4278
  if (typeof url === 'number') {
4026
4279
  const pages = this._root.data.Pages.data;
@@ -4040,62 +4293,55 @@ var AnnotationsMixin = {
4040
4293
  });
4041
4294
  options.A.end();
4042
4295
  }
4296
+ if (options.structParent && !options.Contents) {
4297
+ options.Contents = new String('');
4298
+ }
4043
4299
  return this.annotate(x, y, w, h, options);
4044
4300
  },
4045
- _markup(x, y, w, h) {
4046
- let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
4301
+ _markup(x, y, w, h, options = {}) {
4047
4302
  const [x1, y1, x2, y2] = this._convertRect(x, y, w, h);
4048
4303
  options.QuadPoints = [x1, y2, x2, y2, x1, y1, x2, y1];
4049
4304
  options.Contents = new String();
4050
4305
  return this.annotate(x, y, w, h, options);
4051
4306
  },
4052
- highlight(x, y, w, h) {
4053
- let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
4307
+ highlight(x, y, w, h, options = {}) {
4054
4308
  options.Subtype = 'Highlight';
4055
4309
  if (options.color == null) {
4056
4310
  options.color = [241, 238, 148];
4057
4311
  }
4058
4312
  return this._markup(x, y, w, h, options);
4059
4313
  },
4060
- underline(x, y, w, h) {
4061
- let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
4314
+ underline(x, y, w, h, options = {}) {
4062
4315
  options.Subtype = 'Underline';
4063
4316
  return this._markup(x, y, w, h, options);
4064
4317
  },
4065
- strike(x, y, w, h) {
4066
- let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
4318
+ strike(x, y, w, h, options = {}) {
4067
4319
  options.Subtype = 'StrikeOut';
4068
4320
  return this._markup(x, y, w, h, options);
4069
4321
  },
4070
- lineAnnotation(x1, y1, x2, y2) {
4071
- let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
4322
+ lineAnnotation(x1, y1, x2, y2, options = {}) {
4072
4323
  options.Subtype = 'Line';
4073
4324
  options.Contents = new String();
4074
4325
  options.L = [x1, this.page.height - y1, x2, this.page.height - y2];
4075
4326
  return this.annotate(x1, y1, x2, y2, options);
4076
4327
  },
4077
- rectAnnotation(x, y, w, h) {
4078
- let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
4328
+ rectAnnotation(x, y, w, h, options = {}) {
4079
4329
  options.Subtype = 'Square';
4080
4330
  options.Contents = new String();
4081
4331
  return this.annotate(x, y, w, h, options);
4082
4332
  },
4083
- ellipseAnnotation(x, y, w, h) {
4084
- let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
4333
+ ellipseAnnotation(x, y, w, h, options = {}) {
4085
4334
  options.Subtype = 'Circle';
4086
4335
  options.Contents = new String();
4087
4336
  return this.annotate(x, y, w, h, options);
4088
4337
  },
4089
- textAnnotation(x, y, w, h, text) {
4090
- let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
4338
+ textAnnotation(x, y, w, h, text, options = {}) {
4091
4339
  options.Subtype = 'FreeText';
4092
4340
  options.Contents = new String(text);
4093
4341
  options.DA = new String();
4094
4342
  return this.annotate(x, y, w, h, options);
4095
4343
  },
4096
- fileAnnotation(x, y, w, h) {
4097
- let file = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
4098
- let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
4344
+ fileAnnotation(x, y, w, h, file = {}, options = {}) {
4099
4345
  const filespec = this.file(file.src, Object.assign({
4100
4346
  hidden: true
4101
4347
  }, file));
@@ -4121,16 +4367,26 @@ var AnnotationsMixin = {
4121
4367
  }
4122
4368
  };
4123
4369
 
4370
+ const DEFAULT_OPTIONS = {
4371
+ top: 0,
4372
+ left: 0,
4373
+ zoom: 0,
4374
+ fit: true,
4375
+ pageNumber: null,
4376
+ expanded: false
4377
+ };
4124
4378
  class PDFOutline {
4125
- constructor(document, parent, title, dest) {
4126
- let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
4127
- expanded: false
4128
- };
4379
+ constructor(document, parent, title, dest, options = DEFAULT_OPTIONS) {
4129
4380
  this.document = document;
4130
4381
  this.options = options;
4131
4382
  this.outlineData = {};
4132
4383
  if (dest !== null) {
4133
- this.outlineData['Dest'] = [dest.dictionary, 'Fit'];
4384
+ const destWidth = dest.data.MediaBox[2];
4385
+ const destHeight = dest.data.MediaBox[3];
4386
+ const top = destHeight - (options.top || 0);
4387
+ const left = destWidth - (options.left || 0);
4388
+ const zoom = options.zoom || 0;
4389
+ this.outlineData['Dest'] = options.fit ? [dest, 'Fit'] : [dest, 'XYZ', left, top, zoom];
4134
4390
  }
4135
4391
  if (parent !== null) {
4136
4392
  this.outlineData['Parent'] = parent;
@@ -4141,11 +4397,10 @@ class PDFOutline {
4141
4397
  this.dictionary = this.document.ref(this.outlineData);
4142
4398
  this.children = [];
4143
4399
  }
4144
- addItem(title) {
4145
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
4146
- expanded: false
4147
- };
4148
- const result = new PDFOutline(this.document, this.dictionary, title, this.document.page, options);
4400
+ addItem(title, options = DEFAULT_OPTIONS) {
4401
+ const pages = this.document._root.data.Pages.data.Kids;
4402
+ const dest = options.pageNumber != null ? pages[options.pageNumber] : this.document.page.dictionary;
4403
+ const result = new PDFOutline(this.document, this.dictionary, title, dest, options);
4149
4404
  this.children.push(result);
4150
4405
  return result;
4151
4406
  }
@@ -4181,7 +4436,7 @@ var OutlineMixin = {
4181
4436
  this.outline.endOutline();
4182
4437
  if (this.outline.children.length > 0) {
4183
4438
  this._root.data.Outlines = this.outline.dictionary;
4184
- return this._root.data.PageMode = 'UseOutlines';
4439
+ return this._root.data.PageMode = this._root.data.PageMode || 'UseOutlines';
4185
4440
  }
4186
4441
  }
4187
4442
  };
@@ -4199,9 +4454,7 @@ class PDFStructureContent {
4199
4454
  }
4200
4455
 
4201
4456
  class PDFStructureElement {
4202
- constructor(document, type) {
4203
- let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
4204
- let children = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
4457
+ constructor(document, type, options = {}, children = null) {
4205
4458
  this.document = document;
4206
4459
  this._attached = false;
4207
4460
  this._ended = false;
@@ -4214,21 +4467,41 @@ class PDFStructureElement {
4214
4467
  children = options;
4215
4468
  options = {};
4216
4469
  }
4217
- if (typeof options.title !== 'undefined') {
4470
+ if (options.title) {
4218
4471
  data.T = new String(options.title);
4219
4472
  }
4220
- if (typeof options.lang !== 'undefined') {
4473
+ if (options.lang) {
4221
4474
  data.Lang = new String(options.lang);
4222
4475
  }
4223
- if (typeof options.alt !== 'undefined') {
4476
+ if (options.alt) {
4224
4477
  data.Alt = new String(options.alt);
4225
4478
  }
4226
- if (typeof options.expanded !== 'undefined') {
4479
+ if (options.expanded) {
4227
4480
  data.E = new String(options.expanded);
4228
4481
  }
4229
- if (typeof options.actual !== 'undefined') {
4482
+ if (options.actual) {
4230
4483
  data.ActualText = new String(options.actual);
4231
4484
  }
4485
+ const hasBbox = Array.isArray(options.bbox) && options.bbox.length === 4;
4486
+ const hasPlacement = typeof options.placement === 'string';
4487
+ if (hasBbox || hasPlacement) {
4488
+ const attrs = {
4489
+ O: 'Layout'
4490
+ };
4491
+ attrs.Placement = hasPlacement ? options.placement : 'Block';
4492
+ if (hasBbox) {
4493
+ const height = document.page.height;
4494
+ attrs.BBox = [options.bbox[0], height - options.bbox[3], options.bbox[2], height - options.bbox[1]];
4495
+ }
4496
+ data.A = attrs;
4497
+ }
4498
+ if (options.scope) {
4499
+ data.A = {
4500
+ ...(data.A || {}),
4501
+ O: 'Table',
4502
+ Scope: options.scope
4503
+ };
4504
+ }
4232
4505
  this._children = [];
4233
4506
  if (children) {
4234
4507
  if (!Array.isArray(children)) {
@@ -4254,6 +4527,9 @@ class PDFStructureElement {
4254
4527
  if (child instanceof PDFStructureContent) {
4255
4528
  this._addContentToParentTree(child);
4256
4529
  }
4530
+ if (child instanceof PDFAnnotationReference) {
4531
+ this._addAnnotationToParentTree(child.annotationRef);
4532
+ }
4257
4533
  if (typeof child === 'function' && this._attached) {
4258
4534
  child = this._contentForClosure(child);
4259
4535
  }
@@ -4261,15 +4537,20 @@ class PDFStructureElement {
4261
4537
  return this;
4262
4538
  }
4263
4539
  _addContentToParentTree(content) {
4264
- content.refs.forEach(_ref => {
4265
- let {
4266
- pageRef,
4267
- mcid
4268
- } = _ref;
4540
+ content.refs.forEach(({
4541
+ pageRef,
4542
+ mcid
4543
+ }) => {
4269
4544
  const pageStructParents = this.document.getStructParentTree().get(pageRef.data.StructParents);
4270
4545
  pageStructParents[mcid] = this.dictionary;
4271
4546
  });
4272
4547
  }
4548
+ _addAnnotationToParentTree(annotRef) {
4549
+ const parentTreeKey = this.document.createStructParentTreeNextKey();
4550
+ annotRef.data.StructParent = parentTreeKey;
4551
+ const parentTree = this.document.getStructParentTree();
4552
+ parentTree.add(parentTreeKey, this.dictionary);
4553
+ }
4273
4554
  setParent(parentRef) {
4274
4555
  if (this.dictionary.data.P) {
4275
4556
  throw new Error(`Structure element added to more than one parent`);
@@ -4301,11 +4582,17 @@ class PDFStructureElement {
4301
4582
  this._flush();
4302
4583
  }
4303
4584
  _isValidChild(child) {
4304
- return child instanceof PDFStructureElement || child instanceof PDFStructureContent || typeof child === 'function';
4585
+ return child instanceof PDFStructureElement || child instanceof PDFStructureContent || child instanceof PDFAnnotationReference || typeof child === 'function';
4305
4586
  }
4306
4587
  _contentForClosure(closure) {
4307
4588
  const content = this.document.markStructureContent(this.dictionary.data.S);
4589
+ const prevStructElement = this.document._currentStructureElement;
4590
+ this.document._currentStructureElement = this;
4591
+ const wasEnded = this._ended;
4592
+ this._ended = false;
4308
4593
  closure();
4594
+ this._ended = wasEnded;
4595
+ this.document._currentStructureElement = prevStructElement;
4309
4596
  this.document.endMarkedContent();
4310
4597
  this._addContentToParentTree(content);
4311
4598
  return content;
@@ -4340,11 +4627,10 @@ class PDFStructureElement {
4340
4627
  this.dictionary.data.K.push(child.dictionary);
4341
4628
  }
4342
4629
  if (child instanceof PDFStructureContent) {
4343
- child.refs.forEach(_ref2 => {
4344
- let {
4345
- pageRef,
4346
- mcid
4347
- } = _ref2;
4630
+ child.refs.forEach(({
4631
+ pageRef,
4632
+ mcid
4633
+ }) => {
4348
4634
  if (!this.dictionary.data.Pg) {
4349
4635
  this.dictionary.data.Pg = pageRef;
4350
4636
  }
@@ -4359,6 +4645,15 @@ class PDFStructureElement {
4359
4645
  }
4360
4646
  });
4361
4647
  }
4648
+ if (child instanceof PDFAnnotationReference) {
4649
+ const pageRef = this.document.page.dictionary;
4650
+ const objr = {
4651
+ Type: 'OBJR',
4652
+ Obj: child.annotationRef,
4653
+ Pg: pageRef
4654
+ };
4655
+ this.dictionary.data.K.push(objr);
4656
+ }
4362
4657
  }
4363
4658
  }
4364
4659
 
@@ -4382,8 +4677,7 @@ var MarkingsMixin = {
4382
4677
  this.getStructTreeRoot();
4383
4678
  }
4384
4679
  },
4385
- markContent(tag) {
4386
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
4680
+ markContent(tag, options = null) {
4387
4681
  if (tag === 'Artifact' || options && options.mcid) {
4388
4682
  let toClose = 0;
4389
4683
  this.page.markings.forEach(marking => {
@@ -4438,8 +4732,7 @@ var MarkingsMixin = {
4438
4732
  this.addContent(`/${tag} ${PDFObject.convert(dictionary)} BDC`);
4439
4733
  return this;
4440
4734
  },
4441
- markStructureContent(tag) {
4442
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
4735
+ markStructureContent(tag, options = {}) {
4443
4736
  const pageStructParents = this.getStructParentTree().get(this.page.structParentTreeKey);
4444
4737
  const mcid = pageStructParents.length;
4445
4738
  pageStructParents.push(null);
@@ -4454,11 +4747,16 @@ var MarkingsMixin = {
4454
4747
  endMarkedContent() {
4455
4748
  this.page.markings.pop();
4456
4749
  this.addContent('EMC');
4750
+ if (this._textOptions) {
4751
+ delete this._textOptions.link;
4752
+ delete this._textOptions.goTo;
4753
+ delete this._textOptions.destination;
4754
+ delete this._textOptions.underline;
4755
+ delete this._textOptions.strike;
4756
+ }
4457
4757
  return this;
4458
4758
  },
4459
- struct(type) {
4460
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
4461
- let children = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
4759
+ struct(type, options = {}, children = null) {
4462
4760
  return new PDFStructureElement(this, type, options, children);
4463
4761
  },
4464
4762
  addStructure(structElem) {
@@ -4623,15 +4921,13 @@ var AcroFormMixin = {
4623
4921
  }
4624
4922
  return this;
4625
4923
  },
4626
- formField(name) {
4627
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
4924
+ formField(name, options = {}) {
4628
4925
  let fieldDict = this._fieldDict(name, null, options);
4629
4926
  let fieldRef = this.ref(fieldDict);
4630
4927
  this._addToParent(fieldRef);
4631
4928
  return fieldRef;
4632
4929
  },
4633
- formAnnotation(name, type, x, y, w, h) {
4634
- let options = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {};
4930
+ formAnnotation(name, type, x, y, w, h, options = {}) {
4635
4931
  let fieldDict = this._fieldDict(name, type, options);
4636
4932
  fieldDict.Subtype = 'Widget';
4637
4933
  if (fieldDict.F === undefined) {
@@ -4641,28 +4937,22 @@ var AcroFormMixin = {
4641
4937
  let annotRef = this.page.annotations[this.page.annotations.length - 1];
4642
4938
  return this._addToParent(annotRef);
4643
4939
  },
4644
- formText(name, x, y, w, h) {
4645
- let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
4940
+ formText(name, x, y, w, h, options = {}) {
4646
4941
  return this.formAnnotation(name, 'text', x, y, w, h, options);
4647
4942
  },
4648
- formPushButton(name, x, y, w, h) {
4649
- let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
4943
+ formPushButton(name, x, y, w, h, options = {}) {
4650
4944
  return this.formAnnotation(name, 'pushButton', x, y, w, h, options);
4651
4945
  },
4652
- formCombo(name, x, y, w, h) {
4653
- let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
4946
+ formCombo(name, x, y, w, h, options = {}) {
4654
4947
  return this.formAnnotation(name, 'combo', x, y, w, h, options);
4655
4948
  },
4656
- formList(name, x, y, w, h) {
4657
- let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
4949
+ formList(name, x, y, w, h, options = {}) {
4658
4950
  return this.formAnnotation(name, 'list', x, y, w, h, options);
4659
4951
  },
4660
- formRadioButton(name, x, y, w, h) {
4661
- let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
4952
+ formRadioButton(name, x, y, w, h, options = {}) {
4662
4953
  return this.formAnnotation(name, 'radioButton', x, y, w, h, options);
4663
4954
  },
4664
- formCheckbox(name, x, y, w, h) {
4665
- let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
4955
+ formCheckbox(name, x, y, w, h, options = {}) {
4666
4956
  return this.formAnnotation(name, 'checkbox', x, y, w, h, options);
4667
4957
  },
4668
4958
  _addToParent(fieldRef) {
@@ -4677,8 +4967,7 @@ var AcroFormMixin = {
4677
4967
  }
4678
4968
  return this;
4679
4969
  },
4680
- _fieldDict(name, type) {
4681
- let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
4970
+ _fieldDict(name, type, options = {}) {
4682
4971
  if (!this._acroform) {
4683
4972
  throw new Error('Call document.initForm() method before adding form elements to document');
4684
4973
  }
@@ -4867,8 +5156,7 @@ var AcroFormMixin = {
4867
5156
  };
4868
5157
 
4869
5158
  var AttachmentsMixin = {
4870
- file(src) {
4871
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
5159
+ file(src, options = {}) {
4872
5160
  options.name = options.name || src;
4873
5161
  options.relationship = options.relationship || 'Unspecified';
4874
5162
  const refBody = {
@@ -4887,7 +5175,7 @@ var AttachmentsMixin = {
4887
5175
  const match = /^data:(.*?);base64,(.*)$/.exec(src);
4888
5176
  if (match) {
4889
5177
  if (match[1]) {
4890
- refBody.Subtype = match[1].replace('/', '#2F');
5178
+ refBody.Subtype = escapeName(match[1]);
4891
5179
  }
4892
5180
  data = Buffer.from(match[2], 'base64');
4893
5181
  } else {
@@ -4910,9 +5198,9 @@ var AttachmentsMixin = {
4910
5198
  refBody.Params.ModDate = options.modifiedDate;
4911
5199
  }
4912
5200
  if (options.type) {
4913
- refBody.Subtype = options.type.replace('/', '#2F');
5201
+ refBody.Subtype = escapeName(options.type);
4914
5202
  }
4915
- const checksum = CryptoJS.MD5(CryptoJS.lib.WordArray.create(new Uint8Array(data)));
5203
+ const checksum = md5Hex(new Uint8Array(data));
4916
5204
  refBody.Params.CheckSum = new String(checksum);
4917
5205
  refBody.Params.Size = data.byteLength;
4918
5206
  let ref;
@@ -5051,10 +5339,10 @@ const ROW_FIELDS = ['height', 'minHeight', 'maxHeight'];
5051
5339
  const COLUMN_FIELDS = ['width', 'minWidth', 'maxWidth'];
5052
5340
  function memoize(fn, maxSize) {
5053
5341
  const cache = new Map();
5054
- return function () {
5055
- const key = arguments.length <= 0 ? undefined : arguments[0];
5342
+ return function (...args) {
5343
+ const key = args[0];
5056
5344
  if (!cache.has(key)) {
5057
- cache.set(key, fn(...arguments));
5345
+ cache.set(key, fn(...args));
5058
5346
  if (cache.size > maxSize) cache.delete(cache.keys().next());
5059
5347
  }
5060
5348
  return cache.get(key);
@@ -5063,12 +5351,9 @@ function memoize(fn, maxSize) {
5063
5351
  function isObject(item) {
5064
5352
  return item && typeof item === 'object' && !Array.isArray(item);
5065
5353
  }
5066
- function deepMerge(target) {
5354
+ function deepMerge(target, ...sources) {
5067
5355
  if (!isObject(target)) return target;
5068
5356
  target = deepClone(target);
5069
- for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
5070
- sources[_key - 1] = arguments[_key];
5071
- }
5072
5357
  for (const source of sources) {
5073
5358
  if (isObject(source)) {
5074
5359
  for (const key in source) {
@@ -5097,14 +5382,8 @@ function normalizedDefaultStyle(defaultStyleInternal) {
5097
5382
  if (typeof defaultStyle !== 'object') defaultStyle = {
5098
5383
  text: defaultStyle
5099
5384
  };
5100
- const defaultRowStyle = Object.fromEntries(Object.entries(defaultStyle).filter(_ref => {
5101
- let [k] = _ref;
5102
- return ROW_FIELDS.includes(k);
5103
- }));
5104
- const defaultColStyle = Object.fromEntries(Object.entries(defaultStyle).filter(_ref2 => {
5105
- let [k] = _ref2;
5106
- return COLUMN_FIELDS.includes(k);
5107
- }));
5385
+ const defaultRowStyle = Object.fromEntries(Object.entries(defaultStyle).filter(([k]) => ROW_FIELDS.includes(k)));
5386
+ const defaultColStyle = Object.fromEntries(Object.entries(defaultStyle).filter(([k]) => COLUMN_FIELDS.includes(k)));
5108
5387
  defaultStyle.padding = normalizeSides(defaultStyle.padding);
5109
5388
  defaultStyle.border = normalizeSides(defaultStyle.border);
5110
5389
  defaultStyle.borderColor = normalizeSides(defaultStyle.borderColor);
@@ -5564,7 +5843,7 @@ function renderRow(row, rowIndex) {
5564
5843
  function renderCell(cell, rowStruct) {
5565
5844
  const cellRenderer = () => {
5566
5845
  if (cell.backgroundColor != null) {
5567
- this.document.save().rect(cell.x, cell.y, cell.width, cell.height).fill(cell.backgroundColor).restore();
5846
+ this.document.save().fillColor(cell.backgroundColor).rect(cell.x, cell.y, cell.width, cell.height).fill().restore();
5568
5847
  }
5569
5848
  renderBorder.call(this, cell.border, cell.borderColor, cell.x, cell.y, cell.width, cell.height);
5570
5849
  if (cell.debug) {
@@ -5621,34 +5900,30 @@ function renderCellText(cell) {
5621
5900
  if (cell.font) doc.font(rollbackFont, rollbackFontFamily, rollbackFontSize);
5622
5901
  }
5623
5902
  function renderBorder(border, borderColor, x, y, width, height, mask) {
5624
- border = Object.fromEntries(Object.entries(border).map(_ref => {
5625
- let [k, v] = _ref;
5626
- return [k, mask && !mask[k] ? 0 : v];
5627
- }));
5903
+ border = Object.fromEntries(Object.entries(border).map(([k, v]) => [k, mask && !mask[k] ? 0 : v]));
5628
5904
  const doc = this.document;
5629
5905
  if ([border.right, border.bottom, border.left].every(val => val === border.top)) {
5630
5906
  if (border.top > 0) {
5631
- doc.save().lineWidth(border.top).rect(x, y, width, height).stroke(borderColor.top).restore();
5907
+ doc.save().lineWidth(border.top).strokeColor(borderColor.top).rect(x, y, width, height).stroke().restore();
5632
5908
  }
5633
5909
  } else {
5634
5910
  if (border.top > 0) {
5635
- doc.save().lineWidth(border.top).moveTo(x, y).lineTo(x + width, y).stroke(borderColor.top).restore();
5911
+ doc.save().lineWidth(border.top).moveTo(x, y).strokeColor(borderColor.top).lineTo(x + width, y).stroke().restore();
5636
5912
  }
5637
5913
  if (border.right > 0) {
5638
- doc.save().lineWidth(border.right).moveTo(x + width, y).lineTo(x + width, y + height).stroke(borderColor.right).restore();
5914
+ doc.save().lineWidth(border.right).moveTo(x + width, y).strokeColor(borderColor.right).lineTo(x + width, y + height).stroke().restore();
5639
5915
  }
5640
5916
  if (border.bottom > 0) {
5641
- doc.save().lineWidth(border.bottom).moveTo(x + width, y + height).lineTo(x, y + height).stroke(borderColor.bottom).restore();
5917
+ doc.save().lineWidth(border.bottom).moveTo(x + width, y + height).strokeColor(borderColor.bottom).lineTo(x, y + height).stroke().restore();
5642
5918
  }
5643
5919
  if (border.left > 0) {
5644
- doc.save().lineWidth(border.left).moveTo(x, y + height).lineTo(x, y).stroke(borderColor.left).restore();
5920
+ doc.save().lineWidth(border.left).moveTo(x, y + height).strokeColor(borderColor.left).lineTo(x, y).stroke().restore();
5645
5921
  }
5646
5922
  }
5647
5923
  }
5648
5924
 
5649
5925
  class PDFTable {
5650
- constructor(document) {
5651
- let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
5926
+ constructor(document, opts = {}) {
5652
5927
  this.document = document;
5653
5928
  this.opts = Object.freeze(opts);
5654
5929
  normalizeTable.call(this);
@@ -5660,8 +5935,7 @@ class PDFTable {
5660
5935
  return this.end();
5661
5936
  }
5662
5937
  }
5663
- row(row) {
5664
- let lastRow = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
5938
+ row(row, lastRow = false) {
5665
5939
  if (this._ended) {
5666
5940
  throw new Error(`Table was marked as ended on row ${this._currRowIndex}`);
5667
5941
  }
@@ -5712,8 +5986,7 @@ class PDFMetadata {
5712
5986
  <?xpacket end="w"?>
5713
5987
  `);
5714
5988
  }
5715
- append(xml) {
5716
- let newline = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
5989
+ append(xml, newline = true) {
5717
5990
  this._metadata = this._metadata.concat(xml);
5718
5991
  if (newline) this._metadata = this._metadata.concat('\n');
5719
5992
  }
@@ -5733,8 +6006,7 @@ var MetadataMixin = {
5733
6006
  initMetadata() {
5734
6007
  this.metadata = new PDFMetadata();
5735
6008
  },
5736
- appendXML(xml) {
5737
- let newline = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
6009
+ appendXML(xml, newline = true) {
5738
6010
  this.metadata.append(xml, newline);
5739
6011
  },
5740
6012
  _addInfo() {
@@ -5781,7 +6053,7 @@ var MetadataMixin = {
5781
6053
  }
5782
6054
  this.appendXML(`
5783
6055
  <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
5784
- <pdf:Producer>${this.info.Creator}</pdf:Producer>`, false);
6056
+ <pdf:Producer>${this.info.Producer}</pdf:Producer>`, false);
5785
6057
  if (this.info.Keywords) {
5786
6058
  this.appendXML(`
5787
6059
  <pdf:Keywords>${this.info.Keywords}</pdf:Keywords>`, false);
@@ -5808,8 +6080,7 @@ var MetadataMixin = {
5808
6080
  };
5809
6081
 
5810
6082
  class PDFDocument extends stream.Readable {
5811
- constructor() {
5812
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6083
+ constructor(options = {}) {
5813
6084
  super(options);
5814
6085
  this.options = options;
5815
6086
  switch (options.pdfVersion) {
@@ -5853,6 +6124,10 @@ class PDFDocument extends stream.Readable {
5853
6124
  if (this.options.lang) {
5854
6125
  this._root.data.Lang = new String(this.options.lang);
5855
6126
  }
6127
+ if (this.options.pageLayout) {
6128
+ const layout = this.options.pageLayout;
6129
+ this._root.data.PageLayout = layout.charAt(0).toUpperCase() + layout.slice(1);
6130
+ }
5856
6131
  this.page = null;
5857
6132
  this.initMetadata();
5858
6133
  this.initColor();
@@ -5937,10 +6212,7 @@ class PDFDocument extends stream.Readable {
5937
6212
  page.end();
5938
6213
  }
5939
6214
  }
5940
- addNamedDestination(name) {
5941
- for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
5942
- args[_key - 1] = arguments[_key];
5943
- }
6215
+ addNamedDestination(name, ...args) {
5944
6216
  if (args.length === 0) {
5945
6217
  args = ['XYZ', null, null, null];
5946
6218
  }