Documentation
¶
Overview ¶
Simple system for writing HTML as Go code. Better-performing replacement for `html/template` and `text/template`; see benchmarks in readme.
Vaguely inspired by JS library https://github.com/mitranim/prax.
Features / benefits:
- No weird special language to learn.
- Use actual Go code.
- Use normal Go conditionals.
- Use normal Go loops.
- Use normal Go functions.
- Benefit from static typing.
- Benefit from Go code analysis.
- Benefit from Go performance.
- Tiny and dependency-free.
The API is bloated with "just in case" public exports, but 99% of what you want is `E`, `F`, `Bui`, and `Bui.E`. See the `Bui` example below.
Index ¶
- Constants
- Variables
- func Vac(val any) any
- type Attr
- type AttrWri
- type Attrs
- type Bui
- func (self *Bui) Attr(val Attr)
- func (self *Bui) Attrs(vals ...Attr)
- func (self *Bui) Begin(tag string, attrs Attrs)
- func (self Bui) Bytes() []byte
- func (self *Bui) C(val any)
- func (self *Bui) Child(val any)
- func (self *Bui) E(tag string, attrs Attrs, children ...any)
- func (self *Bui) End(tag string)
- func (self *Bui) EscBytes(val []byte)
- func (self *Bui) EscString(val string)
- func (self *Bui) F(vals ...any)
- func (self *Bui) NonEscBytes(val []byte)
- func (self *Bui) NonEscString(val string)
- func (self Bui) Render(bui *Bui)
- func (self Bui) String() string
- func (self *Bui) T(val string)
- func (self *Bui) Text(val string)
- type Elem
- type NonEscWri
- type Ren
- type Str
- type TextWri
Examples ¶
Constants ¶
const Doctype = `<!doctype html>`
Shortcut for prepending HTML doctype. Use `Bui(Doctype)` to create a document-level HTML builder, or `Str(Doctype)` to prepend this in `F`.
Variables ¶
var Bool = newStringSet(
`allowfullscreen`, `allowpaymentrequest`, `async`, `autofocus`, `autoplay`,
`checked`, `controls`, `default`, `disabled`, `formnovalidate`, `hidden`,
`ismap`, `itemscope`, `loop`, `multiple`, `muted`, `nomodule`, `novalidate`,
`open`, `playsinline`, `readonly`, `required`, `reversed`, `selected`,
`truespeed`,
)
Set of known HTML boolean attributes. Can be modified via `Bool.Add` and `Bool.Del`. The specification postulates the concept, but where's the standard list? Taken from non-authoritative sources. Reference:
https://www.w3.org/TR/html52/infrastructure.html#boolean-attribute
var Void = newStringSet(
`area`, `base`, `br`, `col`, `embed`, `hr`, `img`, `input`, `link`, `meta`,
`param`, `source`, `track`, `wbr`,
)
Set of known HTML void elements, also known as self-closing tags. Can be modified via `Void.Add` and `Void.Del`. Reference:
https://www.w3.org/TR/html52/ https://www.w3.org/TR/html52/syntax.html#writing-html-documents-elements
Functions ¶
Types ¶
type Attr ¶
type Attr [2]string
Represents an arbitrary HTML/XML attribute. Usually part of `Attrs{}`. An empty/zero attr (equal to `Attr{}`) is ignored during encoding.
Example ¶
package main
import (
"fmt"
x "github.com/mitranim/gax"
)
func main() {
fmt.Println(x.Attr{`class`, `some-class`})
}
Output: class="some-class"
func (Attr) Add ¶ added in v0.3.1
Returns a modified version where the given input is appended to `.Value`, space-separated if both values are non-empty.
func (Attr) Name ¶
Attribute name. If the attr is not equal to `Attr{}`, the name is validated during encoding. Using an invalid name causes a panic.
func (Attr) Set ¶ added in v0.3.1
Returns a modified version with `.Value` replaced with the given input.
func (Attr) SetName ¶ added in v0.3.1
Returns a modified version with `.Name` replaced with the given input.
type AttrWri ¶
type AttrWri []byte
Short for "attribute writer". Mostly for internal use. Writes text as if it were inside an HTML/XML attribute, without enclosing quotes, escaping as necessary. For escaping rules, see:
https://www.w3.org/TR/html52/syntax.html#escaping-a-string
func (*AttrWri) Write ¶
Implement `io.Writer`. Similar to `strings.Builder.Write`, but escapes special chars. Technically not compliant with `io.Writer`: the returned count of written bytes may exceed the size of the provided chunk.
type Attrs ¶ added in v0.2.0
type Attrs []Attr
Short for "attributes". List of arbitrary HTML/XML attributes. Used by `Elem`. Usually passed to `E` or `Bui.E`.
Example ¶
package main
import (
"fmt"
x "github.com/mitranim/gax"
)
func main() {
attrs := x.Attrs{
{`class`, `some-class`},
{`style`, `some: style`},
}
fmt.Println(attrs)
}
Output: class="some-class" style="some: style"
func A ¶
Short for "attributes". Same as the `Attrs{}` constructor, but uses parentheses, which is sometimes more convenient. Symmetric with `Attrs.A`.
Example ¶
package main
import (
"fmt"
x "github.com/mitranim/gax"
)
func main() {
attrs := x.A(
x.Attr{`class`, `some-class`},
x.Attr{`style`, `some: style`},
)
fmt.Println(attrs)
}
Output: class="some-class" style="some: style"
func AP ¶ added in v0.2.0
Short for "attributes from pairs". Recommended way to write attributes, due to its brevity. Symmetric with `Attrs.AP`.
Example ¶
package main
import (
"fmt"
x "github.com/mitranim/gax"
)
func main() {
fmt.Println(
x.AP(
`href`, `/`,
`aria-current`, `page`,
`class`, `some-class`,
),
)
}
Output: href="/" aria-current="page" class="some-class"
func LinkBlank ¶ added in v0.3.0
func LinkBlank() Attrs
Shortcut for `target="_blank" rel="noopener noreferrer"`, which must always be used together, which is easy to forget.
func (Attrs) A ¶ added in v0.2.0
Shortcut for appending more attributes. Useful when combining attributes from hardcoded pairs (via `AP`) with attributes created as `Attr`. For example, you can write a function that generates a specific attribute, and use this to append the result.
Example ¶
package main
import (
"fmt"
x "github.com/mitranim/gax"
)
func main() {
cur := func() x.Attr { return x.Attr{`aria-current`, `page`} }
bg := func() x.Attr { return x.Attr{`style`, `background-image: url(...)`} }
fmt.Println(
x.AP(`class`, `some-class`).A(cur(), bg()),
)
// class="some-class" aria-current="page" style="background-image: url(...)"
}
func (Attrs) AP ¶ added in v0.2.0
Shortcut for appending more attributes from pairs, as if by calling `AP`. Panics if the argument count is not even.
Example ¶
package main
import (
"fmt"
x "github.com/mitranim/gax"
)
func main() {
fmt.Println(
x.AP(`class`, `some-class`).AP(`href`, `/`),
)
// class="some-class" href="/"
}
func (Attrs) Add ¶ added in v0.3.1
Returns a modified version where each attribute with the matching key is modified via `Attr.Add` to append the given value to the previous value, space-separated. If no matching attribute is found, appends the given key-value as a new attribute. As a special case, if the key is empty, returns self as-is.
func (Attrs) GoString ¶ added in v0.2.0
Implement `fmt.GoStringer` for debug purposes. Not used by builder methods. Represents itself as a call to `AP`, which is the recommended way to write this.
type Bui ¶
type Bui []byte
Short for "builder" or "builder for UI". Has methods for generating HTML/XML markup, declarative but efficient. See `E`, `F`, and `Bui.E` for 99% of the API you will use.
When used as a child (see `Bui.E`, `Bui.F`, `Bui.Child`), this also indicates pre-escaped markup, appending itself to another `Bui` without HTML/XML escaping. For strings, see `Str`.
Example ¶
package main
import (
"fmt"
x "github.com/mitranim/gax"
)
func main() {
var (
E = x.E
AP = x.AP
)
type Dat struct {
Title string
Posts []string
}
dat := Dat{
Title: `Posts`,
Posts: []string{`Post0`, `Post1`},
}
bui := x.F(
x.Str(x.Doctype),
E(`html`, AP(`lang`, `en`),
E(`head`, nil,
E(`meta`, AP(`charset`, `utf-8`)),
E(`link`, AP(`rel`, `icon`, `href`, `data:;base64,=`)),
// Use normal Go conditionals.
func(b *x.Bui) {
if dat.Title != "" {
b.E(`title`, nil, dat.Title)
} else {
b.E(`title`, nil, `test markup`)
}
},
),
E(`body`, nil,
E(`h1`, AP(`class`, `title`), `Posts`),
// Use normal Go loops.
func(b *x.Bui) {
for _, post := range dat.Posts {
b.E(`h2`, nil, post)
}
},
),
),
)
fmt.Println(bui)
}
Output: <!doctype html><html lang="en"><head><meta charset="utf-8"><link rel="icon" href="data:;base64,="><title>Posts</title></head><body><h1 class="title">Posts</h1><h2>Post0</h2><h2>Post1</h2></body></html>
func F ¶ added in v0.2.0
Short for "fragment" or "document fragment". Shortcut for making `Bui` with these children.
Example ¶
package main
import (
"fmt"
x "github.com/mitranim/gax"
)
func main() {
var doc = x.F(
x.Str(x.Doctype),
x.E(`html`, nil),
)
fmt.Println(doc)
}
Output: <!doctype html><html></html>
func (*Bui) Attr ¶
Mostly for internal use. Writes an HTML/XML attribute, preceded with a space. Supports HTML bool attrs: if `Bool.Has(key)`, the attribute value may be adjusted for spec compliance. Automatically escapes the attribute value.
Sanity-checks the attribute name. Using an invalid name causes a panic.
func (*Bui) Attrs ¶
Mostly for internal use. Writes HTML/XML attributes. Supports HTML special cases; see `Bui.Attr`.
func (*Bui) Begin ¶
Mostly for internal use. Writes the beginning of an HTML/XML element, with optional attrs. Supports HTML special cases; see `Bui.Attrs`. Sanity-checks the tag. Using an invalid tag causes a panic.
func (*Bui) Child ¶
Mostly for internal use. Writes an arbitrary child. See `Bui.E` for the list of special rules.
func (*Bui) E ¶
One of the primary APIs. Counterpart to the function `E`. Short for "element" or "HTML element". Writes an HTML/XML tag, with attributes and inner content.
For a runnable example, see the definition of `Bui`.
Special rules for children:
- `nil` is ignored.
- `func()`, `func(*Bui)`, or `Ren.Render` is called for side effects.
- `[]any` is recursively walked.
- `[]Ren` is walked, calling `Ren.Render` on each val.
- `[]T` where `T` implements `Ren` is walked, calling `Ren.Render` on each val.
- Other values are stringified and escaped via `TextWri`.
To write text without escaping, use `Str` for strings and `Bui` for byte slices.
func (*Bui) End ¶
Mostly for internal use. Writes the end of an HTML/XML element. Supports HTML void elements, also known as self-closing tags: if `Void.Has(tag)`, this method is a nop. Sanity-checks the tag. Using an invalid tag causes a panic.
func (*Bui) EscBytes ¶
Writes text content, escaping if necessary. For writing `string`, see `Bui.EscString`.
func (*Bui) EscString ¶
Writes text content, escaping if necessary. For writing `[]byte`, see `Bui.EscBytes`.
func (*Bui) F ¶ added in v0.2.0
Writes multiple children via `Bui.Child`. Like the "tail part" of `Bui.E`. Counterpart to the function `F`.
func (*Bui) NonEscBytes ¶
Mostly for internal use. Writes without escaping. Intended for markup. For writing `string`, see `Bui.NonEscString`. For escaping, see `Bui.EscBytes`.
func (*Bui) NonEscString ¶
Mostly for internal use. Writes without escaping. Intended for markup. For writing `[]byte`, see `Bui.NonEscBytes`. For escaping, see `Bui.EscString`.
func (Bui) Render ¶ added in v0.2.0
Implement `Ren`. Appends itself without HTML/XML escaping.
Example ¶
package main
import (
"fmt"
x "github.com/mitranim/gax"
)
func main() {
var bui x.Bui
bui.E(`div`, nil, x.Bui(`<script>alert('hacked!')</script>`))
fmt.Println(bui)
}
Output: <div><script>alert('hacked!')</script></div>
type Elem ¶ added in v0.2.0
Represents an HTML element. Usually created via `E`. Can render itself, or be passed as a child to `F` or `Bui.E`.
func E ¶
Primary API. Short for "element" or "HTML element". Expresses an HTML/XML tag, with attributes and inner content. Creates an instance of `Elem`, which implements the `Ren` interface. It can render itself as HTML/XML, or be passed as a child to `F`, `E`, `Bui.E`.
For special rules regarding child encoding, see `Bui.E`.
Example ¶
package main
import (
"fmt"
x "github.com/mitranim/gax"
)
func main() {
var (
E = x.E
AP = x.AP
)
fmt.Println(
E(`span`, AP(`aria-hidden`, `true`), `🔥`),
)
}
Output: <span aria-hidden="true">🔥</span>
func (Elem) AttrSet ¶ added in v0.3.1
Returns a modified version where `.Attrs` contain an attribute with
func (Elem) GoString ¶ added in v0.2.0
Implement `fmt.GoStringer` for debug purposes. Not used by builder methods. Represents itself as a call to `E`, which is the recommended way to write this.
type NonEscWri ¶
type NonEscWri []byte
Short for "non-escaping writer". Mostly for internal use. Similar to `bytes.Buffer` or `strings.Builder`, but simpler and more flexible, because it's just a typedef of `[]byte`.
type Ren ¶ added in v0.2.0
type Ren interface{ Render(*Bui) }
Short for "renderer". On children implementing this interface, the `Render` method is called for side effects, instead of stringifying the child.
type Str ¶ added in v0.2.0
type Str string
Indicates pre-escaped markup. Children of this type are written as-is without additional HTML/XML escaping. For bytes, use `Bui`.
func (Str) Render ¶ added in v0.2.0
Implement `Ren`. Appends itself without HTML/XML escaping.
Example ¶
package main
import (
"fmt"
x "github.com/mitranim/gax"
)
func main() {
var bui x.Bui
bui.E(`div`, nil, x.Str(`<script>alert('hacked!')</script>`))
fmt.Println(bui)
}
Output: <div><script>alert('hacked!')</script></div>
type TextWri ¶
type TextWri []byte
Short for "text writer". Mostly for internal use. Writes text as if it were inside an HTML/XML element, escaping as necessary. For escaping rules, see:
https://www.w3.org/TR/html52/syntax.html#escaping-a-string
func (*TextWri) Write ¶
Implement `io.Writer`. Similar to `strings.Builder.Write`, but escapes special chars. Technically not compliant with `io.Writer`: the returned count of written bytes may exceed the size of the provided chunk.