8000 Add links to godoc by markuswustenberg · Pull Request #183 · maragudk/gomponents · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add links to godoc #183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions components/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
. "github.com/maragudk/gomponents/html"
)

// HTML5Props for HTML5.
// HTML5Props for [HTML5].
// Title is set no matter what, Description and Language elements only if the strings are non-empty.
type HTML5Props struct {
Title string
Expand Down Expand Up @@ -41,6 +41,7 @@ func HTML5(p HTML5Props) g.Node {
// for which the corresponding map value is true.
type Classes map[string]bool

// Render satisfies [g.Node].
func (c Classes) Render(w io.Writer) error {
var included []string
for c, include := range c {
Expand All @@ -56,7 +57,7 @@ func (c Classes) Type() g.NodeType {
return g.AttributeType
}

// String satisfies fmt.Stringer.
// String satisfies [fmt.Stringer].
func (c Classes) String() string {
var b strings.Builder
_ = c.Render(&b)
Expand Down
64 changes: 34 additions & 30 deletions gomponents.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
// Package gomponents provides view components in Go, that render to HTML 5.
// Package gomponents provides HTML components in Go, that render to HTML 5.
//
// The primary interface is a Node. It describes a function Render, which should render the Node
// The primary interface is a [Node]. It describes a function Render, which should render the [Node]
// to the given writer as a string.
//
// All DOM elements and attributes can be created by using the El and Attr functions.
// The functions Text, Textf, Raw, and Rawf can be used to create text nodes, either HTML-escaped or unescaped.
// See also helper functions Group, Map, and If for mapping data to Nodes and inserting them conditionally.
// All DOM elements and attributes can be created by using the [El] and [Attr] functions.
// The functions [Text], [Textf], [Raw], and [Rawf] can be used to create text nodes, either HTML-escaped or unescaped.
// See also helper functions [Group], [Map], [If], and [Iff] for mapping data to nodes and inserting them conditionally.
//
// For basic HTML elements and attributes, see the package html.
//
// For higher-level HTML components, see the package components.
//
// For SVG elements and attributes, see the package svg.
//
// For HTTP helpers, see the package http.
package gomponents

Expand All @@ -20,31 +23,32 @@ import (
"strings"
)

// Node is a DOM node that can Render itself to a io.Writer.
// Node is a DOM node that can Render itself to a [io.Writer].
type Node interface {
Render(w io.Writer) error
}

// NodeType describes what type of Node it is, currently either an ElementType or an AttributeType.
// This decides where a Node should be rendered.
// Nodes default to being ElementType.
// NodeType describes what type of [Node] it is, currently either an [ElementType] or an [AttributeType].
// This decides where a [Node] should be rendered.
// Nodes default to being [ElementType].
type NodeType int

const (
ElementType = NodeType(iota)
AttributeType
)

// nodeTypeDescriber can be implemented by Nodes to let callers know whether the Node is
// an ElementType or an AttributeType. This is used for rendering.
// nodeTypeDescriber can be implemented by Nodes to let callers know whether the [Node] is
// an [ElementType] or an [AttributeType].
// See [NodeType].
type nodeTypeDescriber interface {
Type() NodeType
}

// NodeFunc is a render function that is also a Node of ElementType.
// NodeFunc is a render function that is also a [Node] of [ElementType].
type NodeFunc func(io.Writer) error

// Render satisfies Node.
// Render satisfies [Node].
func (n NodeFunc) Render(w io.Writer) error {
return n(w)
}
Expand All @@ -54,19 +58,19 @@ func (n NodeFunc) Type() NodeType {
return ElementType
}

// String satisfies fmt.Stringer.
// String satisfies [fmt.Stringer].
func (n NodeFunc) String() string {
var b strings.Builder
_ = n.Render(&b)
return b.String()
}

// El creates an element DOM Node with a name and child Nodes.
// El creates an element DOM [Node] with a name and child Nodes.
// See https://dev.w3.org/html5/spec-LC/syntax.html#elements-0 for how elements are rendered.
// No tags are ever omitted from normal tags, even though it's allowed for elements given at
// https://dev.w3.org/html5/spec-LC/syntax.html#optional-tags
// If an element is a void element, non-attribute children nodes are ignored.
// Use this if no convenience creator exists.
// Use this if no convenience creator exists in the html package.
func El(name string, children ...Node) Node {
return NodeFunc(func(w2 io.Writer) error {
w := &statefulWriter{w: w2}
Expand Down Expand Up @@ -156,11 +160,11 @@ func isVoidElement(name string) bool {
return ok
}

// Attr creates an attribute DOM Node with a name and optional value.
// 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.
// More than one value make [Attr] panic.
// Use this if no convenience creator exists in the html package.
func Attr(name string, value ...string) Node {
switch len(value) {
case 0:
Expand All @@ -177,7 +181,7 @@ type attr struct {
value *string
}

// Render satisfies Node.
// Render satisfies [Node].
func (a *attr) Render(w io.Writer) error {
if a.value == nil {
_, err := w.Write([]byte(" " + a.name))
Expand All @@ -187,43 +191,43 @@ func (a *attr) Render(w io.Writer) error {
return err
}

// Type satisfies nodeTypeDescriber.
// Type satisfies [nodeTypeDescriber].
func (a *attr) Type() NodeType {
return AttributeType
}

// String satisfies fmt.Stringer.
// String satisfies [fmt.Stringer].
func (a *attr) String() string {
var b strings.Builder
_ = a.Render(&b)
return b.String()
}

// Text creates a text DOM Node that Renders the escaped string t.
// Text creates a text DOM [Node] that Renders the escaped string t.
func Text(t string) Node {
return NodeFunc(func(w io.Writer) error {
_, err := w.Write([]byte(template.HTMLEscapeString(t)))
return err
})
}

// Textf creates a text DOM Node that Renders the interpolated and escaped string format.
// Textf creates a text DOM [Node] that Renders the interpolated and escaped string format.
func Textf(format string, a ...interface{}) Node {
return NodeFunc(func(w io.Writer) error {
_, err := w.Write([]byte(template.HTMLEscapeString(fmt.Sprintf(format, a...))))
return err
})
}

// Raw creates a text DOM Node that just Renders the unescaped string t.
// Raw creates a text DOM [Node] that just Renders the unescaped string t.
func Raw(t string) Node {
return NodeFunc(func(w io.Writer) error {
_, err := w.Write([]byte(t))
return err
})
}

// Rawf creates a text DOM Node that just Renders the interpolated and unescaped string format.
// Rawf creates a text DOM [Node] that just Renders the interpolated and unescaped string format.
func Rawf(format string, a ...interface{}) Node {
return NodeFunc(func(w io.Writer) error {
_, err := w.Write([]byte(fmt.Sprintf(format, a...)))
Expand All @@ -235,12 +239,12 @@ type group struct {
children []Node
}

// String satisfies fmt.Stringer.
// String satisfies [fmt.Stringer].
func (g group) String() string {
panic("cannot render group directly")
}

// Render satisfies Node.
// Render satisfies [Node].
func (g group) Render(io.Writer) error {
panic("cannot render group directly")
}
Expand All @@ -252,9 +256,9 @@ func Group(children []Node) Node {
return group{children: children}
}

// If condition is true, return the given Node. Otherwise, return nil.
// If condition is true, return the given [Node]. Otherwise, return nil.
// This helper function is good for inlining elements conditionally.
// If it's important that the given Node is only evaluated if condition is true
// If it's important that the given [Node] is only evaluated if condition is true
// (for example, when using nilable variables), use [Iff] instead.
func If(condition bool, n Node) Node {
if condition {
Expand Down
4 changes: 3 additions & 1 deletion html/elements.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Package html provides common HTML elements and attributes.
//
// See https://developer.mozilla.org/en-US/docs/Web/HTML/Element for a list of elements.
//
// See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes for a list of attributes.
package html

Expand All @@ -9,7 +11,7 @@ import (
g "github.com/maragudk/gomponents"
)

// Doctype returns a special kind of Node that prefixes its sibling with the string "<!doctype html>".
// Doctype returns a special kind of [g.Node] that prefixes its sibling with the string "<!doctype html>".
func Doctype(sibling g.Node) g.Node {
return g.NodeFunc(func(w io.Writer) error {
if _, err := w.Write([]byte("<!doctype html>")); err != nil {
Expand Down
12 changes: 6 additions & 6 deletions http/handler.go
E2D0
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ import (
g "github.com/maragudk/gomponents"
)

// Handler is like http.Handler but returns a Node and an error.
// See Adapt for how errors are translated to HTTP responses.
// Handler is like [http.Handler] but returns a [g.Node] and an error.
// See [Adapt] for how errors are translated to HTTP responses.
type Handler = func(http.ResponseWriter, *http.Request) (g.Node, error)

type errorWithStatusCode interface {
StatusCode() int
}

// Adapt a Handler to a http.Handlerfunc.
// The returned Node is rendered to the ResponseWriter, in both normal and error cases.
// If the Handler returns an error, and it implements a "StatusCode() int" method, that HTTP status code is sent
// in the response header. Otherwise, the status code http.StatusInternalServerError (500) is used.
// Adapt a [Handler] to a [http.HandlerFunc].
// The returned [g.Node] is rendered to the [http.ResponseWriter], in both normal and error cases.
// If the [Handler] returns an error, and it implements a "StatusCode() int" method, that HTTP status code is sent
// in the response header. Otherwise, the status code [http.StatusInternalServerError] (500) is used.
func Adapt(h Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
n, err := h(w, r)
Expand Down
8 changes: 8 additions & 0 deletions http/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,11 @@ func get(t *testing.T, h http.Handler) (int, string) {
}
return result.StatusCode, string(body)
}

func ExampleAdapt() {
h := ghttp.Adapt(func(w http.ResponseWriter, r *http.Request) (g.Node, error) {
return g.El("div"), nil
})
mux := http.NewServeMux()
mux.Handle("/", h)
}
Loading
0