about summary refs log tree commit diff stats
path: root/components
diff options
context:
space:
mode:
authorMarkus Wüstenberg2020-12-10 13:00:23 +0100
committerGitHub2020-12-10 13:00:23 +0100
commita76262652b227c95ce140f3698c46f59b79354ac (patch)
tree15987ad4a4a4f830f0df9fc110faf667fe83514a /components
parenta7e24c6cddaafb98091c3989c9da7779eeba30b5 (diff)
downloadgomponents-a76262652b227c95ce140f3698c46f59b79354ac.tar.lz
gomponents-a76262652b227c95ce140f3698c46f59b79354ac.tar.zst
gomponents-a76262652b227c95ce140f3698c46f59b79354ac.zip
Move elements and attributes into html package (#52)
This makes it easier to use dot-imports.

Also updated the readme and examples with new usage, and move the `Classes` helper into the `components` package.
Diffstat (limited to 'components')
-rw-r--r--components/attributes.go37
-rw-r--r--components/attributes_test.go32
-rw-r--r--components/documents.go29
-rw-r--r--components/documents_test.go13
4 files changed, 89 insertions, 22 deletions
diff --git a/components/attributes.go b/components/attributes.go
new file mode 100644
index 0000000..dc7ef9b
--- /dev/null
+++ b/components/attributes.go
@@ -0,0 +1,37 @@
+package components
+
+import (
+	"io"
+	"sort"
+	"strings"
+
+	g "github.com/maragudk/gomponents"
+	"github.com/maragudk/gomponents/html"
+)
+
+// Classes is a map of strings to booleans, which Renders to an attribute with name "class".
+// The attribute value is a sorted, space-separated string of all the map keys,
+// for which the corresponding map value is true.
+type Classes map[string]bool
+
+func (c Classes) Render(w io.Writer) error {
+	var included []string
+	for c, include := range c {
+		if include {
+			included = append(included, c)
+		}
+	}
+	sort.Strings(included)
+	return html.Class(strings.Join(included, " ")).Render(w)
+}
+
+func (c Classes) Type() g.NodeType {
+	return g.AttributeType
+}
+
+// String satisfies fmt.Stringer.
+func (c Classes) String() string {
+	var b strings.Builder
+	_ = c.Render(&b)
+	return b.String()
+}
diff --git a/components/attributes_test.go b/components/attributes_test.go
new file mode 100644
index 0000000..bf3e93b
--- /dev/null
+++ b/components/attributes_test.go
@@ -0,0 +1,32 @@
+package components_test
+
+import (
+	"testing"
+
+	g "github.com/maragudk/gomponents"
+	"github.com/maragudk/gomponents/assert"
+	c "github.com/maragudk/gomponents/components"
+)
+
+func TestClasses(t *testing.T) {
+	t.Run("given a map, returns sorted keys from the map with value true", func(t *testing.T) {
+		assert.Equal(t, ` class="boheme-hat hat partyhat"`, c.Classes{
+			"boheme-hat": true,
+			"hat":        true,
+			"partyhat":   true,
+			"turtlehat":  false,
+		})
+	})
+
+	t.Run("renders as attribute in an element", func(t *testing.T) {
+		e := g.El("div", c.Classes{"hat": true})
+		assert.Equal(t, `<div class="hat"></div>`, e)
+	})
+
+	t.Run("also works with fmt", func(t *testing.T) {
+		a := c.Classes{"hat": true}
+		if a.String() != ` class="hat"` {
+			t.FailNow()
+		}
+	})
+}
diff --git a/components/documents.go b/components/documents.go
index 5e96466..e2d3a22 100644
--- a/components/documents.go
+++ b/components/documents.go
@@ -1,15 +1,14 @@
-// Package components provides high-level components that are composed of low-level elements and attributes.
+// Package components provides high-level components and helpers that are composed of low-level elements and attributes.
 package components
 
 import (
 	g "github.com/maragudk/gomponents"
-	"github.com/maragudk/gomponents/attr"
-	"github.com/maragudk/gomponents/el"
+	. "github.com/maragudk/gomponents/html"
 )
 
-// DocumentProps for HTML5.
+// HTML5Props for HTML5.
 // Title is set no matter what, Description and Language elements only if the strings are non-empty.
-type DocumentProps struct {
+type HTML5Props struct {
 	Title       string
 	Description string
 	Language    string
@@ -18,24 +17,24 @@ type DocumentProps struct {
 }
 
 // HTML5 document template.
-func HTML5(p DocumentProps) g.NodeFunc {
+func HTML5(p HTML5Props) g.NodeFunc {
 	var lang, description g.Node
 	if p.Language != "" {
-		lang = attr.Lang(p.Language)
+		lang = Lang(p.Language)
 	}
 	if p.Description != "" {
-		description = el.Meta(attr.Name("description"), attr.Content(p.Description))
+		description = Meta(Name("description"), Content(p.Description))
 	}
-	return el.Document(
-		el.HTML(lang,
-			el.Head(
-				el.Meta(attr.Charset("utf-8")),
-				el.Meta(attr.Name("viewport"), attr.Content("width=device-width, initial-scale=1")),
-				el.Title(p.Title),
+	return Document(
+		HTML(lang,
+			Head(
+				Meta(Charset("utf-8")),
+				Meta(Name("viewport"), Content("width=device-width, initial-scale=1")),
+				TitleEl(p.Title),
 				description,
 				g.Group(p.Head),
 			),
-			el.Body(g.Group(p.Body)),
+			Body(g.Group(p.Body)),
 		),
 	)
 }
diff --git a/components/documents_test.go b/components/documents_test.go
index 863ac96..07f8697 100644
--- a/components/documents_test.go
+++ b/components/documents_test.go
@@ -5,26 +5,25 @@ import (
 
 	g "github.com/maragudk/gomponents"
 	"github.com/maragudk/gomponents/assert"
-	"github.com/maragudk/gomponents/attr"
-	c "github.com/maragudk/gomponents/components"
-	"github.com/maragudk/gomponents/el"
+	. "github.com/maragudk/gomponents/components"
+	. "github.com/maragudk/gomponents/html"
 )
 
 func TestHTML5(t *testing.T) {
 	t.Run("returns an html5 document template", func(t *testing.T) {
-		e := c.HTML5(c.DocumentProps{
+		e := HTML5(HTML5Props{
 			Title:       "Hat",
 			Description: "Love hats.",
 			Language:    "en",
-			Head:        []g.Node{el.Link(attr.Rel("stylesheet"), attr.Href("/hat.css"))},
-			Body:        []g.Node{el.Div()},
+			Head:        []g.Node{Link(Rel("stylesheet"), Href("/hat.css"))},
+			Body:        []g.Node{Div()},
 		})
 
 		assert.Equal(t, `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Hat</title><meta name="description" content="Love hats."><link rel="stylesheet" href="/hat.css"></head><body><div></div></body></html>`, e)
 	})
 
 	t.Run("returns no language, description, and extra head/body elements if empty", func(t *testing.T) {
-		e := c.HTML5(c.DocumentProps{
+		e := HTML5(HTML5Props{
 			Title: "Hat",
 		})