diff options
Diffstat (limited to 'gomponents.go')
-rw-r--r-- | gomponents.go | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/gomponents.go b/gomponents.go index 21d3e75..73d0545 100644 --- a/gomponents.go +++ b/gomponents.go @@ -19,6 +19,20 @@ type Node interface { Render() string } +// Placer can be implemented to tell Render functions where to place the string representation of a Node +// in the parent element. +type Placer interface { + Place() Placement +} + +// Placement is used with the Placer interface. +type Placement int + +const ( + Outside = Placement(iota) + Inside +) + // NodeFunc is render function that is also a Node. type NodeFunc func() string @@ -26,6 +40,10 @@ func (n NodeFunc) Render() string { return n() } +func (n NodeFunc) Place() Placement { + return Outside +} + // String satisfies fmt.Stringer. func (n NodeFunc) String() string { return n.Render() @@ -35,7 +53,7 @@ func (n NodeFunc) String() string { // Use this if no convenience creator exists. func El(name string, children ...Node) NodeFunc { return func() string { - var b, attrString, childrenString strings.Builder + var b, inside, outside strings.Builder b.WriteString("<") b.WriteString(name) @@ -46,22 +64,28 @@ func El(name string, children ...Node) NodeFunc { } for _, c := range children { - if _, ok := c.(attr); ok { - attrString.WriteString(c.Render()) - } else { - childrenString.WriteString(c.Render()) + if p, ok := c.(Placer); ok { + switch p.Place() { + case Inside: + inside.WriteString(c.Render()) + case Outside: + outside.WriteString(c.Render()) + } + continue } + // If c doesn't implement Placer, default to outside + outside.WriteString(c.Render()) } - b.WriteString(attrString.String()) + b.WriteString(inside.String()) - if childrenString.Len() == 0 { + if outside.Len() == 0 { b.WriteString("/>") return b.String() } b.WriteString(">") - b.WriteString(childrenString.String()) + b.WriteString(outside.String()) b.WriteString("</") b.WriteString(name) b.WriteString(">") @@ -97,6 +121,10 @@ func (a attr) Render() string { return fmt.Sprintf(` %v="%v"`, a.name, *a.value) } +func (a attr) Place() Placement { + return Inside +} + // String satisfies fmt.Stringer. func (a attr) String() string { return a.Render() |