Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Outlines: multilevel table of contents. #216

Closed
wants to merge 7 commits into from

Conversation

alexvdev
Copy link

Outlines

Outlines represent table of contents of a document and are very convenient in large documents with complex hierarchical structure. In PDF readers they can be called Bookmarks, Index, Table of Contents.

Specifications

PDF 1.3 - good sample of outlines itself.

Supports

  • nested levels
  • unicode titles (different languages)
  • all destination types according to spec (7.2.1)

Sample

/demo/test_outlines.coffee  --> out_outlines.pdf  ( /demo/out_outlines.pdf on the repo )

@alexvdev alexvdev mentioned this pull request Mar 27, 2014
@@ -31,9 +32,24 @@ class PDFDocument extends stream.Readable
Type: 'Pages'
Count: 0
Kids: []

if @options.hasOutlines
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of an option, can these extra pieces of data be added automatically later once the first outline has been added?

@devongovett
Copy link
Member

Great, glad to see this! I left a few small notes inline, but generally it looks good. I have an idea for a different API that might make the implementation simpler though:

# doc.outline is the root
outline = doc.outline

# addItem adds an item to an outline
outline.addItem('Test')

# addSection returns another outline object that you can call addItem or addSection on
subsection = outline.addSection('Some section')
subsection.addItem('Foo bar baz')

Basically, the idea is that there would be one PDFOutline class with two methods:

  • addItem - adds an item to the outline
  • addSection - adds a subsection to the outline and returns another PDFOutline object

And the PDFDocument would just have a single outline property with the root outline. If you added anything to it, it would appear in the document once it is finalized.

I'd prefer not to have an endSection method for the user to call, it would be better if the parent counts were just incremented recursively as the items are being added instead.

This API might make the implementation simpler since you wouldn't need to do all the work of keeping track of which section is the current, etc. since the user would do that by just using the outline objects returned from addSection. I don't think this would require a huge refactor, just some moving around of pieces.

What do you think of this idea?

@alexvdev
Copy link
Author

alexvdev commented Apr 7, 2014

This will allow to create outlines on arbitrary levels but will put all the work of tracking the levels and data structures to the user. It will not be very convenient, imho, as any programmer should track the outline level model and organize stacks (or the whole tree) by theirself, - suppose we have a function (in node js) of processing some source text:

function onNextLevel (text) {
    var subsection = outline.addSection ();   // outline already has title
    subsection.addItem(text); // OK, but...
   // where to store subsection(s) if there will be subsequent calls to this function?
}

From the implementation point of view, it should work, although inserting item in arbitrary position will touch the counters of all up level subsections. We can though recalculate all counters at the end when the whole tree will be build.

I thought about enumerating all items as 1.1, 1.1.2, ... (it is single-valued correspondence), but implementation would be more complicated, so I did the current variant as the first one.

It is not easy to design a good API for the feature, I think in many respects it depends on the tasks for which it will be used. If the document is created from up to down there is no need for arbitrary access. I want to look also how outlines are implemented in wkhtmltopdf / qt.

@devongovett
Copy link
Member

I don't think it's really any more work for users of the API. They kinda have to keep track of what section they're in anyway in their head as they're using the API, this just makes it more explicit.

To achieve the same thing, I'd just keep a single variable e.g. outline and set that to the current outline each time. Then when I want to move up a level, do outline = outline.parent or something. Or, the user could have multiple variables if they want.

This would also allow users to insert items in any order they wanted, or insert items into the outline at positions other than the current one. It just gives them more flexibility to do what they want, and keeps PDFKit's code simpler at the same time IMO.

@alexvdev
Copy link
Author

OK, I'll change mentioned issues and the API also. It is simpler API, agree.

@sanderboom
Copy link

This would be a great addition. Thanks for working on this!

@sbmadhav
Copy link

sbmadhav commented Sep 3, 2016

What happened to this pull request ? Is any one still using this tool ?

@alexvdev
Copy link
Author

alexvdev commented Sep 3, 2016

Hi @sbmadhav, there were some remarks from the team lead which I had not time to address. Really I want to finish this and merge to master. So - intend to review the current state and test.

@devongovett devongovett mentioned this pull request Sep 3, 2016
@holly-weisser
Copy link

Any update on this? Is this still planned?

@kseniya292
Copy link

I need to create a Table Of Content. Is there a way I can implement this even though it's not merged in? @alexvdev

@kseniya292
Copy link

@devongovett I'm really struggling to create a Table of Contents. I tried implementing the code from this PR but I'm not sure how to use it. It seems to be working but i can't figure out how to display the actual table of contents with page numbers. Any help would be greatly appreciated. I've spent a lot of time creating a nice report using pdfkit and the last piece is the TOC.

@alafr alafr mentioned this pull request Jun 20, 2018
@alafr alafr closed this in f91bdd6 Jun 22, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants