How to use a external Javascript library (PDF lib) in Apps script?
Asked Answered
D

1

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 ?

Deluge answered 29/7, 2022 at 11:59 Comment(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): #71327982Dibromide
I tried but it didn't work. It can't find PDFDocument againDeluge
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.Dibromide
P
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'))
}

Plier answered 30/7, 2022 at 10:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.