Documentation
¶
Overview ¶
Package html2pdf renders static HTML straight to a vector PDF: it drives go-webengine's own layout tree (no screenshot, no raster slicing) into go-pdfkit text/rect/stroke calls. Pagination is the engine's (paginate.Breaks): it cuts between atoms — a text line, a whole table row — never through one, and honours the document's CSS fragmentation (break-before/after: page, break-inside: avoid, break-after: avoid, orphans, widows) and its @page size and margins.
Scope ¶
This is a static renderer: no JavaScript and no @font-face (text uses the three families go-webengine's own paint package bundles — Inter for sans, Lora for serif, Go Mono for mono — plus its last-resort DejaVu Sans for a character the family has no glyph for, so the glyphs drawn always match the metrics layout measured against). External stylesheets — <link rel="stylesheet"> and their @import chains — are fetched through the engine's own bounded loader (Engine.LoadStylesheets) and cascaded for the print medium by default (Options.Media), so a page's @media print rules apply and its screen-only ones do not, as in a browser's print preview. Inline-level background and borders paint per line fragment from the engine's own LineBox.Inlines (box-decoration-break: slice); border-radius, background-image and box-shadow on an inline element do not.
Images — raster <img>, <img src="*.svg"> and inline <svg> — are fetched, decoded and sized by the engine's own pipeline (Engine.LoadImageSet) and laid out in the boxes it gives them — but embedded at the SOURCE's own resolution rather than at the canvas-sized bitmap the engine decoded for itself, which on paper would be a 96 dpi ceiling (see sourcePixels): a JPEG source as its own bytes (DCTDecode), any other lossy source re-encoded as JPEG when opaque, everything else as a flate bitmap with a soft mask for transparency — see images.go and Options.ImageDPI. A relative src resolves against Options.BaseURL; an image that fails to fetch or decode is simply left out. Stylesheets (<link>, @import) and images (<img>, CSS url()) are the only places Export touches the network: there is no script engine, no @font-face, and an <iframe>, <object> or <embed> is never loaded. Options.Fetch replaces the network client, and Offline refuses every request — see offline.go.
Navigation ¶
An <a href> becomes a link annotation — a URI action for an http(s) target, a GoTo to a named destination for a fragment that points at an element id in the document — one clickable rectangle per line the anchor spans, or the box of an anchor that lays out no text (engine.LinkRuns). Every element id becomes a named destination, and the headings become the viewer's bookmark tree (<h1> at the top level, deeper headings nested under the last shallower one). The <title> fills the PDF's Title unless Options.Title is set.
Quick start ¶
doc, err := html2pdf.Export(htmlSource, html2pdf.Options{})
if err != nil { ... }
f, _ := os.Create("out.pdf")
defer f.Close()
doc.Write(f)
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrOffline = errors.New("html2pdf: network access refused (offline)")
ErrOffline is what Offline returns. A Fetcher that wraps it (errors.Is) is counted as a refusal by Options.OnRefused.
Functions ¶
func Export ¶
Export parses htmlSrc, lays it out at opts.ViewportPx and returns a paginated pdfkit.Document — scaled to fit the page's printable width — ready to Write.
func Offline ¶ added in v0.4.0
Offline is a Fetcher that refuses every request. Pass it as Options.Fetch to render with no network access at all: a stylesheet, an @import, an image or a CSS background that is not a data: URL is treated as missing — the layout carries on without it, Export does not fail — and Options.OnRefused is told which URL it was.
Nothing is ever sent, so no redirect can be followed, and no DNS lookup is made. data: URLs never reach the Fetcher (the engine decodes them in place), so inline images still render. A file: URL is refused by the engine itself: html2pdf never sets the engine's FileRoot, so a BaseURL of file:///… cannot make a relative src read the filesystem.
Types ¶
type Fetcher ¶ added in v0.4.0
Fetcher fetches one http(s) sub-resource — a stylesheet, an @import target, an image — for Export, returning its body and Content-Type. It is the go-webengine engine's own Engine.Fetcher hook (engine.go in go-webengine/engine), so it sees every request Export would otherwise send itself, and none that the engine resolves without the network: a data: URL is decoded in place, and a file: URL is refused by the engine unless it is given a FileRoot, which Export never does.
A Fetcher may be called from several goroutines at once (stylesheets and images are loaded concurrently).
type Options ¶
type Options struct {
PageSize pdfkit.PageSize // zero value: pdfkit.A4; overridden by @page { size }
MarginMm float64 // zero value: 20; overridden by @page { margin }
// ViewportPx is the width (CSS px) the page is laid out against, then
// uniformly scaled down to fit the print column. Many real pages carry a
// fixed-width element sized for a desktop viewport — a sidebar, a
// multi-column nav — that a browser's own responsive CSS only collapses
// below some breakpoint. Laying out directly at the print column's actual
// width (a plain A4 page is under 650px wide) sits below most such
// breakpoints, so that fixed-width element squeezes the rest of the page
// into a narrow remainder and the whole document wraps far taller than it
// needs to — confirmed against RFC 9110's HTML edition, whose
// table-of-contents sidebar did exactly this (428 pages laid out at the
// print column's own ~642px width vs. 184 at 1024px). Zero value: 1024,
// a common small-desktop/tablet breakpoint — unless the document carries
// an @page rule: a document that names its paper was designed for it,
// its absolute units (a 12pt body, a 40mm figure) must print at their
// true size, and it is laid out 1:1 as a browser prints it. Set below
// the print column's own width (rare) to lay out 1:1 with no scaling.
ViewportPx float64
// BaseURL is the document's own URL, used to resolve a relative <img src>
// and a relative <a href> (and to satisfy same-origin-shaped fetch logic
// in the engine). A link whose href is this URL plus a fragment becomes an
// in-document jump. Leave it empty for a document whose images and links
// are all absolute or data: URIs.
BaseURL string
// Title, Author, Subject and Keywords fill the PDF's information
// dictionary. An empty Title is taken from the document's <title>.
Title, Author, Subject, Keywords string
// ImageDPI caps the pixel density of an embedded bitmap at its painted
// size: a bitmap that would exceed it — a 1024 px photograph painted
// 60 mm wide is 430 dpi — is downsampled to it. Zero (the default) keeps
// every pixel the SOURCE has, not merely the ones the engine kept for
// its own canvas (see sourcePixels), which is what Chrome's print and
// WeasyPrint do by default; WeasyPrint's --dpi is the same lever. 150
// is a sound print value, 96 the screen's.
ImageDPI float64
// Media is the CSS medium the page is styled for: "print" (the zero
// value) applies the page's @media print rules and print-only
// stylesheets and skips its screen-only ones — a browser's print
// preview, where a site's navigation, sidebars and footers are usually
// hidden; "screen" styles the page as displayed. Width features
// (min-width, max-width) are evaluated at ViewportPx under either.
Media string
// Fetch replaces the network client for every http(s) sub-resource
// (stylesheets, @import chains, images). Nil, the default, keeps the
// engine's own browser-like client: it follows redirects (net/http's
// default of up to 10 hops, to any host, including a loopback or private
// one), has a 30 s timeout per request, and honours no allow-list — so a
// document built from untrusted text can make the server running Export
// send GET requests to any address it can reach. A server that renders
// such documents should set Fetch: Offline refuses everything.
Fetch Fetcher
// OnRefused, when non-nil, is called with the URL of each request Fetch
// refused by returning an error that wraps ErrOffline (as Offline does).
// It may be called from several goroutines at once; count with an atomic.
OnRefused func(rawurl string)
}
Options configures a single Export call. The zero value is A4, 20mm margins on all sides, and a 1024px layout viewport — unless the document says otherwise: an @page rule's size and margins win over PageSize and MarginMm, as they do in a browser's print (Chrome honours @page size in headless print-to-PDF; WeasyPrint always has).