feat: add Attr() helper for setting element attributes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude 2026-02-17 00:08:17 +00:00
parent e041f7681f
commit f49ddbf374
No known key found for this signature in database
GPG key ID: AF404715446AEB41
2 changed files with 37 additions and 0 deletions

View file

@ -71,6 +71,15 @@ func El(tag string, children ...Node) Node {
} }
} }
// Attr sets an attribute on an El node. Returns the node for chaining.
// If the node is not an *elNode, returns it unchanged.
func Attr(n Node, key, value string) Node {
if el, ok := n.(*elNode); ok {
el.attrs[key] = value
}
return n
}
func (n *elNode) Render(ctx *Context) string { func (n *elNode) Render(ctx *Context) string {
var b strings.Builder var b strings.Builder

View file

@ -155,6 +155,34 @@ func TestEachNode_Empty(t *testing.T) {
} }
} }
func TestElNode_Attr(t *testing.T) {
ctx := NewContext()
node := Attr(El("div", Raw("content")), "class", "container")
got := node.Render(ctx)
want := `<div class="container">content</div>`
if got != want {
t.Errorf("Attr() = %q, want %q", got, want)
}
}
func TestElNode_AttrEscaping(t *testing.T) {
ctx := NewContext()
node := Attr(El("img"), "alt", `he said "hello"`)
got := node.Render(ctx)
if !strings.Contains(got, `alt="he said &quot;hello&quot;"`) {
t.Errorf("Attr should escape attribute values, got %q", got)
}
}
func TestElNode_MultipleAttrs(t *testing.T) {
ctx := NewContext()
node := Attr(Attr(El("a", Raw("link")), "href", "/home"), "class", "nav")
got := node.Render(ctx)
if !strings.Contains(got, `class="nav"`) || !strings.Contains(got, `href="/home"`) {
t.Errorf("multiple Attr() calls should stack, got %q", got)
}
}
func TestSwitchNode(t *testing.T) { func TestSwitchNode(t *testing.T) {
ctx := NewContext() ctx := NewContext()
cases := map[string]Node{ cases := map[string]Node{