PDF Output
A unihtml.Document is not the PDF. It is a handle on some HTML plus the settings
you want applied to it, and there are three ways to turn it into pages. They behave
differently enough that picking the wrong one is the most common reason UniHTML
output disappoints, so this is the decision to make first.
Just the HTML, nothing else in the file:
err := doc.WriteToFile("out.pdf")Rendered pages you add to a document you are assembling:
pages, err := doc.GetPdfPages(ctx)The HTML placed inline, like any other creator component:
err := c.Draw(doc)What each one does
Measured against a running server, not inferred.
Document.WriteToFile | GetPdfPages + c.AddPage | c.Draw(document) | |
|---|---|---|---|
Page size from SetPageSize | Applied | Applied | Ignored |
| Margins | Applied | Applied | Ignored |
| Orientation | Applied | Applied | Ignored |
| Link annotations | Kept | Kept | Dropped |
TrimLastPageContent | No effect | No effect | Applied |
| Creator content in the same file | No | Yes, whole pages | Yes, in the flow |
Takes a context.Context | No | Yes | No |
The annotation row is the one that surprises people. c.Draw wraps each rendered
page with creator.NewBlockFromPage, which flattens it into a content stream, and
annotations do not survive that. A page full of <a href> still looks right, blue
and underlined, and nothing in it is clickable. Three links survive WriteToFile
and GetPdfPages; zero survive c.Draw.
Choosing
Use WriteToFile when the PDF is nothing but the converted HTML. It is a single call
and it needs no creator.Creator, which makes it the shortest program that does
anything useful.
Use GetPdfPages when you are building a larger document and the HTML contributes
whole pages to it. This is also the path to use whenever the markup has links, or
whenever the page geometry matters. You get []*model.PdfPage back and add them with
c.AddPage.
Use c.Draw when creator content has to sit next to the HTML on the same page: a
generated heading above it, a signature block below it. That inline placement is the
only thing it gives you that the others do not, and it costs annotations and page
control.
A trap when mixing c.Draw with page settings
SetPageSize, SetMargins, SetPageWidth, SetPageHeight and SetPos all switch
the document to absolute positioning. On the c.Draw path that changes where the
rendered block lands: instead of flowing at the current cursor, it is pinned to the
coordinates from SetPos, which default to (0, 0). An A5 document drawn onto a
Letter page ends up in the top-left corner with the rest of the sheet empty.
Either leave the geometry alone and let c.Draw flow the content, or set the
geometry and take the pages with GetPdfPages. Doing both produces the corner case
above.
Where to look
| Guide | Covers |
|---|---|
| Extract Pages | GetPdfPages, adding rendered pages to a creator, and context timeouts. |
| Draw into a Document | c.Draw, and trimming the last page so following content sits against it. |
| Chapters | Adding HTML to a creator.Chapter so it gets a numbered heading and an outline bookmark. |
| Links | Keeping <a href> clickable, and which path throws the annotations away. |