Add "Node-API"
parent
33f3d81bae
commit
541130dd78
1 changed files with 186 additions and 0 deletions
186
Node-API.-.md
Normal file
186
Node-API.-.md
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
# Node API
|
||||
|
||||
The `Node` interface is the fundamental building block. All rendered elements implement it.
|
||||
|
||||
See also: [[Home]] | [[Architecture]] | [[Pipeline]] | [[WebAssembly]] | [[Code-Generation]]
|
||||
|
||||
## Node Interface
|
||||
|
||||
```go
|
||||
type Node interface {
|
||||
Render(ctx *Context) string
|
||||
}
|
||||
```
|
||||
|
||||
Every node receives a `Context` and returns an HTML string. Nodes compose into trees via `El()` children.
|
||||
|
||||
## Node Types
|
||||
|
||||
### Text — i18n-Aware Text
|
||||
|
||||
```go
|
||||
func Text(key string, args ...any) Node
|
||||
```
|
||||
|
||||
Renders localised text through the i18n service in the context. Output is **HTML-escaped** (safe by default). Supports `fmt.Sprintf`-style arguments.
|
||||
|
||||
```go
|
||||
html.Text("greeting", userName)
|
||||
// Looks up "greeting" in locale, formats with userName
|
||||
// Output: "Hello, Alice" (escaped)
|
||||
```
|
||||
|
||||
### El — HTML Element
|
||||
|
||||
```go
|
||||
func El(tag string, children ...Node) Node
|
||||
```
|
||||
|
||||
Creates an HTML element. Children are rendered in order. Void elements (`br`, `img`, `hr`, `input`, `meta`, `link`, `area`, `base`, `col`, `embed`, `source`, `track`, `wbr`) self-close.
|
||||
|
||||
```go
|
||||
html.El("div",
|
||||
html.El("h1", html.Text("page.title")),
|
||||
html.El("p", html.Text("page.body")),
|
||||
)
|
||||
// <div><h1>Page Title</h1><p>Body text</p></div>
|
||||
```
|
||||
|
||||
### Attr — Attribute Setter
|
||||
|
||||
```go
|
||||
func Attr(n Node, key, value string) Node
|
||||
```
|
||||
|
||||
Sets an attribute on an element node. Returns the same node for chaining. Values are attribute-escaped.
|
||||
|
||||
```go
|
||||
html.Attr(
|
||||
html.El("a", html.Text("link.text")),
|
||||
"href", "/about",
|
||||
)
|
||||
// <a href="/about">About</a>
|
||||
```
|
||||
|
||||
### Raw — Unescaped Content
|
||||
|
||||
```go
|
||||
func Raw(content string) Node
|
||||
```
|
||||
|
||||
Renders content without escaping. **Use only for trusted content** (pre-sanitised HTML, SVG, etc.).
|
||||
|
||||
```go
|
||||
html.Raw("<svg>...</svg>")
|
||||
```
|
||||
|
||||
### If — Conditional Rendering
|
||||
|
||||
```go
|
||||
func If(cond func(*Context) bool, node Node) Node
|
||||
```
|
||||
|
||||
Renders the node only when the condition returns true. The condition receives the current context.
|
||||
|
||||
```go
|
||||
html.If(
|
||||
func(ctx *html.Context) bool { return ctx.Identity != "" },
|
||||
html.El("span", html.Text("user.welcome")),
|
||||
)
|
||||
```
|
||||
|
||||
### Unless — Negated Conditional
|
||||
|
||||
```go
|
||||
func Unless(cond func(*Context) bool, node Node) Node
|
||||
```
|
||||
|
||||
Renders the node when the condition is false. Inverse of `If`.
|
||||
|
||||
```go
|
||||
html.Unless(
|
||||
func(ctx *html.Context) bool { return ctx.Identity != "" },
|
||||
html.El("a", html.Text("auth.login")),
|
||||
)
|
||||
```
|
||||
|
||||
### Entitled — Feature Gate
|
||||
|
||||
```go
|
||||
func Entitled(feature string, node Node) Node
|
||||
```
|
||||
|
||||
Renders the node only if the feature is present in `ctx.Entitlements`. Used for plan/tier-gated UI.
|
||||
|
||||
```go
|
||||
html.Entitled("analytics-pro",
|
||||
html.El("div", html.Text("analytics.advanced_panel")),
|
||||
)
|
||||
```
|
||||
|
||||
### Switch — Runtime Case Selection
|
||||
|
||||
```go
|
||||
func Switch(selector func(*Context) string, cases map[string]Node) Node
|
||||
```
|
||||
|
||||
Evaluates the selector at render time and renders the matching case. No output if no case matches.
|
||||
|
||||
```go
|
||||
html.Switch(
|
||||
func(ctx *html.Context) string { return ctx.Data["theme"] },
|
||||
map[string]html.Node{
|
||||
"dark": html.El("div", html.Attr(html.El("div"), "class", "dark")),
|
||||
"light": html.El("div", html.Attr(html.El("div"), "class", "light")),
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
### Each — Generic Iteration
|
||||
|
||||
```go
|
||||
func Each[T any](items []T, fn func(T) Node) Node
|
||||
```
|
||||
|
||||
Iterates over a typed slice, calling the function for each item. Uses Go generics.
|
||||
|
||||
```go
|
||||
type Article struct { Title, Slug string }
|
||||
|
||||
html.Each(articles, func(a Article) html.Node {
|
||||
return html.El("li",
|
||||
html.Attr(html.El("a", html.Text(a.Title)), "href", "/"+a.Slug),
|
||||
)
|
||||
})
|
||||
```
|
||||
|
||||
## Context
|
||||
|
||||
```go
|
||||
type Context struct {
|
||||
Identity string
|
||||
Locale string
|
||||
Entitlements map[string]bool
|
||||
Data map[string]string
|
||||
Service *i18n.Service
|
||||
}
|
||||
|
||||
func NewContext() *Context
|
||||
func NewContextWithService(svc *i18n.Service) *Context
|
||||
```
|
||||
|
||||
| Field | Purpose |
|
||||
|-------|---------|
|
||||
| `Identity` | Current user identifier |
|
||||
| `Locale` | Language code for i18n lookups |
|
||||
| `Entitlements` | Feature flags for `Entitled()` gating |
|
||||
| `Data` | Arbitrary string data for `Switch()` selectors |
|
||||
| `Service` | go-i18n service for `Text()` rendering |
|
||||
|
||||
## Convenience
|
||||
|
||||
```go
|
||||
func Render(node Node, ctx *Context) string
|
||||
```
|
||||
|
||||
Shorthand for `node.Render(ctx)`. Useful in pipelines.
|
||||
Loading…
Add table
Reference in a new issue