parallax / jsPDF

Client-side JavaScript PDF generation for everyone.
https://parall.ax/products/jspdf
MIT License
29.29k stars 4.68k forks source link

Support hyperlinks in html() #3146

Open rd0rnot opened 3 years ago

rd0rnot commented 3 years ago

I'm running jsPDF 2.3.1 to render PDFs from HTML. I am able to generate PDF files, but hyperlinks are not always rendering correctly.

Here are two examples:

<a href="https://github.com">https://github.com</a>

<a href="https://github.com">GitHub</a>

The first example generates a clickable link in the PDF (good), while the second example just colors the text blue with no hyperlinking (bad).

Here's the code I'm using to generate this:

const doc = new jsPDF('portrait', 'pt', 'letter');
const fullDocBody = '<a href="https://github.com">GitHub</a>'; 
doc.html(fullDocBody, {
  // Callback function is called when html conversion to PDF completes
  callback: function (doc) {
    doc.save('test.pdf');   // Saves to a file
  },
  x: 60,
  y: 60
 });

Changing fullDocBody to one of the two link strings shown above will demonstrate the behavior I am describing.

My application needs to accept either link type, as it is taking HTML from a rich text editor component to render the PDF.

Thanks for your time.

HackbrettXXX commented 3 years ago

Please attach the PDF file with the two links. I'm very convinced, though, that hyperlinks don't work at all. It's probably the PDF viewer that adds the hyperlinks. See my https://github.com/MrRio/jsPDF/issues/2222#issuecomment-613275518.

rd0rnot commented 3 years ago

Thanks @HackbrettXXX for the reply. Attached are the PDF files you requested.

Question: In your comment for #2222, you mentioned jsPDF.link() and jsPDF.textWithLink(). From what I see, it appears these would require knowledge of the (x, y) coordinates on the page where the link would go. Is that correct, or did you have a different suggestion for using this in the context of a rendered html page?

PDF link test 1.pdf PDF link test 2.pdf

HackbrettXXX commented 3 years ago

The files confirm what I wrote ;)

Yes, you would need the x,y (and width/height) coordinates of the links. That's the challenging part. I don't have good ideas how to retrieve them.

joseDaKing commented 3 years ago

For me, neither of @rd0rnot examples work and I am using version 2.3.1 @rd0rnot have you found a way to overcome this bug?

rd0rnot commented 3 years ago

@HackbrettXXX - thanks for looking at those files and confirming your earlier comments. I appreciate the quick response.

@joseDaKing - No, I haven't found a convenient way to overcome this. I think one possible solution would be to write logic to parse the HTML and directly write content using the jsPDF API instead of relying on the .html() method. As I understand it (and I could be mistaken), .html() uses the html2canvas library to internally render the content and takes a "screenshot" of that rendered page to produce a PDF.

For my team, we will likely see if we can purchase an off-the-shelf PDF component. I think jsPDF is great, but generating a document from HTML doesn't work the way we would need it to.

ItzhakBokris commented 3 years ago

any update?

sjenkins5 commented 3 years ago

The issue is still present on 2.4.0.

Uzlopak commented 3 years ago

This is like the issue with annotations with html2canvas. html2canvas just paints on a canvas. To be able to make create hyperlinks, we would actually need some hook method or callback method per element to inject our specific instructions to make a "blue" text to be annotated with a hyperlink. Nothing what we can do from our side, till html2canvas implements such a thing. Probably nobody created an issue in the issue tracker of html2canvas.

Uzlopak commented 3 years ago

Maybe if you take the onClone method as in #3178 and we do a .link() in that rectangular instead of an .addImage()?

Potentially an issue would be, that link is expecting the coordinates on the current page, so if you want to print on multiple pages, we would need to modify .link() it.