Hopding / pdf-lib

Create and modify PDF documents in any JavaScript environment
https://pdf-lib.js.org
MIT License
6.88k stars 656 forks source link

Create Table of content in pdf #1257

Open vsshukla opened 2 years ago

vsshukla commented 2 years ago

Hi @Hopding,

thanks for this library.

I am working on pdf generation and have scenarios where i need to create TOC (at first page all link will be available and user can click on it and navigate to respective page.) i have seen #123 but this is using page ref, where i need text ref (correct me if i am wrong). i.e

` const tocData = [ { tocText: 'chapter 1', pageNo: 2, targetId: '#chapter1' }, { tocText: 'chapter 2', pageNo: 4, targetId: '#chapter2' }, { tocText: 'chapter 3', pageNo: 10, targetId: '#chapter3' }, { tocText: 'chapter 4', pageNo: 23, targetId: '#chapter4' }, ...... ];

so i will keep tocText text as table of content (index) and when user click on it then is should be navigate targetId with respected pageNo`

kindly help me with it.

xoriant-vikas commented 2 years ago

@Hopding, may i know if we can get resolution on this issue ?

jcramercodes commented 1 year ago

I was able to accomplish this by using the addAnnot function:

    const createPageLinkAnnotation = (
      pdfDoc: PDFDocument,
      pageRef: PDFRef,
      anchorBounds: [number, number, number, number],
    ) =>
      pdfDoc.context.register(
        pdfDoc.context.obj({
          Type: 'Annot',
          Subtype: 'Link',
          /* Bounds of the link on the page */
          Rect: [
            anchorBounds[0], // lower left x coord
            anchorBounds[1], // lower left y coord
            anchorBounds[2], // upper right x coord
            anchorBounds[3], // upper right y coord
          ],
          /* Give the link a 2-unit-wide border, with sharp corners */
          Border: [0, 0, 2],
          /* Make the border color blue: rgb(0, 0, 1) */
          C: [0, 0, 1],
          /* Page to be visited when the link is clicked */
          Dest: [pageRef, 'XYZ', null, null, null],
        }),
      )

Run the following bit for each of the internal text links you want (aka: for each of your ToC elements)

    const textBounds = [x1, y1, x2, y2] // AKA: the bounds of the text element in question
    const link = createPageLinkAnnotation(pdfDoc, page.ref, textBounds)
    page.node.addAnnot(link)

Hope this makes sense! Happy to explain in more detail if need be. Currently, createPageLinkAnnotation() will just draw a blue rect around the text element in question. I imagine the text itself can be restyled to look more like a traditional link (add desired hyperlink text color/underline it)- and then hide the blue rect styling for the annotation link.