stephanrauh / ngx-extended-pdf-viewer

A full-blown PDF viewer for Angular 16, 17, and beyond
https://pdfviewer.net
Apache License 2.0
450 stars 167 forks source link

Some links cannot be clicked in the ngx-extended-pdf-viewer, while they are 'clickable' when viewed after downloading in other viewers. #2342

Open kad-rothul opened 1 month ago

kad-rothul commented 1 month ago

Describe the bug I have a angular application where I need to view several PDF's, with the option to print and download them. Unfortunately I cannot share the PDFs. The PDFs contain links to other websites and to emails. All documents are already generated and should only be viewed, not altered. The problem is that users are not able to click on every link.

To be more specific, I have a document with a table of users with email adresses. The email adresses are blue, which suggests they are clickable. However, they are not. When I download the document and watch it in the browser (Chrome), the links work as expected, indicating the PDF is generated correctly. For some other documents, the links do work as expected. I have included the following, which seems to work correctly: pdfDefaultOptions.externalLinkTarget = LinkTarget.BLANK;

Possible cause: I noticed that when inspecting the html in console, that for some pages (that do contain links), i see: <div class="annotationLayer" hidden=""></div> For other documents, the annotationLayer class contains children like: <section data-annotation-id="151R" tabindex="1000" class="linkAnnotation" style="z-index: 0; left: 9.67619%; top: 85.9597%; width: 25.7024%; height: 1.12845%;"><a data-element-id="151R" title="..." href="..." target="_blank" rel="noopener noreferrer nofollow" id="pdfjs_internal_id_151R"></a></section> (I removed the title and href). This is what I would also expect for the other documents, but it looks like the annotationLayer is somehow empty in this viewer.

Version info Tested with 17.3.1 and 20.0.2

Demo PDF file I cannot share the PDF here unfortunately.

I hope someone has any idea how to resolve this issue/bug.

EDIT: I tried to open a specific PDF in multiple ways and look if it was possible to click on the email links. In Chrome, Edge, Acrobat Reader, it worked just fine. In Mozilla Firefox (and in my application), it doesn't work. This lib makes use of pdf.js which is used in Firefox, so it seems to be an issue with this pdf.js

stephanrauh commented 1 month ago

I agree it sounds like a problem of the base library. To confirm that, please navigate to https://mozilla.github.io/pdf.js/web/viewer.html and open your file in that viewer. The "open file" button is hidden in the drop-down menu on the right-hand side.

If the links aren't clickable in the Mozilla showcase, please report at but at https://github.com/mozilla/pdf.js/issues.

As for the annotation layer: I guess you're right. There should be an annotation layer containing the links.

kad-rothul commented 1 month ago

Thank you for the quick response! The PDF containing the table with emails is still not clickable in this viewer. The mailto: annotations (that are visible in e.g. Acrobat Reader) are not present in this viewer. Other PDF documents I use in my application (which are generated/created externally) do also contain mailto: anchors, but these ARE clickable, also in this viewer.

So to summarize: I have two different kind of PDFs, both containing mailto:-links/anchors in the document. PDF_A contains a table with emails which are NOT clickable in the ngx-extended-pdf-viewer nor in the pdf.js viewer, but in Acrobat Reader/Chrome/Edge they are clickable. PDF_B has some individual mailto: links, but these ARE clickable in every PDF reader.

This shows that these mailto:-links are supported and do work in some cases, but not in all cases. Do you have any idea what causes this difference in behaviour and how to fix this?

EDIT: Since the annotation layer is hidden (or maybe empty for this PDF), it might be that the anchors are not picked up correctly by pdf.js. Since the links aren't recognized, they are not added to the annotation layer, so this layer is empty, causing it to be hidden in the HTML. Just an idea that could explain this behaviour.

stephanrauh commented 1 month ago

Can I talk you into debugging the issue yourself? Set [minifiedJSLibraries]="false" and add breakpoints to these lines in the pdf-4.x.x.js file:

class AnnotationElementFactory {
  /**
   * @param {AnnotationElementParameters} parameters
   * @returns {AnnotationElement}
   */
  static create(parameters) {
    const subtype = parameters.data.annotationType;

    switch (subtype) {
      case AnnotationType.LINK:
        return new LinkAnnotationElement(parameters);

and

class LinkAnnotationElement extends AnnotationElement {
  constructor(parameters, options = null) {
    super(parameters, {
      isRenderable: true,
      ignoreBorder: !!options?.ignoreBorder,
      createQuadrilaterals: true,
    });
    this.isTooltipOnly = parameters.data.isTooltipOnly;
  }

  render() {
    const { data, linkService } = this;
    const link = document.createElement("a");
    link.setAttribute("data-element-id", data.id);

It's also possible that these methods aren't called in your bogus PDF. Nonetheless, you should be able to hunt down the problem and find the root cause. As mentioned before, I don't think it's "my" bug, but if we can tell the pdf.js team what's going wrong they might fix the problem faster.