feat(html): apply attrs through iterator wrappers
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
60d8225a83
commit
c2ff591ec9
2 changed files with 46 additions and 1 deletions
19
node.go
19
node.go
|
|
@ -91,7 +91,7 @@ func El(tag string, children ...Node) Node {
|
|||
|
||||
// Attr sets an attribute on an El node. Returns the node for chaining.
|
||||
// Usage example: Attr(El("a", Text("docs")), "href", "/docs")
|
||||
// It recursively traverses through wrappers like If, Unless, and Entitled.
|
||||
// It recursively traverses through wrappers like If, Unless, Entitled, and Each.
|
||||
func Attr(n Node, key, value string) Node {
|
||||
if n == nil {
|
||||
return n
|
||||
|
|
@ -110,6 +110,8 @@ func Attr(n Node, key, value string) Node {
|
|||
for _, child := range t.cases {
|
||||
Attr(child, key, value)
|
||||
}
|
||||
case attrApplier:
|
||||
t.applyAttr(key, value)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
|
@ -314,6 +316,10 @@ type eachNode[T any] struct {
|
|||
fn func(T) Node
|
||||
}
|
||||
|
||||
type attrApplier interface {
|
||||
applyAttr(key, value string)
|
||||
}
|
||||
|
||||
// Each iterates items and renders each via fn.
|
||||
// Usage example: Each([]string{"a", "b"}, func(v string) Node { return Text(v) })
|
||||
func Each[T any](items []T, fn func(T) Node) Node {
|
||||
|
|
@ -330,6 +336,17 @@ func (n *eachNode[T]) Render(ctx *Context) string {
|
|||
return n.renderWithLayoutPath(ctx, "")
|
||||
}
|
||||
|
||||
func (n *eachNode[T]) applyAttr(key, value string) {
|
||||
if n == nil || n.fn == nil {
|
||||
return
|
||||
}
|
||||
|
||||
prev := n.fn
|
||||
n.fn = func(item T) Node {
|
||||
return Attr(prev(item), key, value)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *eachNode[T]) renderWithLayoutPath(ctx *Context, path string) string {
|
||||
if n == nil || n.fn == nil || n.items == nil {
|
||||
return ""
|
||||
|
|
|
|||
28
node_test.go
28
node_test.go
|
|
@ -318,6 +318,34 @@ func TestAttr_ThroughSwitchNode_Good(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestAttr_ThroughEachNode_Good(t *testing.T) {
|
||||
ctx := NewContext()
|
||||
node := Each([]string{"a", "b"}, func(item string) Node {
|
||||
return El("span", Raw(item))
|
||||
})
|
||||
Attr(node, "class", "item")
|
||||
|
||||
got := node.Render(ctx)
|
||||
want := `<span class="item">a</span><span class="item">b</span>`
|
||||
if got != want {
|
||||
t.Errorf("Attr through Each = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAttr_ThroughEachSeqNode_Good(t *testing.T) {
|
||||
ctx := NewContext()
|
||||
node := EachSeq(slices.Values([]string{"a", "b"}), func(item string) Node {
|
||||
return El("span", Raw(item))
|
||||
})
|
||||
Attr(node, "data-kind", "item")
|
||||
|
||||
got := node.Render(ctx)
|
||||
want := `<span data-kind="item">a</span><span data-kind="item">b</span>`
|
||||
if got != want {
|
||||
t.Errorf("Attr through EachSeq = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextNode_WithService_Good(t *testing.T) {
|
||||
svc, _ := i18n.New()
|
||||
ctx := NewContextWithService(svc)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue