Documentation
¶
Overview ¶
Package h is a Go-native DSL for HTML composition.
Every element, attribute, and text node is a value implementing H, the single render-to-writer interface. Trees compose as ordinary Go values — `h.Div(h.ID("c"), h.H1(h.T("Counter")))` — and render with one Write per node, no per-render escaping, and no template engine.
Design properties:
- one heap allocation per element (the element pointer + its variadic children slice fold into one object when the compiler can stack-promote the slice, otherwise two);
- attributes are pre-escaped at construction so re-renders write their bytes verbatim;
- text nodes carry the HTML-escaped payload directly;
- rendering walks each child twice — attributes-pass then content-pass — using a concrete type switch rather than an interface-method indirection.
For fragments that don't depend on per-request state, Static pre-renders to bytes once and writes verbatim on every Render. For dynamic-tag escape hatches use Tag / NewTag. For shared composition use With to extend an existing element non-destructively.
Plugin authors emitting attribute-shaped output must use RawAttr: the attribute marker is unexported on purpose so external packages cannot inject raw bytes into the opening-tag region. See the on package for the canonical pattern.
Index ¶
- func IfStr(cond bool, s string) string
- func NewTag(name string) func(children ...H) H
- func NewVoidTag(name string) func(children ...H) H
- type H
- func A(children ...H) H
- func Abbr(children ...H) H
- func Action(v string) H
- func Address(children ...H) H
- func Alt(v string) H
- func Area(children ...H) H
- func Aria(name, value string) H
- func Article(children ...H) H
- func Aside(children ...H) H
- func Attr(name string, value ...string) H
- func AttrNum[T numeric](name string, v T) H
- func Audio(children ...H) H
- func AutoComplete(v string) H
- func B(children ...H) H
- func Base(children ...H) H
- func BlockQuote(children ...H) H
- func Body(children ...H) H
- func Br(children ...H) H
- func Button(children ...H) H
- func Canvas(children ...H) H
- func Caption(children ...H) H
- func Charset(v string) H
- func Checked() H
- func Cite(children ...H) H
- func Class(parts ...string) H
- func ClassMap(m map[string]bool) H
- func Classes(parts ...string) Hdeprecated
- func Code(children ...H) H
- func Col(children ...H) H
- func ColGroup(children ...H) H
- func ColSpan(v string) H
- func Content(v string) H
- func Data(name, value string) H
- func DataClass(className, format string, args ...any) H
- func DataIgnoreMorph() H
- func DataInit(format string, args ...any) H
- func DataList(children ...H) H
- func DataOnClick(format string, args ...any) H
- func DataShow(format string, args ...any) H
- func Dd(children ...H) H
- func Del(children ...H) H
- func Details(children ...H) H
- func Dfn(children ...H) H
- func Dialog(children ...H) H
- func Disabled() H
- func Div(children ...H) H
- func Dl(children ...H) H
- func Dt(children ...H) H
- func Each[T any](items []T, fn func(T) H) H
- func EachIndexed[T any](items []T, fn func(i int, v T) H) H
- func EachSeq[T any](seq iter.Seq[T], fn func(T) H) H
- func EachSeq2[K, V any](seq iter.Seq2[K, V], fn func(K, V) H) H
- func Em(children ...H) H
- func Embed(children ...H) H
- func FieldSet(children ...H) H
- func FigCaption(children ...H) H
- func Figure(children ...H) H
- func Footer(children ...H) H
- func For(v string) H
- func Form(children ...H) H
- func Fragment(items ...H) H
- func H1(children ...H) H
- func H2(children ...H) H
- func H3(children ...H) H
- func H4(children ...H) H
- func H5(children ...H) H
- func H6(children ...H) H
- func HGroup(children ...H) H
- func HTML(children ...H) H
- func HTML5(p HTML5Props) H
- func Head(children ...H) H
- func Header(children ...H) H
- func Height(v string) H
- func Hr(children ...H) H
- func Href(v string) H
- func I(children ...H) H
- func ID(v string) H
- func IFrame(children ...H) H
- func If(condition bool, n H) H
- func IfElse(condition bool, then, els H) H
- func Img(children ...H) H
- func Input(children ...H) H
- func Ins(children ...H) H
- func Kbd(children ...H) H
- func Label(children ...H) H
- func Lang(v string) H
- func Legend(children ...H) H
- func Li(children ...H) H
- func Link(children ...H) H
- func Main(children ...H) H
- func Mark(children ...H) H
- func Max(v string) H
- func MaxLength(n int) H
- func MaxNum[T numeric](v T) H
- func Maybe[T comparable](v T, fn func(T) H) H
- func Meta(children ...H) H
- func Meter(children ...H) H
- func Method(v string) H
- func Min(v string) H
- func MinLength(n int) H
- func MinNum[T numeric](v T) H
- func Name(v string) H
- func Nav(children ...H) H
- func NoScript(children ...H) H
- func Object(children ...H) H
- func Ol(children ...H) H
- func OptGroup(children ...H) H
- func Option(children ...H) H
- func P(children ...H) H
- func Pattern(v string) H
- func Picture(children ...H) H
- func Placeholder(v string) H
- func Pre(children ...H) H
- func Progress(children ...H) H
- func Q(children ...H) H
- func Raw(s string) H
- func Rel(v string) H
- func Required() H
- func Role(v string) H
- func RowSpan(v string) H
- func S(children ...H) H
- func Samp(children ...H) H
- func Script(children ...H) H
- func Section(children ...H) H
- func Select(children ...H) H
- func Selected() H
- func Small(children ...H) H
- func Source(children ...H) H
- func Span(children ...H) H
- func Src(v string) H
- func Static(n H) H
- func Step(v string) H
- func StepNum[T numeric](v T) H
- func Strong(children ...H) H
- func Style(v string) H
- func StyleEl(children ...H) H
- func Styles(parts ...string) H
- func Sub(children ...H) H
- func Summary(children ...H) H
- func Sup(children ...H) H
- func Switch[K comparable](value K, cases ...SwitchCase[K]) H
- func T(s string) H
- func TBody(children ...H) H
- func TFoot(children ...H) H
- func THead(children ...H) H
- func TabIndex(v string) H
- func Table(children ...H) H
- func Tag(name string, children ...H) H
- func Target(v string) H
- func Td(children ...H) H
- func Template(children ...H) H
- func Text(s string) H
- func Textarea(children ...H) H
- func Textf(format string, a ...any) H
- func Th(children ...H) H
- func Time(children ...H) H
- func Title(v string) H
- func Tr(children ...H) H
- func Type(v string) H
- func U(children ...H) H
- func Ul(children ...H) H
- func Value(v string) H
- func ValueNum[T numeric](v T) H
- func Var(children ...H) H
- func Video(children ...H) H
- func VoidTag(name string, children ...H) H
- func Wbr(children ...H) H
- func When(condition bool, build func() H) H
- func WhenElse(condition bool, then, els func() H) H
- func Width(v string) H
- func With(base H, more ...H) H
- type HTML5Props
- type RawAttr
- type SwitchCase
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IfStr ¶ added in v0.4.0
IfStr returns s if cond is true, "" otherwise. Pairs with Class and Styles for inline conditional fragments.
Types ¶
type H ¶
H is anything that renders itself to an io.Writer.
func Aria ¶ added in v0.6.0
Aria is shorthand for `aria-<name>="value"` (HTML-escaped). Use it for accessibility attributes (`aria-label`, `aria-invalid`, …) instead of the stringly-typed Attr("aria-"+name, value).
func Attr ¶
Attr creates an attribute. A single value produces name="escaped"; no value produces a boolean attribute (`required`); more than one value panics.
func AttrNum ¶ added in v0.6.0
AttrNum emits `name="<v>"` for a numeric value, sparing callers the strconv/fmt conversion that string-valued Attr would require.
func AutoComplete ¶ added in v0.6.0
AutoComplete emits the autocomplete attribute.
func BlockQuote ¶
BlockQuote renders the HTML <blockquote> element.
func Class ¶
Class joins non-empty class names with spaces and emits a single class attribute. Returns nil when no class names remain so the attribute is omitted entirely.
h.Class("btn") // single
h.Class("btn", "primary") // many
h.Class("btn", h.IfStr(active, "active")) // conditional
func ClassMap ¶ added in v0.4.0
ClassMap renders a class attribute that includes each key whose value is true. Keys are emitted in sorted order so the output is stable across renders.
func Data ¶
Data is shorthand for `data-<name>="value"`. Specialised over Attr("data-"+name, value) to skip the per-call name-prefix concatenation.
func DataIgnoreMorph ¶ added in v0.2.0
func DataIgnoreMorph() H
DataIgnoreMorph tells datastar to skip morphing this element on patch.
func DataOnClick ¶ added in v0.4.0
DataOnClick attaches a datastar click handler. Use for frontend-only signal mutations; for server actions prefer the `on` package.
func DataShow ¶ added in v0.4.0
DataShow conditionally shows/hides the element based on the expression's truthiness.
func EachIndexed ¶ added in v0.4.0
EachIndexed is Each with the element index passed alongside the value.
func EachSeq2 ¶ added in v0.4.0
EachSeq2 renders one node per (K, V) pair drawn from a Go 1.23 iter.Seq2.
func FigCaption ¶
FigCaption renders the HTML <figcaption> element.
func Fragment ¶ added in v0.4.0
Fragment bundles many nodes into one H. Use it when a function whose signature returns a single H needs to yield several:
return Fragment(H2(T("title")), Hr())
return Fragment(items...)
Attribute arguments (ID, Class, on.*, …) panic at construction: a fragment has no opening tag to put them in, so they were previously dropped without a trace — a programming mistake better caught where the bad call is written.
The returned node aliases items — there is no defensive copy. Callers must not mutate items after handing it to Fragment.
func HTML5 ¶
func HTML5(p HTML5Props) H
HTML5 returns a fully formed HTML5 document. The injected datastar script tag matches the h.HTML5 surface so the runtime can serve the same fragment regardless of which package built it.
func Href ¶
One shorthand per common HTML attribute — each emits `name="value"` (HTML-escaped) via [buildAttr]. For an attribute without a shorthand use Attr; for data-* use Data; for boolean attributes see Selected, Checked, Required, Disabled. Href emits the href attribute.
func If ¶
If returns n when condition is true, otherwise nil — which renders as nothing. Both branches are evaluated eagerly; use When if constructing n is expensive or has side effects you only want when condition holds.
func IfElse ¶ added in v0.4.0
IfElse picks between two pre-built branches. Both are constructed eagerly — use WhenElse if construction is expensive.
func MaxNum ¶ added in v0.6.0
func MaxNum[T numeric](v T) H
MaxNum is the numeric form of Max for range/number inputs.
func Maybe ¶ added in v0.4.0
func Maybe[T comparable](v T, fn func(T) H) H
Maybe renders fn(v) only when v differs from its zero value, so optional fields and pointer-style data render cleanly without an explicit guard at every call site. T must be [comparable] because the zero check is `v == zero` — uncomparable types (slices, maps, funcs) fail at compile time rather than via a generics error at instantiation.
h.Maybe(user.Email, func(s string) h.H {
return h.P("email: ", s)
})
func MinNum ¶ added in v0.6.0
func MinNum[T numeric](v T) H
MinNum is the numeric form of Min for range/number inputs.
func Pattern ¶ added in v0.6.0
Pattern emits the pattern attribute — a regex for native client-side input validation. Pairs with Required for zero-round-trip constraint checks.
func Static ¶ added in v0.4.0
Static pre-renders n into a byte slice and returns an H that writes those bytes on every Render. Use it for fragments that don't depend on per-request state — site headers, navigation, layout chrome — so they stop allocating across reloads.
Capturing a subtree that embeds a RawAttr (or any other node derived from per-request data) is almost certainly a bug: the bytes are frozen at construction and will keep emitting the original values regardless of later state. Reserve Static for truly static content built at package-init time.
Panics if n.Render returns an error during pre-render; a Static node is built at package-init time where the only realistic failure is a misconfigured writer.
func StepNum ¶ added in v0.6.0
func StepNum[T numeric](v T) H
StepNum is the numeric form of Step for range/number inputs.
func Style ¶
Style emits an inline `style="..."` attribute. For the `<style>...</style>` element use StyleEl.
func Styles ¶ added in v0.4.0
Styles joins non-empty CSS declarations with `;` and emits one inline style attribute. Skip-on-empty makes inline conditionals natural:
h.Styles("flex:1", h.IfStr(done, "text-decoration:line-through"))
func Switch ¶ added in v0.4.0
func Switch[K comparable](value K, cases ...SwitchCase[K]) H
Switch renders the first matching SwitchCase and nothing else.
value and every Case key share the comparable type K, so a mismatched case is a compile error. Note Go's comparable admits interface and comparable-struct types whose comparison can still panic at runtime if a value carries a non-comparable dynamic type — for tab-style branching on such a value, project it to a simple key first (e.g. a tag string or enum) and Switch on that.
func T ¶ added in v0.4.0
T is a brevity alias for Text. The short name matters at call sites where many small text nodes nest inside one-letter element constructors — `h.H1(h.T("Counter"))` reads cleaner than `h.H1(h.Text("Counter"))` without sacrificing static typing.
func Tag ¶ added in v0.4.0
Tag emits a custom non-void element. Use it for tags absent from the static constructor list (web components, SVG primitives, etc.). The tag name is written verbatim — callers must supply a valid HTML element name; nothing here validates it.
func Text ¶
Text creates an HTML-escaped text node. When the input contains no characters that need escaping, the node carries the input string verbatim — no byte copy.
func Title ¶
Title emits <title>v</title> with v HTML-escaped. Defined alongside element constructors because it produces an element node, not an attribute.
func ValueNum ¶ added in v0.6.0
func ValueNum[T numeric](v T) H
ValueNum is the numeric form of Value for range/number inputs.
func VoidTag ¶ added in v0.4.0
VoidTag emits a custom void element (no closing tag, content children dropped at render time). The tag name is written verbatim — callers must supply a valid HTML element name; nothing here validates it.
func WhenElse ¶ added in v0.4.0
WhenElse is IfElse with lazy builders — only the winning branch runs. Either builder may be nil; a nil builder for the winning branch renders nothing.
func With ¶ added in v0.4.0
With returns a copy of base extended with additional children. It makes component composition compose without forcing every component signature to take a variadic — e.g. a Card(body) constructor can still gain an extra class or click handler at the call site:
h.With(Card(myBody), on.Click(open))
When base is not an *element (text, group, attribute, raw fragment, …) With falls back to a plain group so the result still renders the base followed by more. In that fallback path, attribute children bubble to the wrapping element via group semantics (the renderer skips attributes at the group top level and the parent element consumes them); they do not attach to base itself.
type HTML5Props ¶
type HTML5Props struct {
Title string
Description string
Language string
Head []H
Body []H
HTMLAttrs []H
}
HTML5Props defines properties for HTML5 pages. Title is always set; Description and Language are emitted only when their strings are non-empty.
type RawAttr ¶ added in v0.4.0
type RawAttr []byte
RawAttr is a pre-rendered attribute fragment (leading space, name, optional `="escaped-value"`). It implements H as an attribute so the element renderer emits it inside the opening tag, and writes its bytes verbatim on every Render — no per-render escape.
The bytes are owned by the caller; do not mutate them after passing the value to H consumers.
type SwitchCase ¶ added in v0.4.0
type SwitchCase[K comparable] struct { // contains filtered or unexported fields }
SwitchCase pairs a key with the node to render when Switch's value matches the key. Build with Case / Default.
func Case ¶ added in v0.4.0
func Case[K comparable](key K, node H) SwitchCase[K]
Case returns a SwitchCase that fires when Switch's value equals key.
func Default ¶ added in v0.4.0
func Default[K comparable](node H) SwitchCase[K]
Default returns a SwitchCase that fires when no other case matches. At most one Default per Switch is honoured (the first one wins).
K cannot be inferred from the argument, so it is spelled explicitly at the call site: h.Default[Status](unknownView).