diff options
author | Markus Wüstenberg | 2020-09-24 13:19:52 +0200 |
---|---|---|
committer | GitHub | 2020-09-24 13:19:52 +0200 |
commit | 4c109f9f1d4db4733d267ece171a533521029bdb (patch) | |
tree | 555c4ef5ad7281e8e36431d31968ade85c61aa72 /gomponents.go | |
parent | f27cb0c05f23785189979e57c831eb798e1da1f1 (diff) | |
download | gomponents-4c109f9f1d4db4733d267ece171a533521029bdb.tar.lz gomponents-4c109f9f1d4db4733d267ece171a533521029bdb.tar.zst gomponents-4c109f9f1d4db4733d267ece171a533521029bdb.zip |
Introduce Placer interface (#18)
When implemented, the `Place` method of the `Placer` interface tells `Render` in `El` where to put a Node. This is relevant for helpers that want to be rendered like attributes, inside the parent element. Fixes the bug where `attr.Classes` was rendered outside the element.
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() |