HTML to PDF Action - NodeJS & PHP [Open Source]

Thanks, but where should I place those head parameters?

At the top of whatever Html you are passing in body field. Body does not mean html body tag. You can have head tag in the html you pass here.

1 Like

@salvuccicarlos Finally got around to trying puppeteer in Docker, and I was able to get it to work easily.
Here are the steps that might help others too. You will still have to run npm install pup... in terminal or add in packages and re-install packages from bottom toolbar first.
Although you can move that step to Dockerfile described below, I have not done that to keep the first part same as other Wappler NodeJS Extension installations.

  1. There is a file called Dockerfile for each Docker based target. This file can be found in .wappler/targets/{{target_name}}/web/Dockerfile
  2. This file usually looks like this for a local development server:
FROM wapplerio/node-14

ENV NODE_ENV development
WORKDIR /opt/node_app
COPY package.json .
RUN npm install --no-optional
CMD [ "nodemon", "--legacy-watch", "./index.js" ]
  1. To allow puppeteer to find Chromium, we need to install it at the time of Docker image creation, which is done using the file above. As per the library’s documentation, I add a few lines of code and this is what my Dockerfile looks like now:
FROM wapplerio/node-14

ENV NODE_ENV development
WORKDIR /opt/node_app
COPY package.json .
RUN npm install --no-optional
RUN apt-get update \
    && apt-get install -y wget gnupg \
    && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
    && apt-get update \
    && apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \
      --no-install-recommends \
    && rm -rf /var/lib/apt/lists/*
CMD [ "nodemon", "--legacy-watch", "./index.js" ]
  1. Save this, and click DEPLOY in the bottom toolbar to re-deploy the image.
  2. In the logs, you should see that it will take a bit more time than usual during deployment, since it now also runs additional RUN command for Chromium.

You will have to modify this Dockerfile file for each Docker-type target in Wappler.
I have tested this on Digital Ocean based setup Wappler provides. So I can now generate PDFs on local as well as remote dockers.

4 Likes

Thank you @sid for a detailed explanation and step-by-step solution.

May I ask you how it’s possible to use array items, for instance for multiply query results or repeats in HTML code?
For instance generate table?

Thank you in advance.

This is not in the scope of this extension.
That is part of how you create the HTML which you give to this extension as input.

The question about repeating items has been a problem with sending emails too. This is not natively supported in Wappler right now, and neither is it available as a custom extension from what I know.

The solution below is from a dev in our team, which also applies here.

@sid it’s possible to provide example of this workaround?

The link above has the code. And if you read the discussion there, you will understand the context of it.

Those who uses this solution: is it possible to mark page number on each generated PDF sheet?

Yes there is. But you will have to look at Puppeteer and mPDF documentation to see how to use.

Hi all, first time poster, long time community crawler looking for answers :joy:

After a lot of hit and miss, I’ve been able to get this working. However, I cannot seem to be able to get the styles from Bootstrap working at all. Here is my current setup (don’t mind the repeat, I’m still working on that):

My “styles” Set Value is:

<link rel="stylesheet" href="{{host}}/bootstrap/5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.4.1/font/bootstrap-icons.css" integrity="sha384-NUDU7Qr8dfscXBIhA0px/bRl3cgNrOT9l/WPm15DzH5xnBs4fL4vgRiXURs98/ID" crossorigin="anonymous">`

{{host}} resolves to http://localhost:8100

I have put the <link> tags inside <head> tags (just in case) to no avail. I’ve changed the path of the bootstrap file to /assets/bootstrap… etc. Nothing I have tried to even get some kind of styling has worked.

As you can see below, the PDF that is generated has no styling except for, if I understand how Puppeteer works correctly, the user agent stylesheet from Chromium.

Thanks in advance for any help you can provide.

This is where the issue is. You need a link here which is accessible over internet.
So, from my understanding, how Puppeteer works is by opening Chome and placing the passed HTML as a page. Here, your localhost does not exist. So only links which are accessible over internet will work. Then, whatever the final render is, is printed-as-PDF and the file is returned.
Hope this helps.

I started getting some styles swapping out the local bootstrap path for the cdn straight from getbootstrap.com. The rows and columns don’t seem to be working, but I’ll see if I can’t troubleshoot that.

Kind of interesting that the bootstrap icons are still not rendering though.

Looks like I may have to point to my git repository to get my custom styles for the time being while I’m working locally. Thanks Sid!

UPDATE:
After much trying, webfonts not loading, jsdelivr not working, I have figured everything out now. Updating here in case anyone else has the same issue.

DOCKER ISSUES
Running Docker and not “own server” (as HTMLtoPDF Wappler project is) is why http:localhost:8100 wasn’t working. The hostname in my Docker container was very different, which is what Chromium in Puppeteer was looking for.

Going to the web server terminal, type hostname -f and use this in place of localhost. I found correct port in the inspect tab of my container in the Docker desktop app, thus the host actually needed to be http://5dbd3e3d50fc:3000.

SERVER CONNECT DYNAMIC HOST
With Docker issues fixed, all I had to do was set up a conditional in my Server Connect file as you can see below.

image

I could then use the {{host}} value in the <link> tags in the html and also any image sources I have.

WEB FONTS NOT LOADING
With Bootstrap CSS and images working, I was stoked, yet every PDF generated no text. This is because Puppeteer wasn’t waiting for the fonts to load in Chromium before shutting the browser and outputting the PDF. Thus, no text. Now I know there is a provision in the HTMLtoPDF.js file, however this didn’t seem to be working.

Thanks to this comment on github, I have edited the .js file to include this line of code and everything is now working as intended.

await page.evaluateHandle('document.fonts.ready');

Just include this line of code before await page.pdf(pdfOptions);

1 Like

Not sure how the extension works, but I don’t think localhost is the issue here. I use chromium puppeteer on localhost without any issue.

1 Like

Because I was running docker, it’s its own container with its own host. Localhost didn’t work, but the hostname I got from running hostname -f did. In saying that, not running a Docker server and using the “Own Hosting” option in Targets allows for localhost, if that makes sense.

Ya, using server variables like hostname or base_url is definitely the way to go as it allows for things to work on all targets. Glad you got it sorted!

1 Like

Absolutely. One day I hope to open this program up to other business and don’t need to be changing everywhere where a host is referenced. Thanks mate. :slight_smile:

@sid do yo know if it is possible to combine 2 PDF’s with puppeteer? I didn’t find anything on their documentation. I need to use a stationery. I know that it works with mPDF but I switched to NodeJS so I need the same functionality.

From what I know, there is no such option in Puppeteer.
If you are creating PDF by passing HTML, you can combine the two HTMLs first and then pass as input.

Best to use another NPM package which can merge PDFs if you cant combine HTMLs.

For PHP, although mPDF can do it, but the page size (A4,A3 etc) becomes an issue from my experience - last I had tried. I eneded up using Ghostscript in PHP to merge PDFs at that time as another extension.

Hello,

Could you please give the help link or tutorial for integration with wappler?

@gitlab there is no installation information for wappler!

Thank you.

HI.
Please refer the links for Wappler Extensibility Docs in the main post.
The project on Gitlab is just an example, along with the files you will need to add to your Wappler project.

1 Like