print

package
v0.44.0 Latest Latest
Warning

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

Go to latest
Published: Jul 25, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package print is a GoFastr battery for printable documents. A host declares named, route-addressable print documents — the print-battery equivalent of a screen/route — and the battery server-renders each into a clean, chrome-free, print-friendly HTML page (its own @page size and margins, the browser's native print dialog, no nav/sidebar/runtime).

The HTML core is pure Go with no extra dependencies. Real PDF output is opt-in through the pluggable PDFRenderer interface; the headless-Chromium implementation lives in the separate battery/print/chromepdf subpackage so this package never imports chromedp.

See https://github.com/DonaldMurillo/gofastr for documentation.

Index

Constants

This section is empty.

Variables

View Source
var ErrForbidden = errors.New("print: forbidden")

ErrForbidden is the sentinel a Document.Build returns to render a clean 403. Prefer an Access policy for authz; this is for cases only Build can decide.

View Source
var ErrNotFound = errors.New("print: document not found")

ErrNotFound is the sentinel a Document.Build returns when the requested resource doesn't exist (or the caller may not see it). It renders a clean 404 instead of a 500.

Functions

func Public

func Public(_ *http.Request) (int, string)

Public allows every request, authenticated or not. Use only for documents that contain no per-user data.

func RequireAuth

func RequireAuth(r *http.Request) (int, string)

RequireAuth allows the request only when an authenticated user is present in context (set by the framework's auth chain). It is the default policy, so per-user documents are never world-readable unless a Document explicitly opts into Public.

Types

type AccessPolicy

type AccessPolicy func(r *http.Request) (status int, msg string)

AccessPolicy gates a print document. It runs with the request and returns the HTTP status to short-circuit with, plus a message. A zero status means "allow". Policies run BEFORE Document.Build, so an unauthorized caller never triggers a data load.

func RequireOwner

func RequireOwner(owns func(r *http.Request, user any) bool) AccessPolicy

RequireOwner allows the request only when a user is authenticated AND the owns callback returns true for that user. The user is passed as the opaque value the auth chain stored (handler.GetUser); the host asserts its own concrete user type. The framework cannot know an app's ownership model, so this delegates it.

type Battery

type Battery struct {
	// contains filtered or unexported fields
}

Battery is the framework.Battery implementation for printable documents.

func New

func New(cfg Config) *Battery

New constructs the print battery. Pass the result to framework.App.RegisterBattery after declaring documents with Document.

func (*Battery) Document

func (b *Battery) Document(doc Document) *Battery

Document declares a printable document. Returns the battery for chaining. Panics on a duplicate name, an invalid declaration, or a call after Init — documents are immutable once routes are mounted.

func (*Battery) Init

func (b *Battery) Init(app *framework.App) error

Init implements framework.Battery. Mounts every declared document's HTML route, its sibling PDF route, and the shared auto-print script.

func (*Battery) Name

func (b *Battery) Name() string

Name implements framework.Battery.

func (b *Battery) PrintLink(docName string, params map[string]string, label string) render.HTML

PrintLink renders an anchor to a print document, opened in a new tab so the host SPA is untouched. params fill the document's {placeholders}. label defaults to "Print". Returns empty HTML for an unknown document.

func (*Battery) RegisterRoutes

func (b *Battery) RegisterRoutes(r *router.Router) error

RegisterRoutes mounts the print routes on the supplied router. Exposed so apps composing their own router can mount without the battery lifecycle.

type Config

type Config struct {
	// PathPrefix is the URL prefix for all print documents.
	// Defaults to "/print". A trailing slash is trimmed.
	PathPrefix string

	// DefaultPage is the page setup inherited by documents that don't
	// set their own. Zero value resolves to A4 portrait, 12mm margins.
	DefaultPage PageConfig

	// DefaultAccess gates documents whose Access is nil. Defaults to
	// RequireAuth — so per-user documents are never world-readable
	// unless a document explicitly opts into Public.
	DefaultAccess AccessPolicy

	// AppCSSURL, when non-empty, is linked into every print shell so
	// documents inherit the host's design tokens (var(--*)). Typically
	// "/__gofastr/app.css". Empty = print base only. runtime.js is
	// NEVER linked.
	AppCSSURL string

	// BaseURL is the canonical, host-configured origin of the app (e.g.
	// "https://app.example.com"), used ONLY on the PDF path to make the
	// app.css link absolute so headless Chromium — which renders an
	// in-memory data: document with no origin — can fetch the tokens.
	// It is deliberately NOT derived from the request Host header, which
	// is client-controlled and would otherwise let a spoofed Host point
	// the server-side fetch at an arbitrary/internal address (SSRF).
	// When empty, the PDF app.css link stays relative (and simply won't
	// resolve in the data: document — PDFs render with the print base
	// only). The HTML path never needs this.
	BaseURL string

	// PDFRenderer is the pluggable PDF backend. nil = PDF routes return
	// 501. The chromedp-backed implementation lives in the separate
	// battery/print/chromepdf subpackage so this package imports no
	// chromedp.
	PDFRenderer PDFRenderer

	// PrintBaseCSS overrides the built-in readable print base stylesheet.
	// Empty = use the battery default.
	PrintBaseCSS string
}

Config configures the print battery.

type Document

type Document struct {
	// Name is a stable identifier. It is the registry key, the default
	// PDF filename stem, and what shows up in logs. Required, unique
	// per battery.
	Name string

	// Path is the route relative to Config.PathPrefix. It supports the
	// router's Go-1.22 {param} syntax, e.g. "/invoice/{id}". Required,
	// must begin with "/".
	Path string

	// Title is the document <title> (and the default PDF filename stem
	// when Name is unsuitable). For per-request titles set TitleFunc.
	Title string

	// TitleFunc, when non-nil, overrides Title per request — e.g.
	// "Invoice #1042". The returned string is HTML-escaped by the shell.
	TitleFunc func(r *http.Request) string

	// Build produces the document body for one request. This is the
	// host's hook: it reads route params via router.Param(r, …), closes
	// over the host's own services/DB to load data, and returns the body
	// component. The component is rendered with component.SafeRenderCtx
	// (panic-safe, RenderCtx-aware).
	//
	// Return ErrNotFound to render a clean 404; any other error renders a
	// clean 500 status page — never a stack trace. Required.
	Build func(r *http.Request) (component.Component, error)

	// Page overrides the battery default PageConfig for this document
	// (an invoice may be A4 portrait while a receipt is an 80mm roll).
	// nil = inherit Config.DefaultPage.
	Page *PageConfig

	// Access gates the document, evaluated BEFORE Build so an
	// unauthorized caller never triggers a data load. nil = inherit
	// Config.DefaultAccess (which itself defaults to RequireAuth).
	Access AccessPolicy

	// AutoPrint, when true, opens the browser print dialog on load. It
	// is implemented as a CSP-safe external script (see autoPrintPath),
	// not an inline <script>. Ignored on the PDF path.
	AutoPrint bool

	// Stylesheet is optional document-specific CSS appended after the
	// generated @page rules and the print base. It is trusted host
	// input (not user input) and injected verbatim into a <style>.
	Stylesheet string
}

Document declares one named, route-addressable print document — the print-battery equivalent of a screen/route. Each document mounts a chrome-free, print-friendly HTML route (and, when a PDFRenderer is configured, a sibling PDF route).

type Margins

type Margins struct {
	Top    string
	Right  string
	Bottom string
	Left   string
}

Margins holds the four page margins as CSS lengths (e.g. "12mm"). An empty side inherits the battery default ("12mm").

func MM

func MM(n int) Margins

MM builds uniform Margins of n millimetres on every side.

type Orientation

type Orientation string

Orientation is the page orientation for named sizes.

const (
	Portrait  Orientation = "portrait"
	Landscape Orientation = "landscape"
)

The supported orientations.

type PDFRenderer

type PDFRenderer interface {
	// RenderPDF converts the shelled HTML into a PDF. page carries the
	// resolved page setup (paper size + margins). baseURL is the
	// scheme+host origin of the originating request, so an adapter can
	// resolve absolute resource links (e.g. the app.css stylesheet)
	// against the live host.
	RenderPDF(ctx context.Context, html string, page PageConfig, baseURL string) ([]byte, error)
}

PDFRenderer turns a fully-assembled, standalone print HTML document into PDF bytes. It is the pluggable seam that keeps this package free of any headless-browser dependency: the chromedp-backed implementation lives in battery/print/chromepdf.

type PageConfig

type PageConfig struct {
	Size         PageSize
	Orientation  Orientation
	Margin       Margins
	CustomWidth  string // only when Size == Custom, e.g. "80mm"
	CustomHeight string // only when Size == Custom, e.g. "auto"
}

PageConfig is the physical page setup. It is turned into @page CSS for the HTML shell and into paper/margin flags for the PDF renderer.

func A4Portrait

func A4Portrait(m Margins) PageConfig

A4Portrait is a convenience constructor for the most common page setup.

func LetterPortrait

func LetterPortrait(m Margins) PageConfig

LetterPortrait is a convenience constructor for US Letter portrait.

func (PageConfig) Ptr

func (p PageConfig) Ptr() *PageConfig

Ptr returns a pointer to a copy of p, for use in Document.Page.

type PageSize

type PageSize string

PageSize is a named physical page size used for @page { size: … }.

const (
	A4     PageSize = "A4"
	Letter PageSize = "Letter"
	Legal  PageSize = "Legal"
	Custom PageSize = "Custom"
)

The supported page sizes. A4/Letter/Legal map directly to the CSS @page size keyword; Custom uses CustomWidth/CustomHeight instead.

Directories

Path Synopsis
Package chromepdf is the headless-Chromium PDF backend for the github.com/DonaldMurillo/gofastr/battery/print battery.
Package chromepdf is the headless-Chromium PDF backend for the github.com/DonaldMurillo/gofastr/battery/print battery.

Jump to

Keyboard shortcuts

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