Repository: Hopding/pdf-lib
Pull request #1011 (2021-10-01 20:16:56)

Tweaks to #986
Followup to https://github.com/Hopding/pdf-lib/pull/986.


Patch:
diff --git a/src/api/PDFDocument.ts b/src/api/PDFDocument.ts
index d5b3075..e102368 100644
--- a/src/api/PDFDocument.ts
+++ b/src/api/PDFDocument.ts
@@ -735,6 +735,54 @@ export default class PDFDocument {
     return copiedPages;
   }
 
+  /**
+   * Get a copy of this document.
+   *
+   * For example:
+   * ```js
+   * const srcDoc = await PDFDocument.load(...)
+   * const pdfDoc = await srcDoc.copy()
+   * ```
+   *
+   * > **NOTE:**  This method won't copy all information over to the new
+   * > document (acroforms, outlines, etc...).
+   *
+   * @returns Resolves with a copy this document.
+   */
+  async copy(): Promise<PDFDocument> {
+    const pdfCopy = await PDFDocument.create();
+    const contentPages = await pdfCopy.copyPages(this, this.getPageIndices());
+
+    for (let idx = 0, len = contentPages.length; idx < len; idx++) {
+      pdfCopy.addPage(contentPages[idx]);
+    }
+
+    if (this.getAuthor() !== undefined) {
+      pdfCopy.setAuthor(this.getAuthor()!);
+    }
+    if (this.getCreationDate() !== undefined) {
+      pdfCopy.setCreationDate(this.getCreationDate()!);
+    }
+    if (this.getCreator() !== undefined) {
+      pdfCopy.setCreator(this.getCreator()!);
+    }
+    if (this.getModificationDate() !== undefined) {
+      pdfCopy.setModificationDate(this.getModificationDate()!);
+    }
+    if (this.getProducer() !== undefined) {
+      pdfCopy.setProducer(this.getProducer()!);
+    }
+    if (this.getSubject() !== undefined) {
+      pdfCopy.setSubject(this.getSubject()!);
+    }
+    if (this.getTitle() !== undefined) {
+      pdfCopy.setTitle(this.getTitle()!);
+    }
+    pdfCopy.defaultWordBreaks = this.defaultWordBreaks;
+
+    return pdfCopy;
+  }
+
   /**
    * Add JavaScript to this document. The supplied `script` is executed when the
    * document is opened. The `script` can be used to perform some operation


Test patch:
diff --git a/tests/api/PDFDocument.spec.ts b/tests/api/PDFDocument.spec.ts
index b8baa66..1b42e75 100644
--- a/tests/api/PDFDocument.spec.ts
+++ b/tests/api/PDFDocument.spec.ts
@@ -488,3 +488,47 @@ describe(`PDFDocument`, () => {
     });
   });
 });
+
+describe(`copy() method`, () => {
+  let pdfDoc: PDFDocument;
+  let srcDoc: PDFDocument;
+  beforeAll(async () => {
+    const parseSpeed = ParseSpeeds.Fastest;
+    srcDoc = await PDFDocument.load(unencryptedPdfBytes, { parseSpeed });
+    const title = '🥚 The Life of an Egg 🍳';
+    const author = 'Humpty Dumpty';
+    const subject = '📘 An Epic Tale of Woe 📖';
+    const keywords = ['eggs', 'wall', 'fall', 'king', 'horses', 'men', '🥚'];
+    const producer = 'PDF App 9000 🤖';
+    const creator = 'PDF App 8000 🤖';
+
+    // Milliseconds  will not get saved, so these dates do not have milliseconds.
+    const creationDate = new Date('1997-08-15T01:58:37Z');
+    const modificationDate = new Date('2018-12-21T07:00:11Z');
+
+    srcDoc.setTitle(title);
+    srcDoc.setAuthor(author);
+    srcDoc.setSubject(subject);
+    srcDoc.setKeywords(keywords);
+    srcDoc.setProducer(producer);
+    srcDoc.setCreator(creator);
+    srcDoc.setCreationDate(creationDate);
+    srcDoc.setModificationDate(modificationDate);
+    pdfDoc = await srcDoc.copy();
+  });
+  
+  it(`Returns a pdf with the same number of pages`, async () => {
+    expect(pdfDoc.getPageCount()).toBe(srcDoc.getPageCount());
+  });
+  
+  it(`Can copy author, creationDate, creator, producer, subject, title, defaultWordBreaks`, async () => {
+    expect(pdfDoc.getAuthor()).toBe(srcDoc.getAuthor());
+    expect(pdfDoc.getCreationDate()).toStrictEqual(srcDoc.getCreationDate());
+    expect(pdfDoc.getCreator()).toBe(srcDoc.getCreator());
+    expect(pdfDoc.getModificationDate()).toStrictEqual(srcDoc.getModificationDate());
+    expect(pdfDoc.getProducer()).toBe(srcDoc.getProducer());
+    expect(pdfDoc.getSubject()).toBe(srcDoc.getSubject());
+    expect(pdfDoc.getTitle()).toBe(srcDoc.getTitle());
+    expect(pdfDoc.defaultWordBreaks).toEqual(srcDoc.defaultWordBreaks);
+  });
+});
\ No newline at end of file