Files
via/h/h.go
Ryan Hamamura 50e368f47b
All checks were successful
CI / Build and Test (push) Successful in 38s
CI / Build and Test (pull_request) Successful in 33s
fix: nil-close bug, stale docs, dead code, and tracked binaries
- Fix potential nil file.Close() panic in devModePersist/devModeRemovePersisted
  by extracting loadDevModeMap/saveDevModeMap helpers with proper defer
- Remove tracked binaries (pathparams 10.8 MB, shake.db 22 MB) and consolidate
  .gitignore with a wildcard pattern covering all 19 examples
- Remove stale reaper reference in README (removed in dc56261), update example
  count from 14 to 19, fix OnChange debounce claim in docs
- Fix typos: "percist"→"persist", "percisted"→"persisted", "tmplates"→"templates"
- Remove dead code: commented import in signal_test.go, unnecessary fmt.Sprintf
  in computed.go, commented picocss imports and no-op Config calls in examples
- Replace go fmt with gofmt -l check in ci-check.sh to fail on unformatted code
  instead of silently reformatting
2026-02-20 09:58:46 -10:00

92 lines
2.4 KiB
Go

// Package h provides a Go-native DSL for HTML composition.
// Every element, attribute, and text node is constructed as a function that returns a [h.H] DOM node.
//
// Example:
//
// h.Div(
// h.H1(h.Text("Hello, Via")),
// h.P(h.Text("Pure Go. No templates.")),
// )
package h
import (
"io"
g "maragu.dev/gomponents"
gc "maragu.dev/gomponents/components"
)
// H represents a DOM node.
type H interface {
Render(w io.Writer) error
}
// Text creates a text DOM node that Renders the escaped string t.
func Text(t string) H {
return g.Text(t)
}
// Textf creates a text DOM node that Renders the interpolated and escaped string format.
func Textf(format string, a ...any) H {
return g.Textf(format, a...)
}
// Raw creates a text DOM [Node] that just Renders the unescaped string t.
func Raw(s string) H {
return g.Raw(s)
}
// Rawf creates a text DOM [Node] that just Renders the interpolated and
// unescaped string format.
func Rawf(format string, a ...any) H {
return g.Rawf(format, a...)
}
// Attr creates an attribute DOM [Node] with a name and optional value.
// If only a name is passed, it's a name-only (boolean) attribute (like "required").
// If a name and value are passed, it's a name-value attribute (like `class="header"`).
// More than one value make [Attr] panic.
// Use this if no convenience creator exists in the h package.
func Attr(name string, value ...string) H {
return g.Attr(name, value...)
}
func If(condition bool, n H) H {
if condition {
return n
}
return nil
}
// HTML5Props defines properties for HTML5 pages. Title is set always set, Description
// and Language elements only if the strings are non-empty.
type HTML5Props struct {
Title string
Description string
Language string
Head []H
Body []H
HTMLAttrs []H
}
// HTML5 document template.
func HTML5(p HTML5Props) H {
gp := gc.HTML5Props{
Title: p.Title,
Description: p.Description,
Language: p.Language,
Head: retype(p.Head),
Body: retype(p.Body),
HTMLAttrs: retype(p.HTMLAttrs),
}
return gc.HTML5(gp)
}
// JoinAttrs with the given name only on the first level of the given nodes. This means that
// attributes on non-direct descendants are ignored. Attribute values are joined by spaces.
//
// Note that this renders all first-level attributes to check whether they should be processed.
func JoinAttrs(name string, children ...H) H {
return gc.JoinAttrs(name, retype(children)...)
}