3

I need to modify a PDF on a Apps script application. To do that I want to use a JS library : PDF-LIB

my code :

eval(UrlFetchApp.fetch("https://unpkg.com/pdf-lib/dist/pdf-lib.js").getContentText());

function modifyPdf() {
  const url = 'https://pdf-lib.js.org/assets/with_update_sections.pdf'
  const existingPdfBytes = UrlFetchApp.fetch(url).getContentText();

  const pdfDoc = PDFDocument.load(existingPdfBytes)
  const helveticaFont = pdfDoc.embedFont(StandardFonts.Helvetica)

  const pages = pdfDoc.getPages()
  const firstPage = pages[0]
  const { width, height } = firstPage.getSize()
  firstPage.drawText('This text was added with JavaScript!', {
    x: 5,
    y: height / 2 + 300,
    size: 50,
    font: helveticaFont,
    color: rgb(0.95, 0.1, 0.1),
    rotate: degrees(-45),
  })

  const pdfBytes = pdfDoc.save()
}

When I execute the function modifyPDF I have :

Error
ReferenceError: PDFDocument is not defined modifyPdf @ modifie_pdf.gs:7

Do you know how I can import the js lib on my Apps script application ?

3
  • You can download the pdf-lib.js as a file. And paste its contents into your code. Something like here (external lib to parse YAML): stackoverflow.com/questions/71327482/… Commented Jul 29, 2022 at 12:37
  • I tried but it didn't work. It can't find PDFDocument again Commented Jul 29, 2022 at 13:11
  • Technically you can include a library into your project this way. If the code from this library doesn't work it is another matter. It's quite likely that the code can't do on Google servers the same things as in the local browser. Commented Jul 29, 2022 at 16:15

1 Answer 1

7
  • The evaluated global variable namespace is PDFLib. So, all variables like rgb, degrees, PDFDocument are keys of this object and should be referenced as such.

  • Most functions present in the library use promises, which, although is not supported by apps script functionally, it is supported syntactically. Therefore, async, await should be used, else you'll only get promise objects and not the actual document or font

  • The library uses setTimeout, which is not available in apps script. I used Utilities.sleep to simulate it's behavior.

  • getContentText() returns text and not binary content. Use getContent() to get byte[] instead and cast it to Uint8Array

eval(UrlFetchApp.fetch("https://unpkg.com/pdf-lib/dist/pdf-lib.js").getContentText());
/*+++simulate setTimeout*/setTimeout = (func, sleep) => (Utilities.sleep(sleep),func())

async function modifyPdf() {
  const url = 'https://pdf-lib.js.org/assets/with_update_sections.pdf'
  const existingPdfBytes = new /*cast to uint8*/Uint8Array(/*returns byte[]*/UrlFetchApp.fetch(url).getContent/*---Text*/());
  /*+++ simulate import*/const { PDFDocument, StandardFonts, rgb, degrees} = PDFLib;
  const pdfDoc = /*+++*/await PDFDocument.load(existingPdfBytes)
  const helveticaFont = /*+++*/ await pdfDoc.embedFont(StandardFonts.Helvetica)

  const pages = pdfDoc.getPages()
  const firstPage = pages[0]
  const { width, height } = firstPage.getSize()
  firstPage.drawText(`This text was added with JavaScript\n\n${' '.repeat(10)}(Google Apps script)!`, {
    x: width/10 + 60,
    y: height/10 + 120,
    size: 40,
    font: helveticaFont,
    color: rgb(0.1, 0.1, 0.1),
    rotate: degrees(50),
    opacity: 0.5,
  })

  const pdfBytes = /*+++*/await pdfDoc.save();
  /*+++*/DriveApp.createFile(Utilities.newBlob(pdfBytes).setName('newpdf from apps script'))
}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.