html2pdf

package module
v0.0.0-...-a0ccfc4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 5, 2026 License: BSD-3-Clause Imports: 13 Imported by: 0

README

html2pdf

CI Go Reference

Pure-Go, zero-C, static HTML to vector PDF. No headless browser, no screenshot-then-slice: it drives go-webengine's own layout tree straight into go-pdfkit text/rect/stroke calls, so the PDF's text is real text — selectable, searchable, small — not a raster of it.

Quick start

doc, err := html2pdf.Export(htmlSource, html2pdf.Options{})
if err != nil {
    log.Fatal(err)
}
f, _ := os.Create("out.pdf")
defer f.Close()
doc.Write(f)

Or from the shell:

go run ./cmd/html2pdf -in report.html -out report.pdf

Pagination

Page breaks land between atoms — a text line, or a whole <tr> — never through one. A table row that would overflow the page moves to the next page whole; a paragraph may still break between its own lines, same as printed text always has.

Layout width vs. print width

A page is laid out at Options.ViewportPx (default 1024px), then scaled down to fit the print column — not laid out directly at the print column's own width (a plain A4 page is under 650px wide). 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 narrower than that breakpoint just squeezes the rest of the page into a sliver instead of dropping the sidebar. Confirmed against RFC 9110's HTML edition, whose table-of-contents sidebar did exactly this — see corpus/CORPUS.md for the before/after page counts across all 8 corpus pages.

Scope

This renders static HTML: no JavaScript, no external stylesheets, no @font-face. Text is set in the three families go-webengine's own paint package bundles — Inter (sans), Lora (serif), Go Mono (mono) — so the glyphs drawn always match the metrics the layout pass measured against; there is no web-font fetch to fail silently.

Images — raster <img>, <img src="*.svg"> and inline <svg> — go through the engine's own fetch/decode/size pipeline (Engine.LoadImages) and are embedded as bitmaps, so they're laid out and drawn exactly as the engine's raster canvas would draw them. A relative src resolves against Options.BaseURL; an image that fails to fetch or decode is simply left out, as on the raster canvas. This is the one place Export touches the network.

One gap remains, inherited from — not introduced by — the layout engine:

  • Inline-level background/border/padding does not paint. A styled <span> never gets its own box in go-webengine's layout (confirmed against its reference raster painter too — a shared engine limitation). Style the containing block/table-cell instead of an inner inline element when you need a filled badge or pill.

Status

Validated against a hand-built regression suite (html2pdf_test.go, ~94% statement coverage) and a corpus of 8 real public pages (corpus/, in the spirit of go-webengine's own bench/) — see corpus/CORPUS.md for current results and the bugs the corpus run has found so far.

License

BSD-3-Clause, see LICENSE.

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 breaks between atoms — a text line, or a whole table row — never through one; see atoms.go.

Scope

This is a static renderer: no JavaScript, no external stylesheets or @font-face (text uses the three families go-webengine's own paint package bundles — Inter for sans, Lora for serif, Go Mono for mono — so the glyphs drawn always match the metrics layout measured against). Inline-level background/border/padding do not paint: go-webengine's layout does not give a styled inline run its own box, only block/table/flex-level elements do (confirmed in the reference raster painter too — this is a shared engine limitation, not something this package works around).

Images — raster <img>, <img src="*.svg"> and inline <svg> — are fetched, decoded and sized by the engine's own pipeline (Engine.LoadImages) and embedded as bitmaps, so they are laid out and drawn exactly as the engine's raster canvas would. A relative src resolves against Options.BaseURL; an image that fails to fetch or decode is simply left out. This is the one place Export touches the network.

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

This section is empty.

Functions

func Export

func Export(htmlSrc string, opts Options) (*pdfkit.Document, error)

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.

Types

type Options

type Options struct {
	PageSize pdfkit.PageSize // zero value: pdfkit.A4
	MarginMm float64         // zero value: 20

	// 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. 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 to satisfy same-origin-shaped fetch logic in the engine). Leave it
	// empty for a document whose images are all absolute or data: URIs.
	BaseURL string
}

Options configures a single Export call. The zero value is A4, 20mm margins on all sides, and a 1024px layout viewport.

Directories

Path Synopsis
cmd
html2pdf command
Command html2pdf renders a static HTML file to a vector PDF.
Command html2pdf renders a static HTML file to a vector PDF.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL