htmlbag

package module
v0.0.22 Latest Latest
Warning

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

Go to latest
Published: May 16, 2026 License: BSD-3-Clause Imports: 38 Imported by: 4

README

htmlbag

htmlbag is the HTML/CSS renderer within the Boxes and Glue stack. It turns HTML fragments plus CSS into internal text and node structures (frontend.Text, node.VList, etc.) that are later shipped to PDF.

Core pieces

  • CSSBuilder (cssbuilder.go): owns a frontend.Document and csshtml.CSS, parses HTML (ParseHTMLFromNode/HTMLToText), applies CSS, and builds vlists.
  • Styles: inheritablestyles.go models CSS inheritance; list markers, indents, and table handling live here and in htmltable.go.
  • Rendering: vlistbuilder.go builds vertical lists from frontend.Text; output.go ships pages via the frontend/pdfdraw backend.
  • Fonts: fonts.go loads embedded webfonts; assets live under fonts/.

Quick start

css := csshtml.New()
_ = css.ParseString(`@page { size: A4; } body { font-family: serif; }`)
doc := frontend.NewDocument()
cb, _ := htmlbag.New(doc, css)

te, _ := cb.HTMLToText(`<p><b>Hello</b> world</p>`)
vl, _ := cb.CreateVlist(te, bag.MustSP("15cm"))
doc.Doc.OutputAt(0, 0, vl) // example: output directly

Development

  • Go 1.22+. Import path: github.com/boxesandglue/htmlbag.
  • Tests/lint: no test at the moment.
  • Changes in the CSS/HTML pipeline should be validated against PDF references (downstream projects rely on stable output).

Documentation

Index

Constants

View Source
const PageDimensionsKey = "htmlbag.PageDimensions"

PageDimensionsKey is the key used to store PageDimensions in Page.Userdata.

Variables

This section is empty.

Functions

func AddFontFamiliesFromCSS

func AddFontFamiliesFromCSS(cs *csshtml.CSS, fe *frontend.Document) error

AddFontFamiliesFromCSS adds entries to the font families of the frontend document.

func ApplySettings

func ApplySettings(settings frontend.TypesettingSettings, ih *FormattingStyles)

ApplySettings converts the inheritable settings to boxes and glue text settings.

func GetHTMLItemFromHTMLNode

func GetHTMLItemFromHTMLNode(thisNode *html.Node, direction Mode, firstItem *HTMLItem) error

GetHTMLItemFromHTMLNode fills the firstItem with the contents of thisNode. Comments and DocumentNodes are ignored.

func HTMLNodeToText

func HTMLNodeToText(cb *CSSBuilder, n *html.Node, ss StylesStack, df *frontend.Document, anchorPages map[string]int) (*frontend.Text, error)

HTMLNodeToText converts an HTML node to a *frontend.Text element. cb is needed so Output can collect anchors and inline-anchor markers onto the same builder state used at shipout. anchorPages is the previous-pass id → page map used to resolve CSS target-counter(). Pass nil for anchorPages on a clean first pass.

func LoadIncludedFonts

func LoadIncludedFonts(fe *frontend.Document) error

LoadIncludedFonts creates the font families monospace, sans and serif for default fonts.

func Output

func Output(cb *CSSBuilder, item *HTMLItem, ss StylesStack, df *frontend.Document, anchorPages map[string]int) (*frontend.Text, error)

Output turns HTML structure into a nested frontend.Text element. anchorPages provides the id → page map from a previous render pass (used to resolve CSS target-counter() references). Pass nil on the first pass or when the call is not in a target-counter context.

func ParseHorizontalAlign

func ParseHorizontalAlign(align string, styles *FormattingStyles) frontend.HorizontalAlignment

ParseHorizontalAlign parses the input ("left","center") and returns the HorizontalAlignment value. CSS Text 3 §7 logical keywords "start" and "end" stay logical here; FormatParagraph resolves them to physical Left/Right after paragraph direction is known.

func ParseRelativeSize

func ParseRelativeSize(fs string, cur bag.ScaledPoint, root bag.ScaledPoint) bag.ScaledPoint

ParseRelativeSize converts the string fs to a scaled point. This can be an absolute size like 12pt but also a size like 1.2 or 2em. The provided dflt is the source size. The root is the document's default value.

func ParseVerticalAlign

func ParseVerticalAlign(align string, styles *FormattingStyles) frontend.VerticalAlignment

ParseVerticalAlign parses the input ("top","middle",...) and returns the VerticalAlignment value.

func StylesToStyles

func StylesToStyles(ih *FormattingStyles, attributes map[string]string, df *frontend.Document, curFontSize bag.ScaledPoint) error

StylesToStyles updates the inheritable formattingStyles from the attributes (of the current HTML element).

Types

type AnchorEntry added in v0.0.21

type AnchorEntry struct {
	ID   string
	Text string
	Page int // 1-based page number, 0 until assigned
}

AnchorEntry records an element with an id attribute (block or inline). Used as the target side of CSS target-counter() and target-text() cross-references. The Page field is filled during shipout, mirroring HeadingEntry; Text is filled at collection time from the element's contents (capped at 200 characters to keep the aux file bounded — long block anchors get a trailing "…").

type BarcodeType added in v0.0.11

type BarcodeType int

BarcodeType represents the type of barcode to create.

const (
	BarcodeEAN13 BarcodeType = iota
	BarcodeCode128
	BarcodeQR
)

type CSSBuilder

type CSSBuilder struct {
	ElementCallback  ElementCallbackFunc
	PageInitCallback PageInitCallbackFunc
	// Counters holds named counter values used when evaluating CSS content
	// properties (e.g. "page" for the current page, "pages" for the total).
	// The "page" counter is set automatically during shipout; other counters
	// (like "pages") should be set by the caller.
	Counters map[string]int

	// Headings collects all h1–h6 headings encountered during VList
	// construction. Page numbers are assigned during OutputPages.
	Headings []HeadingEntry
	// Anchors collects every block-level element with an id attribute
	// encountered during VList construction. Page numbers are assigned
	// during shipout, just like Headings. Read by the multi-pass aux
	// loop to feed target-counter() resolution on the following pass.
	Anchors []AnchorEntry

	// PendingVLists stores pre-rendered VLists keyed by a unique ID.
	// Used to pass already-rendered content (e.g. group contents) through
	// the HTML/CSS pipeline into table cells.
	PendingVLists map[string]*node.VList

	// FootnoteSeparatorHeight overrides the default footnote rule thickness.
	// Zero falls back to the package default (0.4pt).
	FootnoteSeparatorHeight bag.ScaledPoint
	// FootnoteSeparatorSkip overrides the default skip between content area
	// and the rule. Zero falls back to the package default (6pt).
	FootnoteSeparatorSkip bag.ScaledPoint
	// FootnoteInterSkip overrides the default skip between consecutive
	// footnote bodies. Zero falls back to the package default (2pt).
	FootnoteInterSkip bag.ScaledPoint
	// FootnoteCallSizeRatio overrides the marker-call font-size relative to
	// the surrounding text. Zero falls back to 0.7.
	FootnoteCallSizeRatio float64
	// FootnoteCallRiseRatio overrides the marker-call rise (PDF Ts operator)
	// relative to the surrounding font size. Zero falls back to 0.4.
	FootnoteCallRiseRatio float64
	// FloatTopInterSkip overrides the default skip between consecutive
	// top-floats and below the stack (separating it from body content).
	// Zero falls back to the package default (6pt).
	FloatTopInterSkip bag.ScaledPoint
	// FloatBottomInterSkip overrides the default skip between consecutive
	// bottom-floats and above the stack (separating it from body content).
	// Zero falls back to the package default (6pt).
	FloatBottomInterSkip bag.ScaledPoint
	// contains filtered or unexported fields
}

CSSBuilder handles HTML chunks and CSS instructions.

func New

func New(fd *frontend.Document, c *csshtml.CSS) (*CSSBuilder, error)

New creates an instance of the CSSBuilder.

func (*CSSBuilder) AddCSS

func (cb *CSSBuilder) AddCSS(css string) error

AddCSS reads the CSS instructions in css.

func (*CSSBuilder) BeforeShipout

func (cb *CSSBuilder) BeforeShipout() error

BeforeShipout should be called when placing a CSS page in the PDF. It adds page margin boxes to the current page.

func (*CSSBuilder) CSS added in v0.0.6

func (cb *CSSBuilder) CSS() *csshtml.CSS

CSS returns the underlying CSS parser.

func (*CSSBuilder) CSSPropertiesToValues

func (cb *CSSBuilder) CSSPropertiesToValues(p HTMLProperties) HTMLValues

CSSPropertiesToValues converts CSS values to the HTMLValues struct.

func (*CSSBuilder) CreateVlist

func (cb *CSSBuilder) CreateVlist(te *frontend.Text, wd bag.ScaledPoint) (*node.VList, error)

CreateVlist builds a vlist (a vertical list) from the Text object.

func (*CSSBuilder) HTMLBorder

func (cb *CSSBuilder) HTMLBorder(vl *node.VList, hv HTMLValues) *node.VList

HTMLBorder returns two string with a HTML border. The first string is part of a prefix for a possible background string and the second string renders the border.

func (*CSSBuilder) HTMLToText

func (cb *CSSBuilder) HTMLToText(html string) (*frontend.Text, error)

HTMLToText interprets the HTML string and applies all previously read CSS data.

func (*CSSBuilder) InitPage

func (cb *CSSBuilder) InitPage() error

InitPage makes sure that there is a valid page in the frontend.

func (*CSSBuilder) NewPage

func (cb *CSSBuilder) NewPage() error

NewPage puts the current page into the PDF document and starts with a new page.

func (*CSSBuilder) OutputPages added in v0.0.6

func (cb *CSSBuilder) OutputPages(vl *node.VList) error

OutputPages distributes the content of a VList across pages, breaking between child nodes whenever the next node would exceed the content height. It ships out each page automatically and starts new pages as needed. The final page is shipped out before returning.

func (*CSSBuilder) OutputPagesFromText added in v0.0.9

func (cb *CSSBuilder) OutputPagesFromText(te *frontend.Text) error

OutputPagesFromText takes a Text tree (from HTMLToText), splits it at forced page breaks, and formats each group with the content width of its target page. This ensures that different @page margins produce different text widths.

func (*CSSBuilder) PageSize

func (cb *CSSBuilder) PageSize() (PageDimensions, error)

PageSize returns a struct with the dimensions of the current page.

func (*CSSBuilder) ParseCSSString

func (cb *CSSBuilder) ParseCSSString(css string) error

ParseCSSString reads CSS instructions from a string.

func (*CSSBuilder) ParseHTMLFromNode

func (cb *CSSBuilder) ParseHTMLFromNode(input *html.Node) (*frontend.Text, error)

ParseHTMLFromNode interprets the HTML structure and applies all previously read CSS data.

func (*CSSBuilder) ReadCSSFile

func (cb *CSSBuilder) ReadCSSFile(filename string) error

ReadCSSFile reads the given file name and tries to parse the CSS contents from the file.

func (*CSSBuilder) SetAnchorPages added in v0.0.21

func (cb *CSSBuilder) SetAnchorPages(m map[string]int)

SetAnchorPages installs the id → page map collected on the previous render pass. The CSS evaluator reads this when resolving target-counter() references. Pass nil to clear.

func (*CSSBuilder) SetAnchorTexts added in v0.0.21

func (cb *CSSBuilder) SetAnchorTexts(m map[string]string)

SetAnchorTexts installs the id → text map collected on the previous render pass. The CSS evaluator reads this when resolving target-text() references. Pass nil to clear.

type ElementCallbackFunc added in v0.0.6

type ElementCallbackFunc func(event ElementEvent)

ElementCallbackFunc is called after a block element's VList is built.

type ElementEvent added in v0.0.6

type ElementEvent struct {
	TagName     string
	TextContent string
	VList       *node.VList
}

ElementEvent holds information about a processed block element.

type FormattingStyles

type FormattingStyles struct {
	BackgroundColor         *color.Color
	BorderLeftWidth         bag.ScaledPoint
	BorderRightWidth        bag.ScaledPoint
	BorderBottomWidth       bag.ScaledPoint
	BorderTopWidth          bag.ScaledPoint
	BorderTopLeftRadius     bag.ScaledPoint
	BorderTopRightRadius    bag.ScaledPoint
	BorderBottomLeftRadius  bag.ScaledPoint
	BorderBottomRightRadius bag.ScaledPoint
	BorderLeftColor         *color.Color
	BorderRightColor        *color.Color
	BorderBottomColor       *color.Color
	BorderTopColor          *color.Color
	BorderLeftStyle         frontend.BorderStyle
	BorderRightStyle        frontend.BorderStyle
	BorderBottomStyle       frontend.BorderStyle
	BorderTopStyle          frontend.BorderStyle
	DefaultFontSize         bag.ScaledPoint
	DefaultFontFamily       *frontend.FontFamily

	Hide bool

	Fontsize bag.ScaledPoint

	Fontweight frontend.FontWeight

	Halign frontend.HorizontalAlignment

	ListStyleType string

	OlCounter int
	// LocalCounters holds CSS counter values defined in this element's
	// scope. Children look up counter values by walking the StylesStack
	// from the top down, so siblings share counters declared on the
	// nearest common ancestor (e.g. <ol counter-reset: list-item> seen
	// from each <li counter-increment: list-item>).
	LocalCounters map[string]int

	ListPaddingLeft    bag.ScaledPoint
	PaddingBottom      bag.ScaledPoint
	PaddingLeft        bag.ScaledPoint
	PaddingRight       bag.ScaledPoint
	PaddingTop         bag.ScaledPoint
	TextDecorationLine frontend.TextDecorationLine

	Valign frontend.VerticalAlignment
	// contains filtered or unexported fields
}

FormattingStyles are HTML formatting styles.

func (*FormattingStyles) Clone

func (is *FormattingStyles) Clone() *FormattingStyles

Clone mimics style inheritance.

type HTMLItem

type HTMLItem struct {
	Typ        html.NodeType
	Data       string
	Dir        Mode
	Attributes map[string]string
	Styles     map[string]string
	Children   []*HTMLItem
}

HTMLItem is a struct which represents a HTML element or a text node.

func (*HTMLItem) String

func (itm *HTMLItem) String() string

type HTMLProperties

type HTMLProperties map[string]string

HTMLProperties contains css values

type HTMLValues

type HTMLValues struct {
	BackgroundColor         *color.Color
	BorderTopWidth          bag.ScaledPoint
	BorderRightWidth        bag.ScaledPoint
	BorderBottomWidth       bag.ScaledPoint
	BorderLeftWidth         bag.ScaledPoint
	BorderTopLeftRadius     bag.ScaledPoint
	BorderTopRightRadius    bag.ScaledPoint
	BorderBottomLeftRadius  bag.ScaledPoint
	BorderBottomRightRadius bag.ScaledPoint
	BorderTopColor          *color.Color
	BorderRightColor        *color.Color
	BorderBottomColor       *color.Color
	BorderLeftColor         *color.Color
	BorderTopStyle          frontend.BorderStyle
	BorderRightStyle        frontend.BorderStyle
	BorderBottomStyle       frontend.BorderStyle
	BorderLeftStyle         frontend.BorderStyle
	MarginTop               bag.ScaledPoint
	MarginRight             bag.ScaledPoint
	MarginBottom            bag.ScaledPoint
	MarginLeft              bag.ScaledPoint
	PaddingTop              bag.ScaledPoint
	PaddingRight            bag.ScaledPoint
	PaddingBottom           bag.ScaledPoint
	PaddingLeft             bag.ScaledPoint
}

HTMLValues contains margin, padding and border values for a rectangular area.

type HeadingEntry added in v0.0.6

type HeadingEntry struct {
	Level string // "h1", "h2", etc.
	Text  string
	Page  int // 1-based page number, 0 until assigned
}

HeadingEntry records a heading found during VList construction. The Page field is filled later during OutputPages when the heading is placed on a page.

type Insert added in v0.0.14

type Insert struct {
	Class  InsertClass
	Number int
	Body   *node.VList
}

Insert is one extracted, fully formatted page-layer item ready for placement (footnote, float, ...). The Class field selects the placement strategy at flush time.

For InsertFootnote: Body width equals the footnote-area width (currently the paragraph content width); Number is assigned at extraction time as a running document counter (cb.Counters["footnote"]).

type InsertClass added in v0.0.14

type InsertClass int

InsertClass distinguishes the layout role of an Insert: footnotes stack at the bottom of the page, top-floats at the top of the content area, etc.

const (
	// InsertFootnote: bottom-of-page stack, separator rule above, running
	// number rendered as a superscript call in body text.
	InsertFootnote InsertClass = iota
	// InsertFloatTop: top-of-page stack, no separator, no in-text marker.
	// With Phase 3 (two-pass page assembly), top-floats and their source
	// paragraphs share a page when they fit; otherwise the page-builder
	// ships and starts fresh.
	InsertFloatTop
	// InsertFloatBottom: bottom-of-page float stack, painted between the
	// body content and the footnote stack. No separator, no in-text
	// marker. Same fit-or-ship semantics as InsertFloatTop.
	InsertFloatBottom
)

type Mode

type Mode int

Mode is the progression direction of the current HTML element.

const (
	// ModeHorizontal represents inline progression direction.
	ModeHorizontal Mode = iota
	// ModeVertical represents block progression direction.
	ModeVertical
)

func (Mode) String

func (m Mode) String() string

type PageDimensions

type PageDimensions struct {
	Width         bag.ScaledPoint
	Height        bag.ScaledPoint
	MarginLeft    bag.ScaledPoint
	MarginRight   bag.ScaledPoint
	MarginTop     bag.ScaledPoint
	MarginBottom  bag.ScaledPoint
	PageAreaLeft  bag.ScaledPoint
	PageAreaTop   bag.ScaledPoint
	ContentWidth  bag.ScaledPoint
	ContentHeight bag.ScaledPoint
	// contains filtered or unexported fields
}

PageDimensions contains the page size and the margins of the page.

func (PageDimensions) PageAreas added in v0.0.6

func (pd PageDimensions) PageAreas() map[string]map[string]string

PageAreas returns the CSS page margin box areas (e.g. "@top-center") for the current page type, or nil if no @page rule is active.

type PageInitCallbackFunc added in v0.0.6

type PageInitCallbackFunc func()

PageInitCallbackFunc is called after a new page has been initialized.

type StylesStack

type StylesStack []*FormattingStyles

StylesStack mimics CSS style inheritance.

func (StylesStack) CounterValue added in v0.0.20

func (ss StylesStack) CounterValue(name string) int

CounterValue returns the value of the innermost counter with the given name (walking the stack top-down). Returns 0 when no such counter exists, matching the CSS fallback for counter(name).

func (StylesStack) CounterValues added in v0.0.20

func (ss StylesStack) CounterValues(name string) []int

CounterValues returns every counter with the given name along the ancestor chain, root-first. counters(name, sep) uses this for nested numbering like "2.1.1".

func (StylesStack) CurrentStyle

func (ss StylesStack) CurrentStyle() *FormattingStyles

CurrentStyle returns the current style from the stack. CurrentStyle does not change the stack.

func (*StylesStack) PopStyles

func (ss *StylesStack) PopStyles()

PopStyles removes the top style from the stack.

func (*StylesStack) PushStyles

func (ss *StylesStack) PushStyles() *FormattingStyles

PushStyles creates a new style instance, pushes it onto the stack and returns the new style.

func (*StylesStack) SetDefaultFontFamily

func (ss *StylesStack) SetDefaultFontFamily(ff *frontend.FontFamily)

SetDefaultFontFamily sets the font family that should be used as a default for the document.

func (*StylesStack) SetDefaultFontSize

func (ss *StylesStack) SetDefaultFontSize(size bag.ScaledPoint)

SetDefaultFontSize sets the document font size which should be used for rem calculation.

Directories

Path Synopsis
fonts
camingocodebold
Package camingocodebold provides the "CamingoCode" font
Package camingocodebold provides the "CamingoCode" font
camingocodebolditalic
Package camingocodebolditalic provides the "CamingoCode" font
Package camingocodebolditalic provides the "CamingoCode" font
camingocodeitalic
Package camingocodeitalic provides the "CamingoCode" font
Package camingocodeitalic provides the "CamingoCode" font
camingocoderegular
Package camingocoderegular provides the "CamingoCode" font
Package camingocoderegular provides the "CamingoCode" font
crimsonprobold
Package crimsonprobold provides the "Crimson Pro" font
Package crimsonprobold provides the "Crimson Pro" font
crimsonprobolditalic
Package crimsonprobolditalic provides the "Crimson Pro" font
Package crimsonprobolditalic provides the "Crimson Pro" font
crimsonproitalic
Package crimsonproitalic provides the "Crimson Pro" font
Package crimsonproitalic provides the "Crimson Pro" font
crimsonproregular
Package crimsonproregular provides the "Crimson Pro" font
Package crimsonproregular provides the "Crimson Pro" font
texgyreherosbold
Package texgyreherosbold provides the "TeXGyreHeros" font
Package texgyreherosbold provides the "TeXGyreHeros" font
texgyreherosbolditalic
Package texgyreherosbolditalic provides the "TeXGyreHeros" font
Package texgyreherosbolditalic provides the "TeXGyreHeros" font
texgyreherositalic
Package texgyreherositalic provides the "TeXGyreHeros" font
Package texgyreherositalic provides the "TeXGyreHeros" font
texgyreherosregular
Package texgyreherosregular provides the "TeXGyreHeros" font
Package texgyreherosregular provides the "TeXGyreHeros" font

Jump to

Keyboard shortcuts

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